diff --git a/Mesh_2/include/CGAL/Mesh_2/Refine_edges.h b/Mesh_2/include/CGAL/Mesh_2/Refine_edges.h index b2bb3b50b3d..055ae0d7a21 100644 --- a/Mesh_2/include/CGAL/Mesh_2/Refine_edges.h +++ b/Mesh_2/include/CGAL/Mesh_2/Refine_edges.h @@ -344,27 +344,7 @@ protected: void scan_triangulation_impl(Tag_true) { - // with constraint hierarchy - - // create a vector of pairs of vertex handles, from the subconstraints - // and sort it to ensure the determinism - std::vector> subconstraints_vector(tr.number_of_subconstraints()); - std::transform(tr.subconstraints_begin(), tr.subconstraints_end(), subconstraints_vector.begin(), - [](const auto& sc) { - return std::array{sc.first.first, sc.first.second}; - }); - - auto comp_vh = [&] (Vertex_handle va, Vertex_handle vb) { - return tr.compare_xy(va->point(), vb->point()) == SMALLER; - }; - auto comp_pair_vh = [&] (const auto& e1, const auto& e2) { - return comp_vh(e1[0], e2[0]) || - (!comp_vh(e2[0], e1[0]) && comp_vh(e1[1], e2[1])); - }; - - std::sort(subconstraints_vector.begin(), subconstraints_vector.end(), comp_pair_vh); - - for(const auto& [v1, v2] : subconstraints_vector) + for(const auto& [v1, v2] : tr.hierarchy_ref().edges()) { if(!is_locally_conform(tr, v1, v2) ){ add_constrained_edge_to_be_conformed(v1, v2); diff --git a/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h b/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h index 761d7f75871..5033898200c 100644 --- a/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h +++ b/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h @@ -22,6 +22,8 @@ #include #include +#include + #include #include #include @@ -212,6 +214,115 @@ public: typedef typename Sc_to_c_map::const_iterator Sc_iterator; typedef Sc_iterator Subconstraint_iterator; + class Edge_iterator : public boost::stl_interfaces::proxy_iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS + Edge_iterator, +#endif + std::bidirectional_iterator_tag, + Edge> + { + using base_type = boost::stl_interfaces::proxy_iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS + Edge_iterator, +#endif + std::bidirectional_iterator_tag, + Edge>; + + const Constraint_set* constraint_set = nullptr; + C_iterator constraint_it{}; + Vertex_it vertex_it{}; + + public: + // - The object is singular if and only if `constraint_set==nullptr`. + // + // - The end value is when `constraint_it` is the end iterator of `constraint_set`. + // In that case `vertex_it` must be singular. + // + // - Otherwise all members must be valid pointers or dereferencable iterators. + + bool equal(const Edge_iterator& other) const { + return constraint_set == other.constraint_set && + (constraint_set == nullptr || (constraint_it == other.constraint_it && vertex_it == other.vertex_it)); + } + + Vertex_it first_vertex_it(C_iterator constraint_it) const { + if(constraint_it == constraint_set->end()) { + return Vertex_it(); + } + return constraint_it->begin(); + } + + public: + Edge_iterator() = default; + + // Constructors for begin and end. The constructors are public, but only the + // hierarchy can create an iterator of this class, through its friendship of + // the nested class `Construction_access`: Construction_access::begin_tag() and + // Construction_access::end_tag(). + class Construction_access + { + private: + friend class Edge_iterator; + friend class Polyline_constraint_hierarchy_2; + + static auto begin_tag() { return Begin_tag(); } + static auto end_tag() { return End_tag(); } + + struct Begin_tag + {}; + struct End_tag + {}; + }; + // + // constructor for the begin iterator + explicit Edge_iterator(Construction_access::Begin_tag, const Constraint_set* constraint_set) + : constraint_set(constraint_set) + , constraint_it(constraint_set->begin()) + , vertex_it(first_vertex_it(constraint_set->begin())) {} + // + // constructor for the end iterator + explicit Edge_iterator(Construction_access::End_tag, const Constraint_set* constraint_set) + : constraint_set(constraint_set) + , constraint_it(constraint_set->end()) + , vertex_it() {} + + Edge operator*() const { + CGAL_precondition(constraint_set != nullptr && constraint_it != constraint_set->end()); + CGAL_assertion(vertex_it != constraint_it->end()); + CGAL_assertion(std::next(vertex_it) != constraint_it->end()); + return Edge(*vertex_it, *std::next(vertex_it)); + } + + friend bool operator==(const Edge_iterator& lhs, const Edge_iterator& rhs) { return lhs.equal(rhs); } + + using base_type::operator++; + Edge_iterator& operator++() { + CGAL_precondition(constraint_set != nullptr && constraint_it != constraint_set->end()); + + ++vertex_it; + CGAL_assertion(vertex_it != constraint_it->end()); + + if(std::next(vertex_it) == constraint_it->end()) { + ++constraint_it; + vertex_it = first_vertex_it(constraint_it); + } + return *this; + } + + using base_type::operator--; + Edge_iterator& operator--() { + CGAL_precondition(constraint_set != nullptr); + CGAL_precondition(constraint_it != constraint_set->begin() || vertex_it != constraint_it->begin()); + if(constraint_it == constraint_set->end() || vertex_it == constraint_it->begin()) { + --constraint_it; + vertex_it = std::prev(constraint_it->end(), 2); + } else { + --vertex_it; + } + return *this; + } + }; // end class Edge_iterator + private: // data for the 1d hierarchy Compare comp; @@ -302,6 +413,20 @@ public: return sc_to_c_map.end(); } + Edge_iterator edges_begin() const { + BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(Edge_iterator, std::bidirectional_iterator); + BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS(Edge_iterator, std::bidirectional_iterator_tag, + std::bidirectional_iterator, Edge, Edge, + typename Edge_iterator::pointer, std::ptrdiff_t); + return Edge_iterator(Edge_iterator::Construction_access::begin_tag(), &constraint_set); + } + + Edge_iterator edges_end() const { + return Edge_iterator(Edge_iterator::Construction_access::end_tag(), &constraint_set); + } + + auto edges() const { return Iterator_range(edges_begin(), edges_end()); } + Sc_iterator sc_begin() const{ return sc_to_c_map.begin(); } Sc_iterator sc_end() const{ return sc_to_c_map.end(); } C_iterator c_begin() const{ return constraint_set.begin(); }