orient_outward.cpp 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. #include "orient_outward.h"
  2. #include "per_face_normals.h"
  3. #include "barycenter.h"
  4. #include "doublearea.h"
  5. #include <iostream>
  6. template <
  7. typename DerivedV,
  8. typename DerivedF,
  9. typename DerivedC,
  10. typename DerivedFF,
  11. typename DerivedI>
  12. IGL_INLINE void igl::orient_outward(
  13. const Eigen::PlainObjectBase<DerivedV> & V,
  14. const Eigen::PlainObjectBase<DerivedF> & F,
  15. const Eigen::PlainObjectBase<DerivedC> & C,
  16. Eigen::PlainObjectBase<DerivedFF> & FF,
  17. Eigen::PlainObjectBase<DerivedI> & I)
  18. {
  19. using namespace Eigen;
  20. using namespace std;
  21. assert(C.rows() == F.rows());
  22. assert(F.cols() == 3);
  23. assert(V.cols() == 3);
  24. // number of faces
  25. const int m = F.rows();
  26. // number of patches
  27. const int num_cc = C.maxCoeff()+1;
  28. I.resize(num_cc);
  29. if(&FF != &F)
  30. {
  31. FF = F;
  32. }
  33. PlainObjectBase<DerivedV> N,BC,BCmean;
  34. Matrix<typename DerivedV::Scalar,Dynamic,1> A;
  35. VectorXd totA(num_cc), dot(num_cc);
  36. per_face_normals(V,F,N);
  37. barycenter(V,F,BC);
  38. doublearea(V,F,A);
  39. BCmean.setConstant(num_cc,3,0);
  40. // loop over faces
  41. for(int f = 0;f<m;f++)
  42. {
  43. BCmean.row(C(f)) += A(f)*BC.row(f);
  44. totA(C(f))++;
  45. }
  46. // take area weighted average
  47. for(int c = 0;c<num_cc;c++)
  48. {
  49. BCmean.row(c) /= (typename DerivedV::Scalar) totA(c);
  50. }
  51. // subtract bcmean
  52. for(int f = 0;f<m;f++)
  53. {
  54. BC.row(f) -= BCmean.row(C(f));
  55. dot(C(f)) += A(f)*N.row(f).dot(BC.row(f));
  56. }
  57. // take area weighted average
  58. for(int c = 0;c<num_cc;c++)
  59. {
  60. dot(c) /= (typename DerivedV::Scalar) totA(c);
  61. if(dot(c) < 0)
  62. {
  63. I(c) = true;
  64. }else
  65. {
  66. I(c) = false;
  67. }
  68. }
  69. // flip according to I
  70. for(int f = 0;f<m;f++)
  71. {
  72. if(I(C(f)))
  73. {
  74. FF.row(f) = FF.row(f).reverse().eval();
  75. }
  76. }
  77. }
  78. #ifndef IGL_HEADER_ONLY
  79. // Explicit template specialization
  80. template void igl::orient_outward<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::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> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
  81. #endif