diff --git a/BGL/include/CGAL/boost/graph/parameters_interface.h b/BGL/include/CGAL/boost/graph/parameters_interface.h index ad0949af770..fa3450b2c85 100644 --- a/BGL/include/CGAL/boost/graph/parameters_interface.h +++ b/BGL/include/CGAL/boost/graph/parameters_interface.h @@ -23,6 +23,7 @@ CGAL_add_named_parameter(face_index_t, face_index, face_index_map) CGAL_add_named_parameter(edge_index_t, edge_index, edge_index_map) CGAL_add_named_parameter(halfedge_index_t, halfedge_index, halfedge_index_map) CGAL_add_named_parameter(edge_is_constrained_t, edge_is_constrained, edge_is_constrained_map) +CGAL_add_named_parameter(vertex_incident_patches_t, vertex_incident_patches, vertex_incident_patches_map) CGAL_add_named_parameter(first_index_t, first_index, first_index) CGAL_add_named_parameter(vertex_feature_degree_t, vertex_feature_degree, vertex_feature_degree_map) CGAL_add_named_parameter(set_cache_policy_t, set_cache_policy, set_cache) diff --git a/Mesh_3/include/CGAL/Polyhedral_complex_mesh_domain_3.h b/Mesh_3/include/CGAL/Polyhedral_complex_mesh_domain_3.h index fe9b164f72a..c11a5e961d0 100644 --- a/Mesh_3/include/CGAL/Polyhedral_complex_mesh_domain_3.h +++ b/Mesh_3/include/CGAL/Polyhedral_complex_mesh_domain_3.h @@ -823,8 +823,10 @@ detect_features(FT angle_in_degree, typedef typename boost::property_map >::type VIPMap; PIDMap pid_map = get(face_patch_id_t(), p); VIPMap vip_map = get(vertex_incident_patches_t(), p); - nb_of_patch_plus_one +=PMP::detect_features(p, angle_in_degree,pid_map, vip_map, PMP::parameters::first_index(nb_of_patch_plus_one) - .face_index_map(boost::make_assoc_property_map(face_ids))); + nb_of_patch_plus_one +=PMP::sharp_edges_segmentation(p, angle_in_degree,pid_map, PMP::parameters::first_index(nb_of_patch_plus_one) + .face_index_map(boost::make_assoc_property_map(face_ids)) + .edge_is_constrained_map(get(CGAL::edge_is_feature, p)) + .vertex_incident_patches_map(vip_map)); internal::Mesh_3::Is_featured_edge is_featured_edge(p); diff --git a/Mesh_3/include/CGAL/Polyhedral_mesh_domain_with_features_3.h b/Mesh_3/include/CGAL/Polyhedral_mesh_domain_with_features_3.h index 2dd10f188b0..d9700959a2e 100644 --- a/Mesh_3/include/CGAL/Polyhedral_mesh_domain_with_features_3.h +++ b/Mesh_3/include/CGAL/Polyhedral_mesh_domain_with_features_3.h @@ -466,8 +466,10 @@ detect_features(FT angle_in_degree, std::vector& poly) PIDMap pid_map = get(face_patch_id_t(), p); VIPMap vip_map = get(vertex_incident_patches_t(), p); // Get sharp features - nb_of_patch_plus_one += PMP::detect_features(p, angle_in_degree,pid_map, vip_map, PMP::parameters::first_index(nb_of_patch_plus_one) - .face_index_map(boost::make_assoc_property_map(face_ids))); + nb_of_patch_plus_one += PMP::sharp_edges_segmentation(p, angle_in_degree,pid_map, PMP::parameters::first_index(nb_of_patch_plus_one) + .face_index_map(boost::make_assoc_property_map(face_ids)) + .edge_is_constrained_map(get(CGAL::edge_is_feature, p)) + .vertex_incident_patches_map(vip_map)); internal::Mesh_3::Is_featured_edge is_featured_edge(p); diff --git a/Polygon_mesh_processing/doc/Polygon_mesh_processing/NamedParameters.txt b/Polygon_mesh_processing/doc/Polygon_mesh_processing/NamedParameters.txt index c9fea109172..897a7ba9668 100644 --- a/Polygon_mesh_processing/doc/Polygon_mesh_processing/NamedParameters.txt +++ b/Polygon_mesh_processing/doc/Polygon_mesh_processing/NamedParameters.txt @@ -154,9 +154,19 @@ the marked edges are constrained.\n a default property map where no edge is constrained is provided. \cgalNPEnd +\cgalNPBegin{ vertex_incident_patches_map } \anchor PMP_vertex_incident_patches_map +the property map containing the surface patches incident to each vertex of the input polygon mesh.\n +\b Type : a class model of `LvaluePropertyMap` with +`boost::graph_traits::%vertex_descriptor` as key type.Its value type +must be a container of `boost::property_traits::%value_type` and have a function `insert()`. +A `std::set` or a `boost::unordered_set` are recommended, as a patch index may be +inserted several times.\n +\b Default value is \code boost::get(CGAL::vertex_incident_patches_t, pmesh)\endcode +\cgalNPEnd + \cgalNPBegin{ first_index } \anchor PMP_first_index The index of the first surface patch.\n -\b Type : `std::size_t`.\n +\b Type : `std::size_t`\n \b Default : 1. \cgalNPEnd diff --git a/Polygon_mesh_processing/doc/Polygon_mesh_processing/PackageDescription.txt b/Polygon_mesh_processing/doc/Polygon_mesh_processing/PackageDescription.txt index f5cecc9e7c4..6be846bc625 100644 --- a/Polygon_mesh_processing/doc/Polygon_mesh_processing/PackageDescription.txt +++ b/Polygon_mesh_processing/doc/Polygon_mesh_processing/PackageDescription.txt @@ -154,9 +154,9 @@ and provides a list of the parameters that are used in this package. - `CGAL::Polygon_mesh_processing::sample_triangle_mesh()` ## Feature Detection Functions ## -- `CGAL::Polygon_mesh_processing::detect_features()` +- `CGAL::Polygon_mesh_processing::sharp_edges_segmentation()` - `CGAL::Polygon_mesh_processing::detect_sharp_edges()` -- `CGAL::Polygon_mesh_processing::detect_incident_patches()` +- `CGAL::Polygon_mesh_processing::detect_vertex_incident_patches()` ## Miscellaneous ## - `CGAL::Polygon_mesh_slicer` diff --git a/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt b/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt index a04674e75ee..5e7fdbec874 100644 --- a/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt +++ b/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt @@ -684,10 +684,10 @@ with the following code: This package provides methods to detect some features of a polygon mesh. -The function `CGAL::Polygon_mesh_processing::detect_features()` +The function `CGAL::Polygon_mesh_processing::sharp_edges_segmentation()` detects the sharp edges of a polygon mesh and deduces surface patches and vertices incidences. It can be split into three functions : `CGAL::Polygon_mesh_processing::detect_sharp_edges()`, `CGAL::Polygon_mesh_processing::connected_components()` -and `CGAL::Polygon_mesh_processing::detect_incident_patches()`, +and `CGAL::Polygon_mesh_processing::detect_vertex_incident_patches()`, that respectively detect the sharp edges, compute the patch indices, and give each of `pmesh` vertices the patch indices of its incident faces. \subsection DetectFeaturesExample Feature Detection Example diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/detect_features_example.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/detect_features_example.cpp index ec6d858e347..692bcb8d7b1 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/detect_features_example.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/detect_features_example.cpp @@ -30,9 +30,11 @@ int main(int argc, char* argv[]) typedef boost::property_map >::type VIMap; VIMap vip = get(CGAL::vertex_incident_patches_t(), mesh); std::size_t number_of_patches = 1; - number_of_patches=PMP::detect_features(mesh, 90, pid, vip); typedef boost::property_map::type EIFMap; EIFMap eif = get(CGAL::edge_is_feature, mesh); + number_of_patches=PMP::sharp_edges_segmentation(mesh, 90, pid, + PMP::parameters::edge_is_constrained_map(eif) + .vertex_incident_patches_map(vip)); int nb_sharp_edges =0; BOOST_FOREACH(boost::graph_traits::edge_descriptor e, edges(mesh)) { diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/detect_features.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/detect_features.h index 4291e894433..3257516e524 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/detect_features.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/detect_features.h @@ -75,98 +75,193 @@ is_sharp(PolygonMesh& polygonMesh, //wrapper for patchid map. -template +template::value_type> struct PatchIdMapWrapper { typedef typename boost::property_traits::category category; - typedef typename boost::property_traits::value_type value_type; + typedef ValueType value_type; typedef typename boost::property_traits::reference reference; typedef typename boost::property_traits::key_type key_type; PatchIdMap map; - value_type offset; - PatchIdMapWrapper(PatchIdMap& map, value_type offset) + int offset; + PatchIdMapWrapper(PatchIdMap& map, int offset) :map(map), offset(offset){} }; -template -typename PatchIdMapWrapper::value_type get(PatchIdMapWrapper& map, Handle_type h) + +template +typename PatchIdMapWrapper::value_type get(PatchIdMapWrapper& map, Handle_type h) { return get(map.map, h) - map.offset; } -template -void put(PatchIdMapWrapper& map, Handle_type h, - typename PatchIdMapWrapper::value_type pid) +template +void put(PatchIdMapWrapper& map, Handle_type h, + typename PatchIdMapWrapper::value_type pid) { put(map.map, h, pid + map.offset); } -template + +//specialization for std::pair +template +struct PatchIdMapWrapper > +{ + typedef typename boost::property_traits::category category; + typedef Int value_type; + typedef typename boost::property_traits::reference reference; + typedef typename boost::property_traits::key_type key_type; + + PatchIdMap map; + int offset; + PatchIdMapWrapper(PatchIdMap& map, int offset) + :map(map), offset(offset){} +}; + +template +typename PatchIdMapWrapper >::value_type get(PatchIdMapWrapper >& map, Handle_type h) +{ + return get(map.map, h).first - map.offset; +} + +template +void put(PatchIdMapWrapper >& map, Handle_type h, + typename PatchIdMapWrapper >::value_type pid) +{ + put(map.map, h, std::pair(pid+map.offset, 0)); +} + +template std::size_t detect_surface_patches(PolygonMesh& p, PatchIdMap& patch_id_map, + EdgeIsFeatureMap& eif, const NamedParameters& np) { //extract types from NPs - typedef typename boost::lookup_named_param_def < - internal_np::edge_is_constrained_t, - NamedParameters, - typename boost::property_map::type//default - > ::type EIF_map; - EIF_map eif - = boost::choose_param(get_param(np, internal_np::edge_is_constrained), - get(CGAL::edge_is_feature, p)); typename GetFaceIndexMap::const_type fimap = boost::choose_param(get_param(np, internal_np::face_index), get_const_property_map(boost::face_index, p)); - std::size_t offset = boost::choose_param(get_param(np, internal_np::first_index), - 1); + int offset =static_cast( + boost::choose_param(get_param(np, internal_np::first_index), + 1)); - internal::PatchIdMapWrapper wrapmap(patch_id_map, offset); + internal::PatchIdMapWrapper::value_type> wrapmap(patch_id_map, offset); return connected_components(p, wrapmap, parameters::edge_is_constrained_map(eif) .face_index_map(fimap)); } -template +template typename boost::graph_traits::faces_size_type detect_surface_patches(PolygonMesh& p, - PatchIdMap& patch_id_map) + PatchIdMap& patch_id_map, + EdgeIsFeatureMap& eif) { - return detect_surface_patches(p, patch_id_map, parameters::all_default()); + return detect_surface_patches(p, patch_id_map, eif, parameters::all_default()); } + + +template +struct sharp_caller +{ + template + static void call(PolygonMesh& pmesh, + typename GetGeomTraits::type::FT angle_in_deg, + EIFMap& edge_is_feature_map, + VNFEMap& vnfe) + { + typedef typename GetGeomTraits::type::FT FT; + // Initialize vertices + BOOST_FOREACH(typename boost::graph_traits::vertex_descriptor vd, vertices(pmesh)) + { + put(vnfe,vd, 0); + } + FT cos_angle ( std::cos(CGAL::to_double(angle_in_deg) * CGAL_PI / 180.) ); + + // Detect sharp edges + BOOST_FOREACH(typename boost::graph_traits::edge_descriptor ed, edges(pmesh)) + { + typename boost::graph_traits::halfedge_descriptor he = halfedge(ed,pmesh); + if(is_border(he,pmesh) || angle_in_deg == FT() || + (angle_in_deg != FT(180) && internal::is_sharp(pmesh,he,cos_angle)) + ) + { + put(edge_is_feature_map, edge(he, pmesh), true); + put(vnfe, target(he,pmesh), get(vnfe, target(he,pmesh))+1); + put(vnfe, source(he,pmesh), get(vnfe, source(he,pmesh))+1); + + } + } + } +}; + +template <> +struct sharp_caller +{ + template + static void call(PolygonMesh& pmesh, + typename GetGeomTraits::type::FT angle_in_deg, + EIFMap& edge_is_feature_map, + VNFEMap&) + { + typedef typename GetGeomTraits::type::FT FT; + FT cos_angle ( std::cos(CGAL::to_double(angle_in_deg) * CGAL_PI / 180.) ); + + // Detect sharp edges + BOOST_FOREACH(typename boost::graph_traits::edge_descriptor ed, edges(pmesh)) + { + typename boost::graph_traits::halfedge_descriptor he = halfedge(ed,pmesh); + if(is_border(he,pmesh) || angle_in_deg == FT() || + (angle_in_deg != FT(180) && internal::is_sharp(pmesh,he,cos_angle)) + ) + { + put(edge_is_feature_map, edge(he, pmesh), true); + } + } + } +}; } //end internal /*! * \ingroup PMP_detect_features_grp * - * Detects the sharp edges of `pmesh` according to `angle_in_deg` and computes the number of sharp edges incident to each vertex. + * detects and marks as constrained edges around which incident faces form an angle equal to or greater than `angle_in_deg`. + * Also computes the number of sharp edges incident to each vertex if `vertex_feature_degree_map` is provided. * - * Property maps for `CGAL::edge_is_constrained_t` and `CGAL::vertex_feature_degree_t` should be either - * available as internal property maps to `pmesh` or provided as Named Parameters. - * - * \tparam PolygonMesh a model of `FaceGraph` + * \tparam PolygonMesh a model of `HalfedgeListGraph` * \tparam FT a number type. It is * either deduced from the `geom_traits` \ref namedparameters if provided, * or from the geometric traits class deduced from the point property map * of `PolygonMesh`. + * \tparam EdgeIsFeatureMap a model of `ReadWritePropertyMap` with `boost::graph_traits::%edge_descriptor` + * as key type and `bool` as value type. It should be default constructible. * \tparam NamedParameters a sequence of \ref namedparameters * * \param p the polygon mesh * \param angle_in_deg the floor dihedral angle. + * \param edge_is_feature_map a filled property map that will contain the sharp-or-not status of each edge of `pmesh` * \param np optional \ref namedparameters described below * * \cgalNamedParamsBegin * \cgalParamBegin{geom_traits} an instance of a geometric traits class, model of `Kernel`\cgalParamEnd - * \cgalParamBegin{edge_is_constrained_map} a property map that will contain the constrained-or-not status of each edge of `pmesh` \cgalParamEnd - * \cgalParamBegin{vertex_feature_degree_map} a property map that will contain the number of adjacent feature edges for each vertex of `pmesh` \cgalParamEnd + * \cgalParamBegin{vertex_feature_degree_map} a property map that will contain the number of adjacent feature edges for + * each vertex of `pmesh` \cgalParamEnd * \cgalNamedParamsEnd * */ #ifdef DOXYGEN_RUNNING template #else -template +template #endif void detect_sharp_edges(PolygonMesh& pmesh, #ifdef DOXYGEN_RUNNING @@ -174,17 +269,10 @@ void detect_sharp_edges(PolygonMesh& pmesh, #else typename GetGeomTraits::type::FT angle_in_deg, #endif + EdgeIsFeatureMap& edge_is_feature_map, const NamedParameters& np) { //extract types from NPs - typedef typename boost::lookup_named_param_def < - internal_np::edge_is_constrained_t, - NamedParameters, - typename boost::property_map::type//default - > ::type EIF_map; - EIF_map eif - = boost::choose_param(get_param(np, internal_np::edge_is_constrained), - get(CGAL::edge_is_feature, pmesh)); typedef typename boost::lookup_named_param_def < internal_np::vertex_feature_degree_t, @@ -196,31 +284,11 @@ void detect_sharp_edges(PolygonMesh& pmesh, get(CGAL::vertex_feature_degree_t(), pmesh)); typedef typename GetGeomTraits::type GT; - typedef typename GT::FT FT; - - // Initialize vertices - - BOOST_FOREACH(typename boost::graph_traits::vertex_descriptor vd, vertices(pmesh)) - { - put(vnfe,vd, 0); - } - - FT cos_angle ( std::cos(CGAL::to_double(angle_in_deg) * CGAL_PI / 180.) ); - - // Detect sharp edges - BOOST_FOREACH(typename boost::graph_traits::edge_descriptor ed, edges(pmesh)) - { - typename boost::graph_traits::halfedge_descriptor he = halfedge(ed,pmesh); - if(is_border(he,pmesh) || angle_in_deg == FT() || - (angle_in_deg != FT(180) && internal::is_sharp(pmesh,he,cos_angle)) - ) - { - put(eif, edge(he, pmesh), true); - - put(vnfe, target(he,pmesh), get(vnfe, target(he,pmesh))+1); - put(vnfe, source(he,pmesh), get(vnfe, source(he,pmesh))+1); - } - } + bool is_default = boost::is_default_param(get_param(np, internal_np::vertex_feature_degree)); + if(is_default) + internal::sharp_caller().call(pmesh, angle_in_deg, edge_is_feature_map, vnfe); + else + internal::sharp_caller().call(pmesh, angle_in_deg, edge_is_feature_map, vnfe); } @@ -228,60 +296,41 @@ void detect_sharp_edges(PolygonMesh& pmesh, /*! * \ingroup PMP_detect_features_grp * - * Collects the surface patches of the faces incident to each vertex + * collects the surface patches of the faces incident to each vertex of the input polygon mesh. * - * * A filled property map for `CGAL::edge_is_constrained_t` should be either - * available as an internal property map to `pmesh` or provided as one of the Named Parameters. - * - * \tparam PolygonMesh a model of `FaceGraph` + * \tparam PolygonMesh a model of `HalfedgeListGraph` * \tparam PatchIdMap a model of `ReadWritePropertyMap` with `boost::graph_traits::%face_descriptor` as key type and the desired patch id, model of `CopyConstructible` as value type. * \tparam VertexIncidentPatchesMap a model of mutable `LvaluePropertyMap` with `boost::graph_traits::%vertex_descriptor` as key type. Its value type must be a container of `boost::property_traits::%value_type` and have a function `insert()`. - A `std::set` or a `std::unordered_set` are recommended, as a patch index may be + A `std::set` or a `boost::unordered_set` are recommended, as a patch index may be inserted several times. - - * \tparam NamedParameters a sequence of \ref namedparameters - * + * \tparam EdgeIsFeatureMap a model of `ReadWritePropertyMap` with `boost::graph_traits::%edge_descriptor` * \param p the polygon mesh * \param patch_id_map the property map containing the surface patch ids for the faces of `pmesh`. It must be already filled. * \param vertex_incident_patches_map a property map that will contain the patch ids of all the faces incident to each vertex of `pmesh`. - * \param np optional \ref namedparameters described below + * \param edge_is_feature_map a filled property map that will contain the sharp-or-not status of each edge of `pmesh` * - * \cgalNamedParamsBegin - * \cgalParamBegin{geom_traits} an instance of a geometric traits class, model of `Kernel`\cgalParamEnd - * \cgalParamBegin{edge_is_constrained_map} a property map containing the sharp edges of `pmesh` \cgalParamEnd - * \cgalNamedParamsEnd - * - * * @see `CGAL::Polygon_mesh_processing::detect_features()` + * * @see `CGAL::Polygon_mesh_processing::sharp_edges_segmentation()` */ -template -void detect_incident_patches(PolygonMesh& pmesh, +template +void detect_vertex_incident_patches(PolygonMesh& pmesh, PatchIdMap& patch_id_map, VertexIncidentPatchesMap& vertex_incident_patches_map, - const NamedParameters& np) + EdgeIsFeatureMap& edge_is_feature_map) { //extract types from NPs - typedef typename boost::lookup_named_param_def < - internal_np::edge_is_constrained_t, - NamedParameters, - typename boost::property_map::type//default - > ::type EIF_map; - EIF_map eif - = boost::choose_param(get_param(np, internal_np::edge_is_constrained), - get(CGAL::edge_is_feature, pmesh)); typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - typedef typename boost::property_traits::value_type PatchId; BOOST_FOREACH(vertex_descriptor vit,vertices(pmesh)) { // Look only at feature vertices - if( ! get(eif, edge(halfedge(vit, pmesh), pmesh) )){ continue; } + if( ! get(edge_is_feature_map, edge(halfedge(vit, pmesh), pmesh) )){ continue; } // Loop on incident facets of vit typename VertexIncidentPatchesMap::value_type set; @@ -300,18 +349,46 @@ void detect_incident_patches(PolygonMesh& pmesh, } } + +namespace internal +{ +template +struct vip_caller +{ + template + static void call(PolygonMesh& mesh, PIDMap& pid, VIPMap& vip, EIFMap& eif ) + { + CGAL::Polygon_mesh_processing::detect_vertex_incident_patches(mesh, pid, vip, eif); + } +}; + +template <> +struct vip_caller +{ + template + static void call(PolygonMesh&, PIDMap&, VIPMap&, EIFMap&) + { + } +}; +}//end internal /*! * \ingroup PMP_detect_features_grp * - * Detects the sharp edges of `pmesh` according to `angle_in_deg` and computes the corresponding - * surface patch ids for each face. - * * This function calls successively `CGAL::Polygon_mesh_processing::detect_sharp_edges()`, * `CGAL::Polygon_mesh_processing::connected_components()` and - * `CGAL::Polygon_mesh_processing::detect_incident_patches()` + * `CGAL::Polygon_mesh_processing::detect_vertex_incident_patches()` * - * Property maps for `CGAL::edge_is_constrained_t`, `CGAL::vertex_feature_degree_t` and `CGAL::face_index_t` - * should be either available as internal property maps to `pmesh` or provided as Named Parameters. + * It detects the sharp edges of `pmesh` according to `angle_in_deg` and computes the corresponding + * surface patch ids for each face. + * + * A property map for `CGAL::face_index_t`should be either available + * as an internal property map to `pmesh` or provided as one of the Named Parameters. * * \tparam PolygonMesh a model of `FaceGraph` * \tparam FT a number type. It is @@ -321,76 +398,94 @@ void detect_incident_patches(PolygonMesh& pmesh, * \tparam PatchIdMap a model of `ReadWritePropertyMap` with `boost::graph_traits::%face_descriptor` as key type and the desired patch id, model of `CopyConstructible` as value type. - * \tparam VertexIncidentPatchesMap a model of mutable `LvaluePropertyMap` with - `boost::graph_traits::%vertex_descriptor` as key type. Its value type - must be a container of `boost::property_traits::%value_type` and have a function `insert()`. - A `std::set` or a `std::unordered_set` are recommended, as a patch index may be - inserted several times. - * \tparam NamedParameters a sequence of \ref namedparameters * * \param p the polygon mesh * \param angle_in_deg the floor dihedral angle. * \param patch_id_map the property map that will contain the surface patch ids for the faces of `pmesh`. - * \param vertex_incident_patches_map a property map that will contain the patch ids of all the faces incident to each vertex of `pmesh`. * \param np optional \ref namedparameters described below * * \cgalNamedParamsBegin * \cgalParamBegin{geom_traits} an instance of a geometric traits class, model of `Kernel`\cgalParamEnd * \cgalParamBegin{edge_is_constrained_map} a property map that will contain the constrained-or-not status of each edge of `pmesh` \cgalParamEnd * \cgalParamBegin{vertex_feature_degree_map} a property map that will contain the number of adjacent feature edges for each vertex of `pmesh` \cgalParamEnd - * \cgalParamBegin{first_index} an std::size_t containing the index of the first surface patch of `pmesh` \cgalParamEnd + * \cgalParamBegin{first_index} a `std::size_t` containing the index of the first surface patch of `pmesh`. + * The patches will be numbered on [first_index; first_index + num_patches], where num_patches is the number of surface patches \cgalParamEnd * \cgalParamBegin{face_index_map} a property map containing the index of each face of `pmesh` \cgalParamEnd + * \cgalParamBegin{vertex_incident_patches_map} a property map that will contain the patch ids of all the faces incident to each vertex of `pmesh`. \cgalParamEnd * \cgalNamedParamsEnd * \returns the number of surface patches. * * @see `CGAL::Polygon_mesh_processing::detect_sharp_edges()` * @see `CGAL::Polygon_mesh_processing::connected_components()` - * @see `CGAL::Polygon_mesh_processing::detect_incident_patches()` + * @see `CGAL::Polygon_mesh_processing::detect_vertex_incident_patches()` */ #ifdef DOXYGEN_RUNNING -template +template #else -template +template #endif -std::size_t detect_features(PolygonMesh& pmesh, +typename boost::graph_traits::faces_size_type +sharp_edges_segmentation(PolygonMesh& pmesh, #ifdef DOXYGEN_RUNNING FT angle_in_deg, #else typename GetGeomTraits::type::FT angle_in_deg, #endif PatchIdMap& patch_id_map, - VertexIncidentPatchesMap& vertex_incident_patches_map, const NamedParameters& np) { - detect_sharp_edges(pmesh,angle_in_deg, np); - std::size_t result = internal::detect_surface_patches(pmesh, patch_id_map, np); - detect_incident_patches(pmesh, patch_id_map, vertex_incident_patches_map, np); + typedef typename boost::lookup_named_param_def < + internal_np::edge_is_constrained_t, + NamedParameters, + typename boost::associative_property_map::edge_descriptor, + bool> >//default + > ::type EIF_map; + std::map::edge_descriptor, bool> def_map; + EIF_map eif + = boost::choose_param(get_param(np, internal_np::edge_is_constrained), + boost::make_assoc_property_map(def_map)); + + typedef typename boost::lookup_named_param_def < + internal_np::vertex_incident_patches_t, + NamedParameters, + typename boost::property_map::value_type > >::type //default + > ::type VIP_map; + + VIP_map vip + = boost::choose_param(get_param(np, internal_np::vertex_incident_patches), + get(CGAL::vertex_incident_patches_t< + typename boost::property_traits::value_type >(), pmesh)); + + detect_sharp_edges(pmesh,angle_in_deg, eif, np); + typename boost::graph_traits::faces_size_type result = + internal::detect_surface_patches(pmesh, patch_id_map, eif, np); + const bool is_default= boost::is_default_param(get_param(np, internal_np::vertex_incident_patches)); + if(is_default) + internal::vip_caller().call(pmesh, patch_id_map, vip, eif); + else + internal::vip_caller().call(pmesh, patch_id_map, vip, eif); return result; } //Convenient overrides -template +template void detect_sharp_edges(PolygonMesh& p, - FT angle_in_deg) + FT angle_in_deg, + EdgeIsFeatureMap& edge_is_feature_map) { - detect_sharp_edges(p, angle_in_deg, parameters::all_default()); + detect_sharp_edges(p, angle_in_deg, edge_is_feature_map, parameters::all_default()); } -template -void detect_incident_patches(PolygonMesh& p, - PatchIdMap& patch_id_map, - VertexIncidentPatchesMap& vertex_incident_patches_map) -{ - detect_incident_patches(p, patch_id_map, vertex_incident_patches_map, parameters::all_default()); -} template -std::size_t detect_features(PolygonMesh& p, +std::size_t sharp_edges_segmentation(PolygonMesh& p, FT angle_in_deg, PatchIdMap& patch_id_map, VertexIncidentPatchesMap& vertex_incident_patches_map) { - return detect_features(p,angle_in_deg, patch_id_map, vertex_incident_patches_map, parameters::all_default()); + return sharp_edges_segmentation(p,angle_in_deg, patch_id_map, vertex_incident_patches_map, parameters::all_default()); } diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_detect_features.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_detect_features.cpp index bd36c588f81..796d96e1d89 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_detect_features.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_detect_features.cpp @@ -8,6 +8,7 @@ typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef CGAL::Surface_mesh Mesh; typedef boost::graph_traits::face_descriptor face_descriptor; +typedef boost::graph_traits::vertex_descriptor vertex_descriptor; namespace PMP = CGAL::Polygon_mesh_processing; @@ -28,9 +29,10 @@ int main(int argc, char* argv[]) PatchID pid = get(CGAL::face_patch_id_t(), mesh); typedef boost::property_map >::type VIP; VIP vip = get(CGAL::vertex_incident_patches_t(), mesh); - std::size_t number_of_patches = PMP::detect_features(mesh, 90, pid, vip); typedef boost::property_map::type EIF_map; EIF_map eif = get(CGAL::edge_is_feature, mesh); + std::size_t number_of_patches = PMP::sharp_edges_segmentation(mesh, 90, pid, + PMP::parameters::edge_is_constrained_map(eif)); int nb_sharp_edges =0; BOOST_FOREACH(boost::graph_traits::edge_descriptor e, edges(mesh)) { @@ -42,22 +44,13 @@ int main(int argc, char* argv[]) CGAL_assertion(nb_sharp_edges == 12); CGAL_assertion(number_of_patches == 6); - number_of_patches = PMP::detect_features(mesh, 90, pid, vip, PMP::parameters::first_index(1) - .edge_is_constrained_map(eif)); - nb_sharp_edges =0; - BOOST_FOREACH(boost::graph_traits::edge_descriptor e, edges(mesh)) - { - if(get(eif, e)) - ++nb_sharp_edges; - } - - - CGAL_assertion(nb_sharp_edges == 12); + number_of_patches = PMP::sharp_edges_segmentation(mesh, 90, pid, PMP::parameters::first_index(1) + .vertex_incident_patches_map(vip)); CGAL_assertion(number_of_patches == 6); - PMP::detect_sharp_edges(mesh, 90); - number_of_patches = PMP::internal::detect_surface_patches(mesh, pid); - PMP::detect_incident_patches(mesh, pid, vip); + PMP::detect_sharp_edges(mesh, 90, eif); + number_of_patches = PMP::internal::detect_surface_patches(mesh, pid, eif); + PMP::detect_vertex_incident_patches(mesh, pid, vip, eif); nb_sharp_edges =0; BOOST_FOREACH(boost::graph_traits::edge_descriptor e, edges(mesh)) @@ -69,9 +62,14 @@ int main(int argc, char* argv[]) CGAL_assertion(nb_sharp_edges == 12); CGAL_assertion(number_of_patches == 6); - PMP::detect_sharp_edges(mesh, 90, PMP::parameters::edge_is_constrained_map(eif)); - number_of_patches = PMP::internal::detect_surface_patches(mesh, pid, PMP::parameters::first_index(1)); - PMP::detect_incident_patches(mesh, pid, vip, PMP::parameters::edge_is_constrained_map(eif)); + + Mesh::Property_map > patch_id_map + = mesh.add_property_map >("f:pid",std::pair()).first; + Mesh::Property_map > > vertex_incident_patch_map + = mesh.add_property_map > >("f:vip",std::set >()).first; + PMP::detect_sharp_edges(mesh, 90, eif); + number_of_patches = PMP::internal::detect_surface_patches(mesh, patch_id_map, eif, PMP::parameters::first_index(1)); + PMP::detect_vertex_incident_patches(mesh, patch_id_map, vertex_incident_patch_map, eif); nb_sharp_edges =0; BOOST_FOREACH(boost::graph_traits::edge_descriptor e, edges(mesh)) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Detect_sharp_edges_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Detect_sharp_edges_plugin.cpp index 7c3692847d2..6fc3b5d096c 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Detect_sharp_edges_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Detect_sharp_edges_plugin.cpp @@ -135,8 +135,12 @@ void Polyhedron_demo_detect_sharp_edges_plugin::detectSharpEdges(bool input_dial PatchID pid = get(CGAL::face_patch_id_t(), *pMesh); typedef boost::property_map >::type VIP; VIP vip = get(CGAL::vertex_incident_patches_t(), *pMesh); - first_patch+=PMP::detect_features(*pMesh, angle, pid, vip, - PMP::parameters::first_index(first_patch)); + typename boost::property_map::type eif = + get(CGAL::edge_is_feature, *pMesh); + first_patch+=PMP::sharp_edges_segmentation(*pMesh, angle, pid, + PMP::parameters::first_index(first_patch) + .edge_is_constrained_map(eif) + .vertex_incident_patches_map(vip)); //update item item->setItemIsMulticolor(true); #ifndef USE_SURFACE_MESH diff --git a/Polyhedron/demo/Polyhedron/Polyhedron_demo_detect_sharp_edges.h b/Polyhedron/demo/Polyhedron/Polyhedron_demo_detect_sharp_edges.h index 9d1d95be3f6..f697d67a50a 100644 --- a/Polyhedron/demo/Polyhedron/Polyhedron_demo_detect_sharp_edges.h +++ b/Polyhedron/demo/Polyhedron/Polyhedron_demo_detect_sharp_edges.h @@ -25,11 +25,9 @@ namespace CGAL // Detect edges in current polyhedron typedef typename boost::property_map >::type PIDMap; typedef typename boost::property_map >::type VIPMap; - PIDMap pid_map = get(face_patch_id_t(), *pMesh); - VIPMap vip_map = get(vertex_incident_patches_t(), *pMesh); - - - CGAL::Polygon_mesh_processing::detect_sharp_edges(*pMesh, angle); + typename boost::property_map::type eif = + get(CGAL::edge_is_feature, *pMesh); + CGAL::Polygon_mesh_processing::detect_sharp_edges(*pMesh, angle, eif); } }//end namespace CGAL