grad.h 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  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 IGL_GRAD_H
  9. #define IGL_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. template <typename T>
  32. inline void grad(const Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> &V,
  33. const Eigen::MatrixXi &F,
  34. const Eigen::Matrix<T, Eigen::Dynamic, 1>&X,
  35. Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> &G );
  36. }
  37. // Implementation
  38. template <typename T>
  39. inline void igl::grad(const Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> &V,
  40. const Eigen::MatrixXi &F,
  41. const Eigen::Matrix<T, Eigen::Dynamic, 1>&X,
  42. Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> &G )
  43. {
  44. G = Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>::Zero(F.rows(),3);
  45. for (int i = 0; i<F.rows(); ++i)
  46. {
  47. // renaming indices of vertices of triangles for convenience
  48. int i1 = F(i,0);
  49. int i2 = F(i,1);
  50. int i3 = F(i,2);
  51. // #F x 3 matrices of triangle edge vectors, named after opposite vertices
  52. Eigen::Matrix<T, 1, 3> v32 = V.row(i3) - V.row(i2);
  53. Eigen::Matrix<T, 1, 3> v13 = V.row(i1) - V.row(i3);
  54. Eigen::Matrix<T, 1, 3> v21 = V.row(i2) - V.row(i1);
  55. // area of parallelogram is twice area of triangle
  56. // area of parallelogram is || v1 x v2 ||
  57. Eigen::Matrix<T, 1, 3> n = v32.cross(v13);
  58. // This does correct l2 norm of rows, so that it contains #F list of twice
  59. // triangle areas
  60. double dblA = std::sqrt(n.dot(n));
  61. // now normalize normals to get unit normals
  62. Eigen::Matrix<T, 1, 3> u = n / dblA;
  63. // rotate each vector 90 degrees around normal
  64. double norm21 = std::sqrt(v21.dot(v21));
  65. double norm13 = std::sqrt(v13.dot(v13));
  66. Eigen::Matrix<T, 1, 3> eperp21 = u.cross(v21);
  67. eperp21 = eperp21 / std::sqrt(eperp21.dot(eperp21));
  68. eperp21 *= norm21;
  69. Eigen::Matrix<T, 1, 3> eperp13 = u.cross(v13);
  70. eperp13 = eperp13 / std::sqrt(eperp13.dot(eperp13));
  71. eperp13 *= norm13;
  72. G.row(i) = ((X[i2] -X[i1]) *eperp13 + (X[i3] - X[i1]) *eperp21) / dblA;
  73. };
  74. }
  75. #endif