cotmatrix.h 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. #ifndef IGL_COTMATRIX_H
  2. #define IGL_COTMATRIX_H
  3. #define EIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET
  4. #include <Eigen/Dense>
  5. #include <Eigen/Sparse>
  6. // History:
  7. // Used const references rather than copying the entire mesh
  8. // Alec 9 October 2011
  9. // removed cotan (uniform weights) optional parameter it was building a buggy
  10. // half of the uniform laplacian, please see adjacency_matrix istead
  11. // Alec 9 October 2011
  12. namespace igl
  13. {
  14. // Constructs the cotangent stiffness matrix (discrete laplacian) for a given
  15. // mesh (V,F).
  16. //
  17. // Templates:
  18. // DerivedV derived type of eigen matrix for V (e.g. derived from
  19. // MatirxXd)
  20. // DerivedF derived type of eigen matrix for F (e.g. derived from
  21. // MatrixXi)
  22. // Scalar scalar type for eigen sparse matrix (e.g. double)
  23. // Inputs:
  24. // V #V by dim list of mesh vertex positions
  25. // F #F by simplex_size list of mesh faces (must be triangles)
  26. // Outputs:
  27. // L #V by #V cotangent matrix, each row i corresponding to V(i,:)
  28. //
  29. // See also: adjacency_matrix
  30. //
  31. // Known bugs: off by 1e-16 on regular grid. I think its a problem of
  32. // arithmetic order in cotangent.h: C(i,e) = (arithmetic)/dblA/4
  33. template <typename DerivedV, typename DerivedF, typename Scalar>
  34. inline void cotmatrix(
  35. const Eigen::MatrixBase<DerivedV> & V,
  36. const Eigen::MatrixBase<DerivedF> & F,
  37. Eigen::SparseMatrix<Scalar>& L);
  38. }
  39. // Implementation
  40. // For error printing
  41. #include <cstdio>
  42. #include "cotangent.h"
  43. template <typename DerivedV, typename DerivedF, typename Scalar>
  44. inline void igl::cotmatrix(
  45. const Eigen::MatrixBase<DerivedV> & V,
  46. const Eigen::MatrixBase<DerivedF> & F,
  47. Eigen::SparseMatrix<Scalar>& L)
  48. {
  49. using namespace igl;
  50. using namespace Eigen;
  51. DynamicSparseMatrix<Scalar, RowMajor> dyn_L (V.rows(), V.rows());
  52. Matrix<int,Dynamic,2> edges;
  53. int simplex_size = F.cols();
  54. // 3 for triangles, 4 for tets
  55. assert(simplex_size == 3 || simplex_size == 4);
  56. if(simplex_size == 3)
  57. {
  58. // This is important! it could decrease the comptuation time by a factor of 2
  59. // Laplacian for a closed 2d manifold mesh will have on average 7 entries per
  60. // row
  61. dyn_L.reserve(7*V.rows());
  62. edges.resize(3,2);
  63. edges <<
  64. 1,2,
  65. 2,0,
  66. 0,1;
  67. }else if(simplex_size == 4)
  68. {
  69. dyn_L.reserve(17*V.rows());
  70. edges.resize(6,2);
  71. edges <<
  72. 1,2,
  73. 2,0,
  74. 0,1,
  75. 3,0,
  76. 3,1,
  77. 3,2;
  78. }else
  79. {
  80. return;
  81. }
  82. // Gather cotangents
  83. Matrix<Scalar,Dynamic,Dynamic> C;
  84. cotangent(V,F,C);
  85. // Loop over triangles
  86. for(int i = 0; i < F.rows(); i++)
  87. {
  88. // loop over edges of element
  89. for(int e = 0;e<edges.rows();e++)
  90. {
  91. int source = F(i,edges(e,0));
  92. int dest = F(i,edges(e,1));
  93. dyn_L.coeffRef(source,dest) += C(i,e);
  94. dyn_L.coeffRef(dest,source) += C(i,e);
  95. dyn_L.coeffRef(source,source) += -C(i,e);
  96. dyn_L.coeffRef(dest,dest) += -C(i,e);
  97. }
  98. }
  99. // Corner indices of this triangle
  100. L = SparseMatrix<Scalar>(dyn_L);
  101. }
  102. #endif