collapse_edge_would_create_intersections.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. #include "collapse_edge_would_create_intersections.h"
  2. #include "AABB.h"
  3. #include "circulation.h"
  4. #include "writePLY.h"
  5. #include "triangle_triangle_intersect.h"
  6. #include <Eigen/Geometry>
  7. #include <vector>
  8. #include <iostream>
  9. #include <algorithm>
  10. #include <cassert>
  11. template <
  12. typename Derivedp,
  13. typename DerivedV,
  14. typename DerivedF,
  15. typename DerivedE,
  16. typename DerivedEMAP,
  17. typename DerivedEF,
  18. typename DerivedEI>
  19. IGL_INLINE bool igl::collapse_edge_would_create_intersections(
  20. const int e,
  21. const Eigen::MatrixBase<Derivedp> & p,
  22. const Eigen::MatrixBase<DerivedV> & V,
  23. const Eigen::MatrixBase<DerivedF> & F,
  24. const Eigen::MatrixBase<DerivedE> & E,
  25. const Eigen::MatrixBase<DerivedEMAP> & EMAP,
  26. const Eigen::MatrixBase<DerivedEF> & EF,
  27. const Eigen::MatrixBase<DerivedEI> & EI,
  28. const igl::AABB<DerivedV,3> & tree,
  29. const int inf_face_id)
  30. {
  31. // Merge two lists of integers
  32. const auto merge = [&](
  33. const std::vector<int> & A, const std::vector<int> & B)->
  34. std::vector<int>
  35. {
  36. std::vector<int> C;
  37. C.reserve( A.size() + B.size() ); // preallocate memory
  38. C.insert( C.end(), A.begin(), A.end() );
  39. C.insert( C.end(), B.begin(), B.end() );
  40. // https://stackoverflow.com/a/1041939/148668
  41. std::sort( C.begin(), C.end() );
  42. C.erase( std::unique( C.begin(), C.end() ), C.end() );
  43. return C;
  44. };
  45. std::vector<int> old_one_ring;
  46. {
  47. std::vector<int> Nsv,Nsf,Ndv,Ndf;
  48. igl::circulation(e, true,F,EMAP,EF,EI,Nsv,Nsf);
  49. igl::circulation(e,false,F,EMAP,EF,EI,Ndv,Ndf);
  50. old_one_ring = merge(Nsf,Ndf);
  51. }
  52. int f1 = EF(e,0);
  53. int f2 = EF(e,1);
  54. std::vector<int> new_one_ring = old_one_ring;
  55. // erase if ==f1 or ==f2
  56. new_one_ring.erase(
  57. std::remove(new_one_ring.begin(), new_one_ring.end(), f1),
  58. new_one_ring.end());
  59. new_one_ring.erase(
  60. std::remove(new_one_ring.begin(), new_one_ring.end(), f2),
  61. new_one_ring.end());
  62. // big box containing new_one_ring
  63. Eigen::AlignedBox<double,3> big_box;
  64. // Extend box by placement point
  65. big_box.extend(p.transpose());
  66. // Extend box by all other corners (skipping old edge vertices)
  67. for(const auto f : new_one_ring)
  68. {
  69. Eigen::RowVector3d corners[3];
  70. for(int c = 0;c<3;c++)
  71. {
  72. if(F(f,c) == E(e,0) || F(f,c) == E(e,1))
  73. {
  74. corners[c] = p;
  75. }else
  76. {
  77. corners[c] = V.row(F(f,c));
  78. big_box.extend(V.row(F(f,c)).transpose());
  79. }
  80. }
  81. // Degenerate triangles are considered intersections
  82. if((corners[0]-corners[1]).cross(corners[0]-corners[2]).squaredNorm() < 1e-16)
  83. {
  84. return true;
  85. }
  86. }
  87. std::vector<const igl::AABB<Eigen::MatrixXd,3>*> candidates;
  88. tree.append_intersecting_leaves(big_box,candidates);
  89. // Exclude any candidates that are in old_one_ring.
  90. // consider using unordered_set above so that this is O(n+m) rather than O(nm)
  91. candidates.erase(
  92. std::remove_if(candidates.begin(), candidates.end(),
  93. [&](const igl::AABB<Eigen::MatrixXd,3>* candidate) {
  94. return std::find(old_one_ring.begin(), old_one_ring.end(), candidate->m_primitive) != old_one_ring.end();
  95. }),
  96. candidates.end());
  97. // print candidates
  98. //const bool stinker = e==2581;
  99. constexpr bool stinker = false;
  100. if(stinker)
  101. {
  102. igl::writePLY("before.ply",V,F);
  103. std::cout<<"Ee = ["<<E(e,0)<<" "<<E(e,1)<<"]+1;"<<std::endl;
  104. std::cout<<"p = ["<<p<<"];"<<std::endl;
  105. // print new_one_ring as matlab vector of indices
  106. std::cout<<"new_one_ring = [";
  107. for(const auto f : new_one_ring)
  108. {
  109. std::cout<<f<<" ";
  110. }
  111. std::cout<<"]+1;"<<std::endl;
  112. // print candidates as matlab vector of indices
  113. std::cout<<"candidates = [";
  114. for(const auto * candidate : candidates)
  115. {
  116. std::cout<<candidate->m_primitive<<" ";
  117. }
  118. std::cout<<"]+1;"<<std::endl;
  119. }
  120. // For each pair of candidate and new_one_ring, check if they intersect
  121. bool found_intersection = false;
  122. for(const int & f : new_one_ring)
  123. {
  124. if(inf_face_id >= 0 && f >= inf_face_id) { continue; }
  125. Eigen::AlignedBox<double,3> small_box;
  126. small_box.extend(p.transpose());
  127. for(int c = 0;c<3;c++)
  128. {
  129. if(F(f,c) != E(e,0) && F(f,c) != E(e,1))
  130. {
  131. small_box.extend(V.row(F(f,c)).transpose());
  132. }
  133. }
  134. for(const auto * candidate : candidates)
  135. {
  136. const int g = candidate->m_primitive;
  137. //constexpr bool inner_stinker = false;
  138. const bool inner_stinker = stinker && (f==1492 && g==1554);
  139. if(inner_stinker){ printf(" f: %d g: %d\n",f,g); }
  140. if(!small_box.intersects(candidate->m_box))
  141. {
  142. if(inner_stinker){ printf(" ✅ boxes don't overlap\n"); }
  143. continue;
  144. }
  145. // Corner replaced by p
  146. int c;
  147. for(c = 0;c<3;c++)
  148. {
  149. if(F(f,c) == E(e,0) || F(f,c) == E(e,1))
  150. {
  151. break;
  152. }
  153. }
  154. assert(c<3);
  155. found_intersection = triangle_triangle_intersect(V,F,E,EMAP,EF,f,c,p,g);
  156. if(found_intersection) { break; }
  157. }
  158. if(found_intersection) { break; }
  159. }
  160. return found_intersection;
  161. }
  162. #ifdef IGL_STATIC_LIBRARY
  163. // Explicit template instantiation
  164. template bool igl::collapse_edge_would_create_intersections<Eigen::Matrix<double, 1, -1, 1, 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>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>>(int, Eigen::MatrixBase<Eigen::Matrix<double, 1, -1, 1, 1, -1>> const&, 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::MatrixBase<Eigen::Matrix<int, -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&, igl::AABB<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 3> const&, int);
  165. #endif