diff --git a/BGL/include/CGAL/boost/graph/parameters_interface.h b/BGL/include/CGAL/boost/graph/parameters_interface.h index 16e1810ea62..193a496e26a 100644 --- a/BGL/include/CGAL/boost/graph/parameters_interface.h +++ b/BGL/include/CGAL/boost/graph/parameters_interface.h @@ -80,7 +80,9 @@ CGAL_add_named_parameter(clip_volume_t, clip_volume, clip_volume) CGAL_add_named_parameter(use_compact_clipper_t, use_compact_clipper, use_compact_clipper) CGAL_add_named_parameter(do_orientation_tests_t, do_orientation_tests, do_orientation_tests) CGAL_add_named_parameter(do_self_intersection_tests_t, do_self_intersection_tests, do_self_intersection_tests) - +CGAL_add_named_parameter(error_codes_t, error_codes, error_codes) +CGAL_add_named_parameter(volume_inclusions_t, volume_inclusions, volume_inclusions) +CGAL_add_named_parameter(face_cc_map_t, face_connected_component_map, face_connected_component_map) // List of named parameters that we use in the package 'Surface Mesh Simplification' CGAL_add_named_parameter(get_cost_policy_t, get_cost_policy, get_cost) diff --git a/BGL/test/BGL/test_cgal_bgl_named_params.cpp b/BGL/test/BGL/test_cgal_bgl_named_params.cpp index ca1fda75b5f..59120379db6 100644 --- a/BGL/test/BGL/test_cgal_bgl_named_params.cpp +++ b/BGL/test/BGL/test_cgal_bgl_named_params.cpp @@ -163,6 +163,9 @@ void test(const NamedParameters& np) check_same_type<45>(get_param(np, CGAL::internal_np::use_compact_clipper)); check_same_type<47>(get_param(np, CGAL::internal_np::do_self_intersection_tests)); check_same_type<48>(get_param(np, CGAL::internal_np::do_orientation_tests)); + check_same_type<49>(get_param(np, CGAL::internal_np::error_codes)); + check_same_type<50>(get_param(np, CGAL::internal_np::volume_inclusions)); + check_same_type<51>(get_param(np, CGAL::internal_np::face_connected_component_map)); // Named parameters that we use in the package 'Surface Mesh Simplification' check_same_type<34>(get_param(np, CGAL::internal_np::get_cost_policy)); @@ -242,6 +245,9 @@ int main() .apply_per_connected_component(A<46>(46)) .do_self_intersection_tests(A<47>(47)) .do_orientation_tests(A<48>(48)) + .error_codes(A<49>(49)) + .volume_inclusions(A<50>(50)) + .face_connected_component_map(A<51>(51)) ); return EXIT_SUCCESS; diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/orientation.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/orientation.h index 791f7b218ed..6d2256b6934 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/orientation.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/orientation.h @@ -723,7 +723,53 @@ enum Volume_error_code { VALID_VOLUME, SURFACE_SELF_INTERSECTION, VOLUME_INTERSECTION, NON_TRIANGULATED_SURFACE, - INCONSISTENT_ORIENTATION }; + INCONSISTENT_ORIENTATION, + SINGLE_CONNECTED_COMPONENT}; +namespace internal { +template +void copy_error_codes(std::vector& error_codes_in, + RefToVector ref_wrapper) +{ + error_codes_in.swap(ref_wrapper.get()); +} + +inline void copy_error_codes(std::vector&, + boost::param_not_found) +{} + +template +void copy_nested_cc_per_cc( + std::vector< std::vector >& nested_cc_per_cc, + RefToVector ref_to_vector) +{ + ref_to_vector.get().swap( nested_cc_per_cc); +} + +inline void copy_nested_cc_per_cc( + std::vector< std::vector >&, + boost::param_not_found) +{} + +template +void set_f_cc_id(const std::vector& f_cc, + FaceIndexMap face_index_map, + FaceCCIdMap face_cc_map, + const TriangleMesh& tm) +{ + BOOST_FOREACH(typename boost::graph_traits::face_descriptor fd, faces(tm)) + { + put(face_cc_map, fd, f_cc[ get(face_index_map, fd) ]); + } +} + +template +void set_f_cc_id(const std::vector&, + FaceIndexMap, + boost::param_not_found, + const TriangleMesh&) +{} + +} // internal //TODO Add documentation // doc: non-closed connected components are reported as isolated volumes @@ -734,9 +780,14 @@ enum Volume_error_code { VALID_VOLUME, // component must be taken into account rather than only the nesting. In case of incompatible // orientation of a cc X with its parent, all other CC included in X (as well as X) are reported // as independant volumes +// doc: in case there is only one CC, no extra test is performed // NP do_orientation_tests // NP do_self_intersection_tests -// TODO return a vector with info on the volume? non-triangle/open/SI/regular/... +// NP error_codes +// NP face_index +// NP vertex_point_map +// NP volume_inclusions (must be a reference_wrapper) +// NP face_connected_component_map template std::size_t volume_connected_components(const TriangleMesh& tm, @@ -768,6 +819,12 @@ volume_connected_components(const TriangleMesh& tm, bind_property_maps(fid_map,make_property_map(face_cc)), parameters::face_index_map(fid_map)); + // contains for each CC the CC that are in its bounded side + std::vector > nested_cc_per_cc(nb_cc); + + // copy cc-id info + internal::set_f_cc_id(face_cc, fid_map, boost::get_param(np, internal_np::face_connected_component_map), tm); + const bool do_self_intersection_tests = boost::choose_param(boost::get_param(np, internal_np::do_self_intersection_tests), false); @@ -776,13 +833,13 @@ volume_connected_components(const TriangleMesh& tm, if (nb_cc == 1) { - if (do_self_intersection_tests && does_self_intersect(tm, np)) - error_codes.push_back(SURFACE_SELF_INTERSECTION); - else - error_codes.push_back(VALID_VOLUME); + error_codes.push_back(SINGLE_CONNECTED_COMPONENT); BOOST_FOREACH(face_descriptor fd, faces(tm)) put(volume_id_map, fd, 0); + + internal::copy_error_codes(error_codes, boost::get_param(np, internal_np::error_codes)); + internal::copy_nested_cc_per_cc(nested_cc_per_cc, boost::get_param(np, internal_np::volume_inclusions)); return 1; } @@ -898,8 +955,6 @@ volume_connected_components(const TriangleMesh& tm, // init the main loop std::size_t k = 0; - // contains for each CC the CC that are in its bounded side - std::vector > nested_cc_per_cc(nb_cc); // similar as above but exclusively contains cc ids included by more that one CC. // The result will be then merged with nested_cc_per_cc but temporarilly we need // another container to not more than once the inclusion testing (in case a CC is @@ -1120,8 +1175,9 @@ volume_connected_components(const TriangleMesh& tm, } } - //TODO add a NP to output it CGAL_assertion(next_volume_id == error_codes.size()); + internal::copy_error_codes(error_codes, boost::get_param(np, internal_np::error_codes)); + internal::copy_nested_cc_per_cc(nested_cc_per_cc, boost::get_param(np, internal_np::volume_inclusions)); return next_volume_id; } diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_split_volume.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_split_volume.cpp index 5290c7f9c75..663598342df 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_split_volume.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_split_volume.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -10,6 +11,8 @@ typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; typedef CGAL::Surface_mesh Surface_mesh; +namespace PMP = CGAL::Polygon_mesh_processing; + int main(int argc, char** argv) { if (argc==1) @@ -17,7 +20,7 @@ int main(int argc, char** argv) std::cerr << "Nothing tested\n"; return 1; } - + for(int i=1;i> sm; + std::vector error_codes; + std::vector< std::vector > nested_cc_per_cc; + + Surface_mesh::Property_map fccmap = + sm.add_property_map("f:CC").first; + Surface_mesh::Property_map vol_id_map = sm.add_property_map().first; - std::size_t nb_vol = - CGAL::Polygon_mesh_processing::volume_connected_components(sm, vol_id_map); + std::size_t nb_vol = PMP::volume_connected_components( + sm, vol_id_map, + CGAL::parameters::error_codes(boost::ref(error_codes)). + face_connected_component_map(fccmap). + volume_inclusions(boost::ref(nested_cc_per_cc))); + std::cout << " found " << nb_vol << " volumes\n"; typedef CGAL::Face_filtered_graph Filtered_graph; Filtered_graph vol_mesh(sm, 0, vol_id_map);