mirror of https://github.com/CGAL/cgal
Implementation review Jane and sebastien
This commit is contained in:
parent
080d3a0895
commit
43ff0d092c
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -823,8 +823,10 @@ detect_features(FT angle_in_degree,
|
|||
typedef typename boost::property_map<Polyhedron_type,CGAL::vertex_incident_patches_t<Patch_id> >::type VIPMap;
|
||||
PIDMap pid_map = get(face_patch_id_t<Patch_id>(), p);
|
||||
VIPMap vip_map = get(vertex_incident_patches_t<Patch_id>(), 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<Polyhedron_type> is_featured_edge(p);
|
||||
|
||||
|
|
|
|||
|
|
@ -466,8 +466,10 @@ detect_features(FT angle_in_degree, std::vector<Polyhedron>& poly)
|
|||
PIDMap pid_map = get(face_patch_id_t<P_id>(), p);
|
||||
VIPMap vip_map = get(vertex_incident_patches_t<P_id>(), 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<Polyhedron> is_featured_edge(p);
|
||||
|
|
|
|||
|
|
@ -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<PolygonMesh>::%vertex_descriptor` as key type.Its value type
|
||||
must be a container of `boost::property_traits<PatchIdMap>::%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
|
||||
|
||||
|
|
|
|||
|
|
@ -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`
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -30,9 +30,11 @@ int main(int argc, char* argv[])
|
|||
typedef boost::property_map<Mesh,CGAL::vertex_incident_patches_t<int> >::type VIMap;
|
||||
VIMap vip = get(CGAL::vertex_incident_patches_t<int>(), mesh);
|
||||
std::size_t number_of_patches = 1;
|
||||
number_of_patches=PMP::detect_features(mesh, 90, pid, vip);
|
||||
typedef boost::property_map<Mesh,CGAL::edge_is_feature_t>::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<Mesh>::edge_descriptor e, edges(mesh))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -75,98 +75,193 @@ is_sharp(PolygonMesh& polygonMesh,
|
|||
|
||||
|
||||
//wrapper for patchid map.
|
||||
template<typename PatchIdMap>
|
||||
template<typename PatchIdMap, typename ValueType = typename boost::property_traits<PatchIdMap>::value_type>
|
||||
struct PatchIdMapWrapper
|
||||
{
|
||||
typedef typename boost::property_traits<PatchIdMap>::category category;
|
||||
typedef typename boost::property_traits<PatchIdMap>::value_type value_type;
|
||||
typedef ValueType value_type;
|
||||
typedef typename boost::property_traits<PatchIdMap>::reference reference;
|
||||
typedef typename boost::property_traits<PatchIdMap>::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 PatchIdMap, typename Handle_type>
|
||||
typename PatchIdMapWrapper<PatchIdMap>::value_type get(PatchIdMapWrapper<PatchIdMap>& map, Handle_type h)
|
||||
|
||||
template <typename PatchIdMap, typename Handle_type, typename Int>
|
||||
typename PatchIdMapWrapper<PatchIdMap, Int>::value_type get(PatchIdMapWrapper<PatchIdMap, Int>& map, Handle_type h)
|
||||
{
|
||||
return get(map.map, h) - map.offset;
|
||||
}
|
||||
|
||||
template <typename PatchIdMap, typename Handle_type>
|
||||
void put(PatchIdMapWrapper<PatchIdMap>& map, Handle_type h,
|
||||
typename PatchIdMapWrapper<PatchIdMap>::value_type pid)
|
||||
template <typename PatchIdMap, typename Handle_type, typename Int>
|
||||
void put(PatchIdMapWrapper<PatchIdMap, Int>& map, Handle_type h,
|
||||
typename PatchIdMapWrapper<PatchIdMap, Int>::value_type pid)
|
||||
{
|
||||
put(map.map, h, pid + map.offset);
|
||||
}
|
||||
|
||||
template <typename PolygonMesh, typename PatchIdMap, typename NamedParameters>
|
||||
|
||||
//specialization for std::pair
|
||||
template<typename PatchIdMap, typename Int>
|
||||
struct PatchIdMapWrapper<PatchIdMap, std::pair<Int, Int> >
|
||||
{
|
||||
typedef typename boost::property_traits<PatchIdMap>::category category;
|
||||
typedef Int value_type;
|
||||
typedef typename boost::property_traits<PatchIdMap>::reference reference;
|
||||
typedef typename boost::property_traits<PatchIdMap>::key_type key_type;
|
||||
|
||||
PatchIdMap map;
|
||||
int offset;
|
||||
PatchIdMapWrapper(PatchIdMap& map, int offset)
|
||||
:map(map), offset(offset){}
|
||||
};
|
||||
|
||||
template <typename PatchIdMap, typename Handle_type, typename Int>
|
||||
typename PatchIdMapWrapper<PatchIdMap, std::pair<Int, Int> >::value_type get(PatchIdMapWrapper<PatchIdMap,
|
||||
std::pair<Int, Int> >& map, Handle_type h)
|
||||
{
|
||||
return get(map.map, h).first - map.offset;
|
||||
}
|
||||
|
||||
template <typename PatchIdMap, typename Handle_type, typename Int>
|
||||
void put(PatchIdMapWrapper<PatchIdMap, std::pair<Int, Int> >& map, Handle_type h,
|
||||
typename PatchIdMapWrapper<PatchIdMap, std::pair<Int, Int> >::value_type pid)
|
||||
{
|
||||
put(map.map, h, std::pair<Int, Int>(pid+map.offset, 0));
|
||||
}
|
||||
|
||||
template <typename PolygonMesh, typename PatchIdMap, typename EdgeIsFeatureMap, typename NamedParameters>
|
||||
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<PolygonMesh,CGAL::edge_is_feature_t>::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<PolygonMesh, NamedParameters>::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<int>(
|
||||
boost::choose_param(get_param(np, internal_np::first_index),
|
||||
1));
|
||||
|
||||
internal::PatchIdMapWrapper<PatchIdMap> wrapmap(patch_id_map, offset);
|
||||
internal::PatchIdMapWrapper<PatchIdMap,
|
||||
typename boost::property_traits<PatchIdMap>::value_type> wrapmap(patch_id_map, offset);
|
||||
return connected_components(p, wrapmap, parameters::edge_is_constrained_map(eif)
|
||||
.face_index_map(fimap));
|
||||
|
||||
}
|
||||
template <typename PolygonMesh, typename PatchIdMap>
|
||||
template <typename PolygonMesh, typename EdgeIsFeatureMap, typename PatchIdMap>
|
||||
typename boost::graph_traits<PolygonMesh>::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 <bool b>
|
||||
struct sharp_caller
|
||||
{
|
||||
template<typename PolygonMesh,
|
||||
typename GT,
|
||||
typename EIFMap,
|
||||
typename VNFEMap>
|
||||
static void call(PolygonMesh& pmesh,
|
||||
typename GetGeomTraits<PolygonMesh, GT>::type::FT angle_in_deg,
|
||||
EIFMap& edge_is_feature_map,
|
||||
VNFEMap& vnfe)
|
||||
{
|
||||
typedef typename GetGeomTraits<PolygonMesh, GT>::type::FT FT;
|
||||
// Initialize vertices
|
||||
BOOST_FOREACH(typename boost::graph_traits<PolygonMesh>::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<PolygonMesh>::edge_descriptor ed, edges(pmesh))
|
||||
{
|
||||
typename boost::graph_traits<PolygonMesh>::halfedge_descriptor he = halfedge(ed,pmesh);
|
||||
if(is_border(he,pmesh) || angle_in_deg == FT() ||
|
||||
(angle_in_deg != FT(180) && internal::is_sharp<PolygonMesh, GT>(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<false>
|
||||
{
|
||||
template<typename PolygonMesh,
|
||||
typename GT,
|
||||
typename EIFMap,
|
||||
typename VNFEMap>
|
||||
static void call(PolygonMesh& pmesh,
|
||||
typename GetGeomTraits<PolygonMesh, GT>::type::FT angle_in_deg,
|
||||
EIFMap& edge_is_feature_map,
|
||||
VNFEMap&)
|
||||
{
|
||||
typedef typename GetGeomTraits<PolygonMesh, GT>::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<PolygonMesh>::edge_descriptor ed, edges(pmesh))
|
||||
{
|
||||
typename boost::graph_traits<PolygonMesh>::halfedge_descriptor he = halfedge(ed,pmesh);
|
||||
if(is_border(he,pmesh) || angle_in_deg == FT() ||
|
||||
(angle_in_deg != FT(180) && internal::is_sharp<PolygonMesh, GT>(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<PolygonMesh>::%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 <typename PolygonMesh, typename FT, typename NamedParameters>
|
||||
#else
|
||||
template <typename PolygonMesh, typename NamedParameters>
|
||||
template <typename PolygonMesh, typename EdgeIsFeatureMap, typename NamedParameters>
|
||||
#endif
|
||||
void detect_sharp_edges(PolygonMesh& pmesh,
|
||||
#ifdef DOXYGEN_RUNNING
|
||||
|
|
@ -174,17 +269,10 @@ void detect_sharp_edges(PolygonMesh& pmesh,
|
|||
#else
|
||||
typename GetGeomTraits<PolygonMesh, NamedParameters>::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<PolygonMesh,edge_is_feature_t>::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<PolygonMesh, NamedParameters>::type GT;
|
||||
typedef typename GT::FT FT;
|
||||
|
||||
// Initialize vertices
|
||||
|
||||
BOOST_FOREACH(typename boost::graph_traits<PolygonMesh>::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<PolygonMesh>::edge_descriptor ed, edges(pmesh))
|
||||
{
|
||||
typename boost::graph_traits<PolygonMesh>::halfedge_descriptor he = halfedge(ed,pmesh);
|
||||
if(is_border(he,pmesh) || angle_in_deg == FT() ||
|
||||
(angle_in_deg != FT(180) && internal::is_sharp<PolygonMesh, GT>(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<false>().call<PolygonMesh, GT, EdgeIsFeatureMap, VNFE_map>(pmesh, angle_in_deg, edge_is_feature_map, vnfe);
|
||||
else
|
||||
internal::sharp_caller<true>().call<PolygonMesh, GT, EdgeIsFeatureMap, VNFE_map>(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<PolygonMesh>::%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<PolygonMesh>::%vertex_descriptor` as key type. Its value type
|
||||
must be a container of `boost::property_traits<PatchIdMap>::%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<PolygonMesh>::%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 <typename PolygonMesh, typename PatchIdMap, typename VertexIncidentPatchesMap, typename NamedParameters>
|
||||
void detect_incident_patches(PolygonMesh& pmesh,
|
||||
template <typename PolygonMesh, typename PatchIdMap, typename VertexIncidentPatchesMap, typename EdgeIsFeatureMap>
|
||||
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<PolygonMesh,edge_is_feature_t>::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<PolygonMesh>::vertex_descriptor vertex_descriptor;
|
||||
typedef typename boost::graph_traits<PolygonMesh>::halfedge_descriptor halfedge_descriptor;
|
||||
|
||||
typedef typename boost::property_traits<PatchIdMap>::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 <bool b>
|
||||
struct vip_caller
|
||||
{
|
||||
template<typename PolygonMesh,
|
||||
typename PIDMap,
|
||||
typename VIPMap,
|
||||
typename EIFMap>
|
||||
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<false>
|
||||
{
|
||||
template<typename PolygonMesh,
|
||||
typename PIDMap,
|
||||
typename VIPMap,
|
||||
typename EIFMap>
|
||||
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<PolygonMesh>::%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<PolygonMesh>::%vertex_descriptor` as key type. Its value type
|
||||
must be a container of `boost::property_traits<PatchIdMap>::%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 <typename PolygonMesh, typename FT, typename PatchIdMap, typename VertexIncidentPatchesMap, typename NamedParameters>
|
||||
template <typename PolygonMesh, typename FT, typename PatchIdMap, typename NamedParameters>
|
||||
#else
|
||||
template <typename PolygonMesh, typename PatchIdMap, typename VertexIncidentPatchesMap, typename NamedParameters>
|
||||
template <typename PolygonMesh, typename PatchIdMap, typename NamedParameters>
|
||||
#endif
|
||||
std::size_t detect_features(PolygonMesh& pmesh,
|
||||
typename boost::graph_traits<PolygonMesh>::faces_size_type
|
||||
sharp_edges_segmentation(PolygonMesh& pmesh,
|
||||
#ifdef DOXYGEN_RUNNING
|
||||
FT angle_in_deg,
|
||||
#else
|
||||
typename GetGeomTraits<PolygonMesh, NamedParameters>::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<std::map<
|
||||
typename boost::graph_traits<PolygonMesh>::edge_descriptor,
|
||||
bool> >//default
|
||||
> ::type EIF_map;
|
||||
std::map<typename boost::graph_traits<PolygonMesh>::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<PolygonMesh,CGAL::vertex_incident_patches_t<
|
||||
typename boost::property_traits<PatchIdMap>::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<PatchIdMap>::value_type >(), pmesh));
|
||||
|
||||
detect_sharp_edges(pmesh,angle_in_deg, eif, np);
|
||||
typename boost::graph_traits<PolygonMesh>::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<false>().call(pmesh, patch_id_map, vip, eif);
|
||||
else
|
||||
internal::vip_caller<true>().call(pmesh, patch_id_map, vip, eif);
|
||||
return result;
|
||||
}
|
||||
|
||||
//Convenient overrides
|
||||
template <typename PolygonMesh, typename FT>
|
||||
template <typename PolygonMesh, typename EdgeIsFeatureMap, typename FT>
|
||||
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 <typename PolygonMesh, typename PatchIdMap, typename VertexIncidentPatchesMap>
|
||||
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 <typename PolygonMesh, typename FT, typename PatchIdMap, typename VertexIncidentPatchesMap>
|
||||
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());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
|
||||
typedef CGAL::Surface_mesh<K::Point_3> Mesh;
|
||||
typedef boost::graph_traits<Mesh>::face_descriptor face_descriptor;
|
||||
typedef boost::graph_traits<Mesh>::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<int>(), mesh);
|
||||
typedef boost::property_map<Mesh,CGAL::vertex_incident_patches_t<int> >::type VIP;
|
||||
VIP vip = get(CGAL::vertex_incident_patches_t<int>(), mesh);
|
||||
std::size_t number_of_patches = PMP::detect_features(mesh, 90, pid, vip);
|
||||
typedef boost::property_map<Mesh,CGAL::edge_is_feature_t>::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<Mesh>::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<Mesh>::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<Mesh>::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<face_descriptor,std::pair<int, int> > patch_id_map
|
||||
= mesh.add_property_map<face_descriptor,std::pair<int, int> >("f:pid",std::pair<int,int>()).first;
|
||||
Mesh::Property_map<vertex_descriptor,std::set<std::pair<int, int> > > vertex_incident_patch_map
|
||||
= mesh.add_property_map<vertex_descriptor,std::set<std::pair<int, int> > >("f:vip",std::set<std::pair<int, int> >()).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<Mesh>::edge_descriptor e, edges(mesh))
|
||||
|
|
|
|||
|
|
@ -135,8 +135,12 @@ void Polyhedron_demo_detect_sharp_edges_plugin::detectSharpEdges(bool input_dial
|
|||
PatchID pid = get(CGAL::face_patch_id_t<int>(), *pMesh);
|
||||
typedef boost::property_map<FaceGraph,CGAL::vertex_incident_patches_t<int> >::type VIP;
|
||||
VIP vip = get(CGAL::vertex_incident_patches_t<int>(), *pMesh);
|
||||
first_patch+=PMP::detect_features(*pMesh, angle, pid, vip,
|
||||
PMP::parameters::first_index(first_patch));
|
||||
typename boost::property_map<FaceGraph, CGAL::edge_is_feature_t>::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
|
||||
|
|
|
|||
|
|
@ -25,11 +25,9 @@ namespace CGAL
|
|||
// Detect edges in current polyhedron
|
||||
typedef typename boost::property_map<Polyhedron,CGAL::face_patch_id_t<int> >::type PIDMap;
|
||||
typedef typename boost::property_map<Polyhedron,CGAL::vertex_incident_patches_t<int> >::type VIPMap;
|
||||
PIDMap pid_map = get(face_patch_id_t<int>(), *pMesh);
|
||||
VIPMap vip_map = get(vertex_incident_patches_t<int>(), *pMesh);
|
||||
|
||||
|
||||
CGAL::Polygon_mesh_processing::detect_sharp_edges(*pMesh, angle);
|
||||
typename boost::property_map<Polyhedron,edge_is_feature_t>::type eif =
|
||||
get(CGAL::edge_is_feature, *pMesh);
|
||||
CGAL::Polygon_mesh_processing::detect_sharp_edges(*pMesh, angle, eif);
|
||||
}
|
||||
|
||||
}//end namespace CGAL
|
||||
|
|
|
|||
Loading…
Reference in New Issue