void simplifyMesh(TriangleMesh &src, TriangleMesh &dst){ namespace SMS = CGAL::Surface_mesh_simplification; Surface surface; PolyhedronBuilder<HalfedgeDS> builder(src.points, src.facets); surface.delegate(builder); // --- before mesh simplification, to maintain mesh quality high poisson surface reconstruction is applied --- // This is a stop predicate (defines when the algorithm terminates). // In this example, the simplification stops when the number of undirected edges // left in the surface drops below the specified number (1000) // SMS::Count_stop_predicate<Surface> stop(3000); //SMS::Count_ratio_stop_predicate<Surface> stop(0.1); SMS::Count_stop_predicate<Surface> stop(100); // This the actual call to the simplification algorithm. // The surface and stop conditions are mandatory arguments. // The index maps are needed because the vertices and edges // of this surface lack an "id()" field. int r = SMS::edge_collapse (surface ,stop ,CGAL::vertex_index_map(boost::get(CGAL::vertex_external_index, surface)) .edge_index_map(boost::get(CGAL::edge_external_index, surface)) .get_cost(CGAL::Surface_mesh_simplification::Edge_length_cost<Polyhedron>()) .get_placement(CGAL::Surface_mesh_simplification::Midpoint_placement<Polyhedron>()) //.get_cost(CGAL::Surface_mesh_simplification::LindstromTurk_cost<Polyhedron>()) //.get_placement(CGAL::Surface_mesh_simplification::LindstromTurk_placement<Polyhedron>()) ); std::cout << "\nFinished...\n" << r << " edges removed.\n" << (surface.size_of_halfedges()/2) << " final edges.\n" ; std::vector<Eigen::Vector3d> points; std::vector<std::vector<int> > faces; points.resize(surface.size_of_vertices()); faces.resize(surface.size_of_facets()); Polyhedron::Point_iterator pit; int index = 0; for(pit=surface.points_begin(); pit!=surface.points_end(); ++pit){ points[index][0] = pit->x(); points[index][1] = pit->y(); points[index][2] = pit->z(); index ++; } index = 0; Polyhedron::Face_iterator fit; for(fit=surface.facets_begin(); fit!=surface.facets_end(); ++fit){ std::vector<int > face(3); Halfedge_facet_circulator j = fit->facet_begin(); int f_index = 0; do { face[f_index] = std::distance(surface.vertices_begin(), j->vertex()); f_index++; } while ( ++j != fit->facet_begin()); faces[index] = face; index++; } dst.createFromFaceVertex(points, faces); }
void PoissonSurfaceReconstruction::reconstruct(std::vector<Eigen::Vector3d> &points, std::vector<Eigen::Vector3d> &normals, TriangleMesh &mesh){ assert(points.size() == normals.size()); std::cout << "creating points with normal..." << std::endl; std::vector<Point_with_normal> points_with_normal; points_with_normal.resize((int)points.size()); for(int i=0; i<(int)points.size(); i++){ Vector vec(normals[i][0], normals[i][1], normals[i][2]); //Point_with_normal pwn(points[i][0], points[i][1], points[i][2], vec); //points_with_normal[i] = pwn; points_with_normal[i] = Point_with_normal(points[i][0], points[i][1], points[i][2], vec); } std::cout << "constructing poisson reconstruction function..." << std::endl; Poisson_reconstruction_function function(points_with_normal.begin(), points_with_normal.end(), CGAL::make_normal_of_point_with_normal_pmap(PointList::value_type())); std::cout << "computing implicit function..." << std::endl; if( ! function.compute_implicit_function() ) { std::cout << "compute implicit function is failure" << std::endl; return; } //return EXIT_FAILURE; // Computes average spacing std::cout << "compute average spacing..." << std::endl; FT average_spacing = CGAL::compute_average_spacing(points_with_normal.begin(), points_with_normal.end(), 6 /* knn = 1 ring */); // Gets one point inside the implicit surface // and computes implicit function bounding sphere radius. Point inner_point = function.get_inner_point(); Sphere bsphere = function.bounding_sphere(); FT radius = std::sqrt(bsphere.squared_radius()); // Defines the implicit surface: requires defining a // conservative bounding sphere centered at inner point. FT sm_sphere_radius = 5.0 * radius; FT sm_dichotomy_error = distance_criteria*average_spacing/1000.0; // Dichotomy error must be << sm_distance //FT sm_dichotomy_error = distance_criteria*average_spacing/10.0; // Dichotomy error must be << sm_distance std::cout << "reconstructed surface" << std::endl; Surface_3 reconstructed_surface(function, Sphere(inner_point,sm_sphere_radius*sm_sphere_radius), sm_dichotomy_error/sm_sphere_radius); // Defines surface mesh generation criteria CGAL::Surface_mesh_default_criteria_3<STr> criteria(angle_criteria, // Min triangle angle (degrees) radius_criteria*average_spacing, // Max triangle size distance_criteria*average_spacing); // Approximation error std::cout << "generating surface mesh..." << std::endl; // Generates surface mesh with manifold option STr tr; // 3D Delaunay triangulation for surface mesh generation C2t3 c2t3(tr); // 2D complex in 3D Delaunay triangulation CGAL::make_surface_mesh(c2t3, // reconstructed mesh reconstructed_surface, // implicit surface criteria, // meshing criteria CGAL::Manifold_tag()); // require manifold mesh if(tr.number_of_vertices() == 0){ std::cout << "surface mesh generation is failed" << std::endl; return; } Polyhedron surface; CGAL::output_surface_facets_to_polyhedron(c2t3, surface); // convert CGAL::surface to TriangleMesh // std::cout << "converting CGA::surface to TriangleMesh..." << std::endl; std::vector<Eigen::Vector3d> pts; std::vector<std::vector<int> > faces; pts.resize(surface.size_of_vertices()); faces.resize(surface.size_of_facets()); Polyhedron::Point_iterator pit; int index = 0; for(pit=surface.points_begin(); pit!=surface.points_end(); ++pit){ pts[index][0] = pit->x(); pts[index][1] = pit->y(); pts[index][2] = pit->z(); index ++; } index = 0; Polyhedron::Face_iterator fit; for(fit=surface.facets_begin(); fit!=surface.facets_end(); ++fit){ std::vector<int > face(3); Halfedge_facet_circulator j = fit->facet_begin(); int f_index = 0; do { face[f_index] = std::distance(surface.vertices_begin(), j->vertex()); f_index++; } while ( ++j != fit->facet_begin()); faces[index] = face; index++; } mesh.createFromFaceVertex(pts, faces); }