Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:55:27

0001 // Boost.Polygon library voronoi_diagram.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_VORONOI_DIAGRAM
0011 #define BOOST_POLYGON_VORONOI_DIAGRAM
0012 
0013 #include <vector>
0014 #include <utility>
0015 
0016 #include "detail/voronoi_ctypes.hpp"
0017 #include "detail/voronoi_structures.hpp"
0018 
0019 #include "voronoi_geometry_type.hpp"
0020 
0021 namespace boost {
0022 namespace polygon {
0023 
0024 // Forward declarations.
0025 template <typename T>
0026 class voronoi_edge;
0027 
0028 // Represents Voronoi cell.
0029 // Data members:
0030 //   1) index of the source within the initial input set
0031 //   2) pointer to the incident edge
0032 //   3) mutable color member
0033 // Cell may contain point or segment site inside.
0034 template <typename T>
0035 class voronoi_cell {
0036  public:
0037   typedef T coordinate_type;
0038   typedef std::size_t color_type;
0039   typedef voronoi_edge<coordinate_type> voronoi_edge_type;
0040   typedef std::size_t source_index_type;
0041   typedef SourceCategory source_category_type;
0042 
0043   voronoi_cell(source_index_type source_index,
0044                source_category_type source_category) :
0045       source_index_(source_index),
0046       incident_edge_(NULL),
0047       color_(source_category) {}
0048 
0049   // Returns true if the cell contains point site, false else.
0050   bool contains_point() const {
0051     source_category_type source_category = this->source_category();
0052     return belongs(source_category, GEOMETRY_CATEGORY_POINT);
0053   }
0054 
0055   // Returns true if the cell contains segment site, false else.
0056   bool contains_segment() const {
0057     source_category_type source_category = this->source_category();
0058     return belongs(source_category, GEOMETRY_CATEGORY_SEGMENT);
0059   }
0060 
0061   source_index_type source_index() const {
0062     return source_index_;
0063   }
0064 
0065   source_category_type source_category() const {
0066     return static_cast<source_category_type>(color_ & SOURCE_CATEGORY_BITMASK);
0067   }
0068 
0069   // Degenerate cells don't have any incident edges.
0070   bool is_degenerate() const { return incident_edge_ == NULL; }
0071 
0072   voronoi_edge_type* incident_edge() { return incident_edge_; }
0073   const voronoi_edge_type* incident_edge() const { return incident_edge_; }
0074   void incident_edge(voronoi_edge_type* e) { incident_edge_ = e; }
0075 
0076   color_type color() const { return color_ >> BITS_SHIFT; }
0077   void color(color_type color) const {
0078     color_ &= BITS_MASK;
0079     color_ |= color << BITS_SHIFT;
0080   }
0081 
0082  private:
0083   // 5 color bits are reserved.
0084   enum Bits {
0085     BITS_SHIFT = 0x5,
0086     BITS_MASK = 0x1F
0087   };
0088 
0089   source_index_type source_index_;
0090   voronoi_edge_type* incident_edge_;
0091   mutable color_type color_;
0092 };
0093 
0094 // Represents Voronoi vertex.
0095 // Data members:
0096 //   1) vertex coordinates
0097 //   2) pointer to the incident edge
0098 //   3) mutable color member
0099 template <typename T>
0100 class voronoi_vertex {
0101  public:
0102   typedef T coordinate_type;
0103   typedef std::size_t color_type;
0104   typedef voronoi_edge<coordinate_type> voronoi_edge_type;
0105 
0106   voronoi_vertex(const coordinate_type& x, const coordinate_type& y) :
0107       x_(x),
0108       y_(y),
0109       incident_edge_(NULL),
0110       color_(0) {}
0111 
0112   const coordinate_type& x() const { return x_; }
0113   const coordinate_type& y() const { return y_; }
0114 
0115   bool is_degenerate() const { return incident_edge_ == NULL; }
0116 
0117   voronoi_edge_type* incident_edge() { return incident_edge_; }
0118   const voronoi_edge_type* incident_edge() const { return incident_edge_; }
0119   void incident_edge(voronoi_edge_type* e) { incident_edge_ = e; }
0120 
0121   color_type color() const { return color_ >> BITS_SHIFT; }
0122   void color(color_type color) const {
0123     color_ &= BITS_MASK;
0124     color_ |= color << BITS_SHIFT;
0125   }
0126 
0127  private:
0128   // 5 color bits are reserved.
0129   enum Bits {
0130     BITS_SHIFT = 0x5,
0131     BITS_MASK = 0x1F
0132   };
0133 
0134   coordinate_type x_;
0135   coordinate_type y_;
0136   voronoi_edge_type* incident_edge_;
0137   mutable color_type color_;
0138 };
0139 
0140 // Half-edge data structure. Represents Voronoi edge.
0141 // Data members:
0142 //   1) pointer to the corresponding cell
0143 //   2) pointer to the vertex that is the starting
0144 //      point of the half-edge
0145 //   3) pointer to the twin edge
0146 //   4) pointer to the CCW next edge
0147 //   5) pointer to the CCW prev edge
0148 //   6) mutable color member
0149 template <typename T>
0150 class voronoi_edge {
0151  public:
0152   typedef T coordinate_type;
0153   typedef voronoi_cell<coordinate_type> voronoi_cell_type;
0154   typedef voronoi_vertex<coordinate_type> voronoi_vertex_type;
0155   typedef voronoi_edge<coordinate_type> voronoi_edge_type;
0156   typedef std::size_t color_type;
0157 
0158   voronoi_edge(bool is_linear, bool is_primary) :
0159       cell_(NULL),
0160       vertex_(NULL),
0161       twin_(NULL),
0162       next_(NULL),
0163       prev_(NULL),
0164       color_(0) {
0165     if (is_linear)
0166       color_ |= BIT_IS_LINEAR;
0167     if (is_primary)
0168       color_ |= BIT_IS_PRIMARY;
0169   }
0170 
0171   voronoi_cell_type* cell() { return cell_; }
0172   const voronoi_cell_type* cell() const { return cell_; }
0173   void cell(voronoi_cell_type* c) { cell_ = c; }
0174 
0175   voronoi_vertex_type* vertex0() { return vertex_; }
0176   const voronoi_vertex_type* vertex0() const { return vertex_; }
0177   void vertex0(voronoi_vertex_type* v) { vertex_ = v; }
0178 
0179   voronoi_vertex_type* vertex1() { return twin_->vertex0(); }
0180   const voronoi_vertex_type* vertex1() const { return twin_->vertex0(); }
0181 
0182   voronoi_edge_type* twin() { return twin_; }
0183   const voronoi_edge_type* twin() const { return twin_; }
0184   void twin(voronoi_edge_type* e) { twin_ = e; }
0185 
0186   voronoi_edge_type* next() { return next_; }
0187   const voronoi_edge_type* next() const { return next_; }
0188   void next(voronoi_edge_type* e) { next_ = e; }
0189 
0190   voronoi_edge_type* prev() { return prev_; }
0191   const voronoi_edge_type* prev() const { return prev_; }
0192   void prev(voronoi_edge_type* e) { prev_ = e; }
0193 
0194   // Returns a pointer to the rotation next edge
0195   // over the starting point of the half-edge.
0196   voronoi_edge_type* rot_next() { return prev_->twin(); }
0197   const voronoi_edge_type* rot_next() const { return prev_->twin(); }
0198 
0199   // Returns a pointer to the rotation prev edge
0200   // over the starting point of the half-edge.
0201   voronoi_edge_type* rot_prev() { return twin_->next(); }
0202   const voronoi_edge_type* rot_prev() const { return twin_->next(); }
0203 
0204   // Returns true if the edge is finite (segment, parabolic arc).
0205   // Returns false if the edge is infinite (ray, line).
0206   bool is_finite() const { return vertex0() && vertex1(); }
0207 
0208   // Returns true if the edge is infinite (ray, line).
0209   // Returns false if the edge is finite (segment, parabolic arc).
0210   bool is_infinite() const { return !vertex0() || !vertex1(); }
0211 
0212   // Returns true if the edge is linear (segment, ray, line).
0213   // Returns false if the edge is curved (parabolic arc).
0214   bool is_linear() const {
0215     return (color_ & BIT_IS_LINEAR) ? true : false;
0216   }
0217 
0218   // Returns true if the edge is curved (parabolic arc).
0219   // Returns false if the edge is linear (segment, ray, line).
0220   bool is_curved() const {
0221     return (color_ & BIT_IS_LINEAR) ? false : true;
0222   }
0223 
0224   // Returns false if edge goes through the endpoint of the segment.
0225   // Returns true else.
0226   bool is_primary() const {
0227     return (color_ & BIT_IS_PRIMARY) ? true : false;
0228   }
0229 
0230   // Returns true if edge goes through the endpoint of the segment.
0231   // Returns false else.
0232   bool is_secondary() const {
0233     return (color_ & BIT_IS_PRIMARY) ? false : true;
0234   }
0235 
0236   color_type color() const { return color_ >> BITS_SHIFT; }
0237   void color(color_type color) const {
0238     color_ &= BITS_MASK;
0239     color_ |= color << BITS_SHIFT;
0240   }
0241 
0242  private:
0243   // 5 color bits are reserved.
0244   enum Bits {
0245     BIT_IS_LINEAR = 0x1,  // linear is opposite to curved
0246     BIT_IS_PRIMARY = 0x2,  // primary is opposite to secondary
0247 
0248     BITS_SHIFT = 0x5,
0249     BITS_MASK = 0x1F
0250   };
0251 
0252   voronoi_cell_type* cell_;
0253   voronoi_vertex_type* vertex_;
0254   voronoi_edge_type* twin_;
0255   voronoi_edge_type* next_;
0256   voronoi_edge_type* prev_;
0257   mutable color_type color_;
0258 };
0259 
0260 template <typename T>
0261 struct voronoi_diagram_traits {
0262   typedef T coordinate_type;
0263   typedef voronoi_cell<coordinate_type> cell_type;
0264   typedef voronoi_vertex<coordinate_type> vertex_type;
0265   typedef voronoi_edge<coordinate_type> edge_type;
0266   class vertex_equality_predicate_type {
0267    public:
0268     enum { ULPS = 128 };
0269     bool operator()(const vertex_type& v1, const vertex_type& v2) const {
0270       return (ulp_cmp(v1.x(), v2.x(), ULPS) ==
0271               detail::ulp_comparison<T>::EQUAL) &&
0272              (ulp_cmp(v1.y(), v2.y(), ULPS) ==
0273               detail::ulp_comparison<T>::EQUAL);
0274     }
0275    private:
0276     typename detail::ulp_comparison<T> ulp_cmp;
0277   };
0278 };
0279 
0280 // Voronoi output data structure.
0281 // CCW ordering is used on the faces perimeter and around the vertices.
0282 template <typename T, typename TRAITS = voronoi_diagram_traits<T> >
0283 class voronoi_diagram {
0284  public:
0285   typedef typename TRAITS::coordinate_type coordinate_type;
0286   typedef typename TRAITS::cell_type cell_type;
0287   typedef typename TRAITS::vertex_type vertex_type;
0288   typedef typename TRAITS::edge_type edge_type;
0289 
0290   typedef std::vector<cell_type> cell_container_type;
0291   typedef typename cell_container_type::const_iterator const_cell_iterator;
0292 
0293   typedef std::vector<vertex_type> vertex_container_type;
0294   typedef typename vertex_container_type::const_iterator const_vertex_iterator;
0295 
0296   typedef std::vector<edge_type> edge_container_type;
0297   typedef typename edge_container_type::const_iterator const_edge_iterator;
0298 
0299   voronoi_diagram() {}
0300 
0301   void clear() {
0302     cells_.clear();
0303     vertices_.clear();
0304     edges_.clear();
0305   }
0306 
0307   const cell_container_type& cells() const {
0308     return cells_;
0309   }
0310 
0311   const vertex_container_type& vertices() const {
0312     return vertices_;
0313   }
0314 
0315   const edge_container_type& edges() const {
0316     return edges_;
0317   }
0318 
0319   std::size_t num_cells() const {
0320     return cells_.size();
0321   }
0322 
0323   std::size_t num_edges() const {
0324     return edges_.size();
0325   }
0326 
0327   std::size_t num_vertices() const {
0328     return vertices_.size();
0329   }
0330 
0331   void _reserve(std::size_t num_sites) {
0332     cells_.reserve(num_sites);
0333     vertices_.reserve(num_sites << 1);
0334     edges_.reserve((num_sites << 2) + (num_sites << 1));
0335   }
0336 
0337   template <typename CT>
0338   void _process_single_site(const detail::site_event<CT>& site) {
0339     cells_.push_back(cell_type(site.initial_index(), site.source_category()));
0340   }
0341 
0342   // Insert a new half-edge into the output data structure.
0343   // Takes as input left and right sites that form a new bisector.
0344   // Returns a pair of pointers to a new half-edges.
0345   template <typename CT>
0346   std::pair<void*, void*> _insert_new_edge(
0347       const detail::site_event<CT>& site1,
0348       const detail::site_event<CT>& site2) {
0349     // Get sites' indexes.
0350     std::size_t site_index1 = site1.sorted_index();
0351     std::size_t site_index2 = site2.sorted_index();
0352 
0353     bool is_linear = is_linear_edge(site1, site2);
0354     bool is_primary = is_primary_edge(site1, site2);
0355 
0356     // Create a new half-edge that belongs to the first site.
0357     edges_.push_back(edge_type(is_linear, is_primary));
0358     edge_type& edge1 = edges_.back();
0359 
0360     // Create a new half-edge that belongs to the second site.
0361     edges_.push_back(edge_type(is_linear, is_primary));
0362     edge_type& edge2 = edges_.back();
0363 
0364     // Add the initial cell during the first edge insertion.
0365     if (cells_.empty()) {
0366       cells_.push_back(cell_type(
0367           site1.initial_index(), site1.source_category()));
0368     }
0369 
0370     // The second site represents a new site during site event
0371     // processing. Add a new cell to the cell records.
0372     cells_.push_back(cell_type(
0373         site2.initial_index(), site2.source_category()));
0374 
0375     // Set up pointers to cells.
0376     edge1.cell(&cells_[site_index1]);
0377     edge2.cell(&cells_[site_index2]);
0378 
0379     // Set up twin pointers.
0380     edge1.twin(&edge2);
0381     edge2.twin(&edge1);
0382 
0383     // Return a pointer to the new half-edge.
0384     return std::make_pair(&edge1, &edge2);
0385   }
0386 
0387   // Insert a new half-edge into the output data structure with the
0388   // start at the point where two previously added half-edges intersect.
0389   // Takes as input two sites that create a new bisector, circle event
0390   // that corresponds to the intersection point of the two old half-edges,
0391   // pointers to those half-edges. Half-edges' direction goes out of the
0392   // new Voronoi vertex point. Returns a pair of pointers to a new half-edges.
0393   template <typename CT1, typename CT2>
0394   std::pair<void*, void*> _insert_new_edge(
0395       const detail::site_event<CT1>& site1,
0396       const detail::site_event<CT1>& site3,
0397       const detail::circle_event<CT2>& circle,
0398       void* data12, void* data23) {
0399     edge_type* edge12 = static_cast<edge_type*>(data12);
0400     edge_type* edge23 = static_cast<edge_type*>(data23);
0401 
0402     // Add a new Voronoi vertex.
0403     vertices_.push_back(vertex_type(circle.x(), circle.y()));
0404     vertex_type& new_vertex = vertices_.back();
0405 
0406     // Update vertex pointers of the old edges.
0407     edge12->vertex0(&new_vertex);
0408     edge23->vertex0(&new_vertex);
0409 
0410     bool is_linear = is_linear_edge(site1, site3);
0411     bool is_primary = is_primary_edge(site1, site3);
0412 
0413     // Add a new half-edge.
0414     edges_.push_back(edge_type(is_linear, is_primary));
0415     edge_type& new_edge1 = edges_.back();
0416     new_edge1.cell(&cells_[site1.sorted_index()]);
0417 
0418     // Add a new half-edge.
0419     edges_.push_back(edge_type(is_linear, is_primary));
0420     edge_type& new_edge2 = edges_.back();
0421     new_edge2.cell(&cells_[site3.sorted_index()]);
0422 
0423     // Update twin pointers.
0424     new_edge1.twin(&new_edge2);
0425     new_edge2.twin(&new_edge1);
0426 
0427     // Update vertex pointer.
0428     new_edge2.vertex0(&new_vertex);
0429 
0430     // Update Voronoi prev/next pointers.
0431     edge12->prev(&new_edge1);
0432     new_edge1.next(edge12);
0433     edge12->twin()->next(edge23);
0434     edge23->prev(edge12->twin());
0435     edge23->twin()->next(&new_edge2);
0436     new_edge2.prev(edge23->twin());
0437 
0438     // Return a pointer to the new half-edge.
0439     return std::make_pair(&new_edge1, &new_edge2);
0440   }
0441 
0442   void _build() {
0443     // Remove degenerate edges.
0444     edge_iterator last_edge = edges_.begin();
0445     for (edge_iterator it = edges_.begin(); it != edges_.end(); it += 2) {
0446       const vertex_type* v1 = it->vertex0();
0447       const vertex_type* v2 = it->vertex1();
0448       if (v1 && v2 && vertex_equality_predicate_(*v1, *v2)) {
0449         remove_edge(&(*it));
0450       } else {
0451         if (it != last_edge) {
0452           edge_type* e1 = &(*last_edge = *it);
0453           edge_type* e2 = &(*(last_edge + 1) = *(it + 1));
0454           e1->twin(e2);
0455           e2->twin(e1);
0456           if (e1->prev()) {
0457             e1->prev()->next(e1);
0458             e2->next()->prev(e2);
0459           }
0460           if (e2->prev()) {
0461             e1->next()->prev(e1);
0462             e2->prev()->next(e2);
0463           }
0464         }
0465         last_edge += 2;
0466       }
0467     }
0468     edges_.erase(last_edge, edges_.end());
0469 
0470     // Set up incident edge pointers for cells and vertices.
0471     for (edge_iterator it = edges_.begin(); it != edges_.end(); ++it) {
0472       it->cell()->incident_edge(&(*it));
0473       if (it->vertex0()) {
0474         it->vertex0()->incident_edge(&(*it));
0475       }
0476     }
0477 
0478     // Remove degenerate vertices.
0479     vertex_iterator last_vertex = vertices_.begin();
0480     for (vertex_iterator it = vertices_.begin(); it != vertices_.end(); ++it) {
0481       if (it->incident_edge()) {
0482         if (it != last_vertex) {
0483           *last_vertex = *it;
0484           vertex_type* v = &(*last_vertex);
0485           edge_type* e = v->incident_edge();
0486           do {
0487             e->vertex0(v);
0488             e = e->rot_next();
0489           } while (e != v->incident_edge());
0490         }
0491         ++last_vertex;
0492       }
0493     }
0494     vertices_.erase(last_vertex, vertices_.end());
0495 
0496     // Set up next/prev pointers for infinite edges.
0497     if (vertices_.empty()) {
0498       if (!edges_.empty()) {
0499         // Update prev/next pointers for the line edges.
0500         edge_iterator edge_it = edges_.begin();
0501         edge_type* edge1 = &(*edge_it);
0502         edge1->next(edge1);
0503         edge1->prev(edge1);
0504         ++edge_it;
0505         edge1 = &(*edge_it);
0506         ++edge_it;
0507 
0508         while (edge_it != edges_.end()) {
0509           edge_type* edge2 = &(*edge_it);
0510           ++edge_it;
0511 
0512           edge1->next(edge2);
0513           edge1->prev(edge2);
0514           edge2->next(edge1);
0515           edge2->prev(edge1);
0516 
0517           edge1 = &(*edge_it);
0518           ++edge_it;
0519         }
0520 
0521         edge1->next(edge1);
0522         edge1->prev(edge1);
0523       }
0524     } else {
0525       // Update prev/next pointers for the ray edges.
0526       for (cell_iterator cell_it = cells_.begin();
0527          cell_it != cells_.end(); ++cell_it) {
0528         if (cell_it->is_degenerate())
0529           continue;
0530         // Move to the previous edge while
0531         // it is possible in the CW direction.
0532         edge_type* left_edge = cell_it->incident_edge();
0533         while (left_edge->prev() != NULL) {
0534           left_edge = left_edge->prev();
0535           // Terminate if this is not a boundary cell.
0536           if (left_edge == cell_it->incident_edge())
0537             break;
0538         }
0539 
0540         if (left_edge->prev() != NULL)
0541           continue;
0542 
0543         edge_type* right_edge = cell_it->incident_edge();
0544         while (right_edge->next() != NULL)
0545           right_edge = right_edge->next();
0546         left_edge->prev(right_edge);
0547         right_edge->next(left_edge);
0548       }
0549     }
0550   }
0551 
0552  private:
0553   typedef typename cell_container_type::iterator cell_iterator;
0554   typedef typename vertex_container_type::iterator vertex_iterator;
0555   typedef typename edge_container_type::iterator edge_iterator;
0556   typedef typename TRAITS::vertex_equality_predicate_type
0557     vertex_equality_predicate_type;
0558 
0559   template <typename SEvent>
0560   bool is_primary_edge(const SEvent& site1, const SEvent& site2) const {
0561     bool flag1 = site1.is_segment();
0562     bool flag2 = site2.is_segment();
0563     if (flag1 && !flag2) {
0564       return (site1.point0() != site2.point0()) &&
0565              (site1.point1() != site2.point0());
0566     }
0567     if (!flag1 && flag2) {
0568       return (site2.point0() != site1.point0()) &&
0569              (site2.point1() != site1.point0());
0570     }
0571     return true;
0572   }
0573 
0574   template <typename SEvent>
0575   bool is_linear_edge(const SEvent& site1, const SEvent& site2) const {
0576     if (!is_primary_edge(site1, site2)) {
0577       return true;
0578     }
0579     return !(site1.is_segment() ^ site2.is_segment());
0580   }
0581 
0582   // Remove degenerate edge.
0583   void remove_edge(edge_type* edge) {
0584     // Update the endpoints of the incident edges to the second vertex.
0585     vertex_type* vertex = edge->vertex0();
0586     edge_type* updated_edge = edge->twin()->rot_next();
0587     while (updated_edge != edge->twin()) {
0588       updated_edge->vertex0(vertex);
0589       updated_edge = updated_edge->rot_next();
0590     }
0591 
0592     edge_type* edge1 = edge;
0593     edge_type* edge2 = edge->twin();
0594 
0595     edge_type* edge1_rot_prev = edge1->rot_prev();
0596     edge_type* edge1_rot_next = edge1->rot_next();
0597 
0598     edge_type* edge2_rot_prev = edge2->rot_prev();
0599     edge_type* edge2_rot_next = edge2->rot_next();
0600 
0601     // Update prev/next pointers for the incident edges.
0602     edge1_rot_next->twin()->next(edge2_rot_prev);
0603     edge2_rot_prev->prev(edge1_rot_next->twin());
0604     edge1_rot_prev->prev(edge2_rot_next->twin());
0605     edge2_rot_next->twin()->next(edge1_rot_prev);
0606   }
0607 
0608   cell_container_type cells_;
0609   vertex_container_type vertices_;
0610   edge_container_type edges_;
0611   vertex_equality_predicate_type vertex_equality_predicate_;
0612 
0613   // Disallow copy constructor and operator=
0614   voronoi_diagram(const voronoi_diagram&);
0615   void operator=(const voronoi_diagram&);
0616 };
0617 }  // polygon
0618 }  // boost
0619 
0620 #endif  // BOOST_POLYGON_VORONOI_DIAGRAM