mirror of https://github.com/CGAL/cgal
Make functions free functions and wright doc
This commit is contained in:
parent
95dfae314b
commit
d588c55bbb
|
|
@ -23,7 +23,9 @@ 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(edge_index_t, edge_index, edge_index_map)
|
||||||
CGAL_add_named_parameter(halfedge_index_t, halfedge_index, halfedge_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(edge_is_constrained_t, edge_is_constrained, edge_is_constrained_map)
|
||||||
CGAL_add_named_parameter(face_patch_id_t, face_patch_id, face_patch_id_map)
|
CGAL_add_named_parameter(vertex_num_feature_edges_t, vertex_num_feature_edges, vertex_num_feature_edges_map)
|
||||||
|
CGAL_add_named_parameter(halfedge_is_feature_t, halfedge_is_feature, halfedge_is_feature_map)
|
||||||
|
CGAL_add_named_parameter(maximum_number_of_patches_t, maximum_number_of_patches, maximum_number_of_patches)
|
||||||
CGAL_add_named_parameter(set_cache_policy_t, set_cache_policy, set_cache)
|
CGAL_add_named_parameter(set_cache_policy_t, set_cache_policy, set_cache)
|
||||||
CGAL_add_named_parameter(get_cost_policy_t, get_cost_policy, get_cost)
|
CGAL_add_named_parameter(get_cost_policy_t, get_cost_policy, get_cost)
|
||||||
CGAL_add_named_parameter(get_cost_policy_params_t, get_cost_policy_params, get_cost_params)
|
CGAL_add_named_parameter(get_cost_policy_params_t, get_cost_policy_params, get_cost_params)
|
||||||
|
|
|
||||||
|
|
@ -799,7 +799,7 @@ detect_features(FT angle_in_degree,
|
||||||
P2vmap p2vmap;
|
P2vmap p2vmap;
|
||||||
|
|
||||||
namespace PMP = CGAL::Polygon_mesh_processing;
|
namespace PMP = CGAL::Polygon_mesh_processing;
|
||||||
PMP::Detect_features_in_polygon_mesh<Polyhedron_type, Surface_patch_index> detect_features;
|
std::size_t nb_of_patch_plus_one = 1;
|
||||||
BOOST_FOREACH(Polyhedron_type& p, poly)
|
BOOST_FOREACH(Polyhedron_type& p, poly)
|
||||||
{
|
{
|
||||||
initialize_ts(p);
|
initialize_ts(p);
|
||||||
|
|
@ -812,16 +812,17 @@ detect_features(FT angle_in_degree,
|
||||||
#endif // CGAL_MESH_3_VERBOSE
|
#endif // CGAL_MESH_3_VERBOSE
|
||||||
|
|
||||||
// Get sharp features
|
// Get sharp features
|
||||||
detect_features.detect_sharp_edges(p, angle_in_degree);
|
typedef typename boost::property_map<Polyhedron_type,CGAL::face_patch_id_t<Patch_id> >::type PIDMap;
|
||||||
detect_features.detect_surface_patches(p);
|
typedef typename boost::property_map<Polyhedron_type,CGAL::vertex_incident_patches_t<Patch_id> >::type VIPMap;
|
||||||
detect_features.detect_vertices_incident_patches(p);
|
PIDMap pid_map = get(face_patch_id_t<Patch_id>(), p);
|
||||||
|
VIPMap vip_map = get(vertex_incident_patches_t<Patch_id>(), p);
|
||||||
|
CGAL::Polygon_mesh_processing::detect_features(p, angle_in_degree,pid_map, vip_map,
|
||||||
|
CGAL::Polygon_mesh_processing::parameters::maximum_number_of_patches(&nb_of_patch_plus_one));
|
||||||
|
|
||||||
internal::Mesh_3::Is_featured_edge<Polyhedron_type> is_featured_edge(p);
|
internal::Mesh_3::Is_featured_edge<Polyhedron_type> is_featured_edge(p);
|
||||||
|
|
||||||
add_featured_edges_to_graph(p, is_featured_edge, g_copy, p2vmap);
|
add_featured_edges_to_graph(p, is_featured_edge, g_copy, p2vmap);
|
||||||
}
|
}
|
||||||
const std::size_t nb_of_patch_plus_one =
|
|
||||||
detect_features.maximal_surface_patch_index()+1;
|
|
||||||
this->patch_id_to_polyhedron_id.resize(nb_of_patch_plus_one);
|
this->patch_id_to_polyhedron_id.resize(nb_of_patch_plus_one);
|
||||||
this->patch_has_featured_edges.resize(nb_of_patch_plus_one);
|
this->patch_has_featured_edges.resize(nb_of_patch_plus_one);
|
||||||
this->several_vertices_on_patch.resize(nb_of_patch_plus_one);
|
this->several_vertices_on_patch.resize(nb_of_patch_plus_one);
|
||||||
|
|
|
||||||
|
|
@ -448,23 +448,23 @@ detect_features(FT angle_in_degree, std::vector<Polyhedron>& poly)
|
||||||
vertex_descriptor> P2vmap;
|
vertex_descriptor> P2vmap;
|
||||||
// TODO: replace this map by and unordered_map
|
// TODO: replace this map by and unordered_map
|
||||||
P2vmap p2vmap;
|
P2vmap p2vmap;
|
||||||
|
|
||||||
CGAL::Polygon_mesh_processing::Detect_features_in_polygon_mesh<Polyhedron,Surface_patch_index> detect_features;
|
|
||||||
BOOST_FOREACH(Polyhedron& p, poly)
|
BOOST_FOREACH(Polyhedron& p, poly)
|
||||||
{
|
{
|
||||||
initialize_ts(p);
|
initialize_ts(p);
|
||||||
|
typedef typename boost::property_map<Polyhedron,CGAL::face_patch_id_t<Patch_id> >::type PIDMap;
|
||||||
|
typedef typename boost::property_map<Polyhedron,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);
|
||||||
// Get sharp features
|
// Get sharp features
|
||||||
detect_features.detect_sharp_edges(p, angle_in_degree);
|
CGAL::Polygon_mesh_processing::detect_features(p, angle_in_degree,pid_map, vip_map);
|
||||||
detect_features.detect_surface_patches(p);
|
|
||||||
detect_features.detect_vertices_incident_patches(p);
|
|
||||||
|
|
||||||
internal::Mesh_3::Is_featured_edge<Polyhedron> is_featured_edge(p);
|
internal::Mesh_3::Is_featured_edge<Polyhedron> is_featured_edge(p);
|
||||||
|
|
||||||
add_featured_edges_to_graph(p, is_featured_edge, g_copy, p2vmap);
|
add_featured_edges_to_graph(p, is_featured_edge, g_copy, p2vmap);
|
||||||
}
|
}
|
||||||
add_features_from_split_graph_into_polylines(g_copy);
|
add_features_from_split_graph_into_polylines(g_copy);
|
||||||
borders_detected_ = true;/*done by Mesh_3::detect_features*/
|
borders_detected_ = true;/*done by PMP::detect_features*/
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename GT_, typename P_, typename TA_,
|
template < typename GT_, typename P_, typename TA_,
|
||||||
|
|
|
||||||
|
|
@ -152,6 +152,30 @@ the property map containing information about edges of the input polygon mesh be
|
||||||
a default property map where no edge is constrained is provided.
|
a default property map where no edge is constrained is provided.
|
||||||
\cgalNPEnd
|
\cgalNPEnd
|
||||||
|
|
||||||
|
\cgalNPBegin{ maximum_number_of_patches } \anchor PMP_maximum_number_of_patches
|
||||||
|
contains the surface patch beeing treated +1.\n
|
||||||
|
\b Type : `std::size_t`* \n
|
||||||
|
\b Default : a pointer to a `std::size_t` with value 1.
|
||||||
|
\cgalNPEnd
|
||||||
|
|
||||||
|
\cgalNPBegin{ halfedge_is_feature_map } \anchor PMP_halfedge_is_feature_map
|
||||||
|
the property map containing information about halfedges of the input polygon mesh being featured or not.\n
|
||||||
|
\b Type : a class model of `ReadWritePropertyMap` with
|
||||||
|
`boost::graph_traits<PolygonMesh>::%halfedge_descriptor` as key type and
|
||||||
|
`bool` as value type. It should be default constructible.\n
|
||||||
|
\b Default value is \code boost::get(CGAL::halfedge_is_feature, pmesh)\endcode
|
||||||
|
\cgalNPEnd
|
||||||
|
|
||||||
|
\cgalNPBegin{ vertex_num_feature_edges_map } \anchor PMP_vertex_num_feature_edges_map
|
||||||
|
the property map containing the number of feature edges being incident to the vertices of the polygon mesh `pmesh`.\n
|
||||||
|
\b Type : a class model of `ReadWritePropertyMap` with
|
||||||
|
`boost::graph_traits<PolygonMesh>::%vertex_descriptor` as key type and
|
||||||
|
`int` as value type. It should be default constructible.\n
|
||||||
|
\b Default value is \code boost::get(CGAL::vertex_num_feature_edges_t(), pmesh)\endcode
|
||||||
|
\cgalNPEnd
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
\cgalNPBegin{ vertex_is_constrained_map } \anchor PMP_vertex_is_constrained_map
|
\cgalNPBegin{ vertex_is_constrained_map } \anchor PMP_vertex_is_constrained_map
|
||||||
the property map containing information about vertices of the input polygon mesh being constrained or not.
|
the property map containing information about vertices of the input polygon mesh being constrained or not.
|
||||||
Constrained vertices may be replaced by new vertices, but the number and location
|
Constrained vertices may be replaced by new vertices, but the number and location
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,9 @@
|
||||||
/// of the bounded volumes.
|
/// of the bounded volumes.
|
||||||
/// \ingroup PkgPolygonMeshProcessing
|
/// \ingroup PkgPolygonMeshProcessing
|
||||||
|
|
||||||
|
/// \defgroup PMP_detect_features_grp Detect Features Functions
|
||||||
|
/// Functions to detect sharp edges and surface patch ids of polygon meshes.
|
||||||
|
/// \ingroup PkgPolygonMeshProcessing
|
||||||
/*!
|
/*!
|
||||||
\addtogroup PkgPolygonMeshProcessing
|
\addtogroup PkgPolygonMeshProcessing
|
||||||
|
|
||||||
|
|
@ -150,6 +153,12 @@ and provides a list of the parameters that are used in this package.
|
||||||
- `CGAL::Polygon_mesh_processing::max_distance_to_triangle_mesh()`
|
- `CGAL::Polygon_mesh_processing::max_distance_to_triangle_mesh()`
|
||||||
- `CGAL::Polygon_mesh_processing::sample_triangle_mesh()`
|
- `CGAL::Polygon_mesh_processing::sample_triangle_mesh()`
|
||||||
|
|
||||||
|
##Detect Features Functions ##
|
||||||
|
- `CGAL::Polygon_mesh_processing::detect_features()`
|
||||||
|
- `CGAL::Polygon_mesh_processing::detect_sharp_edges()`
|
||||||
|
- `CGAL::Polygon_mesh_processing::detect_surface_patches()`
|
||||||
|
- `CGAL::Polygon_mesh_processing::detect_vertices_incident_patches()`
|
||||||
|
|
||||||
## Miscellaneous ##
|
## Miscellaneous ##
|
||||||
- `CGAL::Polygon_mesh_slicer`
|
- `CGAL::Polygon_mesh_slicer`
|
||||||
- `CGAL::Side_of_triangle_mesh`
|
- `CGAL::Side_of_triangle_mesh`
|
||||||
|
|
|
||||||
|
|
@ -106,6 +106,7 @@ create_single_source_cgal_program( "corefinement_polyhedron_union.cpp" )
|
||||||
create_single_source_cgal_program( "random_perturbation_SM_example.cpp" )
|
create_single_source_cgal_program( "random_perturbation_SM_example.cpp" )
|
||||||
create_single_source_cgal_program( "corefinement_LCC.cpp")
|
create_single_source_cgal_program( "corefinement_LCC.cpp")
|
||||||
create_single_source_cgal_program( "hole_filling_example_LCC.cpp" )
|
create_single_source_cgal_program( "hole_filling_example_LCC.cpp" )
|
||||||
|
create_single_source_cgal_program( "detect_features_example.cpp" )
|
||||||
|
|
||||||
if(OpenMesh_FOUND)
|
if(OpenMesh_FOUND)
|
||||||
create_single_source_cgal_program( "compute_normals_example_OM.cpp" )
|
create_single_source_cgal_program( "compute_normals_example_OM.cpp" )
|
||||||
|
|
|
||||||
|
|
@ -26,318 +26,461 @@
|
||||||
|
|
||||||
|
|
||||||
#include <CGAL/Kernel/global_functions_3.h>
|
#include <CGAL/Kernel/global_functions_3.h>
|
||||||
#include <CGAL/Polygon_mesh_processing/Detect_features_in_polygon_mesh_fwd.h>
|
|
||||||
#include <CGAL/Compare_handles_with_or_without_timestamps.h>
|
|
||||||
#include <CGAL/Polygon_mesh_processing/compute_normal.h>
|
#include <CGAL/Polygon_mesh_processing/compute_normal.h>
|
||||||
|
#include <CGAL/Polygon_mesh_processing/internal/named_params_helper.h>
|
||||||
#include <CGAL/Mesh_3/properties.h>
|
#include <CGAL/Mesh_3/properties.h>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
namespace CGAL {
|
namespace CGAL {
|
||||||
namespace Polygon_mesh_processing {
|
namespace Polygon_mesh_processing {
|
||||||
|
|
||||||
|
namespace internal
|
||||||
|
{
|
||||||
|
template <typename Int>
|
||||||
|
Int
|
||||||
|
generate_patch_id(Int, int i)
|
||||||
|
{
|
||||||
|
return Int(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Int>
|
||||||
|
std::pair<Int, Int>
|
||||||
|
generate_patch_id(std::pair<Int, Int>, int i)
|
||||||
|
{
|
||||||
|
return std::pair<Int, Int>(i, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename PolygonMesh, typename GT>
|
||||||
|
typename GT::Vector_3
|
||||||
|
facet_normal(const PolygonMesh& polygonMesh,
|
||||||
|
const typename boost::graph_traits<PolygonMesh>::face_descriptor& f)
|
||||||
|
{
|
||||||
|
return Polygon_mesh_processing::compute_face_normal(f,polygonMesh);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename PolygonMesh, typename GT>
|
||||||
|
bool
|
||||||
|
is_sharp(PolygonMesh& polygonMesh,
|
||||||
|
const typename boost::graph_traits<PolygonMesh>::halfedge_descriptor& he,
|
||||||
|
typename GT::FT cos_angle)
|
||||||
|
{
|
||||||
|
typedef typename boost::graph_traits<PolygonMesh>::face_descriptor face_descriptor;
|
||||||
|
if(is_border(edge(he,polygonMesh),polygonMesh)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
face_descriptor f1 = face(he,polygonMesh);
|
||||||
|
face_descriptor f2 = face(opposite(he,polygonMesh),polygonMesh);
|
||||||
|
|
||||||
|
const typename GT::Vector_3& n1 = facet_normal<PolygonMesh, GT>(polygonMesh, f1);
|
||||||
|
const typename GT::Vector_3& n2 = facet_normal<PolygonMesh, GT>(polygonMesh, f2);
|
||||||
|
|
||||||
|
if ( n1 * n2 <= cos_angle )
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename PolygonMesh, typename PatchIdMap, typename HIF_map>
|
||||||
|
void
|
||||||
|
flood(PolygonMesh& polygonMesh,
|
||||||
|
typename boost::graph_traits<PolygonMesh>::face_descriptor f,
|
||||||
|
PatchIdMap& pid_map,
|
||||||
|
const typename boost::property_traits<PatchIdMap>::value_type& patch_id,
|
||||||
|
std::set<typename boost::graph_traits<PolygonMesh>::face_descriptor>& unsorted_faces,
|
||||||
|
HIF_map& hif)
|
||||||
|
{
|
||||||
|
typedef typename boost::graph_traits<PolygonMesh>::halfedge_descriptor halfedge_descriptor;
|
||||||
|
typedef typename boost::graph_traits<PolygonMesh>::face_descriptor face_descriptor;
|
||||||
|
|
||||||
|
typedef std::set<face_descriptor> face_descriptor_set;
|
||||||
|
typedef std::set<halfedge_descriptor> He_handle_set;
|
||||||
|
// Initialize he_to_explore with halfedges of the starting facet
|
||||||
|
He_handle_set he_to_explore;
|
||||||
|
BOOST_FOREACH(halfedge_descriptor hd,
|
||||||
|
CGAL::halfedges_around_face(halfedge(f,polygonMesh), polygonMesh))
|
||||||
|
{
|
||||||
|
he_to_explore.insert(opposite(hd,polygonMesh));
|
||||||
|
}
|
||||||
|
|
||||||
|
// While there is something to explore
|
||||||
|
while ( ! he_to_explore.empty() )
|
||||||
|
{
|
||||||
|
// Get next halfedge to explore
|
||||||
|
halfedge_descriptor he = *(he_to_explore.begin());
|
||||||
|
he_to_explore.erase(he_to_explore.begin());
|
||||||
|
|
||||||
|
// If we don't go through a border of the patch
|
||||||
|
if ( ! get(hif, he) && ! is_border(he,polygonMesh) )
|
||||||
|
{
|
||||||
|
face_descriptor explored_facet = face(he,polygonMesh);
|
||||||
|
|
||||||
|
// Mark facet and delete it from unsorted
|
||||||
|
put(pid_map, explored_facet, patch_id);
|
||||||
|
unsorted_faces.erase(explored_facet);
|
||||||
|
|
||||||
|
// Add/Remove facet's halfedge to/from explore list
|
||||||
|
BOOST_FOREACH(halfedge_descriptor hd,
|
||||||
|
CGAL::halfedges_around_face(halfedge(explored_facet,polygonMesh),
|
||||||
|
polygonMesh))
|
||||||
|
{
|
||||||
|
halfedge_descriptor current_he = hd;
|
||||||
|
|
||||||
|
// do not explore heh again
|
||||||
|
if ( current_he == he ) { continue; }
|
||||||
|
|
||||||
|
// if current_he is not in to_explore set, add it, otherwise remove it
|
||||||
|
// (because we just explore the facet he_begin is pointing to)
|
||||||
|
if ( he_to_explore.erase(current_he) == 0 )
|
||||||
|
{
|
||||||
|
he_to_explore.insert(opposite(current_he,polygonMesh));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} //end internal
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \ingroup detect_features_grp
|
* \ingroup PMP_detect_features_grp
|
||||||
* Probably does something
|
|
||||||
*
|
*
|
||||||
* \tparam PolygonMesh a model of `FaceGraph`
|
* Detects the sharp edges of `p` by comparing with `angle_in_deg` and computes the number of sharp edges incident to each vertex.
|
||||||
* \tparam FT is a number type. It must be
|
|
||||||
either `double` or `float`, or an exact number type.
|
|
||||||
* \tparam NamedParameters a sequence of \ref namedparameters
|
|
||||||
*
|
*
|
||||||
* \param p the polygon mesh
|
* Property maps for CGAL::halfedge_is_feature_t and vertex_num_feature_edges_t should be either
|
||||||
* \param angle_in_deg the roof angle.
|
* available as internal property maps to `p` or provided as Named Parameters.
|
||||||
* \param np optional \ref namedparameters described below
|
*
|
||||||
|
* \tparam PolygonMesh a model of `FaceGraph`
|
||||||
|
* \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 NamedParameters a sequence of \ref namedparameters
|
||||||
|
*
|
||||||
|
* \param p the polygon mesh
|
||||||
|
* \param angle_in_deg the floor angle.
|
||||||
|
* \param np optional \ref namedparameters described below
|
||||||
*
|
*
|
||||||
* \cgalNamedParamsBegin
|
* \cgalNamedParamsBegin
|
||||||
* \cgalParamBegin{face_patch_id_map} a property map containing the patches identifiers for the faces of `pmesh` \cgalParamEnd
|
* \cgalParamBegin{geom_traits} an instance of a geometric traits class, model of `Kernel`\cgalParamEnd
|
||||||
|
* \cgalParamBegin{halfedge_is_feature_map} a property map that will contain the sharp edges of `p` \cgalParamEnd
|
||||||
|
* \cgalParamBegin{vertex_num_feature_edges_map} a property map that will contain the number of adjacent feature edges for each vertex of `p` \cgalParamEnd
|
||||||
* \cgalNamedParamsEnd
|
* \cgalNamedParamsEnd
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
template <typename PolygonMesh, typename FT, typename Patch_id, typename NamedParameters>
|
#ifdef DOXYGEN_RUNNING
|
||||||
|
template <typename PolygonMesh, typename FT, typename NamedParameters>
|
||||||
|
#else
|
||||||
|
template <typename PolygonMesh, typename NamedParameters>
|
||||||
|
#endif
|
||||||
|
void detect_sharp_edges(PolygonMesh& p,
|
||||||
|
#ifdef DOXYGEN_RUNNING
|
||||||
|
FT angle_in_deg,
|
||||||
|
#else
|
||||||
|
typename GetGeomTraits<PolygonMesh, NamedParameters>::type::FT angle_in_deg,
|
||||||
|
#endif
|
||||||
|
const NamedParameters& np)
|
||||||
|
{
|
||||||
|
//extract types from NPs
|
||||||
|
typedef typename boost::lookup_named_param_def <
|
||||||
|
internal_np::halfedge_is_feature_t,
|
||||||
|
NamedParameters,
|
||||||
|
typename boost::property_map<PolygonMesh,halfedge_is_feature_t>::type//default
|
||||||
|
> ::type HIF_map;
|
||||||
|
HIF_map hif
|
||||||
|
= choose_param(get_param(np, internal_np::halfedge_is_feature),
|
||||||
|
get(CGAL::halfedge_is_feature, p));
|
||||||
|
|
||||||
|
typedef typename boost::lookup_named_param_def <
|
||||||
|
internal_np::vertex_num_feature_edges_t,
|
||||||
|
NamedParameters,
|
||||||
|
typename boost::property_map<PolygonMesh,vertex_num_feature_edges_t>::type//default
|
||||||
|
> ::type VNFE_map;
|
||||||
|
VNFE_map vnfe
|
||||||
|
= choose_param(get_param(np, internal_np::vertex_num_feature_edges),
|
||||||
|
get(CGAL::vertex_num_feature_edges_t(), p));
|
||||||
|
|
||||||
|
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(p))
|
||||||
|
{
|
||||||
|
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(p))
|
||||||
|
{
|
||||||
|
typename boost::graph_traits<PolygonMesh>::halfedge_descriptor he = halfedge(ed,p);
|
||||||
|
if(is_border(he,p) || angle_in_deg == FT() ||
|
||||||
|
(angle_in_deg != FT(180) && internal::is_sharp<PolygonMesh, GT>(p,he,cos_angle))
|
||||||
|
)
|
||||||
|
{
|
||||||
|
put(hif, he, true);
|
||||||
|
put(hif, opposite(he,p), true);
|
||||||
|
|
||||||
|
put(vnfe, target(he,p), get(vnfe, target(he,p))+1);
|
||||||
|
put(vnfe, source(he,p), get(vnfe, source(he,p))+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \ingroup PMP_detect_features_grp
|
||||||
|
*
|
||||||
|
* Computes for each face the index of the corresponding surface patch,
|
||||||
|
* based on the feature edges.
|
||||||
|
*
|
||||||
|
* A filled property map for CGAL::halfedge_is_feature_t should be either
|
||||||
|
* available as an internal property map to `p` or provided as one of the Named Parameters.
|
||||||
|
*
|
||||||
|
* \tparam PolygonMesh a model of `FaceGraph`
|
||||||
|
* \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 NamedParameters a sequence of \ref namedparameters
|
||||||
|
*
|
||||||
|
* \param p the polygon mesh
|
||||||
|
* \param patch_id_map a property map that will contain the surface patch ids for the faces of `p`.
|
||||||
|
* \param np optional \ref namedparameters described below
|
||||||
|
*
|
||||||
|
* \cgalNamedParamsBegin
|
||||||
|
* \cgalParamBegin{geom_traits} an instance of a geometric traits class, model of `Kernel`\cgalParamEnd
|
||||||
|
* \cgalParamBegin{halfedge_is_feature_map} a property map containing the sharp edges of `p` \cgalParamEnd
|
||||||
|
* \cgalParamBegin{maximum_number_of_patches} an `std::size_t`* the highest number of patches. This usually starts at 1. \cgalParamEnd
|
||||||
|
* \cgalNamedParamsEnd
|
||||||
|
* \returns the number of surface patches.
|
||||||
|
*
|
||||||
|
* @see `CGAL::Polygon_mesh_processing::detect_features()`
|
||||||
|
*/
|
||||||
|
template <typename PolygonMesh, typename PatchIdMap, typename NamedParameters>
|
||||||
|
std::size_t
|
||||||
|
detect_surface_patches(PolygonMesh& p,
|
||||||
|
PatchIdMap& patch_id_map,
|
||||||
|
const NamedParameters& np)
|
||||||
|
{
|
||||||
|
//extract types from NPs
|
||||||
|
typedef typename boost::lookup_named_param_def <
|
||||||
|
internal_np::halfedge_is_feature_t,
|
||||||
|
NamedParameters,
|
||||||
|
typename boost::property_map<PolygonMesh,halfedge_is_feature_t>::type//default
|
||||||
|
> ::type HIF_map;
|
||||||
|
HIF_map hif
|
||||||
|
= choose_param(get_param(np, internal_np::halfedge_is_feature),
|
||||||
|
get(CGAL::halfedge_is_feature, p));
|
||||||
|
|
||||||
|
std::size_t dummy = 1;
|
||||||
|
std::size_t* current_surface_index_ =
|
||||||
|
boost::choose_param(get_param(np, internal_np::maximum_number_of_patches), &dummy);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef typename GetGeomTraits<PolygonMesh, NamedParameters>::type GT;
|
||||||
|
typedef typename boost::graph_traits<PolygonMesh>::face_descriptor face_descriptor;
|
||||||
|
typedef typename boost::property_traits<PatchIdMap>::value_type PatchId;
|
||||||
|
// Initialize unsorted_faces
|
||||||
|
typedef std::set<face_descriptor> face_descriptor_set;
|
||||||
|
face_descriptor_set unsorted_faces;
|
||||||
|
BOOST_FOREACH(typename boost::graph_traits<PolygonMesh>::face_descriptor fd, faces(p))
|
||||||
|
{
|
||||||
|
unsorted_faces.insert(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flood
|
||||||
|
while ( ! unsorted_faces.empty() )
|
||||||
|
{
|
||||||
|
face_descriptor f = *(unsorted_faces.begin());
|
||||||
|
unsorted_faces.erase(unsorted_faces.begin());
|
||||||
|
|
||||||
|
const PatchId patch_id = internal::generate_patch_id(PatchId(),
|
||||||
|
*current_surface_index_);
|
||||||
|
put(patch_id_map, f, patch_id);
|
||||||
|
internal::flood(p, f, patch_id_map, patch_id,unsorted_faces, hif);
|
||||||
|
++(*current_surface_index_);
|
||||||
|
}
|
||||||
|
return *current_surface_index_ - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \ingroup PMP_detect_features_grp
|
||||||
|
*
|
||||||
|
* Gets for each vertex the patch ids of the incident faces.
|
||||||
|
*
|
||||||
|
* * A filled property map for CGAL::halfedge_is_feature_t should be either
|
||||||
|
* available as an internal property map to `p` or provided as one of the Named Parameters.
|
||||||
|
*
|
||||||
|
* \tparam PolygonMesh a model of `FaceGraph`
|
||||||
|
* \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 `ReadWritePropertyMap` with
|
||||||
|
`boost::graph_traits<PolygonMesh>::%vertex_descriptor` as key type
|
||||||
|
and a set of the desired patch id, model of `CopyConstructible` as value type.
|
||||||
|
|
||||||
|
* \tparam NamedParameters a sequence of \ref namedparameters
|
||||||
|
*
|
||||||
|
* \param p the polygon mesh
|
||||||
|
* \param patch_id_map a property map containing the surface patch ids for the faces of `p`. It must be already filled.
|
||||||
|
* \param vertex_incident_patches_map a property map that will contain the patch ids of all the incident faces of each vertex of `p`.
|
||||||
|
* \param np optional \ref namedparameters described below
|
||||||
|
*
|
||||||
|
* \cgalNamedParamsBegin
|
||||||
|
* \cgalParamBegin{geom_traits} an instance of a geometric traits class, model of `Kernel`\cgalParamEnd
|
||||||
|
* \cgalParamBegin{halfedge_is_feature_map} a property map containing the sharp edges of `p` \cgalParamEnd
|
||||||
|
* \cgalNamedParamsEnd
|
||||||
|
*
|
||||||
|
* * @see `CGAL::Polygon_mesh_processing::detect_features()`
|
||||||
|
*/
|
||||||
|
|
||||||
|
template <typename PolygonMesh, typename PatchIdMap, typename VertexIncidentPatchesMap, typename NamedParameters>
|
||||||
|
void detect_vertices_incident_patches(PolygonMesh& p,
|
||||||
|
PatchIdMap& patch_id_map,
|
||||||
|
VertexIncidentPatchesMap& vertex_incident_patches_map,
|
||||||
|
const NamedParameters& np)
|
||||||
|
{
|
||||||
|
//extract types from NPs
|
||||||
|
typedef typename boost::lookup_named_param_def <
|
||||||
|
internal_np::halfedge_is_feature_t,
|
||||||
|
NamedParameters,
|
||||||
|
typename boost::property_map<PolygonMesh,halfedge_is_feature_t>::type//default
|
||||||
|
> ::type HIF_map;
|
||||||
|
HIF_map hif
|
||||||
|
= choose_param(get_param(np, internal_np::halfedge_is_feature),
|
||||||
|
get(CGAL::halfedge_is_feature, p));
|
||||||
|
|
||||||
|
|
||||||
|
typedef typename GetGeomTraits<PolygonMesh, NamedParameters>::type GT;
|
||||||
|
|
||||||
|
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(p))
|
||||||
|
{
|
||||||
|
// Look only at feature vertices
|
||||||
|
if( ! get(hif, halfedge(vit, p)) ){ continue; }
|
||||||
|
|
||||||
|
// Loop on incident facets of vit
|
||||||
|
std::set<PatchId> set;
|
||||||
|
BOOST_FOREACH(halfedge_descriptor he, halfedges_around_target(vit,p))
|
||||||
|
{
|
||||||
|
if( ! is_border(he,p) )
|
||||||
|
{
|
||||||
|
set.insert(get(patch_id_map,face(he,p)));
|
||||||
|
}
|
||||||
|
else if( ! is_border(opposite(he,p),p) )
|
||||||
|
{
|
||||||
|
set.insert(get(patch_id_map, face(opposite(he,p),p)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
put(vertex_incident_patches_map, vit, set);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \ingroup PMP_detect_features_grp
|
||||||
|
*
|
||||||
|
* Detects the sharpd edges of `p` 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::detect_surface_patches()` and
|
||||||
|
* `CGAL::Polygon_mesh_processing::detect_vertices_incident_patches()`
|
||||||
|
*
|
||||||
|
* Property maps for CGAL::halfedge_is_feature_t and vertex_num_feature_edges_t should be either
|
||||||
|
* available as internal property maps to `p` or provided as Named Parameters.
|
||||||
|
*
|
||||||
|
* \tparam PolygonMesh a model of `FaceGraph`
|
||||||
|
* \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 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 `ReadWritePropertyMap` with
|
||||||
|
`boost::graph_traits<PolygonMesh>::%vertex_descriptor` as key type
|
||||||
|
and a set of the desired patch id, model of `CopyConstructible` as value type.
|
||||||
|
|
||||||
|
* \tparam NamedParameters a sequence of \ref namedparameters
|
||||||
|
*
|
||||||
|
* \param p the polygon mesh
|
||||||
|
* \param angle_in_deg the floor angle.
|
||||||
|
* \param patch_id_map a property map that will contain the surface patch ids for the faces of `p`.
|
||||||
|
* \param vertex_incident_patches_map a property map that will contain the patch ids of all the incident faces of each vertex of `p`.
|
||||||
|
* \param np optional \ref namedparameters described below
|
||||||
|
*
|
||||||
|
* \cgalNamedParamsBegin
|
||||||
|
* \cgalParamBegin{geom_traits} an instance of a geometric traits class, model of `Kernel`\cgalParamEnd
|
||||||
|
* \cgalParamBegin{halfedge_is_feature_map} a property map that will contain the sharp edges of `p` \cgalParamEnd
|
||||||
|
* \cgalParamBegin{vertex_num_feature_edges_map} a property map that will contain the number of adjacent feature edges for each vertex of `p` \cgalParamEnd
|
||||||
|
* \cgalParamBegin{maximum_number_of_patches} an `std::size_t` that that will contain the number of surface patches of `p`. \cgalParamEnd
|
||||||
|
* \cgalNamedParamsEnd
|
||||||
|
*
|
||||||
|
* @see `CGAL::Polygon_mesh_processing::detect_sharp_edges()`
|
||||||
|
* @see `CGAL::Polygon_mesh_processing::detect_surface_patches()`
|
||||||
|
* @see `CGAL::Polygon_mesh_processing::detect_vertices_incident_patches()`
|
||||||
|
*/
|
||||||
|
#ifdef DOXYGEN_RUNNING
|
||||||
|
template <typename PolygonMesh, typename FT, typename PatchIdMap, typename VertexIncidentPatchesMap, typename NamedParameters>
|
||||||
|
#else
|
||||||
|
template <typename PolygonMesh, typename PatchIdMap, typename VertexIncidentPatchesMap, typename NamedParameters>
|
||||||
|
#endif
|
||||||
void detect_features(PolygonMesh& p,
|
void detect_features(PolygonMesh& p,
|
||||||
|
#ifdef DOXYGEN_RUNNING
|
||||||
FT angle_in_deg,
|
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)
|
const NamedParameters& np)
|
||||||
{
|
{
|
||||||
typedef typename boost::lookup_named_param_def <
|
detect_sharp_edges(p,angle_in_deg, np);
|
||||||
internal_np::face_patch_id_t,
|
detect_surface_patches(p, patch_id_map, np);
|
||||||
NamedParameters,
|
detect_vertices_incident_patches(p, patch_id_map, vertex_incident_patches_map, np);
|
||||||
typename boost::property_map<PolygonMesh, face_patch_id_t<Patch_id> >::type//default
|
|
||||||
> ::type PatchId_pmap;
|
|
||||||
PatchId_pmap pid_map
|
|
||||||
= choose_param(get_param(np, internal_np::face_patch_id),
|
|
||||||
get(typename CGAL::face_patch_id_t<Patch_id>(), p));
|
|
||||||
|
|
||||||
Detect_features_in_polygon_mesh<PolygonMesh, Patch_id, PatchId_pmap> go(pid_map);
|
|
||||||
// AF todo: Add overload for the next three functions so that we use the pid_map
|
|
||||||
// Add a default for pid_map
|
|
||||||
go.detect_sharp_edges(p,angle_in_deg);
|
|
||||||
go.detect_surface_patches(p);
|
|
||||||
go.detect_vertices_incident_patches(p);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Convenient overrides
|
||||||
template <typename Polyhedron_, typename Patch_id_, typename PatchId_pmap>
|
template <typename PolygonMesh, typename FT>
|
||||||
class Detect_features_in_polygon_mesh
|
void detect_sharp_edges(PolygonMesh& p,
|
||||||
|
FT angle_in_deg)
|
||||||
{
|
{
|
||||||
public:
|
detect_sharp_edges(p, angle_in_deg, parameters::all_default());
|
||||||
|
}
|
||||||
|
|
||||||
typedef Polyhedron_ Polyhedron;
|
template <typename PolygonMesh, typename PatchIdMap>
|
||||||
typedef Patch_id_ Patch_id;
|
typename boost::graph_traits<PolygonMesh>::faces_size_type
|
||||||
|
detect_surface_patches(PolygonMesh& p,
|
||||||
typedef typename boost::property_traits<typename boost::property_map<Polyhedron,
|
PatchIdMap& patch_id_map)
|
||||||
vertex_point_t>::type>::value_type Point_3;
|
|
||||||
|
|
||||||
typedef typename Kernel_traits<Point_3>::Kernel Geom_traits;
|
|
||||||
|
|
||||||
typedef typename Geom_traits::Vector_3 Vector_3;
|
|
||||||
typedef typename Geom_traits::FT FT;
|
|
||||||
|
|
||||||
typedef typename boost::graph_traits<Polyhedron>::vertex_descriptor vertex_descriptor;
|
|
||||||
typedef typename boost::graph_traits<Polyhedron>::halfedge_descriptor halfedge_descriptor;
|
|
||||||
typedef typename boost::graph_traits<Polyhedron>::face_descriptor face_descriptor;
|
|
||||||
|
|
||||||
typedef CGAL::Compare_handles_with_or_without_timestamps Compare_handles;
|
|
||||||
|
|
||||||
typedef std::set<face_descriptor> face_descriptor_set;
|
|
||||||
typedef std::set<halfedge_descriptor> He_handle_set;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Detect_features_in_polygon_mesh(PatchId_pmap& pid_map)
|
|
||||||
: current_surface_index_(1),
|
|
||||||
pid_map(pid_map)
|
|
||||||
{}
|
|
||||||
|
|
||||||
void detect_sharp_edges(Polyhedron& polyhedron,
|
|
||||||
FT angle_in_deg = FT(60)) const;
|
|
||||||
void detect_surface_patches(Polyhedron& polyhedron);
|
|
||||||
void detect_vertices_incident_patches(Polyhedron& p);
|
|
||||||
|
|
||||||
int maximal_surface_patch_index() const {
|
|
||||||
return current_surface_index_ - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Vector_3 facet_normal(const Polyhedron& polyhedron, const face_descriptor& f) const;
|
|
||||||
bool is_sharp(Polyhedron& polyhedron, const halfedge_descriptor& he, FT cos_angle) const;
|
|
||||||
void flood(Polyhedron& polyhedron,
|
|
||||||
face_descriptor f, const Patch_id& id,
|
|
||||||
face_descriptor_set& unsorted_faces) const;
|
|
||||||
|
|
||||||
template <typename Int>
|
|
||||||
Int generate_patch_id(Int, int);
|
|
||||||
|
|
||||||
template <typename Int>
|
|
||||||
std::pair<Int, Int> generate_patch_id(std::pair<Int, Int>, int);
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Stores the current surface index (usefull to detect different patches
|
|
||||||
// on different polyhedra)
|
|
||||||
int current_surface_index_;
|
|
||||||
PatchId_pmap pid_map;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template <typename P_, typename I_, typename M_>
|
|
||||||
void
|
|
||||||
Detect_features_in_polygon_mesh<P_, I_, M_>::
|
|
||||||
detect_sharp_edges(Polyhedron& polyhedron, FT angle_in_deg) const
|
|
||||||
{
|
{
|
||||||
// Initialize vertices
|
return detect_surface_patches(p, patch_id_map, parameters::all_default());
|
||||||
typename boost::property_map<Polyhedron,vertex_num_feature_edges_t>::type vnfe
|
}
|
||||||
= get(vertex_num_feature_edges_t(),polyhedron);
|
template <typename PolygonMesh, typename PatchIdMap, typename VertexIncidentPatchesMap>
|
||||||
|
void detect_vertices_incident_patches(PolygonMesh& p,
|
||||||
typename boost::property_map<Polyhedron,halfedge_is_feature_t>::type hif
|
PatchIdMap& patch_id_map,
|
||||||
= get(halfedge_is_feature_t(),polyhedron);
|
VertexIncidentPatchesMap& vertex_incident_patches_map)
|
||||||
|
{
|
||||||
BOOST_FOREACH(typename boost::graph_traits<P_>::vertex_descriptor vd, vertices(polyhedron))
|
detect_vertices_incident_patches(p, patch_id_map, vertex_incident_patches_map, parameters::all_default());
|
||||||
{
|
}
|
||||||
put(vnfe,vd, 0);
|
template <typename PolygonMesh, typename FT, typename PatchIdMap, typename VertexIncidentPatchesMap>
|
||||||
}
|
void detect_features(PolygonMesh& p,
|
||||||
|
FT angle_in_deg,
|
||||||
FT cos_angle ( std::cos(CGAL::to_double(angle_in_deg) * CGAL_PI / 180.) );
|
PatchIdMap& patch_id_map,
|
||||||
|
VertexIncidentPatchesMap& vertex_incident_patches_map)
|
||||||
// Detect sharp edges
|
{
|
||||||
BOOST_FOREACH(typename boost::graph_traits<P_>::edge_descriptor ed, edges(polyhedron))
|
detect_features(p,angle_in_deg, patch_id_map, vertex_incident_patches_map, parameters::all_default());
|
||||||
{
|
|
||||||
typename boost::graph_traits<P_>::halfedge_descriptor he = halfedge(ed,polyhedron);
|
|
||||||
if(is_border(he,polyhedron) || angle_in_deg == FT() ||
|
|
||||||
(angle_in_deg != FT(180) && is_sharp(polyhedron,he,cos_angle))
|
|
||||||
)
|
|
||||||
{
|
|
||||||
put(hif, he, true);
|
|
||||||
put(hif, opposite(he,polyhedron), true);
|
|
||||||
|
|
||||||
put(vnfe, target(he,polyhedron), get(vnfe, target(he,polyhedron))+1);
|
|
||||||
put(vnfe, source(he,polyhedron), get(vnfe, source(he,polyhedron))+1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename P_, typename I_, typename M_>
|
|
||||||
template <typename Int>
|
|
||||||
Int
|
|
||||||
Detect_features_in_polygon_mesh<P_, I_, M_>::
|
|
||||||
generate_patch_id(Int, int i)
|
|
||||||
{
|
|
||||||
return Int(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename P_, typename I_, typename M_>
|
|
||||||
template <typename Int>
|
|
||||||
std::pair<Int, Int>
|
|
||||||
Detect_features_in_polygon_mesh<P_, I_, M_>::
|
|
||||||
generate_patch_id(std::pair<Int, Int>, int i)
|
|
||||||
{
|
|
||||||
return std::pair<Int, Int>(i, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename P_, typename I_, typename M_>
|
|
||||||
void
|
|
||||||
Detect_features_in_polygon_mesh<P_, I_, M_>::
|
|
||||||
detect_surface_patches(Polyhedron& polyhedron)
|
|
||||||
{
|
|
||||||
// Initialize unsorted_faces
|
|
||||||
face_descriptor_set unsorted_faces;
|
|
||||||
BOOST_FOREACH(typename boost::graph_traits<Polyhedron>::face_descriptor fd, faces(polyhedron))
|
|
||||||
{
|
|
||||||
unsorted_faces.insert(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flood
|
|
||||||
while ( ! unsorted_faces.empty() )
|
|
||||||
{
|
|
||||||
face_descriptor f = *(unsorted_faces.begin());
|
|
||||||
unsorted_faces.erase(unsorted_faces.begin());
|
|
||||||
|
|
||||||
const Patch_id patch_id = generate_patch_id(Patch_id(),
|
|
||||||
current_surface_index_);
|
|
||||||
put(pid_map, f, patch_id);
|
|
||||||
flood(polyhedron, f,patch_id,unsorted_faces);
|
|
||||||
++current_surface_index_;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <typename P_, typename I_, typename M_>
|
|
||||||
void
|
|
||||||
Detect_features_in_polygon_mesh<P_, I_, M_>::
|
|
||||||
detect_vertices_incident_patches(Polyhedron& polyhedron)
|
|
||||||
{
|
|
||||||
typename boost::property_map<Polyhedron,halfedge_is_feature_t>::type hif
|
|
||||||
= get(halfedge_is_feature,polyhedron);
|
|
||||||
typedef typename boost::property_map<Polyhedron,vertex_incident_patches_t<Patch_id> >::type VIP_map;
|
|
||||||
VIP_map vip = get(vertex_incident_patches_t<Patch_id>(),polyhedron);
|
|
||||||
|
|
||||||
BOOST_FOREACH(vertex_descriptor vit,vertices(polyhedron))
|
|
||||||
{
|
|
||||||
// Look only at feature vertices
|
|
||||||
if( ! get(hif, halfedge(vit, polyhedron)) ){ continue; }
|
|
||||||
|
|
||||||
// Loop on incident facets of vit
|
|
||||||
std::set<Patch_id> set;
|
|
||||||
BOOST_FOREACH(halfedge_descriptor he, halfedges_around_target(vit,polyhedron))
|
|
||||||
{
|
|
||||||
if( ! is_border(he,polyhedron) )
|
|
||||||
{
|
|
||||||
set.insert(get(pid_map,face(he,polyhedron)));
|
|
||||||
}
|
|
||||||
else if( ! is_border(opposite(he,polyhedron),polyhedron) )
|
|
||||||
{
|
|
||||||
set.insert(get(pid_map, face(opposite(he,polyhedron),polyhedron)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
put(vip, vit, set);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------
|
|
||||||
// Private methods
|
|
||||||
// -----------------------------------
|
|
||||||
template <typename P_, typename I_, typename M_>
|
|
||||||
typename Detect_features_in_polygon_mesh<P_, I_, M_>::Vector_3
|
|
||||||
Detect_features_in_polygon_mesh<P_, I_, M_>::
|
|
||||||
facet_normal(const Polyhedron& polyhedron, const face_descriptor& f) const
|
|
||||||
{
|
|
||||||
return Polygon_mesh_processing::compute_face_normal(f,polyhedron);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <typename P_, typename I_, typename M_>
|
|
||||||
bool
|
|
||||||
Detect_features_in_polygon_mesh<P_, I_, M_>::
|
|
||||||
is_sharp(Polyhedron& polyhedron, const halfedge_descriptor& he, FT cos_angle) const
|
|
||||||
{
|
|
||||||
if(is_border(edge(he,polyhedron),polyhedron)){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
face_descriptor f1 = face(he,polyhedron);
|
|
||||||
face_descriptor f2 = face(opposite(he,polyhedron),polyhedron);
|
|
||||||
|
|
||||||
const Vector_3& n1 = facet_normal(polyhedron, f1);
|
|
||||||
const Vector_3& n2 = facet_normal(polyhedron, f2);
|
|
||||||
|
|
||||||
if ( n1 * n2 <= cos_angle )
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <typename P_, typename I_, typename M_>
|
|
||||||
void
|
|
||||||
Detect_features_in_polygon_mesh<P_, I_, M_>::
|
|
||||||
flood(Polyhedron& polyhedron,
|
|
||||||
face_descriptor f,
|
|
||||||
const Patch_id &patch_id,
|
|
||||||
face_descriptor_set& unsorted_faces) const
|
|
||||||
{
|
|
||||||
typename boost::property_map<Polyhedron,halfedge_is_feature_t>::type hif
|
|
||||||
= get(halfedge_is_feature,polyhedron);
|
|
||||||
// Initialize he_to_explore with halfedges of the starting facet
|
|
||||||
He_handle_set he_to_explore;
|
|
||||||
BOOST_FOREACH(halfedge_descriptor hd,
|
|
||||||
halfedges_around_face(halfedge(f,polyhedron), polyhedron))
|
|
||||||
{
|
|
||||||
he_to_explore.insert(opposite(hd,polyhedron));
|
|
||||||
}
|
|
||||||
|
|
||||||
// While there is something to explore
|
|
||||||
while ( ! he_to_explore.empty() )
|
|
||||||
{
|
|
||||||
// Get next halfedge to explore
|
|
||||||
halfedge_descriptor he = *(he_to_explore.begin());
|
|
||||||
he_to_explore.erase(he_to_explore.begin());
|
|
||||||
|
|
||||||
// If we don't go through a border of the patch
|
|
||||||
if ( ! get(hif, he) && ! is_border(he,polyhedron) )
|
|
||||||
{
|
|
||||||
face_descriptor explored_facet = face(he,polyhedron);
|
|
||||||
|
|
||||||
// Mark facet and delete it from unsorted
|
|
||||||
put(pid_map, explored_facet, patch_id);
|
|
||||||
unsorted_faces.erase(explored_facet);
|
|
||||||
|
|
||||||
// Add/Remove facet's halfedge to/from explore list
|
|
||||||
BOOST_FOREACH(halfedge_descriptor hd,
|
|
||||||
halfedges_around_face(halfedge(explored_facet,polyhedron),
|
|
||||||
polyhedron))
|
|
||||||
{
|
|
||||||
halfedge_descriptor current_he = hd;
|
|
||||||
|
|
||||||
// do not explore heh again
|
|
||||||
if ( current_he == he ) { continue; }
|
|
||||||
|
|
||||||
// if current_he is not in to_explore set, add it, otherwise remove it
|
|
||||||
// (because we just explore the facet he_begin is pointing to)
|
|
||||||
if ( he_to_explore.erase(current_he) == 0 )
|
|
||||||
{
|
|
||||||
he_to_explore.insert(opposite(current_he,polyhedron));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end namespace PMP
|
} // end namespace PMP
|
||||||
} // end namespace CGAL
|
} // end namespace CGAL
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
||||||
// Copyright (c) 2017 GeometryFactory (France).
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// This file is part of CGAL (www.cgal.org).
|
|
||||||
// You can redistribute it and/or modify it under the terms of the GNU
|
|
||||||
// General Public License as published by the Free Software Foundation,
|
|
||||||
// either version 3 of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// Licensees holding a valid commercial license may use this file in
|
|
||||||
// accordance with the commercial license agreement provided with the software.
|
|
||||||
//
|
|
||||||
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
|
||||||
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
//
|
|
||||||
// $URL$
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// Author(s) : Laurent Rineau, Stephane Tayeb, Maxime Gimeno
|
|
||||||
//
|
|
||||||
//******************************************************************************
|
|
||||||
// File Description :
|
|
||||||
//******************************************************************************
|
|
||||||
|
|
||||||
#ifndef CGAL_POLYGON_MESH_PROCESSING_DETECT_FEATURES_IN_POLYGON_MESH_FWD_H
|
|
||||||
#define CGAL_POLYGON_MESH_PROCESSING_DETECT_FEATURES_IN_POLYGON_MESH_FWD_H
|
|
||||||
|
|
||||||
#include <CGAL/license/Polygon_mesh_processing.h>
|
|
||||||
|
|
||||||
|
|
||||||
namespace CGAL {
|
|
||||||
template <typename PatchId>
|
|
||||||
class face_patch_id_t;
|
|
||||||
namespace Polygon_mesh_processing {
|
|
||||||
|
|
||||||
template <typename Polyhedron, typename Patch_id_, typename PatchId_pmap>
|
|
||||||
class Detect_features_in_polygon_mesh;
|
|
||||||
|
|
||||||
|
|
||||||
template <typename Polyhedron, typename FT, typename Patch_id>
|
|
||||||
void detect_features(Polyhedron& p,
|
|
||||||
FT angle_in_deg,
|
|
||||||
typename boost::property_map<Polyhedron, CGAL::face_patch_id_t<Patch_id> >::type);
|
|
||||||
|
|
||||||
} // end namespace Polygon_mesh_processing
|
|
||||||
|
|
||||||
} // end namespace CGAL
|
|
||||||
|
|
||||||
#endif // CGAL_POLYGON_MESH_PROCESSING_DETECT_FEATURES_IN_POLYGON_MESH_FWD_H
|
|
||||||
|
|
@ -130,9 +130,10 @@ void Polyhedron_demo_detect_sharp_edges_plugin::detectSharpEdges(bool input_dial
|
||||||
FaceGraph* pMesh = tuple.second;
|
FaceGraph* pMesh = tuple.second;
|
||||||
if (!pMesh) continue;
|
if (!pMesh) continue;
|
||||||
typedef typename boost::property_map<FaceGraph,CGAL::face_patch_id_t<int> >::type PatchID;
|
typedef typename boost::property_map<FaceGraph,CGAL::face_patch_id_t<int> >::type PatchID;
|
||||||
PatchID dummy = get(CGAL::face_patch_id_t<int>(), *pMesh);
|
PatchID pid = get(CGAL::face_patch_id_t<int>(), *pMesh);
|
||||||
CGAL::Polygon_mesh_processing::detect_features<FaceGraph, double, int>(*pMesh, angle,
|
typedef typename boost::property_map<FaceGraph,CGAL::vertex_incident_patches_t<int> >::type VIP;
|
||||||
CGAL::Polygon_mesh_processing::parameters::face_patch_id_map(dummy));
|
VIP vip = get(CGAL::vertex_incident_patches_t<int>(), *pMesh);
|
||||||
|
CGAL::Polygon_mesh_processing::detect_features(*pMesh, angle, pid, vip);
|
||||||
//update item
|
//update item
|
||||||
item->setItemIsMulticolor(true);
|
item->setItemIsMulticolor(true);
|
||||||
item->invalidateOpenGLBuffers();
|
item->invalidateOpenGLBuffers();
|
||||||
|
|
|
||||||
|
|
@ -24,11 +24,13 @@ namespace CGAL
|
||||||
reset_sharp_edges(pMesh);
|
reset_sharp_edges(pMesh);
|
||||||
|
|
||||||
// Detect edges in current polyhedron
|
// Detect edges in current polyhedron
|
||||||
typedef typename boost::property_map<Polyhedron,CGAL::face_patch_id_t<int> >::type PatchID;
|
typedef typename boost::property_map<Polyhedron,CGAL::face_patch_id_t<int> >::type PIDMap;
|
||||||
PatchID pid_map = get(face_patch_id_t<int>(), *pMesh);
|
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_features_in_polygon_mesh<Polyhedron,int,PatchID> features_detector(pid_map);
|
|
||||||
features_detector.detect_sharp_edges(*pMesh, angle);
|
CGAL::Polygon_mesh_processing::detect_sharp_edges(*pMesh, angle);
|
||||||
}
|
}
|
||||||
|
|
||||||
}//end namespace CGAL
|
}//end namespace CGAL
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue