dihedral_angles.cpp 5.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2014 Alec Jacobson <alecjacobson@gmail.com>
  4. //
  5. // This Source Code Form is subject to the terms of the Mozilla Public License
  6. // v. 2.0. If a copy of the MPL was not distributed with this file, You can
  7. // obtain one at http://mozilla.org/MPL/2.0/.
  8. #include "dihedral_angles.h"
  9. #include "edge_lengths.h"
  10. #include "face_areas.h"
  11. #include <cassert>
  12. template <
  13. typename DerivedV,
  14. typename DerivedT,
  15. typename Derivedtheta,
  16. typename Derivedcos_theta>
  17. IGL_INLINE void igl::dihedral_angles(
  18. const Eigen::PlainObjectBase<DerivedV>& V,
  19. const Eigen::PlainObjectBase<DerivedT>& T,
  20. Eigen::PlainObjectBase<Derivedtheta>& theta,
  21. Eigen::PlainObjectBase<Derivedcos_theta>& cos_theta)
  22. {
  23. using namespace Eigen;
  24. assert(T.cols() == 4);
  25. Matrix<typename Derivedtheta::Scalar,Dynamic,6> l;
  26. edge_lengths(V,T,l);
  27. Matrix<typename Derivedtheta::Scalar,Dynamic,4> s;
  28. face_areas(l,s);
  29. return dihedral_angles_intrinsic(l,s,theta,cos_theta);
  30. }
  31. template <
  32. typename DerivedL,
  33. typename DerivedA,
  34. typename Derivedtheta,
  35. typename Derivedcos_theta>
  36. IGL_INLINE void igl::dihedral_angles_intrinsic(
  37. const Eigen::PlainObjectBase<DerivedL>& L,
  38. const Eigen::PlainObjectBase<DerivedA>& A,
  39. Eigen::PlainObjectBase<Derivedtheta>& theta,
  40. Eigen::PlainObjectBase<Derivedcos_theta>& cos_theta)
  41. {
  42. using namespace Eigen;
  43. const int m = L.rows();
  44. assert(m == A.rows());
  45. // Law of cosines
  46. // http://math.stackexchange.com/a/49340/35376
  47. Matrix<typename Derivedtheta::Scalar,Dynamic,6> H_sqr(m,6);
  48. H_sqr.col(0) = (1./16.) * (4. * L.col(3).array().square() * L.col(0).array().square() -
  49. ((L.col(1).array().square() + L.col(4).array().square()) -
  50. (L.col(2).array().square() + L.col(5).array().square())).square());
  51. H_sqr.col(1) = (1./16.) * (4. * L.col(4).array().square() * L.col(1).array().square() -
  52. ((L.col(2).array().square() + L.col(5).array().square()) -
  53. (L.col(3).array().square() + L.col(0).array().square())).square());
  54. H_sqr.col(2) = (1./16.) * (4. * L.col(5).array().square() * L.col(2).array().square() -
  55. ((L.col(3).array().square() + L.col(0).array().square()) -
  56. (L.col(4).array().square() + L.col(1).array().square())).square());
  57. H_sqr.col(3) = (1./16.) * (4. * L.col(0).array().square() * L.col(3).array().square() -
  58. ((L.col(4).array().square() + L.col(1).array().square()) -
  59. (L.col(5).array().square() + L.col(2).array().square())).square());
  60. H_sqr.col(4) = (1./16.) * (4. * L.col(1).array().square() * L.col(4).array().square() -
  61. ((L.col(5).array().square() + L.col(2).array().square()) -
  62. (L.col(0).array().square() + L.col(3).array().square())).square());
  63. H_sqr.col(5) = (1./16.) * (4. * L.col(2).array().square() * L.col(5).array().square() -
  64. ((L.col(0).array().square() + L.col(3).array().square()) -
  65. (L.col(1).array().square() + L.col(4).array().square())).square());
  66. cos_theta.resize(m,6);
  67. cos_theta.col(0) = (H_sqr.col(0).array() -
  68. A.col(1).array().square() - A.col(2).array().square()).array() /
  69. (-2.*A.col(1).array() * A.col(2).array());
  70. cos_theta.col(1) = (H_sqr.col(1).array() -
  71. A.col(2).array().square() - A.col(0).array().square()).array() /
  72. (-2.*A.col(2).array() * A.col(0).array());
  73. cos_theta.col(2) = (H_sqr.col(2).array() -
  74. A.col(0).array().square() - A.col(1).array().square()).array() /
  75. (-2.*A.col(0).array() * A.col(1).array());
  76. cos_theta.col(3) = (H_sqr.col(3).array() -
  77. A.col(3).array().square() - A.col(0).array().square()).array() /
  78. (-2.*A.col(3).array() * A.col(0).array());
  79. cos_theta.col(4) = (H_sqr.col(4).array() -
  80. A.col(3).array().square() - A.col(1).array().square()).array() /
  81. (-2.*A.col(3).array() * A.col(1).array());
  82. cos_theta.col(5) = (H_sqr.col(5).array() -
  83. A.col(3).array().square() - A.col(2).array().square()).array() /
  84. (-2.*A.col(3).array() * A.col(2).array());
  85. theta = cos_theta.array().acos();
  86. cos_theta.resize(m,6);
  87. }
  88. #ifdef IGL_STATIC_LIBRARY
  89. // Explicit template instantiation
  90. template void igl::dihedral_angles_intrinsic< Eigen::Matrix<double, -1, 6, 0, -1, 6>, Eigen::Matrix<double, -1, 4, 0, -1, 4>, Eigen::Matrix<double, -1, 6, 0, -1, 6>, Eigen::Matrix<double, -1, 6, 0, -1, 6> >(const Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 6, 0, -1, 6> >&, const Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 4, 0, -1, 4> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 6, 0, -1, 6> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 6, 0, -1, 6> >&);
  91. template void igl::dihedral_angles<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
  92. #endif