Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 10:04:56

0001 // Boost.Polygon library detail/voronoi_structures.hpp header file
0002 
0003 //          Copyright Andrii Sydorchuk 2010-2012.
0004 // Distributed under the Boost Software License, Version 1.0.
0005 //    (See accompanying file LICENSE_1_0.txt or copy at
0006 //          http://www.boost.org/LICENSE_1_0.txt)
0007 
0008 // See http://www.boost.org for updates, documentation, and revision history.
0009 
0010 #ifndef BOOST_POLYGON_DETAIL_VORONOI_STRUCTURES
0011 #define BOOST_POLYGON_DETAIL_VORONOI_STRUCTURES
0012 
0013 #include <list>
0014 #include <queue>
0015 #include <vector>
0016 
0017 #include "boost/polygon/voronoi_geometry_type.hpp"
0018 
0019 namespace boost {
0020 namespace polygon {
0021 namespace detail {
0022 // Cartesian 2D point data structure.
0023 template <typename T>
0024 class point_2d {
0025  public:
0026   typedef T coordinate_type;
0027 
0028   point_2d() {}
0029 
0030   point_2d(coordinate_type x, coordinate_type y) :
0031       x_(x),
0032       y_(y) {}
0033 
0034   bool operator==(const point_2d& that) const {
0035     return (this->x_ == that.x()) && (this->y_ == that.y());
0036   }
0037 
0038   bool operator!=(const point_2d& that) const {
0039     return (this->x_ != that.x()) || (this->y_ != that.y());
0040   }
0041 
0042   coordinate_type x() const {
0043     return x_;
0044   }
0045 
0046   coordinate_type y() const {
0047     return y_;
0048   }
0049 
0050   point_2d& x(coordinate_type x) {
0051     x_ = x;
0052     return *this;
0053   }
0054 
0055   point_2d& y(coordinate_type y) {
0056     y_ = y;
0057     return *this;
0058   }
0059 
0060  private:
0061   coordinate_type x_;
0062   coordinate_type y_;
0063 };
0064 
0065 // Site event type.
0066 // Occurs when the sweepline sweeps over one of the initial sites:
0067 //   1) point site
0068 //   2) start-point of the segment site
0069 //   3) endpoint of the segment site
0070 // Implicit segment direction is defined: the start-point of
0071 // the segment compares less than its endpoint.
0072 // Each input segment is divided onto two site events:
0073 //   1) One going from the start-point to the endpoint
0074 //      (is_inverse() = false)
0075 //   2) Another going from the endpoint to the start-point
0076 //      (is_inverse() = true)
0077 // In beach line data structure segment sites of the first
0078 // type precede sites of the second type for the same segment.
0079 // Members:
0080 //   point0_ - point site or segment's start-point
0081 //   point1_ - segment's endpoint if site is a segment
0082 //   sorted_index_ - the last bit encodes information if the site is inverse;
0083 //     the other bits encode site event index among the sorted site events
0084 //   initial_index_ - site index among the initial input set
0085 // Note: for all sites is_inverse_ flag is equal to false by default.
0086 template <typename T>
0087 class site_event {
0088  public:
0089   typedef T coordinate_type;
0090   typedef point_2d<T> point_type;
0091 
0092   site_event() :
0093       point0_(0, 0),
0094       point1_(0, 0),
0095       sorted_index_(0),
0096       flags_(0) {}
0097 
0098   site_event(coordinate_type x, coordinate_type y) :
0099       point0_(x, y),
0100       point1_(x, y),
0101       sorted_index_(0),
0102       flags_(0) {}
0103 
0104   explicit site_event(const point_type& point) :
0105       point0_(point),
0106       point1_(point),
0107       sorted_index_(0),
0108       flags_(0) {}
0109 
0110   site_event(coordinate_type x1, coordinate_type y1,
0111              coordinate_type x2, coordinate_type y2):
0112       point0_(x1, y1),
0113       point1_(x2, y2),
0114       sorted_index_(0),
0115       flags_(0) {}
0116 
0117   site_event(const point_type& point1, const point_type& point2) :
0118       point0_(point1),
0119       point1_(point2),
0120       sorted_index_(0),
0121       flags_(0) {}
0122 
0123   bool operator==(const site_event& that) const {
0124     return (this->point0_ == that.point0_) &&
0125            (this->point1_ == that.point1_);
0126   }
0127 
0128   bool operator!=(const site_event& that) const {
0129     return (this->point0_ != that.point0_) ||
0130            (this->point1_ != that.point1_);
0131   }
0132 
0133   coordinate_type x() const {
0134     return point0_.x();
0135   }
0136 
0137   coordinate_type y() const {
0138     return point0_.y();
0139   }
0140 
0141   coordinate_type x0() const {
0142     return point0_.x();
0143   }
0144 
0145   coordinate_type y0() const {
0146     return point0_.y();
0147   }
0148 
0149   coordinate_type x1() const {
0150     return point1_.x();
0151   }
0152 
0153   coordinate_type y1() const {
0154     return point1_.y();
0155   }
0156 
0157   const point_type& point0() const {
0158     return point0_;
0159   }
0160 
0161   const point_type& point1() const {
0162     return point1_;
0163   }
0164 
0165   std::size_t sorted_index() const {
0166     return sorted_index_;
0167   }
0168 
0169   site_event& sorted_index(std::size_t index) {
0170     sorted_index_ = index;
0171     return *this;
0172   }
0173 
0174   std::size_t initial_index() const {
0175     return initial_index_;
0176   }
0177 
0178   site_event& initial_index(std::size_t index) {
0179     initial_index_ = index;
0180     return *this;
0181   }
0182 
0183   bool is_inverse() const {
0184     return (flags_ & IS_INVERSE) ? true : false;
0185   }
0186 
0187   site_event& inverse() {
0188     std::swap(point0_, point1_);
0189     flags_ ^= IS_INVERSE;
0190     return *this;
0191   }
0192 
0193   SourceCategory source_category() const {
0194     return static_cast<SourceCategory>(flags_ & SOURCE_CATEGORY_BITMASK);
0195   }
0196 
0197   site_event& source_category(SourceCategory source_category) {
0198     flags_ |= source_category;
0199     return *this;
0200   }
0201 
0202   bool is_point() const {
0203     return (point0_.x() == point1_.x()) && (point0_.y() == point1_.y());
0204   }
0205 
0206   bool is_segment() const {
0207     return (point0_.x() != point1_.x()) || (point0_.y() != point1_.y());
0208   }
0209 
0210  private:
0211   enum Bits {
0212     IS_INVERSE = 0x20  // 32
0213   };
0214 
0215   point_type point0_;
0216   point_type point1_;
0217   std::size_t sorted_index_;
0218   std::size_t initial_index_;
0219   std::size_t flags_;
0220 };
0221 
0222 // Circle event type.
0223 // Occurs when the sweepline sweeps over the rightmost point of the Voronoi
0224 // circle (with the center at the intersection point of the bisectors).
0225 // Circle event is made of the two consecutive nodes in the beach line data
0226 // structure. In case another node was inserted during algorithm execution
0227 // between the given two nodes circle event becomes inactive.
0228 // Variables:
0229 //   center_x_ - center x-coordinate;
0230 //   center_y_ - center y-coordinate;
0231 //   lower_x_ - leftmost x-coordinate;
0232 //   is_active_ - states whether circle event is still active.
0233 // NOTE: lower_y coordinate is always equal to center_y.
0234 template <typename T>
0235 class circle_event {
0236  public:
0237   typedef T coordinate_type;
0238 
0239   circle_event() : is_active_(true) {}
0240 
0241   circle_event(coordinate_type c_x,
0242                coordinate_type c_y,
0243                coordinate_type lower_x) :
0244       center_x_(c_x),
0245       center_y_(c_y),
0246       lower_x_(lower_x),
0247       is_active_(true) {}
0248 
0249   coordinate_type x() const {
0250     return center_x_;
0251   }
0252 
0253   circle_event& x(coordinate_type center_x) {
0254     center_x_ = center_x;
0255     return *this;
0256   }
0257 
0258   coordinate_type y() const {
0259     return center_y_;
0260   }
0261 
0262   circle_event& y(coordinate_type center_y) {
0263     center_y_ = center_y;
0264     return *this;
0265   }
0266 
0267   coordinate_type lower_x() const {
0268     return lower_x_;
0269   }
0270 
0271   circle_event& lower_x(coordinate_type lower_x) {
0272     lower_x_ = lower_x;
0273     return *this;
0274   }
0275 
0276   coordinate_type lower_y() const {
0277     return center_y_;
0278   }
0279 
0280   bool is_active() const {
0281     return is_active_;
0282   }
0283 
0284   circle_event& deactivate() {
0285     is_active_ = false;
0286     return *this;
0287   }
0288 
0289  private:
0290   coordinate_type center_x_;
0291   coordinate_type center_y_;
0292   coordinate_type lower_x_;
0293   bool is_active_;
0294 };
0295 
0296 // Event queue data structure, holds circle events.
0297 // During algorithm run, some of the circle events disappear (become
0298 // inactive). Priority queue data structure doesn't support
0299 // iterators (there is no direct ability to modify its elements).
0300 // Instead list is used to store all the circle events and priority queue
0301 // of the iterators to the list elements is used to keep the correct circle
0302 // events ordering.
0303 template <typename T, typename Predicate>
0304 class ordered_queue {
0305  public:
0306   ordered_queue() {}
0307 
0308   bool empty() const {
0309     return c_.empty();
0310   }
0311 
0312   const T &top() const {
0313     return *c_.top();
0314   }
0315 
0316   void pop() {
0317     list_iterator_type it = c_.top();
0318     c_.pop();
0319     c_list_.erase(it);
0320   }
0321 
0322   T &push(const T &e) {
0323     c_list_.push_front(e);
0324     c_.push(c_list_.begin());
0325     return c_list_.front();
0326   }
0327 
0328   void clear() {
0329     while (!c_.empty())
0330         c_.pop();
0331     c_list_.clear();
0332   }
0333 
0334  private:
0335   typedef typename std::list<T>::iterator list_iterator_type;
0336 
0337   struct comparison {
0338     bool operator() (const list_iterator_type &it1,
0339                      const list_iterator_type &it2) const {
0340       return cmp_(*it1, *it2);
0341     }
0342     Predicate cmp_;
0343   };
0344 
0345   std::priority_queue< list_iterator_type,
0346                        std::vector<list_iterator_type>,
0347                        comparison > c_;
0348   std::list<T> c_list_;
0349 
0350   // Disallow copy constructor and operator=
0351   ordered_queue(const ordered_queue&);
0352   void operator=(const ordered_queue&);
0353 };
0354 
0355 // Represents a bisector node made by two arcs that correspond to the left
0356 // and right sites. Arc is defined as a curve with points equidistant from
0357 // the site and from the sweepline. If the site is a point then arc is
0358 // a parabola, otherwise it's a line segment. A segment site event will
0359 // produce different bisectors based on its direction.
0360 // In general case two sites will create two opposite bisectors. That's
0361 // why the order of the sites is important to define the unique bisector.
0362 // The one site is considered to be newer than the other one if it was
0363 // processed by the algorithm later (has greater index).
0364 template <typename Site>
0365 class beach_line_node_key {
0366  public:
0367   typedef Site site_type;
0368 
0369   // Constructs degenerate bisector, used to search an arc that is above
0370   // the given site. The input to the constructor is the new site point.
0371   explicit beach_line_node_key(const site_type &new_site) :
0372       left_site_(new_site),
0373       right_site_(new_site) {}
0374 
0375   // Constructs a new bisector. The input to the constructor is the two
0376   // sites that create the bisector. The order of sites is important.
0377   beach_line_node_key(const site_type &left_site,
0378                       const site_type &right_site) :
0379       left_site_(left_site),
0380       right_site_(right_site) {}
0381 
0382   const site_type &left_site() const {
0383     return left_site_;
0384   }
0385 
0386   site_type &left_site() {
0387     return left_site_;
0388   }
0389 
0390   beach_line_node_key& left_site(const site_type &site) {
0391     left_site_ = site;
0392     return *this;
0393   }
0394 
0395   const site_type &right_site() const {
0396     return right_site_;
0397   }
0398 
0399   site_type &right_site() {
0400     return right_site_;
0401   }
0402 
0403   beach_line_node_key& right_site(const site_type &site) {
0404     right_site_ = site;
0405     return *this;
0406   }
0407 
0408  private:
0409   site_type left_site_;
0410   site_type right_site_;
0411 };
0412 
0413 // Represents edge data structure from the Voronoi output, that is
0414 // associated as a value with beach line bisector in the beach
0415 // line. Contains pointer to the circle event in the circle event
0416 // queue if the edge corresponds to the right bisector of the circle event.
0417 template <typename Edge, typename Circle>
0418 class beach_line_node_data {
0419  public:
0420   explicit beach_line_node_data(Edge* new_edge) :
0421       circle_event_(NULL),
0422       edge_(new_edge) {}
0423 
0424   Circle* circle_event() const {
0425     return circle_event_;
0426   }
0427 
0428   beach_line_node_data& circle_event(Circle* circle_event) {
0429     circle_event_ = circle_event;
0430     return *this;
0431   }
0432 
0433   Edge* edge() const {
0434     return edge_;
0435   }
0436 
0437   beach_line_node_data& edge(Edge* new_edge) {
0438     edge_ = new_edge;
0439     return *this;
0440   }
0441 
0442  private:
0443   Circle* circle_event_;
0444   Edge* edge_;
0445 };
0446 }  // detail
0447 }  // polygon
0448 }  // boost
0449 
0450 #endif  // BOOST_POLYGON_DETAIL_VORONOI_STRUCTURES