1 // Boost.Polygon library detail/voronoi_structures.hpp header file
3 // Copyright Andrii Sydorchuk 2010-2012.
4 // Distributed under the Boost Software License, Version 1.0.
5 // (See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
8 // See http://www.boost.org for updates, documentation, and revision history.
10 #ifndef BOOST_POLYGON_DETAIL_VORONOI_STRUCTURES
11 #define BOOST_POLYGON_DETAIL_VORONOI_STRUCTURES
17 #include "boost/polygon/voronoi_geometry_type.hpp"
22 // Cartesian 2D point data structure.
26 typedef T coordinate_type;
30 point_2d(coordinate_type x, coordinate_type y) :
34 bool operator==(const point_2d& that) const {
35 return (this->x_ == that.x()) && (this->y_ == that.y());
38 bool operator!=(const point_2d& that) const {
39 return (this->x_ != that.x()) || (this->y_ != that.y());
42 coordinate_type x() const {
46 coordinate_type y() const {
50 point_2d& x(coordinate_type x) {
55 point_2d& y(coordinate_type y) {
66 // Occurs when the sweepline sweeps over one of the initial sites:
68 // 2) start-point of the segment site
69 // 3) endpoint of the segment site
70 // Implicit segment direction is defined: the start-point of
71 // the segment compares less than its endpoint.
72 // Each input segment is divided onto two site events:
73 // 1) One going from the start-point to the endpoint
74 // (is_inverse() = false)
75 // 2) Another going from the endpoint to the start-point
76 // (is_inverse() = true)
77 // In beach line data structure segment sites of the first
78 // type precede sites of the second type for the same segment.
80 // point0_ - point site or segment's start-point
81 // point1_ - segment's endpoint if site is a segment
82 // sorted_index_ - the last bit encodes information if the site is inverse;
83 // the other bits encode site event index among the sorted site events
84 // initial_index_ - site index among the initial input set
85 // Note: for all sites is_inverse_ flag is equal to false by default.
89 typedef T coordinate_type;
90 typedef point_2d<T> point_type;
98 site_event(coordinate_type x, coordinate_type y) :
104 explicit site_event(const point_type& point) :
110 site_event(coordinate_type x1, coordinate_type y1,
111 coordinate_type x2, coordinate_type y2):
117 site_event(const point_type& point1, const point_type& point2) :
123 bool operator==(const site_event& that) const {
124 return (this->point0_ == that.point0_) &&
125 (this->point1_ == that.point1_);
128 bool operator!=(const site_event& that) const {
129 return (this->point0_ != that.point0_) ||
130 (this->point1_ != that.point1_);
133 coordinate_type x() const {
137 coordinate_type y() const {
141 coordinate_type x0() const {
145 coordinate_type y0() const {
149 coordinate_type x1() const {
153 coordinate_type y1() const {
157 const point_type& point0() const {
161 const point_type& point1() const {
165 std::size_t sorted_index() const {
166 return sorted_index_;
169 site_event& sorted_index(std::size_t index) {
170 sorted_index_ = index;
174 std::size_t initial_index() const {
175 return initial_index_;
178 site_event& initial_index(std::size_t index) {
179 initial_index_ = index;
183 bool is_inverse() const {
184 return (flags_ & IS_INVERSE) ? true : false;
187 site_event& inverse() {
188 std::swap(point0_, point1_);
189 flags_ ^= IS_INVERSE;
193 SourceCategory source_category() const {
194 return static_cast<SourceCategory>(flags_ & SOURCE_CATEGORY_BITMASK);
197 site_event& source_category(SourceCategory source_category) {
198 flags_ |= source_category;
202 bool is_point() const {
203 return (point0_.x() == point1_.x()) && (point0_.y() == point1_.y());
206 bool is_segment() const {
207 return (point0_.x() != point1_.x()) || (point0_.y() != point1_.y());
212 IS_INVERSE = 0x20 // 32
217 std::size_t sorted_index_;
218 std::size_t initial_index_;
222 // Circle event type.
223 // Occurs when the sweepline sweeps over the rightmost point of the Voronoi
224 // circle (with the center at the intersection point of the bisectors).
225 // Circle event is made of the two consecutive nodes in the beach line data
226 // structure. In case another node was inserted during algorithm execution
227 // between the given two nodes circle event becomes inactive.
229 // center_x_ - center x-coordinate;
230 // center_y_ - center y-coordinate;
231 // lower_x_ - leftmost x-coordinate;
232 // is_active_ - states whether circle event is still active.
233 // NOTE: lower_y coordinate is always equal to center_y.
234 template <typename T>
237 typedef T coordinate_type;
239 circle_event() : is_active_(true) {}
241 circle_event(coordinate_type c_x,
243 coordinate_type lower_x) :
249 coordinate_type x() const {
253 circle_event& x(coordinate_type center_x) {
254 center_x_ = center_x;
258 coordinate_type y() const {
262 circle_event& y(coordinate_type center_y) {
263 center_y_ = center_y;
267 coordinate_type lower_x() const {
271 circle_event& lower_x(coordinate_type lower_x) {
276 coordinate_type lower_y() const {
280 bool is_active() const {
284 circle_event& deactivate() {
290 coordinate_type center_x_;
291 coordinate_type center_y_;
292 coordinate_type lower_x_;
296 // Event queue data structure, holds circle events.
297 // During algorithm run, some of the circle events disappear (become
298 // inactive). Priority queue data structure doesn't support
299 // iterators (there is no direct ability to modify its elements).
300 // Instead list is used to store all the circle events and priority queue
301 // of the iterators to the list elements is used to keep the correct circle
303 template <typename T, typename Predicate>
304 class ordered_queue {
312 const T &top() const {
317 list_iterator_type it = c_.top();
322 T &push(const T &e) {
323 c_list_.push_front(e);
324 c_.push(c_list_.begin());
325 return c_list_.front();
335 typedef typename std::list<T>::iterator list_iterator_type;
338 bool operator() (const list_iterator_type &it1,
339 const list_iterator_type &it2) const {
340 return cmp_(*it1, *it2);
345 std::priority_queue< list_iterator_type,
346 std::vector<list_iterator_type>,
348 std::list<T> c_list_;
350 // Disallow copy constructor and operator=
351 ordered_queue(const ordered_queue&);
352 void operator=(const ordered_queue&);
355 // Represents a bisector node made by two arcs that correspond to the left
356 // and right sites. Arc is defined as a curve with points equidistant from
357 // the site and from the sweepline. If the site is a point then arc is
358 // a parabola, otherwise it's a line segment. A segment site event will
359 // produce different bisectors based on its direction.
360 // In general case two sites will create two opposite bisectors. That's
361 // why the order of the sites is important to define the unique bisector.
362 // The one site is considered to be newer than the other one if it was
363 // processed by the algorithm later (has greater index).
364 template <typename Site>
365 class beach_line_node_key {
367 typedef Site site_type;
369 // Constructs degenerate bisector, used to search an arc that is above
370 // the given site. The input to the constructor is the new site point.
371 explicit beach_line_node_key(const site_type &new_site) :
372 left_site_(new_site),
373 right_site_(new_site) {}
375 // Constructs a new bisector. The input to the constructor is the two
376 // sites that create the bisector. The order of sites is important.
377 beach_line_node_key(const site_type &left_site,
378 const site_type &right_site) :
379 left_site_(left_site),
380 right_site_(right_site) {}
382 const site_type &left_site() const {
386 site_type &left_site() {
390 beach_line_node_key& left_site(const site_type &site) {
395 const site_type &right_site() const {
399 site_type &right_site() {
403 beach_line_node_key& right_site(const site_type &site) {
409 site_type left_site_;
410 site_type right_site_;
413 // Represents edge data structure from the Voronoi output, that is
414 // associated as a value with beach line bisector in the beach
415 // line. Contains pointer to the circle event in the circle event
416 // queue if the edge corresponds to the right bisector of the circle event.
417 template <typename Edge, typename Circle>
418 class beach_line_node_data {
420 explicit beach_line_node_data(Edge* new_edge) :
424 Circle* circle_event() const {
425 return circle_event_;
428 beach_line_node_data& circle_event(Circle* circle_event) {
429 circle_event_ = circle_event;
437 beach_line_node_data& edge(Edge* new_edge) {
443 Circle* circle_event_;
450 #endif // BOOST_POLYGON_DETAIL_VORONOI_STRUCTURES