Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r77468 - sandbox/gtl/boost/polygon
From: sydorchuk.andriy_at_[hidden]
Date: 2012-03-21 19:33:36


Author: asydorchuk
Date: 2012-03-21 19:33:36 EDT (Wed, 21 Mar 2012)
New Revision: 77468
URL: http://svn.boost.org/trac/boost/changeset/77468

Log:
Refactoring voronoi builder. Updating comments.
Text files modified:
   sandbox/gtl/boost/polygon/voronoi_builder.hpp | 1044 +++++++++++++++++++--------------------
   sandbox/gtl/boost/polygon/voronoi_utils.hpp | 2
   2 files changed, 510 insertions(+), 536 deletions(-)

Modified: sandbox/gtl/boost/polygon/voronoi_builder.hpp
==============================================================================
--- sandbox/gtl/boost/polygon/voronoi_builder.hpp (original)
+++ sandbox/gtl/boost/polygon/voronoi_builder.hpp 2012-03-21 19:33:36 EDT (Wed, 21 Mar 2012)
@@ -20,550 +20,524 @@
 
 namespace boost {
 namespace polygon {
- // GENERAL INFO:
- // The sweepline algorithm implementation to compute voronoi diagram of
- // input data sets of points and segments (Fortune's algorithm).
- // Complexity - O(N*logN), memory usage - O(N), where N is the total
- // number of input objects.
- //
- // ALGORITHM OVERVIEW:
- // Sweepline is a vertical line that sweeps from the left to the right
- // along the x-axis positive direction. Each of the input objects is
- // wrapped into the site event. Each event is characterized by its
- // coordinates: the point site event is defined by the point itself,
- // the segment site event is defined by its start-point. At any moment we
- // consider only the sites that lie to the left of the sweepline. Beach
- // line is a curve formed by the parabolic arcs and line segments, that
- // consists of the points equidistant from the sweepline and the nearest
- // site to the left of the sweepline. The part of the generated diagram to
- // the left of the beach line remains unchanged until the end of the
- // algorithm. Each node in the beach line corresponds to some voronoi edge.
- // Each node is represented by two sites. Two neighboring nodes has a
- // common site. Circle event appears at the rightmost point of the circle
- // tangent to the three sites that correspond to the two consecutive
- // bisectors. At each step algorithm goes over the leftmost event
- // and processes it appropriately. This is made until there are no events.
- // At the end output data structure holds the voronoi diagram of the
- // initial set of objects.
- //
- // DATA STRUCTURES OVERVIEW:
- // Each point creates one site event. Each segment creates three site
- // events: two for its endpoints and one for the segment itself (this is
- // made to simplify output construction). All the site events are
- // constructed and sorted at the algorithm initialization step.
- // Priority queue is used to dynamically hold circle events. At each step
- // of the algorithm the leftmost event is retrieved by comparing the
- // current site event and the topmost element from the circle event queue.
- // Standard map container was chosen to hold state of the beach line. The
- // keys of the map correspond to the neighboring bisectors and values to
- // the corresponding edges from the output data structure. Specially
- // defined comparison functor is used to make the beach line correctly
- // ordered. Epsilon-based and high-precision approaches are used to guarantee
- // efficiency and robustness of the algorithm implementation.
- template <typename T,
- typename CTT = detail::voronoi_ctype_traits<T>,
- typename VP = detail::voronoi_predicates<CTT> >
- class voronoi_builder {
- public:
- typedef typename CTT::int_type int_type;
- typedef typename CTT::fpt_type fpt_type;
+// GENERAL INFO:
+// The sweepline algorithm implementation to compute voronoi diagram of
+// points and non-intersecting segments (except endpoints).
+// Complexity - O(N*logN), memory usage - O(N), where N is the total number
+// of input geometries. Input geometries should have integer coordinate type.
+//
+// IMPLEMENTATION DETAILS:
+// Each input point creates one site event. Each input segment creates three
+// site events: two for its endpoints and one for the segment itself (this is
+// made to simplify output construction). All the site events are constructed
+// and sorted at the algorithm initialization step. Priority queue is used to
+// dynamically hold circle events. At each step of the algorithm execution the
+// leftmost event is retrieved by comparing the current site event and the
+// topmost element from the circle event queue. STL map (red-black tree)
+// container was chosen to hold state of the beach line. The keys of the map
+// correspond to the neighboring sites that form a bisector and values to the
+// corresponding voronoi edge in the output data structure.
+template <typename T,
+ typename CTT = detail::voronoi_ctype_traits<T>,
+ typename VP = detail::voronoi_predicates<CTT> >
+class voronoi_builder {
+public:
+ typedef typename CTT::int_type int_type;
+ typedef typename CTT::fpt_type fpt_type;
+
+ voronoi_builder() {}
+
+ void insert_point(const int_type& x, const int_type& y) {
+ site_events_.push_back(site_event_type(x, y));
+ }
+
+ template <typename PointType>
+ void insert_point(const PointType& point) {
+ insert_point(point.x(), point.y());
+ }
+
+ template <typename PointIterator>
+ void insert_points(PointIterator first_point, PointIterator last_point) {
+ // Create a site event from each input point.
+ for (PointIterator it = first_point; it != last_point; ++it) {
+ insert_point(*it);
+ }
+ }
+
+ // Each segment creates three site events that correspond to:
+ // 1) the start point of the segment;
+ // 2) the end point of the segment;
+ // 3) the segment itself defined by its start point.
+ void insert_segment(const int_type& x1, const int_type& y1,
+ const int_type& x2, const int_type& y2) {
+ point_type p1(x1, y1);
+ point_type p2(x2, y2);
+ site_events_.push_back(site_event_type(p1));
+ site_events_.push_back(site_event_type(p2));
+ if (point_comparison_(p1, p2)) {
+ site_events_.push_back(site_event_type(p1, p2));
+ } else {
+ site_events_.push_back(site_event_type(p2, p1));
+ }
+ }
+
+ template <typename PointType>
+ void insert_segment(const PointType& point1, const PointType& point2) {
+ insert_segment(point1.x(), point1.y(), point2.x(), point2.y());
+ }
+
+ template <typename SegmentType>
+ void insert_segment(const SegmentType& segment) {
+ insert_segment(segment.low(), segment.high());
+ }
+
+ template <typename SegmentIterator>
+ void insert_segments(
+ SegmentIterator first_segment, SegmentIterator last_segment) {
+ for (SegmentIterator it = first_segment; it != last_segment; ++it) {
+ insert_segment(*it);
+ }
+ }
+
+ template <typename PointIterator, typename SegmentIterator>
+ void insert_sites(
+ PointIterator first_point, PointIterator last_point,
+ SegmentIterator first_segment, SegmentIterator last_segment) {
+ insert_points(first_point, last_point);
+ insert_segments(first_segment, last_segment);
+ }
+
+ // Run sweepline algorithm and fill output datastucture.
+ template <typename OUTPUT>
+ void construct(OUTPUT *output) {
+ // Init structures.
+ output->builder()->reserve(site_events_.size());
+ init_sites_queue();
+ if (!circle_events_.empty())
+ circle_events_.clear();
+ while (!end_points_.empty())
+ end_points_.pop();
+ init_beach_line(output);
+
+ // The algorithm stops when there are no events to process.
+ event_comparison_predicate event_comparison;
+ while (!circle_events_.empty() ||
+ !(site_event_iterator_ == site_events_.end())) {
+ if (circle_events_.empty()) {
+ process_site_event(output);
+ } else if (site_event_iterator_ == site_events_.end()) {
+ process_circle_event(output);
+ } else {
+ if (event_comparison(*site_event_iterator_,
+ circle_events_.top().first)) {
+ process_site_event(output);
+ } else {
+ process_circle_event(output);
+ }
+ }
+ while (!circle_events_.empty() &&
+ !circle_events_.top().first.is_active()) {
+ circle_events_.pop();
+ }
+ }
+ beach_line_.clear();
+
+ // Finish construction.
+ output->builder()->build();
+ }
+
+ void clear() {
+ site_events_.clear();
+ if (!beach_line_.empty())
+ beach_line_.clear();
+ if (!circle_events_.empty())
+ circle_events_.clear();
+ while (!end_points_.empty())
+ end_points_.pop();
+ }
+
+private:
+ typedef detail::point_2d<int_type> point_type;
+ typedef detail::site_event<int_type> site_event_type;
+ typedef typename std::vector<site_event_type>::const_iterator
+ site_event_iterator_type;
+ typedef detail::circle_event<fpt_type> circle_event_type;
+ typedef typename VP::template point_comparison_predicate<point_type>
+ point_comparison_predicate;
+ typedef typename VP::
+ template event_comparison_predicate<site_event_type, circle_event_type>
+ event_comparison_predicate;
+ typedef typename VP::
+ template circle_formation_predicate<site_event_type, circle_event_type>
+ circle_formation_predicate_type;
+ typedef void edge_type;
+ typedef detail::beach_line_node_key<site_event_type> key_type;
+ typedef detail::beach_line_node_data<edge_type, circle_event_type>
+ value_type;
+ typedef typename VP::template node_comparison_predicate<key_type>
+ node_comparer_type;
+ typedef std::map< key_type, value_type, node_comparer_type > beach_line_type;
+ typedef typename beach_line_type::iterator beach_line_iterator;
+ typedef std::pair<circle_event_type, beach_line_iterator> event_type;
+ typedef struct {
+ bool operator()(const event_type &lhs, const event_type &rhs) const {
+ return predicate(rhs.first, lhs.first);
+ }
+ event_comparison_predicate predicate;
+ } event_comparison_type;
+ typedef detail::ordered_queue<event_type, event_comparison_type>
+ circle_event_queue_type;
+ typedef std::pair<point_type, beach_line_iterator> end_point_type;
+
+ void init_sites_queue() {
+ // Sort site events.
+ sort(site_events_.begin(), site_events_.end(),
+ event_comparison_predicate());
+
+ // Remove duplicates.
+ site_events_.erase(unique(
+ site_events_.begin(), site_events_.end()), site_events_.end());
+
+ // Index sites.
+ for (size_t cur = 0; cur < site_events_.size(); ++cur)
+ site_events_[cur].index(cur);
+
+ // Init site iterator.
+ site_event_iterator_ = site_events_.begin();
+ }
+
+ template <typename OUTPUT>
+ void init_beach_line(OUTPUT *output) {
+ if (!beach_line_.empty())
+ beach_line_.clear();
+ if (site_events_.empty())
+ return;
+ if (site_events_.size() == 1) {
+ // Handle single site event case.
+ output->builder()->process_single_site(site_events_[0]);
+ ++site_event_iterator_;
+ } else {
+ int skip = 0;
+
+ while(site_event_iterator_ != site_events_.end() &&
+ VP::is_vertical(site_event_iterator_->point0(),
+ site_events_.begin()->point0()) &&
+ VP::is_vertical(*site_event_iterator_)) {
+ ++site_event_iterator_;
+ ++skip;
+ }
+
+ if (skip == 1) {
+ // Init beach line with the first two sites.
+ init_beach_line_default(output);
+ } else {
+ // Init beach line with collinear vertical sites.
+ init_beach_line_collinear_sites(output);
+ }
+ }
+ }
+
+ // Init beach line with the two first sites.
+ // The first site is always a point.
+ template <typename OUTPUT>
+ void init_beach_line_default(OUTPUT *output) {
+ // Get the first and the second site event.
+ site_event_iterator_type it_first = site_events_.begin();
+ site_event_iterator_type it_second = site_events_.begin();
+ ++it_second;
+ insert_new_arc(
+ *it_first, *it_first, *it_second, beach_line_.end(), output);
+ // The second site was already processed. Move the iterator.
+ ++site_event_iterator_;
+ }
+
+ // Init beach line with collinear sites.
+ template <typename OUTPUT>
+ void init_beach_line_collinear_sites(OUTPUT *output) {
+ site_event_iterator_type it_first = site_events_.begin();
+ site_event_iterator_type it_second = site_events_.begin();
+ ++it_second;
+ while (it_second != site_event_iterator_) {
+ // Create a new beach line node.
+ key_type new_node(*it_first, *it_second);
+
+ // Update the output.
+ edge_type *edge =
+ output->builder()->insert_new_edge(*it_first, *it_second).first;
+
+ // Insert a new bisector into the beach line.
+ beach_line_.insert(beach_line_.end(),
+ std::pair<key_type, value_type>(new_node, value_type(edge)));
+
+ // Update iterators.
+ ++it_first;
+ ++it_second;
+ }
+ }
+
+ void deactivate_circle_event(value_type &value) {
+ if (value.circle_event()) {
+ value.circle_event()->deactivate();
+ value.circle_event(NULL);
+ }
+ }
+
+ template <typename OUTPUT>
+ void process_site_event(OUTPUT *output) {
+ // Get next site event to process.
+ site_event_type site_event = *site_event_iterator_;
+
+ // Move site iterator.
+ site_event_iterator_type last = site_event_iterator_ + 1;
+
+ // If a new site is an end point of some segment,
+ // remove temporary nodes from the beach line data structure.
+ if (!site_event.is_segment()) {
+ while (!end_points_.empty() &&
+ end_points_.top().first == site_event.point0()) {
+ beach_line_iterator b_it = end_points_.top().second;
+ end_points_.pop();
+ beach_line_.erase(b_it);
+ }
+ } else {
+ while (last != site_events_.end() &&
+ last->is_segment() && last->point0() == site_event.point0())
+ ++last;
+ }
+
+ // Find the node in the binary search tree with left arc
+ // lying above the new site point.
+ key_type new_key(*site_event_iterator_);
+ beach_line_iterator right_it = beach_line_.lower_bound(new_key);
+
+ for (; site_event_iterator_ != last; ++site_event_iterator_) {
+ site_event = *site_event_iterator_;
+ beach_line_iterator left_it = right_it;
+
+ // Do further processing depending on the above node position.
+ // For any two neighboring nodes the second site of the first node
+ // is the same as the first site of the second node.
+ if (right_it == beach_line_.end()) {
+ // The above arc corresponds to the second arc of the last node.
+ // Move the iterator to the last node.
+ --left_it;
 
- voronoi_builder() {}
+ // Get the second site of the last node
+ const site_event_type &site_arc = left_it->first.right_site();
 
- void insert_point(const int_type& x, const int_type& y) {
- site_events_.push_back(site_event_type(x, y));
- }
-
- template <typename PointType>
- void insert_point(const PointType& point) {
- insert_point(point.x(), point.y());
- }
-
- template <typename PointIterator>
- void insert_points(PointIterator first_point, PointIterator last_point) {
- // Create a site event from each input point.
- for (PointIterator it = first_point; it != last_point; ++it) {
- insert_point(*it);
- }
- }
-
- void insert_segment(const int_type& x1, const int_type& y1,
- const int_type& x2, const int_type& y2) {
- // Each segment creates three segment sites:
- // 1) the start-point of the segment;
- // 2) the endpoint of the segment;
- // 3) the segment itself.
- point_type p1(x1, y1);
- point_type p2(x2, y2);
- site_events_.push_back(site_event_type(p1));
- site_events_.push_back(site_event_type(p2));
- if (point_comparison_(p1, p2)) {
- site_events_.push_back(site_event_type(p1, p2));
- } else {
- site_events_.push_back(site_event_type(p2, p1));
- }
- }
-
- template <typename PointType>
- void insert_segment(const PointType& point1, const PointType& point2) {
- insert_segment(point1.x(), point1.y(), point2.x(), point2.y());
- }
-
- template <typename SegmentType>
- void insert_segment(const SegmentType& segment) {
- insert_segment(segment.low(), segment.high());
- }
-
- template <typename SegmentIterator>
- void insert_segments(SegmentIterator first_segment, SegmentIterator last_segment) {
- for (SegmentIterator it = first_segment; it != last_segment; ++it) {
- insert_segment(*it);
- }
- }
-
- template <typename PointIterator, typename SegmentIterator>
- void insert_sites(PointIterator first_point, PointIterator last_point,
- SegmentIterator first_segment, SegmentIterator last_segment) {
- insert_points(first_point, last_point);
- insert_segments(first_segment, last_segment);
- }
-
- // Run the sweepline algorithm.
- template <typename OUTPUT>
- void construct(OUTPUT *output) {
- // Init structures.
- output->builder()->reserve(site_events_.size());
- init_sites_queue();
- if (!circle_events_.empty())
- circle_events_.clear();
- while (!end_points_.empty())
- end_points_.pop();
- init_beach_line(output);
-
- // The algorithm stops when there are no events to process.
- // The circle events with the same rightmost point as the next
- // site event go first.
- event_comparison_predicate event_comparison;
- while (!circle_events_.empty() ||
- !(site_event_iterator_ == site_events_.end())) {
- if (circle_events_.empty()) {
- process_site_event(output);
- } else if (site_event_iterator_ == site_events_.end()) {
- process_circle_event(output);
- } else {
- if (event_comparison(*site_event_iterator_, circle_events_.top().first)) {
- process_site_event(output);
- } else {
- process_circle_event(output);
- }
- }
- while (!circle_events_.empty() && !circle_events_.top().first.is_active()) {
- circle_events_.pop();
- }
- }
- beach_line_.clear();
-
- // Finish construction.
- output->builder()->build();
- }
-
- void clear() {
- site_events_.clear();
- if (!beach_line_.empty())
- beach_line_.clear();
- if (!circle_events_.empty())
- circle_events_.clear();
- while (!end_points_.empty())
- end_points_.pop();
- }
-
- private:
- typedef detail::point_2d<int_type> point_type;
- typedef detail::site_event<int_type> site_event_type;
- typedef typename std::vector<site_event_type>::const_iterator
- site_event_iterator_type;
- typedef detail::circle_event<fpt_type> circle_event_type;
- typedef typename VP::template point_comparison_predicate<point_type>
- point_comparison_predicate;
- typedef typename VP::
- template event_comparison_predicate<site_event_type, circle_event_type>
- event_comparison_predicate;
- typedef typename VP::
- template circle_formation_predicate<site_event_type, circle_event_type>
- circle_formation_predicate_type;
- typedef void edge_type;
- typedef detail::beach_line_node_key<site_event_type> key_type;
- typedef detail::beach_line_node_data<edge_type, circle_event_type> value_type;
- typedef typename VP::
- template node_comparison_predicate<key_type> node_comparer_type;
- typedef std::map< key_type, value_type, node_comparer_type > beach_line_type;
- typedef typename beach_line_type::iterator beach_line_iterator;
- typedef std::pair<circle_event_type, beach_line_iterator> event_type;
- typedef struct {
- bool operator()(const event_type &lhs, const event_type &rhs) const {
- return predicate(rhs.first, lhs.first);
- }
- event_comparison_predicate predicate;
- } event_comparison_type;
- typedef detail::ordered_queue<event_type, event_comparison_type>
- circle_event_queue_type;
- typedef std::pair<point_type, beach_line_iterator> end_point_type;
-
- // Create site events.
- // There will be one site event for each input point and three site
- // events for each input segment (both endpoints of a segment and the
- // segment itself).
- void init_sites_queue() {
- // Sort site events.
- sort(site_events_.begin(), site_events_.end(), event_comparison_predicate());
-
- // Remove duplicates.
- site_events_.erase(unique(site_events_.begin(),
- site_events_.end()), site_events_.end());
-
- // Index sites.
- for (size_t cur = 0; cur < site_events_.size(); ++cur)
- site_events_[cur].index(cur);
-
- // Init site iterator.
- site_event_iterator_ = site_events_.begin();
- }
-
- template <typename OUTPUT>
- void init_beach_line(OUTPUT *output) {
- if (!beach_line_.empty())
- beach_line_.clear();
- if (site_events_.empty())
- return;
- if (site_events_.size() == 1) {
- // Handle one input site case.
- output->builder()->process_single_site(site_events_[0]);
- ++site_event_iterator_;
- } else {
- int skip = 0;
-
- // Count the number of the sites to init the beach line.
- while(site_event_iterator_ != site_events_.end() &&
- VP::is_vertical(site_event_iterator_->point0(),
- site_events_.begin()->point0()) &&
- VP::is_vertical(*site_event_iterator_)) {
- ++site_event_iterator_;
- ++skip;
- }
-
- if (skip == 1) {
- // Init the beach line with the two first sites.
- init_beach_line_default(output);
- } else {
- // Init the beach line with the sites situated on the same
- // vertical line. This could be a set of point and vertical
- // segment sites.
- init_beach_line_collinear_sites(output);
- }
- }
- }
-
- // Init the beach line with the two first sites.
- // The first site is always a point.
- template <typename OUTPUT>
- void init_beach_line_default(OUTPUT *output) {
- // Get the first and the second site events.
- site_event_iterator_type it_first = site_events_.begin();
- site_event_iterator_type it_second = site_events_.begin();
- ++it_second;
-
- // Update the beach line.
- insert_new_arc(*it_first, *it_first, *it_second,
- beach_line_.end(), output);
-
- // The second site has been already processed.
- // Move the site's iterator.
- ++site_event_iterator_;
- }
-
- // Insert bisectors for all collinear initial sites.
- template <typename OUTPUT>
- void init_beach_line_collinear_sites(OUTPUT *output) {
- site_event_iterator_type it_first = site_events_.begin();
- site_event_iterator_type it_second = site_events_.begin();
- ++it_second;
- while (it_second != site_event_iterator_) {
- // Create a new beach line node.
- key_type new_node(*it_first, *it_second);
-
- // Update the output.
- edge_type *edge = output->builder()->insert_new_edge(*it_first, *it_second).first;
-
- // Insert a new bisector into the beach line.
- beach_line_.insert(beach_line_.end(),
- std::pair<key_type, value_type>(new_node, value_type(edge)));
-
- // Update iterators.
- ++it_first;
- ++it_second;
- }
- }
-
- void deactivate_circle_event(value_type &value) {
- if (value.circle_event()) {
- value.circle_event()->deactivate();
- value.circle_event(NULL);
- }
- }
-
- template <typename OUTPUT>
- void process_site_event(OUTPUT *output) {
- // Get the site event to process.
- site_event_type site_event = *site_event_iterator_;
-
- // Move site iterator.
- site_event_iterator_type last = site_event_iterator_ + 1;
-
- // If a new site is an end point of some segment,
- // remove temporary nodes from the beach line data structure.
- if (!site_event.is_segment()) {
- while (!end_points_.empty() &&
- end_points_.top().first == site_event.point0()) {
- beach_line_iterator b_it = end_points_.top().second;
- end_points_.pop();
- beach_line_.erase(b_it);
- }
- } else {
- while (last != site_events_.end() &&
- last->is_segment() && last->point0() == site_event.point0())
- ++last;
- }
-
- // Find the node in the binary search tree with left arc
- // lying above the new site point.
- key_type new_key(*site_event_iterator_);
- beach_line_iterator right_it = beach_line_.lower_bound(new_key);
-
- for (; site_event_iterator_ != last; ++site_event_iterator_) {
- site_event = *site_event_iterator_;
- beach_line_iterator left_it = right_it;
-
- // Do further processing depending on the above node position.
- // For any two neighboring nodes the second site of the first node
- // is the same as the first site of the second node.
- if (right_it == beach_line_.end()) {
- // The above arc corresponds to the second arc of the last node.
- // Move the iterator to the last node.
- --left_it;
-
- // Get the second site of the last node
- const site_event_type &site_arc = left_it->first.right_site();
-
- // Insert new nodes into the beach line. Update the output.
- right_it = insert_new_arc(site_arc, site_arc, site_event, right_it, output);
-
- // Add a candidate circle to the circle event queue.
- // There could be only one new circle event formed by
- // a new bisector and the one on the left.
- activate_circle_event(left_it->first.left_site(),
- left_it->first.right_site(),
- site_event, right_it);
- } else if (right_it == beach_line_.begin()) {
- // The above arc corresponds to the first site of the first node.
- const site_event_type &site_arc = right_it->first.left_site();
-
- // Insert new nodes into the beach line. Update the output.
- left_it = insert_new_arc(site_arc, site_arc, site_event, right_it, output);
-
- // If the site event is a segment, update its direction.
- if (site_event.is_segment()) {
- site_event.inverse();
- }
-
- // Add a candidate circle to the circle event queue.
- // There could be only one new circle event formed by
- // a new bisector and the one on the right.
- activate_circle_event(site_event, right_it->first.left_site(),
- right_it->first.right_site(), right_it);
- right_it = left_it;
- } else {
- // The above arc corresponds neither to the first,
- // nor to the last site in the beach line.
- const site_event_type &site_arc2 = right_it->first.left_site();
- const site_event_type &site3 = right_it->first.right_site();
-
- // Remove the candidate circle from the event queue.
- deactivate_circle_event(right_it->second);
- --left_it;
- const site_event_type &site_arc1 = left_it->first.right_site();
- const site_event_type &site1 = left_it->first.left_site();
-
- // Insert new nodes into the beach line. Update the output.
- beach_line_iterator new_node_it =
- insert_new_arc(site_arc1, site_arc2, site_event, right_it, output);
-
- // Add candidate circles to the circle event queue.
- // There could be up to two circle events formed by
- // a new bisector and the one on the left or right.
- activate_circle_event(site1, site_arc1, site_event,
- new_node_it);
-
- // If the site event is a segment, update its direction.
- if (site_event.is_segment()) {
- site_event.inverse();
- }
- activate_circle_event(site_event, site_arc2, site3,
- right_it);
- right_it = new_node_it;
- }
- }
- }
+ // Insert new nodes into the beach line. Update the output.
+ right_it = insert_new_arc(
+ site_arc, site_arc, site_event, right_it, output);
 
- // In general case circle event is made of the three consecutive sites
- // that form two bisector nodes in the beach line data structure.
- // Let circle event sites be A, B, C, two bisectors that define
- // circle event are (A, B), (B, C). During circle event processing
- // we remove (A, B), (B, C) and insert (A, C). As beach line comparison
- // works correctly only if one of the nodes is a new one we remove
- // (B, C) bisector and change (A, B) bisector to the (A, C). That's
- // why we use const_cast there and take all the responsibility that
- // map data structure keeps correct ordering.
- template <typename OUTPUT>
- void process_circle_event(OUTPUT *output) {
- // Get the topmost circle event.
- const event_type &e = circle_events_.top();
- const circle_event_type &circle_event = e.first;
- beach_line_iterator it_first = e.second;
- beach_line_iterator it_last = it_first;
-
- // Get the C site.
- site_event_type site3 = it_first->first.right_site();
-
- // Get the half-edge corresponding to the second bisector - (B, C).
- edge_type *bisector2 = it_first->second.edge();
-
- // Get the half-edge corresponding to the first bisector - (A, B).
- --it_first;
- edge_type *bisector1 = it_first->second.edge();
-
- // Get the A site.
- site_event_type site1 = it_first->first.left_site();
-
- if (!site1.is_segment() && site3.is_segment() &&
- site3.point1(true) == site1.point0()) {
- site3.inverse();
- }
-
- // Change the (A, B) bisector node to the (A, C) bisector node.
- const_cast<key_type &>(it_first->first).right_site(site3);
-
- // Insert the new bisector into the beach line.
- it_first->second.edge(output->builder()->insert_new_edge(
- site1, site3, circle_event, bisector1, bisector2).first);
-
- // Remove the (B, C) bisector node from the beach line.
- beach_line_.erase(it_last);
- it_last = it_first;
-
- // Pop the topmost circle event from the event queue.
- circle_events_.pop();
-
- // Check new triplets formed by the neighboring arcs
- // to the left for potential circle events.
- if (it_first != beach_line_.begin()) {
- deactivate_circle_event(it_first->second);
- --it_first;
- const site_event_type &site_l1 = it_first->first.left_site();
- activate_circle_event(site_l1, site1, site3, it_last);
- }
-
- // Check the new triplet formed by the neighboring arcs
- // to the right for potential circle events.
- ++it_last;
- if (it_last != beach_line_.end()) {
- deactivate_circle_event(it_last->second);
- const site_event_type &site_r1 = it_last->first.right_site();
- activate_circle_event(site1, site3, site_r1, it_last);
- }
- }
+ // Add a candidate circle to the circle event queue.
+ // There could be only one new circle event formed by
+ // a new bisector and the one on the left.
+ activate_circle_event(left_it->first.left_site(),
+ left_it->first.right_site(),
+ site_event, right_it);
+ } else if (right_it == beach_line_.begin()) {
+ // The above arc corresponds to the first site of the first node.
+ const site_event_type &site_arc = right_it->first.left_site();
 
         // Insert new nodes into the beach line. Update the output.
- template <typename OUTPUT>
- beach_line_iterator insert_new_arc(const site_event_type &site_arc1,
- const site_event_type &site_arc2,
- const site_event_type &site_event,
- beach_line_iterator position,
- OUTPUT *output) {
- // Create two new bisectors with opposite directions.
- key_type new_left_node(site_arc1, site_event);
- key_type new_right_node(site_event, site_arc2);
-
- // Set correct orientation for the first site of the second node.
- if (site_event.is_segment()) {
- new_right_node.left_site().inverse();
- }
-
- // Update the output.
- std::pair<edge_type*, edge_type*> edges =
- output->builder()->insert_new_edge(site_arc2, site_event);
- position = beach_line_.insert(position,
- typename beach_line_type::value_type(new_right_node, value_type(edges.second)));
-
- if (site_event.is_segment()) {
- // Update the beach line with temporary bisector, that will
- // disappear after processing site event going through the
- // endpoint of the segment site.
- key_type new_node(site_event, site_event);
- new_node.right_site().inverse();
- position = beach_line_.insert(position,
- typename beach_line_type::value_type(new_node, value_type(NULL)));
-
- // Update the data structure that holds temporary bisectors.
- end_points_.push(std::make_pair(site_event.point1(), position));
- }
+ left_it = insert_new_arc(
+ site_arc, site_arc, site_event, right_it, output);
 
- position = beach_line_.insert(position,
- typename beach_line_type::value_type(new_left_node, value_type(edges.first)));
+ // If the site event is a segment, update its direction.
+ if (site_event.is_segment()) {
+ site_event.inverse();
+ }
+
+ // Add a candidate circle to the circle event queue.
+ // There could be only one new circle event formed by
+ // a new bisector and the one on the right.
+ activate_circle_event(site_event, right_it->first.left_site(),
+ right_it->first.right_site(), right_it);
+ right_it = left_it;
+ } else {
+ // The above arc corresponds neither to the first,
+ // nor to the last site in the beach line.
+ const site_event_type &site_arc2 = right_it->first.left_site();
+ const site_event_type &site3 = right_it->first.right_site();
+
+ // Remove the candidate circle from the event queue.
+ deactivate_circle_event(right_it->second);
+ --left_it;
+ const site_event_type &site_arc1 = left_it->first.right_site();
+ const site_event_type &site1 = left_it->first.left_site();
 
- return position;
- }
-
- // Add a new circle event to the event queue.
- // bisector_node corresponds to the (site2, site3) bisector.
- void activate_circle_event(const site_event_type &site1,
- const site_event_type &site2,
- const site_event_type &site3,
- beach_line_iterator bisector_node) {
- circle_event_type c_event;
- // Check if the three input sites create a circle event.
- if (circle_formation_predicate_(site1, site2, site3, c_event)) {
- // Add the new circle event to the circle events queue.
- // Update bisector's circle event iterator to point to the
- // new circle event in the circle event queue.
- event_type &e = circle_events_.push(
- std::pair<circle_event_type, beach_line_iterator>(c_event, bisector_node));
- bisector_node->second.circle_event(&e.first);
- }
- }
+ // Insert new nodes into the beach line. Update the output.
+ beach_line_iterator new_node_it =
+ insert_new_arc(site_arc1, site_arc2, site_event, right_it, output);
 
- private:
- point_comparison_predicate point_comparison_;
- struct end_point_comparison {
- bool operator() (const end_point_type &end1, const end_point_type &end2) const {
- return point_comparison(end2.first, end1.first);
- }
- point_comparison_predicate point_comparison;
- };
-
- std::vector<site_event_type> site_events_;
- site_event_iterator_type site_event_iterator_;
- std::priority_queue< end_point_type, std::vector<end_point_type>,
- end_point_comparison > end_points_;
- circle_event_queue_type circle_events_;
- beach_line_type beach_line_;
- circle_formation_predicate_type circle_formation_predicate_;
-
- //Disallow copy constructor and operator=
- voronoi_builder(const voronoi_builder&);
- void operator=(const voronoi_builder&);
- };
+ // Add candidate circles to the circle event queue.
+ // There could be up to two circle events formed by
+ // a new bisector and the one on the left or right.
+ activate_circle_event(site1, site_arc1, site_event, new_node_it);
+
+ // If the site event is a segment, update its direction.
+ if (site_event.is_segment()) {
+ site_event.inverse();
+ }
+ activate_circle_event(site_event, site_arc2, site3, right_it);
+ right_it = new_node_it;
+ }
+ }
+ }
+
+ // In general case circle event is made of the three consecutive sites
+ // that form two bisectors in the beach line data structure.
+ // Let circle event sites be A, B, C, two bisectors that define
+ // circle event are (A, B), (B, C). During circle event processing
+ // we remove (A, B), (B, C) and insert (A, C). As beach line comparison
+ // works correctly only if one of the nodes is a new one we remove
+ // (B, C) bisector and change (A, B) bisector to the (A, C). That's
+ // why we use const_cast there and take all the responsibility that
+ // map data structure keeps correct ordering.
+ template <typename OUTPUT>
+ void process_circle_event(OUTPUT *output) {
+ // Get the topmost circle event.
+ const event_type &e = circle_events_.top();
+ const circle_event_type &circle_event = e.first;
+ beach_line_iterator it_first = e.second;
+ beach_line_iterator it_last = it_first;
+
+ // Get the C site.
+ site_event_type site3 = it_first->first.right_site();
+
+ // Get the half-edge corresponding to the second bisector - (B, C).
+ edge_type *bisector2 = it_first->second.edge();
+
+ // Get the half-edge corresponding to the first bisector - (A, B).
+ --it_first;
+ edge_type *bisector1 = it_first->second.edge();
+
+ // Get the A site.
+ site_event_type site1 = it_first->first.left_site();
+
+ if (!site1.is_segment() && site3.is_segment() &&
+ site3.point1(true) == site1.point0()) {
+ site3.inverse();
+ }
+
+ // Change the (A, B) bisector node to the (A, C) bisector node.
+ const_cast<key_type &>(it_first->first).right_site(site3);
+
+ // Insert the new bisector into the beach line.
+ it_first->second.edge(output->builder()->insert_new_edge(
+ site1, site3, circle_event, bisector1, bisector2).first);
+
+ // Remove the (B, C) bisector node from the beach line.
+ beach_line_.erase(it_last);
+ it_last = it_first;
+
+ // Pop the topmost circle event from the event queue.
+ circle_events_.pop();
+
+ // Check new triplets formed by the neighboring arcs
+ // to the left for potential circle events.
+ if (it_first != beach_line_.begin()) {
+ deactivate_circle_event(it_first->second);
+ --it_first;
+ const site_event_type &site_l1 = it_first->first.left_site();
+ activate_circle_event(site_l1, site1, site3, it_last);
+ }
+
+ // Check the new triplet formed by the neighboring arcs
+ // to the right for potential circle events.
+ ++it_last;
+ if (it_last != beach_line_.end()) {
+ deactivate_circle_event(it_last->second);
+ const site_event_type &site_r1 = it_last->first.right_site();
+ activate_circle_event(site1, site3, site_r1, it_last);
+ }
+ }
+
+ // Insert new nodes into the beach line. Update the output.
+ template <typename OUTPUT>
+ beach_line_iterator insert_new_arc(
+ const site_event_type &site_arc1, const site_event_type &site_arc2,
+ const site_event_type &site_event, beach_line_iterator position,
+ OUTPUT *output) {
+ // Create two new bisectors with opposite directions.
+ key_type new_left_node(site_arc1, site_event);
+ key_type new_right_node(site_event, site_arc2);
+
+ // Set correct orientation for the first site of the second node.
+ if (site_event.is_segment()) {
+ new_right_node.left_site().inverse();
+ }
+
+ // Update the output.
+ std::pair<edge_type*, edge_type*> edges =
+ output->builder()->insert_new_edge(site_arc2, site_event);
+ position = beach_line_.insert(position,
+ typename beach_line_type::value_type(
+ new_right_node, value_type(edges.second)));
+
+ if (site_event.is_segment()) {
+ // Update the beach line with temporary bisector, that will
+ // disappear after processing site event going through the
+ // endpoint of the segment site.
+ key_type new_node(site_event, site_event);
+ new_node.right_site().inverse();
+ position = beach_line_.insert(position,
+ typename beach_line_type::value_type(new_node, value_type(NULL)));
+
+ // Update the data structure that holds temporary bisectors.
+ end_points_.push(std::make_pair(site_event.point1(), position));
+ }
+
+ position = beach_line_.insert(position,
+ typename beach_line_type::value_type(
+ new_left_node, value_type(edges.first)));
+
+ return position;
+ }
+
+ // Add a new circle event to the event queue.
+ // bisector_node corresponds to the (site2, site3) bisector.
+ void activate_circle_event(const site_event_type &site1,
+ const site_event_type &site2,
+ const site_event_type &site3,
+ beach_line_iterator bisector_node) {
+ circle_event_type c_event;
+ // Check if the three input sites create a circle event.
+ if (circle_formation_predicate_(site1, site2, site3, c_event)) {
+ // Add the new circle event to the circle events queue.
+ // Update bisector's circle event iterator to point to the
+ // new circle event in the circle event queue.
+ event_type &e = circle_events_.push(
+ std::pair<circle_event_type, beach_line_iterator>(
+ c_event, bisector_node));
+ bisector_node->second.circle_event(&e.first);
+ }
+ }
+
+private:
+ point_comparison_predicate point_comparison_;
+ struct end_point_comparison {
+ bool operator() (const end_point_type &end1,
+ const end_point_type &end2) const {
+ return point_comparison(end2.first, end1.first);
+ }
+ point_comparison_predicate point_comparison;
+ };
+
+ std::vector<site_event_type> site_events_;
+ site_event_iterator_type site_event_iterator_;
+ std::priority_queue< end_point_type, std::vector<end_point_type>,
+ end_point_comparison > end_points_;
+ circle_event_queue_type circle_events_;
+ beach_line_type beach_line_;
+ circle_formation_predicate_type circle_formation_predicate_;
+
+ //Disallow copy constructor and operator=
+ voronoi_builder(const voronoi_builder&);
+ void operator=(const voronoi_builder&);
+};
 
- typedef voronoi_builder<detail::int32> default_voronoi_builder;
+typedef voronoi_builder<detail::int32> default_voronoi_builder;
 } // polygon
 } // boost
 

Modified: sandbox/gtl/boost/polygon/voronoi_utils.hpp
==============================================================================
--- sandbox/gtl/boost/polygon/voronoi_utils.hpp (original)
+++ sandbox/gtl/boost/polygon/voronoi_utils.hpp 2012-03-21 19:33:36 EDT (Wed, 21 Mar 2012)
@@ -58,7 +58,7 @@
     x_max_ = 0;
   }
 
- bool contains(coordinate_type x, coordinate_type y) {
+ bool contains(coordinate_type x, coordinate_type y) const {
     return x > x_min_ && x < x_max_ && y > y_min_ && y < y_max_;
   }
 


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk