gradMat.cpp 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. #include "gradMat.h"
  2. #include <vector>
  3. template <typename T, typename S>
  4. IGL_INLINE void igl::gradMat(const Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> &V,
  5. const Eigen::Matrix<S, Eigen::Dynamic, Eigen::Dynamic> &F,
  6. Eigen::SparseMatrix<T> &G )
  7. {
  8. Eigen::PlainObjectBase<Eigen::Matrix<T,Eigen::Dynamic,3> > eperp21, eperp13;
  9. eperp21.resize(F.rows(),3);
  10. eperp13.resize(F.rows(),3);
  11. for (int i=0;i<F.rows();++i)
  12. {
  13. // renaming indices of vertices of triangles for convenience
  14. int i1 = F(i,0);
  15. int i2 = F(i,1);
  16. int i3 = F(i,2);
  17. // #F x 3 matrices of triangle edge vectors, named after opposite vertices
  18. Eigen::Matrix<T, 1, 3> v32 = V.row(i3) - V.row(i2);
  19. Eigen::Matrix<T, 1, 3> v13 = V.row(i1) - V.row(i3);
  20. Eigen::Matrix<T, 1, 3> v21 = V.row(i2) - V.row(i1);
  21. // area of parallelogram is twice area of triangle
  22. // area of parallelogram is || v1 x v2 ||
  23. Eigen::Matrix<T, 1, 3> n = v32.cross(v13);
  24. // This does correct l2 norm of rows, so that it contains #F list of twice
  25. // triangle areas
  26. double dblA = std::sqrt(n.dot(n));
  27. // now normalize normals to get unit normals
  28. Eigen::Matrix<T, 1, 3> u = n / dblA;
  29. // rotate each vector 90 degrees around normal
  30. double norm21 = std::sqrt(v21.dot(v21));
  31. double norm13 = std::sqrt(v13.dot(v13));
  32. eperp21.row(i) = u.cross(v21);
  33. eperp21.row(i) = eperp21.row(i) / std::sqrt(eperp21.row(i).dot(eperp21.row(i)));
  34. eperp21.row(i) *= norm21 / dblA;
  35. eperp13.row(i) = u.cross(v13);
  36. eperp13.row(i) = eperp13.row(i) / std::sqrt(eperp13.row(i).dot(eperp13.row(i)));
  37. eperp13.row(i) *= norm13 / dblA;
  38. }
  39. std::vector<int> rs;
  40. rs.reserve(F.rows()*4*3);
  41. std::vector<int> cs;
  42. cs.reserve(F.rows()*4*3);
  43. std::vector<double> vs;
  44. vs.reserve(F.rows()*4*3);
  45. // row indices
  46. for(int r=0;r<3;r++)
  47. {
  48. for(int j=0;j<4;j++)
  49. {
  50. for(int i=r*F.rows();i<(r+1)*F.rows();i++) rs.push_back(i);
  51. }
  52. }
  53. // column indices
  54. for(int r=0;r<3;r++)
  55. {
  56. for(int i=0;i<F.rows();i++) cs.push_back(F(i,1));
  57. for(int i=0;i<F.rows();i++) cs.push_back(F(i,0));
  58. for(int i=0;i<F.rows();i++) cs.push_back(F(i,2));
  59. for(int i=0;i<F.rows();i++) cs.push_back(F(i,0));
  60. }
  61. // values
  62. for(int i=0;i<F.rows();i++) vs.push_back(eperp13(i,0));
  63. for(int i=0;i<F.rows();i++) vs.push_back(-eperp13(i,0));
  64. for(int i=0;i<F.rows();i++) vs.push_back(eperp21(i,0));
  65. for(int i=0;i<F.rows();i++) vs.push_back(-eperp21(i,0));
  66. for(int i=0;i<F.rows();i++) vs.push_back(eperp13(i,1));
  67. for(int i=0;i<F.rows();i++) vs.push_back(-eperp13(i,1));
  68. for(int i=0;i<F.rows();i++) vs.push_back(eperp21(i,1));
  69. for(int i=0;i<F.rows();i++) vs.push_back(-eperp21(i,1));
  70. for(int i=0;i<F.rows();i++) vs.push_back(eperp13(i,2));
  71. for(int i=0;i<F.rows();i++) vs.push_back(-eperp13(i,2));
  72. for(int i=0;i<F.rows();i++) vs.push_back(eperp21(i,2));
  73. for(int i=0;i<F.rows();i++) vs.push_back(-eperp21(i,2));
  74. // create sparse gradient operator matrix
  75. G.resize(3*F.rows(),V.rows());
  76. std::vector<Eigen::Triplet<T> > triplets;
  77. for (int i=0;i<vs.size();++i)
  78. {
  79. triplets.push_back(Eigen::Triplet<T>(rs[i],cs[i],vs[i]));
  80. }
  81. G.setFromTriplets(triplets.begin(), triplets.end());
  82. }
  83. #ifndef IGL_HEADER_ONLY
  84. // Explicit template specialization
  85. #endif