]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> |
2 | <html><head> | |
3 | ||
4 | ||
5 | ||
6 | <meta http-equiv="Content-Type" content="text/html; charset=windows-1252"><title>Voronoi Advanced Tutorial</title></head><body> | |
7 | <h1>Voronoi Advanced Tutorial<br> | |
8 | </h1> | |
9 | ||
10 | This tutorial consists of two parts. The first one provides two | |
11 | examples of a real world problems that default configuration of Voronoi | |
12 | library is capable to solve. By default configuration we mean the one | |
13 | that accepts | |
14 | signed 32-bit integer and outputs floating-point (64-bit | |
15 | double) coordinates. We provide those examples to convince even the | |
16 | most skeptical users that they probably don't need to configure library | |
17 | for higher-precision input or output coordinate types. However if the | |
18 | posed problem really requires those, fully featured configuration of | |
19 | both input and output coordinate types is provided in the second part | |
20 | of this tutorial.<br> | |
21 | ||
22 | <h2>Red Planet</h2> | |
23 | ||
24 | <h3>Problem Statement</h3> | |
25 | ||
26 | <img style="width: 665px; height: 369px;" alt="" src="images/rover.jpg"><br> | |
27 | ||
28 | <br>Lets imagine that NASA is | |
29 | planning to send a new robot to Mars. Each day the center situated on Earth | |
30 | will send a destination point coordinates the robot needs to reach by | |
31 | the end of the day. Of course we'd like to save as much energy as | |
32 | possible thus choosing the shortest possible path. This would be a | |
33 | straight line in a perfect world (we don't consider curvature of | |
34 | surface), but situation becomes more complicated as there are some | |
35 | rocks and wells on Mars our robot can't go through. Behind of those our | |
36 | robot has some dimensions that might not allow it to pass narrow places.<br> | |
37 | ||
38 | <h3>Application of Voronoi diagram</h3> | |
39 | ||
40 | The problem above could be solved using Voronoi diagram. The first | |
41 | stage would be to discretize obstacles (rocks and wells) with | |
42 | polylines. Afterwards we will compute Voronoi diagram of the input set | |
43 | of segments. As each Voronoi edge is equidistant from the two closest | |
44 | sites we are able to filter edges the robot won't be able to pass due | |
45 | to it's dimensions. The last step would be to run a bit optimized A* | |
46 | algorithm to find | |
47 | the shortest or at least suboptimal path and we are done.<br> | |
48 | ||
49 | <h3>Discretization of input geometries</h3> | |
50 | ||
51 | To show how good is the default input coordinate type provided by the | |
52 | Voronoi library | |
53 | we will discretize the whole area of Mars. That will be approximately | |
54 | 1.44 * 10^8 square kilometres that is equal to 1.44 * | |
55 | 10^18 square centimetres, which could be snapped to the integer | |
56 | grid with a side of 1.2 * 10^9 centimetres. To make the Voronoi | |
57 | graph | |
58 | precise on the boundaries of that grid we will replicate input map 9 | |
59 | times (3x3), thus Voronoi diagram within a central piece will | |
60 | provide us with a correct connectivity graph. This step will increase | |
61 | the size of our grid to 3.6 * 10^9 centimetres that is less than 2^32. | |
62 | So we are able to discretize the Red Planet's surface within a 1 | |
63 | centimetre | |
64 | precision using the default input coordinate type (signed 32-bit | |
65 | integer). That would imply maximum absolute error to be | |
66 | equal up to 0.5 centimetres per coordinate. Considering the radius of | |
67 | our robot to be | |
68 | 0.3 metres and for security reasons avoiding any large enough obstacles | |
69 | that are within 1 metre distance from it that error would be irrelevant.<br> | |
70 | ||
71 | <span style="color: rgb(0, 0, 0); font-family: sans-serif; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 13px; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; background-color: rgb(249, 249, 249); display: inline ! important; float: none;"></span> | |
72 | <h3>Output analysis</h3> | |
73 | ||
74 | Estimates of the resulting Voronoi diagram precision were already | |
75 | explained <a href="voronoi_main.htm">here</a>. | |
76 | So to avoid those computations again we will simply state that the | |
77 | maximum absolute error of the output geometries will be on the grid | |
78 | boundaries and will be equal to 2^-16 centimetres, which is | |
79 | approximately equal to 150 nanometres and is 100 times larger than | |
80 | a radius of a complex molecule. We would like to notice that the | |
81 | absolute error of the discretization step is much higher than the one | |
82 | produced by the Voronoi diagram construction algorithm. | |
83 | <h2>VLSI Design</h2> | |
84 | ||
85 | <h3>Problem Statement</h3> | |
86 | ||
87 | <img style="width: 400px; height: 283px;" alt="" src="images/vlsi.jpg"><br> | |
88 | ||
89 | <br> | |
90 | ||
91 | Very-large-scale integration (<a href="http://www.rulabinsky.com/cavd/index.html">VLSI</a>) is the | |
92 | process of creating | |
93 | integrated circuits by combining thousands of transistors into a single | |
94 | chip. Considering the fact that it may take weeks or months to get an | |
95 | integrated circuit manufactured, designers often spend large amounts of | |
96 | time analyzing their layouts to avoid costly mistakes. One of the | |
97 | common static analysis checks is minimum distance requirement between | |
98 | the components of an integrated circuit (distance should be greater | |
99 | than | |
100 | specified value).<br> | |
101 | ||
102 | <h3>Application of Voronoi diagram</h3> | |
103 | ||
104 | It appears that the minimum distance between components of the input | |
105 | set of points and segments corresponds to the one of the Voronoi | |
106 | diagram edges. This means that we can iterate through each edge of | |
107 | the Voronoi graph, extract the pair of input geometries that form it | |
108 | and find | |
109 | the distance between those. As the total amount of such edges is O(N) | |
110 | value | |
111 | (N - is the number of input geometries) the minimum distance could be | |
112 | efficiently find in a linear time once we construct the diagram.<br> | |
113 | ||
114 | <h3>Discretization of input geometries</h3> | |
115 | ||
116 | The average size of the modern CPUs is around 2.5 x 2.5 centimetres. | |
117 | Snapping this to the 32-bit integer grid will give discretization | |
118 | precision of 2.5 / 2^33 centimetres or 3 picometres that is 10 times | |
119 | smaller value than radius of an atom. That would be probably good | |
120 | enough precision even for a few next generations of processors.<br> | |
121 | ||
122 | <h3>Output analysis</h3> | |
123 | ||
124 | The maximum absolute error of the output geometries will be 2.5 / 2^47 | |
125 | centimetres or 0.2 femtometres that is 10 times smaller value than | |
126 | the radius of an electron. However in this particular case we are not | |
127 | interested in the precision of the output, rather in its topology. As | |
128 | it was noticed on | |
129 | the <a href="voronoi_main.htm">Voronoi main page</a> very small edges | |
130 | are removed from the Voronoi diagram. However user should not worry | |
131 | because the edge that correspond to the minimal distance won't be among | |
132 | those. That means that we would be able to 100% correctly identify a | |
133 | pair of closest objects within the discretization precision.<br> | |
134 | ||
135 | <h2>Conclusions</h2> | |
136 | ||
137 | The above two examples show usage of the default Voronoi coordinate | |
138 | types | |
139 | in the macro and micro world. The main point of those was to give the user | |
140 | understanding of a scale that the default coordinate types provide. There | |
141 | are | |
142 | two main points we didn't mention before, but that would be relevant to | |
143 | the most real world problems:<br> | |
144 | ||
145 | <ul> | |
146 | ||
147 | <li>The absolute error of the coordinates of the output Voronoi | |
148 | diagram | |
149 | inside the 32-bit integer discretization grid is slightly smaller than | |
150 | the absolute error of discretization itself, thus could be neglected at | |
151 | all.</li> | |
152 | <li>In both problems above we didn't consider error of measurement. | |
153 | For example: is it possible to construct a map of the Mars within the | |
154 | 0.5 | |
155 | centimetres precision, or to get coordinates of the circuit parts | |
156 | withing the subatomic precision? I guess the answer for both questions | |
157 | would be "No". And that actually means that the error of the | |
158 | discretization | |
159 | step could be neglected comparing to the error produced by the | |
160 | measuring | |
161 | devices.<br> | |
162 | </li> | |
163 | </ul> | |
164 | The second statement means that there is actually no point to provide | |
165 | implementation that operates with floating-point input coordinates, | |
166 | because those always could be snapped to the integer grid. In case the | |
167 | user is not satisfied with the precision that the 32-bit integer grid | |
168 | provides or would like to retrieve coordinates of the output geometries | |
169 | within a smaller | |
170 | relative error, follow the next paragraph.<br> | |
171 | ||
172 | <h2>Voronoi Coordinate Types Configuration</h2> | |
173 | ||
174 | In the following chapter we are going to extend input coordinate type | |
175 | to the 48-bit signed | |
176 | integer and output coordinate type to the 80-bit IEEE floating-point | |
177 | type | |
178 | (long double). The code for this chapter is available in <a href="../example/voronoi_advanced_tutorial.cpp">voroni_advanced_tutorial.cpp</a>. | |
179 | While it won't be possible to compile it using the MSVC compiler (it | |
180 | doesn't | |
181 | support 80-bit long double type; ieee754.h header is required), it | |
182 | should give a clear understanding of how the library supports the user | |
183 | provided coordinate types.<br> | |
184 | ||
185 | <br> | |
186 | ||
187 | So the main step would be to declare the voronoi coordinate type traits | |
188 | that satisfy set of restrictions explained <a href="voronoi_builder.htm">here</a>:<br> | |
189 | ||
190 | <br> | |
191 | ||
192 | <span style="font-family: Courier New,Courier,monospace;">struct | |
193 | my_voronoi_ctype_traits {</span><br style="font-family: Courier New,Courier,monospace;"> | |
194 | ||
195 | <span style="font-family: Courier New,Courier,monospace;"> | |
196 | typedef boost::int64_t int_type;</span><br style="font-family: Courier New,Courier,monospace;"> | |
197 | ||
198 | <span style="font-family: Courier New,Courier,monospace;"> | |
199 | typedef detail::extended_int<3> int_x2_type;</span><br style="font-family: Courier New,Courier,monospace;"> | |
200 | ||
201 | <span style="font-family: Courier New,Courier,monospace;"> | |
202 | typedef detail::extended_int<3> uint_x2_type;</span><br style="font-family: Courier New,Courier,monospace;"> | |
203 | ||
204 | <span style="font-family: Courier New,Courier,monospace;"> | |
205 | typedef detail::extended_int<128> big_int_type;</span><br style="font-family: Courier New,Courier,monospace;"> | |
206 | ||
207 | <span style="font-family: Courier New,Courier,monospace;"> | |
208 | typedef fpt80 fpt_type;</span><br style="font-family: Courier New,Courier,monospace;"> | |
209 | ||
210 | <span style="font-family: Courier New,Courier,monospace;"> | |
211 | typedef fpt80 efpt_type;</span><br style="font-family: Courier New,Courier,monospace;"> | |
212 | ||
213 | <span style="font-family: Courier New,Courier,monospace;"> | |
214 | typedef my_ulp_comparison ulp_cmp_type;</span><br style="font-family: Courier New,Courier,monospace;"> | |
215 | ||
216 | <span style="font-family: Courier New,Courier,monospace;"> | |
217 | typedef my_fpt_converter to_fpt_converter_type;</span><br style="font-family: Courier New,Courier,monospace;"> | |
218 | ||
219 | <span style="font-family: Courier New,Courier,monospace;"> | |
220 | typedef my_fpt_converter to_efpt_converter_type;</span><br style="font-family: Courier New,Courier,monospace;"> | |
221 | ||
222 | <span style="font-family: Courier New,Courier,monospace;">};<br> | |
223 | <br> | |
224 | </span>It is always better to use C++ built-in types wherever it's | |
225 | possible. That's why we use the 64-bit signed integer type to handle | |
226 | our | |
227 | input coordinates. <span style="font-family: Courier New,Courier,monospace;">int_x2_type</span> | |
228 | and <span style="font-family: Courier New,Courier,monospace;">uint_x2_type</span> | |
229 | is required to handle 96-bit signed/unsigned integers. As there is no | |
230 | such built-in type we use library provided efficient fixed integer | |
231 | type. | |
232 | The big integer type should be capable to handle 48 * 64 bit integers, | |
233 | that is | |
234 | less than 32 * 128, and so far we are good with <span style="font-family: Courier New,Courier,monospace;">extended_int<128></span> | |
235 | type. We use the same floating point type for both <span style="font-family: Courier New,Courier,monospace;">fpt_type</span> | |
236 | and <span style="font-family: Courier New,Courier,monospace;">efpt_type</span> | |
237 | as it has enough exponent bits to represent both 48 * 32 bit and 48 * | |
238 | 64 bit integers (that is also the reason we don't need two | |
239 | floating-point converter structures). The <span style="font-family: Courier New,Courier,monospace;">ulp_cmp_type</span> | |
240 | structure checks weather two IEEE floating-point values are within the | |
241 | given signed integer ulp range (we won't analyze corresponding code | |
242 | here as it requires deep understanding of the <a href="http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html">floating-point | |
243 | architecture</a> and its <a href="../../../boost/polygon/detail/voronoi_ctypes.hpp">usage to compare | |
244 | floating-point values</a>), but just to mention the declaration is | |
245 | following:<br> | |
246 | ||
247 | <span style="font-family: Courier New,Courier,monospace;"></span><br style="font-family: Courier New,Courier,monospace;"> | |
248 | ||
249 | <span style="font-family: Courier New,Courier,monospace;">struct | |
250 | my_ulp_comparison {</span><br style="font-family: Courier New,Courier,monospace;"> | |
251 | ||
252 | <span style="font-family: Courier New,Courier,monospace;"> enum | |
253 | Result {</span><span style="font-family: Courier New,Courier,monospace;"><br> | |
254 | LESS = -1,</span><br style="font-family: Courier New,Courier,monospace;"> | |
255 | ||
256 | <span style="font-family: Courier New,Courier,monospace;"> | |
257 | EQUAL = 0,</span><br style="font-family: Courier New,Courier,monospace;"> | |
258 | ||
259 | <span style="font-family: Courier New,Courier,monospace;"> | |
260 | MORE = 1</span><br style="font-family: Courier New,Courier,monospace;"> | |
261 | ||
262 | <span style="font-family: Courier New,Courier,monospace;"> };</span><br style="font-family: Courier New,Courier,monospace;"> | |
263 | ||
264 | <span style="font-family: Courier New,Courier,monospace;"> Result | |
265 | operator()(fpt80 a, fpt80 b, unsigned int maxUlps) const;</span><br style="font-family: Courier New,Courier,monospace;"> | |
266 | ||
267 | <span style="font-family: Courier New,Courier,monospace;">};<br> | |
268 | <br> | |
269 | </span>The last step would be to declare the <span style="font-family: Courier New,Courier,monospace;">my_fpt_converter</span> | |
270 | structure (converts the integer types to the floating-point type):<br> | |
271 | ||
272 | <br> | |
273 | ||
274 | <span style="font-family: Courier New,Courier,monospace;">struct | |
275 | my_fpt_converter {</span><br style="font-family: Courier New,Courier,monospace;"> | |
276 | ||
277 | <span style="font-family: Courier New,Courier,monospace;"> | |
278 | template <typename T></span><br style="font-family: Courier New,Courier,monospace;"> | |
279 | ||
280 | <span style="font-family: Courier New,Courier,monospace;"> fpt80 | |
281 | operator()(const T& that) const {</span><br style="font-family: Courier New,Courier,monospace;"> | |
282 | ||
283 | <span style="font-family: Courier New,Courier,monospace;"> | |
284 | return static_cast<fpt80>(that);</span><br style="font-family: Courier New,Courier,monospace;"> | |
285 | ||
286 | <span style="font-family: Courier New,Courier,monospace;"> }</span><br style="font-family: Courier New,Courier,monospace;"> | |
287 | ||
288 | <br style="font-family: Courier New,Courier,monospace;"> | |
289 | ||
290 | <span style="font-family: Courier New,Courier,monospace;"> | |
291 | template <size_t N></span><br style="font-family: Courier New,Courier,monospace;"> | |
292 | ||
293 | <span style="font-family: Courier New,Courier,monospace;"> fpt80 | |
294 | operator()(const typename detail::extended_int<N>& that) | |
295 | const {</span><br style="font-family: Courier New,Courier,monospace;"> | |
296 | ||
297 | <span style="font-family: Courier New,Courier,monospace;"> | |
298 | fpt80 result = 0.0;</span><br style="font-family: Courier New,Courier,monospace;"> | |
299 | ||
300 | <span style="font-family: Courier New,Courier,monospace;"> | |
301 | for (size_t i = 1; i <= (std::min)((size_t)3, that.size()); ++i) {</span><br style="font-family: Courier New,Courier,monospace;"> | |
302 | ||
303 | <span style="font-family: Courier New,Courier,monospace;"> | |
304 | if (i != 1)</span><br style="font-family: Courier New,Courier,monospace;"> | |
305 | ||
306 | <span style="font-family: Courier New,Courier,monospace;"> | |
307 | result *= static_cast<fpt80>(0x100000000ULL);</span><br style="font-family: Courier New,Courier,monospace;"> | |
308 | ||
309 | <span style="font-family: Courier New,Courier,monospace;"> | |
310 | result += that.chunks()[that.size() - i];</span><br style="font-family: Courier New,Courier,monospace;"> | |
311 | ||
312 | <span style="font-family: Courier New,Courier,monospace;"> | |
313 | }</span><br style="font-family: Courier New,Courier,monospace;"> | |
314 | ||
315 | <span style="font-family: Courier New,Courier,monospace;"> | |
316 | return (that.count() < 0) ? -result : result;</span><br style="font-family: Courier New,Courier,monospace;"> | |
317 | ||
318 | <span style="font-family: Courier New,Courier,monospace;"> }</span><br style="font-family: Courier New,Courier,monospace;"> | |
319 | ||
320 | <span style="font-family: Courier New,Courier,monospace;">};<br> | |
321 | <br> | |
322 | </span>At this point we are done with declaration of the Voronoi | |
323 | coordinate type traits. The next step is to declare the Voronoi diagram | |
324 | traits:<br> | |
325 | ||
326 | <br> | |
327 | ||
328 | <span style="font-family: Courier New,Courier,monospace;">struct | |
329 | my_voronoi_diagram_traits {</span><br style="font-family: Courier New,Courier,monospace;"> | |
330 | ||
331 | <span style="font-family: Courier New,Courier,monospace;"> | |
332 | typedef fpt80 coordinate_type;</span><span style="font-family: Courier New,Courier,monospace;"></span><span style="font-family: Courier New,Courier,monospace;"></span><br style="font-family: Courier New,Courier,monospace;"> | |
333 | ||
334 | <span style="font-family: Courier New,Courier,monospace;"> | |
335 | typedef voronoi_cell<coordinate_type> cell_type;</span><br style="font-family: Courier New,Courier,monospace;"> | |
336 | ||
337 | <span style="font-family: Courier New,Courier,monospace;"> | |
338 | typedef voronoi_vertex<coordinate_type> vertex_type;</span><br style="font-family: Courier New,Courier,monospace;"> | |
339 | ||
340 | <span style="font-family: Courier New,Courier,monospace;"> | |
341 | typedef voronoi_edge<coordinate_type> edge_type;</span><br style="font-family: Courier New,Courier,monospace;"> | |
342 | ||
343 | <span style="font-family: Courier New,Courier,monospace;"> | |
344 | typedef struct {</span><br style="font-family: Courier New,Courier,monospace;"> | |
345 | ||
346 | <span style="font-family: Courier New,Courier,monospace;"> public:</span><br style="font-family: Courier New,Courier,monospace;"> | |
347 | ||
348 | <span style="font-family: Courier New,Courier,monospace;"> | |
349 | enum { ULPS = 128 };</span><br style="font-family: Courier New,Courier,monospace;"> | |
350 | ||
351 | <span style="font-family: Courier New,Courier,monospace;"> | |
352 | bool operator()(const point_type &v1, const point_type &v2) | |
353 | const {</span><br style="font-family: Courier New,Courier,monospace;"> | |
354 | ||
355 | <span style="font-family: Courier New,Courier,monospace;"> | |
356 | return (ulp_cmp(v1.x(), v2.x(), ULPS) == my_ulp_comparison::EQUAL | |
357 | &&</span><br style="font-family: Courier New,Courier,monospace;"> | |
358 | ||
359 | <span style="font-family: Courier New,Courier,monospace;"> | |
360 | ulp_cmp(v1.y(), v2.y(), ULPS) == my_ulp_comparison::EQUAL);</span><br style="font-family: Courier New,Courier,monospace;"> | |
361 | ||
362 | <span style="font-family: Courier New,Courier,monospace;"> | |
363 | }</span><br style="font-family: Courier New,Courier,monospace;"> | |
364 | ||
365 | <span style="font-family: Courier New,Courier,monospace;"> | |
366 | private:</span><br style="font-family: Courier New,Courier,monospace;"> | |
367 | ||
368 | <span style="font-family: Courier New,Courier,monospace;"> | |
369 | my_ulp_comparison ulp_cmp;</span><br style="font-family: Courier New,Courier,monospace;"> | |
370 | ||
371 | <span style="font-family: Courier New,Courier,monospace;"> } | |
372 | vertex_equality_predicate_type;</span><br style="font-family: Courier New,Courier,monospace;"> | |
373 | ||
374 | <span style="font-family: Courier New,Courier,monospace;">};</span><br> | |
375 | ||
376 | <span style="font-family: Courier New,Courier,monospace;"></span><br> | |
377 | ||
378 | Above we simply declared the Voronoi primitive types | |
379 | and vertex | |
380 | equality predicate using the new coordinate type and corresponding ulp | |
381 | comparison structure. As we are done with the declaration of the | |
382 | coordinate | |
383 | type specific structures we are ready to proceed to the construction | |
384 | step itself. The first step would be to initialize voronoi_builder | |
385 | structure with a set of random points:<br> | |
386 | ||
387 | <br> | |
388 | ||
389 | <span style="font-family: Courier New,Courier,monospace;">// Random | |
390 | generator and distribution. MAX is equal to 2^48.</span><br> | |
391 | ||
392 | <span style="font-family: Courier New,Courier,monospace;">boost::mt19937_64 | |
393 | gen(std::time(0));</span><br style="font-family: Courier New,Courier,monospace;"> | |
394 | ||
395 | <span style="font-family: Courier New,Courier,monospace;">boost::random::uniform_int_distribution<boost::int64_t> | |
396 | distr(-MAX, MAX-1);<br> | |
397 | <br> | |
398 | </span><span style="font-family: Courier New,Courier,monospace;"> | |
399 | // Declaring and configuring Voronoi builder with the new coordinate | |
400 | type traits.<br> | |
401 | voronoi_builder<boost::int64_t, my_voronoi_ctype_traits> vb;</span><br> | |
402 | <span style="font-family: Courier New,Courier,monospace;"></span><br style="font-family: Courier New,Courier,monospace;"> | |
403 | ||
404 | <span style="font-family: Courier New,Courier,monospace;">// Voronoi | |
405 | builder initialization step.<br> | |
406 | for (size_t i = 0; i < GENERATED_POINTS; ++i) {</span><br style="font-family: Courier New,Courier,monospace;"> | |
407 | ||
408 | <span style="font-family: Courier New,Courier,monospace;"> | |
409 | boost::int64_t x = distr(gen);</span><br style="font-family: Courier New,Courier,monospace;"> | |
410 | ||
411 | <span style="font-family: Courier New,Courier,monospace;"> | |
412 | boost::int64_t y = distr(gen);</span><br style="font-family: Courier New,Courier,monospace;"> | |
413 | ||
414 | <span style="font-family: Courier New,Courier,monospace;"> | |
415 | vb.insert_point(x, y);</span><br style="font-family: Courier New,Courier,monospace;"> | |
416 | ||
417 | <span style="font-family: Courier New,Courier,monospace;">}<br> | |
418 | <br> | |
419 | </span>The second step would be to generate the Voronoi diagram and | |
420 | this is done as before with the two lines of code:<br> | |
421 | ||
422 | <br> | |
423 | ||
424 | <span style="font-family: Courier New,Courier,monospace;">// Declaring | |
425 | and configuring Voronoi diagram structure with the new coordinate type | |
426 | traits.<br> | |
427 | voronoi_diagram<fpt80, my_voronoi_diagram_traits> vd;</span><br> | |
428 | ||
429 | <span style="font-family: Courier New,Courier,monospace;">vb.construct(&vd);<br> | |
430 | <br> | |
431 | </span>From this point the user can operate with the Voronoi diagram | |
432 | data structure | |
433 | and in our tutorial we output some simple stats of the resulting | |
434 | Voronoi graph. Probably the hardest part of this tutorial is | |
435 | the declaration of the ulp comparison structure. The library provides | |
436 | efficient well-commented cross-platform implementation for 64-bit | |
437 | floating-point type (double). So the best advice would be to follow | |
438 | that implementation, but before doing that really consider thoughtfully if the | |
439 | default | |
440 | coordinate types are not capable to deal with your problem.<br> | |
441 | ||
442 | <br> | |
443 | ||
444 | <table class="docinfo" id="table1" frame="void" rules="none"> | |
445 | ||
446 | <colgroup> <col class="docinfo-name"><col class="docinfo-content"> </colgroup> | |
447 | <tbody valign="top"> | |
448 | <tr> | |
449 | <th class="docinfo-name">Copyright:</th> | |
450 |