mirror of https://github.com/CGAL/cgal
Merge pull request #3268 from afabri/PMP-visitor-GF
PMP::triangulate_faces() Add a visitor that allows to map each triangle to its original face
This commit is contained in:
commit
47d2189f8e
|
|
@ -293,7 +293,6 @@ CGAL_DEF_GET_INITIALIZED_INDEX_MAP(face, typename boost::graph_traits<Graph>::fa
|
||||||
> ::type type;
|
> ::type type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(Has_nested_type_iterator, iterator, false)
|
BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(Has_nested_type_iterator, iterator, false)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ CGAL_add_named_parameter(halfedge_index_t, halfedge_index, halfedge_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(face_index_t, face_index, face_index_map)
|
CGAL_add_named_parameter(face_index_t, face_index, face_index_map)
|
||||||
CGAL_add_named_parameter(vertex_index_t, vertex_index, vertex_index_map)
|
CGAL_add_named_parameter(vertex_index_t, vertex_index, vertex_index_map)
|
||||||
CGAL_add_named_parameter(graph_visitor_t, graph_visitor, visitor)
|
CGAL_add_named_parameter(visitor_t, visitor, visitor)
|
||||||
|
|
||||||
CGAL_add_named_parameter(point_t, point_map, point_map)
|
CGAL_add_named_parameter(point_t, point_map, point_map)
|
||||||
|
|
||||||
|
|
@ -172,7 +172,6 @@ CGAL_add_named_parameter(pca_plane_t, pca_plane, pca_plane)
|
||||||
CGAL_add_named_parameter(remesh_boundaries_t, remesh_boundaries, remesh_boundaries)
|
CGAL_add_named_parameter(remesh_boundaries_t, remesh_boundaries, remesh_boundaries)
|
||||||
CGAL_add_named_parameter(cell_selector_t, cell_selector, cell_selector)
|
CGAL_add_named_parameter(cell_selector_t, cell_selector, cell_selector)
|
||||||
CGAL_add_named_parameter(facet_is_constrained_t, facet_is_constrained, facet_is_constrained_map)
|
CGAL_add_named_parameter(facet_is_constrained_t, facet_is_constrained, facet_is_constrained_map)
|
||||||
CGAL_add_named_parameter(remeshing_visitor_t, remeshing_visitor, remeshing_visitor)
|
|
||||||
CGAL_add_named_parameter(smooth_constrained_edges_t, smooth_constrained_edges, smooth_constrained_edges)
|
CGAL_add_named_parameter(smooth_constrained_edges_t, smooth_constrained_edges, smooth_constrained_edges)
|
||||||
|
|
||||||
// output parameters
|
// output parameters
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ void test(const NamedParameters& np)
|
||||||
|
|
||||||
// Named parameters that we use in CGAL
|
// Named parameters that we use in CGAL
|
||||||
assert(get_parameter(np, CGAL::internal_np::vertex_index).v == 0);
|
assert(get_parameter(np, CGAL::internal_np::vertex_index).v == 0);
|
||||||
assert(get_parameter(np, CGAL::internal_np::graph_visitor).v == 1);
|
assert(get_parameter(np, CGAL::internal_np::visitor).v == 1);
|
||||||
assert(get_parameter(np, CGAL::internal_np::vertex_point).v == 2);
|
assert(get_parameter(np, CGAL::internal_np::vertex_point).v == 2);
|
||||||
assert(get_parameter(np, CGAL::internal_np::halfedge_index).v == 3);
|
assert(get_parameter(np, CGAL::internal_np::halfedge_index).v == 3);
|
||||||
assert(get_parameter(np, CGAL::internal_np::edge_index).v == 4);
|
assert(get_parameter(np, CGAL::internal_np::edge_index).v == 4);
|
||||||
|
|
@ -125,7 +125,7 @@ void test(const NamedParameters& np)
|
||||||
|
|
||||||
// Named parameters that we use in CGAL
|
// Named parameters that we use in CGAL
|
||||||
check_same_type<0>(get_parameter(np, CGAL::internal_np::vertex_index));
|
check_same_type<0>(get_parameter(np, CGAL::internal_np::vertex_index));
|
||||||
check_same_type<1>(get_parameter(np, CGAL::internal_np::graph_visitor));
|
check_same_type<1>(get_parameter(np, CGAL::internal_np::visitor));
|
||||||
check_same_type<2>(get_parameter(np, CGAL::internal_np::vertex_point));
|
check_same_type<2>(get_parameter(np, CGAL::internal_np::vertex_point));
|
||||||
check_same_type<3>(get_parameter(np, CGAL::internal_np::halfedge_index));
|
check_same_type<3>(get_parameter(np, CGAL::internal_np::halfedge_index));
|
||||||
check_same_type<4>(get_parameter(np, CGAL::internal_np::edge_index));
|
check_same_type<4>(get_parameter(np, CGAL::internal_np::edge_index));
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
Release History
|
Release History
|
||||||
===============
|
===============
|
||||||
|
|
||||||
|
|
||||||
[Release 5.2](https://github.com/CGAL/cgal/releases/tag/v5.2)
|
[Release 5.2](https://github.com/CGAL/cgal/releases/tag/v5.2)
|
||||||
|
|
||||||
Release date: December 2020
|
Release date: December 2020
|
||||||
|
|
@ -32,6 +33,11 @@ Release date: December 2020
|
||||||
that all calls to `decompose()` are fixed to use the new interface.
|
that all calls to `decompose()` are fixed to use the new interface.
|
||||||
|
|
||||||
### [Polygon Mesh Processing](https://doc.cgal.org/5.2/Manual/packages.html#PkgPolygonMeshProcessing)
|
### [Polygon Mesh Processing](https://doc.cgal.org/5.2/Manual/packages.html#PkgPolygonMeshProcessing)
|
||||||
|
- Added a visitor to the functions
|
||||||
|
[`CGAL::Polygon_mesh_processing::triangulate_face()`](https://doc.cgal.org/5.2/Polygon_mesh_processing/group__PMP__meshing__grp.html#ga70d65044f8c7309c24ade88fa280124a)
|
||||||
|
and [`CGAL::Polygon_mesh_processing::triangulate_faces()`](https://doc.cgal.org/5.2/Polygon_mesh_processing/group__PMP__meshing__grp.html#gacaaff4d520500c530d9c3d5ebe2a0760),
|
||||||
|
that enables the user to keep track of the newly created faces through the triangulation process.
|
||||||
|
|
||||||
- Added an option in `corefine()`, `split()` and `clip()` functions that enables the operation to be done on a mesh with
|
- Added an option in `corefine()`, `split()` and `clip()` functions that enables the operation to be done on a mesh with
|
||||||
self-intersections present in the intersection area.
|
self-intersections present in the intersection area.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
/// \ingroup PkgPolygonMeshProcessingConcepts
|
||||||
|
/// \cgalConcept
|
||||||
|
///
|
||||||
|
/// The concept `PMPTriangulateFaceVisitor` defines the requirements for the visitor
|
||||||
|
/// used in \link PMP_meshing_grp triangulation-related functions \endlink to track
|
||||||
|
/// the creation of new faces.
|
||||||
|
///
|
||||||
|
/// \cgalRefines `CopyConstructible`
|
||||||
|
/// \cgalHasModel `CGAL::Polygon_mesh_processing::Triangulate_faces::Default_visitor`.
|
||||||
|
|
||||||
|
|
||||||
|
class PMPTriangulateFaceVisitor {
|
||||||
|
public:
|
||||||
|
/// Face decriptor type
|
||||||
|
typedef unspecified_type face_descriptor;
|
||||||
|
|
||||||
|
/// @name Functions used by triangulate_face() and triangulate_faces()
|
||||||
|
/// @{
|
||||||
|
/// called before the triangulation of `f_split`. Note that `f_split`
|
||||||
|
/// will be one of the faces of the triangulation. Each subsequent call to
|
||||||
|
/// `after_subface_created()` will correspond to
|
||||||
|
/// the creation of a new face of the triangulation of `f_split`.
|
||||||
|
void before_subface_creations(face_descriptor f_split);
|
||||||
|
|
||||||
|
/// called when the triangulation of a face in `tm` is finished.
|
||||||
|
void after_subface_creations();
|
||||||
|
|
||||||
|
/// called after creating a new triangle face `f_new` to triangulate the face passed to `before_subface_creations()`.
|
||||||
|
/// Note that the call is placed just after a call to `add_face()` so the halfedge pointer is not set yet.
|
||||||
|
void after_subface_created(face_descriptor f_new);
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
@ -193,6 +193,11 @@ as shown in the following example.
|
||||||
|
|
||||||
\cgalExample{Polygon_mesh_processing/triangulate_faces_example.cpp}
|
\cgalExample{Polygon_mesh_processing/triangulate_faces_example.cpp}
|
||||||
|
|
||||||
|
An additional parameter, named `visitor` can be used to track the how faces
|
||||||
|
are triangulated into subfaces. The following examples shows how to use it.
|
||||||
|
|
||||||
|
\cgalExample{Polygon_mesh_processing/triangulate_faces_split_visitor_example.cpp}
|
||||||
|
|
||||||
|
|
||||||
\subsubsection RemeshingExample_1 Isotropic Remeshing of a Region on a Polygon Mesh
|
\subsubsection RemeshingExample_1 Isotropic Remeshing of a Region on a Polygon Mesh
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,4 +29,5 @@
|
||||||
\example Polygon_mesh_processing/shape_smoothing_example.cpp
|
\example Polygon_mesh_processing/shape_smoothing_example.cpp
|
||||||
\example Polygon_mesh_processing/locate_example.cpp
|
\example Polygon_mesh_processing/locate_example.cpp
|
||||||
\example Polygon_mesh_processing/orientation_pipeline_example.cpp
|
\example Polygon_mesh_processing/orientation_pipeline_example.cpp
|
||||||
|
\example Polygon_mesh_processing/triangulate_faces_split_visitor_example.cpp
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,7 @@ create_single_source_cgal_program( "compute_normals_example_Polyhedron.cpp" CXX
|
||||||
create_single_source_cgal_program( "compute_normals_example.cpp" CXX_FEATURES cxx_range_for cxx_auto_type )
|
create_single_source_cgal_program( "compute_normals_example.cpp" CXX_FEATURES cxx_range_for cxx_auto_type )
|
||||||
create_single_source_cgal_program( "point_inside_example.cpp")
|
create_single_source_cgal_program( "point_inside_example.cpp")
|
||||||
create_single_source_cgal_program( "triangulate_faces_example.cpp")
|
create_single_source_cgal_program( "triangulate_faces_example.cpp")
|
||||||
|
create_single_source_cgal_program( "triangulate_faces_split_visitor_example.cpp")
|
||||||
create_single_source_cgal_program( "connected_components_example.cpp")
|
create_single_source_cgal_program( "connected_components_example.cpp")
|
||||||
create_single_source_cgal_program( "face_filtered_graph_example.cpp")
|
create_single_source_cgal_program( "face_filtered_graph_example.cpp")
|
||||||
create_single_source_cgal_program( "orient_polygon_soup_example.cpp")
|
create_single_source_cgal_program( "orient_polygon_soup_example.cpp")
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,105 @@
|
||||||
|
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||||
|
#include <CGAL/Surface_mesh.h>
|
||||||
|
|
||||||
|
#include <CGAL/Polygon_mesh_processing/triangulate_faces.h>
|
||||||
|
#include <CGAL/boost/graph/copy_face_graph.h>
|
||||||
|
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
|
#include <boost/unordered_map.hpp>
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
|
||||||
|
typedef Kernel::Point_3 Point;
|
||||||
|
typedef CGAL::Surface_mesh<Point> Surface_mesh;
|
||||||
|
typedef boost::graph_traits<Surface_mesh>::face_descriptor face_descriptor;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Insert_iterator
|
||||||
|
{
|
||||||
|
typedef boost::unordered_map<face_descriptor,face_descriptor> Container;
|
||||||
|
Container& container;
|
||||||
|
public:
|
||||||
|
|
||||||
|
Insert_iterator(Container &c)
|
||||||
|
: container(c) {}
|
||||||
|
|
||||||
|
Insert_iterator&
|
||||||
|
operator=(const std::pair<face_descriptor, face_descriptor>& p)
|
||||||
|
{
|
||||||
|
container[p.second] = p.first;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Insert_iterator&
|
||||||
|
operator*() { return *this; }
|
||||||
|
|
||||||
|
Insert_iterator
|
||||||
|
operator++(int) { return *this; }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct Visitor
|
||||||
|
{
|
||||||
|
typedef boost::unordered_map<face_descriptor,face_descriptor> Container;
|
||||||
|
|
||||||
|
Container& container;
|
||||||
|
face_descriptor qfd;
|
||||||
|
|
||||||
|
Visitor(Container& container)
|
||||||
|
: container(container)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void before_subface_creations(face_descriptor fd)
|
||||||
|
{
|
||||||
|
std::cout << "split : " << fd << " into:" << std::endl;
|
||||||
|
Container::iterator it = container.find(fd);
|
||||||
|
qfd = it->second;
|
||||||
|
container.erase(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
void after_subface_created(face_descriptor fd)
|
||||||
|
{
|
||||||
|
std::cout << " " << fd;
|
||||||
|
container[fd]=qfd;
|
||||||
|
}
|
||||||
|
|
||||||
|
void after_subface_creations()
|
||||||
|
{
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
const char* filename = (argc > 1) ? argv[1] : "data/P.off";
|
||||||
|
std::ifstream input(filename);
|
||||||
|
|
||||||
|
Surface_mesh mesh;
|
||||||
|
if (!input || !(input >> mesh) || mesh.is_empty())
|
||||||
|
{
|
||||||
|
std::cerr << "Not a valid off file." << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::unordered_map<face_descriptor,face_descriptor> t2q;
|
||||||
|
|
||||||
|
Surface_mesh copy;
|
||||||
|
|
||||||
|
copy_face_graph(mesh, copy, CGAL::Emptyset_iterator(), CGAL::Emptyset_iterator(),Insert_iterator(t2q));
|
||||||
|
|
||||||
|
Visitor v(t2q);
|
||||||
|
CGAL::Polygon_mesh_processing::triangulate_faces(copy,
|
||||||
|
CGAL::Polygon_mesh_processing::parameters::visitor(v));
|
||||||
|
|
||||||
|
|
||||||
|
for(boost::unordered_map<face_descriptor,face_descriptor>::iterator it = t2q.begin(); it != t2q.end(); ++it){
|
||||||
|
std::cout << it->first << " " << it->second << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -469,11 +469,11 @@ generic_clip_impl(
|
||||||
|
|
||||||
// User visitor
|
// User visitor
|
||||||
typedef typename internal_np::Lookup_named_param_def <
|
typedef typename internal_np::Lookup_named_param_def <
|
||||||
internal_np::graph_visitor_t,
|
internal_np::visitor_t,
|
||||||
NamedParameters1,
|
NamedParameters1,
|
||||||
Corefinement::Default_visitor<TriangleMesh>//default
|
Corefinement::Default_visitor<TriangleMesh>//default
|
||||||
> ::type User_visitor;
|
> ::type User_visitor;
|
||||||
User_visitor uv(choose_parameter<User_visitor>(get_parameter(np1, internal_np::graph_visitor)));
|
User_visitor uv(choose_parameter<User_visitor>(get_parameter(np1, internal_np::visitor)));
|
||||||
|
|
||||||
// surface intersection algorithm call
|
// surface intersection algorithm call
|
||||||
typedef Corefinement::Generic_clip_output_builder<TriangleMesh,
|
typedef Corefinement::Generic_clip_output_builder<TriangleMesh,
|
||||||
|
|
|
||||||
|
|
@ -367,11 +367,11 @@ corefine_and_compute_boolean_operations(
|
||||||
|
|
||||||
// User visitor
|
// User visitor
|
||||||
typedef typename internal_np::Lookup_named_param_def <
|
typedef typename internal_np::Lookup_named_param_def <
|
||||||
internal_np::graph_visitor_t,
|
internal_np::visitor_t,
|
||||||
NamedParameters1,
|
NamedParameters1,
|
||||||
Corefinement::Default_visitor<TriangleMesh>//default
|
Corefinement::Default_visitor<TriangleMesh>//default
|
||||||
> ::type User_visitor;
|
> ::type User_visitor;
|
||||||
User_visitor uv(choose_parameter<User_visitor>(get_parameter(np1, internal_np::graph_visitor)));
|
User_visitor uv(choose_parameter<User_visitor>(get_parameter(np1, internal_np::visitor)));
|
||||||
|
|
||||||
// surface intersection algorithm call
|
// surface intersection algorithm call
|
||||||
typedef Corefinement::Face_graph_output_builder<TriangleMesh,
|
typedef Corefinement::Face_graph_output_builder<TriangleMesh,
|
||||||
|
|
@ -777,11 +777,11 @@ corefine( TriangleMesh& tm1,
|
||||||
|
|
||||||
// User visitor
|
// User visitor
|
||||||
typedef typename internal_np::Lookup_named_param_def <
|
typedef typename internal_np::Lookup_named_param_def <
|
||||||
internal_np::graph_visitor_t,
|
internal_np::visitor_t,
|
||||||
NamedParameters1,
|
NamedParameters1,
|
||||||
Corefinement::Default_visitor<TriangleMesh>//default
|
Corefinement::Default_visitor<TriangleMesh>//default
|
||||||
> ::type User_visitor;
|
> ::type User_visitor;
|
||||||
User_visitor uv(choose_parameter<User_visitor>(get_parameter(np1, internal_np::graph_visitor)));
|
User_visitor uv(choose_parameter<User_visitor>(get_parameter(np1, internal_np::visitor)));
|
||||||
|
|
||||||
// surface intersection algorithm call
|
// surface intersection algorithm call
|
||||||
typedef Corefinement::No_extra_output_from_corefinement<TriangleMesh> Ob;
|
typedef Corefinement::No_extra_output_from_corefinement<TriangleMesh> Ob;
|
||||||
|
|
@ -867,11 +867,11 @@ autorefine( TriangleMesh& tm,
|
||||||
|
|
||||||
// User visitor
|
// User visitor
|
||||||
typedef typename internal_np::Lookup_named_param_def <
|
typedef typename internal_np::Lookup_named_param_def <
|
||||||
internal_np::graph_visitor_t,
|
internal_np::visitor_t,
|
||||||
NamedParameters,
|
NamedParameters,
|
||||||
Corefinement::Default_visitor<TriangleMesh>//default
|
Corefinement::Default_visitor<TriangleMesh>//default
|
||||||
> ::type User_visitor;
|
> ::type User_visitor;
|
||||||
User_visitor uv(choose_parameter<User_visitor>(get_parameter(np, internal_np::graph_visitor)));
|
User_visitor uv(choose_parameter<User_visitor>(get_parameter(np, internal_np::visitor)));
|
||||||
|
|
||||||
|
|
||||||
// surface intersection algorithm call
|
// surface intersection algorithm call
|
||||||
|
|
@ -964,11 +964,11 @@ autorefine_and_remove_self_intersections( TriangleMesh& tm,
|
||||||
|
|
||||||
// User visitor
|
// User visitor
|
||||||
typedef typename internal_np::Lookup_named_param_def <
|
typedef typename internal_np::Lookup_named_param_def <
|
||||||
internal_np::graph_visitor_t,
|
internal_np::visitor_t,
|
||||||
NamedParameters,
|
NamedParameters,
|
||||||
Corefinement::Default_visitor<TriangleMesh>//default
|
Corefinement::Default_visitor<TriangleMesh>//default
|
||||||
> ::type User_visitor;
|
> ::type User_visitor;
|
||||||
User_visitor uv(choose_parameter<User_visitor>(get_parameter(np, internal_np::graph_visitor)));
|
User_visitor uv(choose_parameter<User_visitor>(get_parameter(np, internal_np::visitor)));
|
||||||
|
|
||||||
// surface intersection algorithm call
|
// surface intersection algorithm call
|
||||||
typedef Corefinement::Output_builder_for_autorefinement<TriangleMesh,
|
typedef Corefinement::Output_builder_for_autorefinement<TriangleMesh,
|
||||||
|
|
|
||||||
|
|
@ -45,11 +45,32 @@ namespace CGAL {
|
||||||
|
|
||||||
namespace Polygon_mesh_processing {
|
namespace Polygon_mesh_processing {
|
||||||
|
|
||||||
|
namespace Triangulate_faces
|
||||||
|
{
|
||||||
|
/** \ingroup PMP_meshing_grp
|
||||||
|
* %Default new face visitor model of `PMPTriangulateFaceVisitor`.
|
||||||
|
* All its functions have an empty body. This class can be used as a
|
||||||
|
* base class if only some of the functions of the concept require to be
|
||||||
|
* overriden.
|
||||||
|
*/
|
||||||
|
template<class PolygonMesh>
|
||||||
|
struct Default_visitor {
|
||||||
|
typedef boost::graph_traits<PolygonMesh> GT;
|
||||||
|
typedef typename GT::face_descriptor face_descriptor;
|
||||||
|
|
||||||
|
void before_subface_creations(face_descriptor /*f_old*/) {}
|
||||||
|
void after_subface_creations() {}
|
||||||
|
void after_subface_created(face_descriptor /*f_new*/) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
} //end namespace Triangulate_faces
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
template <class PM
|
template <class PM
|
||||||
, typename VertexPointMap
|
, typename VertexPointMap
|
||||||
, typename Kernel>
|
, typename Kernel
|
||||||
|
, typename Visitor>
|
||||||
class Triangulate_modifier
|
class Triangulate_modifier
|
||||||
{
|
{
|
||||||
typedef Kernel Traits;
|
typedef Kernel Traits;
|
||||||
|
|
@ -80,7 +101,7 @@ public:
|
||||||
return fh->info().is_external;
|
return fh->info().is_external;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool triangulate_face(face_descriptor f, PM& pmesh, bool use_cdt)
|
bool triangulate_face(face_descriptor f, PM& pmesh, bool use_cdt, Visitor visitor)
|
||||||
{
|
{
|
||||||
typedef typename Traits::FT FT;
|
typedef typename Traits::FT FT;
|
||||||
|
|
||||||
|
|
@ -116,14 +137,15 @@ public:
|
||||||
*/
|
*/
|
||||||
FT p1p3 = CGAL::cross_product(p2-p1,p3-p2) * CGAL::cross_product(p0-p3,p1-p0);
|
FT p1p3 = CGAL::cross_product(p2-p1,p3-p2) * CGAL::cross_product(p0-p3,p1-p0);
|
||||||
FT p0p2 = CGAL::cross_product(p1-p0,p1-p2) * CGAL::cross_product(p3-p2,p3-p0);
|
FT p0p2 = CGAL::cross_product(p1-p0,p1-p2) * CGAL::cross_product(p3-p2,p3-p0);
|
||||||
if(p0p2>p1p3)
|
visitor.before_subface_creations(f);
|
||||||
{
|
halfedge_descriptor res = (p0p2>p1p3)
|
||||||
CGAL::Euler::split_face(v0, v2, pmesh);
|
? CGAL::Euler::split_face(v0, v2, pmesh)
|
||||||
}
|
: CGAL::Euler::split_face(v1, v3, pmesh);
|
||||||
else
|
|
||||||
{
|
visitor.after_subface_created(face(res,pmesh));
|
||||||
CGAL::Euler::split_face(v1, v3, pmesh);
|
visitor.after_subface_created(face(opposite(res,pmesh),pmesh));
|
||||||
}
|
|
||||||
|
visitor.after_subface_creations();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -143,18 +165,18 @@ public:
|
||||||
Itag> CDT;
|
Itag> CDT;
|
||||||
P_traits cdt_traits(normal);
|
P_traits cdt_traits(normal);
|
||||||
CDT cdt(cdt_traits);
|
CDT cdt(cdt_traits);
|
||||||
return triangulate_face_with_CDT(f, pmesh, cdt);
|
return triangulate_face_with_CDT(f, pmesh, cdt, visitor);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
CGAL_USE(use_cdt);
|
CGAL_USE(use_cdt);
|
||||||
#endif
|
#endif
|
||||||
return triangulate_face_with_hole_filling(f, pmesh);
|
return triangulate_face_with_hole_filling(f, pmesh, visitor);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class CDT>
|
template<class CDT>
|
||||||
bool triangulate_face_with_CDT(face_descriptor f, PM& pmesh, CDT& cdt)
|
bool triangulate_face_with_CDT(face_descriptor f, PM& pmesh, CDT& cdt, Visitor visitor)
|
||||||
{
|
{
|
||||||
std::size_t original_size = CGAL::halfedges_around_face(halfedge(f, pmesh), pmesh).size();
|
std::size_t original_size = CGAL::halfedges_around_face(halfedge(f, pmesh), pmesh).size();
|
||||||
|
|
||||||
|
|
@ -212,6 +234,7 @@ public:
|
||||||
|
|
||||||
|
|
||||||
// then modify the polyhedron
|
// then modify the polyhedron
|
||||||
|
visitor.before_subface_creations(f);
|
||||||
// make_hole. (see comment in function body)
|
// make_hole. (see comment in function body)
|
||||||
this->make_hole(halfedge(f, pmesh), pmesh);
|
this->make_hole(halfedge(f, pmesh), pmesh);
|
||||||
|
|
||||||
|
|
@ -268,12 +291,14 @@ public:
|
||||||
set_next(h2, h0, pmesh);
|
set_next(h2, h0, pmesh);
|
||||||
|
|
||||||
Euler::fill_hole(h0, pmesh);
|
Euler::fill_hole(h0, pmesh);
|
||||||
|
visitor.after_subface_created(face(h0, pmesh));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
visitor.after_subface_creations();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool triangulate_face_with_hole_filling(face_descriptor f, PM& pmesh)
|
bool triangulate_face_with_hole_filling(face_descriptor f, PM& pmesh, Visitor visitor)
|
||||||
{
|
{
|
||||||
namespace PMP = CGAL::Polygon_mesh_processing;
|
namespace PMP = CGAL::Polygon_mesh_processing;
|
||||||
|
|
||||||
|
|
@ -307,6 +332,7 @@ public:
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
visitor.before_subface_creations(f);
|
||||||
bool first = true;
|
bool first = true;
|
||||||
std::vector<halfedge_descriptor> hedges;
|
std::vector<halfedge_descriptor> hedges;
|
||||||
hedges.reserve(4);
|
hedges.reserve(4);
|
||||||
|
|
@ -316,6 +342,7 @@ public:
|
||||||
first=false;
|
first=false;
|
||||||
else
|
else
|
||||||
f=add_face(pmesh);
|
f=add_face(pmesh);
|
||||||
|
visitor.after_subface_created(f);
|
||||||
|
|
||||||
std::array<int, 4> indices =
|
std::array<int, 4> indices =
|
||||||
make_array( triangle.first,
|
make_array( triangle.first,
|
||||||
|
|
@ -346,11 +373,12 @@ public:
|
||||||
set_halfedge(f, hedges[0], pmesh);
|
set_halfedge(f, hedges[0], pmesh);
|
||||||
hedges.clear();
|
hedges.clear();
|
||||||
}
|
}
|
||||||
|
visitor.after_subface_creations();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename FaceRange>
|
template<typename FaceRange>
|
||||||
bool operator()(FaceRange face_range, PM& pmesh, bool use_cdt)
|
bool operator()(FaceRange face_range, PM& pmesh, bool use_cdt, Visitor visitor)
|
||||||
{
|
{
|
||||||
bool result = true;
|
bool result = true;
|
||||||
// One need to store facet handles into a vector, because the list of
|
// One need to store facet handles into a vector, because the list of
|
||||||
|
|
@ -368,7 +396,7 @@ public:
|
||||||
// Iterates on the vector of face descriptors
|
// Iterates on the vector of face descriptors
|
||||||
for(face_descriptor f : facets)
|
for(face_descriptor f : facets)
|
||||||
{
|
{
|
||||||
if(!this->triangulate_face(f, pmesh, use_cdt))
|
if(!this->triangulate_face(f, pmesh, use_cdt, visitor))
|
||||||
result = false;
|
result = false;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -422,6 +450,14 @@ public:
|
||||||
* \cgalParamDefault{a \cgal Kernel deduced from the point type, using `CGAL::Kernel_traits`}
|
* \cgalParamDefault{a \cgal Kernel deduced from the point type, using `CGAL::Kernel_traits`}
|
||||||
* \cgalParamExtra{The geometric traits class must be compatible with the vertex point type.}
|
* \cgalParamExtra{The geometric traits class must be compatible with the vertex point type.}
|
||||||
* \cgalParamNEnd
|
* \cgalParamNEnd
|
||||||
|
*
|
||||||
|
* \cgalParamNBegin{visitor}
|
||||||
|
* \cgalParamDescription{a visitor that enables to track how faces are triangulated into subfaces}
|
||||||
|
* \cgalParamType{a class model of `PMPTriangulateFaceVisitor`}
|
||||||
|
* \cgalParamDefault{`Triangulate_faces::Default_visitor<PolygonMesh>`}
|
||||||
|
* \cgalParamExtra{Note that the visitor will be copied, so
|
||||||
|
* it must not have any data member that does not have a reference-like type.}
|
||||||
|
* \cgalParamNEnd
|
||||||
* \cgalNamedParamsEnd
|
* \cgalNamedParamsEnd
|
||||||
*
|
*
|
||||||
* @return `true` if the face has been triangulated.
|
* @return `true` if the face has been triangulated.
|
||||||
|
|
@ -446,8 +482,17 @@ bool triangulate_face(typename boost::graph_traits<PolygonMesh>::face_descriptor
|
||||||
//Option
|
//Option
|
||||||
bool use_cdt = choose_parameter(get_parameter(np, internal_np::use_delaunay_triangulation), true);
|
bool use_cdt = choose_parameter(get_parameter(np, internal_np::use_delaunay_triangulation), true);
|
||||||
|
|
||||||
internal::Triangulate_modifier<PolygonMesh, VPMap, Kernel> modifier(vpmap, traits);
|
typedef typename internal_np::Lookup_named_param_def<
|
||||||
return modifier.triangulate_face(f, pmesh, use_cdt);
|
internal_np::visitor_t,
|
||||||
|
NamedParameters,
|
||||||
|
Triangulate_faces::Default_visitor<PolygonMesh>//default
|
||||||
|
>::type Visitor;
|
||||||
|
Visitor visitor = choose_parameter<Visitor>(
|
||||||
|
get_parameter(np, internal_np::visitor),
|
||||||
|
Triangulate_faces::Default_visitor<PolygonMesh>());
|
||||||
|
|
||||||
|
internal::Triangulate_modifier<PolygonMesh, VPMap, Kernel, Visitor> modifier(vpmap, traits);
|
||||||
|
return modifier.triangulate_face(f, pmesh, use_cdt, visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename PolygonMesh>
|
template<typename PolygonMesh>
|
||||||
|
|
@ -487,6 +532,14 @@ bool triangulate_face(typename boost::graph_traits<PolygonMesh>::face_descriptor
|
||||||
* \cgalParamDefault{a \cgal Kernel deduced from the point type, using `CGAL::Kernel_traits`}
|
* \cgalParamDefault{a \cgal Kernel deduced from the point type, using `CGAL::Kernel_traits`}
|
||||||
* \cgalParamExtra{The geometric traits class must be compatible with the vertex point type.}
|
* \cgalParamExtra{The geometric traits class must be compatible with the vertex point type.}
|
||||||
* \cgalParamNEnd
|
* \cgalParamNEnd
|
||||||
|
*
|
||||||
|
* \cgalParamNBegin{visitor}
|
||||||
|
* \cgalParamDescription{a visitor that enables to track how faces are triangulated into subfaces}
|
||||||
|
* \cgalParamType{a class model of `PMPTriangulateFaceVisitor`}
|
||||||
|
* \cgalParamDefault{`Triangulate_faces::Default_visitor<PolygonMesh>`}
|
||||||
|
* \cgalParamExtra{Note that the visitor will be copied, so
|
||||||
|
* it must not have any data member that does not have a reference-like type.}
|
||||||
|
* `\cgalParamNEnd
|
||||||
* \cgalNamedParamsEnd
|
* \cgalNamedParamsEnd
|
||||||
*
|
*
|
||||||
* @return `true` if all the faces have been triangulated.
|
* @return `true` if all the faces have been triangulated.
|
||||||
|
|
@ -513,8 +566,17 @@ bool triangulate_faces(FaceRange face_range,
|
||||||
//Option
|
//Option
|
||||||
bool use_cdt = choose_parameter(get_parameter(np, internal_np::use_delaunay_triangulation), true);
|
bool use_cdt = choose_parameter(get_parameter(np, internal_np::use_delaunay_triangulation), true);
|
||||||
|
|
||||||
internal::Triangulate_modifier<PolygonMesh, VPMap, Kernel> modifier(vpmap, traits);
|
typedef typename internal_np::Lookup_named_param_def<
|
||||||
return modifier(face_range, pmesh, use_cdt);
|
internal_np::visitor_t,
|
||||||
|
NamedParameters,
|
||||||
|
Triangulate_faces::Default_visitor<PolygonMesh>//default
|
||||||
|
>::type Visitor;
|
||||||
|
Visitor visitor = choose_parameter<Visitor>(
|
||||||
|
get_parameter(np, internal_np::visitor),
|
||||||
|
Triangulate_faces::Default_visitor<PolygonMesh>());
|
||||||
|
|
||||||
|
internal::Triangulate_modifier<PolygonMesh, VPMap, Kernel, Visitor> modifier(vpmap, traits);
|
||||||
|
return modifier(face_range, pmesh, use_cdt, visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename FaceRange, typename PolygonMesh>
|
template <typename FaceRange, typename PolygonMesh>
|
||||||
|
|
@ -548,6 +610,14 @@ bool triangulate_faces(FaceRange face_range, PolygonMesh& pmesh)
|
||||||
* \cgalParamDefault{a \cgal Kernel deduced from the point type, using `CGAL::Kernel_traits`}
|
* \cgalParamDefault{a \cgal Kernel deduced from the point type, using `CGAL::Kernel_traits`}
|
||||||
* \cgalParamExtra{The geometric traits class must be compatible with the vertex point type.}
|
* \cgalParamExtra{The geometric traits class must be compatible with the vertex point type.}
|
||||||
* \cgalParamNEnd
|
* \cgalParamNEnd
|
||||||
|
*
|
||||||
|
* \cgalParamNBegin{visitor}
|
||||||
|
* \cgalParamDescription{a visitor that enables to track how faces are triangulated into subfaces}
|
||||||
|
* \cgalParamType{a class model of `PMPTriangulateFaceVisitor`}
|
||||||
|
* \cgalParamDefault{`Triangulate_faces::Default_visitor<PolygonMesh>`}
|
||||||
|
* \cgalParamExtra{Note that the visitor will be copied, so
|
||||||
|
* it must not have any data member that does not have a reference-like type.}
|
||||||
|
* \cgalParamNEnd
|
||||||
* \cgalNamedParamsEnd
|
* \cgalNamedParamsEnd
|
||||||
*
|
*
|
||||||
* @return `true` if all the faces have been triangulated.
|
* @return `true` if all the faces have been triangulated.
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,7 @@ int edge_collapse(TM& tmesh,
|
||||||
choose_parameter<No_constrained_edge_map<TM> >(get_parameter(np, internal_np::edge_is_constrained)),
|
choose_parameter<No_constrained_edge_map<TM> >(get_parameter(np, internal_np::edge_is_constrained)),
|
||||||
choose_parameter<LindstromTurk_cost<TM> >(get_parameter(np, internal_np::get_cost_policy)),
|
choose_parameter<LindstromTurk_cost<TM> >(get_parameter(np, internal_np::get_cost_policy)),
|
||||||
choose_parameter<LindstromTurk_placement<TM> >(get_parameter(np, internal_np::get_placement_policy)),
|
choose_parameter<LindstromTurk_placement<TM> >(get_parameter(np, internal_np::get_placement_policy)),
|
||||||
choose_parameter<internal::Dummy_visitor>(get_parameter(np, internal_np::graph_visitor)));
|
choose_parameter<internal::Dummy_visitor>(get_parameter(np, internal_np::visitor)));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class TM, class ShouldStop>
|
template<class TM, class ShouldStop>
|
||||||
|
|
|
||||||
|
|
@ -244,12 +244,12 @@ void tetrahedral_isotropic_remeshing(
|
||||||
No_facet());
|
No_facet());
|
||||||
|
|
||||||
typedef typename internal_np::Lookup_named_param_def <
|
typedef typename internal_np::Lookup_named_param_def <
|
||||||
internal_np::remeshing_visitor_t,
|
internal_np::visitor_t,
|
||||||
NamedParameters,
|
NamedParameters,
|
||||||
Tetrahedral_remeshing::internal::Default_remeshing_visitor
|
Tetrahedral_remeshing::internal::Default_remeshing_visitor
|
||||||
> ::type Visitor;
|
> ::type Visitor;
|
||||||
Visitor visitor
|
Visitor visitor
|
||||||
= choose_parameter(get_parameter(np, internal_np::remeshing_visitor),
|
= choose_parameter(get_parameter(np, internal_np::visitor),
|
||||||
Tetrahedral_remeshing::internal::Default_remeshing_visitor());
|
Tetrahedral_remeshing::internal::Default_remeshing_visitor());
|
||||||
|
|
||||||
#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE
|
#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE
|
||||||
|
|
@ -439,12 +439,12 @@ void tetrahedral_isotropic_remeshing(
|
||||||
No_facet());
|
No_facet());
|
||||||
|
|
||||||
typedef typename internal_np::Lookup_named_param_def <
|
typedef typename internal_np::Lookup_named_param_def <
|
||||||
internal_np::remeshing_visitor_t,
|
internal_np::visitor_t,
|
||||||
NamedParameters,
|
NamedParameters,
|
||||||
Tetrahedral_remeshing::internal::Default_remeshing_visitor
|
Tetrahedral_remeshing::internal::Default_remeshing_visitor
|
||||||
> ::type Visitor;
|
> ::type Visitor;
|
||||||
Visitor visitor
|
Visitor visitor
|
||||||
= choose_parameter(get_parameter(np, internal_np::remeshing_visitor),
|
= choose_parameter(get_parameter(np, internal_np::visitor),
|
||||||
Tetrahedral_remeshing::internal::Default_remeshing_visitor());
|
Tetrahedral_remeshing::internal::Default_remeshing_visitor());
|
||||||
|
|
||||||
#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE
|
#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue