internal_angles.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
  4. // Copyright (C) 2015 Daniele Panozzo <daniele.panozzo@gmail.com>
  5. //
  6. // This Source Code Form is subject to the terms of the Mozilla Public License
  7. // v. 2.0. If a copy of the MPL was not distributed with this file, You can
  8. // obtain one at http://mozilla.org/MPL/2.0/.
  9. #include "internal_angles.h"
  10. #include "edge_lengths.h"
  11. #include "get_seconds.h"
  12. template <typename DerivedV, typename DerivedF, typename DerivedK>
  13. IGL_INLINE void igl::internal_angles(
  14. const Eigen::PlainObjectBase<DerivedV>& V,
  15. const Eigen::PlainObjectBase<DerivedF>& F,
  16. Eigen::PlainObjectBase<DerivedK> & K)
  17. {
  18. using namespace Eigen;
  19. using namespace std;
  20. typedef typename DerivedV::Scalar Scalar;
  21. if(F.cols() == 3)
  22. {
  23. // Edge lengths
  24. Matrix<
  25. Scalar,
  26. DerivedF::RowsAtCompileTime,
  27. DerivedF::ColsAtCompileTime> L;
  28. edge_lengths(V,F,L);
  29. assert(F.cols() == 3 && "F should contain triangles");
  30. internal_angles(L,K);
  31. }else
  32. {
  33. assert(V.cols() == 3 && "If F contains non-triangle facets, V must be 3D");
  34. K.resize(F.rows(),F.cols());
  35. auto corner = [](
  36. const Eigen::PlainObjectBase<DerivedV>& x,
  37. const Eigen::PlainObjectBase<DerivedV>& y,
  38. const Eigen::PlainObjectBase<DerivedV>& z)
  39. {
  40. typedef Eigen::Matrix<Scalar,1,3> RowVector3S;
  41. RowVector3S v1 = (x-y).normalized();
  42. RowVector3S v2 = (z-y).normalized();
  43. // http://stackoverflow.com/questions/10133957/signed-angle-between-two-vectors-without-a-reference-plane
  44. Scalar s = v1.cross(v2).norm();
  45. Scalar c = v1.dot(v2);
  46. return atan2(s, c);
  47. };
  48. for(unsigned i=0; i<F.rows(); ++i)
  49. {
  50. for(unsigned j=0; j<F.cols(); ++j)
  51. {
  52. K(i,j) = corner(
  53. V.row(F(i,int(j-1+F.cols())%F.cols())),
  54. V.row(F(i,j)),
  55. V.row(F(i,(j+1+F.cols())%F.cols()))
  56. );
  57. }
  58. }
  59. }
  60. }
  61. template <typename DerivedL, typename DerivedK>
  62. IGL_INLINE void igl::internal_angles(
  63. const Eigen::PlainObjectBase<DerivedL>& L,
  64. Eigen::PlainObjectBase<DerivedK> & K)
  65. {
  66. typedef typename DerivedL::Index Index;
  67. assert(L.cols() == 3 && "Edge-lengths should come from triangles");
  68. const Index m = L.rows();
  69. K.resize(m,3);
  70. //for(int d = 0;d<3;d++)
  71. //{
  72. // const auto & s1 = L.col(d).array();
  73. // const auto & s2 = L.col((d+1)%3).array();
  74. // const auto & s3 = L.col((d+2)%3).array();
  75. // K.col(d) = ((s3.square() + s2.square() - s1.square())/(2.*s3*s2)).acos();
  76. //}
  77. // Minimum number of iterms per openmp thread
  78. #ifndef IGL_OMP_MIN_VALUE
  79. # define IGL_OMP_MIN_VALUE 1000
  80. #endif
  81. #pragma omp parallel for if (m>IGL_OMP_MIN_VALUE)
  82. for(Index f = 0;f<m;f++)
  83. {
  84. for(size_t d = 0;d<3;d++)
  85. {
  86. const auto & s1 = L(f,d);
  87. const auto & s2 = L(f,(d+1)%3);
  88. const auto & s3 = L(f,(d+2)%3);
  89. K(f,d) = acos((s3*s3 + s2*s2 - s1*s1)/(2.*s3*s2));
  90. }
  91. }
  92. }
  93. #ifdef IGL_STATIC_LIBRARY
  94. // Explicit template specialization
  95. // generated by autoexplicit.sh
  96. template void igl::internal_angles<Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3>, Eigen::Matrix<float, -1, 3, 0, -1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> >&);
  97. template void igl::internal_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::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> >&);
  98. template void igl::internal_angles<Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<unsigned int, -1, -1, 1, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<unsigned int, -1, -1, 1, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
  99. template void igl::internal_angles<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
  100. template void igl::internal_angles<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 3, 0, -1, 3> >(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, 3, 0, -1, 3> >&);
  101. template void igl::internal_angles<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&);
  102. #endif