orient_outward.cpp 2.8 KB

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