grad.h 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. //
  2. // grad.h
  3. // Preview3D
  4. //
  5. // Created by Olga Diamanti on 11/11/11.
  6. // Copyright (c) 2011 __MyCompanyName__. All rights reserved.
  7. //
  8. #ifndef Preview3D_grad_h
  9. #define Preview3D_grad_h
  10. #include <Eigen/Core>
  11. namespace igl {
  12. // GRAD
  13. // G = grad(V,F,X)
  14. //
  15. // Compute the numerical gradient at every face of a triangle mesh.
  16. //
  17. // Inputs:
  18. // V #vertices by 3 list of mesh vertex positions
  19. // F #faces by 3 list of mesh face indices
  20. // X # vertices list of scalar function values
  21. // Outputs:
  22. // G #faces by 3 list of gradient values
  23. //
  24. // Gradient of a scalar function defined on piecewise linear elements (mesh)
  25. // is constant on each triangle i,j,k:
  26. // grad(Xijk) = (Xj-Xi) * (Vi - Vk)^R90 / 2A + (Xk-Xi) * (Vj - Vi)^R90 / 2A
  27. // where Xi is the scalar value at vertex i, Vi is the 3D position of vertex
  28. // i, and A is the area of triangle (i,j,k). ^R90 represent a rotation of
  29. // 90 degrees
  30. //
  31. void grad(const Eigen::MatrixXd &V, const Eigen::MatrixXi &F, const Eigen::VectorXd &X, Eigen::MatrixXd &G );
  32. }
  33. inline void igl::grad(const Eigen::MatrixXd &V, const Eigen::MatrixXi &F, const Eigen::VectorXd &X, Eigen::MatrixXd &G)
  34. {
  35. G = Eigen::MatrixXd::Zero(F.rows(),3);
  36. for (int i = 0; i<F.rows(); ++i)
  37. {
  38. // renaming indices of vertices of triangles for convenience
  39. int i1 = F(i,0);
  40. int i2 = F(i,1);
  41. int i3 = F(i,2);
  42. // #F x 3 matrices of triangle edge vectors, named after opposite vertices
  43. Eigen::RowVector3d v32 = V.row(i3) - V.row(i2);
  44. Eigen::RowVector3d v13 = V.row(i1) - V.row(i3);
  45. Eigen::RowVector3d v21 = V.row(i2) - V.row(i1);
  46. // area of parallelogram is twice area of triangle
  47. // area of parallelogram is || v1 x v2 ||
  48. Eigen::RowVector3d n = v32.cross(v13);
  49. // This does correct l2 norm of rows, so that it contains #F list of twice
  50. // triangle areas
  51. double dblA = std::sqrt(n.dot(n));
  52. // now normalize normals to get unit normals
  53. Eigen::RowVector3d u = n / dblA;
  54. // rotate each vector 90 degrees around normal
  55. double norm21 = std::sqrt(v21.dot(v21));
  56. double norm13 = std::sqrt(v13.dot(v13));
  57. Eigen::RowVector3d eperp21 = u.cross(v21);
  58. eperp21 = eperp21 / std::sqrt(eperp21.dot(eperp21));
  59. eperp21 *= norm21;
  60. Eigen::RowVector3d eperp13 = u.cross(v13);
  61. eperp13 = eperp13 / std::sqrt(eperp13.dot(eperp13));
  62. eperp13 *= norm13;
  63. G.row(i) = ((X[i2] -X[i1]) *eperp13 + (X[i3] - X[i1]) *eperp21) / dblA;
  64. };
  65. }
  66. #endif