mirror of https://github.com/CGAL/cgal
add backward compatible visitor calls
This commit is contained in:
parent
e001c7ce53
commit
dc024f7e03
|
|
@ -516,6 +516,34 @@ generic_clip_impl(
|
||||||
functor(CGAL::Emptyset_iterator(), false, true);
|
functor(CGAL::Emptyset_iterator(), false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef CGAL_PLANE_CLIP_DO_NOT_USE_TRIANGULATION
|
||||||
|
template <class PolygonMesh, class Clip_visitor>
|
||||||
|
struct Visitor_wrapper_for_triangulate_face
|
||||||
|
{
|
||||||
|
using face_descriptor = typename boost::graph_traits<PolygonMesh>::face_descriptor;
|
||||||
|
|
||||||
|
Clip_visitor& clip_visitor;
|
||||||
|
const PolygonMesh& pm;
|
||||||
|
|
||||||
|
Visitor_wrapper_for_triangulate_face(const PolygonMesh& pm, Clip_visitor& clip_visitor)
|
||||||
|
: pm(pm)
|
||||||
|
, clip_visitor(clip_visitor)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void before_subface_creations(face_descriptor /* f_split */) {}
|
||||||
|
void after_subface_creations() {}
|
||||||
|
|
||||||
|
void after_subface_created(face_descriptor f_new)
|
||||||
|
{
|
||||||
|
clip_visitor.before_face_copy(boost::graph_traits<PolygonMesh>::null_face(), pm, pm);
|
||||||
|
clip_visitor.after_face_copy(boost::graph_traits<PolygonMesh>::null_face(), pm, f_new, pm);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
} // end of internal namespace
|
} // end of internal namespace
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -667,7 +695,10 @@ clip(TriangleMesh& tm,
|
||||||
* \cgalParamNEnd
|
* \cgalParamNEnd
|
||||||
*
|
*
|
||||||
* \cgalParamNBegin{visitor}
|
* \cgalParamNBegin{visitor}
|
||||||
* \cgalParamDescription{a visitor used to track the creation of new faces}
|
* \cgalParamDescription{a visitor used to track the creation of new faces, edges, and faces.
|
||||||
|
* Note that as there are no mesh associated with `plane`,
|
||||||
|
* `boost::graph_traits<PolygonMesh>::null_halfedge()` and `boost::graph_traits<PolygonMesh>::null_face()` will be used when calling
|
||||||
|
* functions of the visitor expecting a halfedge or a face from `plane`. Similarly, `pm` will be used as the mesh of `plane`.}
|
||||||
* \cgalParamType{a class model of `PMPCorefinementVisitor`}
|
* \cgalParamType{a class model of `PMPCorefinementVisitor`}
|
||||||
* \cgalParamDefault{`Corefinement::Default_visitor<PolygonMesh>`}
|
* \cgalParamDefault{`Corefinement::Default_visitor<PolygonMesh>`}
|
||||||
* \cgalParamNEnd
|
* \cgalParamNEnd
|
||||||
|
|
@ -731,6 +762,7 @@ bool clip(PolygonMesh& pm,
|
||||||
{
|
{
|
||||||
using parameters::choose_parameter;
|
using parameters::choose_parameter;
|
||||||
using parameters::get_parameter;
|
using parameters::get_parameter;
|
||||||
|
using parameters::get_parameter_reference ;
|
||||||
|
|
||||||
using halfedge_descriptor = typename boost::graph_traits<PolygonMesh>::halfedge_descriptor;
|
using halfedge_descriptor = typename boost::graph_traits<PolygonMesh>::halfedge_descriptor;
|
||||||
|
|
||||||
|
|
@ -739,6 +771,13 @@ bool clip(PolygonMesh& pm,
|
||||||
auto vpm = choose_parameter(get_parameter(np, internal_np::vertex_point),
|
auto vpm = choose_parameter(get_parameter(np, internal_np::vertex_point),
|
||||||
get_property_map(vertex_point, pm));
|
get_property_map(vertex_point, pm));
|
||||||
|
|
||||||
|
|
||||||
|
using Default_visitor = Corefinement::Default_visitor<PolygonMesh>;
|
||||||
|
Default_visitor default_visitor;
|
||||||
|
using Visitor_ref = typename internal_np::Lookup_named_param_def<internal_np::visitor_t, NamedParameters, Default_visitor>::reference;
|
||||||
|
Visitor_ref visitor = choose_parameter(get_parameter_reference(np, internal_np::visitor), default_visitor);
|
||||||
|
constexpr bool has_visitor = !std::is_same_v<Default_visitor, std::remove_cv_t<std::remove_reference_t<Visitor_ref>>>;
|
||||||
|
|
||||||
typedef typename internal_np::Lookup_named_param_def <
|
typedef typename internal_np::Lookup_named_param_def <
|
||||||
internal_np::concurrency_tag_t,
|
internal_np::concurrency_tag_t,
|
||||||
NamedParameters,
|
NamedParameters,
|
||||||
|
|
@ -769,16 +808,15 @@ bool clip(PolygonMesh& pm,
|
||||||
.do_not_triangulate_faces(!triangulate)
|
.do_not_triangulate_faces(!triangulate)
|
||||||
.throw_on_self_intersection(!allow_self_intersections &&
|
.throw_on_self_intersection(!allow_self_intersections &&
|
||||||
throw_on_self_intersection)
|
throw_on_self_intersection)
|
||||||
|
.visitor(visitor)
|
||||||
.concurrency_tag(Concurrency_tag()));
|
.concurrency_tag(Concurrency_tag()));
|
||||||
|
|
||||||
|
|
||||||
if (allow_self_intersections)
|
if (allow_self_intersections)
|
||||||
clip_volume=false;
|
clip_volume=false;
|
||||||
|
|
||||||
if (clip_volume && !is_closed(pm)) clip_volume=false;
|
if (clip_volume && !is_closed(pm)) clip_volume=false;
|
||||||
if (clip_volume && !use_compact_clipper) use_compact_clipper=true;
|
if (clip_volume && !use_compact_clipper) use_compact_clipper=true;
|
||||||
|
|
||||||
|
|
||||||
auto fcc = get(dynamic_face_property_t<std::size_t>(), pm);
|
auto fcc = get(dynamic_face_property_t<std::size_t>(), pm);
|
||||||
|
|
||||||
std::size_t nbcc = connected_components(pm, fcc, CGAL::parameters::edge_is_constrained_map(ecm));
|
std::size_t nbcc = connected_components(pm, fcc, CGAL::parameters::edge_is_constrained_map(ecm));
|
||||||
|
|
@ -815,10 +853,22 @@ bool clip(PolygonMesh& pm,
|
||||||
|
|
||||||
for (halfedge_descriptor h : borders)
|
for (halfedge_descriptor h : borders)
|
||||||
{
|
{
|
||||||
|
visitor.before_face_copy(boost::graph_traits<PolygonMesh>::null_face(), pm, pm);
|
||||||
Euler::fill_hole(h, pm);
|
Euler::fill_hole(h, pm);
|
||||||
|
visitor.after_face_copy(boost::graph_traits<PolygonMesh>::null_face(), pm, face(h, pm), pm);
|
||||||
|
|
||||||
#ifndef CGAL_PLANE_CLIP_DO_NOT_USE_TRIANGULATION
|
#ifndef CGAL_PLANE_CLIP_DO_NOT_USE_TRIANGULATION
|
||||||
if (triangulate)
|
if (triangulate)
|
||||||
|
{
|
||||||
|
if constexpr (!has_visitor)
|
||||||
triangulate_face(face(h,pm), pm, parameters::vertex_point_map(vpm).geom_traits(traits));
|
triangulate_face(face(h,pm), pm, parameters::vertex_point_map(vpm).geom_traits(traits));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
using Base_visitor = std::remove_cv_t<std::remove_reference_t<Visitor_ref>>;
|
||||||
|
internal::Visitor_wrapper_for_triangulate_face<PolygonMesh, Base_visitor> visitor_wrapper(pm, visitor);
|
||||||
|
triangulate_face(face(h,pm), pm, parameters::vertex_point_map(vpm).geom_traits(traits).visitor(visitor_wrapper));
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1051,7 +1101,10 @@ void split(TriangleMesh& tm,
|
||||||
* \cgalParamNEnd
|
* \cgalParamNEnd
|
||||||
*
|
*
|
||||||
* \cgalParamNBegin{visitor}
|
* \cgalParamNBegin{visitor}
|
||||||
* \cgalParamDescription{a visitor used to track the creation of new faces}
|
* \cgalParamDescription{a visitor used to track the creation of new faces, edges, and vertices.
|
||||||
|
* Note that as there are no mesh associated with `plane`,
|
||||||
|
* `boost::graph_traits<PolygonMesh>::null_halfedge()` and `boost::graph_traits<PolygonMesh>::null_face()` will be used when calling
|
||||||
|
* functions of the visitor expecting a halfedge or a face from `plane`. Similarly, `pm` will be used as the mesh of `plane`.}}
|
||||||
* \cgalParamType{a class model of `PMPCorefinementVisitor`}
|
* \cgalParamType{a class model of `PMPCorefinementVisitor`}
|
||||||
* \cgalParamDefault{`Corefinement::Default_visitor<TriangleMesh>`}
|
* \cgalParamDefault{`Corefinement::Default_visitor<TriangleMesh>`}
|
||||||
* \cgalParamNEnd
|
* \cgalParamNEnd
|
||||||
|
|
|
||||||
|
|
@ -32,12 +32,38 @@ namespace Polygon_mesh_processing {
|
||||||
template <class PolygonMesh>
|
template <class PolygonMesh>
|
||||||
struct Default_cut_visitor
|
struct Default_cut_visitor
|
||||||
{
|
{
|
||||||
/// called before splitting an edge
|
using halfedge_descriptor = typename boost::graph_traits<PolygonMesh>::halfedge_descriptor;
|
||||||
void before_edge_split(typename boost::graph_traits<PolygonMesh>::halfedge_descriptor, PolygonMesh&) {}
|
using face_descriptor = typename boost::graph_traits<PolygonMesh>::face_descriptor;
|
||||||
/// called after an edge split, `h` = the new halfedge pointing to the new vertex
|
using vertex_descriptor = typename boost::graph_traits<PolygonMesh>::vertex_descriptor;
|
||||||
void edge_split(typename boost::graph_traits<PolygonMesh>::halfedge_descriptor, PolygonMesh&) {}
|
|
||||||
/// gives access to all the vertex that are on the cutting plane
|
/// @name Functions used for tracking face splits
|
||||||
void vertices_on_cut(const std::vector<typename boost::graph_traits<PolygonMesh>::vertex_descriptor>&, PolygonMesh&){}
|
/// @{
|
||||||
|
void before_subface_creations(face_descriptor /* f_split */, const PolygonMesh& /* pm */){}
|
||||||
|
void after_subface_creations(const PolygonMesh& /* pm */){}
|
||||||
|
void before_subface_created(const PolygonMesh& /* pm */){}
|
||||||
|
void after_subface_created(face_descriptor /* f_new */, const PolygonMesh& /* pm */){}
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
/// @name Functions used for tracking edge splits and edge creation
|
||||||
|
/// @{
|
||||||
|
void before_edge_split(halfedge_descriptor, PolygonMesh&) {}
|
||||||
|
void edge_split(halfedge_descriptor, PolygonMesh&) {}
|
||||||
|
void after_edge_split(){}
|
||||||
|
void add_retriangulation_edge(halfedge_descriptor h, const PolygonMesh& pm){}
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
/// @name Functions used when a new vertex is created
|
||||||
|
///@{
|
||||||
|
void intersection_point_detected(std::size_t /* i_id */,
|
||||||
|
int /* sdim */,
|
||||||
|
halfedge_descriptor /* h_e */,
|
||||||
|
halfedge_descriptor /* h_f */,
|
||||||
|
const PolygonMesh& /* tm_e */,
|
||||||
|
const PolygonMesh& /* tm_f */,
|
||||||
|
bool /* is_target_coplanar */,
|
||||||
|
bool /* is_source_coplanar */){}
|
||||||
|
void new_vertex_added(std::size_t /* i_id */, vertex_descriptor /* v */, const PolygonMesh& /* pm */) {}
|
||||||
|
///@}
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: doc me or hide me in the np
|
// TODO: doc me or hide me in the np
|
||||||
|
|
@ -223,6 +249,8 @@ void refine_with_plane(PolygonMesh& pm,
|
||||||
|
|
||||||
Default_visitor default_visitor;
|
Default_visitor default_visitor;
|
||||||
Visitor_ref visitor = choose_parameter(get_parameter_reference(np, internal_np::visitor), default_visitor);
|
Visitor_ref visitor = choose_parameter(get_parameter_reference(np, internal_np::visitor), default_visitor);
|
||||||
|
constexpr bool has_visitor = !std::is_same_v<Default_visitor, std::remove_cv_t<std::remove_reference_t<Visitor_ref>>>;
|
||||||
|
|
||||||
auto vpm = choose_parameter(get_parameter(np, internal_np::vertex_point),
|
auto vpm = choose_parameter(get_parameter(np, internal_np::vertex_point),
|
||||||
get_property_map(vertex_point, pm));
|
get_property_map(vertex_point, pm));
|
||||||
|
|
||||||
|
|
@ -284,6 +312,8 @@ void refine_with_plane(PolygonMesh& pm,
|
||||||
break;
|
break;
|
||||||
case ON_ORIENTED_BOUNDARY:
|
case ON_ORIENTED_BOUNDARY:
|
||||||
at_least_one_on=true;
|
at_least_one_on=true;
|
||||||
|
visitor.intersection_point_detected(on_obnd.size(), 2, halfedge(v, pm), boost::graph_traits<PolygonMesh>::null_halfedge(),
|
||||||
|
pm, pm, true, false);
|
||||||
on_obnd.push_back(v);
|
on_obnd.push_back(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -326,13 +356,17 @@ void refine_with_plane(PolygonMesh& pm,
|
||||||
else
|
else
|
||||||
if (get(vertex_os, tgt)!=CGAL::ON_ORIENTED_BOUNDARY &&
|
if (get(vertex_os, tgt)!=CGAL::ON_ORIENTED_BOUNDARY &&
|
||||||
get(vertex_os, src)!=get(vertex_os, tgt))
|
get(vertex_os, src)!=get(vertex_os, tgt))
|
||||||
|
{
|
||||||
|
visitor.intersection_point_detected(on_obnd.size()+inters.size(), 2, halfedge(e, pm), boost::graph_traits<PolygonMesh>::null_halfedge(),
|
||||||
|
pm, pm, false, false);
|
||||||
inters.push_back(e);
|
inters.push_back(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (all_in || all_out)
|
if (all_in || all_out)
|
||||||
{
|
{
|
||||||
visitor.vertices_on_cut(on_obnd, pm);
|
//visitor.vertices_on_cut(on_obnd, pm);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -358,6 +392,7 @@ void refine_with_plane(PolygonMesh& pm,
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: parallel for
|
//TODO: parallel for
|
||||||
|
std::size_t vid=on_obnd.size();
|
||||||
for (edge_descriptor e : inters)
|
for (edge_descriptor e : inters)
|
||||||
{
|
{
|
||||||
halfedge_descriptor h = halfedge(e, pm);
|
halfedge_descriptor h = halfedge(e, pm);
|
||||||
|
|
@ -368,8 +403,10 @@ void refine_with_plane(PolygonMesh& pm,
|
||||||
visitor.before_edge_split(h, pm);
|
visitor.before_edge_split(h, pm);
|
||||||
h = CGAL::Euler::split_edge(h, pm);
|
h = CGAL::Euler::split_edge(h, pm);
|
||||||
put(vpm, target(h, pm), ip);
|
put(vpm, target(h, pm), ip);
|
||||||
|
visitor.new_vertex_added(vid, target(h,pm), pm);
|
||||||
put(vertex_os, target(h, pm), ON_ORIENTED_BOUNDARY);
|
put(vertex_os, target(h, pm), ON_ORIENTED_BOUNDARY);
|
||||||
visitor.edge_split(h, pm);
|
visitor.edge_split(h, pm);
|
||||||
|
visitor.after_edge_split();
|
||||||
if (was_marked)
|
if (was_marked)
|
||||||
put(ecm, edge(h, pm), true);
|
put(ecm, edge(h, pm), true);
|
||||||
|
|
||||||
|
|
@ -378,9 +415,10 @@ void refine_with_plane(PolygonMesh& pm,
|
||||||
h=prev(opposite(h,pm),pm);
|
h=prev(opposite(h,pm),pm);
|
||||||
if (!is_border(h, pm))
|
if (!is_border(h, pm))
|
||||||
splitted_faces[face(h, pm)].push_back(h);
|
splitted_faces[face(h, pm)].push_back(h);
|
||||||
|
++vid;
|
||||||
}
|
}
|
||||||
|
|
||||||
visitor.vertices_on_cut(on_obnd, pm);
|
// visitor.vertices_on_cut(on_obnd, pm);
|
||||||
|
|
||||||
// collect faces to be cut that have one vertex on the cut plane
|
// collect faces to be cut that have one vertex on the cut plane
|
||||||
for (vertex_descriptor v : on_obnd)
|
for (vertex_descriptor v : on_obnd)
|
||||||
|
|
@ -403,12 +441,17 @@ void refine_with_plane(PolygonMesh& pm,
|
||||||
|
|
||||||
CGAL_assertion( nb_hedges%2 ==0 );
|
CGAL_assertion( nb_hedges%2 ==0 );
|
||||||
|
|
||||||
|
visitor.before_subface_creations(f_and_hs.first, pm);
|
||||||
|
|
||||||
if (nb_hedges==2)
|
if (nb_hedges==2)
|
||||||
{
|
{
|
||||||
halfedge_descriptor h1=f_and_hs.second[0], h2=f_and_hs.second[1];
|
halfedge_descriptor h1=f_and_hs.second[0], h2=f_and_hs.second[1];
|
||||||
CGAL_assertion(next(h1,pm)!=h2 && next(h2,pm)!=h1); // the edge does not already exist
|
CGAL_assertion(next(h1,pm)!=h2 && next(h2,pm)!=h1); // the edge does not already exist
|
||||||
|
visitor.before_subface_created(pm);
|
||||||
halfedge_descriptor res = CGAL::Euler::split_face(h1, h2, pm);
|
halfedge_descriptor res = CGAL::Euler::split_face(h1, h2, pm);
|
||||||
|
visitor.after_subface_created(face(res, pm), pm);
|
||||||
put(edge_is_marked, edge(res, pm), true);
|
put(edge_is_marked, edge(res, pm), true);
|
||||||
|
visitor.add_retriangulation_edge(res, pm);
|
||||||
|
|
||||||
if (triangulate)
|
if (triangulate)
|
||||||
{
|
{
|
||||||
|
|
@ -418,6 +461,7 @@ void refine_with_plane(PolygonMesh& pm,
|
||||||
halfedge_descriptor newh =
|
halfedge_descriptor newh =
|
||||||
CGAL::Euler::split_face(res, next(next(res, pm), pm), pm);
|
CGAL::Euler::split_face(res, next(next(res, pm), pm), pm);
|
||||||
put(edge_is_marked, edge(newh, pm), false);
|
put(edge_is_marked, edge(newh, pm), false);
|
||||||
|
visitor.add_retriangulation_edge(newh, pm);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -425,8 +469,10 @@ void refine_with_plane(PolygonMesh& pm,
|
||||||
if (!is_triangle(res, pm))
|
if (!is_triangle(res, pm))
|
||||||
{
|
{
|
||||||
// TODO: take the criteria in triangulate_faces ?
|
// TODO: take the criteria in triangulate_faces ?
|
||||||
|
visitor.before_subface_created(pm);
|
||||||
halfedge_descriptor newh =
|
halfedge_descriptor newh =
|
||||||
CGAL::Euler::split_face(res, next(next(res, pm), pm), pm);
|
CGAL::Euler::split_face(res, next(next(res, pm), pm), pm);
|
||||||
|
visitor.after_subface_created(face(newh, pm), pm);
|
||||||
put(edge_is_marked, edge(newh, pm), false);
|
put(edge_is_marked, edge(newh, pm), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -447,10 +493,19 @@ void refine_with_plane(PolygonMesh& pm,
|
||||||
{
|
{
|
||||||
halfedge_descriptor h1=f_and_hs.second[i], h2=f_and_hs.second[i+1];
|
halfedge_descriptor h1=f_and_hs.second[i], h2=f_and_hs.second[i+1];
|
||||||
CGAL_assertion(next(h1,pm)!=h2 && next(h2,pm)!=h1); // the edge does not already exist
|
CGAL_assertion(next(h1,pm)!=h2 && next(h2,pm)!=h1); // the edge does not already exist
|
||||||
|
visitor.before_subface_created(pm);
|
||||||
halfedge_descriptor res = CGAL::Euler::split_face(h1, h2, pm);
|
halfedge_descriptor res = CGAL::Euler::split_face(h1, h2, pm);
|
||||||
|
if constexpr (has_visitor)
|
||||||
|
{
|
||||||
|
if (face(h1,pm)!=face(h2,pm))
|
||||||
|
visitor.after_subface_created(face(res, pm), pm);
|
||||||
|
}
|
||||||
put(edge_is_marked, edge(res, pm), true);
|
put(edge_is_marked, edge(res, pm), true);
|
||||||
|
visitor.add_retriangulation_edge(res, pm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
visitor.after_subface_creations(pm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue