From 9e77e501bd9343ecdd0a2beee0e7594812f1dcde Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 4 Aug 2020 15:04:42 +0200 Subject: [PATCH 01/10] Add member functions for indexed sweep --- .../CGAL/No_intersection_surface_sweep_2.h | 61 +++++++ .../No_intersection_surface_sweep_2_impl.h | 161 ++++++++++++++++++ 2 files changed, 222 insertions(+) diff --git a/Surface_sweep_2/include/CGAL/No_intersection_surface_sweep_2.h b/Surface_sweep_2/include/CGAL/No_intersection_surface_sweep_2.h index 6b9e3ebb504..39349d5d42a 100644 --- a/Surface_sweep_2/include/CGAL/No_intersection_surface_sweep_2.h +++ b/Surface_sweep_2/include/CGAL/No_intersection_surface_sweep_2.h @@ -309,6 +309,17 @@ public: m_visitor->after_sweep(); } + template + void indexed_sweep (const EdgeRange& edges, + const Accessor& accessor) + { + m_visitor->before_sweep(); + _init_indexed_sweep(edges, accessor); + _sweep(); + _complete_sweep(); + m_visitor->after_sweep(); + } + /*! Get an iterator for the first subcurve in the status line. */ Status_line_iterator status_line_begin() { return m_statusLine.begin(); } @@ -376,6 +387,32 @@ protected: _init_curve(*cit, index); } + /*! Create a Subcurve object and two Event objects for each curve. */ + template + void _init_indexed_curves(const EdgeRange& edges, + const Accessor& accessor) + { + std::vector events (accessor.nb_vertices()); + + unsigned int index = 0; + for (const auto& e : edges) + { + std::size_t source = accessor.source_index(e); + std::size_t target = accessor.target_index(e); + const X_monotone_curve_2& curve = accessor.curve (e); + + // Construct and initialize a subcurve object. + std::allocator_traits::construct(m_subCurveAlloc, m_subCurves + index, m_masterSubcurve ); + (m_subCurves + index)->set_hint(this->m_statusLine.end()); + (m_subCurves + index)->init (curve); + + _init_curve_end(curve, ARR_MAX_END, m_subCurves + index, events, target); + _init_curve_end(curve, ARR_MIN_END, m_subCurves + index, events, source); + + ++ index; + } + } + /*! Initiliaze the sweep algorithm. */ template void _init_sweep(CurveInputIterator curves_begin, @@ -413,6 +450,11 @@ protected: void _init_curve_end(const X_monotone_curve_2& cv, Arr_curve_end ind, Subcurve* sc); + // Variant keeping track of indexed events + void _init_curve_end(const X_monotone_curve_2& cv, Arr_curve_end ind, + Subcurve* sc, + std::vector& events, std::size_t index); + /*! Handle the subcurves that are to the left of the event point (i.e., * subcurves that we are done with). */ @@ -485,6 +527,14 @@ protected: Arr_parameter_space ps_y, Subcurve* sc = nullptr); + // Variant keeping track of indexed events + std::pair _push_event(const Point_2& pt, Attribute type, + Arr_parameter_space ps_x, + Arr_parameter_space ps_y, + Subcurve* sc, + std::vector& events, + std::size_t index); + /*! Push an event point associated with a curve end into the event queue. * \param cv The x-monotone curve. * \param ind The relevant curve end. @@ -503,6 +553,17 @@ protected: Arr_parameter_space ps_y, Subcurve* sc = nullptr); + // Variant keeping track of indexed events + std::pair _push_event(const X_monotone_curve_2& cv, + Arr_curve_end ind, + Attribute type, + Arr_parameter_space ps_x, + Arr_parameter_space ps_y, + Subcurve* sc, + const Point_2& pt, + std::vector& events, + std::size_t index); + void _update_event_at_open_boundary(Event* e, const X_monotone_curve_2& cv, Arr_curve_end ind, diff --git a/Surface_sweep_2/include/CGAL/Surface_sweep_2/No_intersection_surface_sweep_2_impl.h b/Surface_sweep_2/include/CGAL/Surface_sweep_2/No_intersection_surface_sweep_2_impl.h index f08377e5f9b..eb30c4d310e 100644 --- a/Surface_sweep_2/include/CGAL/Surface_sweep_2/No_intersection_surface_sweep_2_impl.h +++ b/Surface_sweep_2/include/CGAL/Surface_sweep_2/No_intersection_surface_sweep_2_impl.h @@ -301,6 +301,35 @@ _init_curve_end(const X_monotone_curve_2& cv, Arr_curve_end ind, Subcurve* sc) } } +template +void No_intersection_surface_sweep_2:: +_init_curve_end(const X_monotone_curve_2& cv, Arr_curve_end ind, Subcurve* sc, + std::vector& events, std::size_t index) +{ + // Get the boundary conditions of the curve end. + const Attribute end_attr = + (ind == ARR_MIN_END) ? Event::LEFT_END : Event::RIGHT_END; + + Arr_parameter_space ps_x = m_traits->parameter_space_in_x_2_object()(cv, ind); + Arr_parameter_space ps_y = m_traits->parameter_space_in_y_2_object()(cv, ind); + + // Create the corresponding event and push it into the event queue. + std::pair pair_res; + + const Point_2& pt = (ind == ARR_MIN_END) ? + m_traits->construct_min_vertex_2_object()(cv) : + m_traits->construct_max_vertex_2_object()(cv); + + pair_res = ((ps_x == ARR_INTERIOR) && (ps_y == ARR_INTERIOR)) ? + _push_event(pt, end_attr, ps_x, ps_y, sc, events, index) : + _push_event(cv, ind, end_attr, ps_x, ps_y, sc, pt, events, index); + + // Inform the visitor in case we updated an existing event. + Event* e = pair_res.first; + CGAL_assertion(e->is_closed()); + m_visitor->update_event(e, pt, cv, ind, pair_res.second); +} + //----------------------------------------------------------------------------- // Handle the subcurves to the left of the current event point. // @@ -673,6 +702,72 @@ No_intersection_surface_sweep_2::_push_event(const Point_2& pt, return (std::make_pair(e, !exist)); } +template +std::pair::Event*, bool> +No_intersection_surface_sweep_2::_push_event(const Point_2& pt, + Attribute type, + Arr_parameter_space ps_x, + Arr_parameter_space ps_y, + Subcurve* sc, + std::vector& events, + std::size_t index) +{ + Event* e; + + std::pair + pair_res = std::make_pair (events[index], true); + + // If event does not exist + if (events[index] == Event_queue_iterator()) + { + // Still look for the curve end in the event queue in case two + // point are the the same in the vertex range + m_queueEventLess.set_parameter_space_in_x(ps_x); + m_queueEventLess.set_parameter_space_in_y(ps_y); + pair_res = m_queue->find_lower(pt, m_queueEventLess); + } + + bool exist = pair_res.second; + if (! exist) { + // The point is not found in the event queue - create a new event and + // insert it into the queue. + e = _allocate_event(pt, type, ps_x, ps_y); + } + else { + events[index] = pair_res.first; + // The event associated with the given point already exists in the queue, + // so we just have to update it. + e = *(pair_res.first); + CGAL_assertion(e->is_closed()); + + e->set_attribute(type); + } + + // If we are given a subcurve that the event represents one of its + // endpoints, update the event and the subcurve records accordingly. + // Note that this must be done before we actually insert the new event + // into the event queue. + _add_curve(e, sc, type); + + // Insert the new event into the queue using the hint we got when we + // looked for it. + if (! exist) + events[index] = m_queue->insert_before(pair_res.first, e); + +#ifdef CGAL_SS_VERBOSE + if (! exist) { + CGAL_SS_PRINT_NEW_EVENT(pt, e); + } + else { + CGAL_SS_PRINT_UPDATE_EVENT(pt, e); + } +#endif + + // Return the resulting event and a flag indicating whether we have created + // a new event. + return (std::make_pair(e, !exist)); +} + //----------------------------------------------------------------------------- // Push an event point associated with a curve end into the event queue. // @@ -736,6 +831,72 @@ No_intersection_surface_sweep_2::_push_event(const X_monotone_curve_2& cv, return (std::make_pair(e, !exist)); } +template +std::pair::Event*, bool> +No_intersection_surface_sweep_2::_push_event(const X_monotone_curve_2& cv, + Arr_curve_end ind, + Attribute type, + Arr_parameter_space ps_x, + Arr_parameter_space ps_y, + Subcurve* sc, + const Point_2& pt, + std::vector& events, + std::size_t index) +{ + Event* e; + + std::pair + pair_res = std::make_pair (events[index], true); + + // If event does not exist + if (events[index] == Event_queue_iterator()) + { + // Still look for the curve end in the event queue in case two + // point are the the same in the vertex range + + m_queueEventLess.set_parameter_space_in_x(ps_x); + m_queueEventLess.set_parameter_space_in_y(ps_y); + m_queueEventLess.set_index(ind); + + pair_res = + m_queue->find_lower(cv, m_queueEventLess); + } + + bool exist = pair_res.second; + + if (! exist) { + // The curve end is not found in the event queue - create a new event and + // insert it into the queue. + // The curve end is closed and so it is associated with a valid + // point. + e = _allocate_event(pt, type, ps_x, ps_y); + } + else { + events[index] = pair_res.first; + + // The event associated with the given curve end already exists in the + // queue, so we just have to update it. + e = *(pair_res.first); + CGAL_assertion((e->parameter_space_in_x() == ps_x) && + (e->parameter_space_in_y() == ps_y)); + + e->set_attribute(type); + } + + // If we are given a subcurve that the event represents one of its + // endpoints, update the event and the subcurve records accordingly. + // Note that this must be done before we actually insert the new event + // into the event queue. + _add_curve(e, sc, type); + + // Insert the new event into the queue using the hint we got when we + // looked for it. + if (! exist) + events[index] = m_queue->insert_before(pair_res.first, e); + + return (std::make_pair(e, !exist)); +} + //----------------------------------------------------------------------------- // add a curve as a right curve or left curve when the event is created // or updated. From caf5b31af6420d9770c6051e8e2067b04f4699c5 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 4 Aug 2020 15:42:26 +0200 Subject: [PATCH 02/10] Indexed sweep in overlay (WIP: triggers assertions in some tests) --- .../include/CGAL/Arr_dcel_base.h | 2 + .../include/CGAL/Arr_overlay_2.h | 50 ++++++++++++++++++- .../Surface_sweep_2/Arr_overlay_traits_2.h | 1 + .../CGAL/No_intersection_surface_sweep_2.h | 11 ++++ 4 files changed, 63 insertions(+), 1 deletion(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_dcel_base.h b/Arrangement_on_surface_2/include/CGAL/Arr_dcel_base.h index 5a93384baa6..76f490663f0 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_dcel_base.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_dcel_base.h @@ -287,6 +287,8 @@ public: typedef Arr_halfedge Halfedge; typedef Arr_isolated_vertex Isolated_vertex; + mutable std::size_t index; + /*! Default constructor. */ Arr_vertex() {} diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_overlay_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_overlay_2.h index e4c739c8c23..569d6e66d93 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_overlay_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_overlay_2.h @@ -40,6 +40,45 @@ namespace CGAL { +template +class Indexed_sweep_accessor +{ + std::size_t nbv; + +public: + Indexed_sweep_accessor (std::size_t nbv) : nbv(nbv) { } + + std::size_t nb_vertices() const { return nbv; } + + std::size_t source_index (const Curve& c) const + { + return halfedge(c)->target()->index; + } + + std::size_t target_index (const Curve& c) const + { + return halfedge(c)->source()->index; + } + + const Curve& curve (const Curve& c) const + { + return c; + } + +private: + + typename Curve::Halfedge_handle halfedge (const Curve& c) const + { + if (c.red_halfedge_handle() == typename Curve::Halfedge_handle()) + { + CGAL_assertion (c.blue_halfedge_handle() != typename Curve::Halfedge_handle()); + return c.blue_halfedge_handle(); + } + // else + return c.red_halfedge_handle(); + } +}; + /*! Compute the overlay of two input arrangements. * \tparam GeometryTraitsA_2 the geometry traits of the first arrangement. * \tparam GeometryTraitsB_2 the geometry traits of the second arrangement. @@ -129,6 +168,15 @@ overlay(const Arrangement_on_surface_2& arr1 CGAL_precondition(((void*)(&arr) != (void*)(&arr1)) && ((void*)(&arr) != (void*)(&arr2))); + // Index vertices for indexed sweep + std::size_t idx = 0; + for (typename Arr_a::Vertex_const_iterator vit = arr1.vertices_begin(); + vit != arr1.vertices_end(); ++vit, ++idx) + vit->index = idx; + for (typename Arr_b::Vertex_const_iterator vit = arr2.vertices_begin(); + vit != arr2.vertices_end(); ++vit, ++idx) + vit->index = idx; + // Prepare a vector of extended x-monotone curves that represent all edges // in both input arrangements. Each curve is associated with a halfedge // directed from right to left. @@ -183,7 +231,7 @@ overlay(const Arrangement_on_surface_2& arr1 if (total_iso_verts == 0) { // Clear the result arrangement and perform the sweep to construct it. arr.clear(); - surface_sweep.sweep(xcvs_vec.begin(), xcvs_vec.end()); + surface_sweep.indexed_sweep (xcvs_vec, Indexed_sweep_accessor(idx)); xcvs_vec.clear(); return; } diff --git a/Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_overlay_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_overlay_traits_2.h index 8f6275e441d..4d10d82a005 100644 --- a/Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_overlay_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_overlay_traits_2.h @@ -134,6 +134,7 @@ public: class Ex_x_monotone_curve_2 { public: typedef Base_x_monotone_curve_2 Base; + typedef Halfedge_handle_blue Halfedge_handle; protected: Base m_base_xcv; // The base curve. diff --git a/Surface_sweep_2/include/CGAL/No_intersection_surface_sweep_2.h b/Surface_sweep_2/include/CGAL/No_intersection_surface_sweep_2.h index 39349d5d42a..659624f48b7 100644 --- a/Surface_sweep_2/include/CGAL/No_intersection_surface_sweep_2.h +++ b/Surface_sweep_2/include/CGAL/No_intersection_surface_sweep_2.h @@ -424,6 +424,17 @@ protected: _init_curves(curves_begin, curves_end); // initialize the curves } + /*! Initiliaze the sweep algorithm. */ + template + void _init_indexed_sweep(const EdgeRange& edges, + const Accessor& accessor) + { + m_num_of_subCurves = + static_cast(std::distance(edges.begin(), edges.end())); + _init_structures(); + _init_indexed_curves(edges, accessor); // initialize the curves + } + /*! Initialize the data structures for the sweep-line algorithm. */ virtual void _init_structures(); From acb96cba86842093ea6d975df04750c46dbffb95 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 12 Aug 2020 15:56:46 +0200 Subject: [PATCH 03/10] Get rid of index using pointer squatting + before/after functions --- .../include/CGAL/Arr_dcel_base.h | 7 ++- .../include/CGAL/Arr_overlay_2.h | 62 ++++++++++++++----- .../CGAL/No_intersection_surface_sweep_2.h | 2 + 3 files changed, 53 insertions(+), 18 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_dcel_base.h b/Arrangement_on_surface_2/include/CGAL/Arr_dcel_base.h index 76f490663f0..2c685385abc 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_dcel_base.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_dcel_base.h @@ -90,6 +90,11 @@ public: /*! Destructor. */ virtual ~Arr_vertex_base() {} + // Access/modification for pointer squatting + void* inc() const { return p_inc; } + void set_inc(void * inc) const + { const_cast(*this).p_inc = inc; } + /*! Check if the point pointer is nullptr. */ bool has_null_point() const { return (p_pt == nullptr); } @@ -287,8 +292,6 @@ public: typedef Arr_halfedge Halfedge; typedef Arr_isolated_vertex Isolated_vertex; - mutable std::size_t index; - /*! Default constructor. */ Arr_vertex() {} diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_overlay_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_overlay_2.h index 569d6e66d93..d6b55cffd2c 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_overlay_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_overlay_2.h @@ -40,24 +40,31 @@ namespace CGAL { -template +template class Indexed_sweep_accessor { - std::size_t nbv; + const Arr1& arr1; + const Arr2& arr2; + mutable std::vector backup_inc; public: - Indexed_sweep_accessor (std::size_t nbv) : nbv(nbv) { } - std::size_t nb_vertices() const { return nbv; } + Indexed_sweep_accessor (const Arr1& arr1, const Arr2& arr2) + : arr1(arr1), arr2(arr2) { } + + std::size_t nb_vertices() const + { + return arr1.number_of_vertices() + arr2.number_of_vertices(); + } std::size_t source_index (const Curve& c) const { - return halfedge(c)->target()->index; + return reinterpret_cast(halfedge(c)->target()->inc()); } std::size_t target_index (const Curve& c) const { - return halfedge(c)->source()->index; + return reinterpret_cast(halfedge(c)->source()->inc()); } const Curve& curve (const Curve& c) const @@ -65,6 +72,35 @@ public: return c; } + void before_init() const + { + std::size_t idx = 0; + backup_inc.reserve (nb_vertices()); + for (typename Arr1::Vertex_const_iterator vit = arr1.vertices_begin(); + vit != arr1.vertices_end(); ++vit, ++idx) + { + backup_inc[idx] = vit->inc(); + vit->set_inc (reinterpret_cast(idx)); + } + for (typename Arr2::Vertex_const_iterator vit = arr2.vertices_begin(); + vit != arr2.vertices_end(); ++vit, ++idx) + { + backup_inc[idx] = vit->inc(); + vit->set_inc (reinterpret_cast(idx)); + } + } + + void after_init() const + { + std::size_t idx = 0; + for (typename Arr1::Vertex_const_iterator vit = arr1.vertices_begin(); + vit != arr1.vertices_end(); ++vit, ++idx) + vit->set_inc (backup_inc[idx]); + for (typename Arr2::Vertex_const_iterator vit = arr2.vertices_begin(); + vit != arr2.vertices_end(); ++vit, ++idx) + vit->set_inc (backup_inc[idx]); + } + private: typename Curve::Halfedge_handle halfedge (const Curve& c) const @@ -168,15 +204,6 @@ overlay(const Arrangement_on_surface_2& arr1 CGAL_precondition(((void*)(&arr) != (void*)(&arr1)) && ((void*)(&arr) != (void*)(&arr2))); - // Index vertices for indexed sweep - std::size_t idx = 0; - for (typename Arr_a::Vertex_const_iterator vit = arr1.vertices_begin(); - vit != arr1.vertices_end(); ++vit, ++idx) - vit->index = idx; - for (typename Arr_b::Vertex_const_iterator vit = arr2.vertices_begin(); - vit != arr2.vertices_end(); ++vit, ++idx) - vit->index = idx; - // Prepare a vector of extended x-monotone curves that represent all edges // in both input arrangements. Each curve is associated with a halfedge // directed from right to left. @@ -231,7 +258,10 @@ overlay(const Arrangement_on_surface_2& arr1 if (total_iso_verts == 0) { // Clear the result arrangement and perform the sweep to construct it. arr.clear(); - surface_sweep.indexed_sweep (xcvs_vec, Indexed_sweep_accessor(idx)); + surface_sweep.indexed_sweep (xcvs_vec, + Indexed_sweep_accessor + + (arr1, arr2)); xcvs_vec.clear(); return; } diff --git a/Surface_sweep_2/include/CGAL/No_intersection_surface_sweep_2.h b/Surface_sweep_2/include/CGAL/No_intersection_surface_sweep_2.h index 659624f48b7..34bd84ce139 100644 --- a/Surface_sweep_2/include/CGAL/No_intersection_surface_sweep_2.h +++ b/Surface_sweep_2/include/CGAL/No_intersection_surface_sweep_2.h @@ -314,7 +314,9 @@ public: const Accessor& accessor) { m_visitor->before_sweep(); + accessor.before_init(); _init_indexed_sweep(edges, accessor); + accessor.after_init(); _sweep(); _complete_sweep(); m_visitor->after_sweep(); From 6022a74ac8458ebc3dc6751900374bdbecdf7370 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 13 Aug 2020 08:47:33 +0200 Subject: [PATCH 04/10] Only use indexed sweep for curves with bottom(/top) side NOT contracted --- .../include/CGAL/Arr_overlay_2.h | 16 ++++++++++------ .../CGAL/No_intersection_surface_sweep_2.h | 4 ++-- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_overlay_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_overlay_2.h index d6b55cffd2c..3cb975e4b0b 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_overlay_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_overlay_2.h @@ -59,12 +59,12 @@ public: std::size_t source_index (const Curve& c) const { - return reinterpret_cast(halfedge(c)->target()->inc()); + return reinterpret_cast(halfedge(c)->source()->inc()); } std::size_t target_index (const Curve& c) const { - return reinterpret_cast(halfedge(c)->source()->inc()); + return reinterpret_cast(halfedge(c)->target()->inc()); } const Curve& curve (const Curve& c) const @@ -258,10 +258,14 @@ overlay(const Arrangement_on_surface_2& arr1 if (total_iso_verts == 0) { // Clear the result arrangement and perform the sweep to construct it. arr.clear(); - surface_sweep.indexed_sweep (xcvs_vec, - Indexed_sweep_accessor - - (arr1, arr2)); + if (std::is_same::value) + surface_sweep.sweep (xcvs_vec.begin(), xcvs_vec.end()); + else + surface_sweep.indexed_sweep (xcvs_vec, + Indexed_sweep_accessor + + (arr1, arr2)); xcvs_vec.clear(); return; } diff --git a/Surface_sweep_2/include/CGAL/No_intersection_surface_sweep_2.h b/Surface_sweep_2/include/CGAL/No_intersection_surface_sweep_2.h index 34bd84ce139..99660eb4c63 100644 --- a/Surface_sweep_2/include/CGAL/No_intersection_surface_sweep_2.h +++ b/Surface_sweep_2/include/CGAL/No_intersection_surface_sweep_2.h @@ -408,8 +408,8 @@ protected: (m_subCurves + index)->set_hint(this->m_statusLine.end()); (m_subCurves + index)->init (curve); - _init_curve_end(curve, ARR_MAX_END, m_subCurves + index, events, target); - _init_curve_end(curve, ARR_MIN_END, m_subCurves + index, events, source); + _init_curve_end(curve, ARR_MAX_END, m_subCurves + index, events, source); + _init_curve_end(curve, ARR_MIN_END, m_subCurves + index, events, target); ++ index; } From b7583f43d57d6e5312edf5e8c4ac8112e9804f94 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 13 Aug 2020 09:19:50 +0200 Subject: [PATCH 05/10] Add indexed sweep with isolated points --- .../include/CGAL/Arr_overlay_2.h | 12 ++++++++++-- .../CGAL/No_intersection_surface_sweep_2.h | 18 ++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_overlay_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_overlay_2.h index 3cb975e4b0b..2d7c0185fa0 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_overlay_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_overlay_2.h @@ -297,8 +297,16 @@ overlay(const Arrangement_on_surface_2& arr1 // Clear the result arrangement and perform the sweep to construct it. arr.clear(); - surface_sweep.sweep(xcvs_vec.begin(), xcvs_vec.end(), - pts_vec.begin(), pts_vec.end()); + if (std::is_same::value) + surface_sweep.sweep(xcvs_vec.begin(), xcvs_vec.end(), + pts_vec.begin(), pts_vec.end()); + else + surface_sweep.indexed_sweep (xcvs_vec, + Indexed_sweep_accessor + + (arr1, arr2), + pts_vec.begin(), pts_vec.end()); xcvs_vec.clear(); pts_vec.clear(); } diff --git a/Surface_sweep_2/include/CGAL/No_intersection_surface_sweep_2.h b/Surface_sweep_2/include/CGAL/No_intersection_surface_sweep_2.h index 99660eb4c63..4bc47c4def0 100644 --- a/Surface_sweep_2/include/CGAL/No_intersection_surface_sweep_2.h +++ b/Surface_sweep_2/include/CGAL/No_intersection_surface_sweep_2.h @@ -322,6 +322,24 @@ public: m_visitor->after_sweep(); } + template + void indexed_sweep (const EdgeRange& edges, + const Accessor& accessor, + PointInputIterator action_points_begin, + PointInputIterator action_points_end) + { + m_visitor->before_sweep(); + accessor.before_init(); + _init_indexed_sweep(edges, accessor); + accessor.after_init(); + _init_points(action_points_begin, action_points_end, Event::ACTION); + //m_visitor->after_init(); + _sweep(); + _complete_sweep(); + m_visitor->after_sweep(); + } + /*! Get an iterator for the first subcurve in the status line. */ Status_line_iterator status_line_begin() { return m_statusLine.begin(); } From 901f52018cf02249ea472d778115e155662a79af Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 13 Aug 2020 09:52:47 +0200 Subject: [PATCH 06/10] Some fixes + internal doc for indexed sweep --- .../include/CGAL/Arr_overlay_2.h | 16 +++--- .../CGAL/No_intersection_surface_sweep_2.h | 49 +++++++++++++++++-- 2 files changed, 53 insertions(+), 12 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_overlay_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_overlay_2.h index 2d7c0185fa0..a383d8602f8 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_overlay_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_overlay_2.h @@ -57,16 +57,16 @@ public: return arr1.number_of_vertices() + arr2.number_of_vertices(); } - std::size_t source_index (const Curve& c) const - { - return reinterpret_cast(halfedge(c)->source()->inc()); - } - - std::size_t target_index (const Curve& c) const + std::size_t min_end_index (const Curve& c) const { return reinterpret_cast(halfedge(c)->target()->inc()); } + std::size_t max_end_index (const Curve& c) const + { + return reinterpret_cast(halfedge(c)->source()->inc()); + } + const Curve& curve (const Curve& c) const { return c; @@ -258,7 +258,7 @@ overlay(const Arrangement_on_surface_2& arr1 if (total_iso_verts == 0) { // Clear the result arrangement and perform the sweep to construct it. arr.clear(); - if (std::is_same::value) surface_sweep.sweep (xcvs_vec.begin(), xcvs_vec.end()); else @@ -297,7 +297,7 @@ overlay(const Arrangement_on_surface_2& arr1 // Clear the result arrangement and perform the sweep to construct it. arr.clear(); - if (std::is_same::value) surface_sweep.sweep(xcvs_vec.begin(), xcvs_vec.end(), pts_vec.begin(), pts_vec.end()); diff --git a/Surface_sweep_2/include/CGAL/No_intersection_surface_sweep_2.h b/Surface_sweep_2/include/CGAL/No_intersection_surface_sweep_2.h index 4bc47c4def0..b007b656a25 100644 --- a/Surface_sweep_2/include/CGAL/No_intersection_surface_sweep_2.h +++ b/Surface_sweep_2/include/CGAL/No_intersection_surface_sweep_2.h @@ -309,6 +309,23 @@ public: m_visitor->after_sweep(); } + /*! + Run the indexed sweep-line algorithm on a given range of + x-monotone curves and accessor. The main difference from the + original sweep() function is that the accessor allows to get + indices of end-points and avoid checking several times in the + event queue when the same vertex as several incident edges. + + \param edges A range of edges + \param accessor An object providing, for a value_type `e` of + range `edges`, the following methods: + - size_t min_end_index(e) -> the index of the min end of curve c + - size_t max_end_index(e) -> the index of the max end of curve c + - X_monotone_curve_2 curve(e) -> the x-monotone curve associated to e + - size_t nb_vertices() -> the total number of points/events + - void before_init() -> called before initialization + - void after_init() -> called after initialization + */ template void indexed_sweep (const EdgeRange& edges, const Accessor& accessor) @@ -322,6 +339,30 @@ public: m_visitor->after_sweep(); } + /*! + Run the indexed sweep-line algorithm on a given range of + x-monotone curves and accessor. The main difference from the + original sweep() function is that the accessor allows to get + indices of end-points and avoid checking several times in the + event queue when the same vertex as several incident edges. + + Variant with action event points (if a curve passed through an + action point, it will be split). + + \param edges A range of edges + \param accessor An object providing, for a value_type `e` of + range `edges`, the following methods: + - size_t min_end_index(e) -> the index of the min end of curve c + - size_t max_end_index(e) -> the index of the max end of curve c + - X_monotone_curve_2 curve(e) -> the x-monotone curve associated to e + - size_t nb_vertices() -> the total number of points/events + - void before_init() -> called before initialization + - void after_init() -> called after initialization + \param points_begin An iterator for the first point in the range. + \param points_end A past-the-end iterator for this range. + \pre The value-type of PointInputIterator is the + traits-class Point_2. + */ template void indexed_sweep (const EdgeRange& edges, @@ -417,8 +458,8 @@ protected: unsigned int index = 0; for (const auto& e : edges) { - std::size_t source = accessor.source_index(e); - std::size_t target = accessor.target_index(e); + std::size_t max_end = accessor.max_end_index(e); + std::size_t min_end = accessor.min_end_index(e); const X_monotone_curve_2& curve = accessor.curve (e); // Construct and initialize a subcurve object. @@ -426,8 +467,8 @@ protected: (m_subCurves + index)->set_hint(this->m_statusLine.end()); (m_subCurves + index)->init (curve); - _init_curve_end(curve, ARR_MAX_END, m_subCurves + index, events, source); - _init_curve_end(curve, ARR_MIN_END, m_subCurves + index, events, target); + _init_curve_end(curve, ARR_MAX_END, m_subCurves + index, events, max_end); + _init_curve_end(curve, ARR_MIN_END, m_subCurves + index, events, min_end); ++ index; } From 36a210065f831d9150eeef330c24b5dadc636ecd Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 17 Aug 2020 10:11:28 +0200 Subject: [PATCH 07/10] Fix for cases where red and blue handles are differently typed --- .../include/CGAL/Arr_overlay_2.h | 22 +++++++++---------- .../Surface_sweep_2/Arr_overlay_traits_2.h | 3 ++- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_overlay_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_overlay_2.h index a383d8602f8..9b45e51dafc 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_overlay_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_overlay_2.h @@ -59,12 +59,20 @@ public: std::size_t min_end_index (const Curve& c) const { - return reinterpret_cast(halfedge(c)->target()->inc()); + if (c.red_halfedge_handle() != typename Curve::HH_red()) + return reinterpret_cast(c.red_halfedge_handle()->target()->inc()); + // else + CGAL_assertion (c.blue_halfedge_handle() != typename Curve::HH_blue()); + return reinterpret_cast(c.blue_halfedge_handle()->target()->inc()); } std::size_t max_end_index (const Curve& c) const { - return reinterpret_cast(halfedge(c)->source()->inc()); + if (c.red_halfedge_handle() != typename Curve::HH_red()) + return reinterpret_cast(c.red_halfedge_handle()->source()->inc()); + // else + CGAL_assertion (c.blue_halfedge_handle() != typename Curve::HH_blue()); + return reinterpret_cast(c.blue_halfedge_handle()->source()->inc()); } const Curve& curve (const Curve& c) const @@ -103,16 +111,6 @@ public: private: - typename Curve::Halfedge_handle halfedge (const Curve& c) const - { - if (c.red_halfedge_handle() == typename Curve::Halfedge_handle()) - { - CGAL_assertion (c.blue_halfedge_handle() != typename Curve::Halfedge_handle()); - return c.blue_halfedge_handle(); - } - // else - return c.red_halfedge_handle(); - } }; /*! Compute the overlay of two input arrangements. diff --git a/Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_overlay_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_overlay_traits_2.h index 4d10d82a005..eff640e5443 100644 --- a/Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_overlay_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_overlay_traits_2.h @@ -134,7 +134,8 @@ public: class Ex_x_monotone_curve_2 { public: typedef Base_x_monotone_curve_2 Base; - typedef Halfedge_handle_blue Halfedge_handle; + typedef Halfedge_handle_red HH_red; + typedef Halfedge_handle_blue HH_blue; protected: Base m_base_xcv; // The base curve. From 47f3372ad9c7e0f50833c72de9767064413b4aef Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 17 Aug 2020 10:22:03 +0200 Subject: [PATCH 08/10] Handle open boundary in indexed sweep (fallback to unindexed mode) --- .../No_intersection_surface_sweep_2_impl.h | 32 +++++++++++++------ 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/Surface_sweep_2/include/CGAL/Surface_sweep_2/No_intersection_surface_sweep_2_impl.h b/Surface_sweep_2/include/CGAL/Surface_sweep_2/No_intersection_surface_sweep_2_impl.h index eb30c4d310e..498984d57b5 100644 --- a/Surface_sweep_2/include/CGAL/Surface_sweep_2/No_intersection_surface_sweep_2_impl.h +++ b/Surface_sweep_2/include/CGAL/Surface_sweep_2/No_intersection_surface_sweep_2_impl.h @@ -316,18 +316,30 @@ _init_curve_end(const X_monotone_curve_2& cv, Arr_curve_end ind, Subcurve* sc, // Create the corresponding event and push it into the event queue. std::pair pair_res; - const Point_2& pt = (ind == ARR_MIN_END) ? - m_traits->construct_min_vertex_2_object()(cv) : - m_traits->construct_max_vertex_2_object()(cv); + if (m_traits->is_closed_2_object()(cv, ind)) { + // The curve end is closed and thus associated with a valid endpoint. + const Point_2& pt = (ind == ARR_MIN_END) ? + m_traits->construct_min_vertex_2_object()(cv) : + m_traits->construct_max_vertex_2_object()(cv); - pair_res = ((ps_x == ARR_INTERIOR) && (ps_y == ARR_INTERIOR)) ? - _push_event(pt, end_attr, ps_x, ps_y, sc, events, index) : - _push_event(cv, ind, end_attr, ps_x, ps_y, sc, pt, events, index); + pair_res = ((ps_x == ARR_INTERIOR) && (ps_y == ARR_INTERIOR)) ? + _push_event(pt, end_attr, ps_x, ps_y, sc, events, index) : + _push_event(cv, ind, end_attr, ps_x, ps_y, sc, pt, events, index); - // Inform the visitor in case we updated an existing event. - Event* e = pair_res.first; - CGAL_assertion(e->is_closed()); - m_visitor->update_event(e, pt, cv, ind, pair_res.second); + // Inform the visitor in case we updated an existing event. + Event* e = pair_res.first; + CGAL_assertion(e->is_closed()); + m_visitor->update_event(e, pt, cv, ind, pair_res.second); + } + else { + // The curve end is open, insert it into the event queue. + pair_res = _push_event(cv, ind, end_attr, ps_x, ps_y, sc); + + // Inform the visitor in case we updated an existing event. + Event* e = pair_res.first; + CGAL_assertion(! e->is_closed()); + _update_event_at_open_boundary(e, cv, ind, pair_res.second); + } } //----------------------------------------------------------------------------- From 7d23ac99e2d2857e81e18398bf45a1dc10ff2577 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 17 Aug 2020 10:26:08 +0200 Subject: [PATCH 09/10] Update internal doc from review --- .../include/CGAL/Arr_overlay_2.h | 2 ++ .../include/CGAL/No_intersection_surface_sweep_2.h | 13 ++++++------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_overlay_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_overlay_2.h index 9b45e51dafc..cf7143001ef 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_overlay_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_overlay_2.h @@ -80,6 +80,7 @@ public: return c; } + // Initializes indices by squatting Vertex::inc(); void before_init() const { std::size_t idx = 0; @@ -98,6 +99,7 @@ public: } } + // Restores state of arrangements before index squatting void after_init() const { std::size_t idx = 0; diff --git a/Surface_sweep_2/include/CGAL/No_intersection_surface_sweep_2.h b/Surface_sweep_2/include/CGAL/No_intersection_surface_sweep_2.h index b007b656a25..99a228f8efc 100644 --- a/Surface_sweep_2/include/CGAL/No_intersection_surface_sweep_2.h +++ b/Surface_sweep_2/include/CGAL/No_intersection_surface_sweep_2.h @@ -310,11 +310,11 @@ public: } /*! - Run the indexed sweep-line algorithm on a given range of + runs the indexed sweep-line algorithm on a given range of x-monotone curves and accessor. The main difference from the - original sweep() function is that the accessor allows to get + original `sweep()` function is that the accessor allows to get indices of end-points and avoid checking several times in the - event queue when the same vertex as several incident edges. + event queue when the same vertex has several incident edges. \param edges A range of edges \param accessor An object providing, for a value_type `e` of @@ -340,11 +340,11 @@ public: } /*! - Run the indexed sweep-line algorithm on a given range of + runs the indexed sweep-line algorithm on a given range of x-monotone curves and accessor. The main difference from the - original sweep() function is that the accessor allows to get + original `sweep()` function is that the accessor allows to get indices of end-points and avoid checking several times in the - event queue when the same vertex as several incident edges. + event queue when the same vertex has several incident edges. Variant with action event points (if a curve passed through an action point, it will be split). @@ -375,7 +375,6 @@ public: _init_indexed_sweep(edges, accessor); accessor.after_init(); _init_points(action_points_begin, action_points_end, Event::ACTION); - //m_visitor->after_init(); _sweep(); _complete_sweep(); m_visitor->after_sweep(); From adef28b496cbdddd150685ea9f83f49fda64cd42 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 21 Oct 2020 10:12:51 +0200 Subject: [PATCH 10/10] Add assertions and fix bug --- Arrangement_on_surface_2/include/CGAL/Arr_overlay_2.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_overlay_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_overlay_2.h index cf7143001ef..393958f3424 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_overlay_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_overlay_2.h @@ -84,16 +84,18 @@ public: void before_init() const { std::size_t idx = 0; - backup_inc.reserve (nb_vertices()); + backup_inc.resize (nb_vertices()); for (typename Arr1::Vertex_const_iterator vit = arr1.vertices_begin(); vit != arr1.vertices_end(); ++vit, ++idx) { + CGAL_assertion (idx < backup_inc.size()); backup_inc[idx] = vit->inc(); vit->set_inc (reinterpret_cast(idx)); } for (typename Arr2::Vertex_const_iterator vit = arr2.vertices_begin(); vit != arr2.vertices_end(); ++vit, ++idx) { + CGAL_assertion (idx < backup_inc.size()); backup_inc[idx] = vit->inc(); vit->set_inc (reinterpret_cast(idx)); } @@ -105,10 +107,16 @@ public: std::size_t idx = 0; for (typename Arr1::Vertex_const_iterator vit = arr1.vertices_begin(); vit != arr1.vertices_end(); ++vit, ++idx) + { + CGAL_assertion (idx < backup_inc.size()); vit->set_inc (backup_inc[idx]); + } for (typename Arr2::Vertex_const_iterator vit = arr2.vertices_begin(); vit != arr2.vertices_end(); ++vit, ++idx) + { + CGAL_assertion (idx < backup_inc.size()); vit->set_inc (backup_inc[idx]); + } } private: