fast_find_self_intersections.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2022 Vladimir S. FONOV <[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 "fast_find_self_intersections.h"
  9. #include "AABB.h"
  10. #include "tri_tri_intersect.h"
  11. namespace igl{
  12. namespace internal {
  13. // helper function, to check if two faces have shared vertices
  14. template <typename Derived>
  15. bool adjacent_faces(const Eigen::MatrixBase<Derived>& A,
  16. const Eigen::MatrixBase<Derived>& B)
  17. {
  18. for(int i=0;i<3;++i)
  19. for(int j=0;j<3;j++)
  20. {
  21. if(A(i)==B(j))
  22. return true;
  23. }
  24. return false;
  25. }
  26. }
  27. }
  28. template <
  29. typename DerivedV,
  30. typename DerivedF,
  31. typename DerivedI>
  32. IGL_INLINE bool igl::fast_find_self_intersections(
  33. const Eigen::MatrixBase<DerivedV>& V,
  34. const Eigen::MatrixBase<DerivedF>& F,
  35. Eigen::PlainObjectBase<DerivedI>& intersect)
  36. {
  37. using Scalar=typename DerivedV::Scalar;
  38. using BBOX=Eigen::AlignedBox<Scalar,3>;
  39. using AABBTree=igl::AABB<DerivedV,3>;
  40. AABBTree tree;
  41. tree.init(V,F);
  42. bool _intersects=false;
  43. intersect.resize(F.rows(),1);
  44. intersect.setConstant(0);
  45. for(int i=0; i<F.rows(); ++i)
  46. {
  47. if( intersect(i) ) continue;
  48. BBOX tri_box;
  49. for(int j=0;j<3;++j)
  50. tri_box.extend( V.row( F(i,j) ).transpose() );
  51. // find leaf nodes containing intersecting tri_box
  52. // need to declare full type to enable recursion
  53. std::function<bool(const AABBTree &,int)> check_intersect =
  54. [&](const AABBTree &t,int d) -> bool
  55. {
  56. if(t.m_primitive != -1) //check for the actual intersection (is_leaf)
  57. {
  58. if(t.m_primitive==i) //itself
  59. return false;
  60. if(igl::internal::adjacent_faces(F.row(i), F.row(t.m_primitive)) )
  61. return false;
  62. bool coplanar=false;
  63. Eigen::Matrix<Scalar,1,3,Eigen::RowMajor> edge1,edge2;
  64. if(igl::tri_tri_intersection_test_3d(
  65. V.row(F(i,0)),V.row(F(i,1)),V.row(F(i,2)),
  66. V.row(F(t.m_primitive,0)),V.row(F(t.m_primitive,1)),V.row(F(t.m_primitive,2)),
  67. coplanar,
  68. edge1,edge2))
  69. {
  70. if(!coplanar)
  71. {
  72. intersect(i)=1;
  73. intersect(t.m_primitive)=1;
  74. return true;
  75. }
  76. }
  77. } else {
  78. if(t.m_box.intersects(tri_box)) {
  79. // need to check both subtrees
  80. bool r1=check_intersect(*t.m_left ,d+1);
  81. bool r2=check_intersect(*t.m_right,d+1);
  82. return r1||r2;
  83. }
  84. }
  85. return false;
  86. };
  87. bool r=check_intersect(tree,0);
  88. _intersects = _intersects || r;
  89. }
  90. return _intersects;
  91. }
  92. template <
  93. typename DerivedV,
  94. typename DerivedF,
  95. typename DerivedI,
  96. typename DerivedE>
  97. IGL_INLINE bool igl::fast_find_self_intersections(
  98. const Eigen::MatrixBase<DerivedV>& V,
  99. const Eigen::MatrixBase<DerivedF>& F,
  100. Eigen::PlainObjectBase<DerivedI>& intersect,
  101. Eigen::PlainObjectBase<DerivedE>& edges )
  102. {
  103. using Scalar=typename DerivedV::Scalar;
  104. using BBOX=Eigen::AlignedBox<Scalar,3>;
  105. using AABBTree=igl::AABB<DerivedV,3>;
  106. using EDGE=Eigen::Matrix<typename DerivedE::Scalar,1,3,Eigen::RowMajor>;
  107. std::vector<EDGE> _edges;
  108. AABBTree tree;
  109. tree.init(V,F);
  110. bool _intersects=false;
  111. intersect.resize(F.rows(),1);
  112. intersect.setConstant(0);
  113. for(int i=0; i<F.rows(); ++i)
  114. {
  115. if( intersect(i) ) continue;
  116. BBOX tri_box;
  117. for(int j=0;j<3;++j)
  118. tri_box.extend( V.row( F(i,j) ).transpose() );
  119. // find leaf nodes containing intersecting tri_box
  120. std::function<bool(const AABBTree &,int)> check_intersect =
  121. [&](const AABBTree &t,int d) -> bool
  122. {
  123. if(t.m_primitive != -1) //check for the actual intersection //t.is_leaf()
  124. {
  125. if(t.m_primitive==i) //itself
  126. return false;
  127. if(igl::internal::adjacent_faces(F.row(i), F.row(t.m_primitive)) )
  128. return false;
  129. bool coplanar=false;
  130. EDGE edge1,edge2;
  131. if(igl::tri_tri_intersection_test_3d(
  132. V.row(F(i,0)), V.row(F(i,1)), V.row(F(i,2)),
  133. V.row(F(t.m_primitive,0)),V.row(F(t.m_primitive,1)),V.row(F(t.m_primitive,2)),
  134. coplanar,
  135. edge1,edge2))
  136. {
  137. if(!coplanar)
  138. {
  139. intersect(i)=1;
  140. intersect(t.m_primitive)=1;
  141. _edges.push_back(edge1);
  142. _edges.push_back(edge2);
  143. return true;
  144. }
  145. }
  146. } else {
  147. if(t.m_box.intersects( tri_box ))
  148. {
  149. bool r1=check_intersect(*t.m_left, d+1);
  150. bool r2=check_intersect(*t.m_right,d+1);
  151. return r1||r2;
  152. }
  153. }
  154. return false;
  155. };
  156. // run actual search
  157. bool r=check_intersect(tree, 0);
  158. _intersects = _intersects || r;
  159. }
  160. edges.resize(_edges.size(),3);
  161. int i=0;
  162. for(auto e=std::begin(_edges);e!=std::end(_edges);++e,++i)
  163. {
  164. edges.row(i) = *e;
  165. }
  166. return _intersects;
  167. }
  168. #ifdef IGL_STATIC_LIBRARY
  169. // Explicit template instantiation
  170. template bool igl::fast_find_self_intersections<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<double, -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::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
  171. template bool igl::fast_find_self_intersections<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::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
  172. #endif