intersect_other.cpp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2014 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 "intersect_other.h"
  9. #include "CGAL_includes.hpp"
  10. #include "mesh_to_cgal_triangle_list.h"
  11. #include "remesh_intersections.h"
  12. #ifndef IGL_FIRST_HIT_EXCEPTION
  13. #define IGL_FIRST_HIT_EXCEPTION 10
  14. #endif
  15. // Un-exposed helper functions
  16. namespace igl
  17. {
  18. namespace copyleft
  19. {
  20. namespace cgal
  21. {
  22. template <typename DerivedF>
  23. static IGL_INLINE void push_result(
  24. const Eigen::PlainObjectBase<DerivedF> & F,
  25. const int f,
  26. const int f_other,
  27. const CGAL::Object & result,
  28. std::map<
  29. typename DerivedF::Index,
  30. std::vector<std::pair<typename DerivedF::Index, CGAL::Object> > > &
  31. offending,
  32. std::map<
  33. std::pair<typename DerivedF::Index,typename DerivedF::Index>,
  34. std::vector<typename DerivedF::Index> > & edge2faces)
  35. {
  36. typedef typename DerivedF::Index Index;
  37. typedef std::pair<Index,Index> EMK;
  38. if(offending.count(f) == 0)
  39. {
  40. // first time marking, initialize with new id and empty list
  41. offending[f] = {};
  42. for(Index e = 0; e<3;e++)
  43. {
  44. // append face to edge's list
  45. Index i = F(f,(e+1)%3) < F(f,(e+2)%3) ? F(f,(e+1)%3) : F(f,(e+2)%3);
  46. Index j = F(f,(e+1)%3) < F(f,(e+2)%3) ? F(f,(e+2)%3) : F(f,(e+1)%3);
  47. edge2faces[EMK(i,j)].push_back(f);
  48. }
  49. }
  50. offending[f].push_back({f_other,result});
  51. }
  52. template <
  53. typename Kernel,
  54. typename DerivedVA,
  55. typename DerivedFA,
  56. typename DerivedVB,
  57. typename DerivedFB,
  58. typename DerivedIF,
  59. typename DerivedVVA,
  60. typename DerivedFFA,
  61. typename DerivedJA,
  62. typename DerivedIMA,
  63. typename DerivedVVB,
  64. typename DerivedFFB,
  65. typename DerivedJB,
  66. typename DerivedIMB>
  67. static IGL_INLINE bool intersect_other_helper(
  68. const Eigen::PlainObjectBase<DerivedVA> & VA,
  69. const Eigen::PlainObjectBase<DerivedFA> & FA,
  70. const Eigen::PlainObjectBase<DerivedVB> & VB,
  71. const Eigen::PlainObjectBase<DerivedFB> & FB,
  72. const RemeshSelfIntersectionsParam & params,
  73. Eigen::PlainObjectBase<DerivedIF> & IF,
  74. Eigen::PlainObjectBase<DerivedVVA> & VVA,
  75. Eigen::PlainObjectBase<DerivedFFA> & FFA,
  76. Eigen::PlainObjectBase<DerivedJA> & JA,
  77. Eigen::PlainObjectBase<DerivedIMA> & IMA,
  78. Eigen::PlainObjectBase<DerivedVVB> & VVB,
  79. Eigen::PlainObjectBase<DerivedFFB> & FFB,
  80. Eigen::PlainObjectBase<DerivedJB> & JB,
  81. Eigen::PlainObjectBase<DerivedIMB> & IMB)
  82. {
  83. using namespace std;
  84. using namespace Eigen;
  85. typedef typename DerivedFA::Index Index;
  86. // 3D Primitives
  87. typedef CGAL::Point_3<Kernel> Point_3;
  88. typedef CGAL::Segment_3<Kernel> Segment_3;
  89. typedef CGAL::Triangle_3<Kernel> Triangle_3;
  90. typedef CGAL::Plane_3<Kernel> Plane_3;
  91. typedef CGAL::Tetrahedron_3<Kernel> Tetrahedron_3;
  92. // 2D Primitives
  93. typedef CGAL::Point_2<Kernel> Point_2;
  94. typedef CGAL::Segment_2<Kernel> Segment_2;
  95. typedef CGAL::Triangle_2<Kernel> Triangle_2;
  96. // 2D Constrained Delaunay Triangulation types
  97. typedef CGAL::Triangulation_vertex_base_2<Kernel> TVB_2;
  98. typedef CGAL::Constrained_triangulation_face_base_2<Kernel> CTAB_2;
  99. typedef CGAL::Triangulation_data_structure_2<TVB_2,CTAB_2> TDS_2;
  100. typedef CGAL::Exact_intersections_tag Itag;
  101. typedef CGAL::Constrained_Delaunay_triangulation_2<Kernel,TDS_2,Itag>
  102. CDT_2;
  103. typedef CGAL::Constrained_triangulation_plus_2<CDT_2> CDT_plus_2;
  104. // Axis-align boxes for all-pairs self-intersection detection
  105. typedef std::vector<Triangle_3> Triangles;
  106. typedef typename Triangles::iterator TrianglesIterator;
  107. typedef typename Triangles::const_iterator TrianglesConstIterator;
  108. typedef
  109. CGAL::Box_intersection_d::Box_with_handle_d<double,3,TrianglesIterator>
  110. Box;
  111. typedef
  112. std::map<Index,std::vector<std::pair<Index,CGAL::Object> > >
  113. OffendingMap;
  114. typedef std::map<std::pair<Index,Index>,std::vector<Index> > EdgeMap;
  115. typedef std::pair<Index,Index> EMK;
  116. Triangles TA,TB;
  117. // Compute and process self intersections
  118. mesh_to_cgal_triangle_list(VA,FA,TA);
  119. mesh_to_cgal_triangle_list(VB,FB,TB);
  120. // http://www.cgal.org/Manual/latest/doc_html/cgal_manual/Box_intersection_d/Chapter_main.html#Section_63.5
  121. // Create the corresponding vector of bounding boxes
  122. std::vector<Box> A_boxes,B_boxes;
  123. const auto box_up = [](Triangles & T, std::vector<Box> & boxes) -> void
  124. {
  125. boxes.reserve(T.size());
  126. for (
  127. TrianglesIterator tit = T.begin();
  128. tit != T.end();
  129. ++tit)
  130. {
  131. boxes.push_back(Box(tit->bbox(), tit));
  132. }
  133. };
  134. box_up(TA,A_boxes);
  135. box_up(TB,B_boxes);
  136. OffendingMap offendingA,offendingB;
  137. EdgeMap edge2facesA,edge2facesB;
  138. std::list<int> lIF;
  139. const auto cb = [&](const Box &a, const Box &b) -> void
  140. {
  141. using namespace std;
  142. // index in F and T
  143. int fa = a.handle()-TA.begin();
  144. int fb = b.handle()-TB.begin();
  145. const Triangle_3 & A = *a.handle();
  146. const Triangle_3 & B = *b.handle();
  147. if(CGAL::do_intersect(A,B))
  148. {
  149. // There was an intersection
  150. lIF.push_back(fa);
  151. lIF.push_back(fb);
  152. if(params.first_only)
  153. {
  154. throw IGL_FIRST_HIT_EXCEPTION;
  155. }
  156. if(!params.detect_only)
  157. {
  158. CGAL::Object result = CGAL::intersection(A,B);
  159. push_result(FA,fa,fb,result,offendingA,edge2facesA);
  160. push_result(FB,fb,fa,result,offendingB,edge2facesB);
  161. }
  162. }
  163. };
  164. try{
  165. CGAL::box_intersection_d(
  166. A_boxes.begin(), A_boxes.end(),
  167. B_boxes.begin(), B_boxes.end(),
  168. cb);
  169. }catch(int e)
  170. {
  171. // Rethrow if not FIRST_HIT_EXCEPTION
  172. if(e != IGL_FIRST_HIT_EXCEPTION)
  173. {
  174. throw e;
  175. }
  176. // Otherwise just fall through
  177. }
  178. // Convert lIF to Eigen matrix
  179. assert(lIF.size()%2 == 0);
  180. IF.resize(lIF.size()/2,2);
  181. {
  182. int i=0;
  183. for(
  184. list<int>::const_iterator ifit = lIF.begin();
  185. ifit!=lIF.end();
  186. )
  187. {
  188. IF(i,0) = (*ifit);
  189. ifit++;
  190. IF(i,1) = (*ifit);
  191. ifit++;
  192. i++;
  193. }
  194. }
  195. if(!params.detect_only)
  196. {
  197. remesh_intersections(VA,FA,TA,offendingA,edge2facesA,VVA,FFA,JA,IMA);
  198. remesh_intersections(VB,FB,TB,offendingB,edge2facesB,VVB,FFB,JB,IMB);
  199. }
  200. return IF.rows() > 0;
  201. }
  202. }
  203. }
  204. }
  205. template <
  206. typename DerivedVA,
  207. typename DerivedFA,
  208. typename DerivedVB,
  209. typename DerivedFB,
  210. typename DerivedIF,
  211. typename DerivedVVA,
  212. typename DerivedFFA,
  213. typename DerivedJA,
  214. typename DerivedIMA,
  215. typename DerivedVVB,
  216. typename DerivedFFB,
  217. typename DerivedJB,
  218. typename DerivedIMB>
  219. IGL_INLINE bool igl::copyleft::cgal::intersect_other(
  220. const Eigen::PlainObjectBase<DerivedVA> & VA,
  221. const Eigen::PlainObjectBase<DerivedFA> & FA,
  222. const Eigen::PlainObjectBase<DerivedVB> & VB,
  223. const Eigen::PlainObjectBase<DerivedFB> & FB,
  224. const RemeshSelfIntersectionsParam & params,
  225. Eigen::PlainObjectBase<DerivedIF> & IF,
  226. Eigen::PlainObjectBase<DerivedVVA> & VVA,
  227. Eigen::PlainObjectBase<DerivedFFA> & FFA,
  228. Eigen::PlainObjectBase<DerivedJA> & JA,
  229. Eigen::PlainObjectBase<DerivedIMA> & IMA,
  230. Eigen::PlainObjectBase<DerivedVVB> & VVB,
  231. Eigen::PlainObjectBase<DerivedFFB> & FFB,
  232. Eigen::PlainObjectBase<DerivedJB> & JB,
  233. Eigen::PlainObjectBase<DerivedIMB> & IMB)
  234. {
  235. if(params.detect_only)
  236. {
  237. return intersect_other_helper<CGAL::Epick>
  238. (VA,FA,VB,FB,params,IF,VVA,FFA,JA,IMA,VVB,FFB,JB,IMB);
  239. }else
  240. {
  241. return intersect_other_helper<CGAL::Epeck>
  242. (VA,FA,VB,FB,params,IF,VVA,FFA,JA,IMA,VVB,FFB,JB,IMB);
  243. }
  244. }
  245. IGL_INLINE bool igl::copyleft::cgal::intersect_other(
  246. const Eigen::MatrixXd & VA,
  247. const Eigen::MatrixXi & FA,
  248. const Eigen::MatrixXd & VB,
  249. const Eigen::MatrixXi & FB,
  250. const bool first_only,
  251. Eigen::MatrixXi & IF)
  252. {
  253. Eigen::MatrixXd VVA,VVB;
  254. Eigen::MatrixXi FFA,FFB;
  255. Eigen::VectorXi JA,JB,IMA,IMB;
  256. return intersect_other(
  257. VA,FA,VB,FB,{true,first_only},IF,VVA,FFA,JA,IMA,VVB,FFB,JB,IMB);
  258. }
  259. #ifdef IGL_STATIC_LIBRARY
  260. // Explicit template specialization
  261. #endif