diff --git a/Alpha_wrap_2/include/CGAL/Alpha_wrap_2/internal/Point_set_oracle.h b/Alpha_wrap_2/include/CGAL/Alpha_wrap_2/internal/Point_set_oracle.h index 88f1a700878..b80d45676f7 100644 --- a/Alpha_wrap_2/include/CGAL/Alpha_wrap_2/internal/Point_set_oracle.h +++ b/Alpha_wrap_2/include/CGAL/Alpha_wrap_2/internal/Point_set_oracle.h @@ -1,5 +1,4 @@ // Copyright (c) 2019-2022 Google LLC (USA). -// Copyright (c) 2025 GeometryFactory (France). // All rights reserved. // // This file is part of CGAL (www.cgal.org). @@ -110,6 +109,10 @@ public: void add_points(const PointRange& points, const CGAL_NP_CLASS& /*np*/ = CGAL::parameters::default_values()) { +#ifdef CGAL_AW2_DEBUG + std::cout << "Insert into AABB tree (points)..." << std::endl; +#endif + if(points.empty()) { #ifdef CGAL_AW2_DEBUG @@ -121,10 +124,6 @@ public: const std::size_t old_size = m_points_ptr->size(); m_points_ptr->insert(std::cend(*m_points_ptr), std::cbegin(points), std::cend(points)); -#ifdef CGAL_AW2_DEBUG - std::cout << "Insert into AABB tree (points)..." << std::endl; -#endif - this->tree().rebuild(std::cbegin(*m_points_ptr), std::cend(*m_points_ptr)); // Manually constructing it here purely for profiling reasons: if we keep the lazy approach, diff --git a/Alpha_wrap_3/examples/Alpha_wrap_3/mixed_inputs_wrap.cpp b/Alpha_wrap_3/examples/Alpha_wrap_3/mixed_inputs_wrap.cpp index 90b488e0407..4198fe9aa2c 100644 --- a/Alpha_wrap_3/examples/Alpha_wrap_3/mixed_inputs_wrap.cpp +++ b/Alpha_wrap_3/examples/Alpha_wrap_3/mixed_inputs_wrap.cpp @@ -100,8 +100,8 @@ int main(int argc, char** argv) Oracle oracle(ss_oracle); oracle.add_triangle_soup(points, faces, CGAL::parameters::default_values()); - oracle.add_segment_soup(segments, CGAL::parameters::default_values()); - oracle.add_point_set(ps_points, CGAL::parameters::default_values()); + oracle.add_segments(segments, CGAL::parameters::default_values()); + oracle.add_points(ps_points, CGAL::parameters::default_values()); CGAL::Alpha_wraps_3::internal::Alpha_wrapper_3 aw3(oracle); diff --git a/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/Alpha_wrap_3.h b/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/Alpha_wrap_3.h index 057e015158b..6eae3e75847 100644 --- a/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/Alpha_wrap_3.h +++ b/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/Alpha_wrap_3.h @@ -207,13 +207,27 @@ public: static_assert(std::is_floating_point::value); } + void clear() + { + m_oracle.clear(); + m_bbox = {}; + m_alpha = m_sq_alpha = FT(-1); + m_offset = m_sq_offset = FT(-1); + m_seeds.clear(); + m_tr.clear(); + m_queue.clear(); + } + public: const Geom_traits& geom_traits() const { return m_tr.geom_traits(); } Oracle& oracle() { return m_oracle; } const Oracle& oracle() const { return m_oracle; } Triangulation& triangulation() { return m_tr; } const Triangulation& triangulation() const { return m_tr; } + Alpha_PQ& queue() { return m_queue; } const Alpha_PQ& queue() const { return m_queue; } + const FT& alpha() const { return m_alpha; } + const FT& offset() const { return m_offset; } double default_alpha() const { @@ -365,6 +379,11 @@ public: #endif } + #ifdef CGAL_AW3_DEBUG_DUMP_INTERMEDIATE_WRAPS + IO::write_polygon_mesh("final_wrap.off", output_mesh, CGAL::parameters::stream_precision(17)); + dump_triangulation_faces("final_tr.off", false /*only_boundary_faces*/); + #endif + extract_surface(output_mesh, ovpm, !do_enforce_manifoldness); #ifdef CGAL_AW3_TIMER @@ -375,11 +394,6 @@ public: #ifdef CGAL_AW3_DEBUG std::cout << "Alpha wrap vertices: " << vertices(output_mesh).size() << std::endl; std::cout << "Alpha wrap faces: " << faces(output_mesh).size() << std::endl; - - #ifdef CGAL_AW3_DEBUG_DUMP_INTERMEDIATE_WRAPS - IO::write_polygon_mesh("final_wrap.off", output_mesh, CGAL::parameters::stream_precision(17)); - dump_triangulation_faces("final_tr.off", false /*only_boundary_faces*/); - #endif #endif visitor.on_alpha_wrapping_end(*this); @@ -501,7 +515,7 @@ private: // which yields // r = a * sin(2pi / 5) =~ 0.95105651629515353 * a // Faces of an icosahedron are equilateral triangles with size a and circumradius a / sqrt(3) - // Since we want faces of the icosahedron to be traversable, we want a such that + // Since we want faces of the icosahedron to be traversable, we want `a` such that // a / sqrt(3) > alpha // Hence r such that // r / (sqrt(3) * sin(2pi/5)) > alpha @@ -509,7 +523,7 @@ private: // // Furthermore, the triangles between edges of the icosahedron and the center of the icosahedron // are not equilateral triangles since a is slightly bigger than r. They are - // slightly flattened isocele triangles with base 'a' and the circumradius is smaller. + // slightly flattened isocele triangles with base `a` and the circumradius is smaller. // The circumradius is // r_iso = r² / (2 * h) = r² / (2 * sqrt(r² - (a / 2)²)) // Since r = a * sin(2pi / 5) @@ -896,6 +910,16 @@ private: return less_squared_radius_of_min_empty_sphere(m_sq_alpha, f, m_tr); } + Steiner_status compute_steiner_point(const Gate& gate, + Point_2& steiner_point) const + { + const Face_handle fh = gate.face(); + const Cell_handle ch = f.first; + const int s = f.second; + const Cell_handle nh = ch->neighbor(s); + return compute_steiner_point(ch, nh, steiner_point); + } + bool compute_steiner_point(const Cell_handle ch, const Cell_handle neighbor, Point_3& steiner_point) const @@ -950,7 +974,7 @@ private: #ifdef CGAL_AW3_DEBUG_STEINER_COMPUTATION std::cout << "Steiner found through first_intersection(): " << steiner_point << std::endl; #endif - return true; + return Steiner_status::RULE_1; } } @@ -959,6 +983,10 @@ private: { // steiner point is the closest point on input from cell centroid with offset const Point_3 closest_pt = m_oracle.closest_point(neighbor_cc); +#ifdef CGAL_AW3_DEBUG_STEINER_COMPUTATION + std::cout << "Steiner found through neighboring triangle intersecting the input" << std::endl; + std::cout << "Closest point: " << closest_pt << std::endl; +#endif CGAL_assertion(closest_pt != neighbor_cc); Vector_3 unit = vector(closest_pt, neighbor_cc); @@ -968,19 +996,18 @@ private: steiner_point = translate(closest_pt, unit); #ifdef CGAL_AW3_DEBUG_STEINER_COMPUTATION - std::cout << "Steiner found through neighboring tet intersecting the input: " << steiner_point << std::endl; - std::cout << "Closest point: " << closest_pt << std::endl; - std::cout << "Direction: " << vector(closest_pt, neighbor_cc) << std::endl; + std::cout << "Direction: " << unit << std::endl; + std::cout << "Steiner: " << steiner_point << std::endl; #endif - return true; + return Steiner_status::RULE_2; } #ifdef CGAL_AW3_DEBUG_STEINER_COMPUTATION std::cout << "No Steiner point" << std::endl; #endif - return false; + return Steiner_status::NO_STEINER_POINT; } private: @@ -1043,7 +1070,12 @@ public: CGAL_precondition(ch->label() == Cell_label::INSIDE || ch->label() == Cell_label::OUTSIDE); if(m_tr.is_infinite(nh)) + { +#ifdef CGAL_AW3_DEBUG_FACET_STATUS + std::cout << "Infinite neighboring cell" << std::endl; +#endif return Facet_status::HAS_INFINITE_NEIGHBOR; + } if(nh->is_outside()) { @@ -1104,9 +1136,23 @@ private: const FT sqr = smallest_squared_radius_3(f, m_tr); const bool is_permissive = (status == Facet_status::HAS_INFINITE_NEIGHBOR || status == Facet_status::SCAFFOLDING); - m_queue.resize_and_push(Gate(f, sqr, is_permissive)); + Gate new_gate(f, sqr, is_permissive); #else - m_queue.push(Gate(f, m_tr)); + Gate new_gate(f, m_tr); +#endif + +#ifdef CGAL_AW2_COMPUTE_AND_STORE_STEINER_INFO_AT_GATE_CREATION + Point_3 steiner_point; + Steiner_status steiner_status = compute_steiner_point(new_gate, steiner_point); + new_gate.m_steiner_status = steiner_status; + if(steiner_status == Steiner_status::RULE_1 || steiner_status == Steiner_status::RULE_2) + new_gate.m_steiner_point = steiner_point; +#endif + +#ifdef CGAL_AW3_USE_SORTED_PRIORITY_QUEUE + m_queue.resize_and_push(new_gate); +#else + m_queue.push(new_gate); #endif #ifdef CGAL_AW3_DEBUG_QUEUE @@ -1241,26 +1287,25 @@ private: #endif const Facet& f = gate.facet(); - CGAL_precondition(!m_tr.is_infinite(f)); - const Cell_handle ch = f.first; const int s = f.second; - CGAL_precondition(ch->is_outside()); - const Cell_handle nh = ch->neighbor(s); - CGAL_precondition(nh->label() == Cell_label::INSIDE || nh->label() == Cell_label::OUTSIDE); #ifdef CGAL_AW3_DEBUG_QUEUE static int fid = 0; std::cout << m_tr.number_of_vertices() << " DT vertices" << std::endl; std::cout << m_queue.size() << " facets in the queue" << std::endl; - std::cout << "Face " << fid++ << "\n" - << "c = " << &*ch << " (" << m_tr.is_infinite(ch) << "), n = " << &*nh << " (" << m_tr.is_infinite(nh) << ")" << "\n" - << m_tr.point(ch, Triangulation::vertex_triple_index(s, 0)) << "\n" - << m_tr.point(ch, Triangulation::vertex_triple_index(s, 1)) << "\n" - << m_tr.point(ch, Triangulation::vertex_triple_index(s, 2)) << std::endl; + std::cout << "Face " << fid++ << " [" + << m_tr.point(ch, Triangulation::vertex_triple_index(s, 0)) << " " + << m_tr.point(ch, Triangulation::vertex_triple_index(s, 1)) << " " + << m_tr.point(ch, Triangulation::vertex_triple_index(s, 2)) << "]" << std::endl; + std::cout << "c = " << &*ch << " (inf: " << m_tr.is_infinite(ch) << ", label: " << ch->label() << "), n = " + << &*nh << " (inf: " << m_tr.is_infinite(nh) << ", label: " << nh->label() << ")" << "\n" + +# ifdef CGAL_AW3_USE_SORTED_PRIORITY_QUEUE std::cout << "Priority: " << gate.priority() << " (sq alpha: " << m_sq_alpha << ")" << std::endl; std::cout << "Permissiveness: " << gate.is_permissive_facet() << std::endl; +# endif #endif #ifdef CGAL_AW3_DEBUG_DUMP_EVERY_STEP @@ -1277,6 +1322,10 @@ private: face_out.close(); #endif + CGAL_precondition(!m_tr.is_infinite(f)); + CGAL_precondition(ch->is_outside()); + CGAL_precondition(nh->label() == Cell_label::INSIDE || nh->label() == Cell_label::OUTSIDE); + visitor.before_facet_treatment(*this, gate); m_queue.pop(); @@ -1291,7 +1340,8 @@ private: } Point_3 steiner_point; - if(compute_steiner_point(ch, nh, steiner_point)) + Steiner_status ss = compute_steiner_point(ch, nh, steiner_point); + if(ss != Steiner_status::NO_STEINER_POINT) { // std::cout << CGAL::abs(CGAL::approximate_sqrt(m_oracle.squared_distance(steiner_point)) - m_offset) // << " vs " << 1e-2 * m_offset << std::endl; diff --git a/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/Alpha_wrap_triangulation_cell_base_3.h b/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/Alpha_wrap_triangulation_cell_base_3.h index bcca1bd0143..f655bd6ba5c 100644 --- a/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/Alpha_wrap_triangulation_cell_base_3.h +++ b/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/Alpha_wrap_triangulation_cell_base_3.h @@ -23,13 +23,33 @@ namespace internal { enum class Cell_label { // Cells that have been carved - OUTSIDE, + OUTSIDE = 0, // Cells that have not yet been carved INSIDE, // OUTSIDE cells that have been labeled "inside" again as to make the result manifold MANIFOLD }; +inline std::string label_string(const Cell_label& label) { + switch(label) { + case Cell_label::OUTSIDE: + return "OUTSIDE"; + case Cell_label::INSIDE: + return "INSIDE"; + case Cell_label::MANIFOLD: + return "MANIFOLD"; + default: + CGAL_assertion_msg(false, "Unknown label"); + return {}; + } +} + +inline std::ostream& operator <<(std::ostream& os, const Cell_label& label) +{ + os << static_cast::type>(label); + return os; +} + template < typename GT, typename Cb = CGAL::Delaunay_triangulation_cell_base_with_circumcenter_3 > class Alpha_wrap_triangulation_cell_base_3 diff --git a/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/Oracle_base.h b/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/Oracle_base.h index 5e105f83047..abee36b9e88 100644 --- a/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/Oracle_base.h +++ b/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/Oracle_base.h @@ -145,7 +145,11 @@ public: bool empty() const { return m_tree_ptr->empty(); } bool do_call() const { return (!empty() || base().do_call()); } - void clear() { m_tree_ptr->clear() && base().clear(); } + void clear() + { + m_tree_ptr->clear(); + base().clear(); + } public: typename AABB_tree::Bounding_box bbox() const diff --git a/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/Point_set_oracle.h b/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/Point_set_oracle.h index d35a20c93fa..199e1f09b90 100644 --- a/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/Point_set_oracle.h +++ b/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/Point_set_oracle.h @@ -97,12 +97,22 @@ public: { } public: + void clear() + { + m_points_ptr->clear(); + Oracle_base::clear(); + } + // adds a range of points to the oracle template - void add_point_set(const PointRange& points, - const CGAL_NP_CLASS& /*np*/ = CGAL::parameters::default_values()) + void add_points(const PointRange& points, + const CGAL_NP_CLASS& /*np*/ = CGAL::parameters::default_values()) { +#ifdef CGAL_AW3_DEBUG + std::cout << "Insert into AABB tree (points)..." << std::endl; +#endif + if(points.empty()) { #ifdef CGAL_AW3_DEBUG @@ -114,20 +124,18 @@ public: const std::size_t old_size = m_points_ptr->size(); m_points_ptr->insert(std::cend(*m_points_ptr), std::cbegin(points), std::cend(points)); -#ifdef CGAL_AW3_DEBUG - std::cout << "Insert into AABB tree (points)..." << std::endl; -#endif - - this->tree().insert(std::next(std::cbegin(*m_points_ptr), old_size), std::cend(*m_points_ptr)); + this->tree().rebuild(std::cbegin(*m_points_ptr), std::cend(*m_points_ptr)); // Manually constructing it here purely for profiling reasons: if we keep the lazy approach, // it will be done at the first treatment of a facet that needs a Steiner point. // So if one wanted to bench the flood fill runtime, it would be skewed by the time it takes // to accelerate the tree. this->tree().accelerate_distance_queries(); - - CGAL_postcondition(this->tree().size() == m_points_ptr->size()); } + +#ifdef CGAL_AW2_DEBUG + std::cout << "PS Tree: " << this->tree().size() << " primitives" << std::endl; +#endif }; } // namespace internal diff --git a/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/Segment_soup_oracle.h b/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/Segment_soup_oracle.h index 88d565c6b66..ca3a83bd95a 100644 --- a/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/Segment_soup_oracle.h +++ b/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/Segment_soup_oracle.h @@ -99,11 +99,21 @@ public: { } public: + void clear() + { + m_segments_ptr->clear(); + Oracle_base::clear(); + } + template - void add_segment_soup(const SegmentRange& segments, - const CGAL_NP_CLASS& /*np*/ = CGAL::parameters::default_values()) + void add_segments(const SegmentRange& segments, + const CGAL_NP_CLASS& /*np*/ = CGAL::parameters::default_values()) { +#ifdef CGAL_AW3_DEBUG + std::cout << "Insert into AABB Tree (" << segments.size() << " segments)..." << std::endl; +#endif + if(segments.empty()) { #ifdef CGAL_AW3_DEBUG @@ -129,10 +139,7 @@ public: m_segments_ptr->push_back(s); } -#ifdef CGAL_AW3_DEBUG - std::cout << "Insert into AABB tree (segments)..." << std::endl; -#endif - this->tree().insert(std::next(std::cbegin(*m_segments_ptr), old_size), std::cend(*m_segments_ptr)); + this->tree().rebuild(std::cbegin(*m_segments_ptr), std::cend(*m_segments_ptr)); // Manually constructing it here purely for profiling reasons: if we keep the lazy approach, // it will be done at the first treatment of a facet that needs a Steiner point. @@ -140,7 +147,9 @@ public: // to accelerate the tree. this->tree().accelerate_distance_queries(); - CGAL_postcondition(this->tree().size() == m_segments_ptr->size()); +#ifdef CGAL_AW3_DEBUG + std::cout << "SS Tree: " << this->tree().size() << " primitives" << std::endl; +#endif } }; diff --git a/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/Triangle_mesh_oracle.h b/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/Triangle_mesh_oracle.h index d7f325e1428..a4c30e6cc88 100644 --- a/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/Triangle_mesh_oracle.h +++ b/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/Triangle_mesh_oracle.h @@ -130,6 +130,10 @@ public: using VPM = typename GetVertexPointMap::const_type; using Point_ref = typename boost::property_traits::reference; +#ifdef CGAL_AW3_DEBUG + std::cout << "Insert into AABB tree (" << faces(tmesh).size() << " faces)..." << std::endl; +#endif + CGAL_precondition(CGAL::is_triangle_mesh(tmesh)); if(is_empty(tmesh)) @@ -140,10 +144,6 @@ public: return; } -#ifdef CGAL_AW3_DEBUG - std::cout << "Insert into AABB tree (faces)..." << std::endl; -#endif - VPM vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), get_const_property_map(vertex_point, tmesh)); static_assert(std::is_same::value_type, Point_3>::value); @@ -176,7 +176,7 @@ public: this->tree().accelerate_distance_queries(); #ifdef CGAL_AW3_DEBUG - std::cout << "Tree: " << this->tree().size() << " primitives (" << num_faces(tmesh) << " faces in input)" << std::endl; + std::cout << "Tree: " << this->tree().size() << " primitives" << std::endl; #endif } }; diff --git a/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/Triangle_soup_oracle.h b/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/Triangle_soup_oracle.h index d066107f620..947dd6ff8df 100644 --- a/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/Triangle_soup_oracle.h +++ b/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/Triangle_soup_oracle.h @@ -130,6 +130,10 @@ public: using Face = typename boost::range_value::type; +#ifdef CGAL_AW3_DEBUG + std::cout << "Insert into AABB Tree (" << faces.size() << " faces)..." << std::endl; +#endif + if(points.empty() || faces.empty()) { #ifdef CGAL_AW3_DEBUG @@ -138,10 +142,6 @@ public: return; } -#ifdef CGAL_AW3_DEBUG - std::cout << "Insert into AABB Tree (triangles)..." << std::endl; -#endif - PPM pm = choose_parameter(get_parameter(np, internal_np::point_map)); static_assert(std::is_same::value_type, Point_3>::value); @@ -181,15 +181,19 @@ public: this->tree().accelerate_distance_queries(); #ifdef CGAL_AW3_DEBUG - std::cout << "Tree: " << this->tree().size() << " primitives (" << faces.size() << " faces in input)" << std::endl; + std::cout << "TS Tree: " << this->tree().size() << " primitives" << std::endl; #endif } template - void add_triangle_soup(const TriangleRange& triangles, - const CGAL_NP_CLASS& /*np*/ = CGAL::parameters::default_values()) + void add_triangles(const TriangleRange& triangles, + const CGAL_NP_CLASS& /*np*/ = CGAL::parameters::default_values()) { +#ifdef CGAL_AW3_DEBUG + std::cout << "Insert into AABB Tree (" << triangles.size() << " triangles)..." << std::endl; +#endif + if(triangles.empty()) { #ifdef CGAL_AW3_DEBUG @@ -198,10 +202,6 @@ public: return; } -#ifdef CGAL_AW3_DEBUG - std::cout << "Insert into AABB Tree (triangles)..." << std::endl; -#endif - typename Geom_traits::Is_degenerate_3 is_degenerate = this->geom_traits().is_degenerate_3_object(); Splitter_base::reserve(triangles.size()); @@ -218,6 +218,9 @@ public: Splitter_base::split_and_insert_datum(tr, this->tree(), this->geom_traits()); } +#ifdef CGAL_AW3_DEBUG + std::cout << "TS Tree: " << this->tree().size() << " primitives" << std::endl; +#endif } }; diff --git a/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/gate_priority_queue.h b/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/gate_priority_queue.h index ec48b4f458b..1df539b4093 100644 --- a/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/gate_priority_queue.h +++ b/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/gate_priority_queue.h @@ -22,16 +22,46 @@ #include #include +#include namespace CGAL { namespace Alpha_wraps_3 { namespace internal { +enum class Steiner_status +{ + UNKONWN = 0, + NO_STEINER_POINT, + RULE_1, + RULE_2 +}; + +#ifdef CGAL_AW2_COMPUTE_AND_STORE_STEINER_INFO_AT_GATE_CREATION +template +struct Gate_steiner_info +{ + using Point_3 = typename Tr::Geom_traits::Point_3; + + Steiner_status m_steiner_status = Steiner_status::UNKNOWN; + std::optional m_steiner_point = std::nullopt; + + bool has_steiner_point() const { return m_steiner_point.has_value(); } + bool has_steiner_from_projection() const { return (m_steiner_status == Steiner_status::RULE_2); } + const Point_3& steiner_point() const { + CGAL_precondition(has_steiner_point()); + return *m_steiner_point; + } +}; +#endif + #ifdef CGAL_AW3_USE_SORTED_PRIORITY_QUEUE // Represents an alpha-traversable facet in the mutable priority queue template class Gate +#ifdef CGAL_AW2_COMPUTE_AND_STORE_STEINER_INFO_AT_GATE_CREATION + : public Gate_steiner_info +#endif { using Facet = typename Tr::Facet; using FT = typename Tr::Geom_traits::FT; @@ -97,6 +127,9 @@ struct Less_gate // Represents an alpha-traversable facet in the mutable priority queue template class Gate +#ifdef CGAL_AW2_COMPUTE_AND_STORE_STEINER_INFO_AT_GATE_CREATION + : public Gate_steiner_info +#endif { using Facet = typename Tr::Facet; using FT = typename Tr::Geom_traits::FT; diff --git a/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/validation.h b/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/validation.h index 6d9a9191d5f..d5702304de6 100644 --- a/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/validation.h +++ b/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/validation.h @@ -65,20 +65,30 @@ bool has_degenerated_faces(const TriangleMesh& mesh, // Edge length is bounded by twice the circumradius template -bool check_edge_length(const TriangleMesh& output_mesh, - const double alpha, - const NamedParameters& np = CGAL::parameters::default_values()) +bool has_bounded_edge_length(const TriangleMesh& wrap, + const double alpha, + const NamedParameters& np = CGAL::parameters::default_values()) { - const auto sq_alpha_bound = 4 * square(alpha); - for(auto e : edges(output_mesh)) + using Geom_traits = typename GetGeomTraits::type; + using FT = typename Geom_traits::FT; + using VPM = typename CGAL::GetVertexPointMap::type; + + Geom_traits gt = choose_parameter(get_parameter(in_np, internal_np::geom_traits)); + VPM vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), + get_const_property_map(vertex_point, tmesh)); + + const FT sq_alpha_bound = 4 * square(alpha); + for(auto e : edges(wrap)) { - const auto sqd = Polygon_mesh_processing::squared_edge_length(e, output_mesh, np); - if(sqd > sq_alpha_bound) // alpha is the circumradius + if(gt.compare_squared_distance(get(vpm, source(e, wrap)), + get(vpm, target(e, wrap)), + sq_alpha_bound) == LARGER) { #ifdef CGAL_AW3_DEBUG + const FT sqd = Polygon_mesh_processing::squared_edge_length(e, wrap, np); std::cerr << "Error: " << sqd << " greater than " << sq_alpha_bound << std::endl; - std::cerr << get(CGAL::vertex_point, output_mesh, source(e, output_mesh)) << std::endl; - std::cerr << get(CGAL::vertex_point, output_mesh, target(e, output_mesh)) << std::endl; + std::cerr << "source pt: " << get(vpm, source(e, wrap)) << std::endl; + std::cerr << "target pt: " << get(vpm, target(e, wrap)) << std::endl; #endif return false; } @@ -346,13 +356,12 @@ bool is_outer_wrap_of_point_set(const TriangleMesh& wrap, CGAL::Side_of_triangle_mesh side_of_wrap(wrap, out_vpm); - // @speed a single vertex per CC would be sufficient for(const auto& p : points) { if(side_of_wrap(get(in_pm, p)) != CGAL::ON_BOUNDED_SIDE) { #ifdef CGAL_AW3_DEBUG - std::cerr << "Part(s) of the input mesh are outside the wrap: " << get(in_pm, p) << std::endl; + std::cerr << "An input point is outside the wrap: " << get(in_pm, p) << std::endl; #endif return false; } diff --git a/Alpha_wrap_3/include/CGAL/alpha_wrap_3.h b/Alpha_wrap_3/include/CGAL/alpha_wrap_3.h index 8be78675422..50b540f4eed 100644 --- a/Alpha_wrap_3/include/CGAL/alpha_wrap_3.h +++ b/Alpha_wrap_3/include/CGAL/alpha_wrap_3.h @@ -355,7 +355,7 @@ void alpha_wrap_3(const PointRange& points, Geom_traits gt = choose_parameter(get_parameter(in_np, internal_np::geom_traits)); Oracle oracle(gt); - oracle.add_point_set(points, in_np); + oracle.add_points(points, in_np); AW3 alpha_wrap_builder(oracle); alpha_wrap_builder(alpha, offset, alpha_wrap, in_np, out_np); } diff --git a/Alpha_wrap_3/test/Alpha_wrap_3/test_AW3_cavity_initializations.cpp b/Alpha_wrap_3/test/Alpha_wrap_3/test_AW3_cavity_initializations.cpp index af94eecd25a..eef71c321a1 100644 --- a/Alpha_wrap_3/test/Alpha_wrap_3/test_AW3_cavity_initializations.cpp +++ b/Alpha_wrap_3/test/Alpha_wrap_3/test_AW3_cavity_initializations.cpp @@ -105,7 +105,7 @@ void alpha_wrap_triangle_mesh(Mesh& input_mesh, } if(!enforce_manifoldness) - assert(AW3::internal::check_edge_length(wrap, alpha)); + assert(AW3::internal::has_bounded_edge_length(wrap, alpha)); } void alpha_wrap_triangle_mesh(Mesh& input_mesh, diff --git a/Alpha_wrap_3/test/Alpha_wrap_3/test_AW3_manifoldness.cpp b/Alpha_wrap_3/test/Alpha_wrap_3/test_AW3_manifoldness.cpp index 954fe6163df..32893100730 100644 --- a/Alpha_wrap_3/test/Alpha_wrap_3/test_AW3_manifoldness.cpp +++ b/Alpha_wrap_3/test/Alpha_wrap_3/test_AW3_manifoldness.cpp @@ -57,7 +57,7 @@ void alpha_wrap_triangle_manifoldness(Mesh& input_mesh, assert(AW3::internal::has_expected_Hausdorff_distance(nm_wrap, input_mesh, alpha, offset)); } - assert(AW3::internal::check_edge_length(nm_wrap, alpha)); + assert(AW3::internal::has_bounded_edge_length(nm_wrap, alpha)); FT base_vol = 0; if(!is_closed(nm_wrap)) diff --git a/Alpha_wrap_3/test/Alpha_wrap_3/test_AW3_multiple_calls.cpp b/Alpha_wrap_3/test/Alpha_wrap_3/test_AW3_multiple_calls.cpp index 35a954f17b2..c9352c2caa9 100644 --- a/Alpha_wrap_3/test/Alpha_wrap_3/test_AW3_multiple_calls.cpp +++ b/Alpha_wrap_3/test/Alpha_wrap_3/test_AW3_multiple_calls.cpp @@ -52,7 +52,7 @@ void alpha_wrap_triangle_soup(Points& pr, // AW3 Oracle oracle; - oracle.add_triangle_soup(pr, fr); + oracle.add_triangles(pr, fr); AW3::internal::Alpha_wrapper_3 aw3(oracle); Mesh wrap; @@ -65,7 +65,7 @@ void alpha_wrap_triangle_soup(Points& pr, assert(AW3::internal::is_valid_wrap(wrap, false /*manifoldness*/)); assert(AW3::internal::is_outer_wrap_of_triangle_soup(wrap, pr, fr)); assert(AW3::internal::has_expected_Hausdorff_distance(wrap, input_mesh, alpha, offset)); - assert(AW3::internal::check_edge_length(wrap, alpha)); + assert(AW3::internal::has_bounded_edge_length(wrap, alpha)); alpha *= 2; offset *= 2; @@ -83,7 +83,7 @@ void alpha_wrap_triangle_soup(Points& pr, assert(AW3::internal::is_valid_wrap(wrap_2, false /*manifoldness*/)); assert(AW3::internal::is_outer_wrap_of_triangle_soup(wrap_2, pr, fr)); assert(AW3::internal::has_expected_Hausdorff_distance(wrap_2, input_mesh, alpha, offset)); - assert(AW3::internal::check_edge_length(wrap_2, alpha)); + assert(AW3::internal::has_bounded_edge_length(wrap_2, alpha)); } void alpha_wrap_triangle_soup(const std::string& filename) diff --git a/Alpha_wrap_3/test/Alpha_wrap_3/test_alpha_wrap_3_mesh.cpp b/Alpha_wrap_3/test/Alpha_wrap_3/test_alpha_wrap_3_mesh.cpp index 6209019a7a4..06b64164430 100644 --- a/Alpha_wrap_3/test/Alpha_wrap_3/test_alpha_wrap_3_mesh.cpp +++ b/Alpha_wrap_3/test/Alpha_wrap_3/test_alpha_wrap_3_mesh.cpp @@ -63,7 +63,7 @@ void alpha_wrap_triangle_mesh(Mesh& input_mesh, } if(!enforce_manifoldness) - assert(AW3::internal::check_edge_length(wrap, alpha)); + assert(AW3::internal::has_bounded_edge_length(wrap, alpha)); } void alpha_wrap_triangle_mesh(const std::string& filename, diff --git a/Lab/demo/Lab/Plugins/Alpha_wrap_3/Alpha_wrap_3_plugin.cpp b/Lab/demo/Lab/Plugins/Alpha_wrap_3/Alpha_wrap_3_plugin.cpp index 3374d7fe619..1896ac74fa7 100644 --- a/Lab/demo/Lab/Plugins/Alpha_wrap_3/Alpha_wrap_3_plugin.cpp +++ b/Lab/demo/Lab/Plugins/Alpha_wrap_3/Alpha_wrap_3_plugin.cpp @@ -732,11 +732,11 @@ public Q_SLOTS: Oracle oracle(ss_oracle); if(wrap_triangles) - oracle.add_triangle_soup(triangles); + oracle.add_triangles(triangles); if(wrap_segments) - oracle.add_segment_soup(segments); + oracle.add_segments(segments); if(wrap_points) - oracle.add_point_set(points); + oracle.add_points(points); if(!oracle.do_call()) {