462 lines
22 KiB
HTML
462 lines
22 KiB
HTML
|
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
|||
|
|
<html><head>
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252"><title>Voronoi Advanced Tutorial</title></head><body>
|
|||
|
|
<h1>Voronoi Advanced Tutorial<br>
|
|||
|
|
</h1>
|
|||
|
|
|
|||
|
|
This tutorial consists of two parts. The first one provides two
|
|||
|
|
examples of a real world problems that default configuration of Voronoi
|
|||
|
|
library is capable to solve. By default configuration we mean the one
|
|||
|
|
that accepts
|
|||
|
|
signed 32-bit integer and outputs floating-point (64-bit
|
|||
|
|
double) coordinates. We provide those examples to convince even the
|
|||
|
|
most skeptical users that they probably don't need to configure library
|
|||
|
|
for higher-precision input or output coordinate types. However if the
|
|||
|
|
posed problem really requires those, fully featured configuration of
|
|||
|
|
both input and output coordinate types is provided in the second part
|
|||
|
|
of this tutorial.<br>
|
|||
|
|
|
|||
|
|
<h2>Red Planet</h2>
|
|||
|
|
|
|||
|
|
<h3>Problem Statement</h3>
|
|||
|
|
|
|||
|
|
<img style="width: 665px; height: 369px;" alt="" src="images/rover.jpg"><br>
|
|||
|
|
|
|||
|
|
<br>Lets imagine that NASA is
|
|||
|
|
planning to send a new robot to Mars. Each day the center situated on Earth
|
|||
|
|
will send a destination point coordinates the robot needs to reach by
|
|||
|
|
the end of the day. Of course we'd like to save as much energy as
|
|||
|
|
possible thus choosing the shortest possible path. This would be a
|
|||
|
|
straight line in a perfect world (we don't consider curvature of
|
|||
|
|
surface), but situation becomes more complicated as there are some
|
|||
|
|
rocks and wells on Mars our robot can't go through. Behind of those our
|
|||
|
|
robot has some dimensions that might not allow it to pass narrow places.<br>
|
|||
|
|
|
|||
|
|
<h3>Application of Voronoi diagram</h3>
|
|||
|
|
|
|||
|
|
The problem above could be solved using Voronoi diagram. The first
|
|||
|
|
stage would be to discretize obstacles (rocks and wells) with
|
|||
|
|
polylines. Afterwards we will compute Voronoi diagram of the input set
|
|||
|
|
of segments. As each Voronoi edge is equidistant from the two closest
|
|||
|
|
sites we are able to filter edges the robot won't be able to pass due
|
|||
|
|
to it's dimensions. The last step would be to run a bit optimized A*
|
|||
|
|
algorithm to find
|
|||
|
|
the shortest or at least suboptimal path and we are done.<br>
|
|||
|
|
|
|||
|
|
<h3>Discretization of input geometries</h3>
|
|||
|
|
|
|||
|
|
To show how good is the default input coordinate type provided by the
|
|||
|
|
Voronoi library
|
|||
|
|
we will discretize the whole area of Mars. That will be approximately
|
|||
|
|
1.44 * 10^8 square kilometres that is equal to 1.44 *
|
|||
|
|
10^18 square centimetres, which could be snapped to the integer
|
|||
|
|
grid with a side of 1.2 * 10^9 centimetres. To make the Voronoi
|
|||
|
|
graph
|
|||
|
|
precise on the boundaries of that grid we will replicate input map 9
|
|||
|
|
times (3x3), thus Voronoi diagram within a central piece will
|
|||
|
|
provide us with a correct connectivity graph. This step will increase
|
|||
|
|
the size of our grid to 3.6 * 10^9 centimetres that is less than 2^32.
|
|||
|
|
So we are able to discretize the Red Planet's surface within a 1
|
|||
|
|
centimetre
|
|||
|
|
precision using the default input coordinate type (signed 32-bit
|
|||
|
|
integer). That would imply maximum absolute error to be
|
|||
|
|
equal up to 0.5 centimetres per coordinate. Considering the radius of
|
|||
|
|
our robot to be
|
|||
|
|
0.3 metres and for security reasons avoiding any large enough obstacles
|
|||
|
|
that are within 1 metre distance from it that error would be irrelevant.<br>
|
|||
|
|
|
|||
|
|
<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>
|
|||
|
|
<h3>Output analysis</h3>
|
|||
|
|
|
|||
|
|
Estimates of the resulting Voronoi diagram precision were already
|
|||
|
|
explained <a href="voronoi_main.htm">here</a>.
|
|||
|
|
So to avoid those computations again we will simply state that the
|
|||
|
|
maximum absolute error of the output geometries will be on the grid
|
|||
|
|
boundaries and will be equal to 2^-16 centimetres, which is
|
|||
|
|
approximately equal to 150 nanometres and is 100 times larger than
|
|||
|
|
a radius of a complex molecule. We would like to notice that the
|
|||
|
|
absolute error of the discretization step is much higher than the one
|
|||
|
|
produced by the Voronoi diagram construction algorithm.
|
|||
|
|
<h2>VLSI Design</h2>
|
|||
|
|
|
|||
|
|
<h3>Problem Statement</h3>
|
|||
|
|
|
|||
|
|
<img style="width: 400px; height: 283px;" alt="" src="images/vlsi.jpg"><br>
|
|||
|
|
|
|||
|
|
<br>
|
|||
|
|
|
|||
|
|
Very-large-scale integration (<a href="http://www.rulabinsky.com/cavd/index.html">VLSI</a>) is the
|
|||
|
|
process of creating
|
|||
|
|
integrated circuits by combining thousands of transistors into a single
|
|||
|
|
chip. Considering the fact that it may take weeks or months to get an
|
|||
|
|
integrated circuit manufactured, designers often spend large amounts of
|
|||
|
|
time analyzing their layouts to avoid costly mistakes. One of the
|
|||
|
|
common static analysis checks is minimum distance requirement between
|
|||
|
|
the components of an integrated circuit (distance should be greater
|
|||
|
|
than
|
|||
|
|
specified value).<br>
|
|||
|
|
|
|||
|
|
<h3>Application of Voronoi diagram</h3>
|
|||
|
|
|
|||
|
|
It appears that the minimum distance between components of the input
|
|||
|
|
set of points and segments corresponds to the one of the Voronoi
|
|||
|
|
diagram edges. This means that we can iterate through each edge of
|
|||
|
|
the Voronoi graph, extract the pair of input geometries that form it
|
|||
|
|
and find
|
|||
|
|
the distance between those. As the total amount of such edges is O(N)
|
|||
|
|
value
|
|||
|
|
(N - is the number of input geometries) the minimum distance could be
|
|||
|
|
efficiently find in a linear time once we construct the diagram.<br>
|
|||
|
|
|
|||
|
|
<h3>Discretization of input geometries</h3>
|
|||
|
|
|
|||
|
|
The average size of the modern CPUs is around 2.5 x 2.5 centimetres.
|
|||
|
|
Snapping this to the 32-bit integer grid will give discretization
|
|||
|
|
precision of 2.5 / 2^33 centimetres or 3 picometres that is 10 times
|
|||
|
|
smaller value than radius of an atom. That would be probably good
|
|||
|
|
enough precision even for a few next generations of processors.<br>
|
|||
|
|
|
|||
|
|
<h3>Output analysis</h3>
|
|||
|
|
|
|||
|
|
The maximum absolute error of the output geometries will be 2.5 / 2^47
|
|||
|
|
centimetres or 0.2 femtometres that is 10 times smaller value than
|
|||
|
|
the radius of an electron. However in this particular case we are not
|
|||
|
|
interested in the precision of the output, rather in its topology. As
|
|||
|
|
it was noticed on
|
|||
|
|
the <a href="voronoi_main.htm">Voronoi main page</a> very small edges
|
|||
|
|
are removed from the Voronoi diagram. However user should not worry
|
|||
|
|
because the edge that correspond to the minimal distance won't be among
|
|||
|
|
those. That means that we would be able to 100% correctly identify a
|
|||
|
|
pair of closest objects within the discretization precision.<br>
|
|||
|
|
|
|||
|
|
<h2>Conclusions</h2>
|
|||
|
|
|
|||
|
|
The above two examples show usage of the default Voronoi coordinate
|
|||
|
|
types
|
|||
|
|
in the macro and micro world. The main point of those was to give the user
|
|||
|
|
understanding of a scale that the default coordinate types provide. There
|
|||
|
|
are
|
|||
|
|
two main points we didn't mention before, but that would be relevant to
|
|||
|
|
the most real world problems:<br>
|
|||
|
|
|
|||
|
|
<ul>
|
|||
|
|
|
|||
|
|
<li>The absolute error of the coordinates of the output Voronoi
|
|||
|
|
diagram
|
|||
|
|
inside the 32-bit integer discretization grid is slightly smaller than
|
|||
|
|
the absolute error of discretization itself, thus could be neglected at
|
|||
|
|
all.</li>
|
|||
|
|
<li>In both problems above we didn't consider error of measurement.
|
|||
|
|
For example: is it possible to construct a map of the Mars within the
|
|||
|
|
0.5
|
|||
|
|
centimetres precision, or to get coordinates of the circuit parts
|
|||
|
|
withing the subatomic precision? I guess the answer for both questions
|
|||
|
|
would be "No". And that actually means that the error of the
|
|||
|
|
discretization
|
|||
|
|
step could be neglected comparing to the error produced by the
|
|||
|
|
measuring
|
|||
|
|
devices.<br>
|
|||
|
|
</li>
|
|||
|
|
</ul>
|
|||
|
|
The second statement means that there is actually no point to provide
|
|||
|
|
implementation that operates with floating-point input coordinates,
|
|||
|
|
because those always could be snapped to the integer grid. In case the
|
|||
|
|
user is not satisfied with the precision that the 32-bit integer grid
|
|||
|
|
provides or would like to retrieve coordinates of the output geometries
|
|||
|
|
within a smaller
|
|||
|
|
relative error, follow the next paragraph.<br>
|
|||
|
|
|
|||
|
|
<h2>Voronoi Coordinate Types Configuration</h2>
|
|||
|
|
|
|||
|
|
In the following chapter we are going to extend input coordinate type
|
|||
|
|
to the 48-bit signed
|
|||
|
|
integer and output coordinate type to the 80-bit IEEE floating-point
|
|||
|
|
type
|
|||
|
|
(long double). The code for this chapter is available in <a href="../example/voronoi_advanced_tutorial.cpp">voroni_advanced_tutorial.cpp</a>.
|
|||
|
|
While it won't be possible to compile it using the MSVC compiler (it
|
|||
|
|
doesn't
|
|||
|
|
support 80-bit long double type; ieee754.h header is required), it
|
|||
|
|
should give a clear understanding of how the library supports the user
|
|||
|
|
provided coordinate types.<br>
|
|||
|
|
|
|||
|
|
<br>
|
|||
|
|
|
|||
|
|
So the main step would be to declare the voronoi coordinate type traits
|
|||
|
|
that satisfy set of restrictions explained <a href="voronoi_builder.htm">here</a>:<br>
|
|||
|
|
|
|||
|
|
<br>
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">struct
|
|||
|
|
my_voronoi_ctype_traits {</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
typedef boost::int64_t int_type;</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
typedef detail::extended_int<3> int_x2_type;</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
typedef detail::extended_int<3> uint_x2_type;</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
typedef detail::extended_int<128> big_int_type;</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
typedef fpt80 fpt_type;</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
typedef fpt80 efpt_type;</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
typedef my_ulp_comparison ulp_cmp_type;</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
typedef my_fpt_converter to_fpt_converter_type;</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
typedef my_fpt_converter to_efpt_converter_type;</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">};<br>
|
|||
|
|
<br>
|
|||
|
|
</span>It is always better to use C++ built-in types wherever it's
|
|||
|
|
possible. That's why we use the 64-bit signed integer type to handle
|
|||
|
|
our
|
|||
|
|
input coordinates. <span style="font-family: Courier New,Courier,monospace;">int_x2_type</span>
|
|||
|
|
and <span style="font-family: Courier New,Courier,monospace;">uint_x2_type</span>
|
|||
|
|
is required to handle 96-bit signed/unsigned integers. As there is no
|
|||
|
|
such built-in type we use library provided efficient fixed integer
|
|||
|
|
type.
|
|||
|
|
The big integer type should be capable to handle 48 * 64 bit integers,
|
|||
|
|
that is
|
|||
|
|
less than 32 * 128, and so far we are good with <span style="font-family: Courier New,Courier,monospace;">extended_int<128></span>
|
|||
|
|
type. We use the same floating point type for both <span style="font-family: Courier New,Courier,monospace;">fpt_type</span>
|
|||
|
|
and <span style="font-family: Courier New,Courier,monospace;">efpt_type</span>
|
|||
|
|
as it has enough exponent bits to represent both 48 * 32 bit and 48 *
|
|||
|
|
64 bit integers (that is also the reason we don't need two
|
|||
|
|
floating-point converter structures). The <span style="font-family: Courier New,Courier,monospace;">ulp_cmp_type</span>
|
|||
|
|
structure checks weather two IEEE floating-point values are within the
|
|||
|
|
given signed integer ulp range (we won't analyze corresponding code
|
|||
|
|
here as it requires deep understanding of the <a href="http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html">floating-point
|
|||
|
|
architecture</a> and its <a href="../../../boost/polygon/detail/voronoi_ctypes.hpp">usage to compare
|
|||
|
|
floating-point values</a>), but just to mention the declaration is
|
|||
|
|
following:<br>
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;"></span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">struct
|
|||
|
|
my_ulp_comparison {</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;"> enum
|
|||
|
|
Result {</span><span style="font-family: Courier New,Courier,monospace;"><br>
|
|||
|
|
LESS = -1,</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
EQUAL = 0,</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
MORE = 1</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;"> };</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;"> Result
|
|||
|
|
operator()(fpt80 a, fpt80 b, unsigned int maxUlps) const;</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">};<br>
|
|||
|
|
<br>
|
|||
|
|
</span>The last step would be to declare the <span style="font-family: Courier New,Courier,monospace;">my_fpt_converter</span>
|
|||
|
|
structure (converts the integer types to the floating-point type):<br>
|
|||
|
|
|
|||
|
|
<br>
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">struct
|
|||
|
|
my_fpt_converter {</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
template <typename T></span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;"> fpt80
|
|||
|
|
operator()(const T& that) const {</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
return static_cast<fpt80>(that);</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;"> }</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
template <size_t N></span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;"> fpt80
|
|||
|
|
operator()(const typename detail::extended_int<N>& that)
|
|||
|
|
const {</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
fpt80 result = 0.0;</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
for (size_t i = 1; i <= (std::min)((size_t)3, that.size()); ++i) {</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
if (i != 1)</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
result *= static_cast<fpt80>(0x100000000ULL);</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
result += that.chunks()[that.size() - i];</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
}</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
return (that.count() < 0) ? -result : result;</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;"> }</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">};<br>
|
|||
|
|
<br>
|
|||
|
|
</span>At this point we are done with declaration of the Voronoi
|
|||
|
|
coordinate type traits. The next step is to declare the Voronoi diagram
|
|||
|
|
traits:<br>
|
|||
|
|
|
|||
|
|
<br>
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">struct
|
|||
|
|
my_voronoi_diagram_traits {</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
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;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
typedef voronoi_cell<coordinate_type> cell_type;</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
typedef voronoi_vertex<coordinate_type> vertex_type;</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
typedef voronoi_edge<coordinate_type> edge_type;</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
typedef struct {</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;"> public:</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
enum { ULPS = 128 };</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
bool operator()(const point_type &v1, const point_type &v2)
|
|||
|
|
const {</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
return (ulp_cmp(v1.x(), v2.x(), ULPS) == my_ulp_comparison::EQUAL
|
|||
|
|
&&</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
ulp_cmp(v1.y(), v2.y(), ULPS) == my_ulp_comparison::EQUAL);</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
}</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
private:</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
my_ulp_comparison ulp_cmp;</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;"> }
|
|||
|
|
vertex_equality_predicate_type;</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">};</span><br>
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;"></span><br>
|
|||
|
|
|
|||
|
|
Above we simply declared the Voronoi primitive types
|
|||
|
|
and vertex
|
|||
|
|
equality predicate using the new coordinate type and corresponding ulp
|
|||
|
|
comparison structure. As we are done with the declaration of the
|
|||
|
|
coordinate
|
|||
|
|
type specific structures we are ready to proceed to the construction
|
|||
|
|
step itself. The first step would be to initialize voronoi_builder
|
|||
|
|
structure with a set of random points:<br>
|
|||
|
|
|
|||
|
|
<br>
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">// Random
|
|||
|
|
generator and distribution. MAX is equal to 2^48.</span><br>
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">boost::mt19937_64
|
|||
|
|
gen(std::time(0));</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">boost::random::uniform_int_distribution<boost::int64_t>
|
|||
|
|
distr(-MAX, MAX-1);<br>
|
|||
|
|
<br>
|
|||
|
|
</span><span style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
// Declaring and configuring Voronoi builder with the new coordinate
|
|||
|
|
type traits.<br>
|
|||
|
|
voronoi_builder<boost::int64_t, my_voronoi_ctype_traits> vb;</span><br>
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;"></span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">// Voronoi
|
|||
|
|
builder initialization step.<br>
|
|||
|
|
for (size_t i = 0; i < GENERATED_POINTS; ++i) {</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
boost::int64_t x = distr(gen);</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
boost::int64_t y = distr(gen);</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
vb.insert_point(x, y);</span><br style="font-family: Courier New,Courier,monospace;">
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">}<br>
|
|||
|
|
<br>
|
|||
|
|
</span>The second step would be to generate the Voronoi diagram and
|
|||
|
|
this is done as before with the two lines of code:<br>
|
|||
|
|
|
|||
|
|
<br>
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">// Declaring
|
|||
|
|
and configuring Voronoi diagram structure with the new coordinate type
|
|||
|
|
traits.<br>
|
|||
|
|
voronoi_diagram<fpt80, my_voronoi_diagram_traits> vd;</span><br>
|
|||
|
|
|
|||
|
|
<span style="font-family: Courier New,Courier,monospace;">vb.construct(&vd);<br>
|
|||
|
|
<br>
|
|||
|
|
</span>From this point the user can operate with the Voronoi diagram
|
|||
|
|
data structure
|
|||
|
|
and in our tutorial we output some simple stats of the resulting
|
|||
|
|
Voronoi graph. Probably the hardest part of this tutorial is
|
|||
|
|
the declaration of the ulp comparison structure. The library provides
|
|||
|
|
efficient well-commented cross-platform implementation for 64-bit
|
|||
|
|
floating-point type (double). So the best advice would be to follow
|
|||
|
|
that implementation, but before doing that really consider thoughtfully if the
|
|||
|
|
default
|
|||
|
|
coordinate types are not capable to deal with your problem.<br>
|
|||
|
|
|
|||
|
|
<br>
|
|||
|
|
|
|||
|
|
<table class="docinfo" id="table1" frame="void" rules="none">
|
|||
|
|
|
|||
|
|
<colgroup> <col class="docinfo-name"><col class="docinfo-content"> </colgroup>
|
|||
|
|
<tbody valign="top">
|
|||
|
|
<tr>
|
|||
|
|
<th class="docinfo-name">Copyright:</th>
|
|||
|
|
<td>Copyright <20> Andrii Sydorchuk 2010-2012.</td>
|
|||
|
|
</tr>
|
|||
|
|
<tr class="field">
|
|||
|
|
<th class="docinfo-name">License:</th>
|
|||
|
|
<td class="field-body">Distributed under the Boost Software
|
|||
|
|
License, Version 1.0. (See accompanying file <tt class="literal"> <span class="pre">LICENSE_1_0.txt</span></tt> or copy at <a class="reference" target="_top" href="http://www.boost.org/LICENSE_1_0.txt">
|
|||
|
|
http://www.boost.org/LICENSE_1_0.txt</a>)</td>
|
|||
|
|
</tr>
|
|||
|
|
</tbody>
|
|||
|
|
</table>
|
|||
|
|
|
|||
|
|
|
|||
|
|
</body></html>
|