orient_outward.cpp 2.4 KB

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