remesh_intersections_beta.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. #include "remesh_intersections_beta.h"
  2. #include <vector>
  3. #include <map>
  4. #include <unordered_map>
  5. #include <iostream>
  6. template <
  7. typename DerivedV,
  8. typename DerivedF,
  9. typename Kernel,
  10. typename DerivedVV,
  11. typename DerivedFF,
  12. typename DerivedJ,
  13. typename DerivedIM>
  14. IGL_INLINE void igl::cgal::remesh_intersections_beta(
  15. const Eigen::PlainObjectBase<DerivedV> & V,
  16. const Eigen::PlainObjectBase<DerivedF> & F,
  17. const std::vector<CGAL::Triangle_3<Kernel> > & T,
  18. const std::map<
  19. typename DerivedF::Index,
  20. std::pair<typename DerivedF::Index,
  21. std::vector<CGAL::Object> > > & offending,
  22. const std::map<
  23. std::pair<typename DerivedF::Index,typename DerivedF::Index>,
  24. std::vector<typename DerivedF::Index> > & edge2faces,
  25. Eigen::PlainObjectBase<DerivedVV> & VV,
  26. Eigen::PlainObjectBase<DerivedFF> & FF,
  27. Eigen::PlainObjectBase<DerivedJ> & J,
  28. Eigen::PlainObjectBase<DerivedIM> & IM) {
  29. typedef CGAL::Point_3<Kernel> Point_3;
  30. typedef CGAL::Segment_3<Kernel> Segment_3;
  31. typedef CGAL::Triangle_3<Kernel> Triangle_3;
  32. typedef CGAL::Plane_3<Kernel> Plane_3;
  33. typedef CGAL::Point_2<Kernel> Point_2;
  34. typedef CGAL::Segment_2<Kernel> Segment_2;
  35. typedef CGAL::Triangle_2<Kernel> Triangle_2;
  36. typedef CGAL::Triangulation_vertex_base_2<Kernel> TVB_2;
  37. typedef CGAL::Constrained_triangulation_face_base_2<Kernel> CTFB_2;
  38. typedef CGAL::Triangulation_data_structure_2<TVB_2,CTFB_2> TDS_2;
  39. typedef CGAL::Exact_intersections_tag Itag;
  40. typedef CGAL::Constrained_Delaunay_triangulation_2<Kernel,TDS_2,Itag>
  41. CDT_2;
  42. typedef CGAL::Constrained_triangulation_plus_2<CDT_2> CDT_plus_2;
  43. typedef typename DerivedF::Index Index;
  44. typedef std::pair<Index, Index> Edge;
  45. struct EdgeHash {
  46. size_t operator()(const Edge& e) const {
  47. return (e.first * 805306457) ^ (e.second * 201326611);
  48. }
  49. };
  50. typedef std::unordered_map<Edge, std::vector<Index>, EdgeHash > EdgeMap;
  51. auto normalize_plane_coeff = [](const Plane_3& P) {
  52. std::vector<typename Kernel::FT> coeffs = {
  53. P.a(), P.b(), P.c(), P.d()
  54. };
  55. const auto max_itr = std::max_element(coeffs.begin(), coeffs.end());
  56. const auto min_itr = std::min_element(coeffs.begin(), coeffs.end());
  57. typename Kernel::FT max_coeff;
  58. if (*max_itr < -1 * *min_itr) {
  59. max_coeff = *min_itr;
  60. } else {
  61. max_coeff = *max_itr;
  62. }
  63. std::transform(coeffs.begin(), coeffs.end(), coeffs.begin(),
  64. [&](const typename Kernel::FT& val)
  65. {return val / max_coeff; } );
  66. return coeffs;
  67. };
  68. auto plane_comp = [&](const Plane_3& p1, const Plane_3& p2) {
  69. const auto p1_coeffs = normalize_plane_coeff(p1);
  70. const auto p2_coeffs = normalize_plane_coeff(p2);
  71. if (p1_coeffs[0] != p2_coeffs[0])
  72. return p1_coeffs[0] < p2_coeffs[0];
  73. if (p1_coeffs[1] != p2_coeffs[1])
  74. return p1_coeffs[1] < p2_coeffs[1];
  75. if (p1_coeffs[2] != p2_coeffs[2])
  76. return p1_coeffs[2] < p2_coeffs[2];
  77. if (p1_coeffs[3] != p2_coeffs[3])
  78. return p1_coeffs[3] < p2_coeffs[3];
  79. return false;
  80. };
  81. std::map<Plane_3, std::vector<Index>, decltype(plane_comp)>
  82. unique_planes(plane_comp);
  83. const size_t num_faces = F.rows();
  84. const size_t num_base_vertices = V.rows();
  85. assert(num_faces == T.size());
  86. std::vector<bool> is_offending(num_faces, false);
  87. for (const auto itr : offending) {
  88. const auto& fid = itr.first;
  89. is_offending[fid] = true;
  90. Plane_3 key = T[fid].supporting_plane();
  91. assert(!key.is_degenerate());
  92. const auto jtr = unique_planes.find(key);
  93. if (jtr == unique_planes.end()) {
  94. unique_planes.insert({key, {fid}});
  95. } else {
  96. jtr->second.push_back(fid);
  97. }
  98. }
  99. const size_t INVALID = std::numeric_limits<size_t>::max();
  100. std::vector<std::vector<Index> > resolved_faces;
  101. std::vector<Index> source_faces;
  102. std::vector<Point_3> new_vertices;
  103. EdgeMap edge_vertices;
  104. /**
  105. * Run constraint Delaunay triangulation on the plane.
  106. */
  107. auto run_delaunay_triangulation = [&](const Plane_3& P,
  108. const std::vector<Index>& involved_faces,
  109. std::vector<Point_3>& vertices,
  110. std::vector<std::vector<Index> >& faces) {
  111. CDT_plus_2 cdt;
  112. for (const auto& fid : involved_faces) {
  113. const auto itr = offending.find(fid);
  114. const auto& triangle = T[fid];
  115. cdt.insert_constraint(P.to_2d(triangle[0]), P.to_2d(triangle[1]));
  116. cdt.insert_constraint(P.to_2d(triangle[1]), P.to_2d(triangle[2]));
  117. cdt.insert_constraint(P.to_2d(triangle[2]), P.to_2d(triangle[0]));
  118. if (itr == offending.end()) continue;
  119. for (const auto& obj : itr->second.second) {
  120. if(const Segment_3 *iseg = CGAL::object_cast<Segment_3 >(&obj)) {
  121. // Add segment constraint
  122. cdt.insert_constraint(
  123. P.to_2d(iseg->vertex(0)),P.to_2d(iseg->vertex(1)));
  124. }else if(const Point_3 *ipoint = CGAL::object_cast<Point_3 >(&obj)) {
  125. // Add point
  126. cdt.insert(P.to_2d(*ipoint));
  127. } else if(const Triangle_3 *itri = CGAL::object_cast<Triangle_3 >(&obj)) {
  128. // Add 3 segment constraints
  129. cdt.insert_constraint(
  130. P.to_2d(itri->vertex(0)),P.to_2d(itri->vertex(1)));
  131. cdt.insert_constraint(
  132. P.to_2d(itri->vertex(1)),P.to_2d(itri->vertex(2)));
  133. cdt.insert_constraint(
  134. P.to_2d(itri->vertex(2)),P.to_2d(itri->vertex(0)));
  135. } else if(const std::vector<Point_3 > *polyp =
  136. CGAL::object_cast< std::vector<Point_3 > >(&obj)) {
  137. //cerr<<REDRUM("Poly...")<<endl;
  138. const std::vector<Point_3 > & poly = *polyp;
  139. const Index m = poly.size();
  140. assert(m>=2);
  141. for(Index p = 0;p<m;p++)
  142. {
  143. const Index np = (p+1)%m;
  144. cdt.insert_constraint(P.to_2d(poly[p]),P.to_2d(poly[np]));
  145. }
  146. }else {
  147. throw std::runtime_error("Unknown intersection object!");
  148. }
  149. }
  150. }
  151. const size_t num_vertices = cdt.number_of_vertices();
  152. const size_t num_faces = cdt.number_of_faces();
  153. std::map<typename CDT_plus_2::Vertex_handle,Index> v2i;
  154. size_t count=0;
  155. for (auto itr = cdt.finite_vertices_begin();
  156. itr != cdt.finite_vertices_end(); itr++) {
  157. vertices.push_back(P.to_3d(itr->point()));
  158. v2i[itr] = count;
  159. count++;
  160. }
  161. for (auto itr = cdt.finite_faces_begin();
  162. itr != cdt.finite_faces_end(); itr++) {
  163. faces.push_back( {
  164. v2i[itr->vertex(0)],
  165. v2i[itr->vertex(1)],
  166. v2i[itr->vertex(2)] });
  167. }
  168. };
  169. /**
  170. * Given p on triangle indexed by ori_f, determine the index of p.
  171. */
  172. auto determine_point_index = [&](
  173. const Point_3& p, const size_t ori_f) -> Index {
  174. const auto& triangle = T[ori_f];
  175. const auto& f = F.row(ori_f).eval();
  176. // Check if p is one of the triangle corners.
  177. for (size_t i=0; i<3; i++) {
  178. if (p == triangle[i]) return f[i];
  179. }
  180. // Check if p is on one of the edges.
  181. for (size_t i=0; i<3; i++) {
  182. const Point_3 curr_corner = triangle[i];
  183. const Point_3 next_corner = triangle[(i+1)%3];
  184. const Segment_3 edge(curr_corner, next_corner);
  185. if (edge.has_on(p)) {
  186. const Index curr = f[i];
  187. const Index next = f[(i+1)%3];
  188. Edge key;
  189. key.first = curr<next?curr:next;
  190. key.second = curr<next?next:curr;
  191. auto itr = edge_vertices.find(key);
  192. if (itr == edge_vertices.end()) {
  193. const Index index =
  194. num_base_vertices + new_vertices.size();
  195. edge_vertices.insert({key, {index}});
  196. new_vertices.push_back(p);
  197. return index;
  198. } else {
  199. for (const auto vid : itr->second) {
  200. if (p == new_vertices[vid - num_base_vertices]) {
  201. return vid;
  202. }
  203. }
  204. const size_t index = num_base_vertices + new_vertices.size();
  205. new_vertices.push_back(p);
  206. itr->second.push_back(index);
  207. return index;
  208. }
  209. }
  210. }
  211. // p must be in the middle of the triangle.
  212. const size_t index = num_base_vertices + new_vertices.size();
  213. new_vertices.push_back(p);
  214. return index;
  215. };
  216. /**
  217. * Determine the vertex indices for each corner of each output triangle.
  218. */
  219. auto post_triangulation_process = [&](
  220. const std::vector<Point_3>& vertices,
  221. const std::vector<std::vector<Index> >& faces,
  222. const std::vector<Index>& involved_faces) {
  223. for (const auto& f : faces) {
  224. const Point_3& v0 = vertices[f[0]];
  225. const Point_3& v1 = vertices[f[1]];
  226. const Point_3& v2 = vertices[f[2]];
  227. Point_3 center(
  228. (v0[0] + v1[0] + v2[0]) / 3.0,
  229. (v0[1] + v1[1] + v2[1]) / 3.0,
  230. (v0[2] + v1[2] + v2[2]) / 3.0);
  231. for (const auto& ori_f : involved_faces) {
  232. const auto& triangle = T[ori_f];
  233. const Plane_3 P = triangle.supporting_plane();
  234. if (triangle.has_on(center)) {
  235. std::vector<Index> corners(3);
  236. corners[0] = determine_point_index(v0, ori_f);
  237. corners[1] = determine_point_index(v1, ori_f);
  238. corners[2] = determine_point_index(v2, ori_f);
  239. if (CGAL::orientation(
  240. P.to_2d(v0), P.to_2d(v1), P.to_2d(v2))
  241. == CGAL::RIGHT_TURN) {
  242. std::swap(corners[0], corners[1]);
  243. }
  244. resolved_faces.emplace_back(corners);
  245. source_faces.push_back(ori_f);
  246. }
  247. }
  248. }
  249. };
  250. // Process un-touched faces.
  251. for (size_t i=0; i<num_faces; i++) {
  252. if (!is_offending[i]) {
  253. resolved_faces.push_back(
  254. { F(i,0), F(i,1), F(i,2) } );
  255. source_faces.push_back(i);
  256. }
  257. }
  258. // Process self-intersecting faces.
  259. for (const auto itr : unique_planes) {
  260. Plane_3 P = itr.first;
  261. const auto& involved_faces = itr.second;
  262. std::vector<Point_3> vertices;
  263. std::vector<std::vector<Index> > faces;
  264. run_delaunay_triangulation(P, involved_faces, vertices, faces);
  265. post_triangulation_process(vertices, faces, involved_faces);
  266. }
  267. // Output resolved mesh.
  268. const size_t num_out_vertices = new_vertices.size() + num_base_vertices;
  269. VV.resize(num_out_vertices, 3);
  270. for (size_t i=0; i<num_base_vertices; i++) {
  271. assign_scalar(V(i,0), VV(i,0));
  272. assign_scalar(V(i,1), VV(i,1));
  273. assign_scalar(V(i,2), VV(i,2));
  274. }
  275. for (size_t i=num_base_vertices; i<num_out_vertices; i++) {
  276. assign_scalar(new_vertices[i-num_base_vertices][0], VV(i,0));
  277. assign_scalar(new_vertices[i-num_base_vertices][1], VV(i,1));
  278. assign_scalar(new_vertices[i-num_base_vertices][2], VV(i,2));
  279. }
  280. const size_t num_out_faces = resolved_faces.size();
  281. FF.resize(num_out_faces, 3);
  282. for (size_t i=0; i<num_out_faces; i++) {
  283. FF(i,0) = resolved_faces[i][0];
  284. FF(i,1) = resolved_faces[i][1];
  285. FF(i,2) = resolved_faces[i][2];
  286. }
  287. J.resize(num_out_faces);
  288. std::copy(source_faces.begin(), source_faces.end(), J.data());
  289. // Extract unique vertex indices.
  290. IM.resize(VV.rows(),1);
  291. std::map<Point_3,Index> vv2i;
  292. // Safe to check for duplicates using double for original vertices: if
  293. // incoming reps are different then the points are unique.
  294. for(Index v = 0;v<VV.rows();v++) {
  295. typename Kernel::FT p0,p1,p2;
  296. assign_scalar(VV(v,0),p0);
  297. assign_scalar(VV(v,1),p1);
  298. assign_scalar(VV(v,2),p2);
  299. const Point_3 p(p0,p1,p2);
  300. if(vv2i.count(p)==0) {
  301. vv2i[p] = v;
  302. }
  303. assert(vv2i.count(p) == 1);
  304. IM(v) = vv2i[p];
  305. }
  306. }