voronoi_basic_tutorial.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. // Boost.Polygon library voronoi_basic_tutorial.cpp file
  2. // Copyright Andrii Sydorchuk 2010-2012.
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // (See accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. // See http://www.boost.org for updates, documentation, and revision history.
  7. #include <cstdio>
  8. #include <vector>
  9. #include <boost/polygon/voronoi.hpp>
  10. using boost::polygon::voronoi_builder;
  11. using boost::polygon::voronoi_diagram;
  12. using boost::polygon::x;
  13. using boost::polygon::y;
  14. using boost::polygon::low;
  15. using boost::polygon::high;
  16. #include "voronoi_visual_utils.hpp"
  17. struct Point {
  18. int a;
  19. int b;
  20. Point(int x, int y) : a(x), b(y) {}
  21. };
  22. struct Segment {
  23. Point p0;
  24. Point p1;
  25. Segment(int x1, int y1, int x2, int y2) : p0(x1, y1), p1(x2, y2) {}
  26. };
  27. namespace boost {
  28. namespace polygon {
  29. template <>
  30. struct geometry_concept<Point> {
  31. typedef point_concept type;
  32. };
  33. template <>
  34. struct point_traits<Point> {
  35. typedef int coordinate_type;
  36. static inline coordinate_type get(
  37. const Point& point, orientation_2d orient) {
  38. return (orient == HORIZONTAL) ? point.a : point.b;
  39. }
  40. };
  41. template <>
  42. struct geometry_concept<Segment> {
  43. typedef segment_concept type;
  44. };
  45. template <>
  46. struct segment_traits<Segment> {
  47. typedef int coordinate_type;
  48. typedef Point point_type;
  49. static inline point_type get(const Segment& segment, direction_1d dir) {
  50. return dir.to_int() ? segment.p1 : segment.p0;
  51. }
  52. };
  53. } // polygon
  54. } // boost
  55. // Traversing Voronoi edges using edge iterator.
  56. int iterate_primary_edges1(const voronoi_diagram<double>& vd) {
  57. int result = 0;
  58. for (voronoi_diagram<double>::const_edge_iterator it = vd.edges().begin();
  59. it != vd.edges().end(); ++it) {
  60. if (it->is_primary())
  61. ++result;
  62. }
  63. return result;
  64. }
  65. // Traversing Voronoi edges using cell iterator.
  66. int iterate_primary_edges2(const voronoi_diagram<double> &vd) {
  67. int result = 0;
  68. for (voronoi_diagram<double>::const_cell_iterator it = vd.cells().begin();
  69. it != vd.cells().end(); ++it) {
  70. const voronoi_diagram<double>::cell_type& cell = *it;
  71. const voronoi_diagram<double>::edge_type* edge = cell.incident_edge();
  72. // This is convenient way to iterate edges around Voronoi cell.
  73. do {
  74. if (edge->is_primary())
  75. ++result;
  76. edge = edge->next();
  77. } while (edge != cell.incident_edge());
  78. }
  79. return result;
  80. }
  81. // Traversing Voronoi edges using vertex iterator.
  82. // As opposite to the above two functions this one will not iterate through
  83. // edges without finite endpoints and will iterate only once through edges
  84. // with single finite endpoint.
  85. int iterate_primary_edges3(const voronoi_diagram<double> &vd) {
  86. int result = 0;
  87. for (voronoi_diagram<double>::const_vertex_iterator it =
  88. vd.vertices().begin(); it != vd.vertices().end(); ++it) {
  89. const voronoi_diagram<double>::vertex_type& vertex = *it;
  90. const voronoi_diagram<double>::edge_type* edge = vertex.incident_edge();
  91. // This is convenient way to iterate edges around Voronoi vertex.
  92. do {
  93. if (edge->is_primary())
  94. ++result;
  95. edge = edge->rot_next();
  96. } while (edge != vertex.incident_edge());
  97. }
  98. return result;
  99. }
  100. int main() {
  101. // Preparing Input Geometries.
  102. std::vector<Point> points;
  103. points.push_back(Point(0, 0));
  104. points.push_back(Point(1, 6));
  105. std::vector<Segment> segments;
  106. segments.push_back(Segment(-4, 5, 5, -1));
  107. segments.push_back(Segment(3, -11, 13, -1));
  108. // Construction of the Voronoi Diagram.
  109. voronoi_diagram<double> vd;
  110. construct_voronoi(points.begin(), points.end(),
  111. segments.begin(), segments.end(),
  112. &vd);
  113. // Traversing Voronoi Graph.
  114. {
  115. printf("Traversing Voronoi graph.\n");
  116. printf("Number of visited primary edges using edge iterator: %d\n",
  117. iterate_primary_edges1(vd));
  118. printf("Number of visited primary edges using cell iterator: %d\n",
  119. iterate_primary_edges2(vd));
  120. printf("Number of visited primary edges using vertex iterator: %d\n",
  121. iterate_primary_edges3(vd));
  122. printf("\n");
  123. }
  124. // Using color member of the Voronoi primitives to store the average number
  125. // of edges around each cell (including secondary edges).
  126. {
  127. printf("Number of edges (including secondary) around the Voronoi cells:\n");
  128. for (voronoi_diagram<double>::const_edge_iterator it = vd.edges().begin();
  129. it != vd.edges().end(); ++it) {
  130. std::size_t cnt = it->cell()->color();
  131. it->cell()->color(cnt + 1);
  132. }
  133. for (voronoi_diagram<double>::const_cell_iterator it = vd.cells().begin();
  134. it != vd.cells().end(); ++it) {
  135. printf("%lu ", it->color());
  136. }
  137. printf("\n");
  138. printf("\n");
  139. }
  140. // Linking Voronoi cells with input geometries.
  141. {
  142. unsigned int cell_index = 0;
  143. for (voronoi_diagram<double>::const_cell_iterator it = vd.cells().begin();
  144. it != vd.cells().end(); ++it) {
  145. if (it->contains_point()) {
  146. if (it->source_category() ==
  147. boost::polygon::SOURCE_CATEGORY_SINGLE_POINT) {
  148. std::size_t index = it->source_index();
  149. Point p = points[index];
  150. printf("Cell #%u contains a point: (%d, %d).\n",
  151. cell_index, x(p), y(p));
  152. } else if (it->source_category() ==
  153. boost::polygon::SOURCE_CATEGORY_SEGMENT_START_POINT) {
  154. std::size_t index = it->source_index() - points.size();
  155. Point p0 = low(segments[index]);
  156. printf("Cell #%u contains segment start point: (%d, %d).\n",
  157. cell_index, x(p0), y(p0));
  158. } else if (it->source_category() ==
  159. boost::polygon::SOURCE_CATEGORY_SEGMENT_END_POINT) {
  160. std::size_t index = it->source_index() - points.size();
  161. Point p1 = high(segments[index]);
  162. printf("Cell #%u contains segment end point: (%d, %d).\n",
  163. cell_index, x(p1), y(p1));
  164. }
  165. } else {
  166. std::size_t index = it->source_index() - points.size();
  167. Point p0 = low(segments[index]);
  168. Point p1 = high(segments[index]);
  169. printf("Cell #%u contains a segment: ((%d, %d), (%d, %d)). \n",
  170. cell_index, x(p0), y(p0), x(p1), y(p1));
  171. }
  172. ++cell_index;
  173. }
  174. }
  175. return 0;
  176. }