]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/polygon/doc/voronoi_basic_tutorial.htm
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / polygon / doc / voronoi_basic_tutorial.htm
CommitLineData
7c673cae
FG
1<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
2<html><head>
3
4
5
6
7
8
9
10
11
12
13
14
15 <meta http-equiv="Content-Type" content="text/html; charset=windows-1252"><title>Voronoi Basic Tutorial</title><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body>
16<h1>Voronoi Basic Tutorial<br>
17</h1>
18
19<p>In this tutorial we will cover the basic usage of the Boost.Polygon
20Voronoi library that should be enough for the 95% of cases. Below we will
21discuss the following topics:<br>
22</p>
23
24<ul>
25
26 <li>preparing input geometries<br>
27 </li>
28 <li>Voronoi diagram construction</li>
29
30 <li>Voronoi graph traversal<br>
31 </li>
32
33 <li>associating the user data with the Voronoi primitives</li>
34 <li>accessing input site inside the Voronoi cell</li>
35 <li>Voronoi diagram rendering<br>
36 </li>
37
38
39</ul>
40
41In the example that goes through this tutorial (<a href="../example/voronoi_basic_tutorial.cpp">voronoi_basic_tutorial.cpp</a>)
42we
43are going to construct the Voronoi diagram of a few points and
44segments.
45On the image below one may see the corresponding rendered Voronoi
46graph. The primary Voronoi edges
47are marked with
48the black color, non-primary with green, input geometries have blue
49color. We split each input segment onto three sites (segment
50itself and both endpoints), edges that go between the sites corresponding to the same segment are
51considered to be non-primary.<br>
52
53<br>
54
55<img style="border: 2px solid ; width: 300px; height: 300px;" alt="" src="images/voronoi4.png"><br>
56
57<br>
58
59And before you proceed don't forget to:<span style="font-family: Courier New,Courier,monospace;"><br>
60</span><span style="font-family: Courier New,Courier,monospace;"></span><br>
61<span style="font-family: Courier New,Courier,monospace;">#include "boost/polygon/voronoi.hpp"<br>
62using boost::polygon::voronoi_builder;<br>
63using boost::polygon::voronoi_diagram;<br>
64</span>
65
66<h2>Preparing Input Geometries</h2>Below is the example of how the user provided point and segment classes might look like:<br>
67<br><span style="font-family: Courier New,Courier,monospace;">struct Point {<br>&nbsp; int a;<br>
68&nbsp; int b;<br>
69&nbsp; Point (int x, int y) : a(x), b(y) {}<br>
70
71};</span><span style="font-family: Courier New,Courier,monospace;"><br>
72<br>struct Segment {</span><span style="font-family: Courier New,Courier,monospace;"></span><br>
73<span style="font-family: Courier New,Courier,monospace;">
74&nbsp; Point p0;<br>
75&nbsp; Point p1;<br>
76&nbsp; Segment (int x1, int y1, int x2, int y2) : p0(x1, y1), p1(x2, y2) {}<br>
77</span><span style="font-family: Courier New,Courier,monospace;"></span>
78
79<span style="font-family: Courier New,Courier,monospace;">};<br>
80<br>
81</span>As we are going to use the default routines defined in the
82voronoi.hpp header to construct the Voronoi diagram, we are required to map
83our point and segment classes to the corresponding Boost.Polygon concepts:<br>
84<br>
85<span style="color: rgb(0, 0, 0); font-family: 'Courier New'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium; display: inline ! important; float: none;">template &lt;&gt;</span><span style="color: rgb(0, 0, 0); font-family: 'Courier New'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium; display: inline ! important; float: none;"><br>
86struct geometry_concept&lt;Point&gt; { typedef point_concept type; };</span><br style="color: rgb(0, 0, 0); font-family: 'Courier New'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;"><span style="color: rgb(0, 0, 0); font-family: 'Courier New'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium; display: inline ! important; float: none;"></span><span style="color: rgb(0, 0, 0); font-family: 'Courier New'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium; display: inline ! important; float: none;">&nbsp;&nbsp; <span class="Apple-converted-space"></span></span><span style="color: rgb(0, 0, 0); font-family: 'Courier New'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium; display: inline ! important; float: none;"></span><br style="color: rgb(0, 0, 0); font-family: 'Courier New'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;"><span style="color: rgb(0, 0, 0); font-family: 'Courier New'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium; display: inline ! important; float: none;">template &lt;&gt;</span><br style="color: rgb(0, 0, 0); font-family: 'Courier New'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;"><span style="color: rgb(0, 0, 0); font-family: 'Courier New'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium; display: inline ! important; float: none;">struct point_traits&lt;</span><span style="font-family: Courier New,Courier,monospace;">Point</span><span style="color: rgb(0, 0, 0); font-family: 'Courier New'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium; display: inline ! important; float: none;">&gt; {</span><br style="color: rgb(0, 0, 0); font-family: 'Courier New'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;"><span style="color: rgb(0, 0, 0); font-family: 'Courier New'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium; display: inline ! important; float: none;">&nbsp; typedef int coordinate_type;</span><span style="color: rgb(0, 0, 0); font-family: 'Courier New'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium; display: inline ! important; float: none;"><br>
87&nbsp; &nbsp;<span class="Apple-converted-space"> </span></span><br style="color: rgb(0, 0, 0); font-family: 'Courier New'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;"><span style="color: rgb(0, 0, 0); font-family: 'Courier New'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium; display: inline ! important; float: none;">&nbsp; static inline coordinate_type get(const </span><span style="font-family: Courier New,Courier,monospace;">Point</span><span style="color: rgb(0, 0, 0); font-family: 'Courier New'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium; display: inline ! important; float: none;">&amp; point,<span class="Apple-converted-space"> </span></span><span style="color: rgb(0, 0, 0); font-family: 'Courier New'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium; display: inline ! important; float: none;">orientation_2d orient) {<br>
88&nbsp;&nbsp;&nbsp; return </span><span style="color: rgb(0, 0, 0); font-family: 'Courier New'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium; display: inline ! important; float: none;">(orient == HORIZONTAL) ? point.a : point.b;</span><span style="color: rgb(0, 0, 0); font-family: 'Courier New'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium; display: inline ! important; float: none;"></span><br style="color: rgb(0, 0, 0); font-family: 'Courier New'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;"><span style="color: rgb(0, 0, 0); font-family: 'Courier New'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium; display: inline ! important; float: none;">&nbsp; }<br>
89};</span><br>
90<span style="color: rgb(0, 0, 0); font-family: 'Courier New'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium; display: inline ! important; float: none;">
91<br>
92template &lt;&gt;<br>
93</span><span style="color: rgb(0, 0, 0); font-family: 'Courier New'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium; display: inline ! important; float: none;">struct geometry_concept&lt;Segment&gt; { typedef segment_concept type; };<br>
94<br>
95</span><span style="color: rgb(0, 0, 0); font-family: 'Courier New'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium; display: inline ! important; float: none;">template &lt;&gt;</span><br style="color: rgb(0, 0, 0); font-family: 'Courier New'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;">
96<span style="color: rgb(0, 0, 0); font-family: 'Courier New'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium; display: inline ! important; float: none;">struct point_traits&lt;</span><span style="font-family: Courier New,Courier,monospace;">Segment</span><span style="color: rgb(0, 0, 0); font-family: 'Courier New'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium; display: inline ! important; float: none;">&gt; {</span><br style="color: rgb(0, 0, 0); font-family: 'Courier New'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;">
97<span style="color: rgb(0, 0, 0); font-family: 'Courier New'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium; display: inline ! important; float: none;">&nbsp; typedef int coordinate_type;<br>
98&nbsp; typedef Point point_type;<br style="color: rgb(0, 0, 0); font-family: 'Courier New'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;">
99</span>
100<span style="color: rgb(0, 0, 0); font-family: 'Courier New'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium; display: inline ! important; float: none;">&nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span></span><br style="color: rgb(0, 0, 0); font-family: 'Courier New'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;">
101<span style="color: rgb(0, 0, 0); font-family: 'Courier New'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium; display: inline ! important; float: none;">&nbsp; static inline coordinate_type get(const </span><span style="font-family: Courier New,Courier,monospace;">Segment</span><span style="color: rgb(0, 0, 0); font-family: 'Courier New'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium; display: inline ! important; float: none;">&amp; segment,<span class="Apple-converted-space"> direction_1d dir</span></span><span style="color: rgb(0, 0, 0); font-family: 'Courier New'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium; display: inline ! important; float: none;">) {<br>
102&nbsp;&nbsp;&nbsp; return </span><span style="color: rgb(0, 0, 0); font-family: 'Courier New'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium; display: inline ! important; float: none;">dir.to_int() ? segment.p1() : segment.p0();</span><span style="color: rgb(0, 0, 0); font-family: 'Courier New'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium; display: inline ! important; float: none;"></span><br style="color: rgb(0, 0, 0); font-family: 'Courier New'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;">
103<span style="color: rgb(0, 0, 0); font-family: 'Courier New'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium; display: inline ! important; float: none;">&nbsp; }<br>};</span><br>
104<br>
105It's also possible to use the native Boost.Polygon types as <a href="../../../boost/polygon/point_data.hpp">point_data</a> and <a href="../../../boost/polygon/segment_data.hpp">segment_data</a>, that won't require the above mapping.<br>
106<br>
107So once we are done we can create the sample input:<br>
108
109<br>
110
111<span style="font-family: Courier New,Courier,monospace;">std::vector&lt;Point&gt;
112points;<br>
113points.push_back(Point(0, 0));<br>
114points.push_back(Point(1, 6));<br>
115std::vector&lt;Segment&gt; segments;<br>
116segments.push_back(Segment(-4, 5, 5, -1));<br>
117segments.push_back(Segment(3, -11, 13, -1));</span><span style="font-family: Courier New,Courier,monospace;"><br>
118</span>
119<h2>Construction of the Voronoi Diagram<br>
120</h2>At this point we are ready to construct the Voronoi diagram:<br>
121<span style="font-family: Courier New,Courier,monospace;"><br>
122</span><span style="font-family: Courier New,Courier,monospace;">
123voronoi_diagram&lt;double&gt; vd;<br>
124construct_voronoi(points.begin(), points.end(), segments.begin(), segments.end(), &amp;vd);</span><br>
125
126<h2>Traversing Voronoi Graph</h2>
127
128Voronoi graph traversal is the basic
129operation one would like to do once the Voronoi diagram is constructed.
130There are three ways to do that and we are going to cover all of them:<br>
131
132<ul>
133
134 <li>simply iterating over the Voronoi edges (counts each edge twice):<br>
135 <span style="font-family: Courier New,Courier,monospace;"><br>
136int iterate_primary_edges1(const voronoi_diagram&lt;double&gt; &amp;vd)
137{<br>
138&nbsp; int result = 0;<br>
139&nbsp; for (voronoi_diagram&lt;double&gt;::const_edge_iterator it =
140vd.edges().begin();<br>
141&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; it != vd.edges().end(); ++it) {<br>
142&nbsp;&nbsp;&nbsp; if (it-&gt;is_primary())<br>
143&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ++result;<br>
144&nbsp; }<br>
145&nbsp; return result;<br>
146}</span><br>
147 <span style="font-family: Courier New,Courier,monospace;">&nbsp;</span><br>
148 </li>
149 <li>iterating over the Voronoi cells and then traversing edges around
150each cell (counts each edge twice):<br>
151 <br>
152 <span style="font-family: Courier New,Courier,monospace;">int
153iterate_primary_edges2(const voronoi_diagram&lt;double&gt; &amp;vd) {<br>
154&nbsp; int result = 0;<br>
155&nbsp; for (voronoi_diagram&lt;double&gt;::const_cell_iterator it =
156vd.cells().begin();<br>
157&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; it != vd.cells().end(); ++it) {<br>
158&nbsp;&nbsp;&nbsp; const voronoi_diagram&lt;double&gt;::cell_type
159&amp;cell = *it;<br>
160&nbsp;&nbsp;&nbsp; const voronoi_diagram&lt;double&gt;::edge_type *edge
161= cell.incident_edge();<br>
162&nbsp;&nbsp;&nbsp; // This is convenient way to iterate edges around
163Voronoi cell.<br>
164&nbsp;&nbsp;&nbsp; do {<br>
165&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (edge-&gt;is_primary())<br>
166&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ++result;<br>
167&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; edge = edge-&gt;next();<br>
168&nbsp;&nbsp;&nbsp; } while (edge != cell.incident_edge());<br>
169&nbsp; }<br>
170&nbsp; return result;<br>
171}</span><br>
172 <br>
173 </li>
174 <li>iterating over the Voronoi
175vertices and then traversing edges around each vertex (the number of the
176iterations through each edge is equal to the number of finite endpoints
177of the edge):<span style="font-family: Courier New,Courier,monospace;"></span><br>
178 <span style="font-family: Courier New,Courier,monospace;">int
179iterate_primary_edges3(const voronoi_diagram&lt;double&gt; &amp;vd) {<br>
180&nbsp; int result = 0;<br>
181&nbsp; for (voronoi_diagram&lt;double&gt;::const_vertex_iterator it =
182vd.vertices().begin();<br>
183&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; it != vd.vertices().end(); ++it) {<br>
184&nbsp;&nbsp;&nbsp; const voronoi_diagram&lt;double&gt;::vertex_type
185&amp;vertex = *it;<br>
186&nbsp;&nbsp;&nbsp; const voronoi_diagram&lt;double&gt;::edge_type *edge
187= vertex.incident_edge();<br>
188&nbsp;&nbsp;&nbsp; // This is convenient way to iterate edges around
189Voronoi vertex.<br>
190&nbsp;&nbsp;&nbsp; do {<br>
191&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (edge-&gt;is_primary())<br>
192&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ++result;<br>
193&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; edge = edge-&gt;rot_next();<br>
194&nbsp;&nbsp;&nbsp; } while (edge != vertex.incident_edge());<br>
195&nbsp; }<br>
196&nbsp; return result;<br>
197}</span></li>
198</ul>
199
200This should give a very nice idea on how to do the Voronoi
201diagram traversal. Notice that while the output from the first two methods should
202be the same, it wouldn't for the third one. The reason is that in the
203last case we will iterate only once through the edges with a single
204finite endpoint and will skip all the edges with no finite endpoints.<br>
205
206<h2>Associating User Data with Voronoi Primitives</h2>
207
208A few simple cases of associating the user data with the Voronoi primitives are
209following:<br>
210
211<ul>
212
213 <li>associating number of incident edges with each cell, vertex;</li>
214 <li>associating color information with each edge;</li>
215 <li>using DFS or BFS on the Voronoi graph requires to mark visited
216edges/vertices/cells.</li>
217</ul>
218
219We will consider the first example and will associate the total number
220of incident edges with each cell.<br>
221
222Note: Each Voronoi primitive contains mutable color member,
223that allows to use it for the graph algorithms or associate user data via array indices.<br>
224
225<br style="font-family: Courier New,Courier,monospace;">
226
227<span style="font-family: Courier New,Courier,monospace;">// Using color member of the Voronoi primitives to store the average number<br>
228// of edges around each cell (including secondary edges).<br>
229{<br>
230&nbsp; printf("Number of edges (including secondary) around the Voronoi cells:\n");<br>
231&nbsp; for (voronoi_diagram&lt;double&gt;::const_edge_iterator it = vd.edges().begin();<br>
232&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; it != vd.edges().end(); ++it) {<br>
233&nbsp;&nbsp;&nbsp; std::size_t cnt = it-&gt;cell()-&gt;color();<br>
234&nbsp;&nbsp;&nbsp; it-&gt;cell()-&gt;color(cnt + 1);<br>
235&nbsp; }<br>
236&nbsp; for (voronoi_diagram&lt;double&gt;::const_cell_iterator it = vd.cells().begin();<br>
237&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; it != vd.cells().end(); ++it) {<br>
238&nbsp;&nbsp;&nbsp; printf("%lu ", it-&gt;color());<br>
239&nbsp; }<br>
240&nbsp; printf("\n");<br>
241&nbsp; printf("\n");<br>
242}</span><span style="font-family: Courier New,Courier,monospace;"></span><br>
243
244<h2>Accessing Input Site inside the Voronoi Cell</h2>
245As explained in the <a href="voronoi_diagram.htm">Voronoi diagram</a>
246section, Voronoi cells don't contain coordinates of the input
247geometries directly. Instead they contains source index and source
248category that uniquely identify input site. The below routines
249traverses over the all Voronoi cells, fetches input geometry
250corresponding to the Voronoi cell and prints coordinates of the input
251site.<br>
252<br>
253<span style="font-family: Courier New,Courier,monospace;">unsigned int cell_index = 0;</span><br style="font-family: Courier New,Courier,monospace;">
254<span style="font-family: Courier New,Courier,monospace;">for (voronoi_diagram&lt;double&gt;::const_cell_iterator it = vd.cells().begin();</span><br style="font-family: Courier New,Courier,monospace;">
255<span style="font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp;&nbsp; it != vd.cells().end(); ++it) {</span><br style="font-family: Courier New,Courier,monospace;">
256<span style="font-family: Courier New,Courier,monospace;">&nbsp; if (it-&gt;contains_point()) {</span><br style="font-family: Courier New,Courier,monospace;">
257<span style="font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp; std::size_t index = it-&gt;source_index();</span><br style="font-family: Courier New,Courier,monospace;">
258<span style="font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp; Point p = points[index];</span><br style="font-family: Courier New,Courier,monospace;">
259<span style="font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp; printf("Cell #%ud contains a point: (%d, %d).\n",</span><br style="font-family: Courier New,Courier,monospace;">
260<span style="font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cell_index, x(p), y(p));</span><br style="font-family: Courier New,Courier,monospace;">
261<span style="font-family: Courier New,Courier,monospace;">&nbsp; } else {</span><br style="font-family: Courier New,Courier,monospace;">
262<span style="font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp; std::size_t index = it-&gt;source_index() - points.size();</span><br style="font-family: Courier New,Courier,monospace;">
263<span style="font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp; Point p0 = low(segments[index]);</span><br style="font-family: Courier New,Courier,monospace;">
264<span style="font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp; Point p1 = high(segments[index]);</span><br style="font-family: Courier New,Courier,monospace;">
265<span style="font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp; if (it-&gt;source_category() ==</span><br style="font-family: Courier New,Courier,monospace;">
266<span style="font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; boost::polygon::SOURCE_CATEGORY_SEGMENT_START_POINT) {</span><br style="font-family: Courier New,Courier,monospace;">
267<span style="font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("Cell #%ud contains segment start point: (%d, %d).\n",</span><br style="font-family: Courier New,Courier,monospace;">
268<span style="font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cell_index, x(p0), y(p0));</span><br style="font-family: Courier New,Courier,monospace;">
269<span style="font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp; } else if (it-&gt;source_category() ==</span><br style="font-family: Courier New,Courier,monospace;">
270<span style="font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
271boost::polygon::SOURCE_CATEGORY_SEGMENT_END_POINT) {</span><br style="font-family: Courier New,Courier,monospace;">
272<span style="font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("Cell #%ud contains segment end point: (%d, %d).\n",</span><br style="font-family: Courier New,Courier,monospace;">
273<span style="font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cell_index, x(p0), y(p0));</span><br style="font-family: Courier New,Courier,monospace;">
274<span style="font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp; } else {</span><br style="font-family: Courier New,Courier,monospace;">
275<span style="font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("Cell #%ud contains a segment: ((%d, %d), (%d, %d)). \n",</span><br style="font-family: Courier New,Courier,monospace;">
276<span style="font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cell_index, x(p0), y(p0), x(p1), y(p1));</span><br style="font-family: Courier New,Courier,monospace;">
277<span style="font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp; }</span><br style="font-family: Courier New,Courier,monospace;">
278<span style="font-family: Courier New,Courier,monospace;">&nbsp; }</span><br style="font-family: Courier New,Courier,monospace;">
279<span style="font-family: Courier New,Courier,monospace;">&nbsp; ++cell_index;</span><br style="font-family: Courier New,Courier,monospace;">
280}<br>
281<h2>Voronoi Diagram Rendering<br>
282</h2>
283
284
285There are two main issues that don't allow to strictly render the resulting
286Voronoi diagram using such rendering tools as OpenGL or DirectX.
287Those are:<br>
288
289<ul>
290
291 <li>Some of the Voronoi edges are infinite, so should be clipped;</li>
292 <li>Some of the Voronoi edge are parabolic arcs, so should be
293discretized.</li>
294</ul>
295
296Note: This would be the issues not only for rendering tools.
297Basically every task that requires diagram to be represented as a set
298of finite segments will fall into this category.<a href="../example/voronoi_visualizer.cpp"> voronoi_visualizer.cpp</a>
299contains a simple fully featured implementation of the Voronoi diagram
300renderer using the Qt libraries. It was used to generate all the .png
301drawings under the boost/libs/polygon/example directory.<span style="text-decoration: underline;"></span><span style="font-family: Courier New,Courier,monospace;"><br>
302</span>
303<h2>Summary<br>
304</h2>
305<span style="font-family: Courier New,Courier,monospace;">
306</span>I hope the reader managed to get to this point and found the
307basic tutorial to be useful (in the end it's not so basic). Worth
308to notice that construction of the Voronoi diagram takes only two lines
309of code, everything else is about initializing input data structures,
310traversing Voronoi graph, associating data with the diagram primitives. In the
311default mode the Voronoi diagram operates with the signed int (32-bit) input
312coordinate type and double (64-bit) output coordinate type. In the <a href="voronoi_advanced_tutorial.htm">advanced Voronoi tutorial</a> we
313explain why this is enough for the 95% of cases and how to expand the
314algorithm coordinate types for the other 5%.<br>
315
316<span style="font-family: Courier New,Courier,monospace;"></span><br>
317
318<table class="docinfo" id="table1" frame="void" rules="none">
319
320 <colgroup> <col class="docinfo-name"><col class="docinfo-content"> </colgroup>
321 <tbody valign="top">
322 <tr>
323 <th class="docinfo-name">Copyright:</th>
324