intersect_other.cpp 8.6 KB

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