diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/decimation_planar_patches.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/decimation_planar_patches.cpp index 479cab49de8..0356ced84ea 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/decimation_planar_patches.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/decimation_planar_patches.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -17,8 +18,7 @@ namespace PMP = CGAL::Polygon_mesh_processing; int main() { Surface_mesh sm; - std::ifstream in("data/cube_quad.off"); - in >> sm; + CGAL::IO::read_polygon_mesh(CGAL::data_file_path("meshes/cube_quad.off"), sm); // triangulate faces; PMP::triangulate_faces(sm); @@ -36,11 +36,12 @@ int main() assert(faces(sm).size()>100); // decimate the mesh - PMP::remesh_planar_patches(sm); - std::ofstream("cube_decimated.off") << sm; + Surface_mesh out; + PMP::remesh_planar_patches(sm, out); + std::ofstream("cube_decimated.off") << out; // we should be back to 12 faces - assert(faces(sm).size()==12); + assert(faces(out).size()==12); return 0; } diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remesh_planar_patches.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remesh_planar_patches.h index c5bdb06fdf9..eb5809d4454 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remesh_planar_patches.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remesh_planar_patches.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018 GeometryFactory (France). +// Copyright (c) 2018-2023 GeometryFactory (France). // All rights reserved. // // This file is part of CGAL (www.cgal.org). @@ -8,7 +8,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Sebastien Loriot +// Author(s) : Sébastien Loriot #ifndef CGAL_POLYGON_MESH_PROCESSING_REMESH_PLANAR_PATCHES_H #define CGAL_POLYGON_MESH_PROCESSING_REMESH_PLANAR_PATCHES_H @@ -27,19 +27,98 @@ #include #include #include +#include #include -/// @todo remove Kernel_traits -/// @todo function to move in PMP: retriangulate_planar_patches(in, out, vci, ecm, fccid, np) (pca is a np option) - - namespace CGAL{ namespace Polygon_mesh_processing { namespace Planar_segmentation{ +template +struct Triangle_index_tracker_base +{ + typedef boost::graph_traits GT; + + Triangle_index_tracker_base(VertexCornerMapOut vertex_corner_map) + : vertex_corner_map(vertex_corner_map) + {} + + decltype(auto) + v2v_oi() + { + auto l = [this](const std::pair& p) + { + put(vertex_corner_map, p.second, p.first); + }; + return boost::make_function_output_iterator(l); + } + + VertexCornerMapOut vertex_corner_map; +}; + +template +struct Triangle_index_tracker_base +{ + typedef boost::graph_traits GT; + + Triangle_index_tracker_base(internal_np::Param_not_found) {} + Emptyset_iterator v2v_oi() { return Emptyset_iterator(); } +}; + +template +struct Triangle_index_tracker + : public Triangle_index_tracker_base +{ + typedef boost::graph_traits GT; + + Triangle_index_tracker(VertexCornerMapOut vertex_corner_map, FacePatchMapOut face_patch_map) + : Triangle_index_tracker_base(vertex_corner_map) + , face_patch_map(face_patch_map) + {} + + std::vector triangle_ids; + void new_triangle_added_to_patch(std::size_t i) + { + triangle_ids.push_back(i); + } + + void new_triangles_added_to_patch(std::size_t nb_triangles, std::size_t i) + { + triangle_ids.resize(triangle_ids.size()+nb_triangles, i); + } + + decltype(auto) + f2f_oi() + { + auto l = [this](const std::pair& p) + { + put(face_patch_map, p.second, triangle_ids[p.first]); + }; + return boost::make_function_output_iterator(l); + } + + FacePatchMapOut face_patch_map; +}; + + +template +struct Triangle_index_tracker + : public Triangle_index_tracker_base +{ + Triangle_index_tracker(VertexCornerMapOut vertex_corner_map,internal_np::Param_not_found) + : Triangle_index_tracker_base(vertex_corner_map) + {} + + void new_triangle_added_to_patch(std::size_t /*in_patch_id*/) {} + void new_triangles_added_to_patch(std::size_t /*nb_triangles*/, std::size_t /*in_patch_id*/) {} + + Emptyset_iterator f2f_oi() { return Emptyset_iterator(); } +}; + + inline std::size_t init_id() { return std::size_t(-1); @@ -85,7 +164,8 @@ struct FaceInfo2 bool in_domain() const { return m_in_domain==1; } }; -template bool is_edge_between_coplanar_faces(edge_descriptor e, @@ -93,8 +173,7 @@ bool is_edge_between_coplanar_faces(edge_descriptor e, double coplanar_cos_threshold, const VertexPointMap& vpm) { - typedef typename boost::property_traits::value_type Point_3; - typedef typename Kernel_traits::type K; + typedef typename Kernel::Point_3 Point_3; typedef typename boost::property_traits::reference Point_ref_3; if (is_border(e, tm)) return false; typename boost::graph_traits::halfedge_descriptor @@ -108,12 +187,13 @@ bool is_edge_between_coplanar_faces(edge_descriptor e, return coplanar(p, q, r, s); else { - typename K::Compare_dihedral_angle_3 pred; - return pred(p, q, r, s, typename K::FT(coplanar_cos_threshold)) == CGAL::LARGER; + typename Kernel::Compare_dihedral_angle_3 pred; + return pred(p, q, r, s, typename Kernel::FT(coplanar_cos_threshold)) == CGAL::LARGER; } } -template @@ -123,8 +203,7 @@ bool is_target_vertex_a_corner(halfedge_descriptor h, double coplanar_cos_threshold, const VertexPointMap& vpm) { - typedef typename boost::property_traits::value_type Point_3; - typedef typename Kernel_traits::type K; + typedef typename Kernel::Point_3 Point_3; typedef typename boost::graph_traits graph_traits; halfedge_descriptor h2 = graph_traits::null_halfedge(); @@ -150,12 +229,13 @@ bool is_target_vertex_a_corner(halfedge_descriptor h, return !collinear(p, q, r); else { - typename K::Compare_angle_3 pred; - return pred(p, q, r, typename K::FT(coplanar_cos_threshold))==CGAL::SMALLER; + typename Kernel::Compare_angle_3 pred; + return pred(p, q, r, typename Kernel::FT(coplanar_cos_threshold))==CGAL::SMALLER; } } -template void @@ -168,12 +248,13 @@ mark_constrained_edges( for(typename boost::graph_traits::edge_descriptor e : edges(tm)) { if (!get(edge_is_constrained,e)) - if (!is_edge_between_coplanar_faces(e, tm, coplanar_cos_threshold, vpm)) + if (!is_edge_between_coplanar_faces(e, tm, coplanar_cos_threshold, vpm)) put(edge_is_constrained, e, true); } } -template @@ -194,14 +275,14 @@ mark_corner_vertices( if (is_init_id(get(vertex_corner_id, target(h, tm)))) { - if (is_target_vertex_a_corner(h, edge_is_constrained, tm, coplanar_cos_threshold, vpm)) + if (is_target_vertex_a_corner(h, edge_is_constrained, tm, coplanar_cos_threshold, vpm)) put(vertex_corner_id, target(h, tm), corner_id++); else put(vertex_corner_id, target(h, tm), default_id()); } if (is_init_id(get(vertex_corner_id, source(h, tm)))) { - if (is_target_vertex_a_corner(opposite(h, tm), edge_is_constrained, tm, coplanar_cos_threshold, vpm)) + if (is_target_vertex_a_corner(opposite(h, tm), edge_is_constrained, tm, coplanar_cos_threshold, vpm)) put(vertex_corner_id, source(h, tm), corner_id++); else put(vertex_corner_id, source(h, tm), default_id()); @@ -301,7 +382,7 @@ template bool add_triangle_faces(const std::vector< std::pair >& csts, typename Kernel::Vector_3 normal, const std::vector& corners, - std::vector >& triangles) + std::vector >& triangles) { typedef Projection_traits_3 P_traits; typedef Triangulation_vertex_base_with_id_2 Vb; @@ -400,7 +481,8 @@ bool add_triangle_faces(const std::vector< std::pair > return true; } -template graph_traits; // mark constrained edges - mark_constrained_edges(tm, edge_is_constrained, coplanar_cos_threshold, vpm); + mark_constrained_edges(tm, edge_is_constrained, coplanar_cos_threshold, vpm); // mark connected components (cc) delimited by constrained edges std::size_t nb_cc = Polygon_mesh_processing::connected_components( @@ -435,40 +517,39 @@ tag_corners_and_constrained_edges(TriangleMesh& tm, } std::size_t nb_corners = - mark_corner_vertices(tm, edge_is_constrained, vertex_corner_id, coplanar_cos_threshold, vpm); + mark_corner_vertices(tm, edge_is_constrained, vertex_corner_id, coplanar_cos_threshold, vpm); return std::make_pair(nb_corners, nb_cc); } -template + typename IndexTracking> bool decimate_impl(const TriangleMesh& tm, std::pair& nb_corners_and_nb_cc, VertexCornerIdMap& vertex_corner_id, EdgeIsConstrainedMap& edge_is_constrained, FaceCCIdMap& face_cc_ids, const VertexPointMap& vpm, - std::vector< Point_3 >& corners, - std::vector< cpp11::array >& out_triangles) + std::vector< typename Kernel::Point_3 >& corners, + std::vector< std::array >& out_triangles, + IndexTracking& t_id_tracker) { - typedef typename Kernel_traits::type K; + typedef typename Kernel::Point_3 Point_3; + typedef typename Kernel::Vector_3 Vector_3; typedef typename boost::graph_traits graph_traits; typedef typename graph_traits::halfedge_descriptor halfedge_descriptor; typedef typename graph_traits::vertex_descriptor vertex_descriptor; typedef typename graph_traits::face_descriptor face_descriptor; typedef std::pair Id_pair; - std::vector< typename K::Vector_3 > face_normals(nb_corners_and_nb_cc.second, NULL_VECTOR); - - - /// @TODO this is rather drastic in particular if the mesh has almost none simplified faces -/// TODO use add_faces? + std::vector< Vector_3 > face_normals(nb_corners_and_nb_cc.second, NULL_VECTOR); // compute the new mesh - std::vector< std::vector< cpp11::array > > triangles_per_cc(nb_corners_and_nb_cc.second); + std::vector< std::vector< std::array > > triangles_per_cc(nb_corners_and_nb_cc.second); boost::dynamic_bitset<> cc_to_handle(nb_corners_and_nb_cc.second); cc_to_handle.set(); @@ -526,7 +607,7 @@ bool decimate_impl(const TriangleMesh& tm, cc_id < cc_to_handle.npos; cc_id = cc_to_handle.find_next(cc_id)) { - std::vector< cpp11::array >& triangles = triangles_per_cc[cc_id]; + std::vector< std::array >& triangles = triangles_per_cc[cc_id]; triangles.clear(); std::vector< Id_pair >& csts = face_boundaries[cc_id]; @@ -551,10 +632,12 @@ bool decimate_impl(const TriangleMesh& tm, csts[0].second==csts[1].first ? csts[1].second:csts[1].first) ); cc_to_handle.set(cc_id, 0); + t_id_tracker.new_triangle_added_to_patch(cc_id); } else { - if (csts.size() > 3 && add_triangle_faces(csts, face_normals[cc_id], corners, triangles)) + std::size_t prev_triangles_size=triangles.size(); + if (csts.size() > 3 && add_triangle_faces(csts, face_normals[cc_id], corners, triangles)) cc_to_handle.set(cc_id, 0); else { @@ -571,7 +654,8 @@ bool decimate_impl(const TriangleMesh& tm, std::size_t i = get(vertex_corner_id, v); if ( !is_corner_id(i) ) { - put(vertex_corner_id, v, nb_corners_and_nb_cc.first++); + i = nb_corners_and_nb_cc.first++; + put(vertex_corner_id, v, i); corners.push_back(get(vpm, v)); new_corners.push_back(v); } @@ -583,6 +667,7 @@ bool decimate_impl(const TriangleMesh& tm, triangles.push_back({ get(vertex_corner_id, source(h,tm)), get(vertex_corner_id, target(h,tm)), get(vertex_corner_id, target(next(h,tm), tm)) }); + t_id_tracker.new_triangle_added_to_patch(cc_id); } // reset flag for neighbor connected components only if interface has changed for (vertex_descriptor v : new_corners) @@ -599,58 +684,75 @@ bool decimate_impl(const TriangleMesh& tm, } cc_to_handle.set(cc_id, 0); } + t_id_tracker.new_triangles_added_to_patch(triangles.size()-prev_triangles_size, cc_id); } } } while(cc_to_handle.any()); - for (const std::vector>& cc_trs : triangles_per_cc) + for (const std::vector>& cc_trs : triangles_per_cc) out_triangles.insert(out_triangles.end(), cc_trs.begin(), cc_trs.end()); return all_patches_successfully_remeshed; } -template -bool decimate_impl(TriangleMesh& tm, + typename VertexPointMapIn, + typename VertexPointMapOut, + typename VertexCornerMapOut, + typename FacePatchMapOut> +bool decimate_impl(const TriangleMeshIn& tm_in, + TriangleMeshOut& tm_out, std::pair nb_corners_and_nb_cc, VertexCornerIdMap& vertex_corner_id, EdgeIsConstrainedMap& edge_is_constrained, FaceCCIdMap& face_cc_ids, - const VertexPointMap& vpm) + const VertexPointMapIn& vpm_in, + const VertexPointMapOut& vpm_out, + VertexCornerMapOut vcorner_map_out, + FacePatchMapOut fpatch_map_out) { - typedef typename boost::graph_traits graph_traits; + typedef typename boost::graph_traits graph_traits; typedef typename graph_traits::vertex_descriptor vertex_descriptor; - typedef typename boost::property_traits::value_type Point_3; + typedef typename Kernel::Point_3 Point_3; + + Triangle_index_tracker + t_id_tracker(vcorner_map_out, fpatch_map_out); //collect corners std::vector< Point_3 > corners(nb_corners_and_nb_cc.first); - for(vertex_descriptor v : vertices(tm)) + for(vertex_descriptor v : vertices(tm_in)) { std::size_t i = get(vertex_corner_id, v); if ( is_corner_id(i) ) - corners[i]=get(vpm, v); + { + corners[i]=get(vpm_in, v); + } } - std::vector< cpp11::array > triangles; - bool remeshing_failed = decimate_impl(tm, - nb_corners_and_nb_cc, - vertex_corner_id, - edge_is_constrained, - face_cc_ids, - vpm, - corners, - triangles); + std::vector< std::array > triangles; + bool remeshing_failed = decimate_impl(tm_in, + nb_corners_and_nb_cc, + vertex_corner_id, + edge_is_constrained, + face_cc_ids, + vpm_in, + corners, + triangles, + t_id_tracker); if (!is_polygon_soup_a_polygon_mesh(triangles)) return false; - //clear(tm); - tm.clear_without_removing_property_maps(); - polygon_soup_to_polygon_mesh(corners, triangles, tm, parameters::all_default(), parameters::vertex_point_map(vpm)); + polygon_soup_to_polygon_mesh(corners, triangles, tm_out, + parameters::vertex_to_vertex_output_iterator(t_id_tracker.v2v_oi()). + face_to_face_output_iterator(t_id_tracker.f2f_oi()), + parameters::vertex_point_map(vpm_out)); return remeshing_failed; } @@ -811,7 +913,8 @@ void propagate_corner_status( } } -template bool decimate_meshes_with_common_interfaces_impl(TriangleMeshRange& meshes, @@ -922,12 +1025,12 @@ bool decimate_meshes_with_common_interfaces_impl(TriangleMeshRange& meshes, if (!mesh_has_non_manifold_vertices[mesh_id]) nb_corners_and_nb_cc_all[mesh_id] = - tag_corners_and_constrained_edges(tm, - coplanar_cos_threshold, - vertex_corner_id_maps[mesh_id], - edge_is_constrained_maps[mesh_id], - face_cc_ids_maps[mesh_id], - vpms[mesh_id]); + tag_corners_and_constrained_edges(tm, + coplanar_cos_threshold, + vertex_corner_id_maps[mesh_id], + edge_is_constrained_maps[mesh_id], + face_cc_ids_maps[mesh_id], + vpms[mesh_id]); else { nb_corners_and_nb_cc_all[mesh_id]={0,1}; @@ -951,7 +1054,7 @@ bool decimate_meshes_with_common_interfaces_impl(TriangleMeshRange& meshes, // now call the decimation // storage of all new triangles and all corners std::vector< std::vector< Point_3 > > all_corners(nb_meshes); - std::vector< std::vector< cpp11::array > > all_triangles(nb_meshes); + std::vector< std::vector< std::array > > all_triangles(nb_meshes); bool res = true; std::vector to_be_processed(nb_meshes, true); bool loop_again; @@ -1162,45 +1265,68 @@ void remesh_planar_patches(const TriangleMeshIn& tm_in, const NamedParametersIn& np_in = parameters::default_values(), const NamedParametersOut& np_out = parameters::default_values()) { -/* - // typedef typename GetGeomTraits::type Traits; - typedef typename GetVertexPointMap ::type VPM; + //TODO: demo plugin + + typedef typename GetGeomTraits::type Traits; + typedef typename GetVertexPointMap ::const_type VPM_in; + typedef typename GetVertexPointMap ::type VPM_out; using parameters::choose_parameter; using parameters::get_parameter; - typedef typename boost::graph_traits graph_traits; + typedef typename boost::graph_traits graph_traits; typedef typename graph_traits::edge_descriptor edge_descriptor; typedef typename graph_traits::vertex_descriptor vertex_descriptor; typedef typename graph_traits::face_descriptor face_descriptor; - double coplanar_cos_threshold = choose_parameter(get_parameter(np, internal_np::cosinus_threshold), -1); + double coplanar_cos_threshold = choose_parameter(get_parameter(np_in, internal_np::cosinus_threshold), -1); CGAL_precondition(coplanar_cos_threshold<0); - // initialize property maps - typename boost::property_map >::type edge_is_constrained = get(CGAL::dynamic_edge_property_t(), tm); - for(edge_descriptor e : edges(tm)) - put(edge_is_constrained, e, false); + // initialize property maps (fill user provided or user internal ones) + typedef typename boost::property_map >::const_type Default_ECM; + typedef typename boost::property_map >::const_type Default_VCM; + typedef typename boost::property_map >::const_type Default_FCM; - typename boost::property_map >::type vertex_corner_id = get(CGAL::dynamic_vertex_property_t(), tm); - for(vertex_descriptor v : vertices(tm)) - put(vertex_corner_id, v, Planar_segmentation::init_id()); + typename internal_np::Lookup_named_param_def< internal_np::edge_is_constrained_t, + NamedParametersIn, + Default_ECM>::type + edge_is_constrained = choose_parameter(get_parameter(np_in, internal_np::edge_is_constrained), + dynamic_edge_property_t(), tm_in); - typename boost::property_map >::type face_cc_ids = get(CGAL::dynamic_face_property_t(), tm); - for(face_descriptor f : faces(tm)) - put(face_cc_ids, f, -1); + typename internal_np::Lookup_named_param_def< internal_np::vertex_corner_map_t, + NamedParametersIn, + Default_VCM>::type + vertex_corner_id = choose_parameter(get_parameter(np_in, internal_np::vertex_corner_map), + dynamic_vertex_property_t(), tm_in); - VPM vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), - get_property_map(vertex_point, tm)); + typename internal_np::Lookup_named_param_def< internal_np::face_patch_t, + NamedParametersIn, + Default_FCM>::type + face_cc_ids = choose_parameter(get_parameter(np_in, internal_np::face_patch), + dynamic_face_property_t(), tm_in); + + for(edge_descriptor e : edges(tm_in)) put(edge_is_constrained, e, false); + for(vertex_descriptor v : vertices(tm_in)) put(vertex_corner_id, v, Planar_segmentation::init_id()); + for(face_descriptor f : faces(tm_in)) put(face_cc_ids, f, -1); + + VPM_in vpm_in = choose_parameter(get_parameter(np_in, internal_np::vertex_point), + get_const_property_map(vertex_point, tm_in)); + + VPM_out vpm_out = choose_parameter(get_parameter(np_out, internal_np::vertex_point), + get_property_map(vertex_point, tm_out)); std::pair nb_corners_and_nb_cc = - Planar_segmentation::tag_corners_and_constrained_edges(tm, coplanar_cos_threshold, vertex_corner_id, edge_is_constrained, face_cc_ids, vpm); - Planar_segmentation::decimate_impl(tm, - nb_corners_and_nb_cc, - vertex_corner_id, - edge_is_constrained, - face_cc_ids, - vpm); -*/ + Planar_segmentation::tag_corners_and_constrained_edges(tm_in, coplanar_cos_threshold, vertex_corner_id, edge_is_constrained, face_cc_ids, vpm_in); + Planar_segmentation::decimate_impl(tm_in, tm_out, + nb_corners_and_nb_cc, + vertex_corner_id, + edge_is_constrained, + face_cc_ids, + vpm_in, vpm_out, + get_parameter(np_out, internal_np::vertex_corner_map), + get_parameter(np_out, internal_np::face_patch)); } /*! @@ -1280,7 +1406,8 @@ template + typename NamedParametersIn = parameters::Default_named_parameters, + typename NamedParametersOut = parameters::Default_named_parameters> bool remesh_almost_planar_patches(const TriangleMeshIn& tm_in, TriangleMeshOut& tm_out, std::size_t nb_patches, @@ -1291,21 +1418,25 @@ bool remesh_almost_planar_patches(const TriangleMeshIn& tm_in, const NamedParametersIn& np_in = parameters::default_values(), const NamedParametersOut& np_out = parameters::default_values()) { -/* - typedef typename GetVertexPointMap ::type VPM; + typedef typename GetGeomTraits::type Traits; + typedef typename GetVertexPointMap ::const_type VPM_in; + typedef typename GetVertexPointMap ::type VPM_out; using parameters::choose_parameter; using parameters::get_parameter; - VPM vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), - get_property_map(vertex_point, tm)); + VPM_in vpm_in = choose_parameter(get_parameter(np_in, internal_np::vertex_point), + get_const_property_map(vertex_point, tm_in)); - return Planar_segmentation::decimate_impl(tm, - std::make_pair(nb_corners, nb_patches), - vertex_corner_map, ecm, face_patch_map, vpm); -*/ + VPM_out vpm_out = choose_parameter(get_parameter(np_out, internal_np::vertex_point), + get_property_map(vertex_point, tm_out)); + + return Planar_segmentation::decimate_impl(tm_in, tm_out, + std::make_pair(nb_corners, nb_patches), + vertex_corner_map, ecm, face_patch_map, vpm_in, vpm_out, + get_parameter(np_out, internal_np::vertex_corner_map), + get_parameter(np_out, internal_np::face_patch)); } - #ifndef DOXYGEN_RUNNING // MeshMap must be a mutable lvalue pmap with Triangle_mesh as value_type template diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_decimation_of_planar_patches.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_decimation_of_planar_patches.cpp index ea5eed4405a..719c3a8811f 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_decimation_of_planar_patches.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_decimation_of_planar_patches.cpp @@ -38,7 +38,8 @@ int main() in >> sm; // call the decimation function - if (!PMP::remesh_planar_patches(sm)) + Surface_mesh out; + if (!PMP::remesh_planar_patches(sm, out)) { std::cerr << "ERROR: decimate failed to remesh some patches\n"; OK=false; @@ -46,9 +47,9 @@ int main() ss=std::stringstream(); ss << "out" << i << ".off"; std::ofstream out(ss.str().c_str()); - out << sm; + out << out; std::cout << " output written to out" << i << ".off\n"; - assert(is_valid_polygon_mesh(sm)); + assert(is_valid_polygon_mesh(out)); } // testing border non-manifold vertex: not working for now, test kept /* @@ -81,11 +82,12 @@ int main() CGAL::Euler::remove_face(halfedge(f2, sm), sm); PMP::duplicate_non_manifold_vertices(sm); std::size_t nbv_before = vertices(sm).size(); - if (!PMP::remesh_planar_patches(sm)) + Surface_mesh out; + if (!PMP::remesh_planar_patches(sm, out)) std::cerr << "decimate failed to remesh some patches (expected)\n"; - assert(vertices(sm).size()> sm; // call the decimation function - if (!PMP::remesh_planar_patches(sm, CGAL::parameters::cosinus_threshold(-0.99))) + Surface_mesh out; + if (!PMP::remesh_planar_patches(sm, out, CGAL::parameters::cosinus_threshold(-0.99))) { OK=false; std::cerr << "ERROR: decimate failed to remesh some patches\n"; @@ -125,9 +129,9 @@ int main() ss=std::stringstream(); ss << "out_a" << i << ".off"; std::ofstream out(ss.str().c_str()); - out << sm; + out << out; std::cout << " output written to out_a" << i << ".off\n"; - assert(is_valid_polygon_mesh(sm)); + assert(is_valid_polygon_mesh(out)); } //testing decimation of meshes, preserving common interface @@ -310,7 +314,8 @@ int main() std::cout << "decimate of data/decimation/sphere.off using approximate predicates\n"; std::ifstream in("data/decimation/sphere.off"); in >> sm; - if (!PMP::remesh_planar_patches(sm, CGAL::parameters::cosinus_threshold(-0.99))) + Surface_mesh out; + if (!PMP::remesh_planar_patches(sm, out, CGAL::parameters::cosinus_threshold(-0.99))) std::cerr << "decimate failed to remesh some patches\n"; } { @@ -318,12 +323,13 @@ int main() std::cout << "decimate of data/decimation/sphere_selection.off using approximate predicates\n"; std::ifstream in("data/decimation/sphere_selection.off"); in >> sm; - if (!PMP::remesh_planar_patches(sm, CGAL::parameters::cosinus_threshold(-0.99))) + Surface_mesh out; + if (!PMP::remesh_planar_patches(sm, out, CGAL::parameters::cosinus_threshold(-0.99))) std::cout << "decimate failed to remesh some patches (this is the expected behavior)\n"; std::ofstream out("sphere_selection_app.off"); - out << sm; + out << out; std::cout << "output written to sphere_selection_app.off\n"; - assert(is_valid_polygon_mesh(sm)); + assert(is_valid_polygon_mesh(out)); } assert(OK);