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

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 // Boost.Polygon library voronoi_builder.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_BUILDER
Chris@16 11 #define BOOST_POLYGON_VORONOI_BUILDER
Chris@16 12
Chris@16 13 #include <algorithm>
Chris@16 14 #include <map>
Chris@16 15 #include <queue>
Chris@16 16 #include <utility>
Chris@16 17 #include <vector>
Chris@16 18
Chris@16 19 #include "detail/voronoi_ctypes.hpp"
Chris@16 20 #include "detail/voronoi_predicates.hpp"
Chris@16 21 #include "detail/voronoi_structures.hpp"
Chris@16 22
Chris@16 23 #include "voronoi_geometry_type.hpp"
Chris@16 24
Chris@16 25 namespace boost {
Chris@16 26 namespace polygon {
Chris@16 27 // GENERAL INFO:
Chris@16 28 // The sweepline algorithm implementation to compute Voronoi diagram of
Chris@101 29 // points and non-intersecting segments (excluding endpoints).
Chris@16 30 // Complexity - O(N*logN), memory usage - O(N), where N is the total number
Chris@101 31 // of input geometries.
Chris@101 32 //
Chris@101 33 // CONTRACT:
Chris@101 34 // 1) Input geometries should have integral (e.g. int32, int64) coordinate type.
Chris@101 35 // 2) Input geometries should not intersect except their endpoints.
Chris@16 36 //
Chris@16 37 // IMPLEMENTATION DETAILS:
Chris@101 38 // Each input point creates one input site. Each input segment creates three
Chris@101 39 // input sites: two for its endpoints and one for the segment itself (this is
Chris@101 40 // made to simplify output construction). All the site objects are constructed
Chris@16 41 // and sorted at the algorithm initialization step. Priority queue is used to
Chris@16 42 // dynamically hold circle events. At each step of the algorithm execution the
Chris@16 43 // leftmost event is retrieved by comparing the current site event and the
Chris@16 44 // topmost element from the circle event queue. STL map (red-black tree)
Chris@16 45 // container was chosen to hold state of the beach line. The keys of the map
Chris@16 46 // correspond to the neighboring sites that form a bisector and values map to
Chris@16 47 // the corresponding Voronoi edges in the output data structure.
Chris@16 48 template <typename T,
Chris@16 49 typename CTT = detail::voronoi_ctype_traits<T>,
Chris@16 50 typename VP = detail::voronoi_predicates<CTT> >
Chris@16 51 class voronoi_builder {
Chris@16 52 public:
Chris@16 53 typedef typename CTT::int_type int_type;
Chris@16 54 typedef typename CTT::fpt_type fpt_type;
Chris@16 55
Chris@16 56 voronoi_builder() : index_(0) {}
Chris@16 57
Chris@16 58 // Each point creates a single site event.
Chris@16 59 std::size_t insert_point(const int_type& x, const int_type& y) {
Chris@16 60 site_events_.push_back(site_event_type(x, y));
Chris@16 61 site_events_.back().initial_index(index_);
Chris@16 62 site_events_.back().source_category(SOURCE_CATEGORY_SINGLE_POINT);
Chris@16 63 return index_++;
Chris@16 64 }
Chris@16 65
Chris@16 66 // Each segment creates three site events that correspond to:
Chris@16 67 // 1) the start point of the segment;
Chris@16 68 // 2) the end point of the segment;
Chris@16 69 // 3) the segment itself defined by its start point.
Chris@16 70 std::size_t insert_segment(
Chris@16 71 const int_type& x1, const int_type& y1,
Chris@16 72 const int_type& x2, const int_type& y2) {
Chris@16 73 // Set up start point site.
Chris@16 74 point_type p1(x1, y1);
Chris@16 75 site_events_.push_back(site_event_type(p1));
Chris@16 76 site_events_.back().initial_index(index_);
Chris@16 77 site_events_.back().source_category(SOURCE_CATEGORY_SEGMENT_START_POINT);
Chris@16 78
Chris@16 79 // Set up end point site.
Chris@16 80 point_type p2(x2, y2);
Chris@16 81 site_events_.push_back(site_event_type(p2));
Chris@16 82 site_events_.back().initial_index(index_);
Chris@16 83 site_events_.back().source_category(SOURCE_CATEGORY_SEGMENT_END_POINT);
Chris@16 84
Chris@16 85 // Set up segment site.
Chris@16 86 if (point_comparison_(p1, p2)) {
Chris@16 87 site_events_.push_back(site_event_type(p1, p2));
Chris@16 88 site_events_.back().source_category(SOURCE_CATEGORY_INITIAL_SEGMENT);
Chris@16 89 } else {
Chris@16 90 site_events_.push_back(site_event_type(p2, p1));
Chris@16 91 site_events_.back().source_category(SOURCE_CATEGORY_REVERSE_SEGMENT);
Chris@16 92 }
Chris@16 93 site_events_.back().initial_index(index_);
Chris@16 94 return index_++;
Chris@16 95 }
Chris@16 96
Chris@16 97 // Run sweepline algorithm and fill output data structure.
Chris@16 98 template <typename OUTPUT>
Chris@16 99 void construct(OUTPUT* output) {
Chris@16 100 // Init structures.
Chris@16 101 output->_reserve(site_events_.size());
Chris@16 102 init_sites_queue();
Chris@16 103 init_beach_line(output);
Chris@16 104
Chris@16 105 // The algorithm stops when there are no events to process.
Chris@16 106 event_comparison_predicate event_comparison;
Chris@16 107 while (!circle_events_.empty() ||
Chris@16 108 !(site_event_iterator_ == site_events_.end())) {
Chris@16 109 if (circle_events_.empty()) {
Chris@16 110 process_site_event(output);
Chris@16 111 } else if (site_event_iterator_ == site_events_.end()) {
Chris@16 112 process_circle_event(output);
Chris@16 113 } else {
Chris@16 114 if (event_comparison(*site_event_iterator_,
Chris@16 115 circle_events_.top().first)) {
Chris@16 116 process_site_event(output);
Chris@16 117 } else {
Chris@16 118 process_circle_event(output);
Chris@16 119 }
Chris@16 120 }
Chris@16 121 while (!circle_events_.empty() &&
Chris@16 122 !circle_events_.top().first.is_active()) {
Chris@16 123 circle_events_.pop();
Chris@16 124 }
Chris@16 125 }
Chris@16 126 beach_line_.clear();
Chris@16 127
Chris@16 128 // Finish construction.
Chris@16 129 output->_build();
Chris@16 130 }
Chris@16 131
Chris@16 132 void clear() {
Chris@16 133 index_ = 0;
Chris@16 134 site_events_.clear();
Chris@16 135 }
Chris@16 136
Chris@16 137 private:
Chris@16 138 typedef detail::point_2d<int_type> point_type;
Chris@16 139 typedef detail::site_event<int_type> site_event_type;
Chris@16 140 typedef typename std::vector<site_event_type>::const_iterator
Chris@16 141 site_event_iterator_type;
Chris@16 142 typedef detail::circle_event<fpt_type> circle_event_type;
Chris@16 143 typedef typename VP::template point_comparison_predicate<point_type>
Chris@16 144 point_comparison_predicate;
Chris@16 145 typedef typename VP::
Chris@16 146 template event_comparison_predicate<site_event_type, circle_event_type>
Chris@16 147 event_comparison_predicate;
Chris@16 148 typedef typename VP::
Chris@16 149 template circle_formation_predicate<site_event_type, circle_event_type>
Chris@16 150 circle_formation_predicate_type;
Chris@16 151 typedef void edge_type;
Chris@16 152 typedef detail::beach_line_node_key<site_event_type> key_type;
Chris@16 153 typedef detail::beach_line_node_data<edge_type, circle_event_type>
Chris@16 154 value_type;
Chris@16 155 typedef typename VP::template node_comparison_predicate<key_type>
Chris@16 156 node_comparer_type;
Chris@16 157 typedef std::map< key_type, value_type, node_comparer_type > beach_line_type;
Chris@16 158 typedef typename beach_line_type::iterator beach_line_iterator;
Chris@16 159 typedef std::pair<circle_event_type, beach_line_iterator> event_type;
Chris@16 160 typedef struct {
Chris@16 161 bool operator()(const event_type& lhs, const event_type& rhs) const {
Chris@16 162 return predicate(rhs.first, lhs.first);
Chris@16 163 }
Chris@16 164 event_comparison_predicate predicate;
Chris@16 165 } event_comparison_type;
Chris@16 166 typedef detail::ordered_queue<event_type, event_comparison_type>
Chris@16 167 circle_event_queue_type;
Chris@16 168 typedef std::pair<point_type, beach_line_iterator> end_point_type;
Chris@16 169
Chris@16 170 void init_sites_queue() {
Chris@16 171 // Sort site events.
Chris@16 172 std::sort(site_events_.begin(), site_events_.end(),
Chris@16 173 event_comparison_predicate());
Chris@16 174
Chris@16 175 // Remove duplicates.
Chris@16 176 site_events_.erase(std::unique(
Chris@16 177 site_events_.begin(), site_events_.end()), site_events_.end());
Chris@16 178
Chris@16 179 // Index sites.
Chris@16 180 for (std::size_t cur = 0; cur < site_events_.size(); ++cur) {
Chris@16 181 site_events_[cur].sorted_index(cur);
Chris@16 182 }
Chris@16 183
Chris@16 184 // Init site iterator.
Chris@16 185 site_event_iterator_ = site_events_.begin();
Chris@16 186 }
Chris@16 187
Chris@16 188 template <typename OUTPUT>
Chris@16 189 void init_beach_line(OUTPUT* output) {
Chris@16 190 if (site_events_.empty())
Chris@16 191 return;
Chris@16 192 if (site_events_.size() == 1) {
Chris@16 193 // Handle single site event case.
Chris@16 194 output->_process_single_site(site_events_[0]);
Chris@16 195 ++site_event_iterator_;
Chris@16 196 } else {
Chris@16 197 int skip = 0;
Chris@16 198
Chris@16 199 while (site_event_iterator_ != site_events_.end() &&
Chris@16 200 VP::is_vertical(site_event_iterator_->point0(),
Chris@16 201 site_events_.begin()->point0()) &&
Chris@16 202 VP::is_vertical(*site_event_iterator_)) {
Chris@16 203 ++site_event_iterator_;
Chris@16 204 ++skip;
Chris@16 205 }
Chris@16 206
Chris@16 207 if (skip == 1) {
Chris@16 208 // Init beach line with the first two sites.
Chris@16 209 init_beach_line_default(output);
Chris@16 210 } else {
Chris@16 211 // Init beach line with collinear vertical sites.
Chris@16 212 init_beach_line_collinear_sites(output);
Chris@16 213 }
Chris@16 214 }
Chris@16 215 }
Chris@16 216
Chris@16 217 // Init beach line with the two first sites.
Chris@16 218 // The first site is always a point.
Chris@16 219 template <typename OUTPUT>
Chris@16 220 void init_beach_line_default(OUTPUT* output) {
Chris@16 221 // Get the first and the second site event.
Chris@16 222 site_event_iterator_type it_first = site_events_.begin();
Chris@16 223 site_event_iterator_type it_second = site_events_.begin();
Chris@16 224 ++it_second;
Chris@16 225 insert_new_arc(
Chris@16 226 *it_first, *it_first, *it_second, beach_line_.end(), output);
Chris@16 227 // The second site was already processed. Move the iterator.
Chris@16 228 ++site_event_iterator_;
Chris@16 229 }
Chris@16 230
Chris@16 231 // Init beach line with collinear sites.
Chris@16 232 template <typename OUTPUT>
Chris@16 233 void init_beach_line_collinear_sites(OUTPUT* output) {
Chris@16 234 site_event_iterator_type it_first = site_events_.begin();
Chris@16 235 site_event_iterator_type it_second = site_events_.begin();
Chris@16 236 ++it_second;
Chris@16 237 while (it_second != site_event_iterator_) {
Chris@16 238 // Create a new beach line node.
Chris@16 239 key_type new_node(*it_first, *it_second);
Chris@16 240
Chris@16 241 // Update the output.
Chris@16 242 edge_type* edge = output->_insert_new_edge(*it_first, *it_second).first;
Chris@16 243
Chris@16 244 // Insert a new bisector into the beach line.
Chris@16 245 beach_line_.insert(beach_line_.end(),
Chris@16 246 std::pair<key_type, value_type>(new_node, value_type(edge)));
Chris@16 247
Chris@16 248 // Update iterators.
Chris@16 249 ++it_first;
Chris@16 250 ++it_second;
Chris@16 251 }
Chris@16 252 }
Chris@16 253
Chris@16 254 void deactivate_circle_event(value_type* value) {
Chris@16 255 if (value->circle_event()) {
Chris@16 256 value->circle_event()->deactivate();
Chris@16 257 value->circle_event(NULL);
Chris@16 258 }
Chris@16 259 }
Chris@16 260
Chris@16 261 template <typename OUTPUT>
Chris@16 262 void process_site_event(OUTPUT* output) {
Chris@16 263 // Get next site event to process.
Chris@16 264 site_event_type site_event = *site_event_iterator_;
Chris@16 265
Chris@16 266 // Move site iterator.
Chris@16 267 site_event_iterator_type last = site_event_iterator_ + 1;
Chris@16 268
Chris@16 269 // If a new site is an end point of some segment,
Chris@16 270 // remove temporary nodes from the beach line data structure.
Chris@16 271 if (!site_event.is_segment()) {
Chris@16 272 while (!end_points_.empty() &&
Chris@16 273 end_points_.top().first == site_event.point0()) {
Chris@16 274 beach_line_iterator b_it = end_points_.top().second;
Chris@16 275 end_points_.pop();
Chris@16 276 beach_line_.erase(b_it);
Chris@16 277 }
Chris@16 278 } else {
Chris@16 279 while (last != site_events_.end() &&
Chris@16 280 last->is_segment() && last->point0() == site_event.point0())
Chris@16 281 ++last;
Chris@16 282 }
Chris@16 283
Chris@16 284 // Find the node in the binary search tree with left arc
Chris@16 285 // lying above the new site point.
Chris@16 286 key_type new_key(*site_event_iterator_);
Chris@16 287 beach_line_iterator right_it = beach_line_.lower_bound(new_key);
Chris@16 288
Chris@16 289 for (; site_event_iterator_ != last; ++site_event_iterator_) {
Chris@16 290 site_event = *site_event_iterator_;
Chris@16 291 beach_line_iterator left_it = right_it;
Chris@16 292
Chris@16 293 // Do further processing depending on the above node position.
Chris@16 294 // For any two neighboring nodes the second site of the first node
Chris@16 295 // is the same as the first site of the second node.
Chris@16 296 if (right_it == beach_line_.end()) {
Chris@16 297 // The above arc corresponds to the second arc of the last node.
Chris@16 298 // Move the iterator to the last node.
Chris@16 299 --left_it;
Chris@16 300
Chris@16 301 // Get the second site of the last node
Chris@16 302 const site_event_type& site_arc = left_it->first.right_site();
Chris@16 303
Chris@16 304 // Insert new nodes into the beach line. Update the output.
Chris@16 305 right_it = insert_new_arc(
Chris@16 306 site_arc, site_arc, site_event, right_it, output);
Chris@16 307
Chris@16 308 // Add a candidate circle to the circle event queue.
Chris@16 309 // There could be only one new circle event formed by
Chris@16 310 // a new bisector and the one on the left.
Chris@16 311 activate_circle_event(left_it->first.left_site(),
Chris@16 312 left_it->first.right_site(),
Chris@16 313 site_event, right_it);
Chris@16 314 } else if (right_it == beach_line_.begin()) {
Chris@16 315 // The above arc corresponds to the first site of the first node.
Chris@16 316 const site_event_type& site_arc = right_it->first.left_site();
Chris@16 317
Chris@16 318 // Insert new nodes into the beach line. Update the output.
Chris@16 319 left_it = insert_new_arc(
Chris@16 320 site_arc, site_arc, site_event, right_it, output);
Chris@16 321
Chris@16 322 // If the site event is a segment, update its direction.
Chris@16 323 if (site_event.is_segment()) {
Chris@16 324 site_event.inverse();
Chris@16 325 }
Chris@16 326
Chris@16 327 // Add a candidate circle to the circle event queue.
Chris@16 328 // There could be only one new circle event formed by
Chris@16 329 // a new bisector and the one on the right.
Chris@16 330 activate_circle_event(site_event, right_it->first.left_site(),
Chris@16 331 right_it->first.right_site(), right_it);
Chris@16 332 right_it = left_it;
Chris@16 333 } else {
Chris@16 334 // The above arc corresponds neither to the first,
Chris@16 335 // nor to the last site in the beach line.
Chris@16 336 const site_event_type& site_arc2 = right_it->first.left_site();
Chris@16 337 const site_event_type& site3 = right_it->first.right_site();
Chris@16 338
Chris@16 339 // Remove the candidate circle from the event queue.
Chris@16 340 deactivate_circle_event(&right_it->second);
Chris@16 341 --left_it;
Chris@16 342 const site_event_type& site_arc1 = left_it->first.right_site();
Chris@16 343 const site_event_type& site1 = left_it->first.left_site();
Chris@16 344
Chris@16 345 // Insert new nodes into the beach line. Update the output.
Chris@16 346 beach_line_iterator new_node_it =
Chris@16 347 insert_new_arc(site_arc1, site_arc2, site_event, right_it, output);
Chris@16 348
Chris@16 349 // Add candidate circles to the circle event queue.
Chris@16 350 // There could be up to two circle events formed by
Chris@16 351 // a new bisector and the one on the left or right.
Chris@16 352 activate_circle_event(site1, site_arc1, site_event, new_node_it);
Chris@16 353
Chris@16 354 // If the site event is a segment, update its direction.
Chris@16 355 if (site_event.is_segment()) {
Chris@16 356 site_event.inverse();
Chris@16 357 }
Chris@16 358 activate_circle_event(site_event, site_arc2, site3, right_it);
Chris@16 359 right_it = new_node_it;
Chris@16 360 }
Chris@16 361 }
Chris@16 362 }
Chris@16 363
Chris@16 364 // In general case circle event is made of the three consecutive sites
Chris@16 365 // that form two bisectors in the beach line data structure.
Chris@16 366 // Let circle event sites be A, B, C, two bisectors that define
Chris@16 367 // circle event are (A, B), (B, C). During circle event processing
Chris@16 368 // we remove (A, B), (B, C) and insert (A, C). As beach line comparison
Chris@16 369 // works correctly only if one of the nodes is a new one we remove
Chris@16 370 // (B, C) bisector and change (A, B) bisector to the (A, C). That's
Chris@16 371 // why we use const_cast there and take all the responsibility that
Chris@16 372 // map data structure keeps correct ordering.
Chris@16 373 template <typename OUTPUT>
Chris@16 374 void process_circle_event(OUTPUT* output) {
Chris@16 375 // Get the topmost circle event.
Chris@16 376 const event_type& e = circle_events_.top();
Chris@16 377 const circle_event_type& circle_event = e.first;
Chris@16 378 beach_line_iterator it_first = e.second;
Chris@16 379 beach_line_iterator it_last = it_first;
Chris@16 380
Chris@16 381 // Get the C site.
Chris@16 382 site_event_type site3 = it_first->first.right_site();
Chris@16 383
Chris@16 384 // Get the half-edge corresponding to the second bisector - (B, C).
Chris@16 385 edge_type* bisector2 = it_first->second.edge();
Chris@16 386
Chris@16 387 // Get the half-edge corresponding to the first bisector - (A, B).
Chris@16 388 --it_first;
Chris@16 389 edge_type* bisector1 = it_first->second.edge();
Chris@16 390
Chris@16 391 // Get the A site.
Chris@16 392 site_event_type site1 = it_first->first.left_site();
Chris@16 393
Chris@16 394 if (!site1.is_segment() && site3.is_segment() &&
Chris@16 395 site3.point1() == site1.point0()) {
Chris@16 396 site3.inverse();
Chris@16 397 }
Chris@16 398
Chris@16 399 // Change the (A, B) bisector node to the (A, C) bisector node.
Chris@16 400 const_cast<key_type&>(it_first->first).right_site(site3);
Chris@16 401
Chris@16 402 // Insert the new bisector into the beach line.
Chris@16 403 it_first->second.edge(output->_insert_new_edge(
Chris@16 404 site1, site3, circle_event, bisector1, bisector2).first);
Chris@16 405
Chris@16 406 // Remove the (B, C) bisector node from the beach line.
Chris@16 407 beach_line_.erase(it_last);
Chris@16 408 it_last = it_first;
Chris@16 409
Chris@16 410 // Pop the topmost circle event from the event queue.
Chris@16 411 circle_events_.pop();
Chris@16 412
Chris@16 413 // Check new triplets formed by the neighboring arcs
Chris@16 414 // to the left for potential circle events.
Chris@16 415 if (it_first != beach_line_.begin()) {
Chris@16 416 deactivate_circle_event(&it_first->second);
Chris@16 417 --it_first;
Chris@16 418 const site_event_type& site_l1 = it_first->first.left_site();
Chris@16 419 activate_circle_event(site_l1, site1, site3, it_last);
Chris@16 420 }
Chris@16 421
Chris@16 422 // Check the new triplet formed by the neighboring arcs
Chris@16 423 // to the right for potential circle events.
Chris@16 424 ++it_last;
Chris@16 425 if (it_last != beach_line_.end()) {
Chris@16 426 deactivate_circle_event(&it_last->second);
Chris@16 427 const site_event_type& site_r1 = it_last->first.right_site();
Chris@16 428 activate_circle_event(site1, site3, site_r1, it_last);
Chris@16 429 }
Chris@16 430 }
Chris@16 431
Chris@16 432 // Insert new nodes into the beach line. Update the output.
Chris@16 433 template <typename OUTPUT>
Chris@16 434 beach_line_iterator insert_new_arc(
Chris@16 435 const site_event_type& site_arc1, const site_event_type &site_arc2,
Chris@16 436 const site_event_type& site_event, beach_line_iterator position,
Chris@16 437 OUTPUT* output) {
Chris@16 438 // Create two new bisectors with opposite directions.
Chris@16 439 key_type new_left_node(site_arc1, site_event);
Chris@16 440 key_type new_right_node(site_event, site_arc2);
Chris@16 441
Chris@16 442 // Set correct orientation for the first site of the second node.
Chris@16 443 if (site_event.is_segment()) {
Chris@16 444 new_right_node.left_site().inverse();
Chris@16 445 }
Chris@16 446
Chris@16 447 // Update the output.
Chris@16 448 std::pair<edge_type*, edge_type*> edges =
Chris@16 449 output->_insert_new_edge(site_arc2, site_event);
Chris@16 450 position = beach_line_.insert(position,
Chris@16 451 typename beach_line_type::value_type(
Chris@16 452 new_right_node, value_type(edges.second)));
Chris@16 453
Chris@16 454 if (site_event.is_segment()) {
Chris@16 455 // Update the beach line with temporary bisector, that will
Chris@16 456 // disappear after processing site event corresponding to the
Chris@16 457 // second endpoint of the segment site.
Chris@16 458 key_type new_node(site_event, site_event);
Chris@16 459 new_node.right_site().inverse();
Chris@16 460 position = beach_line_.insert(position,
Chris@16 461 typename beach_line_type::value_type(new_node, value_type(NULL)));
Chris@16 462
Chris@16 463 // Update the data structure that holds temporary bisectors.
Chris@16 464 end_points_.push(std::make_pair(site_event.point1(), position));
Chris@16 465 }
Chris@16 466
Chris@16 467 position = beach_line_.insert(position,
Chris@16 468 typename beach_line_type::value_type(
Chris@16 469 new_left_node, value_type(edges.first)));
Chris@16 470
Chris@16 471 return position;
Chris@16 472 }
Chris@16 473
Chris@16 474 // Add a new circle event to the event queue.
Chris@16 475 // bisector_node corresponds to the (site2, site3) bisector.
Chris@16 476 void activate_circle_event(const site_event_type& site1,
Chris@16 477 const site_event_type& site2,
Chris@16 478 const site_event_type& site3,
Chris@16 479 beach_line_iterator bisector_node) {
Chris@16 480 circle_event_type c_event;
Chris@16 481 // Check if the three input sites create a circle event.
Chris@16 482 if (circle_formation_predicate_(site1, site2, site3, c_event)) {
Chris@16 483 // Add the new circle event to the circle events queue.
Chris@16 484 // Update bisector's circle event iterator to point to the
Chris@16 485 // new circle event in the circle event queue.
Chris@16 486 event_type& e = circle_events_.push(
Chris@16 487 std::pair<circle_event_type, beach_line_iterator>(
Chris@16 488 c_event, bisector_node));
Chris@16 489 bisector_node->second.circle_event(&e.first);
Chris@16 490 }
Chris@16 491 }
Chris@16 492
Chris@16 493 private:
Chris@16 494 point_comparison_predicate point_comparison_;
Chris@16 495 struct end_point_comparison {
Chris@16 496 bool operator() (const end_point_type& end1,
Chris@16 497 const end_point_type& end2) const {
Chris@16 498 return point_comparison(end2.first, end1.first);
Chris@16 499 }
Chris@16 500 point_comparison_predicate point_comparison;
Chris@16 501 };
Chris@16 502
Chris@16 503 std::vector<site_event_type> site_events_;
Chris@16 504 site_event_iterator_type site_event_iterator_;
Chris@16 505 std::priority_queue< end_point_type, std::vector<end_point_type>,
Chris@16 506 end_point_comparison > end_points_;
Chris@16 507 circle_event_queue_type circle_events_;
Chris@16 508 beach_line_type beach_line_;
Chris@16 509 circle_formation_predicate_type circle_formation_predicate_;
Chris@16 510 std::size_t index_;
Chris@16 511
Chris@16 512 // Disallow copy constructor and operator=
Chris@16 513 voronoi_builder(const voronoi_builder&);
Chris@16 514 void operator=(const voronoi_builder&);
Chris@16 515 };
Chris@16 516
Chris@16 517 typedef voronoi_builder<detail::int32> default_voronoi_builder;
Chris@16 518 } // polygon
Chris@16 519 } // boost
Chris@16 520
Chris@16 521 #endif // BOOST_POLYGON_VORONOI_BUILDER