doublearea.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. #include "doublearea.h"
  2. #include "edge_lengths.h"
  3. #include "sort.h"
  4. #include <cassert>
  5. #include <iostream>
  6. template <typename DerivedV, typename DerivedF, typename DeriveddblA>
  7. IGL_INLINE void igl::doublearea(
  8. const Eigen::PlainObjectBase<DerivedV> & V,
  9. const Eigen::PlainObjectBase<DerivedF> & F,
  10. Eigen::PlainObjectBase<DeriveddblA> & dblA)
  11. {
  12. const int dim = V.cols();
  13. // Only support triangles
  14. assert(F.cols() == 3);
  15. const int m = F.rows();
  16. // Compute edge lengths
  17. Eigen::PlainObjectBase<DerivedV> l;
  18. // "Lecture Notes on Geometric Robustness" Shewchuck 09, Section 3.1
  19. // http://www.cs.berkeley.edu/~jrs/meshpapers/robnotes.pdf
  20. switch(dim)
  21. {
  22. case 3:
  23. {
  24. dblA = Eigen::PlainObjectBase<DeriveddblA>::Zero(m,1);
  25. for(int d = 0;d<3;d++)
  26. {
  27. Eigen::Matrix<typename DerivedV::Scalar, DerivedV::RowsAtCompileTime, 2> Vd(V.rows(),2);
  28. Vd << V.col(d), V.col((d+1)%3);
  29. Eigen::PlainObjectBase<DeriveddblA> dblAd;
  30. doublearea(Vd,F,dblAd);
  31. dblA.array() += dblAd.array().square();
  32. }
  33. dblA = dblA.array().sqrt().eval();
  34. break;
  35. }
  36. case 2:
  37. {
  38. dblA.resize(m,1);
  39. for(int f = 0;f<m;f++)
  40. {
  41. auto r = V.row(F(f,0))-V.row(F(f,2));
  42. auto s = V.row(F(f,1))-V.row(F(f,2));
  43. dblA(f) = r(0)*s(1) - r(1)*s(0);
  44. }
  45. break;
  46. }
  47. default:
  48. {
  49. edge_lengths(V,F,l);
  50. return doublearea(l,dblA);
  51. }
  52. }
  53. }
  54. template <typename Derivedl, typename DeriveddblA>
  55. IGL_INLINE void igl::doublearea(
  56. const Eigen::PlainObjectBase<Derivedl> & ul,
  57. Eigen::PlainObjectBase<DeriveddblA> & dblA)
  58. {
  59. using namespace Eigen;
  60. using namespace std;
  61. // Only support triangles
  62. assert(ul.cols() == 3);
  63. // Number of triangles
  64. const int m = ul.rows();
  65. Eigen::PlainObjectBase<Derivedl> l;
  66. MatrixXi _;
  67. sort(ul,2,false,l,_);
  68. // semiperimeters
  69. Matrix<typename Derivedl::Scalar,Dynamic,1> s = l.rowwise().sum()*0.5;
  70. assert(s.rows() == m);
  71. // resize output
  72. dblA.resize(l.rows(),1);
  73. for(int i = 0;i<m;i++)
  74. {
  75. //// Heron's formula for area
  76. //const typename Derivedl::Scalar arg =
  77. // s(i)*(s(i)-l(i,0))*(s(i)-l(i,1))*(s(i)-l(i,2));
  78. //assert(arg>=0);
  79. //dblA(i) = 2.0*sqrt(arg);
  80. // Kahan's Heron's formula
  81. const typename Derivedl::Scalar arg =
  82. (l(i,0)+(l(i,1)+l(i,2)))*
  83. (l(i,2)-(l(i,0)-l(i,1)))*
  84. (l(i,2)+(l(i,0)-l(i,1)))*
  85. (l(i,0)+(l(i,1)-l(i,2)));
  86. dblA(i) = 2.0*0.25*sqrt(arg);
  87. assert( l(i,2) - (l(i,0)-l(i,1)) && "FAILED KAHAN'S ASSERTION");
  88. assert(dblA(i) == dblA(i) && "DOUBLEAREA() PRODUCED NaN");
  89. }
  90. }
  91. #ifndef IGL_HEADER_ONLY
  92. // Explicit template specialization
  93. // generated by autoexplicit.sh
  94. template void igl::doublearea<Eigen::Matrix<float, -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<float, -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> >&);
  95. template void igl::doublearea<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> >&);
  96. template void igl::doublearea<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<double, -1, 1, 0, -1, 1> >&);
  97. template void igl::doublearea<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -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<int, -1, 1, 0, -1, 1> >&);
  98. #endif