cut_mesh.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2019 Hanxiao Shen <[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 "cut_mesh.h"
  9. #include "triangle_triangle_adjacency.h"
  10. #include "HalfEdgeIterator.h"
  11. #include "is_border_vertex.h"
  12. // wrapper for input/output style
  13. template <typename DerivedV, typename DerivedF, typename DerivedC>
  14. IGL_INLINE void igl::cut_mesh(
  15. const Eigen::MatrixBase<DerivedV>& V,
  16. const Eigen::MatrixBase<DerivedF>& F,
  17. const Eigen::MatrixBase<DerivedC>& C,
  18. Eigen::PlainObjectBase<DerivedV>& Vn,
  19. Eigen::PlainObjectBase<DerivedF>& Fn
  20. ){
  21. Vn = V;
  22. Fn = F;
  23. typedef typename DerivedF::Scalar Index;
  24. Eigen::Matrix<Index,Eigen::Dynamic,1> _I;
  25. cut_mesh(Vn,Fn,C,_I);
  26. }
  27. template <
  28. typename DerivedV,
  29. typename DerivedF,
  30. typename DerivedC,
  31. typename DerivedVn,
  32. typename DerivedFn,
  33. typename DerivedI>
  34. IGL_INLINE void igl::cut_mesh(
  35. const Eigen::MatrixBase<DerivedV>& V,
  36. const Eigen::MatrixBase<DerivedF>& F,
  37. const Eigen::MatrixBase<DerivedC>& C,
  38. Eigen::PlainObjectBase<DerivedVn>& Vn,
  39. Eigen::PlainObjectBase<DerivedFn>& Fn,
  40. Eigen::PlainObjectBase<DerivedI>& I
  41. ){
  42. static_assert(std::is_same<typename DerivedV::Scalar, typename DerivedVn::Scalar>::value, "Scalar types of V and Vn must match");
  43. static_assert(std::is_same<typename DerivedF::Scalar, typename DerivedFn::Scalar>::value, "Scalar types of F and Fn must match");
  44. Vn = V;
  45. Fn = F;
  46. cut_mesh(Vn,Fn,C,I);
  47. }
  48. template <typename DerivedV, typename DerivedF, typename DerivedC, typename DerivedI>
  49. IGL_INLINE void igl::cut_mesh(
  50. Eigen::PlainObjectBase<DerivedV>& V,
  51. Eigen::PlainObjectBase<DerivedF>& F,
  52. const Eigen::MatrixBase<DerivedC>& C,
  53. Eigen::PlainObjectBase<DerivedI>& I
  54. ){
  55. DerivedF FF, FFi;
  56. igl::triangle_triangle_adjacency(F,FF,FFi);
  57. igl::cut_mesh(V,F,FF,FFi,C,I);
  58. }
  59. template <typename DerivedV, typename DerivedF, typename DerivedFF, typename DerivedFFi, typename DerivedC, typename DerivedI>
  60. IGL_INLINE void igl::cut_mesh(
  61. Eigen::PlainObjectBase<DerivedV>& V,
  62. Eigen::PlainObjectBase<DerivedF>& F,
  63. Eigen::MatrixBase<DerivedFF>& FF,
  64. Eigen::MatrixBase<DerivedFFi>& FFi,
  65. const Eigen::MatrixBase<DerivedC>& C,
  66. Eigen::PlainObjectBase<DerivedI>& I
  67. ){
  68. typedef typename DerivedF::Scalar Index;
  69. // store current number of occurance of each vertex as the alg proceed
  70. Eigen::Matrix<Index,Eigen::Dynamic,1> occurence(V.rows());
  71. occurence.setConstant(1);
  72. // set eventual number of occurance of each vertex expected
  73. Eigen::Matrix<Index,Eigen::Dynamic,1> eventual(V.rows());
  74. eventual.setZero();
  75. for(Index i=0;i<F.rows();i++){
  76. for(Index k=0;k<3;k++){
  77. Index u = F(i,k);
  78. Index v = F(i,(k+1)%3);
  79. if(FF(i,k) == -1){
  80. // add one extra occurance for boundary vertices
  81. eventual(u) += 1;
  82. }else if(
  83. (u < v) &&
  84. (C(i,k) || C(FF(i,k),FFi(i,k))) )
  85. {
  86. // only compute every (undirected) edge ones
  87. eventual(u) += 1;
  88. eventual(v) += 1;
  89. }
  90. }
  91. }
  92. // original number of vertices
  93. Index n_v = V.rows();
  94. // estimate number of new vertices and resize V
  95. Index n_new = 0;
  96. for(Index i=0;i<eventual.rows();i++)
  97. n_new += ((eventual(i) > 0) ? eventual(i)-1 : 0);
  98. V.conservativeResize(n_v+n_new,Eigen::NoChange);
  99. I = DerivedI::LinSpaced(V.rows(),0,V.rows());
  100. // pointing to the current bottom of V
  101. Index pos = n_v;
  102. for(Index f=0;f<C.rows();f++){
  103. for(Index k=0;k<3;k++){
  104. Index v0 = F(f,k);
  105. if(F(f,k) >= n_v) continue; // ignore new vertices
  106. if(C(f,k) == 1 && occurence(v0) != eventual(v0)){
  107. igl::HalfEdgeIterator<DerivedF,DerivedF,DerivedF> he(F,FF,FFi,f,k);
  108. // rotate clock-wise around v0 until hit another cut
  109. std::vector<Index> fan;
  110. Index fi = he.Fi();
  111. Index ei = he.Ei();
  112. do{
  113. fan.push_back(fi);
  114. he.flipE();
  115. he.flipF();
  116. fi = he.Fi();
  117. ei = he.Ei();
  118. }while(C(fi,ei) == 0 && !he.isBorder());
  119. // make a copy
  120. V.row(pos) << V.row(v0);
  121. I(pos) = v0;
  122. // add one occurance to v0
  123. occurence(v0) += 1;
  124. // replace old v0
  125. for(Index f0: fan)
  126. for(Index j=0;j<3;j++)
  127. if(F(f0,j) == v0)
  128. F(f0,j) = pos;
  129. // mark cuts as boundary
  130. FF(f,k) = -1;
  131. FF(fi,ei) = -1;
  132. pos++;
  133. }
  134. }
  135. }
  136. }
  137. #ifdef IGL_STATIC_LIBRARY
  138. // Explicit template instantiation
  139. template void igl::cut_mesh<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
  140. template void igl::cut_mesh<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(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<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
  141. template void igl::cut_mesh<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::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<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
  142. template void igl::cut_mesh<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::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
  143. #endif