From 403cf9d75cfc810879bf82f79c9ed73859947eb2 Mon Sep 17 00:00:00 2001 From: Ron Wein Date: Sun, 19 Feb 2006 13:10:16 +0000 Subject: [PATCH] Improved the divide-and-conquer algorithm for aggregated operations, so that we use merge sort instead of O(n log(n)) sort. (with Baruch) --- .../Boolean_set_operations_2/Gps_agg_op.h | 90 ++---- .../Gps_agg_op_sweep.h | 275 ++++++++++++++++++ .../Gps_agg_op_visitor.h | 155 +++++++++- .../CGAL/Boolean_set_operations_2/Gps_merge.h | 77 +++-- .../Gps_polygon_simplifier.h | 11 +- .../include/CGAL/General_polygon_set_2.h | 219 +++++++++----- 6 files changed, 650 insertions(+), 177 deletions(-) create mode 100644 Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_agg_op_sweep.h diff --git a/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_agg_op.h b/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_agg_op.h index d2e4cec3655..fa57759dfbc 100644 --- a/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_agg_op.h +++ b/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_agg_op.h @@ -12,7 +12,7 @@ // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // // $URL$ -// $Id$ +// $Id$ $Date$ // // // Author(s) : Baruch Zukerman @@ -21,7 +21,7 @@ #define GSP_AGG_OP_H #include -#include +#include #include #include @@ -52,20 +52,28 @@ class Gps_agg_op Ccb_halfedge_const_circulator; typedef typename Arrangement_2::Ccb_halfedge_circulator Ccb_halfedge_circulator; + + typedef std::pair *> Arr_entry; + typedef Arr_construction_curve Subcurve; typedef Arr_construction_event Event; + Halfedge_handle> Base_event; + + typedef Indexed_event Event; typedef Gps_agg_op_visitor Visitor; - typedef Sweep_line_2 Sweep_line_2; + typedef Gps_agg_op_sweep_line_2 Sweep_line_2; + typedef Unique_hash_map Edges_hash; @@ -85,19 +93,18 @@ protected: public: /*! Constructor. */ - Gps_agg_op (Arrangement_2& arr, Traits_2& tr) : + Gps_agg_op (Arrangement_2& arr, std::vector& vert_vec, + Traits_2& tr) : m_arr (&arr), m_traits(new Meta_traits(tr)), - m_visitor (&arr, &m_edges_hash), + m_visitor (&arr, &m_edges_hash, &vert_vec), m_sweep_line (m_traits, &m_visitor) {} - - void sweep_arrangements(unsigned int lower, unsigned int upper, unsigned int jump, - std::vector& arr_vec) + std::vector& arr_vec) { std::list curves_list; @@ -106,14 +113,16 @@ public: unsigned int n_inf_pgn = 0; // number of infinte polygons (arrangement // with a contained unbounded face - unsigned int n_pgn = 0; // number of polygons (arrangements) - for(unsigned int i=lower; i<=upper; i+=jump, ++n_pgn) + unsigned int n_pgn = 0; // number of polygons (arrangements) + unsigned int i; + + for (i = lower; i <= upper; i += jump, ++n_pgn) { - Arrangement_2* arr = arr_vec[i]; - if(arr->unbounded_face()->contained()) + Arrangement_2* arr = (arr_vec[i]).first; + if (arr->unbounded_face()->contained()) ++n_inf_pgn; - Edge_iterator itr = arr->edges_begin(); + Edge_iterator itr = arr->edges_begin(); for(; itr != arr->edges_end(); ++itr) { // take only relevant edges (which seperate between contained and @@ -129,7 +138,10 @@ public: curves_list.push_back(Meta_X_monotone_curve_2(he->curve(), cv_data)); } } - m_sweep_line.sweep(curves_list.begin(), curves_list.end()); + + m_sweep_line.sweep (curves_list.begin(), curves_list.end(), + lower, upper, jump, + arr_vec); m_faces_hash[m_arr->unbounded_face()] = n_inf_pgn; Bfs_visitor visitor(&m_edges_hash, &m_faces_hash, n_pgn); @@ -139,48 +151,6 @@ public: visitor.after_scan(*m_arr); } - //Arrangement_2* create_clean_arr() - //{ - // typedef Gps_insertion_meta_traits Insert_meta_traits; - // typedef typename Insert_meta_traits::Curve_data Curve_data; - // typedef Arr_construction_curve Subcurve; - // typedef Arr_construction_event Event; - // typedef typename Insert_meta_traits::X_monotone_curve_2 Ex_X_monotone_curve_2; - // typedef Arr_construction_visitor Insertion_visitor; - // typedef Basic_sweep_line_2 Basic_sweep_line_2; - - // - // - // Arrangement_2* new_arr = new Arrangement_2(); - // std::vector xcurves_vec; - // for(Edge_iterator itr = m_arr->edges_begin(); - // itr != m_arr->edges_end(); - // ++itr) - // { - // Halfedge_handle he = itr; - // if(he->face()->contained() == he->twin()->face()->contained()) - // continue; //redundent edge, continue. - - // if(he->direction() == LARGER) - // he = he->twin(); - - // xcurves_vec.push_back(Ex_X_monotone_curve_2(he->curve(), Curve_data(he))); - // } - - // std::cout<<"number of edges in clear arr: " << xcurves_vec.size()<<"\n"; - // Insertion_visitor visitor(new_arr); - // Basic_sweep_line_2 sl (&visitor); - // sl.sweep(xcurves_vec.begin(), xcurves_vec.end()); - //} - ~Gps_agg_op() { delete m_traits; diff --git a/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_agg_op_sweep.h b/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_agg_op_sweep.h new file mode 100644 index 00000000000..2df63d68714 --- /dev/null +++ b/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_agg_op_sweep.h @@ -0,0 +1,275 @@ +// Copyright (c) 2005 Tel-Aviv University (Israel). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you may redistribute it under +// the terms of the Q Public License version 1.0. +// See the file LICENSE.QPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ $Date$ +// +// +// Author(s) : Baruch Zukerman +// Ron Wein + +#ifndef GSP_AGG_OP_SWEEP_H +#define GSP_AGG_OP_SWEEP_H + +#include +#include + +CGAL_BEGIN_NAMESPACE + +template +class Gps_agg_op_sweep_line_2 : + public Sweep_line_2 +{ +public: + + typedef Arrangement_ Arrangement_2; + typedef MetaTraits_ Traits_2; + typedef typename Traits_2::Point_2 Point_2; + typedef typename Traits_2::X_monotone_curve_2 X_monotone_curve_2; + + typedef typename Arrangement_2::Vertex_handle Vertex_handle; + typedef typename Arrangement_2::Halfedge_handle Halfedge_handle; + + typedef std::pair *> Arr_entry; + + typedef Sweep_line_2 Base; + + typedef SweepEvent Event; + typedef typename Base::EventQueueIter EventQueueIter; + typedef typename Event::SubCurveIter EventCurveIter; + + typedef typename Base::Base_event Base_event; + typedef typename Base_event::Attribute Attribute; + + typedef typename Base::Base_subcurve Base_subcurve; + + typedef CurveWrap Subcurve; + + typedef std::list SubCurveList; + typedef typename SubCurveList::iterator SubCurveListIter; + + typedef typename Base::StatusLineIter StatusLineIter; + +public: + + /*! + * Constructor. + * \param visitor A pointer to a sweep-line visitor object. + */ + Gps_agg_op_sweep_line_2 (SweepVisitor* visitor) : + Base (visitor) + {} + + /*! + * Constructor. + * \param traits A pointer to a sweep-line traits object. + * \param visitor A pointer to a sweep-line visitor object. + */ + Gps_agg_op_sweep_line_2 (Traits_2 *traits, SweepVisitor* visitor) : + Base(traits, visitor) + {} + + /*! Perform the sweep. */ + template + void sweep (CurveInputIterator curves_begin, + CurveInputIterator curves_end, + unsigned int lower, + unsigned int upper, + unsigned int jump, + std::vector& arr_vec) + { + CGAL_assertion (this->m_queue->empty() && + this->m_statusLine.size() == 0); + + typedef Unique_hash_map Vertices_map; + typedef typename Traits_2::Compare_xy_2 Compare_xy_2; + + // Allocate all of the Subcurve objects as one block. + this->m_num_of_subCurves = std::distance (curves_begin, curves_end); + this->m_subCurves = + this->m_subCurveAlloc.allocate (this->m_num_of_subCurves); + + this->m_curves_pair_set.resize (2 * this->m_num_of_subCurves); + + // Initialize the event queue using the vertices vectors. Note that these + // vertices are already sorted, we simply have to merge them + Vertices_map vert_map; + Vertex_handle vh; + Vertex_handle invalid_v; + unsigned int i = lower; + unsigned int n = (arr_vec[i].second)->size(); + unsigned int j; + EventQueueIter q_iter; + bool first = true; + Attribute event_type; + Event *event; + + for (j = 0; + j < n && (vh = (*(arr_vec[i].second))[j]) != invalid_v; + j++) + { + // Insert the vertices of the first vector one after the other. + event_type = _type_of_vertex (vh); + if (event_type == Base_event::DEFAULT) + continue; + + event = this->allocate_event (vh->point(), event_type); + + if (! first) + { + q_iter = this->m_queue->insert_after (q_iter, event); + } + else + { + q_iter = this->m_queue->insert (event); + first = false; + } + + vert_map[vh] = event; + } + + Comparison_result res = LARGER; + Compare_xy_2 comp_xy = this->m_traits->compare_xy_2_object(); + EventQueueIter q_end = this->m_queue->end(); + + for (i += jump; i <= upper; i += jump) + { + // Merge the vertices of the other vectors into the existing queue. + q_iter = this->m_queue->begin(); + n = (arr_vec[i].second)->size(); + + for (j = 0; + j < n && (vh = (*(arr_vec[i].second))[j]) != invalid_v; + j++) + { + event_type = _type_of_vertex (vh); + if (event_type == Base_event::DEFAULT) + continue; + + while (q_iter != q_end && + (res = comp_xy (vh->point(), (*q_iter)->get_point())) == LARGER) + { + ++q_iter; + } + + if (res == SMALLER || q_iter == q_end) + { + event = this->allocate_event (vh->point(), event_type); + this->m_queue->insert_before (q_iter, event); + vert_map[vh] = event; + } + else if (res == EQUAL) + { + // In this case q_iter points to an event already associated with + // the vertex, so we just update the map: + vert_map[vh] = *q_iter; + } + } + } + + // Go over all curves (which are associated with halfedges) and associate + // them with the events we have just created. + unsigned int index = 0; + CurveInputIterator iter; + Halfedge_handle he; + Event *e_left; + Event *e_right; + + for (iter = curves_begin; iter != curves_end; ++iter, index++) + { + // Get the events associated with the end-vertices of the current + // halfedge. + he = iter->data().halfedge(); + + CGAL_assertion (vert_map.is_defined (he->source())); + CGAL_assertion (vert_map.is_defined (he->target())); + + if (he->direction() == SMALLER) + { + e_left = vert_map[he->source()]; + e_right = vert_map[he->target()]; + } + else + { + e_left = vert_map[he->target()]; + e_right = vert_map[he->source()]; + } + + // Create the subcurve object. + this->m_subCurveAlloc.construct (this->m_subCurves + index, + this->m_masterSubcurve); + + (this->m_subCurves + index)->init (*iter, e_left, e_right); + + e_right->add_curve_to_left (this->m_subCurves + index); + this->_add_curve_to_right (e_left, this->m_subCurves + index); + } + + // Perform the sweep: + this->m_visitor->after_init(); + this->_sweep(); + this->_complete_sweep(); + this->m_visitor->after_sweep(); + + return; + } + +private: + + /*! + * Check if the given vertex is an endpoint of an edge we are going + * to use in the sweep. + */ + Attribute _type_of_vertex (Vertex_handle v) + { + typename Arrangement_2::Halfedge_around_vertex_circulator first, circ; + + circ = first = v->incident_halfedges(); + do + { + // Check if the current edge separates two faces with unequal + // containment flags (otherwise we will simply not keep it). + if (circ->face()->contained() != circ->twin()->face()->contained()) + { + if (circ->direction() == SMALLER) + return (Base_event::RIGHT_END); + else + return (Base_event::LEFT_END); + } + ++circ; + + } while (circ != first); + + // If we reached here, we should not keep this vertex. + return (Base_event::DEFAULT); + } +}; + + +CGAL_END_NAMESPACE + +#endif diff --git a/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_agg_op_visitor.h b/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_agg_op_visitor.h index 21bf7e6aa9a..d1fc62a5a80 100644 --- a/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_agg_op_visitor.h +++ b/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_agg_op_visitor.h @@ -16,6 +16,7 @@ // // // Author(s) : Baruch Zukerman +// Ron Wein #ifndef GSP_AGG_OP_VISITOR #define GSP_AGG_OP_VISITOR @@ -26,7 +27,7 @@ CGAL_BEGIN_NAMESPACE template -class Gps_agg_op_visitor : +class Gps_agg_op_base_visitor : public Arr_construction_visitor { protected: @@ -38,11 +39,6 @@ class Gps_agg_op_visitor : Event, Subcurve> Base; - typedef Gps_agg_op_visitor Self; - typedef typename Base::SL_iterator SL_iterator; typedef typename Base::Halfedge_handle Halfedge_handle; typedef typename Base::Vertex_handle Vertex_handle; @@ -51,8 +47,6 @@ class Gps_agg_op_visitor : typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2; typedef typename Traits::Point_2 Point_2; - typedef typename Arrangement::Face_handle Face_handle; - typedef typename Arrangement::Face_const_handle Face_const_handle; typedef Unique_hash_map Edges_hash; protected: @@ -62,9 +56,9 @@ protected: public: - Gps_agg_op_visitor(Arrangement *arr, - Edges_hash* hash): Base(arr), - m_edges_hash(hash) + Gps_agg_op_base_visitor(Arrangement *arr, + Edges_hash* hash): Base(arr), + m_edges_hash(hash) {} virtual Halfedge_handle insert_in_face_interior(const X_monotone_curve_2& cv, @@ -135,6 +129,145 @@ private: }; +template +class Indexed_event : public BaseEvent_ +{ +private: + + unsigned int m_index; + +public: + + Indexed_event () : + BaseEvent_(), + m_index (0) + {} + + unsigned int index () const + { + return (m_index); + } + + void set_index (unsigned int index) + { + m_index = index; + return; + } +}; + +template +class Gps_agg_op_visitor : + public Gps_agg_op_base_visitor +{ +protected: + + typedef Arrangement_ Arrangement; + + typedef Gps_agg_op_base_visitor Base; + + typedef typename Base::SL_iterator SL_iterator; + typedef typename Base::Halfedge_handle Halfedge_handle; + typedef typename Base::Vertex_handle Vertex_handle; + typedef typename Base::SubCurveIter SubCurveIter; + typedef typename Base::SubCurveRevIter SubCurveRevIter; + typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2; + typedef typename Traits::Point_2 Point_2; + +protected: + + unsigned int m_event_count; // The number of events so far. + std::vector *m_vertices_vec; // The vertices, sorted in + // ascending order. + +public: + + Gps_agg_op_visitor (Arrangement *arr, + typename Base::Edges_hash* hash, + std::vector* vertices_vec) : + Base (arr, hash), + m_event_count (0), + m_vertices_vec (vertices_vec) + {} + + void before_handle_event (Event* event) + { + event->set_index (m_event_count); + m_event_count++; + + return; + } + + virtual Halfedge_handle + insert_in_face_interior (const X_monotone_curve_2& cv, + Subcurve* sc) + { + Halfedge_handle res_he = Base::insert_in_face_interior(cv, sc); + + // We now have a halfedge whose source vertex is associated with the + // last event and whose target vertex is associated with the current event: + Event *curr_event = reinterpret_cast(this->current_event()); + Event *last_event = reinterpret_cast((sc)->get_last_event()); + + CGAL_assertion (res_he->direction() == SMALLER); + _insert_vertex (curr_event, res_he->target()); + _insert_vertex (last_event, res_he->source()); + + return (res_he); + } + + virtual Halfedge_handle + insert_from_right_vertex (const X_monotone_curve_2& cv, + Halfedge_handle he, + Subcurve* sc) + { + Halfedge_handle res_he = Base::insert_from_right_vertex (cv, he, sc); + + // We now have a halfedge whose target vertex is associated with the + // last event (we have already dealt with its source vertex). + Event *last_event = reinterpret_cast((sc)->get_last_event()); + + CGAL_assertion (res_he->direction() == LARGER); + _insert_vertex (last_event, res_he->target()); + + return (res_he); + } + + virtual Halfedge_handle + insert_from_left_vertex (const X_monotone_curve_2& cv, + Halfedge_handle he, + Subcurve* sc) + { + Halfedge_handle res_he = Base::insert_from_left_vertex (cv, he, sc); + + // We now have a halfedge whose target vertex is associated with the + // current event (we have already dealt with its source vertex). + Event *curr_event = reinterpret_cast(this->current_event()); + + CGAL_assertion (res_he->direction() == SMALLER); + _insert_vertex (curr_event, res_he->target()); + + return (res_he); + } + +private: + + void _insert_vertex (const Event* event, + Vertex_handle v) + { + const unsigned int index = event->index(); + + if (index >= m_vertices_vec->size()) + m_vertices_vec->resize (2 * (index + 1)); + + (*m_vertices_vec)[index] = v; + return; + } + +}; + CGAL_END_NAMESPACE #endif diff --git a/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_merge.h b/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_merge.h index 7a2ef0497fa..43458de1902 100644 --- a/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_merge.h +++ b/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_merge.h @@ -12,7 +12,7 @@ // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // // $URL$ -// $Id$ +// $Id$ $Date$ // // // Author(s) : Baruch Zukerman @@ -29,86 +29,113 @@ CGAL_BEGIN_NAMESPACE -template +template class Join_merge { + typedef Arrangement_ Arrangement_2; + typedef typename Arrangement_2::Vertex_handle Vertex_handle; + typedef std::pair *> Arr_entry; + public: void operator()(unsigned int i, unsigned int j, unsigned int jump, - std::vector& arr_vec) + std::vector& arr_vec) { if(i==j) return; - typename Arrangement::Traits_2* tr = arr_vec[i]->get_traits(); - Arrangement* res = new Arrangement(tr); - Gps_agg_op > - agg_op(*res, *tr); + typename Arrangement_2::Traits_2* tr = arr_vec[i].first->get_traits(); + Arrangement_2 *res = new Arrangement_2(tr); + std::vector *verts = new std::vector; + + Gps_agg_op > + agg_op(*res, *verts, *tr); agg_op.sweep_arrangements(i, j, jump, arr_vec); for(unsigned int count=i; count<=j; count+=jump) { - delete arr_vec[count]; + delete (arr_vec[count].first); + delete (arr_vec[count].second); } - arr_vec[i] = res; + arr_vec[i].first = res; + arr_vec[i].second = verts; } }; -template +template class Intersection_merge { + typedef Arrangement_ Arrangement_2; + typedef typename Arrangement_2::Vertex_handle Vertex_handle; + typedef std::pair *> Arr_entry; + public: void operator()(unsigned int i, unsigned int j, unsigned int jump, - std::vector& arr_vec) + std::vector& arr_vec) { if(i==j) return; - typename Arrangement::Traits_2* tr = arr_vec[i]->get_traits(); - Arrangement* res = new Arrangement(tr); - Gps_agg_op > - agg_op(*res, *tr); + typename Arrangement_2::Traits_2* tr = arr_vec[i].first->get_traits(); + Arrangement_2 *res = new Arrangement_2 (tr); + std::vector *verts = new std::vector; + + Gps_agg_op > + agg_op(*res, *verts, *tr); agg_op.sweep_arrangements(i, j, jump, arr_vec); for(unsigned int count=i; count<=j; count+=jump) { - delete arr_vec[count]; + delete (arr_vec[count].first); + delete (arr_vec[count].second); } - arr_vec[i] = res; + arr_vec[i].first = res; + arr_vec[i].second = verts; } }; -template +template class Xor_merge { + typedef Arrangement_ Arrangement_2; + typedef typename Arrangement_2::Vertex_handle Vertex_handle; + typedef std::pair *> Arr_entry; + public: void operator()(unsigned int i, unsigned int j, unsigned int jump, - std::vector& arr_vec) + std::vector& arr_vec) { if(i==j) return; - typename Arrangement::Traits_2* tr = arr_vec[i]->get_traits(); - Arrangement* res = new Arrangement(tr); - Gps_agg_op > - agg_op(*res, *tr); + typename Arrangement_2::Traits_2* tr = arr_vec[i].first->get_traits(); + Arrangement_2 *res = new Arrangement_2(tr); + std::vector *verts = new std::vector; + + Gps_agg_op > + agg_op(*res, *verts, *tr); agg_op.sweep_arrangements(i, j, jump, arr_vec); for(unsigned int count=i; count<=j; count+=jump) { - delete arr_vec[count]; + delete (arr_vec[count].first); + delete (arr_vec[count].second); } - arr_vec[i] = res; + arr_vec[i].first = res; + arr_vec[i].second = verts; } }; diff --git a/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_polygon_simplifier.h b/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_polygon_simplifier.h index b3cb67661bd..00a334f9c10 100644 --- a/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_polygon_simplifier.h +++ b/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_polygon_simplifier.h @@ -62,15 +62,16 @@ class Gps_polygon_simplifier Subcurve, Halfedge_handle> Event; - typedef Gps_agg_op_visitor Visitor; + typedef Gps_agg_op_base_visitor Visitor; typedef Sweep_line_2 Sweep_line_2; + typedef Unique_hash_map Edges_hash; diff --git a/Boolean_set_operations_2/include/CGAL/General_polygon_set_2.h b/Boolean_set_operations_2/include/CGAL/General_polygon_set_2.h index 318da5655e5..61c6d3ae168 100644 --- a/Boolean_set_operations_2/include/CGAL/General_polygon_set_2.h +++ b/Boolean_set_operations_2/include/CGAL/General_polygon_set_2.h @@ -12,7 +12,7 @@ // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // // $URL$ -// $Id$ +// $Id$ $Date$ // // // Author(s) : Baruch Zukerman @@ -91,6 +91,8 @@ private: typedef typename Arrangement_2::Halfedge_around_vertex_const_circulator Halfedge_around_vertex_const_circulator; + typedef std::pair *> Arr_entry; typedef Arr_walk_along_line_point_location Walk_pl; protected: @@ -587,21 +589,23 @@ inline void join(InputIterator begin, Polygon_2& pgn, unsigned int k=5) { - std::vector arr_vec (std::distance(begin, end) + 1); + std::vector arr_vec (std::distance(begin, end) + 1); - arr_vec[0] = this->m_arr; + arr_vec[0].first = this->m_arr; unsigned int i = 1; for(InputIterator itr = begin; itr!=end; ++itr, ++i) { - arr_vec[i] = new Arrangement_2(m_traits); - _insert(*itr, *arr_vec[i]); + arr_vec[i].first = new Arrangement_2(m_traits); + _insert(*itr, *(arr_vec[i].first)); } Join_merge join_merge; - divide_and_conquer(0, arr_vec.size()-1, arr_vec, k, join_merge); + _build_sorted_vertices_vectors (arr_vec); + _divide_and_conquer(0, arr_vec.size()-1, arr_vec, k, join_merge); //the result arrangement is at index 0 - this->m_arr = arr_vec[0]; + this->m_arr = arr_vec[0].first; + delete arr_vec[0].second; } @@ -612,21 +616,23 @@ inline void join(InputIterator begin, Polygon_with_holes_2& pgn, unsigned int k=5) { - std::vector arr_vec (std::distance(begin, end) + 1); - arr_vec[0] = this->m_arr; + std::vector arr_vec (std::distance(begin, end) + 1); + arr_vec[0].first = this->m_arr; unsigned int i = 1; for(InputIterator itr = begin; itr!=end; ++itr, ++i) { - arr_vec[i] = new Arrangement_2(m_traits); - _insert(*itr, *arr_vec[i]); + arr_vec[i].first = new Arrangement_2(m_traits); + _insert(*itr, *(arr_vec[i].first)); } Join_merge join_merge; - divide_and_conquer(0, arr_vec.size()-1, arr_vec, k, join_merge); + _build_sorted_vertices_vectors (arr_vec); + _divide_and_conquer(0, arr_vec.size()-1, arr_vec, k, join_merge); //the result arrangement is at index 0 - this->m_arr = arr_vec[0]; + this->m_arr = arr_vec[0].first; + delete arr_vec[0].second; } template @@ -636,29 +642,31 @@ inline void join(InputIterator1 begin1, InputIterator2 end2, unsigned int k=5) { - std::vector arr_vec (std::distance(begin1, end1)+ - std::distance(begin2, end2)+1); + std::vector arr_vec (std::distance(begin1, end1)+ + std::distance(begin2, end2)+1); - arr_vec[0] = this->m_arr; + arr_vec[0].first = this->m_arr; unsigned int i = 1; for(InputIterator1 itr1 = begin1; itr1!=end1; ++itr1, ++i) { - arr_vec[i] = new Arrangement_2(m_traits); - _insert(*itr1, *arr_vec[i]); + arr_vec[i].first = new Arrangement_2(m_traits); + _insert(*itr1, *(arr_vec[i].first)); } for(InputIterator2 itr2 = begin2; itr2!=end2; ++itr2, ++i) { - arr_vec[i] = new Arrangement_2(m_traits); - _insert(*itr2, *arr_vec[i]); + arr_vec[i].first = new Arrangement_2(m_traits); + _insert(*itr2, *(arr_vec[i].first)); } Join_merge join_merge; - divide_and_conquer(0, arr_vec.size()-1, arr_vec, k, join_merge); + _build_sorted_vertices_vectors (arr_vec); + _divide_and_conquer(0, arr_vec.size()-1, arr_vec, k, join_merge); //the result arrangement is at index 0 - this->m_arr = arr_vec[0]; + this->m_arr = arr_vec[0].first; + delete arr_vec[0].second; this->remove_redundant_edges(); this->_reset_faces(); } @@ -682,22 +690,24 @@ inline void intersection(InputIterator begin, Polygon_2& pgn, unsigned int k) { - std::vector arr_vec (std::distance(begin, end) + 1); - arr_vec[0] = this->m_arr; + std::vector arr_vec (std::distance(begin, end) + 1); + arr_vec[0].first = this->m_arr; unsigned int i = 1; for(InputIterator itr = begin; itr!=end; ++itr, ++i) { CGAL_precondition(m_traits->is_valid_2_object()(*itr)); - arr_vec[i] = new Arrangement_2(m_traits); - _insert(*itr, *arr_vec[i]); + arr_vec[i].first = new Arrangement_2(m_traits); + _insert(*itr, *(arr_vec[i].first)); } Intersection_merge intersection_merge; - divide_and_conquer(0, arr_vec.size()-1, arr_vec, k, intersection_merge); + _build_sorted_vertices_vectors (arr_vec); + _divide_and_conquer(0, arr_vec.size()-1, arr_vec, k, intersection_merge); //the result arrangement is at index 0 - this->m_arr = arr_vec[0]; + this->m_arr = arr_vec[0].first; + delete arr_vec[0].second; } //intersect range of polygons with holes @@ -707,22 +717,24 @@ inline void intersection(InputIterator begin, Polygon_with_holes_2& pgn, unsigned int k) { - std::vector arr_vec (std::distance(begin, end) + 1); - arr_vec[0] = this->m_arr; + std::vector arr_vec (std::distance(begin, end) + 1); + arr_vec[0].first = this->m_arr; unsigned int i = 1; for(InputIterator itr = begin; itr!=end; ++itr, ++i) { CGAL_precondition(m_traits->is_valid_2_object()(*itr)); - arr_vec[i] = new Arrangement_2(m_traits); - _insert(*itr, *arr_vec[i]); + arr_vec[i].first = new Arrangement_2(m_traits); + _insert(*itr, *(arr_vec[i].first)); } Intersection_merge intersection_merge; - divide_and_conquer(0, arr_vec.size()-1, arr_vec, k, intersection_merge); + _build_sorted_vertices_vectors (arr_vec); + _divide_and_conquer(0, arr_vec.size()-1, arr_vec, k, intersection_merge); //the result arrangement is at index 0 - this->m_arr = arr_vec[0]; + this->m_arr = arr_vec[0].first; + delete arr_vec[0].second; } @@ -733,30 +745,32 @@ inline void intersection(InputIterator1 begin1, InputIterator2 end2, unsigned int k=5) { - std::vector arr_vec (std::distance(begin1, end1)+ - std::distance(begin2, end2)+1); - arr_vec[0] = this->m_arr; + std::vector arr_vec (std::distance(begin1, end1)+ + std::distance(begin2, end2)+1); + arr_vec[0].first = this->m_arr; unsigned int i = 1; for(InputIterator1 itr1 = begin1; itr1!=end1; ++itr1, ++i) { CGAL_precondition(m_traits->is_valid_2_object()(*itr1)); - arr_vec[i] = new Arrangement_2(m_traits); - _insert(*itr1, *arr_vec[i]); + arr_vec[i].first = new Arrangement_2(m_traits); + _insert(*itr1, *(arr_vec[i].first)); } for(InputIterator2 itr2 = begin2; itr2!=end2; ++itr2, ++i) { CGAL_precondition(m_traits->is_valid_2_object()(*itr2)); - arr_vec[i] = new Arrangement_2(m_traits); - _insert(*itr2, *arr_vec[i]); + arr_vec[i].first = new Arrangement_2(m_traits); + _insert(*itr2, *(arr_vec[i].first)); } Intersection_merge intersection_merge; - divide_and_conquer(0, arr_vec.size()-1, arr_vec, k, intersection_merge); + _build_sorted_vertices_vectors (arr_vec); + _divide_and_conquer(0, arr_vec.size()-1, arr_vec, k, intersection_merge); //the result arrangement is at index 0 - this->m_arr = arr_vec[0]; + this->m_arr = arr_vec[0].first; + delete arr_vec[0].second; this->remove_redundant_edges(); this->_reset_faces(); } @@ -782,22 +796,24 @@ inline void symmetric_difference(InputIterator begin, Polygon_2& pgn, unsigned int k=5) { - std::vector arr_vec (std::distance(begin, end) + 1); - arr_vec[0] = this->m_arr; + std::vector arr_vec (std::distance(begin, end) + 1); + arr_vec[0].first = this->m_arr; unsigned int i = 1; for(InputIterator itr = begin; itr!=end; ++itr, ++i) { CGAL_precondition(m_traits->is_valid_2_object()(*itr)); - arr_vec[i] = new Arrangement_2(m_traits); - _insert(*itr, *arr_vec[i]); + arr_vec[i].first = new Arrangement_2(m_traits); + _insert(*itr, *(arr_vec[i].first)); } Xor_merge xor_merge; - divide_and_conquer(0, arr_vec.size()-1, arr_vec, k, xor_merge); + _build_sorted_vertices_vectors (arr_vec); + _divide_and_conquer(0, arr_vec.size()-1, arr_vec, k, xor_merge); //the result arrangement is at index 0 - this->m_arr = arr_vec[0]; + this->m_arr = arr_vec[0].first; + delete arr_vec[0].second; } //intersect range of polygons with holes @@ -807,22 +823,24 @@ inline void symmetric_difference(InputIterator begin, Polygon_with_holes_2& pgn, unsigned int k=5) { - std::vector arr_vec (std::distance(begin, end) + 1); - arr_vec[0] = this->m_arr; + std::vector arr_vec (std::distance(begin, end) + 1); + arr_vec[0].first = this->m_arr; unsigned int i = 1; for(InputIterator itr = begin; itr!=end; ++itr, ++i) { CGAL_precondition(m_traits->is_valid_2_object()(*itr)); - arr_vec[i] = new Arrangement_2(m_traits); - _insert(*itr, *arr_vec[i]); + arr_vec[i].first = new Arrangement_2(m_traits); + _insert(*itr, *(arr_vec[i].first)); } Xor_merge xor_merge; - divide_and_conquer(0, arr_vec.size()-1, arr_vec, k, xor_merge); + _build_sorted_vertices_vectors (arr_vec); + _divide_and_conquer(0, arr_vec.size()-1, arr_vec, k, xor_merge); //the result arrangement is at index 0 - this->m_arr = arr_vec[0]; + this->m_arr = arr_vec[0].first; + delete arr_vec[0].second; } @@ -833,30 +851,32 @@ inline void symmetric_difference(InputIterator1 begin1, InputIterator2 end2, unsigned int k=5) { - std::vector arr_vec (std::distance(begin1, end1)+ - std::distance(begin2, end2)+1); - arr_vec[0] = this->m_arr; + std::vector arr_vec (std::distance(begin1, end1)+ + std::distance(begin2, end2)+1); + arr_vec[0].first = this->m_arr; unsigned int i = 1; for(InputIterator1 itr1 = begin1; itr1!=end1; ++itr1, ++i) { CGAL_precondition(m_traits->is_valid_2_object()(*itr1)); - arr_vec[i] = new Arrangement_2(m_traits); - _insert(*itr1, *arr_vec[i]); + arr_vec[i].first = new Arrangement_2(m_traits); + _insert(*itr1, *(arr_vec[i].first)); } for(InputIterator2 itr2 = begin2; itr2!=end2; ++itr2, ++i) { CGAL_precondition(m_traits->is_valid_2_object()(*itr2)); - arr_vec[i] = new Arrangement_2(m_traits); - _insert(*itr2, *arr_vec[i]); + arr_vec[i].first = new Arrangement_2(m_traits); + _insert(*itr2, *(arr_vec[i].first)); } Xor_merge xor_merge; - divide_and_conquer(0, arr_vec.size()-1, arr_vec, k, xor_merge); + _build_sorted_vertices_vectors (arr_vec); + _divide_and_conquer(0, arr_vec.size()-1, arr_vec, k, xor_merge); //the result arrangement is at index 0 - this->m_arr = arr_vec[0]; + this->m_arr = arr_vec[0].first; + delete arr_vec[0].second; this->remove_redundant_edges(); this->_reset_faces(); } @@ -895,13 +915,60 @@ void _remove_redundant_edges(Arrangement_2* arr) ++itr; } } + +class Less_vertex_handle +{ + typename Traits_2::Compare_xy_2 comp_xy; + +public: + + Less_vertex_handle (const typename Traits_2::Compare_xy_2& cmp) : + comp_xy (cmp) + {} + + bool operator() (Vertex_handle v1, Vertex_handle v2) const + { + return (comp_xy (v1->point(), v2->point()) == SMALLER); + } +}; + +void _build_sorted_vertices_vectors (std::vector& arr_vec) +{ + Less_vertex_handle comp (m_traits->compare_xy_2_object()); + Arrangement_2 *p_arr; + Vertex_iterator vit; + const unsigned int n = arr_vec.size(); + unsigned int i, j; + + for (i = 0; i < n; i++) + { + // Allocate a vector of handles to all vertices in the current + // arrangement. + p_arr = arr_vec[i].first; + arr_vec[i].second = new std::vector; + arr_vec[i].second->resize (p_arr->number_of_vertices()); + + for (j = 0, vit = p_arr->vertices_begin(); + vit != p_arr->vertices_end(); + j++, ++vit) + { + (*(arr_vec[i].second))[j] = vit; + } + + // Sort the vector. + std::sort (arr_vec[i].second->begin(), arr_vec[i].second->end(), + comp); + } + + return; +} template -void divide_and_conquer(unsigned int lower, - unsigned int upper, - std::vector& arr_vec, - unsigned int k, - Merge merge_func) +void _divide_and_conquer (unsigned int lower, + unsigned int upper, + std::vector& arr_vec, + unsigned int k, + Merge merge_func) { if((upper - lower) < k) { @@ -916,14 +983,14 @@ void divide_and_conquer(unsigned int lower, for(; i