remesh_along_isoline.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2018 Alec Jacobson <[email protected]>
  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 "remesh_along_isoline.h"
  9. #include "list_to_matrix.h"
  10. #include <unordered_map>
  11. template <
  12. typename DerivedV,
  13. typename DerivedF,
  14. typename DerivedS,
  15. typename DerivedU,
  16. typename DerivedG,
  17. typename DerivedJ,
  18. typename BCtype,
  19. typename DerivedSU,
  20. typename DerivedL>
  21. IGL_INLINE void igl::remesh_along_isoline(
  22. const Eigen::MatrixBase<DerivedV> & V,
  23. const Eigen::MatrixBase<DerivedF> & F,
  24. const Eigen::MatrixBase<DerivedS> & S,
  25. const typename DerivedS::Scalar val,
  26. Eigen::PlainObjectBase<DerivedU> & U,
  27. Eigen::PlainObjectBase<DerivedG> & G,
  28. Eigen::PlainObjectBase<DerivedSU> & SU,
  29. Eigen::PlainObjectBase<DerivedJ> & J,
  30. Eigen::SparseMatrix<BCtype> & BC,
  31. Eigen::PlainObjectBase<DerivedL> & L)
  32. {
  33. igl::remesh_along_isoline(V.rows(),F,S,val,G,SU,J,BC,L);
  34. U = BC * V;
  35. }
  36. template <
  37. typename DerivedF,
  38. typename DerivedS,
  39. typename DerivedG,
  40. typename DerivedJ,
  41. typename BCtype,
  42. typename DerivedSU,
  43. typename DerivedL>
  44. IGL_INLINE void igl::remesh_along_isoline(
  45. const int num_vertices,
  46. const Eigen::MatrixBase<DerivedF> & F,
  47. const Eigen::MatrixBase<DerivedS> & S,
  48. const typename DerivedS::Scalar val,
  49. Eigen::PlainObjectBase<DerivedG> & G,
  50. Eigen::PlainObjectBase<DerivedSU> & SU,
  51. Eigen::PlainObjectBase<DerivedJ> & J,
  52. Eigen::SparseMatrix<BCtype> & BC,
  53. Eigen::PlainObjectBase<DerivedL> & L)
  54. {
  55. // Lazy implementation using vectors
  56. //assert(val.size() == 1);
  57. const int isoval_i = 0;
  58. //auto isoval = val(isoval_i);
  59. auto isoval = val;
  60. std::vector<std::vector<typename DerivedG::Scalar> > vG;
  61. std::vector<typename DerivedJ::Scalar> vJ;
  62. std::vector<typename DerivedL::Scalar> vL;
  63. std::vector<Eigen::Triplet<BCtype> > vBC;
  64. int Ucount = 0;
  65. for(int i = 0;i<num_vertices;i++)
  66. {
  67. vBC.emplace_back(Ucount,i,1.0);
  68. Ucount++;
  69. }
  70. // Loop over each face
  71. std::unordered_map<int, std::unordered_map<int, int>> edgeToBirthVert;
  72. for(int f = 0;f<F.rows();f++)
  73. {
  74. bool Psign[2];
  75. int P[2];
  76. int count = 0;
  77. for(int p = 0;p<3;p++)
  78. {
  79. const bool psign = S(F(f,p)) > isoval;
  80. // Find crossings
  81. const int n = (p+1)%3;
  82. const bool nsign = S(F(f,n)) > isoval;
  83. if(psign != nsign)
  84. {
  85. P[count] = p;
  86. Psign[count] = psign;
  87. // record crossing
  88. count++;
  89. }
  90. }
  91. assert(count == 0 || count == 2);
  92. switch(count)
  93. {
  94. case 0:
  95. {
  96. // Easy case
  97. std::vector<typename DerivedG::Scalar> row = {F(f,0),F(f,1),F(f,2)};
  98. vG.push_back(row);
  99. vJ.push_back(f);
  100. vL.push_back( S(F(f,0))>isoval ? isoval_i+1 : isoval_i );
  101. break;
  102. }
  103. case 2:
  104. {
  105. // Cut case
  106. // flip so that P[1] is the one-off vertex
  107. if(P[0] == 0 && P[1] == 2)
  108. {
  109. std::swap(P[0],P[1]);
  110. std::swap(Psign[0],Psign[1]);
  111. }
  112. assert(Psign[0] != Psign[1]);
  113. // Create two new vertices
  114. for(int i = 0;i<2;i++)
  115. {
  116. if ((edgeToBirthVert.find(F(f, P[i])) == edgeToBirthVert.end()) || (edgeToBirthVert.at(F(f, P[i])).find(F(f, (P[i] + 1) % 3)) == edgeToBirthVert.at(F(f, P[i])).end()))
  117. {
  118. const double bci = (isoval - S(F(f,(P[i]+1)%3)))/
  119. (S(F(f,P[i]))-S(F(f,(P[i]+1)%3)));
  120. vBC.emplace_back(Ucount,F(f,P[i]),bci);
  121. vBC.emplace_back(Ucount,F(f,(P[i]+1)%3),1.0-bci);
  122. edgeToBirthVert[F(f, P[i])][F(f, (P[i] + 1) % 3)] = Ucount;
  123. edgeToBirthVert[F(f, (P[i] + 1) % 3)][F(f, P[i])] = Ucount;
  124. Ucount++;
  125. }
  126. }
  127. const int v0 = F(f,P[0]);
  128. assert(((P[0]+1)%3) == P[1]);
  129. const int v1 = F(f,P[1]);
  130. const int v2 = F(f,(P[1]+1)%3);
  131. const int v01 = edgeToBirthVert[v0][v1];
  132. const int v12 = edgeToBirthVert[v1][v2];
  133. // v0
  134. // | ╲
  135. // | ╲
  136. // | ╲
  137. // v01 ╲
  138. // | ╲
  139. // | ╲
  140. // | ╲
  141. // v1--v12---v2
  142. typedef std::vector<typename DerivedG::Scalar> Row;
  143. {Row row = {v01,v1,v12}; vG.push_back(row);vJ.push_back(f);vL.push_back(Psign[0]?isoval_i:isoval_i+1);}
  144. {Row row = {v12,v2,v01}; vG.push_back(row);vJ.push_back(f);vL.push_back(Psign[1]?isoval_i:isoval_i+1);}
  145. {Row row = {v2,v0,v01}; vG.push_back(row) ;vJ.push_back(f);vL.push_back(Psign[1]?isoval_i:isoval_i+1);}
  146. break;
  147. }
  148. default: assert(false);
  149. }
  150. }
  151. igl::list_to_matrix(vG,G);
  152. igl::list_to_matrix(vJ,J);
  153. igl::list_to_matrix(vL,L);
  154. BC.resize(Ucount,num_vertices);
  155. BC.setFromTriplets(vBC.begin(),vBC.end());
  156. SU = BC * S;
  157. }
  158. #ifdef IGL_STATIC_LIBRARY
  159. // Explicit template instantiation
  160. template void igl::remesh_along_isoline<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::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, double, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::Matrix<double, -1, 1, 0, -1, 1>::Scalar, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::SparseMatrix<double, 0, int>&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
  161. #endif