gradMat.cpp 3.3 KB

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