Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r63178 - in sandbox/SOC/2010/sweepline: boost/sweepline libs/sweepline/test
From: sydorchuk.andriy_at_[hidden]
Date: 2010-06-20 19:10:18


Author: asydorchuk
Date: 2010-06-20 19:10:16 EDT (Sun, 20 Jun 2010)
New Revision: 63178
URL: http://svn.boost.org/trac/boost/changeset/63178

Log:
Fixed voronoi_output generation.
Added unit tests for simple voronoi diagrams.
Changed cicle events processing algorithm (doesn't use node comparison).
Made refactoring.
Added:
   sandbox/SOC/2010/sweepline/boost/sweepline/voronoi_formation.hpp (contents, props changed)
   sandbox/SOC/2010/sweepline/libs/sweepline/test/node_comparer_test.cpp (contents, props changed)
   sandbox/SOC/2010/sweepline/libs/sweepline/test/voronoi_formation_test.cpp (contents, props changed)
Removed:
   sandbox/SOC/2010/sweepline/boost/sweepline/beach_line.hpp
   sandbox/SOC/2010/sweepline/boost/sweepline/voronoi_builder.hpp
   sandbox/SOC/2010/sweepline/libs/sweepline/test/beach_line_test.cpp
   sandbox/SOC/2010/sweepline/libs/sweepline/test/voronoi_builder_test.cpp
Text files modified:
   sandbox/SOC/2010/sweepline/boost/sweepline/event_queue.hpp | 6 ++-
   sandbox/SOC/2010/sweepline/boost/sweepline/event_types.hpp | 37 +++++++++----------
   sandbox/SOC/2010/sweepline/boost/sweepline/voronoi_output.hpp | 74 ++++++++++++++++++++++++++-------------
   sandbox/SOC/2010/sweepline/libs/sweepline/test/Jamfile.v2 | 3 +
   sandbox/SOC/2010/sweepline/libs/sweepline/test/event_queue_test.cpp | 3 -
   sandbox/SOC/2010/sweepline/libs/sweepline/test/event_types_test.cpp | 2
   6 files changed, 75 insertions(+), 50 deletions(-)

Deleted: sandbox/SOC/2010/sweepline/boost/sweepline/beach_line.hpp
==============================================================================
--- sandbox/SOC/2010/sweepline/boost/sweepline/beach_line.hpp 2010-06-20 19:10:16 EDT (Sun, 20 Jun 2010)
+++ (empty file)
@@ -1,456 +0,0 @@
-// Boost sweepline/beach_line.hpp header file
-
-// Copyright Andrii Sydorchuk 2010.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-// See http://www.boost.org for updates, documentation, and revision history.
-
-#include <map>
-#include <vector>
-#include <cmath>
-
-#ifndef BOOST_SWEEPLINE_BEACH_LINE
-#define BOOST_SWEEPLINE_BEACH_LINE
-
-namespace boost {
-namespace sweepline {
-
- // Represents bisector made by two arcs that correspond to the left and
- // right sites. Arc is defined as curve with points equidistant from the
- // site and from the sweepline.
- // Let sweepline sweep from left to right and it's current coordinate
- // be x0, site coordinates be (x1, y1). In this case equation of the arc
- // may be written as: (x-x0)^2 = (x-x1)^2 + (y-y1)^2, or
- // x = ((y - y1)^2 + x1^2 - x0^2) / (2*(x1 - x0)).
- // In general case two arcs will create two different bisectors. That's why
- // the order of arcs is important to define unique bisector.
- template <typename Point2D>
- struct beach_line_node {
- public:
- typedef typename Point2D Point2D;
- typedef typename Point2D::coordinate_type coordinate_type;
- typedef typename Point2D::site_event_type site_event_type;
- typedef typename Point2D::circle_event_type circle_event_type;
-
- beach_line_node() {}
-
- // Constructs degenerate bisector, used to search arc that is above
- // given site. The input to the constructor is the site event point.
- explicit beach_line_node(const site_event_type &new_point) {
- left_site_ = new_point;
- right_site_ = new_point;
- }
-
- // Constructs new bisector. The input to the constructor is two sites
- // that create bisector. The order of sites is important.
- beach_line_node(const site_event_type &left_point,
- const site_event_type &right_point) {
- left_site_ = left_point;
- right_site_ = right_point;
- }
-
- // Returns the left site of the bisector.
- const site_event_type &get_left_site() const {
- return left_site_;
- }
-
- // Returns the right site of the bisector.
- const site_event_type &get_right_site() const {
- return right_site_;
- }
-
- // Returns x coordinate of the rightmost site.
- coordinate_type get_sweepline_coord() const {
- return std::max(left_site_.x(), right_site_.x());
- }
-
- // Returns rightmost site.
- const site_event_type& get_new_site() const {
- if (left_site_.x() > right_site_.x())
- return left_site_;
- return right_site_;
- }
-
- // Returns true if horizontal line going through new site intersects
- // right arc at first, else returns false. Used during nodes
- // comparison.
- // Let x0 be sweepline coordinate, left site coordinates be (x1, y1),
- // right site coordinates be (x2, y2). Equations of the arcs will be:
- // x1(y) = ((y - y1)^2 + x1^2 - x0^2) / (2*(x1 - x0));
- // x2(y) = ((y - y2)^2 + x2^2 - x0^2) / (2*(x2 - x0)).
- // Horizontal line going throught site (x*, y*) intersects second arc
- // at first if x2(y*) > x1(y*) or:
- // (x2-x0)*(x1-x0)*(x1-x2) + (x2-x0)*(y*-y1)^2 < (x1-x0)*(y*-y2)^2
- bool less(const site_event_type &new_site) const {
- coordinate_type sweepline_coord = new_site.x();
- coordinate_type new_node_coord = new_site.y();
- coordinate_type a1 = left_site_.x() - sweepline_coord;
- coordinate_type a2 = right_site_.x() - sweepline_coord;
- coordinate_type b1 = new_node_coord - left_site_.y();
- coordinate_type b2 = new_node_coord - right_site_.y();
- coordinate_type c = left_site_.x() - right_site_.x();
- return a1 * a2 * c + a2 * b1 * b1 < a1 * b2 * b2;
- }
-
- private:
- site_event_type left_site_;
- site_event_type right_site_;
- };
-
- // Represents edge data sturcture (bisector segment), which is
- // associated with beach line node key in the binary search tree.
- template <typename Edge>
- struct beach_line_node_data {
- beach_line_node_data(Edge &new_edge) : edge(new_edge) {}
-
- Edge &edge;
- };
-
- template <typename BeachLineNode>
- struct node_comparer {
- public:
- typedef typename BeachLineNode::coordinate_type coordinate_type;
-
- // Compares nodes in the balanced binary search tree. Nodes are
- // compared based on the y coordinates of the arcs intersection points.
- // Nodes with lesser y coordinate of the intersection point go first.
- bool operator() (const BeachLineNode &node1,
- const BeachLineNode &node2) const {
- // Get x coordinate of the righmost site from both nodes.
- coordinate_type node1_line = node1.get_sweepline_coord();
- coordinate_type node2_line = node2.get_sweepline_coord();
-
- // Both nodes are situated on the same vertical line.
- if (node1_line == node2_line) {
- // Let A be the new site event point, and B the site that
- // creates arc above A. In this case two new nodes are being
- // inserted: (A,B) and (B,A). As intersection points for the
- // first node and for the second are the same we need to
- // compare them based on some another characteristic.
- // That's why we assume that node (C, D) goes before node
- // (D, C), only if D lies on the sweepline.
- if (node1.get_left_site() == node2.get_right_site() &&
- node1.get_right_site() == node2.get_left_site())
- return node1.get_right_site().x() == node1_line;
-
- // Used when we are searching for the bisector during
- // circle events processing. Guarantees correct comparison.
- if (node1.get_left_site() == node2.get_left_site() &&
- node1.get_right_site() == node2.get_right_site())
- return false;
-
- return node1.get_left_site().y() <=
- node2.get_left_site().y();
- }
- else if (node1_line < node2_line)
- return node1.less(node2.get_new_site());
- else
- return !node2.less(node1.get_new_site());
- }
- };
-
- // Beach line data structure. Sweepline sweeps from left to right.
- template <typename Key,
- typename Value,
- typename NodeComparer,
- typename EventQueue,
- typename Output>
- class beach_line {
- public:
- typedef typename Key::Point2D Point2D;
- typedef typename Key::coordinate_type coordinate_type;
- typedef typename Key::site_event_type site_event_type;
- typedef typename Key::circle_event_type circle_event_type;
-
- typedef typename Output::edge_type edge_type;
-
- typedef typename std::map< Key, Value, node_comparer<Key> >::const_iterator beach_line_iterator;
- typedef typename std::pair< beach_line_iterator, bool > beach_line_pair;
-
- // Functor to process events from the event queue.
- struct event_processor {
- explicit event_processor(beach_line &b_line)
- : beach_line_(b_line) {}
-
- void operator()(const site_event_type &site_event) {
- beach_line_.process_site_event(site_event);
- }
-
- void operator()(const circle_event_type &circle_event) {
- beach_line_.process_circle_event(circle_event);
- }
-
- beach_line &beach_line_;
- };
-
- beach_line() : event_processor_(*this) {
- }
-
- // Init beach line before sweepline run.
- // In case of a few first sites situated on the same
- // vertical line, we init beach line with all of them.
- // In other case just use the first two sites for the initialization.
- void init(const std::vector<Point2D> &sites) {
- std::sort(sites.begin(), sites.end());
- int skip = 0;
-
- if (sites.size() == 1) {
- skip = 1;
- } else {
- std::vector<Point2D>::const_iterator it = sites.begin();
- while(it != sites.end() && it->x() == sites.begin()->x()) {
- it++;
- skip++;
- }
-
- if (num == 1) {
- // Init beach line with two sites.
- init_beach_line(*sites.begin(), *it);
- } else {
- // Init beach line with sites situated on the same vertical line.
- init_beach_line(sites.begin(), it);
- }
- }
- // Init event queue with the rest of the sites.
- event_queue_.init(sites, skip);
- output_.init(sites.size());
- }
-
- void reset() {
- event_queue_.reset();
- beach_line_.clear();
- output_.clear();
- }
-
- void run_sweepline() {
- // Algorithm stops when there are no events in the queue.
- while (!event_queue_.empty()) {
- event_queue_.process_top_event(event_processor_);
- event_queue_.pop();
- }
- }
-
- void process_site_event(const site_event_type &site_event) {
- // Find the node in the binary search tree with left arc
- // lying above the new site point.
- Key new_key(site_event);
- beach_line_iterator it = beach_line_.lower_bound(new_key);
-
- site_event_type site_arc;
- if (it == beach_line_.end()) {
- it--;
- site_arc = it->first.get_right_site();
-
- // Add candidate circle to the event queue.
- activate_circle_event(it->first.get_left_site(),
- it->first.get_right_site(),
- site_event);
- } else if (it == beach_line_.begin()) {
- site_arc = it->first.get_left_site();
-
- // Add candidate circle to the event queue.
- activate_circle_event(site_event,
- it->first.get_left_site(),
- it->first.get_right_site());
- } else {
- site_arc = it->first.get_left_site();
- const site_event_type &site2 = it->first.get_left_site();
- const site_event_type &site3 = it->first.get_right_site();
- it--;
- const site_event_type &site1 = it->first.get_right_site();
-
- // Remove candidate circle from the event queue.
- deactivate_circle_event(site1, site2, site3);
-
- // Add candidate circles to the event queue.
- activate_circle_event(site1, site2, site_event);
- activate_circle_event(site_event, site2, site3);
- }
-
- // Create two new nodes.
- Key new_left_node(site_arc, site_event);
- Key new_right_node(site_event, site_arc);
- int site_index1 = site_arc.get_site_index();
- int site_index2 = site_event.get_site_index();
-
- // Insert two new nodes into the binary search tree.
- // Update output.
- edge_type &edge = output_.insert_new_edge(site_arc, site_event);
- beach_line_.insert(std::pair<Key, Value>(new_left_node, Value(edge)));
- beach_line_.insert(std::pair<Key, Value>(new_right_node, Value(edge)));
- }
-
- void process_circle_event(const circle_event_type &circle_event) {
- // Find the node that corresponds to the given circle event.
- Key new_key(circle_event.get_bisector_left_site(),
- circle_event.get_bisector_right_site());
- beach_line_iterator it_first = beach_line_.find(new_key);
- beach_line_iterator it_last = it_first;
-
- // Get the second and the third sites that create given circle event.
- site_event_type site2 = it_first->first.get_left_site();
- site_event_type site3 = it_first->first.get_right_site();
-
- // Get second bisector;
- Value bisector2 = it_first->second;
-
- // Get first bisector;
- it_first--;
- Value bisector1 = it_first->second;
-
- // Get the first site that creates given circle event.
- site_event_type site1 = it_first->first.get_left_site();
-
- // Delete nodes that correspond to the (1st and 2d points) and
- // (2d and 3d points).
- it_last++;
- beach_line_.erase(it_first, it_last);
-
- // Insert new node that corresponds to the (1st and 3d points).
- // Update output.
- Key new_node(site1, site3);
- beach_line_pair it_pair = beach_line_.insert(std::pair<Key, Value>(
- new_node,
- output_.insert_new_edge(site1, site2, site3,
- circle_event,
- bisector1.edge, bisector2.edge)));
- it_first = it_pair.first;
- it_last = it_first;
-
- // Check the new triplets formed by the neighboring arcs
- // for potential circle events. Check left.
- if (it_first != beach_line_.begin()) {
- it_first--;
- const site_event_type &site_l1 = it_first->first.get_left_site();
- deactivate_circle_event(site_l1, site1, site2);
- if (it_first != beach_line_.begin()) {
- it_first--;
- const site_event_type &site_l2 = it_first->first.get_left_site();
- activate_circle_event(site_l2, site_l1, site1);
- }
- }
-
- // Check the new triplets formed by the neighboring arcs
- // for potential circle events. Check right.
- it_last++;
- if (it_last != beach_line_.end()) {
- const site_event_type &site_r1 = it_last->first.get_right_site();
- deactivate_circle_event(site2, site3, site_r1);
- it_last++;
- if (it_last != beach_line_.end()) {
- it_last++;
- const site_event_type &site_r2 = it_last->first.get_right_site();
- activate_circle_event(site3, site_r1, site_r2);
- }
- }
- }
-
- protected:
- void init_beach_line(typename std::vector<Point2D>::const_iterator it_begin,
- typename std::vector<Point2D>::const_iterator it_end) {
- typename std::vector<Point2D>::const_iterator it_first = it_begin;
- typename std::vector<Point2D>::const_iterator it_second = it_begin;
- it_second++;
- int cur_site = 0;
- while (it_second != it_end) {
- site_event_type site1 = make_site_event(it_first->x, it_first->y, cur_site);
- site_event_type site2 = make_site_event(it_second->x, it_second->y, cur_site+1);
-
- // Create new beach line node.
- beach_line_node new_node(site1, site2);
-
- // Update output.
- edge_type &edge = output_.insert_new_edge(site1, site2);
-
- // Insert new node into the binary search tree.
- beach_line_.insert(std::pair<Key, Value>(new_node, Value(edge)));
-
- // Update iterators.
- it_first++;
- it_second++;
- cur_site++;
- }
- }
-
- void init_beach_line(const Point2D &first_point,
- const Point2D &second_point) {
- site_event_type site1 = make_site_event(first_point.x(), first_point.y(), 0);
- site_event_type site2 = make_site_event(second_point.x(), second_point.y(), 1);
-
- // Create two new beach line nodes.
- beach_line_node new_left_node(site1, site2);
- beach_line_node new_second_node(site2, site1);
-
- // Update output.
- edge_type &edge = output_.insert_new_edge(site1, site2);
-
- // Insert two new nodes into the binary search tree.
- beach_line_.insert(std::pair<Key, Value>(new_left_node, Value(edge)));
- beach_line_.insert(std::pair<Key, Value>(new_right_node, Value(egge)));
- }
-
- // Create circle event from the given three points.
- bool create_circle_event(const site_event_type &site1,
- const site_event_type &site2,
- const site_event_type &site3,
- circle_event_type &c_event) const {
- coordinate_type a = (site1.x() - site2.x())*
- (site2.y() - site3.y())-
- (site1.y() - site2.y())*
- (site2.x() - site3.x());
- // Check if bisectors intersect.
- if (a <= static_cast<coordinate_type>(0))
- return false;
- coordinate_type b1 = (site1.x() - site2.x())*
- (site1.x() + site2.x())+
- (site1.y() - site2.y())*
- (site1.y() + site2.y());
- coordinate_type b2 = (site2.x() - site3.x())*
- (site2.x() + site3.x())+
- (site2.y() - site3.y())*
- (site2.y() + site3.y());
- coordinate_type c_x = (b1*(site2.y() - site3.y()) -
- b2*(site1.y() - site2.y())) / a *
- static_cast<coordinate_type>(0.5);
- coordinate_type c_y = (b2*(site1.x() - site2.x()) -
- b1*(site2.x() - site3.x())) / a *
- static_cast<coordinate_type>(0.5);
- coordinate_type sqr_radius = (c_x-site1.x())*(c_x-site1.x()) +
- (c_y-site1.y())*(c_y-site1.y());
- // Create new circle event;
- c_event = make_circle_event(c_x, c_y, sqr_radius);
- c_event.set_bisector(site2, site3);
- return true;
- }
-
- // Add new circle event to the event queue.
- void activate_circle_event(const site_event_type &site1,
- const site_event_type &site2,
- const site_event_type &site3) {
- circle_event_type c_event;
- if (create_circle_event(site1, site2, site3, c_event))
- event_queue_.push(c_event);
- }
-
- // Remove circle event from the event queue.
- void deactivate_circle_event(const site_event_type &point1,
- const site_event_type &point2,
- const site_event_type &point3) {
- circle_event_type c_event;
- if (create_circle_event(point1, point2, point3, c_event))
- event_queue_.deactivate_event(c_event);
- }
-
- private:
- EventQueue event_queue_;
- event_processor event_processor_;
- std::map< Key, Value, NodeComparer > beach_line_;
- Output output_;
- };
-
-} // sweepline
-} // boost
-
-#endif
\ No newline at end of file

Modified: sandbox/SOC/2010/sweepline/boost/sweepline/event_queue.hpp
==============================================================================
--- sandbox/SOC/2010/sweepline/boost/sweepline/event_queue.hpp (original)
+++ sandbox/SOC/2010/sweepline/boost/sweepline/event_queue.hpp 2010-06-20 19:10:16 EDT (Sun, 20 Jun 2010)
@@ -34,6 +34,8 @@
             site_events_iterator_ = site_events_.begin();
         }
 
+ // Init event queue with sites, starting from the element with
+ // skip index. Vector of sites should be sorted.
         void init(const std::vector<Point2D> &sites, int skip) {
             site_events_.clear();
             site_events_.resize(sites.size() - skip);
@@ -50,16 +52,16 @@
             site_events_iterator_ = site_events_.begin();
             while (!circle_events_.empty())
                 circle_events_.pop();
+ while (!deactivated_events_.empty())
+ deactivated_events_.pop();
         }
 
         bool empty() {
             if (site_events_iterator_ != site_events_.end())
                 return false;
-
             remove_not_active_events();
             if (!circle_events_.empty())
                 return false;
-
             return true;
         }
 

Modified: sandbox/SOC/2010/sweepline/boost/sweepline/event_types.hpp
==============================================================================
--- sandbox/SOC/2010/sweepline/boost/sweepline/event_types.hpp (original)
+++ sandbox/SOC/2010/sweepline/boost/sweepline/event_types.hpp 2010-06-20 19:10:16 EDT (Sun, 20 Jun 2010)
@@ -19,8 +19,11 @@
     template <typename T>
     struct circle_event;
 
+ template <typename T>
+ class voronoi_formation;
+
     // Point in 2D space data structure. Comparators defined in this
- // datascturcture actually define sweepline movement direction.
+ // data structure actually define sweepline movement direction.
     template <typename T>
     struct point_2d {
     public:
@@ -44,9 +47,8 @@
         }
 
         // This comparator actually defines sweepline movement direction.
- // Sweepline will move in the horizontal direction:
- // from left to right or from right to left.
         bool operator<(const point_2d &point) const {
+ // Sweepline sweeps from left to right.
             if (this->x_ != point.x_)
                 return this->x_ < point.x_;
             return this->y_ < point.y_;
@@ -90,7 +92,9 @@
         return point_2d<T>(x,y);
     }
 
- // Site event type. Occurs when sweepline sweeps over one of the initial sites.
+ // Site event type.
+ // Occurs when sweepline sweeps over one of the initial sites.
+ // Contains index of a site below the other sorted sites.
     template <typename T>
     struct site_event {
     public:
@@ -158,10 +162,14 @@
     // way voronoi diagram implementation may be used with rational arithmetic.
     // Let circle center coordinates be (x, y), squared radius be r.
     // Bottom point of the voronoi circle will be defined as (x + sqrt(r), y).
+ // Contains reference to the second bisector node (ordered from left to
+ // right in the beach line) that creates given circle event.
     template <typename T>
     struct circle_event {
     public:
         typedef T coordinate_type;
+ typedef typename voronoi_formation<T>::beach_line_iterator
+ beach_line_iterator;
 
         circle_event() {}
 
@@ -254,8 +262,7 @@
         int compare(const site_event<T> &s_event) const {
             if (s_event.x() < center_.x())
                 return 1;
- T sqr_dif_x = (s_event.x() - center_.x()) *
- (s_event.x() - center_.x());
+ T sqr_dif_x = (s_event.x() - center_.x()) * (s_event.x() - center_.x());
             if (sqr_dif_x == sqr_radius_) {
                 if (center_.y() == s_event.y())
                     return 0;
@@ -280,25 +287,17 @@
             return sqr_radius_;
         }
 
- void set_bisector(const site_event<T> &left_site,
- const site_event<T> &right_site) {
- bisector_left_site_ = left_site;
- bisector_right_site_ = right_site;
+ void set_bisector(beach_line_iterator iterator) {
+ bisector_node_ = iterator;
         }
 
- const site_event<T> &get_bisector_left_site() const {
- return bisector_left_site_;
+ const beach_line_iterator &get_bisector() const {
+ return bisector_node_;
         }
-
- const site_event<T> &get_bisector_right_site() const {
- return bisector_right_site_;
- }
-
     private:
         point_2d<T> center_;
         T sqr_radius_;
- site_event<T> bisector_left_site_;
- site_event<T> bisector_right_site_;
+ beach_line_iterator bisector_node_;
     };
 
     template <typename T>

Deleted: sandbox/SOC/2010/sweepline/boost/sweepline/voronoi_builder.hpp
==============================================================================
--- sandbox/SOC/2010/sweepline/boost/sweepline/voronoi_builder.hpp 2010-06-20 19:10:16 EDT (Sun, 20 Jun 2010)
+++ (empty file)
@@ -1,42 +0,0 @@
-// Boost sweepline/voronoi_builder.hpp header file
-
-// Copyright Andrii Sydorchuk 2010.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-// See http://www.boost.org for updates, documentation, and revision history.
-
-#ifndef BOOST_SWEEPLINE_VORONOI_BUILDER
-#define BOOST_SWEEPLINE_VORONOI_BUILDER
-
-#include <vector>
-
-namespace boost {
-namespace sweepline {
-
- template <typename Point2D, typename BeachLine>
- class voronoi_builder {
- public:
- voronoi_builder() {}
-
- void init(const std::vector<Point2D> &sites) {
- beach_line_.init(sites, output_);
- }
-
- void reset() {
- beach_line_.reset();
- }
-
- void build_voronoi_diagram() {
- beach_line_.run_sweepline();
- }
-
- private:
- BeachLine beach_line_;
- };
-
-} // sweepline
-} // boost
-
-#endif
\ No newline at end of file

Added: sandbox/SOC/2010/sweepline/boost/sweepline/voronoi_formation.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2010/sweepline/boost/sweepline/voronoi_formation.hpp 2010-06-20 19:10:16 EDT (Sun, 20 Jun 2010)
@@ -0,0 +1,516 @@
+// Boost sweepline/voronoi_formation.hpp header file
+
+// Copyright Andrii Sydorchuk 2010.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org for updates, documentation, and revision history.
+
+#include <map>
+#include <vector>
+
+#include "event_queue.hpp"
+#include "event_types.hpp"
+#include "voronoi_output.hpp"
+
+#ifndef BOOST_SWEEPLINE_VORONOI_FORMATION
+#define BOOST_SWEEPLINE_VORONOI_FORMATION
+
+namespace boost {
+namespace sweepline {
+
+ // Represents bisector made by two arcs that correspond to the left and
+ // right sites. Arc is defined as curve with points equidistant from the
+ // site and from the sweepline.
+ // Let sweepline sweep from left to right and it's current coordinate
+ // be x0, site coordinates be (x1, y1). In this case equation of the arc
+ // may be written as: (x-x0)^2 = (x-x1)^2 + (y-y1)^2, or
+ // x = ((y - y1)^2 + x1^2 - x0^2) / (2*(x1 - x0)).
+ // In general case two arcs will create two different bisectors. That's why
+ // the order of arcs is important to define unique bisector.
+ template <typename Point2D>
+ struct beach_line_node {
+ public:
+ typedef typename Point2D::coordinate_type coordinate_type;
+ typedef typename Point2D::site_event_type site_event_type;
+ typedef typename Point2D::circle_event_type circle_event_type;
+
+ beach_line_node() {}
+
+ // Constructs degenerate bisector, used to search arc that is above
+ // given site. The input to the constructor is the site event point.
+ explicit beach_line_node(const site_event_type &new_point) {
+ left_site_ = new_point;
+ right_site_ = new_point;
+ }
+
+ // Constructs new bisector. The input to the constructor is two sites
+ // that create bisector. The order of sites is important.
+ beach_line_node(const site_event_type &left_point,
+ const site_event_type &right_point) {
+ left_site_ = left_point;
+ right_site_ = right_point;
+ }
+
+ // Returns the left site of the bisector.
+ const site_event_type &get_left_site() const {
+ return left_site_;
+ }
+
+ // Returns the right site of the bisector.
+ const site_event_type &get_right_site() const {
+ return right_site_;
+ }
+
+ void set_left_site(const site_event_type &site) {
+ left_site_ = site;
+ }
+
+ void set_right_site(const site_event_type &site) {
+ right_site_ = site;
+ }
+
+ // Returns x coordinate of the rightmost site.
+ coordinate_type get_sweepline_coord() const {
+ return std::max(left_site_.x(), right_site_.x());
+ }
+
+ // Returns the rightmost site.
+ const site_event_type& get_new_site() const {
+ if (left_site_.x() > right_site_.x())
+ return left_site_;
+ return right_site_;
+ }
+
+ // Returns true if horizontal line going through new site intersects
+ // right arc at first, else returns false. If horizontal line goes
+ // through intersection point of the given two arcs returns false also.
+ // Used during nodes comparison.
+ // Let x0 be sweepline coordinate, left site coordinates be (x1, y1),
+ // right site coordinates be (x2, y2). Equations of the arcs will be:
+ // x1(y) = ((y - y1)^2 + x1^2 - x0^2) / (2*(x1 - x0));
+ // x2(y) = ((y - y2)^2 + x2^2 - x0^2) / (2*(x2 - x0)).
+ // Horizontal line going throught site (x*, y*) intersects second arc
+ // at first if x2(y*) > x1(y*) or:
+ // (x2-x0)*(x1-x0)*(x1-x2) + (x2-x0)*(y*-y1)^2 < (x1-x0)*(y*-y2)^2
+ bool less(const site_event_type &new_site) const {
+ coordinate_type sweepline_coord = new_site.x();
+ coordinate_type new_node_coord = new_site.y();
+ coordinate_type a1 = left_site_.x() - sweepline_coord;
+ coordinate_type a2 = right_site_.x() - sweepline_coord;
+ coordinate_type b1 = new_node_coord - left_site_.y();
+ coordinate_type b2 = new_node_coord - right_site_.y();
+ coordinate_type c = left_site_.x() - right_site_.x();
+ return a1 * a2 * c + a2 * b1 * b1 < a1 * b2 * b2;
+ }
+
+ private:
+ site_event_type left_site_;
+ site_event_type right_site_;
+ };
+
+ // Represents edge data sturcture (bisector segment), which is
+ // associated with beach line node key in the binary search tree.
+ template <typename Point2D>
+ struct beach_line_node_data {
+ typedef typename half_edge<Point2D> Edge;
+
+ Edge *edge;
+
+ beach_line_node_data(Edge *new_edge) : edge(new_edge) {}
+
+ void change_edge(Edge *new_edge) {
+ edge = new_edge;
+ }
+ };
+
+ template <typename BeachLineNode>
+ struct node_comparer {
+ public:
+ typedef typename BeachLineNode::coordinate_type coordinate_type;
+
+ // Compares nodes in the balanced binary search tree. Nodes are
+ // compared based on the y coordinates of the arcs intersection points.
+ // Nodes with lesser y coordinate of the intersection point go first.
+ // Comparison is only called during site events processing. That's why
+ // one of the nodes will always lie on the sweepline. Comparison won't
+ // work fine for nodes situated above sweepline.
+ bool operator() (const BeachLineNode &node1,
+ const BeachLineNode &node2) const {
+ // Get x coordinate of the righmost site from both nodes.
+ coordinate_type node1_line = node1.get_sweepline_coord();
+ coordinate_type node2_line = node2.get_sweepline_coord();
+
+ // Both nodes are situated on the same vertical line.
+ if (node1_line == node2_line) {
+ // Let A be the new site event point, and B the site that
+ // creates arc above A. In this case two new nodes are being
+ // inserted: (A,B) and (B,A). As intersection points for the
+ // first node and for the second are the same we need to
+ // compare them based on some another characteristic.
+ // That's why we assume that node (C, D) goes before node
+ // (D, C), only if D lies on the sweepline.
+ if (node1.get_left_site().get_site_index() ==
+ node2.get_right_site().get_site_index() &&
+ node1.get_right_site().get_site_index() ==
+ node2.get_left_site().get_site_index())
+ return node1.get_right_site().x() == node1_line;
+
+ // Just compare coordinates of the sites situated on the sweepline.
+ return node1.get_new_site().y() < node2.get_new_site().y();
+ }
+ else if (node1_line < node2_line)
+ return node1.less(node2.get_new_site());
+ else
+ return !node2.less(node1.get_new_site());
+ }
+ };
+
+ // Voronoi diagram formation. Sweepline sweeps from left to right.
+ template <typename T>
+ class voronoi_formation {
+ public:
+ typedef typename point_2d<T> Point2D;
+ typedef typename Point2D::coordinate_type coordinate_type;
+ typedef typename Point2D::site_event_type site_event_type;
+ typedef typename Point2D::circle_event_type circle_event_type;
+
+ typedef typename voronoi_output<Point2D> Output;
+ typedef typename Output::edge_type edge_type;
+ typedef typename Output::edge_iterator edge_iterator;
+ typedef typename Output::cell_records cell_records;
+ typedef typename Output::voronoi_vertices voronoi_vertices;
+ typedef typename voronoi_vertices::const_iterator voronoi_vertices_iterator;
+
+ typedef typename event_queue<Point2D> EventQueue;
+ typedef typename beach_line_node<Point2D> Key;
+ typedef typename beach_line_node_data<Point2D> Value;
+ typedef typename node_comparer<Key> NodeComparer;
+ typedef typename std::map< Key, Value, NodeComparer > BeachLine;
+ typedef typename BeachLine::const_iterator beach_line_iterator;
+
+ // Functor to process events from the event queue.
+ struct event_processor {
+ event_processor() : beach_line_(NULL) {}
+
+ void operator()(const site_event_type &site_event) {
+ beach_line_->process_site_event(site_event);
+ }
+
+ void operator()(const circle_event_type &circle_event) {
+ beach_line_->process_circle_event(circle_event);
+ }
+
+ voronoi_formation *beach_line_;
+ };
+
+ voronoi_formation() : event_processor_() {}
+
+ // Init beach line before sweepline run.
+ // In case of a few first sites situated on the same
+ // vertical line, we init beach line with all of them.
+ // In other case just use the first two sites for the initialization.
+ void init(std::vector<Point2D> &sites) {
+ output_.init(sites.size());
+
+ // Init beach_line pointer in the event_processor data sturcture.
+ // This is done here to avoid compiler warning in the constructor.
+ event_processor_.beach_line_ = this;
+
+ // Sort all sites.
+ std::sort(sites.begin(), sites.end());
+ int skip = 0;
+
+ if (sites.size() == 1) {
+ skip = 1;
+ } else {
+ std::vector<Point2D>::const_iterator it = sites.begin();
+ while(it != sites.end() && it->x() == sites.begin()->x()) {
+ it++;
+ skip++;
+ }
+
+ if (skip == 1) {
+ // Init beach line with two sites.
+ init_beach_line(*sites.begin(), *it);
+
+ // Skip the second point also.
+ skip++;
+ } else {
+ // Init beach line with sites situated on the same vertical line.
+ init_beach_line(sites.begin(), it);
+ }
+ }
+ // Init event queue with the rest of the sites.
+ event_queue_.init(sites, skip);
+ }
+
+ void reset() {
+ event_queue_.reset();
+ beach_line_.clear();
+ output_.clear();
+ }
+
+ void run_sweepline() {
+ // Algorithm stops when there are no events in the queue.
+ while (!event_queue_.empty()) {
+ event_queue_.process_top_event(event_processor_);
+ event_queue_.pop();
+ }
+ }
+
+ // Uses special comparison function for the lower bound and insertion
+ // operations.
+ void process_site_event(const site_event_type &site_event) {
+ // Find the node in the binary search tree with left arc
+ // lying above the new site point.
+ Key new_key(site_event);
+ beach_line_iterator it = beach_line_.lower_bound(new_key);
+
+ site_event_type site_arc;
+ if (it == beach_line_.end()) {
+ it--;
+ site_arc = it->first.get_right_site();
+
+ // Insert new arc into the sweepline.
+ beach_line_iterator new_node_it = insert_new_arc(site_arc, site_event);
+ new_node_it--;
+
+ // Add candidate circle to the event queue.
+ activate_circle_event(it->first.get_left_site(),
+ it->first.get_right_site(),
+ site_event,
+ new_node_it);
+ } else if (it == beach_line_.begin()) {
+ site_arc = it->first.get_left_site();
+
+ // Insert new arc into the sweepline.
+ beach_line_iterator new_node_it = insert_new_arc(site_arc, site_event);
+ new_node_it++;
+
+ // Add candidate circle to the event queue.
+ activate_circle_event(site_event,
+ it->first.get_left_site(),
+ it->first.get_right_site(),
+ new_node_it);
+ } else {
+ site_arc = it->first.get_left_site();
+
+ // Insert new arc into the sweepline.
+ beach_line_iterator new_node_it = insert_new_arc(site_arc, site_event);
+
+ const site_event_type &site2 = it->first.get_left_site();
+ const site_event_type &site3 = it->first.get_right_site();
+ it--;
+ const site_event_type &site1 = it->first.get_right_site();
+
+ // Remove candidate circle from the event queue.
+ deactivate_circle_event(site1, site2, site3);
+
+ // Add candidate circles to the event queue.
+ new_node_it--;
+ activate_circle_event(site1, site2, site_event, new_node_it);
+ new_node_it++;
+ new_node_it++;
+ activate_circle_event(site_event, site2, site3, new_node_it);
+ }
+ }
+
+ // Doesn't use special comparison function as it works fine only for
+ // the site events processing.
+ void process_circle_event(const circle_event_type &circle_event) {
+ // Retrieve the second bisector node that corresponds to the given
+ // circle event.
+ beach_line_iterator it_first = circle_event.get_bisector();
+ beach_line_iterator it_last = it_first;
+
+ // Get the second and the third sites that create given circle event.
+ site_event_type site2 = it_first->first.get_left_site();
+ site_event_type site3 = it_first->first.get_right_site();
+
+ // Get second bisector;
+ Value bisector2 = it_first->second;
+
+ // Get first bisector;
+ it_first--;
+ Value bisector1 = it_first->second;
+
+ // Get the first site that creates given circle event.
+ site_event_type site1 = it_first->first.get_left_site();
+
+ // Let circle event sites be A, B, C, two bisectors that define
+ // circle event be (A, B), (B, C). During circle event processing
+ // we remove (A, B), (B, C) and insert (A, C). As beach line nodes
+ // comparer doesn't work fine for the circle events. We only 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.
+ const_cast<Key &>(it_first->first).set_right_site(it_last->first.get_right_site());
+ edge_type *edge = output_.insert_new_edge(site1, site2, site3, circle_event, bisector1.edge, bisector2.edge);
+ const_cast<Value &>(it_first->second).change_edge(edge);
+ beach_line_.erase(it_last);
+ it_last = it_first;
+
+ // Check the new triplets formed by the neighboring arcs
+ // for potential circle events. Check left.
+ if (it_first != beach_line_.begin()) {
+ it_first--;
+ const site_event_type &site_l1 = it_first->first.get_left_site();
+ deactivate_circle_event(site_l1, site1, site2);
+ if (it_first != beach_line_.begin()) {
+ it_first--;
+ const site_event_type &site_l2 = it_first->first.get_left_site();
+ it_first++;
+ activate_circle_event(site_l2, site_l1, site1, it_first);
+ }
+ }
+
+ // Check the new triplets formed by the neighboring arcs
+ // for potential circle events. Check right.
+ it_last++;
+ if (it_last != beach_line_.end()) {
+ const site_event_type &site_r1 = it_last->first.get_right_site();
+ deactivate_circle_event(site2, site3, site_r1);
+ it_last++;
+ if (it_last != beach_line_.end()) {
+ it_last++;
+ const site_event_type &site_r2 = it_last->first.get_right_site();
+ activate_circle_event(site3, site_r1, site_r2, it_last);
+ }
+ }
+ }
+
+ const cell_records &get_cell_records() const {
+ return output_.get_cell_records();
+ }
+
+ const voronoi_vertices &get_voronoi_vertices() const {
+ return output_.get_voronoi_vertices();
+ }
+
+ protected:
+ void init_beach_line(typename std::vector<Point2D>::const_iterator it_begin,
+ typename std::vector<Point2D>::const_iterator it_end) {
+ typename std::vector<Point2D>::const_iterator it_first = it_begin;
+ typename std::vector<Point2D>::const_iterator it_second = it_begin;
+ it_second++;
+ int cur_site = 0;
+ while (it_second != it_end) {
+ site_event_type site1 = make_site_event<coordinate_type>(
+ it_first->x(), it_first->y(), cur_site);
+ site_event_type site2 = make_site_event<coordinate_type>(
+ it_second->x(), it_second->y(), cur_site+1);
+
+ // Create new beach line node.
+ Key new_node(site1, site2);
+
+ // Update output.
+ edge_type *edge = output_.insert_new_edge(site1, site2);
+
+ // Insert new node into the binary search tree.
+ beach_line_.insert(std::pair<Key, Value>(new_node, Value(edge)));
+
+ // Update iterators.
+ it_first++;
+ it_second++;
+ cur_site++;
+ }
+ }
+
+ void init_beach_line(const Point2D &first_point,
+ const Point2D &second_point) {
+ site_event_type site1 = make_site_event<coordinate_type>(
+ first_point.x(), first_point.y(), 0);
+ site_event_type site2 = make_site_event<coordinate_type>(
+ second_point.x(), second_point.y(), 1);
+
+ // Create two new beach line nodes.
+ Key new_left_node(site1, site2);
+ Key new_right_node(site2, site1);
+
+ // Update output.
+ edge_type *edge = output_.insert_new_edge(site1, site2);
+
+ // Insert two new nodes into the binary search tree.
+ beach_line_.insert(std::pair<Key, Value>(new_left_node, Value(edge)));
+ beach_line_.insert(std::pair<Key, Value>(new_right_node, Value(edge->twin)));
+ }
+
+ // Insert new arc below site arc into the beach line.
+ beach_line_iterator insert_new_arc(const site_event_type &site_arc,
+ const site_event_type &site_event) {
+ // Create two new nodes.
+ Key new_left_node(site_arc, site_event);
+ Key new_right_node(site_event, site_arc);
+ int site_index1 = site_arc.get_site_index();
+ int site_index2 = site_event.get_site_index();
+
+ // Insert two new nodes into the binary search tree.
+ // Update output.
+ edge_type *edge = output_.insert_new_edge(site_arc, site_event);
+ beach_line_.insert(std::pair<Key, Value>(new_left_node, Value(edge)));
+ return beach_line_.insert(std::pair<Key, Value>(new_right_node, Value(edge->twin))).first;
+ }
+
+ // Create circle event from the given three points.
+ bool create_circle_event(const site_event_type &site1,
+ const site_event_type &site2,
+ const site_event_type &site3,
+ circle_event_type &c_event) const {
+ coordinate_type a = (site1.x() - site2.x()) * (site2.y() - site3.y()) -
+ (site1.y() - site2.y()) * (site2.x() - site3.x());
+ // Check if bisectors intersect.
+ if (a >= static_cast<coordinate_type>(0))
+ return false;
+ coordinate_type b1 = (site1.x() - site2.x()) * (site1.x() + site2.x())+
+ (site1.y() - site2.y()) * (site1.y() + site2.y());
+ coordinate_type b2 = (site2.x() - site3.x()) * (site2.x() + site3.x())+
+ (site2.y() - site3.y()) * (site2.y() + site3.y());
+ coordinate_type c_x = (b1*(site2.y() - site3.y()) - b2*(site1.y() - site2.y())) / a *
+ static_cast<coordinate_type>(0.5);
+ coordinate_type c_y = (b2*(site1.x() - site2.x()) - b1*(site2.x() - site3.x())) / a *
+ static_cast<coordinate_type>(0.5);
+ coordinate_type sqr_radius = (c_x-site1.x())*(c_x-site1.x()) +
+ (c_y-site1.y())*(c_y-site1.y());
+ // Create new circle event;
+ c_event = make_circle_event(c_x, c_y, sqr_radius);
+ return true;
+ }
+
+ // Add new circle event to the event queue.
+ 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;
+ if (create_circle_event(site1, site2, site3, c_event)) {
+ c_event.set_bisector(bisector_node);
+ event_queue_.push(c_event);
+ }
+ }
+
+ // Remove circle event from the event queue.
+ void deactivate_circle_event(const site_event_type &point1,
+ const site_event_type &point2,
+ const site_event_type &point3) {
+ circle_event_type c_event;
+ if (create_circle_event(point1, point2, point3, c_event))
+ event_queue_.deactivate_event(c_event);
+ }
+
+ private:
+ EventQueue event_queue_;
+ event_processor event_processor_;
+ BeachLine beach_line_;
+ Output output_;
+
+ //Disallow copy constructor and operator=
+ voronoi_formation(const voronoi_formation&);
+ void operator=(const voronoi_formation&);
+ };
+
+} // sweepline
+} // boost
+
+#endif
\ No newline at end of file

Modified: sandbox/SOC/2010/sweepline/boost/sweepline/voronoi_output.hpp
==============================================================================
--- sandbox/SOC/2010/sweepline/boost/sweepline/voronoi_output.hpp (original)
+++ sandbox/SOC/2010/sweepline/boost/sweepline/voronoi_output.hpp 2010-06-20 19:10:16 EDT (Sun, 20 Jun 2010)
@@ -77,9 +77,18 @@
         typedef typename cell_record<Point2D> cell_record_type;
         typedef typename vertex_record<Point2D> vertex_record_type;
         typedef typename half_edge<Point2D> edge_type;
+ typedef typename std::vector<cell_record_type> cell_records;
+ typedef typename std::list<vertex_record_type> voronoi_vertices;
+ typedef typename std::list<edge_type *>::const_iterator edge_iterator;
+ typedef typename voronoi_vertices::const_iterator voronoi_vertices_iterator;
 
         voronoi_output() {}
 
+ // This preserves the validity of iterators.
+ void init(int num_sites) {
+ cell_records_.reserve(num_sites);
+ }
+
         void reset() {
             cell_records_.clear();
             vertex_records_.clear();
@@ -91,24 +100,28 @@
         // beach line node and returns reference to the new half-edge.
         // Second argument is new site. During this step we add two new
         // twin half-edges.
- edge_type &insert_new_edge(const site_event_type &site1,
+ edge_type *insert_new_edge(const site_event_type &site1,
                                    const site_event_type &site2) {
             // Get indexes of sites.
             int site_index1 = site1.get_site_index();
             int site_index2 = site2.get_site_index();
 
- // Create new half-edge that belongs to the cell with second site.
+ // Create new half-edge that belongs to the cell with the first site.
+ edges_.push_back(edge_type(site_index1));
+ edge_type &edge1 = edges_.back();
+
+ // Create new half-edge that belongs to the cell with the second site.
             edges_.push_back(edge_type(site_index2));
             edge_type &edge2 = edges_.back();
 
+ // Add initial cell during first edge insertion.
+ if (cell_records_.empty())
+ cell_records_.push_back(cell_record_type(site1.get_point(), &edge1));
+
             // Second site represents new site during site event processing.
             // Add new cell to the cell records vector.
             cell_records_.push_back(cell_record_type(site2.get_point(), &edge2));
 
- // Create new half-edge that belongs to the cell with first site.
- edges_.push_back(edge_type(site_index1));
- edge_type &edge1 = edges_.back();
-
             // Update pointers to cells.
             edge1.cell_record = &cell_records_[site_index1];
             edge2.cell_record = &cell_records_[site_index2];
@@ -117,25 +130,25 @@
             edge1.twin = &edge2;
             edge2.twin = &edge1;
 
- return edges_.back();
+ return &edge1;
         }
 
- edge_type &insert_new_edge(const site_event_type &site1,
+ edge_type *insert_new_edge(const site_event_type &site1,
                                    const site_event_type &site2,
                                    const site_event_type &site3,
                                    const circle_event_type &circle,
- edge_type &edge12,
- edge_type &edge23) {
+ edge_type *edge12,
+ edge_type *edge23) {
             // Add new voronoi vertex as voronoi circle center.
             vertex_records_.push_back(vertex_record_type(circle.get_center()));
- vertex_record_type new_vertex = vertex_records_.back();
+ vertex_record_type &new_vertex = vertex_records_.back();
 
             // Update two input bisectors and their twins half-edges with
             // new voronoi vertex.
- edge12.start_point = &new_vertex;
- edge12.twin->end_point = &new_vertex;
- edge23.end_point = &new_vertex;
- edge23.twin->start_point = &new_vertex;
+ edge12->start_point = &new_vertex;
+ edge12->twin->end_point = &new_vertex;
+ edge23->start_point = &new_vertex;
+ edge23->twin->end_point = &new_vertex;
 
             // Add new half-edge.
             edges_.push_back(edge_type(site1.get_site_index()));
@@ -155,25 +168,36 @@
 
             // Update voronoi prev/next pointers of all half-edges incident
             // to the new voronoi vertex.
- edge12.prev = &new_edge1;
- new_edge1.next = &edge12;
- edge12.twin->next = &edge23;
- edge23.prev = edge12.twin;
- edge23.twin->next = &new_edge2;
- new_edge2.prev = edge23.twin;
+ edge12->prev = &new_edge1;
+ new_edge1.next = edge12;
+ edge12->twin->next = edge23;
+ edge23->prev = edge12->twin;
+ edge23->twin->next = &new_edge2;
+ new_edge2.prev = edge23->twin;
 
             // Update voronoi vertex incident edges pointers.
- new_vertex.incident_edges.push_back(&edge12);
- new_vertex.incident_edges.push_back(&edge23);
- new_vertex.incident_edges.push_back(&new_edge1);
+ new_vertex.incident_edges.push_back(edge12);
+ new_vertex.incident_edges.push_back(edge23);
+ new_vertex.incident_edges.push_back(&new_edge2);
+ return &new_edge1;
+ }
 
- return edges_.back();
+ const cell_records &get_cell_records() const {
+ return cell_records_;
+ }
+
+ const voronoi_vertices &get_voronoi_vertices() const {
+ return vertex_records_;
         }
 
     private:
         std::vector<cell_record_type> cell_records_;
         std::list<vertex_record_type> vertex_records_;
         std::list<edge_type> edges_;
+
+ //Disallow copy constructor and operator=
+ voronoi_output(const voronoi_output&);
+ void operator=(const voronoi_output&);
     };
 
 } // sweepline

Modified: sandbox/SOC/2010/sweepline/libs/sweepline/test/Jamfile.v2
==============================================================================
--- sandbox/SOC/2010/sweepline/libs/sweepline/test/Jamfile.v2 (original)
+++ sandbox/SOC/2010/sweepline/libs/sweepline/test/Jamfile.v2 2010-06-20 19:10:16 EDT (Sun, 20 Jun 2010)
@@ -13,6 +13,7 @@
 test-suite "sweepline"
     :
         [ run event_queue_test.cpp : : : <link>static ]
- [ run beach_line_test.cpp : : : <link>static ]
         [ run event_types_test.cpp : : : <link>static ]
+ [ run node_comparer_test.cpp : : : <link>static ]
+ [ run voronoi_formation_test.cpp : : : <link>static ]
     ;
\ No newline at end of file

Deleted: sandbox/SOC/2010/sweepline/libs/sweepline/test/beach_line_test.cpp
==============================================================================
--- sandbox/SOC/2010/sweepline/libs/sweepline/test/beach_line_test.cpp 2010-06-20 19:10:16 EDT (Sun, 20 Jun 2010)
+++ (empty file)
@@ -1,80 +0,0 @@
-// Boost sweepline library beach_line_test.cpp file
-
-// Copyright Andrii Sydorchuk 2010.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-// See http://www.boost.org for updates, documentation, and revision history.
-
-#include "test_type_list.hpp"
-#include <boost/sweepline/beach_line.hpp>
-#include <boost/sweepline/event_types.hpp>
-using namespace boost::sweepline;
-
-#define BOOST_TEST_MODULE beach_line_test
-#include <boost/test/test_case_template.hpp>
-
-BOOST_AUTO_TEST_CASE_TEMPLATE(node_comparer_test1, T, test_types) {
- typedef beach_line_node< point_2d<T> > bline_node;
- typedef std::map< bline_node, int, node_comparer<bline_node> >::const_iterator bline_it;
-
- std::map< bline_node, int, node_comparer<bline_node> > test_beach_line;
-
- bline_node initial_node(
- make_site_event<T>(static_cast<T>(0), static_cast<T>(0), 0),
- make_site_event<T>(static_cast<T>(0), static_cast<T>(2), 1));
- test_beach_line[initial_node] = 0;
- BOOST_CHECK_EQUAL(test_beach_line.size(), 1);
-
- bline_node new_node1(make_site_event<T>(static_cast<T>(1), static_cast<T>(0), 2));
- bline_node new_node2(make_site_event<T>(static_cast<T>(1), static_cast<T>(1), 3));
- bline_node new_node3(make_site_event<T>(static_cast<T>(1), static_cast<T>(2), 4));
- bline_node new_node4(make_site_event<T>(static_cast<T>(1), static_cast<T>(1.000001), 5));
- bline_node new_node5(make_site_event<T>(static_cast<T>(1), static_cast<T>(0.999999), 6));
-
- bline_it it = test_beach_line.lower_bound(new_node1);
- BOOST_CHECK_EQUAL(it == test_beach_line.begin(), true);
-
- it = test_beach_line.lower_bound(new_node2);
- BOOST_CHECK_EQUAL(it == test_beach_line.begin(), true);
-
- it = test_beach_line.lower_bound(new_node3);
- BOOST_CHECK_EQUAL(it == test_beach_line.end(), true);
-
- it = test_beach_line.lower_bound(new_node4);
- BOOST_CHECK_EQUAL(it == test_beach_line.end(), true);
-
- it = test_beach_line.lower_bound(new_node5);
- BOOST_CHECK_EQUAL(it == test_beach_line.begin(), true);
-
- it = test_beach_line.lower_bound(initial_node);
- BOOST_CHECK_EQUAL(it == test_beach_line.begin(), true);
-}
-
-BOOST_AUTO_TEST_CASE_TEMPLATE(node_comparer_test2, T, test_types) {
- typedef beach_line_node< point_2d<T> > bline_node;
- typedef std::map< bline_node, int, node_comparer<bline_node> >::const_iterator bline_it;
-
- std::map< bline_node, int, node_comparer<bline_node> > test_beach_line;
-
- site_event<T> site1 = make_site_event<T>(static_cast<T>(0), static_cast<T>(0), 0);
- site_event<T> site2 = make_site_event<T>(static_cast<T>(0), static_cast<T>(2), 1);
- bline_node initial_node(site1, site2);
- test_beach_line[initial_node] = 0;
-
- site_event<T> site3 = make_site_event<T>(static_cast<T>(1), static_cast<T>(0), 2);
- bline_node node1(site1, site3);
- bline_node node2(site3, site1);
- test_beach_line.insert(std::pair< bline_node, int>(node1, 1));
- test_beach_line.insert(std::pair< bline_node, int>(node2, 2));
-
- bline_it it = test_beach_line.begin();
- BOOST_CHECK_EQUAL(it->second == 1, true);
-
- ++it;
- BOOST_CHECK_EQUAL(it->second == 2, true);
-
- ++it;
- BOOST_CHECK_EQUAL(it->second == 0, true);
-}
\ No newline at end of file

Modified: sandbox/SOC/2010/sweepline/libs/sweepline/test/event_queue_test.cpp
==============================================================================
--- sandbox/SOC/2010/sweepline/libs/sweepline/test/event_queue_test.cpp (original)
+++ sandbox/SOC/2010/sweepline/libs/sweepline/test/event_queue_test.cpp 2010-06-20 19:10:16 EDT (Sun, 20 Jun 2010)
@@ -8,8 +8,7 @@
 // See http://www.boost.org for updates, documentation, and revision history.
 
 #include "test_type_list.hpp"
-#include <boost/sweepline/event_queue.hpp>
-#include <boost/sweepline/event_types.hpp>
+#include <boost/sweepline/voronoi_formation.hpp>
 using namespace boost::sweepline;
 
 #define BOOST_TEST_MODULE event_queue_test

Modified: sandbox/SOC/2010/sweepline/libs/sweepline/test/event_types_test.cpp
==============================================================================
--- sandbox/SOC/2010/sweepline/libs/sweepline/test/event_types_test.cpp (original)
+++ sandbox/SOC/2010/sweepline/libs/sweepline/test/event_types_test.cpp 2010-06-20 19:10:16 EDT (Sun, 20 Jun 2010)
@@ -8,7 +8,7 @@
 // See http://www.boost.org for updates, documentation, and revision history.
 
 #include "test_type_list.hpp"
-#include <boost/sweepline/event_types.hpp>
+#include <boost/sweepline/voronoi_formation.hpp>
 using namespace boost::sweepline;
 
 #define BOOST_TEST_MODULE event_types_test

Added: sandbox/SOC/2010/sweepline/libs/sweepline/test/node_comparer_test.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2010/sweepline/libs/sweepline/test/node_comparer_test.cpp 2010-06-20 19:10:16 EDT (Sun, 20 Jun 2010)
@@ -0,0 +1,102 @@
+// Boost sweepline library node_comparer_test.cpp file
+
+// Copyright Andrii Sydorchuk 2010.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org for updates, documentation, and revision history.
+
+#include "test_type_list.hpp"
+#include <boost/sweepline/voronoi_formation.hpp>
+using namespace boost::sweepline;
+
+#define BOOST_TEST_MODULE node_comparer_test
+#include <boost/test/test_case_template.hpp>
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(node_comparer_test1, T, test_types) {
+ typedef beach_line_node< point_2d<T> > bline_node;
+ typedef std::map< bline_node, int, node_comparer<bline_node> >::const_iterator bline_it;
+
+ std::map< bline_node, int, node_comparer<bline_node> > test_beach_line;
+
+ bline_node initial_node(
+ make_site_event<T>(static_cast<T>(0), static_cast<T>(0), 0),
+ make_site_event<T>(static_cast<T>(0), static_cast<T>(2), 1));
+ test_beach_line[initial_node] = 0;
+ BOOST_CHECK_EQUAL(test_beach_line.size(), 1);
+
+ bline_node new_node1(make_site_event<T>(static_cast<T>(1), static_cast<T>(0), 2));
+ bline_node new_node2(make_site_event<T>(static_cast<T>(1), static_cast<T>(1), 3));
+ bline_node new_node3(make_site_event<T>(static_cast<T>(1), static_cast<T>(2), 4));
+ bline_node new_node4(make_site_event<T>(static_cast<T>(1), static_cast<T>(1.000001), 5));
+ bline_node new_node5(make_site_event<T>(static_cast<T>(1), static_cast<T>(0.999999), 6));
+
+ bline_it it = test_beach_line.lower_bound(new_node1);
+ BOOST_CHECK_EQUAL(it == test_beach_line.begin(), true);
+
+ it = test_beach_line.lower_bound(new_node2);
+ BOOST_CHECK_EQUAL(it == test_beach_line.begin(), true);
+
+ it = test_beach_line.lower_bound(new_node3);
+ BOOST_CHECK_EQUAL(it == test_beach_line.end(), true);
+
+ it = test_beach_line.lower_bound(new_node4);
+ BOOST_CHECK_EQUAL(it == test_beach_line.end(), true);
+
+ it = test_beach_line.lower_bound(new_node5);
+ BOOST_CHECK_EQUAL(it == test_beach_line.begin(), true);
+
+ it = test_beach_line.lower_bound(initial_node);
+ BOOST_CHECK_EQUAL(it == test_beach_line.begin(), true);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(node_comparer_test2, T, test_types) {
+ typedef beach_line_node< point_2d<T> > bline_node;
+ typedef std::map< bline_node, int, node_comparer<bline_node> >::const_iterator bline_it;
+
+ std::map< bline_node, int, node_comparer<bline_node> > test_beach_line;
+
+ site_event<T> site1 = make_site_event<T>(static_cast<T>(0), static_cast<T>(0), 0);
+ site_event<T> site2 = make_site_event<T>(static_cast<T>(0), static_cast<T>(2), 1);
+ bline_node initial_node(site1, site2);
+ test_beach_line[initial_node] = 2;
+
+ site_event<T> site3 = make_site_event<T>(static_cast<T>(1), static_cast<T>(0), 2);
+ bline_node node1(site1, site3);
+ bline_node node2(site3, site1);
+ test_beach_line.insert(std::pair< bline_node, int>(node1, 0));
+ test_beach_line.insert(std::pair< bline_node, int>(node2, 1));
+
+ int cur_value = 0;
+ for (bline_it it = test_beach_line.begin();
+ it != test_beach_line.end();
+ it++, cur_value++)
+ BOOST_CHECK_EQUAL(it->second, cur_value);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(node_comparer_test3, T, test_types) {
+ typedef beach_line_node< point_2d<T> > bline_node;
+ typedef std::map< bline_node, int, node_comparer<bline_node> >::const_iterator bline_it;
+
+ std::map< bline_node, int, node_comparer<bline_node> > test_beach_line;
+
+ site_event<T> site1 = make_site_event<T>(static_cast<T>(0), static_cast<T>(1), 0);
+ site_event<T> site2 = make_site_event<T>(static_cast<T>(2), static_cast<T>(0), 1);
+ site_event<T> site3 = make_site_event<T>(static_cast<T>(2), static_cast<T>(4), 2);
+ bline_node initial_node1(site1, site2);
+ bline_node initial_node2(site2, site1);
+ test_beach_line[initial_node1] = 0;
+ test_beach_line[initial_node2] = 1;
+
+ bline_node new_node1(site1, site3);
+ bline_node new_node2(site3, site1);
+ test_beach_line[new_node1] = 2;
+ test_beach_line[new_node2] = 3;
+
+ int cur_value = 0;
+ for (bline_it it = test_beach_line.begin();
+ it != test_beach_line.end();
+ it++, cur_value++)
+ BOOST_CHECK_EQUAL(it->second, cur_value);
+}
\ No newline at end of file

Deleted: sandbox/SOC/2010/sweepline/libs/sweepline/test/voronoi_builder_test.cpp
==============================================================================
--- sandbox/SOC/2010/sweepline/libs/sweepline/test/voronoi_builder_test.cpp 2010-06-20 19:10:16 EDT (Sun, 20 Jun 2010)
+++ (empty file)
@@ -1,20 +0,0 @@
-// Boost sweepline library voronoi_builder_test.cpp file
-
-// Copyright Andrii Sydorchuk 2010.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-// See http://www.boost.org for updates, documentation, and revision history.
-
-//#include "test_type_list.hpp"
-//#include <boost/sweepline/beach_line.hpp>
-//#include <boost/sweepline/event_queue.hpp>
-//#include <boost/sweepline/event_types.hpp>
-//#include <boost/sweepline/voronoi_builder.hpp>
-//
-//#define BOOST_TEST_MODULE voronoi_builder_test
-//#include <boost/test/test_case_template.hpp>
-//
-//BOOST_AUTO_TEST_CASE_TEMPLATE(voronoi_builder_test1, T, test_types) {
-//}
\ No newline at end of file

Added: sandbox/SOC/2010/sweepline/libs/sweepline/test/voronoi_formation_test.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2010/sweepline/libs/sweepline/test/voronoi_formation_test.cpp 2010-06-20 19:10:16 EDT (Sun, 20 Jun 2010)
@@ -0,0 +1,138 @@
+// Boost sweepline library voronoi_formation_test.cpp file
+
+// Copyright Andrii Sydorchuk 2010.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org for updates, documentation, and revision history.
+
+#include "test_type_list.hpp"
+#include <boost/sweepline/voronoi_formation.hpp>
+using namespace boost::sweepline;
+
+#define BOOST_TEST_MODULE voronoi_formation_test
+#include <boost/test/test_case_template.hpp>
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(beach_line_test1, T, test_types) {
+ typedef typename voronoi_formation<T>::edge_type edge_type;
+ typedef typename voronoi_formation<T>::edge_iterator edge_iterator;
+ typedef typename voronoi_formation<T>::voronoi_vertices_iterator
+ voronoi_vertices_iterator;
+
+ voronoi_formation<T> test_beach_line;
+ point_2d<T> point1 = make_point_2d<T>(0, 0);
+ point_2d<T> point2 = make_point_2d<T>(0, 4);
+ point_2d<T> point3 = make_point_2d<T>(2, 1);
+
+ std::vector< point_2d<T> > points;
+ points.push_back(point1);
+ points.push_back(point2);
+ points.push_back(point3);
+
+ test_beach_line.init(points);
+ test_beach_line.run_sweepline();
+ BOOST_CHECK_EQUAL(test_beach_line.get_cell_records().size(), 3);
+ BOOST_CHECK_EQUAL(test_beach_line.get_voronoi_vertices().size(), 1);
+
+ voronoi_vertices_iterator it = test_beach_line.get_voronoi_vertices().begin();
+ BOOST_CHECK_EQUAL(it->incident_edges.size(), 3);
+ BOOST_CHECK_EQUAL(it->vertex.x() == static_cast<T>(0.25) &&
+ it->vertex.y() == static_cast<T>(2.0), true);
+
+ edge_iterator edge_it = it->incident_edges.begin();
+ edge_type *edge1_1 = *edge_it;
+ edge_type *edge1_2 = edge1_1->twin;
+ BOOST_CHECK_EQUAL(edge1_1->cell_record->site_point == point3, true);
+ BOOST_CHECK_EQUAL(edge1_2->cell_record->site_point == point1, true);
+
+ edge_it++;
+ edge_type *edge2_1 = *edge_it;
+ edge_type *edge2_2 = edge2_1->twin;
+ BOOST_CHECK_EQUAL(edge2_1->cell_record->site_point == point1, true);
+ BOOST_CHECK_EQUAL(edge2_2->cell_record->site_point == point2, true);
+
+ edge_it++;
+ edge_type *edge3_1 = *edge_it;
+ edge_type *edge3_2 = edge3_1->twin;
+ BOOST_CHECK_EQUAL(edge3_1->cell_record->site_point == point2, true);
+ BOOST_CHECK_EQUAL(edge3_2->cell_record->site_point == point3, true);
+
+ BOOST_CHECK_EQUAL(edge1_2->twin == edge1_1, true);
+ BOOST_CHECK_EQUAL(edge2_2->twin == edge2_1, true);
+ BOOST_CHECK_EQUAL(edge3_2->twin == edge3_1, true);
+
+ BOOST_CHECK_EQUAL(edge1_1->next == NULL && edge1_2->prev == NULL, true);
+ BOOST_CHECK_EQUAL(edge2_1->next == NULL && edge2_2->prev == NULL, true);
+ BOOST_CHECK_EQUAL(edge3_1->next == NULL && edge3_2->prev == NULL, true);
+
+ BOOST_CHECK_EQUAL(edge1_1->prev == edge3_2, true);
+ BOOST_CHECK_EQUAL(edge2_1->prev == edge1_2, true);
+ BOOST_CHECK_EQUAL(edge3_1->prev == edge2_2, true);
+
+ BOOST_CHECK_EQUAL(edge1_2->next == edge2_1, true);
+ BOOST_CHECK_EQUAL(edge2_2->next == edge3_1, true);
+ BOOST_CHECK_EQUAL(edge3_2->next == edge1_1, true);
+
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(beach_line_test2, T, test_types) {
+ typedef typename voronoi_formation<T>::edge_type edge_type;
+ typedef typename voronoi_formation<T>::edge_iterator edge_iterator;
+ typedef typename voronoi_formation<T>::voronoi_vertices_iterator
+ voronoi_vertices_iterator;
+
+ voronoi_formation<T> test_beach_line;
+ point_2d<T> point1 = make_point_2d<T>(0, 1);
+ point_2d<T> point2 = make_point_2d<T>(2, 0);
+ point_2d<T> point3 = make_point_2d<T>(2, 4);
+
+ std::vector< point_2d<T> > points;
+ points.push_back(point1);
+ points.push_back(point2);
+ points.push_back(point3);
+
+ test_beach_line.init(points);
+ test_beach_line.run_sweepline();
+ BOOST_CHECK_EQUAL(test_beach_line.get_cell_records().size(), 3);
+ BOOST_CHECK_EQUAL(test_beach_line.get_voronoi_vertices().size(), 1);
+
+ voronoi_vertices_iterator it = test_beach_line.get_voronoi_vertices().begin();
+ BOOST_CHECK_EQUAL(it->incident_edges.size(), 3);
+ BOOST_CHECK_EQUAL(it->vertex.x() == static_cast<T>(1.75) &&
+ it->vertex.y() == static_cast<T>(2.0), true);
+
+ edge_iterator edge_it = it->incident_edges.begin();
+ edge_type *edge1_1 = *edge_it;
+ edge_type *edge1_2 = edge1_1->twin;
+ BOOST_CHECK_EQUAL(edge1_1->cell_record->site_point == point2, true);
+ BOOST_CHECK_EQUAL(edge1_2->cell_record->site_point == point1, true);
+
+ edge_it++;
+ edge_type *edge2_1 = *edge_it;
+ edge_type *edge2_2 = edge2_1->twin;
+ BOOST_CHECK_EQUAL(edge2_1->cell_record->site_point == point1, true);
+ BOOST_CHECK_EQUAL(edge2_2->cell_record->site_point == point3, true);
+
+ edge_it++;
+ edge_type *edge3_1 = *edge_it;
+ edge_type *edge3_2 = edge3_1->twin;
+ BOOST_CHECK_EQUAL(edge3_1->cell_record->site_point == point3, true);
+ BOOST_CHECK_EQUAL(edge3_2->cell_record->site_point == point2, true);
+
+ BOOST_CHECK_EQUAL(edge1_2->twin == edge1_1, true);
+ BOOST_CHECK_EQUAL(edge2_2->twin == edge2_1, true);
+ BOOST_CHECK_EQUAL(edge3_2->twin == edge3_1, true);
+
+ BOOST_CHECK_EQUAL(edge1_1->next == NULL && edge1_2->prev == NULL, true);
+ BOOST_CHECK_EQUAL(edge2_1->next == NULL && edge2_2->prev == NULL, true);
+ BOOST_CHECK_EQUAL(edge3_1->next == NULL && edge3_2->prev == NULL, true);
+
+ BOOST_CHECK_EQUAL(edge1_1->prev == edge3_2, true);
+ BOOST_CHECK_EQUAL(edge2_1->prev == edge1_2, true);
+ BOOST_CHECK_EQUAL(edge3_1->prev == edge2_2, true);
+
+ BOOST_CHECK_EQUAL(edge1_2->next == edge2_1, true);
+ BOOST_CHECK_EQUAL(edge2_2->next == edge3_1, true);
+ BOOST_CHECK_EQUAL(edge3_2->next == edge1_1, true);
+}
\ No newline at end of file


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