voronoi_advanced_tutorial.htm 22 KB

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