grad_intrinsic.cpp 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2018 Alec Jacobson <[email protected]>
  4. //
  5. // This Source Code Form is subject to the terms of the Mozilla Public License
  6. // v. 2.0. If a copy of the MPL was not distributed with this file, You can
  7. // obtain one at http://mozilla.org/MPL/2.0/.
  8. #include "grad_intrinsic.h"
  9. #include "grad.h"
  10. #include "PlainMatrix.h"
  11. template <typename Derivedl, typename DerivedF, typename Gtype>
  12. IGL_INLINE void igl::grad_intrinsic(
  13. const Eigen::MatrixBase<Derivedl>&l,
  14. const Eigen::MatrixBase<DerivedF>&F,
  15. Eigen::SparseMatrix<Gtype> &G)
  16. {
  17. assert(F.cols() ==3 && "Only triangles supported");
  18. // number of vertices
  19. const int n = F.maxCoeff()+1;
  20. // number of faces
  21. const int m = F.rows();
  22. // JD: There is a pretty subtle bug when using a fixed column size for this matrix.
  23. // When calling igl::grad(V, ...), the two code paths `grad_tet` and `grad_tri`
  24. // will be compiled. It turns out that `igl::grad_tet` calls `igl::volume`, which
  25. // reads the coordinates of the `V` matrix into `RowVector3d`. If the matrix `V`
  26. // has a known compile-time size of 2, this produces a compilation error when
  27. // libigl is compiled in header-only mode. In static mode this doesn't happen
  28. // because the matrix `V` is probably implicitly copied into a `Eigen::MatrixXd`.
  29. // This is a situation that could be solved using `if constexpr` in C++17.
  30. // In C++11, the alternative is to use SFINAE and `std::enable_if` (ugh).
  31. typedef Eigen::Matrix<Gtype,Eigen::Dynamic,Eigen::Dynamic> MatrixX2S;
  32. MatrixX2S V2 = MatrixX2S::Zero(3*m,2);
  33. // 1=[x,y]
  34. // ╱ ╲
  35. // l3 ╱ ╲l2
  36. // ╱ ╲
  37. // ╱ ╲
  38. // 2-----------3
  39. // l1
  40. //
  41. // x = (l2²-l1²-l3²)/(-2*l1)
  42. // y = sqrt(l3² - x²)
  43. //
  44. //
  45. // Place 3rd vertex at [l(:,1) 0]
  46. V2.block(2*m,0,m,1) = l.col(0);
  47. // Place second vertex at [0 0]
  48. // Place third vertex at [x y]
  49. V2.block(0,0,m,1) =
  50. (l.col(1).cwiseAbs2()-l.col(0).cwiseAbs2()-l.col(2).cwiseAbs2()).array()/
  51. (-2.*l.col(0)).array();
  52. V2.block(0,1,m,1) =
  53. (l.col(2).cwiseAbs2() - V2.block(0,0,m,1).cwiseAbs2()).array().sqrt();
  54. PlainMatrix<DerivedF> F2(F.rows(),F.cols());
  55. std::vector<Eigen::Triplet<Gtype> > Pijv;
  56. Pijv.reserve(F.size());
  57. for(int f = 0;f<m;f++)
  58. {
  59. for(int c = 0;c<F.cols();c++)
  60. {
  61. F2(f,c) = f+c*m;
  62. Pijv.emplace_back(F2(f,c),F(f,c),1);
  63. }
  64. }
  65. Eigen::SparseMatrix<Gtype> P(m*3,n);
  66. P.setFromTriplets(Pijv.begin(),Pijv.end());
  67. Eigen::SparseMatrix<Gtype> G2;
  68. grad(V2,F2,G2);
  69. G = G2*P;
  70. }
  71. #ifdef IGL_STATIC_LIBRARY
  72. // Explicit template instantiation
  73. // generated by autoexplicit.sh
  74. template void igl::grad_intrinsic<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double>(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::SparseMatrix<double, 0, int>&);
  75. // generated by autoexplicit.sh
  76. template void igl::grad_intrinsic<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double>(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::SparseMatrix<double, 0, int>&);
  77. #endif