grad.cpp 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. #include "grad.h"
  2. template <typename T, typename S>
  3. IGL_INLINE void igl::grad(const Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> &V,
  4. const Eigen::Matrix<S, Eigen::Dynamic, Eigen::Dynamic> &F,
  5. const Eigen::Matrix<T, Eigen::Dynamic, 1>&X,
  6. Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> &G )
  7. {
  8. G = Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>::Zero(F.rows(),3);
  9. for (int i = 0; i<F.rows(); ++i)
  10. {
  11. // renaming indices of vertices of triangles for convenience
  12. int i1 = F(i,0);
  13. int i2 = F(i,1);
  14. int i3 = F(i,2);
  15. // #F x 3 matrices of triangle edge vectors, named after opposite vertices
  16. Eigen::Matrix<T, 1, 3> v32 = V.row(i3) - V.row(i2);
  17. Eigen::Matrix<T, 1, 3> v13 = V.row(i1) - V.row(i3);
  18. Eigen::Matrix<T, 1, 3> v21 = V.row(i2) - V.row(i1);
  19. // area of parallelogram is twice area of triangle
  20. // area of parallelogram is || v1 x v2 ||
  21. Eigen::Matrix<T, 1, 3> n = v32.cross(v13);
  22. // This does correct l2 norm of rows, so that it contains #F list of twice
  23. // triangle areas
  24. double dblA = std::sqrt(n.dot(n));
  25. // now normalize normals to get unit normals
  26. Eigen::Matrix<T, 1, 3> u = n / dblA;
  27. // rotate each vector 90 degrees around normal
  28. double norm21 = std::sqrt(v21.dot(v21));
  29. double norm13 = std::sqrt(v13.dot(v13));
  30. Eigen::Matrix<T, 1, 3> eperp21 = u.cross(v21);
  31. eperp21 = eperp21 / std::sqrt(eperp21.dot(eperp21));
  32. eperp21 *= norm21;
  33. Eigen::Matrix<T, 1, 3> eperp13 = u.cross(v13);
  34. eperp13 = eperp13 / std::sqrt(eperp13.dot(eperp13));
  35. eperp13 *= norm13;
  36. G.row(i) = ((X[i2] -X[i1]) *eperp13 + (X[i3] - X[i1]) *eperp21) / dblA;
  37. };
  38. }
  39. #ifndef IGL_HEADER_ONLY
  40. // Explicit template specialization
  41. #endif