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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#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
|
||||
|
||||
/**
|
||||
|
|
@ -667,7 +695,10 @@ clip(TriangleMesh& tm,
|
|||
* \cgalParamNEnd
|
||||
*
|
||||
* \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`}
|
||||
* \cgalParamDefault{`Corefinement::Default_visitor<PolygonMesh>`}
|
||||
* \cgalParamNEnd
|
||||
|
|
@ -731,6 +762,7 @@ bool clip(PolygonMesh& pm,
|
|||
{
|
||||
using parameters::choose_parameter;
|
||||
using parameters::get_parameter;
|
||||
using parameters::get_parameter_reference ;
|
||||
|
||||
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),
|
||||
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 <
|
||||
internal_np::concurrency_tag_t,
|
||||
NamedParameters,
|
||||
|
|
@ -769,16 +808,15 @@ bool clip(PolygonMesh& pm,
|
|||
.do_not_triangulate_faces(!triangulate)
|
||||
.throw_on_self_intersection(!allow_self_intersections &&
|
||||
throw_on_self_intersection)
|
||||
.visitor(visitor)
|
||||
.concurrency_tag(Concurrency_tag()));
|
||||
|
||||
|
||||
if (allow_self_intersections)
|
||||
clip_volume=false;
|
||||
|
||||
if (clip_volume && !is_closed(pm)) clip_volume=false;
|
||||
if (clip_volume && !use_compact_clipper) use_compact_clipper=true;
|
||||
|
||||
|
||||
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));
|
||||
|
|
@ -815,10 +853,22 @@ bool clip(PolygonMesh& pm,
|
|||
|
||||
for (halfedge_descriptor h : borders)
|
||||
{
|
||||
visitor.before_face_copy(boost::graph_traits<PolygonMesh>::null_face(), pm, 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
|
||||
if (triangulate)
|
||||
triangulate_face(face(h,pm), pm, parameters::vertex_point_map(vpm).geom_traits(traits));
|
||||
{
|
||||
if constexpr (!has_visitor)
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
@ -1051,7 +1101,10 @@ void split(TriangleMesh& tm,
|
|||
* \cgalParamNEnd
|
||||
*
|
||||
* \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`}
|
||||
* \cgalParamDefault{`Corefinement::Default_visitor<TriangleMesh>`}
|
||||
* \cgalParamNEnd
|
||||
|
|
|
|||
|
|
@ -32,12 +32,38 @@ namespace Polygon_mesh_processing {
|
|||
template <class PolygonMesh>
|
||||
struct Default_cut_visitor
|
||||
{
|
||||
/// called before splitting an edge
|
||||
void before_edge_split(typename boost::graph_traits<PolygonMesh>::halfedge_descriptor, PolygonMesh&) {}
|
||||
/// called after an edge split, `h` = the new halfedge pointing to the new vertex
|
||||
void edge_split(typename boost::graph_traits<PolygonMesh>::halfedge_descriptor, PolygonMesh&) {}
|
||||
/// gives access to all the vertex that are on the cutting plane
|
||||
void vertices_on_cut(const std::vector<typename boost::graph_traits<PolygonMesh>::vertex_descriptor>&, PolygonMesh&){}
|
||||
using halfedge_descriptor = typename boost::graph_traits<PolygonMesh>::halfedge_descriptor;
|
||||
using face_descriptor = typename boost::graph_traits<PolygonMesh>::face_descriptor;
|
||||
using vertex_descriptor = typename boost::graph_traits<PolygonMesh>::vertex_descriptor;
|
||||
|
||||
/// @name Functions used for tracking face splits
|
||||
/// @{
|
||||
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
|
||||
|
|
@ -223,6 +249,8 @@ void refine_with_plane(PolygonMesh& pm,
|
|||
|
||||
Default_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),
|
||||
get_property_map(vertex_point, pm));
|
||||
|
||||
|
|
@ -284,6 +312,8 @@ void refine_with_plane(PolygonMesh& pm,
|
|||
break;
|
||||
case ON_ORIENTED_BOUNDARY:
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
@ -326,13 +356,17 @@ void refine_with_plane(PolygonMesh& pm,
|
|||
else
|
||||
if (get(vertex_os, tgt)!=CGAL::ON_ORIENTED_BOUNDARY &&
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (all_in || all_out)
|
||||
{
|
||||
visitor.vertices_on_cut(on_obnd, pm);
|
||||
//visitor.vertices_on_cut(on_obnd, pm);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -358,6 +392,7 @@ void refine_with_plane(PolygonMesh& pm,
|
|||
}
|
||||
|
||||
//TODO: parallel for
|
||||
std::size_t vid=on_obnd.size();
|
||||
for (edge_descriptor e : inters)
|
||||
{
|
||||
halfedge_descriptor h = halfedge(e, pm);
|
||||
|
|
@ -368,8 +403,10 @@ void refine_with_plane(PolygonMesh& pm,
|
|||
visitor.before_edge_split(h, pm);
|
||||
h = CGAL::Euler::split_edge(h, pm);
|
||||
put(vpm, target(h, pm), ip);
|
||||
visitor.new_vertex_added(vid, target(h,pm), pm);
|
||||
put(vertex_os, target(h, pm), ON_ORIENTED_BOUNDARY);
|
||||
visitor.edge_split(h, pm);
|
||||
visitor.after_edge_split();
|
||||
if (was_marked)
|
||||
put(ecm, edge(h, pm), true);
|
||||
|
||||
|
|
@ -378,9 +415,10 @@ void refine_with_plane(PolygonMesh& pm,
|
|||
h=prev(opposite(h,pm),pm);
|
||||
if (!is_border(h, pm))
|
||||
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
|
||||
for (vertex_descriptor v : on_obnd)
|
||||
|
|
@ -403,12 +441,17 @@ void refine_with_plane(PolygonMesh& pm,
|
|||
|
||||
CGAL_assertion( nb_hedges%2 ==0 );
|
||||
|
||||
visitor.before_subface_creations(f_and_hs.first, pm);
|
||||
|
||||
if (nb_hedges==2)
|
||||
{
|
||||
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
|
||||
visitor.before_subface_created(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);
|
||||
visitor.add_retriangulation_edge(res, pm);
|
||||
|
||||
if (triangulate)
|
||||
{
|
||||
|
|
@ -418,6 +461,7 @@ void refine_with_plane(PolygonMesh& pm,
|
|||
halfedge_descriptor newh =
|
||||
CGAL::Euler::split_face(res, next(next(res, pm), pm), pm);
|
||||
put(edge_is_marked, edge(newh, pm), false);
|
||||
visitor.add_retriangulation_edge(newh, pm);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -425,8 +469,10 @@ void refine_with_plane(PolygonMesh& pm,
|
|||
if (!is_triangle(res, pm))
|
||||
{
|
||||
// TODO: take the criteria in triangulate_faces ?
|
||||
visitor.before_subface_created(pm);
|
||||
halfedge_descriptor newh =
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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];
|
||||
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);
|
||||
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);
|
||||
visitor.add_retriangulation_edge(res, pm);
|
||||
}
|
||||
}
|
||||
|
||||
visitor.after_subface_creations(pm);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue