Improved the divide-and-conquer algorithm for aggregated operations,

so that we use merge sort instead of O(n log(n)) sort. (with Baruch)
This commit is contained in:
Ron Wein 2006-02-19 13:10:16 +00:00
parent c5492b6644
commit 403cf9d75c
6 changed files with 650 additions and 177 deletions

View File

@ -12,7 +12,7 @@
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
// $Id$ $Date$
//
//
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
@ -21,7 +21,7 @@
#define GSP_AGG_OP_H
#include <CGAL/Boolean_set_operations_2/Gps_agg_meta_traits.h>
#include <CGAL/Sweep_line_2.h>
#include <CGAL/Boolean_set_operations_2/Gps_agg_op_sweep.h>
#include <CGAL/Sweep_line_2/Arr_construction_curve.h>
#include <CGAL/Sweep_line_2/Arr_construction_event.h>
@ -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<Arrangement_2 *,
std::vector<Vertex_handle> *> Arr_entry;
typedef Arr_construction_curve<Meta_traits> Subcurve;
typedef Arr_construction_event<Meta_traits,
Subcurve,
Halfedge_handle> Event;
Halfedge_handle> Base_event;
typedef Indexed_event<Base_event> Event;
typedef Gps_agg_op_visitor<Meta_traits,
Arrangement_2,
Event,
Subcurve> Visitor;
typedef Sweep_line_2<Meta_traits,
Visitor,
Subcurve,
Event> Sweep_line_2;
typedef Gps_agg_op_sweep_line_2<Arrangement_2,
Meta_traits,
Visitor,
Subcurve,
Event> Sweep_line_2;
typedef Unique_hash_map<Halfedge_handle,
unsigned int> 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<Vertex_handle>& 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<Arrangement_2*>& arr_vec)
std::vector<Arr_entry>& arr_vec)
{
std::list<Meta_X_monotone_curve_2> 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<Arrangement_2> Insert_meta_traits;
// typedef typename Insert_meta_traits::Curve_data Curve_data;
// typedef Arr_construction_curve<Insert_meta_traits> Subcurve;
// typedef Arr_construction_event<Insert_meta_traits,
// Subcurve,
// Halfedge_handle> Event;
// typedef typename Insert_meta_traits::X_monotone_curve_2 Ex_X_monotone_curve_2;
// typedef Arr_construction_visitor<Insert_meta_traits,
// Arrangement_2,
// Event,
// Subcurve> Insertion_visitor;
// typedef Basic_sweep_line_2<Insert_meta_traits,
// Insertion_visitor,
// Subcurve,
// Event> Basic_sweep_line_2;
//
//
// Arrangement_2* new_arr = new Arrangement_2();
// std::vector<Ex_X_monotone_curve_2> 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;

View File

@ -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 <baruchzu@post.tau.ac.il>
// Ron Wein <wein@post.tau.ac.il>
#ifndef GSP_AGG_OP_SWEEP_H
#define GSP_AGG_OP_SWEEP_H
#include <CGAL/Sweep_line_2.h>
#include <CGAL/Unique_hash_map.h>
CGAL_BEGIN_NAMESPACE
template <class Arrangement_,
class MetaTraits_,
class SweepVisitor,
class CurveWrap,
class SweepEvent,
typename Allocator = CGAL_ALLOCATOR(int) >
class Gps_agg_op_sweep_line_2 :
public Sweep_line_2<MetaTraits_,
SweepVisitor,
CurveWrap,
SweepEvent,
Allocator>
{
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<Arrangement_2 *,
std::vector<Vertex_handle> *> Arr_entry;
typedef Sweep_line_2<Traits_2,
SweepVisitor,
CurveWrap,
SweepEvent,
Allocator> 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<Subcurve*> 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<class CurveInputIterator>
void sweep (CurveInputIterator curves_begin,
CurveInputIterator curves_end,
unsigned int lower,
unsigned int upper,
unsigned int jump,
std::vector<Arr_entry>& arr_vec)
{
CGAL_assertion (this->m_queue->empty() &&
this->m_statusLine.size() == 0);
typedef Unique_hash_map<Vertex_handle, Event *> 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

View File

@ -16,6 +16,7 @@
//
//
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
// Ron Wein <wein@post.tau.ac.il>
#ifndef GSP_AGG_OP_VISITOR
#define GSP_AGG_OP_VISITOR
@ -26,7 +27,7 @@
CGAL_BEGIN_NAMESPACE
template<class Traits, class Arrangement_, class Event,class Subcurve>
class Gps_agg_op_visitor :
class Gps_agg_op_base_visitor :
public Arr_construction_visitor<Traits,Arrangement_,Event,Subcurve>
{
protected:
@ -38,11 +39,6 @@ class Gps_agg_op_visitor :
Event,
Subcurve> Base;
typedef Gps_agg_op_visitor<Traits,
Arrangement,
Event,
Subcurve> 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<Halfedge_handle, unsigned int> 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 BaseEvent_>
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 Traits, class Arrangement_, class Event, class Subcurve>
class Gps_agg_op_visitor :
public Gps_agg_op_base_visitor<Traits, Arrangement_, Event, Subcurve>
{
protected:
typedef Arrangement_ Arrangement;
typedef Gps_agg_op_base_visitor<Traits,
Arrangement,
Event,
Subcurve> 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<Vertex_handle> *m_vertices_vec; // The vertices, sorted in
// ascending order.
public:
Gps_agg_op_visitor (Arrangement *arr,
typename Base::Edges_hash* hash,
std::vector<Vertex_handle>* 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<Event*>(this->current_event());
Event *last_event = reinterpret_cast<Event*>((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<Event*>((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<Event*>(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

View File

@ -12,7 +12,7 @@
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
// $Id$ $Date$
//
//
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
@ -29,86 +29,113 @@
CGAL_BEGIN_NAMESPACE
template <class Arrangement>
template <class Arrangement_>
class Join_merge
{
typedef Arrangement_ Arrangement_2;
typedef typename Arrangement_2::Vertex_handle Vertex_handle;
typedef std::pair<Arrangement_2 *,
std::vector<Vertex_handle> *> Arr_entry;
public:
void operator()(unsigned int i,
unsigned int j,
unsigned int jump,
std::vector<Arrangement*>& arr_vec)
std::vector<Arr_entry>& arr_vec)
{
if(i==j)
return;
typename Arrangement::Traits_2* tr = arr_vec[i]->get_traits();
Arrangement* res = new Arrangement(tr);
Gps_agg_op<Arrangement, Gps_bfs_join_visitor<Arrangement> >
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<Vertex_handle> *verts = new std::vector<Vertex_handle>;
Gps_agg_op<Arrangement_2, Gps_bfs_join_visitor<Arrangement_2> >
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 <class Arrangement>
template <class Arrangement_>
class Intersection_merge
{
typedef Arrangement_ Arrangement_2;
typedef typename Arrangement_2::Vertex_handle Vertex_handle;
typedef std::pair<Arrangement_2 *,
std::vector<Vertex_handle> *> Arr_entry;
public:
void operator()(unsigned int i,
unsigned int j,
unsigned int jump,
std::vector<Arrangement*>& arr_vec)
std::vector<Arr_entry>& arr_vec)
{
if(i==j)
return;
typename Arrangement::Traits_2* tr = arr_vec[i]->get_traits();
Arrangement* res = new Arrangement(tr);
Gps_agg_op<Arrangement, Gps_bfs_intersection_visitor<Arrangement> >
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<Vertex_handle> *verts = new std::vector<Vertex_handle>;
Gps_agg_op<Arrangement_2, Gps_bfs_intersection_visitor<Arrangement_2> >
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 <class Arrangement>
template <class Arrangement_>
class Xor_merge
{
typedef Arrangement_ Arrangement_2;
typedef typename Arrangement_2::Vertex_handle Vertex_handle;
typedef std::pair<Arrangement_2 *,
std::vector<Vertex_handle> *> Arr_entry;
public:
void operator()(unsigned int i,
unsigned int j,
unsigned int jump,
std::vector<Arrangement*>& arr_vec)
std::vector<Arr_entry>& arr_vec)
{
if(i==j)
return;
typename Arrangement::Traits_2* tr = arr_vec[i]->get_traits();
Arrangement* res = new Arrangement(tr);
Gps_agg_op<Arrangement, Gps_bfs_xor_visitor<Arrangement> >
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<Vertex_handle> *verts = new std::vector<Vertex_handle>;
Gps_agg_op<Arrangement_2, Gps_bfs_xor_visitor<Arrangement_2> >
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;
}
};

View File

@ -62,15 +62,16 @@ class Gps_polygon_simplifier
Subcurve,
Halfedge_handle> Event;
typedef Gps_agg_op_visitor<Meta_traits,
Arrangement_2,
Event,
Subcurve> Visitor;
typedef Gps_agg_op_base_visitor<Meta_traits,
Arrangement_2,
Event,
Subcurve> Visitor;
typedef Sweep_line_2<Meta_traits,
Visitor,
Visitor,
Subcurve,
Event> Sweep_line_2;
typedef Unique_hash_map<Halfedge_handle,
unsigned int> Edges_hash;

View File

@ -12,7 +12,7 @@
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
// $Id$ $Date$
//
//
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
@ -91,6 +91,8 @@ private:
typedef typename Arrangement_2::Halfedge_around_vertex_const_circulator
Halfedge_around_vertex_const_circulator;
typedef std::pair<Arrangement_2 *,
std::vector<Vertex_handle> *> Arr_entry;
typedef Arr_walk_along_line_point_location<Arrangement_2> Walk_pl;
protected:
@ -587,21 +589,23 @@ inline void join(InputIterator begin,
Polygon_2& pgn,
unsigned int k=5)
{
std::vector<Arrangement_2*> arr_vec (std::distance(begin, end) + 1);
std::vector<Arr_entry> 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<Arrangement_2> 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<Arrangement_2*> arr_vec (std::distance(begin, end) + 1);
arr_vec[0] = this->m_arr;
std::vector<Arr_entry> 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<Arrangement_2> 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 <class InputIterator1, class InputIterator2>
@ -636,29 +642,31 @@ inline void join(InputIterator1 begin1,
InputIterator2 end2,
unsigned int k=5)
{
std::vector<Arrangement_2*> arr_vec (std::distance(begin1, end1)+
std::distance(begin2, end2)+1);
std::vector<Arr_entry> 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<Arrangement_2> 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<Arrangement_2*> arr_vec (std::distance(begin, end) + 1);
arr_vec[0] = this->m_arr;
std::vector<Arr_entry> 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<Arrangement_2> 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<Arrangement_2*> arr_vec (std::distance(begin, end) + 1);
arr_vec[0] = this->m_arr;
std::vector<Arr_entry> 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<Arrangement_2> 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<Arrangement_2*> arr_vec (std::distance(begin1, end1)+
std::distance(begin2, end2)+1);
arr_vec[0] = this->m_arr;
std::vector<Arr_entry> 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<Arrangement_2> 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<Arrangement_2*> arr_vec (std::distance(begin, end) + 1);
arr_vec[0] = this->m_arr;
std::vector<Arr_entry> 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<Arrangement_2> 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<Arrangement_2*> arr_vec (std::distance(begin, end) + 1);
arr_vec[0] = this->m_arr;
std::vector<Arr_entry> 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<Arrangement_2> 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<Arrangement_2*> arr_vec (std::distance(begin1, end1)+
std::distance(begin2, end2)+1);
arr_vec[0] = this->m_arr;
std::vector<Arr_entry> 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<Arrangement_2> 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_entry>& 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<Vertex_handle>;
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 <class Merge>
void divide_and_conquer(unsigned int lower,
unsigned int upper,
std::vector<Arrangement_2*>& arr_vec,
unsigned int k,
Merge merge_func)
void _divide_and_conquer (unsigned int lower,
unsigned int upper,
std::vector<Arr_entry>& 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<k-1; ++i, curr_lower += sub_size )
{
divide_and_conquer(curr_lower,
curr_lower + sub_size-1,
arr_vec,
k,
merge_func);
_divide_and_conquer (curr_lower,
curr_lower + sub_size-1,
arr_vec,
k,
merge_func);
}
divide_and_conquer(curr_lower, upper,arr_vec, k, merge_func);
merge_func(lower, curr_lower, sub_size ,arr_vec);
_divide_and_conquer (curr_lower, upper,arr_vec, k, merge_func);
merge_func (lower, curr_lower, sub_size ,arr_vec);
return;
}