annotate DEPENDENCIES/generic/include/boost/polygon/voronoi_diagram.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents 2665513ce2d3
children
rev   line source
Chris@16 1 // Boost.Polygon library voronoi_diagram.hpp header file
Chris@16 2
Chris@16 3 // Copyright Andrii Sydorchuk 2010-2012.
Chris@16 4 // Distributed under the Boost Software License, Version 1.0.
Chris@16 5 // (See accompanying file LICENSE_1_0.txt or copy at
Chris@16 6 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 7
Chris@16 8 // See http://www.boost.org for updates, documentation, and revision history.
Chris@16 9
Chris@16 10 #ifndef BOOST_POLYGON_VORONOI_DIAGRAM
Chris@16 11 #define BOOST_POLYGON_VORONOI_DIAGRAM
Chris@16 12
Chris@16 13 #include <vector>
Chris@16 14 #include <utility>
Chris@16 15
Chris@16 16 #include "detail/voronoi_ctypes.hpp"
Chris@16 17 #include "detail/voronoi_structures.hpp"
Chris@16 18
Chris@16 19 #include "voronoi_geometry_type.hpp"
Chris@16 20
Chris@16 21 namespace boost {
Chris@16 22 namespace polygon {
Chris@16 23
Chris@16 24 // Forward declarations.
Chris@16 25 template <typename T>
Chris@16 26 class voronoi_edge;
Chris@16 27
Chris@16 28 // Represents Voronoi cell.
Chris@16 29 // Data members:
Chris@16 30 // 1) index of the source within the initial input set
Chris@16 31 // 2) pointer to the incident edge
Chris@16 32 // 3) mutable color member
Chris@16 33 // Cell may contain point or segment site inside.
Chris@16 34 template <typename T>
Chris@16 35 class voronoi_cell {
Chris@16 36 public:
Chris@16 37 typedef T coordinate_type;
Chris@16 38 typedef std::size_t color_type;
Chris@16 39 typedef voronoi_edge<coordinate_type> voronoi_edge_type;
Chris@16 40 typedef std::size_t source_index_type;
Chris@16 41 typedef SourceCategory source_category_type;
Chris@16 42
Chris@16 43 voronoi_cell(source_index_type source_index,
Chris@16 44 source_category_type source_category) :
Chris@16 45 source_index_(source_index),
Chris@16 46 incident_edge_(NULL),
Chris@16 47 color_(source_category) {}
Chris@16 48
Chris@16 49 // Returns true if the cell contains point site, false else.
Chris@16 50 bool contains_point() const {
Chris@16 51 source_category_type source_category = this->source_category();
Chris@16 52 return belongs(source_category, GEOMETRY_CATEGORY_POINT);
Chris@16 53 }
Chris@16 54
Chris@16 55 // Returns true if the cell contains segment site, false else.
Chris@16 56 bool contains_segment() const {
Chris@16 57 source_category_type source_category = this->source_category();
Chris@16 58 return belongs(source_category, GEOMETRY_CATEGORY_SEGMENT);
Chris@16 59 }
Chris@16 60
Chris@16 61 source_index_type source_index() const {
Chris@16 62 return source_index_;
Chris@16 63 }
Chris@16 64
Chris@16 65 source_category_type source_category() const {
Chris@16 66 return static_cast<source_category_type>(color_ & SOURCE_CATEGORY_BITMASK);
Chris@16 67 }
Chris@16 68
Chris@16 69 // Degenerate cells don't have any incident edges.
Chris@16 70 bool is_degenerate() const { return incident_edge_ == NULL; }
Chris@16 71
Chris@16 72 voronoi_edge_type* incident_edge() { return incident_edge_; }
Chris@16 73 const voronoi_edge_type* incident_edge() const { return incident_edge_; }
Chris@16 74 void incident_edge(voronoi_edge_type* e) { incident_edge_ = e; }
Chris@16 75
Chris@16 76 color_type color() const { return color_ >> BITS_SHIFT; }
Chris@16 77 void color(color_type color) const {
Chris@16 78 color_ &= BITS_MASK;
Chris@16 79 color_ |= color << BITS_SHIFT;
Chris@16 80 }
Chris@16 81
Chris@16 82 private:
Chris@16 83 // 5 color bits are reserved.
Chris@16 84 enum Bits {
Chris@16 85 BITS_SHIFT = 0x5,
Chris@16 86 BITS_MASK = 0x1F
Chris@16 87 };
Chris@16 88
Chris@16 89 source_index_type source_index_;
Chris@16 90 voronoi_edge_type* incident_edge_;
Chris@16 91 mutable color_type color_;
Chris@16 92 };
Chris@16 93
Chris@16 94 // Represents Voronoi vertex.
Chris@16 95 // Data members:
Chris@16 96 // 1) vertex coordinates
Chris@16 97 // 2) pointer to the incident edge
Chris@16 98 // 3) mutable color member
Chris@16 99 template <typename T>
Chris@16 100 class voronoi_vertex {
Chris@16 101 public:
Chris@16 102 typedef T coordinate_type;
Chris@16 103 typedef std::size_t color_type;
Chris@16 104 typedef voronoi_edge<coordinate_type> voronoi_edge_type;
Chris@16 105
Chris@16 106 voronoi_vertex(const coordinate_type& x, const coordinate_type& y) :
Chris@16 107 x_(x),
Chris@16 108 y_(y),
Chris@16 109 incident_edge_(NULL),
Chris@16 110 color_(0) {}
Chris@16 111
Chris@16 112 const coordinate_type& x() const { return x_; }
Chris@16 113 const coordinate_type& y() const { return y_; }
Chris@16 114
Chris@16 115 bool is_degenerate() const { return incident_edge_ == NULL; }
Chris@16 116
Chris@16 117 voronoi_edge_type* incident_edge() { return incident_edge_; }
Chris@16 118 const voronoi_edge_type* incident_edge() const { return incident_edge_; }
Chris@16 119 void incident_edge(voronoi_edge_type* e) { incident_edge_ = e; }
Chris@16 120
Chris@16 121 color_type color() const { return color_ >> BITS_SHIFT; }
Chris@16 122 void color(color_type color) const {
Chris@16 123 color_ &= BITS_MASK;
Chris@16 124 color_ |= color << BITS_SHIFT;
Chris@16 125 }
Chris@16 126
Chris@16 127 private:
Chris@16 128 // 5 color bits are reserved.
Chris@16 129 enum Bits {
Chris@16 130 BITS_SHIFT = 0x5,
Chris@16 131 BITS_MASK = 0x1F
Chris@16 132 };
Chris@16 133
Chris@16 134 coordinate_type x_;
Chris@16 135 coordinate_type y_;
Chris@16 136 voronoi_edge_type* incident_edge_;
Chris@16 137 mutable color_type color_;
Chris@16 138 };
Chris@16 139
Chris@16 140 // Half-edge data structure. Represents Voronoi edge.
Chris@16 141 // Data members:
Chris@16 142 // 1) pointer to the corresponding cell
Chris@16 143 // 2) pointer to the vertex that is the starting
Chris@16 144 // point of the half-edge
Chris@16 145 // 3) pointer to the twin edge
Chris@16 146 // 4) pointer to the CCW next edge
Chris@16 147 // 5) pointer to the CCW prev edge
Chris@16 148 // 6) mutable color member
Chris@16 149 template <typename T>
Chris@16 150 class voronoi_edge {
Chris@16 151 public:
Chris@16 152 typedef T coordinate_type;
Chris@16 153 typedef voronoi_cell<coordinate_type> voronoi_cell_type;
Chris@16 154 typedef voronoi_vertex<coordinate_type> voronoi_vertex_type;
Chris@16 155 typedef voronoi_edge<coordinate_type> voronoi_edge_type;
Chris@16 156 typedef std::size_t color_type;
Chris@16 157
Chris@16 158 voronoi_edge(bool is_linear, bool is_primary) :
Chris@16 159 cell_(NULL),
Chris@16 160 vertex_(NULL),
Chris@16 161 twin_(NULL),
Chris@16 162 next_(NULL),
Chris@16 163 prev_(NULL),
Chris@16 164 color_(0) {
Chris@16 165 if (is_linear)
Chris@16 166 color_ |= BIT_IS_LINEAR;
Chris@16 167 if (is_primary)
Chris@16 168 color_ |= BIT_IS_PRIMARY;
Chris@16 169 }
Chris@16 170
Chris@16 171 voronoi_cell_type* cell() { return cell_; }
Chris@16 172 const voronoi_cell_type* cell() const { return cell_; }
Chris@16 173 void cell(voronoi_cell_type* c) { cell_ = c; }
Chris@16 174
Chris@16 175 voronoi_vertex_type* vertex0() { return vertex_; }
Chris@16 176 const voronoi_vertex_type* vertex0() const { return vertex_; }
Chris@16 177 void vertex0(voronoi_vertex_type* v) { vertex_ = v; }
Chris@16 178
Chris@16 179 voronoi_vertex_type* vertex1() { return twin_->vertex0(); }
Chris@16 180 const voronoi_vertex_type* vertex1() const { return twin_->vertex0(); }
Chris@16 181
Chris@16 182 voronoi_edge_type* twin() { return twin_; }
Chris@16 183 const voronoi_edge_type* twin() const { return twin_; }
Chris@16 184 void twin(voronoi_edge_type* e) { twin_ = e; }
Chris@16 185
Chris@16 186 voronoi_edge_type* next() { return next_; }
Chris@16 187 const voronoi_edge_type* next() const { return next_; }
Chris@16 188 void next(voronoi_edge_type* e) { next_ = e; }
Chris@16 189
Chris@16 190 voronoi_edge_type* prev() { return prev_; }
Chris@16 191 const voronoi_edge_type* prev() const { return prev_; }
Chris@16 192 void prev(voronoi_edge_type* e) { prev_ = e; }
Chris@16 193
Chris@16 194 // Returns a pointer to the rotation next edge
Chris@16 195 // over the starting point of the half-edge.
Chris@16 196 voronoi_edge_type* rot_next() { return prev_->twin(); }
Chris@16 197 const voronoi_edge_type* rot_next() const { return prev_->twin(); }
Chris@16 198
Chris@16 199 // Returns a pointer to the rotation prev edge
Chris@16 200 // over the starting point of the half-edge.
Chris@16 201 voronoi_edge_type* rot_prev() { return twin_->next(); }
Chris@16 202 const voronoi_edge_type* rot_prev() const { return twin_->next(); }
Chris@16 203
Chris@16 204 // Returns true if the edge is finite (segment, parabolic arc).
Chris@16 205 // Returns false if the edge is infinite (ray, line).
Chris@16 206 bool is_finite() const { return vertex0() && vertex1(); }
Chris@16 207
Chris@16 208 // Returns true if the edge is infinite (ray, line).
Chris@16 209 // Returns false if the edge is finite (segment, parabolic arc).
Chris@16 210 bool is_infinite() const { return !vertex0() || !vertex1(); }
Chris@16 211
Chris@16 212 // Returns true if the edge is linear (segment, ray, line).
Chris@16 213 // Returns false if the edge is curved (parabolic arc).
Chris@16 214 bool is_linear() const {
Chris@16 215 return (color_ & BIT_IS_LINEAR) ? true : false;
Chris@16 216 }
Chris@16 217
Chris@16 218 // Returns true if the edge is curved (parabolic arc).
Chris@16 219 // Returns false if the edge is linear (segment, ray, line).
Chris@16 220 bool is_curved() const {
Chris@16 221 return (color_ & BIT_IS_LINEAR) ? false : true;
Chris@16 222 }
Chris@16 223
Chris@16 224 // Returns false if edge goes through the endpoint of the segment.
Chris@16 225 // Returns true else.
Chris@16 226 bool is_primary() const {
Chris@16 227 return (color_ & BIT_IS_PRIMARY) ? true : false;
Chris@16 228 }
Chris@16 229
Chris@16 230 // Returns true if edge goes through the endpoint of the segment.
Chris@16 231 // Returns false else.
Chris@16 232 bool is_secondary() const {
Chris@16 233 return (color_ & BIT_IS_PRIMARY) ? false : true;
Chris@16 234 }
Chris@16 235
Chris@16 236 color_type color() const { return color_ >> BITS_SHIFT; }
Chris@16 237 void color(color_type color) const {
Chris@16 238 color_ &= BITS_MASK;
Chris@16 239 color_ |= color << BITS_SHIFT;
Chris@16 240 }
Chris@16 241
Chris@16 242 private:
Chris@16 243 // 5 color bits are reserved.
Chris@16 244 enum Bits {
Chris@16 245 BIT_IS_LINEAR = 0x1, // linear is opposite to curved
Chris@16 246 BIT_IS_PRIMARY = 0x2, // primary is opposite to secondary
Chris@16 247
Chris@16 248 BITS_SHIFT = 0x5,
Chris@16 249 BITS_MASK = 0x1F
Chris@16 250 };
Chris@16 251
Chris@16 252 voronoi_cell_type* cell_;
Chris@16 253 voronoi_vertex_type* vertex_;
Chris@16 254 voronoi_edge_type* twin_;
Chris@16 255 voronoi_edge_type* next_;
Chris@16 256 voronoi_edge_type* prev_;
Chris@16 257 mutable color_type color_;
Chris@16 258 };
Chris@16 259
Chris@16 260 template <typename T>
Chris@16 261 struct voronoi_diagram_traits {
Chris@16 262 typedef T coordinate_type;
Chris@16 263 typedef voronoi_cell<coordinate_type> cell_type;
Chris@16 264 typedef voronoi_vertex<coordinate_type> vertex_type;
Chris@16 265 typedef voronoi_edge<coordinate_type> edge_type;
Chris@16 266 typedef class {
Chris@16 267 public:
Chris@16 268 enum { ULPS = 128 };
Chris@16 269 bool operator()(const vertex_type& v1, const vertex_type& v2) const {
Chris@16 270 return (ulp_cmp(v1.x(), v2.x(), ULPS) ==
Chris@16 271 detail::ulp_comparison<T>::EQUAL) &&
Chris@16 272 (ulp_cmp(v1.y(), v2.y(), ULPS) ==
Chris@16 273 detail::ulp_comparison<T>::EQUAL);
Chris@16 274 }
Chris@16 275 private:
Chris@16 276 typename detail::ulp_comparison<T> ulp_cmp;
Chris@16 277 } vertex_equality_predicate_type;
Chris@16 278 };
Chris@16 279
Chris@16 280 // Voronoi output data structure.
Chris@16 281 // CCW ordering is used on the faces perimeter and around the vertices.
Chris@16 282 template <typename T, typename TRAITS = voronoi_diagram_traits<T> >
Chris@16 283 class voronoi_diagram {
Chris@16 284 public:
Chris@16 285 typedef typename TRAITS::coordinate_type coordinate_type;
Chris@16 286 typedef typename TRAITS::cell_type cell_type;
Chris@16 287 typedef typename TRAITS::vertex_type vertex_type;
Chris@16 288 typedef typename TRAITS::edge_type edge_type;
Chris@16 289
Chris@16 290 typedef std::vector<cell_type> cell_container_type;
Chris@16 291 typedef typename cell_container_type::const_iterator const_cell_iterator;
Chris@16 292
Chris@16 293 typedef std::vector<vertex_type> vertex_container_type;
Chris@16 294 typedef typename vertex_container_type::const_iterator const_vertex_iterator;
Chris@16 295
Chris@16 296 typedef std::vector<edge_type> edge_container_type;
Chris@16 297 typedef typename edge_container_type::const_iterator const_edge_iterator;
Chris@16 298
Chris@16 299 voronoi_diagram() {}
Chris@16 300
Chris@16 301 void clear() {
Chris@16 302 cells_.clear();
Chris@16 303 vertices_.clear();
Chris@16 304 edges_.clear();
Chris@16 305 }
Chris@16 306
Chris@16 307 const cell_container_type& cells() const {
Chris@16 308 return cells_;
Chris@16 309 }
Chris@16 310
Chris@16 311 const vertex_container_type& vertices() const {
Chris@16 312 return vertices_;
Chris@16 313 }
Chris@16 314
Chris@16 315 const edge_container_type& edges() const {
Chris@16 316 return edges_;
Chris@16 317 }
Chris@16 318
Chris@16 319 std::size_t num_cells() const {
Chris@16 320 return cells_.size();
Chris@16 321 }
Chris@16 322
Chris@16 323 std::size_t num_edges() const {
Chris@16 324 return edges_.size();
Chris@16 325 }
Chris@16 326
Chris@16 327 std::size_t num_vertices() const {
Chris@16 328 return vertices_.size();
Chris@16 329 }
Chris@16 330
Chris@16 331 void _reserve(std::size_t num_sites) {
Chris@16 332 cells_.reserve(num_sites);
Chris@16 333 vertices_.reserve(num_sites << 1);
Chris@16 334 edges_.reserve((num_sites << 2) + (num_sites << 1));
Chris@16 335 }
Chris@16 336
Chris@16 337 template <typename CT>
Chris@16 338 void _process_single_site(const detail::site_event<CT>& site) {
Chris@16 339 cells_.push_back(cell_type(site.initial_index(), site.source_category()));
Chris@16 340 }
Chris@16 341
Chris@16 342 // Insert a new half-edge into the output data structure.
Chris@16 343 // Takes as input left and right sites that form a new bisector.
Chris@16 344 // Returns a pair of pointers to a new half-edges.
Chris@16 345 template <typename CT>
Chris@16 346 std::pair<void*, void*> _insert_new_edge(
Chris@16 347 const detail::site_event<CT>& site1,
Chris@16 348 const detail::site_event<CT>& site2) {
Chris@16 349 // Get sites' indexes.
Chris@16 350 int site_index1 = site1.sorted_index();
Chris@16 351 int site_index2 = site2.sorted_index();
Chris@16 352
Chris@16 353 bool is_linear = is_linear_edge(site1, site2);
Chris@16 354 bool is_primary = is_primary_edge(site1, site2);
Chris@16 355
Chris@16 356 // Create a new half-edge that belongs to the first site.
Chris@16 357 edges_.push_back(edge_type(is_linear, is_primary));
Chris@16 358 edge_type& edge1 = edges_.back();
Chris@16 359
Chris@16 360 // Create a new half-edge that belongs to the second site.
Chris@16 361 edges_.push_back(edge_type(is_linear, is_primary));
Chris@16 362 edge_type& edge2 = edges_.back();
Chris@16 363
Chris@16 364 // Add the initial cell during the first edge insertion.
Chris@16 365 if (cells_.empty()) {
Chris@16 366 cells_.push_back(cell_type(
Chris@16 367 site1.initial_index(), site1.source_category()));
Chris@16 368 }
Chris@16 369
Chris@16 370 // The second site represents a new site during site event
Chris@16 371 // processing. Add a new cell to the cell records.
Chris@16 372 cells_.push_back(cell_type(
Chris@16 373 site2.initial_index(), site2.source_category()));
Chris@16 374
Chris@16 375 // Set up pointers to cells.
Chris@16 376 edge1.cell(&cells_[site_index1]);
Chris@16 377 edge2.cell(&cells_[site_index2]);
Chris@16 378
Chris@16 379 // Set up twin pointers.
Chris@16 380 edge1.twin(&edge2);
Chris@16 381 edge2.twin(&edge1);
Chris@16 382
Chris@16 383 // Return a pointer to the new half-edge.
Chris@16 384 return std::make_pair(&edge1, &edge2);
Chris@16 385 }
Chris@16 386
Chris@16 387 // Insert a new half-edge into the output data structure with the
Chris@16 388 // start at the point where two previously added half-edges intersect.
Chris@16 389 // Takes as input two sites that create a new bisector, circle event
Chris@16 390 // that corresponds to the intersection point of the two old half-edges,
Chris@16 391 // pointers to those half-edges. Half-edges' direction goes out of the
Chris@16 392 // new Voronoi vertex point. Returns a pair of pointers to a new half-edges.
Chris@16 393 template <typename CT1, typename CT2>
Chris@16 394 std::pair<void*, void*> _insert_new_edge(
Chris@16 395 const detail::site_event<CT1>& site1,
Chris@16 396 const detail::site_event<CT1>& site3,
Chris@16 397 const detail::circle_event<CT2>& circle,
Chris@16 398 void* data12, void* data23) {
Chris@16 399 edge_type* edge12 = static_cast<edge_type*>(data12);
Chris@16 400 edge_type* edge23 = static_cast<edge_type*>(data23);
Chris@16 401
Chris@16 402 // Add a new Voronoi vertex.
Chris@16 403 vertices_.push_back(vertex_type(circle.x(), circle.y()));
Chris@16 404 vertex_type& new_vertex = vertices_.back();
Chris@16 405
Chris@16 406 // Update vertex pointers of the old edges.
Chris@16 407 edge12->vertex0(&new_vertex);
Chris@16 408 edge23->vertex0(&new_vertex);
Chris@16 409
Chris@16 410 bool is_linear = is_linear_edge(site1, site3);
Chris@16 411 bool is_primary = is_primary_edge(site1, site3);
Chris@16 412
Chris@16 413 // Add a new half-edge.
Chris@16 414 edges_.push_back(edge_type(is_linear, is_primary));
Chris@16 415 edge_type& new_edge1 = edges_.back();
Chris@16 416 new_edge1.cell(&cells_[site1.sorted_index()]);
Chris@16 417
Chris@16 418 // Add a new half-edge.
Chris@16 419 edges_.push_back(edge_type(is_linear, is_primary));
Chris@16 420 edge_type& new_edge2 = edges_.back();
Chris@16 421 new_edge2.cell(&cells_[site3.sorted_index()]);
Chris@16 422
Chris@16 423 // Update twin pointers.
Chris@16 424 new_edge1.twin(&new_edge2);
Chris@16 425 new_edge2.twin(&new_edge1);
Chris@16 426
Chris@16 427 // Update vertex pointer.
Chris@16 428 new_edge2.vertex0(&new_vertex);
Chris@16 429
Chris@16 430 // Update Voronoi prev/next pointers.
Chris@16 431 edge12->prev(&new_edge1);
Chris@16 432 new_edge1.next(edge12);
Chris@16 433 edge12->twin()->next(edge23);
Chris@16 434 edge23->prev(edge12->twin());
Chris@16 435 edge23->twin()->next(&new_edge2);
Chris@16 436 new_edge2.prev(edge23->twin());
Chris@16 437
Chris@16 438 // Return a pointer to the new half-edge.
Chris@16 439 return std::make_pair(&new_edge1, &new_edge2);
Chris@16 440 }
Chris@16 441
Chris@16 442 void _build() {
Chris@16 443 // Remove degenerate edges.
Chris@16 444 edge_iterator last_edge = edges_.begin();
Chris@16 445 for (edge_iterator it = edges_.begin(); it != edges_.end(); it += 2) {
Chris@16 446 const vertex_type* v1 = it->vertex0();
Chris@16 447 const vertex_type* v2 = it->vertex1();
Chris@16 448 if (v1 && v2 && vertex_equality_predicate_(*v1, *v2)) {
Chris@16 449 remove_edge(&(*it));
Chris@16 450 } else {
Chris@16 451 if (it != last_edge) {
Chris@16 452 edge_type* e1 = &(*last_edge = *it);
Chris@16 453 edge_type* e2 = &(*(last_edge + 1) = *(it + 1));
Chris@16 454 e1->twin(e2);
Chris@16 455 e2->twin(e1);
Chris@16 456 if (e1->prev()) {
Chris@16 457 e1->prev()->next(e1);
Chris@16 458 e2->next()->prev(e2);
Chris@16 459 }
Chris@16 460 if (e2->prev()) {
Chris@16 461 e1->next()->prev(e1);
Chris@16 462 e2->prev()->next(e2);
Chris@16 463 }
Chris@16 464 }
Chris@16 465 last_edge += 2;
Chris@16 466 }
Chris@16 467 }
Chris@16 468 edges_.erase(last_edge, edges_.end());
Chris@16 469
Chris@16 470 // Set up incident edge pointers for cells and vertices.
Chris@16 471 for (edge_iterator it = edges_.begin(); it != edges_.end(); ++it) {
Chris@16 472 it->cell()->incident_edge(&(*it));
Chris@16 473 if (it->vertex0()) {
Chris@16 474 it->vertex0()->incident_edge(&(*it));
Chris@16 475 }
Chris@16 476 }
Chris@16 477
Chris@16 478 // Remove degenerate vertices.
Chris@16 479 vertex_iterator last_vertex = vertices_.begin();
Chris@16 480 for (vertex_iterator it = vertices_.begin(); it != vertices_.end(); ++it) {
Chris@16 481 if (it->incident_edge()) {
Chris@16 482 if (it != last_vertex) {
Chris@16 483 *last_vertex = *it;
Chris@16 484 vertex_type* v = &(*last_vertex);
Chris@16 485 edge_type* e = v->incident_edge();
Chris@16 486 do {
Chris@16 487 e->vertex0(v);
Chris@16 488 e = e->rot_next();
Chris@16 489 } while (e != v->incident_edge());
Chris@16 490 }
Chris@16 491 ++last_vertex;
Chris@16 492 }
Chris@16 493 }
Chris@16 494 vertices_.erase(last_vertex, vertices_.end());
Chris@16 495
Chris@16 496 // Set up next/prev pointers for infinite edges.
Chris@16 497 if (vertices_.empty()) {
Chris@16 498 if (!edges_.empty()) {
Chris@16 499 // Update prev/next pointers for the line edges.
Chris@16 500 edge_iterator edge_it = edges_.begin();
Chris@16 501 edge_type* edge1 = &(*edge_it);
Chris@16 502 edge1->next(edge1);
Chris@16 503 edge1->prev(edge1);
Chris@16 504 ++edge_it;
Chris@16 505 edge1 = &(*edge_it);
Chris@16 506 ++edge_it;
Chris@16 507
Chris@16 508 while (edge_it != edges_.end()) {
Chris@16 509 edge_type* edge2 = &(*edge_it);
Chris@16 510 ++edge_it;
Chris@16 511
Chris@16 512 edge1->next(edge2);
Chris@16 513 edge1->prev(edge2);
Chris@16 514 edge2->next(edge1);
Chris@16 515 edge2->prev(edge1);
Chris@16 516
Chris@16 517 edge1 = &(*edge_it);
Chris@16 518 ++edge_it;
Chris@16 519 }
Chris@16 520
Chris@16 521 edge1->next(edge1);
Chris@16 522 edge1->prev(edge1);
Chris@16 523 }
Chris@16 524 } else {
Chris@16 525 // Update prev/next pointers for the ray edges.
Chris@16 526 for (cell_iterator cell_it = cells_.begin();
Chris@16 527 cell_it != cells_.end(); ++cell_it) {
Chris@16 528 if (cell_it->is_degenerate())
Chris@16 529 continue;
Chris@16 530 // Move to the previous edge while
Chris@16 531 // it is possible in the CW direction.
Chris@16 532 edge_type* left_edge = cell_it->incident_edge();
Chris@16 533 while (left_edge->prev() != NULL) {
Chris@16 534 left_edge = left_edge->prev();
Chris@16 535 // Terminate if this is not a boundary cell.
Chris@16 536 if (left_edge == cell_it->incident_edge())
Chris@16 537 break;
Chris@16 538 }
Chris@16 539
Chris@16 540 if (left_edge->prev() != NULL)
Chris@16 541 continue;
Chris@16 542
Chris@16 543 edge_type* right_edge = cell_it->incident_edge();
Chris@16 544 while (right_edge->next() != NULL)
Chris@16 545 right_edge = right_edge->next();
Chris@16 546 left_edge->prev(right_edge);
Chris@16 547 right_edge->next(left_edge);
Chris@16 548 }
Chris@16 549 }
Chris@16 550 }
Chris@16 551
Chris@16 552 private:
Chris@16 553 typedef typename cell_container_type::iterator cell_iterator;
Chris@16 554 typedef typename vertex_container_type::iterator vertex_iterator;
Chris@16 555 typedef typename edge_container_type::iterator edge_iterator;
Chris@16 556 typedef typename TRAITS::vertex_equality_predicate_type
Chris@16 557 vertex_equality_predicate_type;
Chris@16 558
Chris@16 559 template <typename SEvent>
Chris@16 560 bool is_primary_edge(const SEvent& site1, const SEvent& site2) const {
Chris@16 561 bool flag1 = site1.is_segment();
Chris@16 562 bool flag2 = site2.is_segment();
Chris@16 563 if (flag1 && !flag2) {
Chris@16 564 return (site1.point0() != site2.point0()) &&
Chris@16 565 (site1.point1() != site2.point0());
Chris@16 566 }
Chris@16 567 if (!flag1 && flag2) {
Chris@16 568 return (site2.point0() != site1.point0()) &&
Chris@16 569 (site2.point1() != site1.point0());
Chris@16 570 }
Chris@16 571 return true;
Chris@16 572 }
Chris@16 573
Chris@16 574 template <typename SEvent>
Chris@16 575 bool is_linear_edge(const SEvent& site1, const SEvent& site2) const {
Chris@16 576 if (!is_primary_edge(site1, site2)) {
Chris@16 577 return true;
Chris@16 578 }
Chris@16 579 return !(site1.is_segment() ^ site2.is_segment());
Chris@16 580 }
Chris@16 581
Chris@16 582 // Remove degenerate edge.
Chris@16 583 void remove_edge(edge_type* edge) {
Chris@16 584 // Update the endpoints of the incident edges to the second vertex.
Chris@16 585 vertex_type* vertex = edge->vertex0();
Chris@16 586 edge_type* updated_edge = edge->twin()->rot_next();
Chris@16 587 while (updated_edge != edge->twin()) {
Chris@16 588 updated_edge->vertex0(vertex);
Chris@16 589 updated_edge = updated_edge->rot_next();
Chris@16 590 }
Chris@16 591
Chris@16 592 edge_type* edge1 = edge;
Chris@16 593 edge_type* edge2 = edge->twin();
Chris@16 594
Chris@16 595 edge_type* edge1_rot_prev = edge1->rot_prev();
Chris@16 596 edge_type* edge1_rot_next = edge1->rot_next();
Chris@16 597
Chris@16 598 edge_type* edge2_rot_prev = edge2->rot_prev();
Chris@16 599 edge_type* edge2_rot_next = edge2->rot_next();
Chris@16 600
Chris@16 601 // Update prev/next pointers for the incident edges.
Chris@16 602 edge1_rot_next->twin()->next(edge2_rot_prev);
Chris@16 603 edge2_rot_prev->prev(edge1_rot_next->twin());
Chris@16 604 edge1_rot_prev->prev(edge2_rot_next->twin());
Chris@16 605 edge2_rot_next->twin()->next(edge1_rot_prev);
Chris@16 606 }
Chris@16 607
Chris@16 608 cell_container_type cells_;
Chris@16 609 vertex_container_type vertices_;
Chris@16 610 edge_container_type edges_;
Chris@16 611 vertex_equality_predicate_type vertex_equality_predicate_;
Chris@16 612
Chris@16 613 // Disallow copy constructor and operator=
Chris@16 614 voronoi_diagram(const voronoi_diagram&);
Chris@16 615 void operator=(const voronoi_diagram&);
Chris@16 616 };
Chris@16 617 } // polygon
Chris@16 618 } // boost
Chris@16 619
Chris@16 620 #endif // BOOST_POLYGON_VORONOI_DIAGRAM