// This file is part of libigl, a simple c++ geometry processing library. // // Copyright (C) 2014 Alec Jacobson // // This Source Code Form is subject to the terms of the Mozilla Public License // v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #include "complex_to_mesh.h" #include "../../centroid.h" #include "../../remove_unreferenced.h" #include #include #include #include template IGL_INLINE bool igl::copyleft::cgal::complex_to_mesh( const CGAL::Complex_2_in_triangulation_3 & c2t3, Eigen::PlainObjectBase & V, Eigen::PlainObjectBase & F) { using namespace Eigen; // CGAL/IO/Complex_2_in_triangulation_3_file_writer.h using CGAL::Surface_mesher::number_of_facets_on_surface; typedef typename CGAL::Complex_2_in_triangulation_3 C2t3; typedef typename Tr::Finite_facets_iterator Finite_facets_iterator; typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; typedef typename Tr::Facet Facet; typedef typename Tr::Edge Edge; typedef typename Tr::Vertex_handle Vertex_handle; // Header. const Tr& tr = c2t3.triangulation(); bool success = true; const int n = tr.number_of_vertices(); const int m = c2t3.number_of_facets(); assert(m == number_of_facets_on_surface(tr)); // Finite vertices coordinates. std::map v2i; V.resize(n,3); { int v = 0; for(Finite_vertices_iterator vit = tr.finite_vertices_begin(); vit != tr.finite_vertices_end(); ++vit) { V(v,0) = vit->point().x(); V(v,1) = vit->point().y(); V(v,2) = vit->point().z(); v2i[vit] = v++; } } { Finite_facets_iterator fit = tr.finite_facets_begin(); std::set oriented_set; std::stack stack; while ((int)oriented_set.size() != m) { while ( fit->first->is_facet_on_surface(fit->second) == false || oriented_set.find(*fit) != oriented_set.end() || oriented_set.find(c2t3.opposite_facet(*fit)) != oriented_set.end() ) { ++fit; } oriented_set.insert(*fit); stack.push(*fit); while(! stack.empty() ) { Facet f = stack.top(); stack.pop(); for(int ih = 0 ; ih < 3 ; ++ih) { const int i1 = tr.vertex_triple_index(f.second, tr. cw(ih)); const int i2 = tr.vertex_triple_index(f.second, tr.ccw(ih)); const typename C2t3::Face_status face_status = c2t3.face_status(Edge(f.first, i1, i2)); if(face_status == C2t3::REGULAR) { Facet fn = c2t3.neighbor(f, ih); if (oriented_set.find(fn) == oriented_set.end()) { if(oriented_set.find(c2t3.opposite_facet(fn)) == oriented_set.end()) { oriented_set.insert(fn); stack.push(fn); }else { success = false; // non-orientable } } }else if(face_status != C2t3::BOUNDARY) { success = false; // non manifold, thus non-orientable } } // end "for each neighbor of f" } // end "stack non empty" } // end "oriented_set not full" F.resize(m,3); int f = 0; for(typename std::set::const_iterator fit = oriented_set.begin(); fit != oriented_set.end(); ++fit) { const typename Tr::Cell_handle cell = fit->first; const int& index = fit->second; const int index1 = v2i[cell->vertex(tr.vertex_triple_index(index, 0))]; const int index2 = v2i[cell->vertex(tr.vertex_triple_index(index, 1))]; const int index3 = v2i[cell->vertex(tr.vertex_triple_index(index, 2))]; // This order is flipped F(f,0) = index1; F(f,1) = index2; F(f,2) = index3; f++; } assert(f == m); } // end if(facets must be oriented) // This CGAL code seems to randomly assign the global orientation // Flip based on the signed volume. Eigen::Vector3d cen; double vol; igl::centroid(V,F,cen,vol); if(vol < 0) { // Flip F = F.rowwise().reverse().eval(); } // CGAL code somehow can end up with unreferenced vertices { VectorXi _1; remove_unreferenced( MatrixXd(V), MatrixXi(F), V,F,_1); } return success; } #ifdef IGL_STATIC_LIBRARY template bool igl::copyleft::cgal::complex_to_mesh, CGAL::Triangulation_data_structure_3, CGAL::Triangulation_vertex_base_3, CGAL::Triangulation_ds_vertex_base_3 > >, CGAL::Delaunay_triangulation_cell_base_with_circumcenter_3, CGAL::Surface_mesh_cell_base_3, CGAL::Triangulation_cell_base_3, CGAL::Triangulation_ds_cell_base_3 > > >, CGAL::Sequential_tag>, CGAL::Default, CGAL::Default>, Eigen::Matrix, Eigen::Matrix >(CGAL::Complex_2_in_triangulation_3, CGAL::Triangulation_data_structure_3, CGAL::Triangulation_vertex_base_3, CGAL::Triangulation_ds_vertex_base_3 > >, CGAL::Delaunay_triangulation_cell_base_with_circumcenter_3, CGAL::Surface_mesh_cell_base_3, CGAL::Triangulation_cell_base_3, CGAL::Triangulation_ds_cell_base_3 > > >, CGAL::Sequential_tag>, CGAL::Default, CGAL::Default>, void> const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); #endif