complex_to_mesh.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2014 Alec Jacobson <[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 "complex_to_mesh.h"
  9. #include "../../centroid.h"
  10. #include "../../remove_unreferenced.h"
  11. #include <CGAL/Surface_mesh_default_triangulation_3.h>
  12. #include <CGAL/Delaunay_triangulation_cell_base_with_circumcenter_3.h>
  13. #include <set>
  14. #include <stack>
  15. template <typename Tr, typename DerivedV, typename DerivedF>
  16. IGL_INLINE bool igl::copyleft::cgal::complex_to_mesh(
  17. const CGAL::Complex_2_in_triangulation_3<Tr> & c2t3,
  18. Eigen::PlainObjectBase<DerivedV> & V,
  19. Eigen::PlainObjectBase<DerivedF> & F)
  20. {
  21. // CGAL/IO/Complex_2_in_triangulation_3_file_writer.h
  22. using CGAL::Surface_mesher::number_of_facets_on_surface;
  23. typedef typename CGAL::Complex_2_in_triangulation_3<Tr> C2t3;
  24. typedef typename Tr::Finite_facets_iterator Finite_facets_iterator;
  25. typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator;
  26. typedef typename Tr::Facet Facet;
  27. typedef typename Tr::Edge Edge;
  28. typedef typename Tr::Vertex_handle Vertex_handle;
  29. // Header.
  30. const Tr& tr = c2t3.triangulation();
  31. bool success = true;
  32. const int n = tr.number_of_vertices();
  33. const int m = c2t3.number_of_facets();
  34. assert(m == number_of_facets_on_surface(tr));
  35. // Finite vertices coordinates.
  36. std::map<Vertex_handle, int> v2i;
  37. V.resize(n,3);
  38. {
  39. int v = 0;
  40. for(Finite_vertices_iterator vit = tr.finite_vertices_begin();
  41. vit != tr.finite_vertices_end();
  42. ++vit)
  43. {
  44. V(v,0) = vit->point().x();
  45. V(v,1) = vit->point().y();
  46. V(v,2) = vit->point().z();
  47. v2i[vit] = v++;
  48. }
  49. }
  50. {
  51. Finite_facets_iterator fit = tr.finite_facets_begin();
  52. std::set<Facet> oriented_set;
  53. std::stack<Facet> stack;
  54. while ((int)oriented_set.size() != m)
  55. {
  56. while ( fit->first->is_facet_on_surface(fit->second) == false ||
  57. oriented_set.find(*fit) != oriented_set.end() ||
  58. oriented_set.find(c2t3.opposite_facet(*fit)) !=
  59. oriented_set.end() )
  60. {
  61. ++fit;
  62. }
  63. oriented_set.insert(*fit);
  64. stack.push(*fit);
  65. while(! stack.empty() )
  66. {
  67. Facet f = stack.top();
  68. stack.pop();
  69. for(int ih = 0 ; ih < 3 ; ++ih)
  70. {
  71. const int i1 = tr.vertex_triple_index(f.second, tr. cw(ih));
  72. const int i2 = tr.vertex_triple_index(f.second, tr.ccw(ih));
  73. const typename C2t3::Face_status face_status
  74. = c2t3.face_status(Edge(f.first, i1, i2));
  75. if(face_status == C2t3::REGULAR)
  76. {
  77. Facet fn = c2t3.neighbor(f, ih);
  78. if (oriented_set.find(fn) == oriented_set.end())
  79. {
  80. if(oriented_set.find(c2t3.opposite_facet(fn)) == oriented_set.end())
  81. {
  82. oriented_set.insert(fn);
  83. stack.push(fn);
  84. }else {
  85. success = false; // non-orientable
  86. }
  87. }
  88. }else if(face_status != C2t3::BOUNDARY)
  89. {
  90. success = false; // non manifold, thus non-orientable
  91. }
  92. } // end "for each neighbor of f"
  93. } // end "stack non empty"
  94. } // end "oriented_set not full"
  95. F.resize(m,3);
  96. int f = 0;
  97. for(typename std::set<Facet>::const_iterator fit =
  98. oriented_set.begin();
  99. fit != oriented_set.end();
  100. ++fit)
  101. {
  102. const typename Tr::Cell_handle cell = fit->first;
  103. const int& index = fit->second;
  104. const int index1 = v2i[cell->vertex(tr.vertex_triple_index(index, 0))];
  105. const int index2 = v2i[cell->vertex(tr.vertex_triple_index(index, 1))];
  106. const int index3 = v2i[cell->vertex(tr.vertex_triple_index(index, 2))];
  107. // This order is flipped
  108. F(f,0) = index1;
  109. F(f,1) = index2;
  110. F(f,2) = index3;
  111. f++;
  112. }
  113. assert(f == m);
  114. } // end if(facets must be oriented)
  115. // This CGAL code seems to randomly assign the global orientation
  116. // Flip based on the signed volume.
  117. Eigen::Vector3d cen;
  118. double vol;
  119. igl::centroid(V,F,cen,vol);
  120. if(vol < 0)
  121. {
  122. // Flip
  123. F = F.rowwise().reverse().eval();
  124. }
  125. // CGAL code somehow can end up with unreferenced vertices
  126. {
  127. Eigen::VectorXi _1;
  128. remove_unreferenced( Eigen::MatrixXd(V), Eigen::MatrixXi(F), V,F,_1);
  129. }
  130. return success;
  131. }
  132. #ifdef IGL_STATIC_LIBRARY
  133. // Explicit template instantiation
  134. template bool igl::copyleft::cgal::complex_to_mesh<CGAL::Delaunay_triangulation_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, CGAL::Triangulation_data_structure_3<CGAL::Surface_mesh_vertex_base_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, CGAL::Triangulation_vertex_base_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, CGAL::Triangulation_ds_vertex_base_3<void> > >, CGAL::Delaunay_triangulation_cell_base_with_circumcenter_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, CGAL::Surface_mesh_cell_base_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, CGAL::Triangulation_cell_base_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, CGAL::Triangulation_ds_cell_base_3<void> > > >, CGAL::Sequential_tag>, CGAL::Default, CGAL::Default>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(CGAL::Complex_2_in_triangulation_3<CGAL::Delaunay_triangulation_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, CGAL::Triangulation_data_structure_3<CGAL::Surface_mesh_vertex_base_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, CGAL::Triangulation_vertex_base_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, CGAL::Triangulation_ds_vertex_base_3<void> > >, CGAL::Delaunay_triangulation_cell_base_with_circumcenter_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, CGAL::Surface_mesh_cell_base_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, CGAL::Triangulation_cell_base_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, CGAL::Triangulation_ds_cell_base_3<void> > > >, CGAL::Sequential_tag>, CGAL::Default, CGAL::Default>, void> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
  135. #endif