|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r63432 - in sandbox/SOC/2010: . sweepline/boost/sweepline sweepline/boost/sweepline/detail sweepline/libs/sweepline/test
From: sydorchuk.andriy_at_[hidden]
Date: 2010-06-29 10:21:06
Author: asydorchuk
Date: 2010-06-29 10:21:05 EDT (Tue, 29 Jun 2010)
New Revision: 63432
URL: http://svn.boost.org/trac/boost/changeset/63432
Log:
Added output checks: half-edges orientation check, cells convexity check, voronoi vertex incident edges correct ordering, half-edges intersection check.
Properties modified:
sandbox/SOC/2010/ (props changed)
Text files modified:
sandbox/SOC/2010/sweepline/boost/sweepline/detail/voronoi_formation.hpp | 6
sandbox/SOC/2010/sweepline/boost/sweepline/voronoi_builder.hpp | 2
sandbox/SOC/2010/sweepline/boost/sweepline/voronoi_output.hpp | 247 +++++++++++++++++++++++++++++++++++++--
sandbox/SOC/2010/sweepline/libs/sweepline/test/test_type_list.hpp | 4
sandbox/SOC/2010/sweepline/libs/sweepline/test/voronoi_builder_test.cpp | 12 +
5 files changed, 245 insertions(+), 26 deletions(-)
Modified: sandbox/SOC/2010/sweepline/boost/sweepline/detail/voronoi_formation.hpp
==============================================================================
--- sandbox/SOC/2010/sweepline/boost/sweepline/detail/voronoi_formation.hpp (original)
+++ sandbox/SOC/2010/sweepline/boost/sweepline/detail/voronoi_formation.hpp 2010-06-29 10:21:05 EDT (Tue, 29 Jun 2010)
@@ -500,11 +500,7 @@
struct beach_line_node_data {
Edge *edge;
- beach_line_node_data(Edge *new_edge) : edge(new_edge) {}
-
- void change_edge(Edge *new_edge) {
- edge = new_edge;
- }
+ explicit beach_line_node_data(Edge *new_edge) : edge(new_edge) {}
};
template <typename BeachLineNode>
Modified: sandbox/SOC/2010/sweepline/boost/sweepline/voronoi_builder.hpp
==============================================================================
--- sandbox/SOC/2010/sweepline/boost/sweepline/voronoi_builder.hpp (original)
+++ sandbox/SOC/2010/sweepline/boost/sweepline/voronoi_builder.hpp 2010-06-29 10:21:05 EDT (Tue, 29 Jun 2010)
@@ -255,7 +255,7 @@
const_cast<Key &>(it_first->first).set_right_site(site3);
edge_type *edge = output_.insert_new_edge(site1, site2, site3, circle_event,
bisector1.edge, bisector2.edge);
- it_first->second.change_edge(edge);
+ it_first->second.edge = edge;
beach_line_.erase(it_last);
it_last = it_first;
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-29 10:21:05 EDT (Tue, 29 Jun 2010)
@@ -92,6 +92,33 @@
// VORONOI OUTPUT TYPES ///////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
+ // Bounding rectangle data structure.
+ template <typename Point2D>
+ struct BRect {
+ typedef typename Point2D::coordinate_type coordinate_type;
+
+ coordinate_type x_min;
+ coordinate_type y_min;
+ coordinate_type x_max;
+ coordinate_type y_max;
+
+ BRect() {}
+
+ BRect(const Point2D &p1, const Point2D &p2) {
+ x_min = std::min(p1.x(), p2.x());
+ y_min = std::min(p1.y(), p2.y());
+ x_max = std::max(p1.x(), p2.x());
+ y_max = std::max(p1.y(), p2.y());
+ }
+
+ void update(const Point2D &p) {
+ x_min = std::min(x_min, p.x());
+ y_min = std::min(y_min, p.y());
+ x_max = std::max(x_max, p.x());
+ y_max = std::max(y_max, p.y());
+ }
+ };
+
// Cell record data structure. Represents voronoi cell.
// Contains site point pointer to any incident half-edge and number
// of incident half-edges.
@@ -101,7 +128,7 @@
Point2D site_point;
int num_incident_edges;
- cell_record(Point2D site, half_edge<Point2D>* edge) :
+ cell_record(const Point2D &site, half_edge<Point2D>* edge) :
incident_edge(edge),
site_point(site),
num_incident_edges(0) {}
@@ -112,16 +139,22 @@
// number of incident half-edges.
template <typename Point2D>
struct vertex_record {
- typedef typename std::list< half_edge<Point2D>* >::iterator vertex_incident_edges_it;
+ typedef typename std::list< half_edge<Point2D>* >::const_iterator
+ vertex_incident_edges_const_it;
std::list< half_edge<Point2D>* > incident_edges;
Point2D vertex;
int num_incident_edges;
typename std::list< vertex_record<Point2D> >::iterator vertex_it;
- vertex_record(Point2D vertex) : vertex(vertex), num_incident_edges(3) {}
+ vertex_record(const Point2D &vertex) : vertex(vertex), num_incident_edges(3) {}
- vertex_incident_edges_it get_prev_incident_edge(vertex_incident_edges_it it) {
+ bool is_boundary_point() const {
+ return (num_incident_edges == 1);
+ }
+
+ vertex_incident_edges_const_it get_prev_incident_edge(
+ vertex_incident_edges_const_it it) const {
if (it != incident_edges.begin()) {
it--;
return it;
@@ -131,7 +164,8 @@
return it;
}
- vertex_incident_edges_it get_next_incident_edge(vertex_incident_edges_it it) {
+ vertex_incident_edges_const_it get_next_incident_edge(
+ vertex_incident_edges_const_it it) const {
it++;
if (it != incident_edges.end())
return it;
@@ -159,7 +193,7 @@
half_edge_type *twin;
typename std::list< half_edge<Point2D>* >::iterator incident_it;
- half_edge(int site_index) :
+ half_edge() :
cell(NULL),
start_point(NULL),
end_point(NULL),
@@ -174,6 +208,7 @@
template <typename Point2D>
class voronoi_output {
public:
+ typedef typename Point2D::coordinate_type coordinate_type;
typedef typename detail::site_event<Point2D> site_event_type;
typedef typename detail::circle_event<Point2D> circle_event_type;
typedef cell_record<Point2D> cell_record_type;
@@ -187,6 +222,12 @@
typedef typename voronoi_vertices_type::const_iterator
voronoi_vertices_const_iterator_type;
+ enum kOrientation {
+ LEFT_ORIENTATION = 1,
+ RIGHT_ORIENTATION = -1,
+ COLINEAR = 0,
+ };
+
voronoi_output() {
num_cell_records_ = 0;
num_edges_ = 0;
@@ -226,22 +267,24 @@
int site_index2 = site2.get_site_index();
// Create new half-edge that belongs to the cell with the first site.
- edges_.push_back(edge_type(site_index1));
+ edges_.push_back(edge_type());
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));
+ edges_.push_back(edge_type());
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));
num_cell_records_++;
+ voronoi_rect_ = BRect<Point2D>(site1.get_point(), site1.get_point());
}
// 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));
+ voronoi_rect_.update(site2.get_point());
// Update pointers to cells.
edge1.cell = &cell_records_[site_index1];
@@ -266,6 +309,7 @@
edge_type *edge23) {
num_vertex_records_++;
num_edges_++;
+ voronoi_rect_.update(circle.get_center());
// Add new voronoi vertex as voronoi circle center.
vertex_records_.push_back(vertex_record_type(circle.get_center()));
@@ -284,14 +328,14 @@
edge23->twin->end_point = &new_vertex;
// Add new half-edge.
- edges_.push_back(edge_type(site1.get_site_index()));
+ edges_.push_back(edge_type());
edge_type &new_edge1 = edges_.back();
new_edge1.cell = &cell_records_[site1.get_site_index()];
cell_records_[site1.get_site_index()].num_incident_edges++;
new_edge1.end_point = &new_vertex;
// Add new half-edge.
- edges_.push_back(edge_type(site3.get_site_index()));
+ edges_.push_back(edge_type());
edge_type &new_edge2 = edges_.back();
new_edge2.cell = &cell_records_[site3.get_site_index()];
cell_records_[site3.get_site_index()].num_incident_edges++;
@@ -312,7 +356,7 @@
// Update voronoi vertex incident edges pointers.
new_vertex.incident_edges.push_back(edge12);
- typename std::list<edge_type*>::iterator temp_iter =new_vertex.incident_edges.begin();
+ edge_pointer_iterator_type temp_iter =new_vertex.incident_edges.begin();
edge12->incident_it = temp_iter;
new_vertex.incident_edges.push_back(edge23);
@@ -346,6 +390,10 @@
return num_edges_;
}
+ const BRect<Point2D> &get_voronoi_bounding_rectangle() const {
+ return voronoi_rect_;
+ }
+
void simplify() {
typename std::list<edge_type>::iterator edge_it1;
typename std::list<edge_type>::iterator edge_it = edges_.begin();
@@ -382,10 +430,136 @@
}
}
- bool check() {
+ bool check() const {
+ // Check correct orientation of each half_edge.
+ typename std::list<edge_type>::const_iterator edge_it;
+ for (edge_it = edges_.begin(); edge_it != edges_.end(); edge_it++) {
+ const Point2D &site = edge_it->cell->site_point;
+ if (edge_it->start_point != NULL && edge_it->end_point != NULL) {
+ const Point2D &start_point = edge_it->start_point->vertex;
+ const Point2D &end_point = edge_it->end_point->vertex;
+ if (check_orientation(start_point, end_point, site) != LEFT_ORIENTATION)
+ return false;
+ }
+ }
+
+ // Check if each site belongs to convex cell.
+ typename cell_records_type::const_iterator cell_it;
+ for (cell_it = cell_records_.begin(); cell_it != cell_records_.end(); cell_it++) {
+ const edge_type *edge = cell_it->incident_edge;
+
+ if (edge->start_point != NULL)
+ edge = edge->prev;
+ while (edge->start_point != NULL && edge != cell_it->incident_edge)
+ edge = edge->prev;
+ if (edge->start_point != NULL)
+ edge = edge->next;
+
+ while (edge->end_point != NULL && edge != cell_it->incident_edge) {
+ if (edge->next->prev != edge)
+ return false;
+ if (edge->cell != &(*cell_it))
+ return false;
+ if (edge->start_point != NULL && edge->next->end_point != NULL) {
+ const Point2D &vertex1 = edge->start_point->vertex;
+ const Point2D &vertex2 = edge->end_point->vertex;
+ const Point2D &vertex3 = edge->next->end_point->vertex;
+ if (check_orientation(vertex1, vertex2, vertex3) != LEFT_ORIENTATION)
+ return false;
+ }
+ edge = edge->next;
+ }
+ }
+
+ // Check voronoi vertex incident edges correct ordering.
+ voronoi_vertices_const_iterator_type vertex_it;
+ for (vertex_it = vertex_records_.begin();
+ vertex_it != vertex_records_.end(); vertex_it++) {
+ edge_pointer_const_iterator_type edge_it;
+ for (edge_it = vertex_it->incident_edges.begin();
+ edge_it != vertex_it->incident_edges.end(); edge_it++) {
+ edge_pointer_const_iterator_type edge_it_next1 =
+ vertex_it->get_next_incident_edge(edge_it);
+ edge_pointer_const_iterator_type edge_it_next2 =
+ vertex_it->get_next_incident_edge(edge_it_next1);
+ const Point2D &site1 = (*edge_it)->cell->site_point;
+ const Point2D &site2 = (*edge_it_next1)->cell->site_point;
+ const Point2D &site3 = (*edge_it_next2)->cell->site_point;
+ if (check_orientation(site3, site2, site1) != LEFT_ORIENTATION)
+ return false;
+ }
+ }
+
+ // Check if any two half_edges intersect not at the end point.
+ // Create map from edges with first point less than the second one.
+ // Key is the first point of the edges, value is vector of second points
+ // with the same first point.
+ std::map< Point2D, std::vector<Point2D> > edge_map;
+ typedef typename std::map< Point2D, std::vector<Point2D> >::const_iterator
+ edge_map_iterator;
+ for (edge_it = edges_.begin(); edge_it != edges_.end(); edge_it++) {
+ if (edge_it->start_point != NULL && edge_it->end_point != NULL) {
+ const Point2D &start_point = edge_it->start_point->vertex;
+ const Point2D &end_point = edge_it->end_point->vertex;
+ if (start_point < end_point)
+ edge_map[start_point].push_back(end_point);
+ }
+ }
+
+ // Iterate over map of edges and check if there are any intersections.
+ // All the edges are stored by the low x value. That's why we iterate
+ // left to right checking for intersections between all pairs of edges
+ // that overlap in the x dimension.
+ // Complexity. Approximately N*sqrt(N). Worst case N^2.
+ edge_map_iterator edge_map_it1, edge_map_it2, edge_map_it_bound;
+ for (edge_map_it1 = edge_map.begin();
+ edge_map_it1 != edge_map.end(); edge_map_it1++) {
+ const Point2D &point1 = edge_map_it1->first;
+
+ typedef typename std::vector<Point2D>::size_type size_type;
+ for (size_type i = 0; i < edge_map_it1->second.size(); i++) {
+ const Point2D &point2 = edge_map_it1->second[i];
+ coordinate_type min_y1 = std::min(point1.y(), point2.y());
+ coordinate_type max_y1 = std::max(point1.y(), point2.y());
+
+ // Find the first edge with greate or equal first point.
+ edge_map_it_bound = edge_map.lower_bound(point2);
+
+ edge_map_it2 = edge_map_it1;
+ edge_map_it2++;
+ for (; edge_map_it2 != edge_map_it_bound; edge_map_it2++) {
+ const Point2D &point3 = edge_map_it2->first;
+
+ for (size_type j = 0; j < edge_map_it2->second.size(); j++) {
+ const Point2D &point4 = edge_map_it2->second[j];
+ coordinate_type min_y2 = std::min(point3.y(), point4.y());
+ coordinate_type max_y2 = std::max(point3.y(), point4.y());
+
+ // In most cases it is enought to make
+ // simple intersection check in the y dimension.
+ if (!(max_y1 > min_y2 && max_y2 > min_y1))
+ continue;
+
+ // Intersection check.
+ if (check_orientation(point1, point2, point3) *
+ check_orientation(point1, point2, point4) == -1 &&
+ check_orientation(point3, point4, point1) *
+ check_orientation(point3, point4, point2) == -1)
+ return false;
+ }
+ }
+ }
+ }
+
return true;
}
+ void clip(coordinate_type x_min, coordinate_type y_min,
+ coordinate_type x_max, coordinate_type y_max) {
+
+
+ }
+
private:
void simplify_edge(edge_type &edge) {
vertex_record_type *vertex1 = edge.start_point;
@@ -406,11 +580,15 @@
edge_pointer_iterator_type edge1_it = edge.incident_it;
edge_pointer_iterator_type edge2_it = edge.twin->incident_it;
- edge_pointer_iterator_type edge1_it_prev = vertex1->get_prev_incident_edge(edge1_it);
- edge_pointer_iterator_type edge1_it_next = vertex1->get_next_incident_edge(edge1_it);
-
- edge_pointer_iterator_type edge2_it_prev = vertex2->get_prev_incident_edge(edge2_it);
- edge_pointer_iterator_type edge2_it_next = vertex2->get_next_incident_edge(edge2_it);
+ edge_pointer_const_iterator_type edge1_it_prev =
+ vertex1->get_prev_incident_edge(edge1_it);
+ edge_pointer_const_iterator_type edge1_it_next =
+ vertex1->get_next_incident_edge(edge1_it);
+
+ edge_pointer_const_iterator_type edge2_it_prev =
+ vertex2->get_prev_incident_edge(edge2_it);
+ edge_pointer_const_iterator_type edge2_it_next =
+ vertex2->get_next_incident_edge(edge2_it);
(*edge1_it_prev)->twin->next = *edge2_it_next;
(*edge2_it_next)->prev = (*edge1_it_prev)->twin;
@@ -434,6 +612,18 @@
vertex_records_.erase(vertex2->vertex_it);
}
+ int check_orientation(const Point2D &point1,
+ const Point2D &point2,
+ const Point2D &point3) const {
+ coordinate_type a = (point2.x() - point1.x()) * (point3.y() - point2.y());
+ coordinate_type b = (point2.y() - point1.y()) * (point3.x() - point2.x());
+ if (a > b)
+ return LEFT_ORIENTATION;
+ else if (a < b)
+ return RIGHT_ORIENTATION;
+ return COLINEAR;
+ }
+
std::vector<cell_record_type> cell_records_;
std::list<vertex_record_type> vertex_records_;
std::list<edge_type> edges_;
@@ -442,11 +632,32 @@
int num_vertex_records_;
int num_edges_;
- //Disallow copy constructor and operator=
+ BRect<Point2D> voronoi_rect_;
+
+ // Disallow copy constructor and operator=
voronoi_output(const voronoi_output&);
void operator=(const voronoi_output&);
};
+ template <typename Point2D>
+ class voronoi_output_clipped {
+ public:
+ typedef typename Point2D::coordinate_type coordinate_type;
+
+ voronoi_output_clipped(const Point2D &p1, const Point2D &p2) : brect_(p1, p2) {}
+
+ void clip(const voronoi_output<Point2D> &output) {
+
+ }
+
+ private:
+ BRect<Point2D> brect_;
+
+ // Disallow copy constructor and operator=
+ voronoi_output_clipped(const voronoi_output_clipped&);
+ void operator=(const voronoi_output_clipped&);
+ };
+
} // sweepline
} // boost
Modified: sandbox/SOC/2010/sweepline/libs/sweepline/test/test_type_list.hpp
==============================================================================
--- sandbox/SOC/2010/sweepline/libs/sweepline/test/test_type_list.hpp (original)
+++ sandbox/SOC/2010/sweepline/libs/sweepline/test/test_type_list.hpp 2010-06-29 10:21:05 EDT (Tue, 29 Jun 2010)
@@ -12,8 +12,8 @@
#include <boost/mpl/list.hpp>
-typedef boost::mpl::list<//float,
- //double,
+typedef boost::mpl::list<float,
+ double,
long double> test_types;
#endif
Modified: sandbox/SOC/2010/sweepline/libs/sweepline/test/voronoi_builder_test.cpp
==============================================================================
--- sandbox/SOC/2010/sweepline/libs/sweepline/test/voronoi_builder_test.cpp (original)
+++ sandbox/SOC/2010/sweepline/libs/sweepline/test/voronoi_builder_test.cpp 2010-06-29 10:21:05 EDT (Tue, 29 Jun 2010)
@@ -38,6 +38,7 @@
test_beach_line.init(points);
test_beach_line.run_sweepline();
const voronoi_output< point_2d<T> > &test_output = test_beach_line.get_output();
+ BOOST_CHECK_EQUAL(test_output.check(), true);
BOOST_CHECK_EQUAL(static_cast<int>(test_output.get_cell_records().size()), 3);
BOOST_CHECK_EQUAL(static_cast<int>(test_output.get_voronoi_vertices().size()), 1);
@@ -104,6 +105,7 @@
test_beach_line.init(points);
test_beach_line.run_sweepline();
const voronoi_output< point_2d<T> > &test_output = test_beach_line.get_output();
+ BOOST_CHECK_EQUAL(test_output.check(), true);
BOOST_CHECK_EQUAL(static_cast<int>(test_output.get_cell_records().size()), 3);
BOOST_CHECK_EQUAL(static_cast<int>(test_output.get_voronoi_vertices().size()), 1);
@@ -166,6 +168,7 @@
test_beach_line.init(points);
test_beach_line.run_sweepline();
const voronoi_output< point_2d<T> > &test_output = test_beach_line.get_output();
+ BOOST_CHECK_EQUAL(test_output.check(), true);
BOOST_CHECK_EQUAL(static_cast<T>(test_output.get_cell_records().size()), 4);
BOOST_CHECK_EQUAL(static_cast<T>(test_output.get_voronoi_vertices().size()), 1);
@@ -239,6 +242,7 @@
test_beach_line.init(points);
test_beach_line.run_sweepline();
const voronoi_output< point_2d<T> > &test_output = test_beach_line.get_output();
+ BOOST_CHECK_EQUAL(test_output.check(), true);
BOOST_CHECK_EQUAL(test_output.get_num_voronoi_cells(), 9);
BOOST_CHECK_EQUAL(test_output.get_num_voronoi_vertices(), 4);
@@ -262,6 +266,7 @@
test_beach_line.init(points);
test_beach_line.run_sweepline();
+ BOOST_CHECK_EQUAL(test_beach_line.get_output().check(), true);
}
// Sites: {(x, y) | x = 0 .. 9, y = 0 .. 9}.
@@ -276,6 +281,7 @@
test_beach_line.init(points);
test_beach_line.run_sweepline();
const voronoi_output< point_2d<T> > &test_output = test_beach_line.get_output();
+ BOOST_CHECK_EQUAL(test_output.check(), true);
BOOST_CHECK_EQUAL(test_output.get_num_voronoi_cells(), 100);
BOOST_CHECK_EQUAL(test_output.get_num_voronoi_vertices(), 81);
@@ -299,6 +305,7 @@
test_beach_line.init(points);
test_beach_line.run_sweepline();
+ BOOST_CHECK_EQUAL(test_beach_line.get_output().check(), true);
}
// Sites: {(x, y) | x = 0 .. 33, y = 0 .. 33}.
@@ -313,6 +320,7 @@
test_beach_line.init(points);
test_beach_line.run_sweepline();
const voronoi_output< point_2d<T> > &test_output = test_beach_line.get_output();
+ BOOST_CHECK_EQUAL(test_output.check(), true);
BOOST_CHECK_EQUAL(test_output.get_num_voronoi_cells(), 1089);
BOOST_CHECK_EQUAL(test_output.get_num_voronoi_vertices(), 1024);
@@ -336,6 +344,7 @@
test_beach_line.init(points);
test_beach_line.run_sweepline();
+ BOOST_CHECK_EQUAL(test_beach_line.get_output().check(), true);
}
// Sites: {(x, y) | x = 0 .. 100, y = 0 .. 100}.
@@ -350,6 +359,7 @@
test_beach_line.init(points);
test_beach_line.run_sweepline();
const voronoi_output< point_2d<T> > &test_output = test_beach_line.get_output();
+ BOOST_CHECK_EQUAL(test_output.check(), true);
BOOST_CHECK_EQUAL(test_output.get_num_voronoi_cells(), 10000);
BOOST_CHECK_EQUAL(test_output.get_num_voronoi_vertices(), 9801);
@@ -367,6 +377,7 @@
test_beach_line.init(points);
test_beach_line.run_sweepline();
+ BOOST_CHECK_EQUAL(test_beach_line.get_output().check(), true);
}
// Sites: {(x, y) | x = 0 .. 333, y = 0 .. 333}.
@@ -381,6 +392,7 @@
test_beach_line.init(points);
test_beach_line.run_sweepline();
const voronoi_output< point_2d<T> > &test_output = test_beach_line.get_output();
+ BOOST_CHECK_EQUAL(test_output.check(), true);
BOOST_CHECK_EQUAL(test_output.get_num_voronoi_cells(), 110889);
BOOST_CHECK_EQUAL(test_output.get_num_voronoi_vertices(), 110224);
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