remesh_intersections.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. #include "remesh_intersections.h"
  2. #include "SelfIntersectMesh.h"
  3. #include "assign_scalar.h"
  4. #include "projected_delaunay.h"
  5. #include <iostream>
  6. #include <cassert>
  7. template <
  8. typename DerivedV,
  9. typename DerivedF,
  10. typename Kernel,
  11. typename DerivedVV,
  12. typename DerivedFF,
  13. typename DerivedJ,
  14. typename DerivedIM>
  15. IGL_INLINE void igl::cgal::remesh_intersections(
  16. const Eigen::PlainObjectBase<DerivedV> & V,
  17. const Eigen::PlainObjectBase<DerivedF> & F,
  18. const std::vector<CGAL::Triangle_3<Kernel> > & T,
  19. const std::map<
  20. typename DerivedF::Index,
  21. std::pair<typename DerivedF::Index,
  22. std::vector<CGAL::Object> > > & offending,
  23. const std::map<
  24. std::pair<typename DerivedF::Index,typename DerivedF::Index>,
  25. std::vector<typename DerivedF::Index> > & edge2faces,
  26. Eigen::PlainObjectBase<DerivedVV> & VV,
  27. Eigen::PlainObjectBase<DerivedFF> & FF,
  28. Eigen::PlainObjectBase<DerivedJ> & J,
  29. Eigen::PlainObjectBase<DerivedIM> & IM)
  30. {
  31. using namespace std;
  32. using namespace Eigen;
  33. typedef typename DerivedF::Index Index;
  34. typedef CGAL::Point_3<Kernel> Point_3;
  35. typedef CGAL::Segment_3<Kernel> Segment_3;
  36. typedef CGAL::Triangle_3<Kernel> Triangle_3;
  37. typedef CGAL::Plane_3<Kernel> Plane_3;
  38. typedef CGAL::Point_2<Kernel> Point_2;
  39. typedef CGAL::Segment_2<Kernel> Segment_2;
  40. typedef CGAL::Triangle_2<Kernel> Triangle_2;
  41. typedef CGAL::Triangulation_vertex_base_2<Kernel> TVB_2;
  42. typedef CGAL::Constrained_triangulation_face_base_2<Kernel> CTFB_2;
  43. typedef CGAL::Triangulation_data_structure_2<TVB_2,CTFB_2> TDS_2;
  44. typedef CGAL::Exact_intersections_tag Itag;
  45. typedef CGAL::Constrained_Delaunay_triangulation_2<Kernel,TDS_2,Itag>
  46. CDT_2;
  47. typedef CGAL::Constrained_triangulation_plus_2<CDT_2> CDT_plus_2;
  48. typedef std::pair<Index,Index> EMK;
  49. typedef std::vector<Index> EMV;
  50. typedef std::map<EMK,EMV> EdgeMap;
  51. typedef std::pair<Index,Index> EMK;
  52. typedef std::vector<CGAL::Object> ObjectList;
  53. typedef std::vector<Index> IndexList;
  54. int NF_count = 0;
  55. // list of new faces, we'll fix F later
  56. vector<
  57. typename Eigen::Matrix<typename DerivedFF::Scalar,Dynamic,Dynamic>
  58. > NF(offending.size());
  59. // list of new vertices
  60. typedef vector<Point_3> Point_3List;
  61. Point_3List NV;
  62. Index NV_count = 0;
  63. vector<CDT_plus_2> cdt(offending.size());
  64. vector<Plane_3> P(offending.size());
  65. // Use map for *all* faces
  66. map<typename CDT_plus_2::Vertex_handle,Index> v2i;
  67. // Loop over offending triangles
  68. const size_t noff = offending.size();
  69. #ifdef IGL_SELFINTERSECTMESH_DEBUG
  70. double t_proj_del = 0;
  71. #endif
  72. // Unfortunately it looks like CGAL has trouble allocating memory when
  73. // multiple openmp threads are running. Crashes durring CDT...
  74. //# pragma omp parallel for if (noff>1000)
  75. for(const auto & okv : offending)
  76. {
  77. // index in F
  78. const Index f = okv.first;
  79. const Index o = okv.second.first;
  80. {
  81. #ifdef IGL_SELFINTERSECTMESH_DEBUG
  82. const double t_before = get_seconds();
  83. #endif
  84. CDT_plus_2 cdt_o;
  85. projected_delaunay(T[f],okv.second.second,cdt_o);
  86. cdt[o] = cdt_o;
  87. #ifdef IGL_SELFINTERSECTMESH_DEBUG
  88. t_proj_del += (get_seconds()-t_before);
  89. #endif
  90. }
  91. // Q: Is this also delaunay in 3D?
  92. // A: No, because the projection is affine and delaunay is not affine
  93. // invariant.
  94. // Q: Then, can't we first get the 2D delaunay triangulation, then lift it
  95. // to 3D and flip any offending edges?
  96. // Plane of projection (also used by projected_delaunay)
  97. P[o] = Plane_3(T[f].vertex(0),T[f].vertex(1),T[f].vertex(2));
  98. // Build index map
  99. {
  100. Index i=0;
  101. for(
  102. typename CDT_plus_2::Finite_vertices_iterator vit = cdt[o].finite_vertices_begin();
  103. vit != cdt[o].finite_vertices_end();
  104. ++vit)
  105. {
  106. if(i<3)
  107. {
  108. //cout<<T[f].vertex(i)<<
  109. // (T[f].vertex(i) == P[o].to_3d(vit->point())?" == ":" != ")<<
  110. // P[o].to_3d(vit->point())<<endl;
  111. #ifndef NDEBUG
  112. // I want to be sure that the original corners really show up as the
  113. // original corners of the CDT. I.e. I don't trust CGAL to maintain
  114. // the order
  115. assert(T[f].vertex(i) == P[o].to_3d(vit->point()));
  116. #endif
  117. // For first three, use original index in F
  118. //# pragma omp critical
  119. v2i[vit] = F(f,i);
  120. }else
  121. {
  122. const Point_3 vit_point_3 = P[o].to_3d(vit->point());
  123. // First look up each edge's neighbors to see if exact point has
  124. // already been added (This makes everything a bit quadratic)
  125. bool found = false;
  126. for(int e = 0; e<3 && !found;e++)
  127. {
  128. // Index of F's eth edge in V
  129. Index i = F(f,(e+1)%3);
  130. Index j = F(f,(e+2)%3);
  131. // Be sure that i<j
  132. if(i>j)
  133. {
  134. swap(i,j);
  135. }
  136. assert(edge2faces.count(EMK(i,j))==1);
  137. const EMV & facesij = edge2faces.find(EMK(i,j))->second;
  138. // loop over neighbors
  139. for(
  140. typename IndexList::const_iterator nit = facesij.begin();
  141. nit != facesij.end() && !found;
  142. nit++)
  143. {
  144. // don't consider self
  145. if(*nit == f)
  146. {
  147. continue;
  148. }
  149. // index of neighbor in offending (to find its cdt)
  150. assert(offending.count(*nit) == 1);
  151. Index no = offending.find(*nit)->second.first;
  152. // Loop over vertices of that neighbor's cdt (might not have been
  153. // processed yet, but then it's OK because it'll just be empty)
  154. for(
  155. typename CDT_plus_2::Finite_vertices_iterator uit = cdt[no].finite_vertices_begin();
  156. uit != cdt[no].finite_vertices_end() && !found;
  157. ++uit)
  158. {
  159. if(vit_point_3 == P[no].to_3d(uit->point()))
  160. {
  161. assert(v2i.count(uit) == 1);
  162. //# pragma omp critical
  163. v2i[vit] = v2i[uit];
  164. found = true;
  165. }
  166. }
  167. }
  168. }
  169. if(!found)
  170. {
  171. //# pragma omp critical
  172. {
  173. v2i[vit] = V.rows()+NV_count;
  174. NV.push_back(vit_point_3);
  175. NV_count++;
  176. }
  177. }
  178. }
  179. i++;
  180. }
  181. }
  182. {
  183. Index i = 0;
  184. // Resize to fit new number of triangles
  185. NF[o].resize(cdt[o].number_of_faces(),3);
  186. //# pragma omp atomic
  187. NF_count+=NF[o].rows();
  188. // Append new faces to NF
  189. for(
  190. typename CDT_plus_2::Finite_faces_iterator fit = cdt[o].finite_faces_begin();
  191. fit != cdt[o].finite_faces_end();
  192. ++fit)
  193. {
  194. NF[o](i,0) = v2i[fit->vertex(0)];
  195. NF[o](i,1) = v2i[fit->vertex(1)];
  196. NF[o](i,2) = v2i[fit->vertex(2)];
  197. i++;
  198. }
  199. }
  200. }
  201. #ifdef IGL_SELFINTERSECTMESH_DEBUG
  202. cout<<"CDT: "<<tictoc()<<" "<<t_proj_del<<endl;
  203. #endif
  204. assert(NV_count == (Index)NV.size());
  205. // Build output
  206. #ifndef NDEBUG
  207. //{
  208. // Index off_count = 0;
  209. // for(Index f = 0;f<F.rows();f++)
  210. // {
  211. // off_count+= (offensive[f]?1:0);
  212. // }
  213. // assert(off_count==(Index)offending.size());
  214. //}
  215. #endif
  216. // Append faces
  217. FF.resize(F.rows()-offending.size()+NF_count,3);
  218. J.resize(FF.rows());
  219. // First append non-offending original faces
  220. // There's an Eigen way to do this in one line but I forget
  221. Index off = 0;
  222. for(Index f = 0;f<F.rows();f++)
  223. {
  224. if(!offending.count(f))
  225. {
  226. FF.row(off) = F.row(f);
  227. J(off) = f;
  228. off++;
  229. }
  230. }
  231. assert(off == (Index)(F.rows()-offending.size()));
  232. // Now append replacement faces for offending faces
  233. for(const auto & okv : offending)
  234. {
  235. // index in F
  236. const Index f = okv.first;
  237. const Index o = okv.second.first;
  238. FF.block(off,0,NF[o].rows(),3) = NF[o];
  239. J.block(off,0,NF[o].rows(),1).setConstant(f);
  240. off += NF[o].rows();
  241. }
  242. // Append vertices
  243. VV.resize(V.rows()+NV_count,3);
  244. VV.block(0,0,V.rows(),3) = V.template cast<typename DerivedVV::Scalar>();
  245. {
  246. Index i = 0;
  247. for(
  248. typename Point_3List::const_iterator nvit = NV.begin();
  249. nvit != NV.end();
  250. nvit++)
  251. {
  252. for(Index d = 0;d<3;d++)
  253. {
  254. const Point_3 & p = *nvit;
  255. // Don't convert via double if output type is same as Kernel
  256. assign_scalar(p[d], VV(V.rows()+i,d));
  257. }
  258. i++;
  259. }
  260. }
  261. IM.resize(VV.rows(),1);
  262. map<Point_3,Index> vv2i;
  263. // Safe to check for duplicates using double for original vertices: if
  264. // incoming reps are different then the points are unique.
  265. for(Index v = 0;v<V.rows();v++)
  266. {
  267. const Point_3 p(V(v,0),V(v,1),V(v,2));
  268. if(vv2i.count(p)==0)
  269. {
  270. vv2i[p] = v;
  271. }
  272. assert(vv2i.count(p) == 1);
  273. IM(v) = vv2i[p];
  274. }
  275. // Must check for duplicates of new vertices using exact.
  276. {
  277. Index v = V.rows();
  278. for(
  279. typename Point_3List::const_iterator nvit = NV.begin();
  280. nvit != NV.end();
  281. nvit++)
  282. {
  283. const Point_3 & p = *nvit;
  284. if(vv2i.count(p)==0)
  285. {
  286. vv2i[p] = v;
  287. }
  288. assert(vv2i.count(p) == 1);
  289. IM(v) = vv2i[p];
  290. v++;
  291. }
  292. }
  293. #ifdef IGL_SELFINTERSECTMESH_DEBUG
  294. cout<<"Output + dupes: "<<tictoc()<<endl;
  295. #endif
  296. }