Merge remote-tracking branch 'cgal/6.0.x-branch' into 'cgal/6.1.x-branch'

This commit is contained in:
Sébastien Loriot 2025-12-19 17:34:39 +01:00
commit f5c550ef44
6 changed files with 110 additions and 34 deletions

View File

@ -484,19 +484,19 @@ public:
private:
/**
* @brief Computes bounding box of one primitive
* @brief Computes the bounding box of a primitive
* @param pr the primitive
* @return the bounding box of the primitive \c pr
*/
template <typename PM>
Bounding_box compute_bbox(const Primitive& pr, const PM&)const
Bounding_box compute_bbox(const Primitive& pr, const PM&) const
{
return get(bbm, pr.id());
}
Bounding_box compute_bbox(const Primitive& pr, const Default&)const
Bounding_box compute_bbox(const Primitive& pr, const Default&) const
{
return GeomTraits().construct_bbox_2_object()(internal::Primitive_helper<AT>::get_datum(pr, *this));
return internal::Primitive_helper<AT>::get_datum(pr,*this).bbox();
}
/// Comparison functions

View File

@ -1537,6 +1537,7 @@ does_satisfy_link_condition(typename boost::graph_traits<Graph>::edge_descriptor
* collapses an edge in a graph.
*
* \tparam Graph must be a model of `MutableFaceGraph`
*
* Let `h` be the halfedge of `e`, and let `v0` and `v1` be the source and target vertices of `h`.
* Let `p_h` and `p_o_h` be respectively the edges of `prev(h,g)` and `prev(opposite(h, g), g)`.
* Let `o_n_h` and `o_n_o_h` be respectively the edges of `opposite(next(h,g))` and `opposite(next(opposite(h, g), g))`.

View File

@ -105,12 +105,19 @@ void simplify_range(HalfedgeRange& halfedge_range,
typedef CGAL::dynamic_halfedge_property_t<bool> Halfedge_bool_tag;
typedef typename boost::property_map<TriangleMesh, Halfedge_bool_tag>::type Range_halfedges;
const bool all_hedges = (::CGAL::internal::exact_num_halfedges(tm)==halfedge_range.size());
#ifdef CGAL_PMP_SNAP_DEBUG_OUTPUT
static int i = 0;
std::ofstream out_in("results/before_simplification_" + std::to_string(i++) + ".polylines.txt");
out_in.precision(17);
#endif
Range_halfedges range_halfedges = get(Halfedge_bool_tag(), tm, all_hedges);
if (!all_hedges)
for(halfedge_descriptor h : halfedge_range)
put(range_halfedges, h, true);
Range_halfedges range_halfedges = get(Halfedge_bool_tag(), tm, false);
for(halfedge_descriptor h : halfedge_range) {
#ifdef CGAL_PMP_SNAP_DEBUG_OUTPUT
out_in << "2 " << get(vpm, source(h, tm)) << " " << get(vpm, target(h, tm)) << "\n";
#endif
put(range_halfedges, h, true);
}
CGAL_postcondition_code(const std::size_t initial_n = halfedge_range.size();)
@ -121,6 +128,9 @@ void simplify_range(HalfedgeRange& halfedge_range,
while(!edges_to_test.empty())
{
const halfedge_descriptor h = *(edges_to_test.begin());
CGAL_precondition(is_border(h, tm));
CGAL_precondition(!is_border(opposite(h, tm), tm));
edges_to_test.erase(edges_to_test.begin());
const vertex_descriptor vs = source(h, tm);
@ -136,8 +146,7 @@ void simplify_range(HalfedgeRange& halfedge_range,
if(gt.compare_squared_distance_3_object()(ps,pt,CGAL::square(max_tol)) == SMALLER)
{
const halfedge_descriptor prev_h = prev(h, tm);
const halfedge_descriptor next_h = next(h, tm);
CGAL_precondition_code(const halfedge_descriptor prev_h = prev(h, tm);)
const halfedge_descriptor prev_oh = prev(opposite(h, tm), tm);
// check that the border has at least 4 edges not to create degenerate volumes
@ -190,19 +199,38 @@ void simplify_range(HalfedgeRange& halfedge_range,
if(!CGAL::Euler::does_satisfy_link_condition(edge(h, tm), tm))
continue;
// Since `o_h` is not a border halfedge, `prev(opp(h))` gets replaced with `opp(next(opp(h)))`.
// But `prev(opp(h))` might have been be a border edge whereas `opp(next(opp(h)))` might not be.
// So, if `opp(prev(opp(h)))` was a border halfedge in the range, we must add `next(opp(h))`
// to the range.
const halfedge_descriptor opoh = opposite(prev(opposite(h, tm), tm), tm);
if(is_border(opoh, tm))
bool was_opoh_border_in_range = false;
const halfedge_descriptor noh = next(opposite(h, tm), tm);
if(is_border(opoh, tm) && get(range_halfedges, opoh)) {
was_opoh_border_in_range = true;
edges_to_test.erase(opoh);
}
vertex_descriptor v = Euler::collapse_edge(edge(h, tm), tm);
CGAL_postcondition(bool(is_border(v, tm)));
CGAL_postcondition(target(prev_h, tm) == v);
put(vpm, v, new_p);
put(tolerance_map, v, new_tolerance);
if(get(range_halfedges, prev_h))
edges_to_test.insert(prev_h);
if(next_h != opoh && get(range_halfedges, next_h))
edges_to_test.insert(next_h);
if(was_opoh_border_in_range)
{
CGAL_assertion(is_border(noh, tm));
put(range_halfedges, noh, true);
}
for(halfedge_descriptor ih : halfedges_around_target(v, tm))
{
if(get(range_halfedges, ih))
edges_to_test.insert(ih);
}
++collapsed_n;
}
}
@ -693,12 +721,18 @@ std::size_t split_edges(EdgesToSplitContainer& edges_to_split,
halfedge_descriptor h_to_split = es.first;
CGAL_assertion(is_border(h_to_split, tm_T));
#ifdef CGAL_PMP_SNAP_DEBUG_PP
std::cout << " -.-.-. Splitting " << edge(h_to_split, tm_T) << " |||| "
<< " Vs " << source(h_to_split, tm_T) << " (" << tm_T.point(source(h_to_split, tm_T)) << ")"
<< " --- Vt " << target(h_to_split, tm_T) << " (" << tm_T.point(target(h_to_split, tm_T)) << ")" << std::endl;
#endif
Vertices_with_new_position& splitters = es.second;
if(splitters.size() > 1)
{
#ifdef CGAL_PMP_SNAP_DEBUG_PP
std::cout << " _______ Multiple splitting points on the same halfedge" << std::endl;
std::cout << " _______ Multiple splitting points on the same halfedge, sorting..." << std::endl;
#endif
const Point_ref hsp = get(vpm_T, source(h_to_split, tm_T));
@ -721,20 +755,36 @@ std::size_t split_edges(EdgesToSplitContainer& edges_to_split,
const vertex_descriptor splitter_v = target(splitter_h, tm_S);
const Point new_position = is_source_mesh_fixed ? get(vpm_S, splitter_v) : vnp.second;
#ifdef CGAL_PMP_SNAP_DEBUG_PP
std::cout << "With point: " << new_position << " (first choice: " << vnp.second << ")" << std::endl;
#endif
bool do_split = true;
// In case of self-snapping, avoid degenerate caps
const bool is_same_mesh = (&tm_T == &tm_S);
if(is_same_mesh && target(next(opposite(h_to_split, tm_T), tm_T), tm_T) == splitter_v)
if(is_same_mesh && target(next(opposite(h_to_split, tm_T), tm_T), tm_T) == splitter_v) {
#ifdef CGAL_PMP_SNAP_DEBUG_PP
std::cout << "Reject split (A)" << std::endl;
#endif
do_split = false;
}
// Do not split if it would create a degenerate needle
if((new_position == get(vpm_T, target(h_to_split, tm_T))) ||
(new_position == get(vpm_T, source(h_to_split, tm_T))))
(new_position == get(vpm_T, source(h_to_split, tm_T)))) {
#ifdef CGAL_PMP_SNAP_DEBUG_PP
std::cout << "Reject split (B)" << std::endl;
#endif
do_split = false;
}
if(!first_split && new_position == previous_split_position)
if(!first_split && new_position == previous_split_position) {
#ifdef CGAL_PMP_SNAP_DEBUG_PP
std::cout << "Reject split (C)" << std::endl;
#endif
do_split = false;
}
// check if the new faces after split will not be degenerate
const Point& p0 = new_position;
@ -759,13 +809,21 @@ std::size_t split_edges(EdgesToSplitContainer& edges_to_split,
if(first_split_face)
{
if(p0p2 <= 0 || collinear(p0,p1,p2) || collinear(p0,p2,p3))
if(p0p2 <= 0 || collinear(p0,p1,p2) || collinear(p0,p2,p3)) {
#ifdef CGAL_PMP_SNAP_DEBUG_PP
std::cout << "Reject split (D)" << std::endl;
#endif
do_split = false;
}
}
else
{
if(p1p3 <= 0 || collinear(p0,p1,p3) || collinear(p1,p2,p3))
if(p1p3 <= 0 || collinear(p0,p1,p3) || collinear(p1,p2,p3)) {
#ifdef CGAL_PMP_SNAP_DEBUG_PP
std::cout << "Reject split (E)" << std::endl;
#endif
do_split = false;
}
}
if(do_split && !is_source_mesh_fixed)
@ -774,6 +832,9 @@ std::size_t split_edges(EdgesToSplitContainer& edges_to_split,
{
if(!is_border(h,tm_S) && collinear(get(vpm_S, source(h,tm_S)), new_position, get(vpm_S, target(next(h,tm_S),tm_S))))
{
#ifdef CGAL_PMP_SNAP_DEBUG_PP
std::cout << "Reject split (F)" << std::endl;
#endif
do_split = false;
break;
}
@ -784,10 +845,6 @@ std::size_t split_edges(EdgesToSplitContainer& edges_to_split,
}
#ifdef CGAL_PMP_SNAP_DEBUG_PP
std::cout << " -.-.-. Splitting " << edge(h_to_split, tm_T) << " |||| "
<< " Vs " << source(h_to_split, tm_T) << " (" << tm_T.point(source(h_to_split, tm_T)) << ")"
<< " --- Vt " << target(h_to_split, tm_T) << " (" << tm_T.point(target(h_to_split, tm_T)) << ")" << std::endl;
std::cout << "With point: " << new_position << " (init: " << vnp.second << ")" << std::endl;
std::cout << "Actually split? " << do_split << std::endl;
#endif
@ -942,11 +999,11 @@ std::size_t snap_non_conformal_one_way(const HalfedgeRange& halfedge_range_S,
for(halfedge_descriptor h : halfedge_range_T)
{
CGAL_precondition(is_border(edge(h, tm_T), tm_T));
CGAL_precondition(is_border_edge(h, tm_T));
if(get(locked_halfedges_T, h))
{
#ifdef CGAL_PMP_SNAP_DEBUG_PP
std::cout << edge(h, tm_T) << " is locked and not a valid target" << std::endl;
std::cout << edge(h, tm_T) << " [" << source(h, tm_T) << " - " << target(h, tm_T) << "] is locked and not a valid target" << std::endl;
#endif
continue;
}

View File

@ -246,7 +246,7 @@ public:
#ifdef CGAL_PMP_SNAP_DEBUG_PP
std::cout << "squared distance between "
<< va << " [" << get(m_vpm_A, va) << "] and "
<< vb << " [" << get(m_vpm_B, vb) << "]: " << sq_dist
<< vb << " [" << get(m_vpm_B, vb) << "]: " << CGAL::squared_distance(get(m_vpm_A, va), get(m_vpm_B, vb))
<< " (tol a/b: " << tol_a << " " << tol_b << ") larger? " << (res == CGAL::LARGER)
<< std::endl;
#endif
@ -755,8 +755,12 @@ std::size_t snap_vertices_two_way(const HalfedgeRange_A& halfedge_range_A,
is_empty_range(halfedge_range_B.begin(), halfedge_range_B.end()))
return 0;
// Vertex-Vertex snapping is performed by identify points which are already equal
// and grouping them together so that they are moved together
// Vertex-Vertex snapping identifies points which are already equal
// and groups them together so that they are moved together
#ifdef CGAL_PMP_SNAP_DEBUG_PP
std::cout << "(A) Positions" << std::endl;
#endif
// @todo all range building could be parallel (worth it?)
Unique_positions unique_positions_A;
@ -766,7 +770,7 @@ std::size_t snap_vertices_two_way(const HalfedgeRange_A& halfedge_range_A,
const FT tolerance = get(tolerance_map_A, v);
#ifdef CGAL_PMP_SNAP_DEBUG_PP
std::cout << "Pos (A): " << v << " (" << get(vpm_A, v) << ")" << std::endl;
std::cout << " " << get(vpm_A, v) << std::endl;
#endif
Vertex_container nvc {{ h }};
@ -784,6 +788,10 @@ std::size_t snap_vertices_two_way(const HalfedgeRange_A& halfedge_range_A,
}
}
#ifdef CGAL_PMP_SNAP_DEBUG_PP
std::cout << "(B) Positions" << std::endl;
#endif
// same for tm_B (@todo when doing boxes, avoid all that for self snapping + use self_intersection_d)
Unique_positions unique_positions_B;
for(halfedge_descriptor h : halfedge_range_B)
@ -792,7 +800,7 @@ std::size_t snap_vertices_two_way(const HalfedgeRange_A& halfedge_range_A,
const FT tolerance = get(tolerance_map_B, v);
#ifdef CGAL_PMP_SNAP_DEBUG_PP
std::cout << "Pos (B): " << v << " (" << get(vpm_B, v) << ")" << std::endl;
std::cout << " " << get(vpm_B, v) << std::endl;
#endif
Vertex_container nvc {{ h }};

View File

@ -143,7 +143,7 @@ else()
message(STATUS "NOTICE: Tests are not using Ceres.")
endif()
if(CGAL_ENABLE_TESTING)
if(CGAL_ENABLE_TESTING AND TARGET CGAL::Eigen3_support)
set_tests_properties(
"execution of triangulate_hole_Polyhedron_3_no_delaunay_test"
"execution of triangulate_hole_Polyhedron_3_test"

View File

@ -248,6 +248,16 @@ Construct_triangle_2 construct_triangle_2_object();
/*!
*/
Less_x_2 less_x_2_object();
/*!
*/
Less_y_2 less_y_2_object();
/*!
*/
Compare_x_2 compare_x_2_object();