1<html> 2<head> 3<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 4<title>Design Rationale</title> 5<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css"> 6<meta name="generator" content="DocBook XSL Stylesheets V1.79.1"> 7<link rel="home" href="../index.html" title="Chapter 1. Geometry"> 8<link rel="up" href="../index.html" title="Chapter 1. Geometry"> 9<link rel="prev" href="compilation.html" title="Compilation"> 10<link rel="next" href="quickstart.html" title="Quick Start"> 11</head> 12<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> 13<table cellpadding="2" width="100%"><tr> 14<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td> 15<td align="center"><a href="../../../../../index.html">Home</a></td> 16<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td> 17<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> 18<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> 19<td align="center"><a href="../../../../../more/index.htm">More</a></td> 20</tr></table> 21<hr> 22<div class="spirit-nav"> 23<a accesskey="p" href="compilation.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="quickstart.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a> 24</div> 25<div class="section"> 26<div class="titlepage"><div><div><h2 class="title" style="clear: both"> 27<a name="geometry.design"></a><a class="link" href="design.html" title="Design Rationale">Design Rationale</a> 28</h2></div></div></div> 29<p> 30 Suppose you need a C++ program to calculate the distance between two points. 31 You might define a struct: 32 </p> 33<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">mypoint</span> 34<span class="special">{</span> 35 <span class="keyword">double</span> <span class="identifier">x</span><span class="special">,</span> <span class="identifier">y</span><span class="special">;</span> 36<span class="special">};</span> 37</pre> 38<p> 39 and a function, containing the algorithm: 40 </p> 41<pre class="programlisting"><span class="keyword">double</span> <span class="identifier">distance</span><span class="special">(</span><span class="identifier">mypoint</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">a</span><span class="special">,</span> <span class="identifier">mypoint</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">b</span><span class="special">)</span> 42<span class="special">{</span> 43 <span class="keyword">double</span> <span class="identifier">dx</span> <span class="special">=</span> <span class="identifier">a</span><span class="special">.</span><span class="identifier">x</span> <span class="special">-</span> <span class="identifier">b</span><span class="special">.</span><span class="identifier">x</span><span class="special">;</span> 44 <span class="keyword">double</span> <span class="identifier">dy</span> <span class="special">=</span> <span class="identifier">a</span><span class="special">.</span><span class="identifier">y</span> <span class="special">-</span> <span class="identifier">b</span><span class="special">.</span><span class="identifier">y</span><span class="special">;</span> 45 <span class="keyword">return</span> <span class="identifier">sqrt</span><span class="special">(</span><span class="identifier">dx</span> <span class="special">*</span> <span class="identifier">dx</span> <span class="special">+</span> <span class="identifier">dy</span> <span class="special">*</span> <span class="identifier">dy</span><span class="special">);</span> 46<span class="special">}</span> 47</pre> 48<p> 49 Quite simple, and it is usable, but not generic. For a library it has to be 50 designed way further. The design above can only be used for 2D points, for 51 the struct <span class="bold"><strong>mypoint</strong></span> (and no other struct), 52 in a Cartesian coordinate system. A generic library should be able to calculate 53 the distance: 54 </p> 55<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "> 56<li class="listitem"> 57 for any point class or struct, not on just this <span class="bold"><strong>mypoint</strong></span> 58 type 59 </li> 60<li class="listitem"> 61 in more than two dimensions 62 </li> 63<li class="listitem"> 64 for other coordinate systems, e.g. over the earth or on a sphere 65 </li> 66<li class="listitem"> 67 between a point and a line or between other geometry combinations 68 </li> 69<li class="listitem"> 70 in higher precision than <span class="emphasis"><em>double</em></span> 71 </li> 72<li class="listitem"> 73 avoiding the square root: often we don't want to do that because it is 74 a relatively expensive function, and for comparing distances it is not 75 necessary 76 </li> 77</ul></div> 78<p> 79 In this and following sections we will make the design step by step more generic. 80 </p> 81<h4> 82<a name="geometry.design.h0"></a> 83 <span class="phrase"><a name="geometry.design.using_templates"></a></span><a class="link" href="design.html#geometry.design.using_templates">Using 84 Templates</a> 85 </h4> 86<p> 87 The distance function can be changed into a template function. This is trivial 88 and allows calculating the distance between other point types than just <span class="bold"><strong>mypoint</strong></span>. We add two template parameters, allowing input 89 of two different point types. 90 </p> 91<pre class="programlisting"><span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">P1</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">P2</span><span class="special">></span> 92<span class="keyword">double</span> <span class="identifier">distance</span><span class="special">(</span><span class="identifier">P1</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">a</span><span class="special">,</span> <span class="identifier">P2</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">b</span><span class="special">)</span> 93<span class="special">{</span> 94 <span class="keyword">double</span> <span class="identifier">dx</span> <span class="special">=</span> <span class="identifier">a</span><span class="special">.</span><span class="identifier">x</span> <span class="special">-</span> <span class="identifier">b</span><span class="special">.</span><span class="identifier">x</span><span class="special">;</span> 95 <span class="keyword">double</span> <span class="identifier">dy</span> <span class="special">=</span> <span class="identifier">a</span><span class="special">.</span><span class="identifier">y</span> <span class="special">-</span> <span class="identifier">b</span><span class="special">.</span><span class="identifier">y</span><span class="special">;</span> 96 <span class="keyword">return</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">sqrt</span><span class="special">(</span><span class="identifier">dx</span> <span class="special">*</span> <span class="identifier">dx</span> <span class="special">+</span> <span class="identifier">dy</span> <span class="special">*</span> <span class="identifier">dy</span><span class="special">);</span> 97<span class="special">}</span> 98</pre> 99<p> 100 This template version is slightly better, but not much. 101 </p> 102<p> 103 Consider a C++ class where member variables are protected... Such a class does 104 not allow to access <code class="computeroutput"><span class="identifier">x</span></code> and 105 <code class="computeroutput"><span class="identifier">y</span></code> members directly. So, this 106 paragraph is short and we just move on. 107 </p> 108<h4> 109<a name="geometry.design.h1"></a> 110 <span class="phrase"><a name="geometry.design.using_traits"></a></span><a class="link" href="design.html#geometry.design.using_traits">Using 111 Traits</a> 112 </h4> 113<p> 114 We need to take a generic approach and allow any point type as input to the 115 distance function. Instead of accessing <code class="computeroutput"><span class="identifier">x</span></code> 116 and <code class="computeroutput"><span class="identifier">y</span></code> members, we will add 117 a few levels of indirection, using a traits system. The function then becomes: 118 </p> 119<pre class="programlisting"><span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">P1</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">P2</span><span class="special">></span> 120<span class="keyword">double</span> <span class="identifier">distance</span><span class="special">(</span><span class="identifier">P1</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">a</span><span class="special">,</span> <span class="identifier">P2</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">b</span><span class="special">)</span> 121<span class="special">{</span> 122 <span class="keyword">double</span> <span class="identifier">dx</span> <span class="special">=</span> <span class="identifier">get</span><span class="special"><</span><span class="number">0</span><span class="special">>(</span><span class="identifier">a</span><span class="special">)</span> <span class="special">-</span> <span class="identifier">get</span><span class="special"><</span><span class="number">0</span><span class="special">>(</span><span class="identifier">b</span><span class="special">);</span> 123 <span class="keyword">double</span> <span class="identifier">dy</span> <span class="special">=</span> <span class="identifier">get</span><span class="special"><</span><span class="number">1</span><span class="special">>(</span><span class="identifier">a</span><span class="special">)</span> <span class="special">-</span> <span class="identifier">get</span><span class="special"><</span><span class="number">1</span><span class="special">>(</span><span class="identifier">b</span><span class="special">);</span> 124 <span class="keyword">return</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">sqrt</span><span class="special">(</span><span class="identifier">dx</span> <span class="special">*</span> <span class="identifier">dx</span> <span class="special">+</span> <span class="identifier">dy</span> <span class="special">*</span> <span class="identifier">dy</span><span class="special">);</span> 125<span class="special">}</span> 126</pre> 127<p> 128 This adapted distance function uses a generic get function, with dimension 129 as a template parameter, to access the coordinates of a point. This get forwards 130 to the traits system, defined as following: 131 </p> 132<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">traits</span> 133<span class="special">{</span> 134 <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">P</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">D</span><span class="special">></span> 135 <span class="keyword">struct</span> <span class="identifier">access</span> <span class="special">{};</span> 136<span class="special">}</span> 137</pre> 138<p> 139 which is then specialized for our <span class="bold"><strong>mypoint</strong></span> 140 type, implementing a static method called <code class="computeroutput"><span class="identifier">get</span></code>: 141 </p> 142<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">traits</span> 143<span class="special">{</span> 144 <span class="keyword">template</span> <span class="special"><></span> 145 <span class="keyword">struct</span> <span class="identifier">access</span><span class="special"><</span><span class="identifier">mypoint</span><span class="special">,</span> <span class="number">0</span><span class="special">></span> 146 <span class="special">{</span> 147 <span class="keyword">static</span> <span class="keyword">double</span> <span class="identifier">get</span><span class="special">(</span><span class="identifier">mypoint</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">p</span><span class="special">)</span> 148 <span class="special">{</span> 149 <span class="keyword">return</span> <span class="identifier">p</span><span class="special">.</span><span class="identifier">x</span><span class="special">;</span> 150 <span class="special">}</span> 151 <span class="special">};</span> 152 <span class="comment">// same for 1: p.y</span> 153 <span class="special">...</span> 154<span class="special">}</span> 155</pre> 156<p> 157 Calling <code class="computeroutput"><span class="identifier">traits</span><span class="special">::</span><span class="identifier">access</span><span class="special"><</span><span class="identifier">mypoint</span><span class="special">,</span> <span class="number">0</span><span class="special">>::</span><span class="identifier">get</span><span class="special">(</span><span class="identifier">a</span><span class="special">)</span></code> 158 now returns us our <code class="computeroutput"><span class="identifier">x</span></code> coordinate. 159 Nice, isn't it? It is too verbose for a function like this, used so often in 160 the library. We can shorten the syntax by adding an extra free function: 161 </p> 162<pre class="programlisting"><span class="keyword">template</span> <span class="special"><</span><span class="keyword">int</span> <span class="identifier">D</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">P</span><span class="special">></span> 163<span class="keyword">inline</span> <span class="keyword">double</span> <span class="identifier">get</span><span class="special">(</span><span class="identifier">P</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">p</span><span class="special">)</span> 164<span class="special">{</span> 165 <span class="keyword">return</span> <span class="identifier">traits</span><span class="special">::</span><span class="identifier">access</span><span class="special"><</span><span class="identifier">P</span><span class="special">,</span> <span class="identifier">D</span><span class="special">>::</span><span class="identifier">get</span><span class="special">(</span><span class="identifier">p</span><span class="special">);</span> 166<span class="special">}</span> 167</pre> 168<p> 169 This enables us to call <code class="computeroutput"><span class="identifier">get</span><span class="special"><</span><span class="number">0</span><span class="special">>(</span><span class="identifier">a</span><span class="special">)</span></code>, for any 170 point having the traits::access specialization, as shown in the distance algorithm 171 at the start of this paragraph. So we wanted to enable classes with methods 172 like <code class="computeroutput"><span class="identifier">x</span><span class="special">()</span></code>, 173 and they are supported as long as there is a specialization of the access 174 <code class="computeroutput"><span class="keyword">struct</span></code> with a static <code class="computeroutput"><span class="identifier">get</span></code> function returning <code class="computeroutput"><span class="identifier">x</span><span class="special">()</span></code> for dimension 0, and similar for 1 and <code class="computeroutput"><span class="identifier">y</span><span class="special">()</span></code>. 175 </p> 176<h4> 177<a name="geometry.design.h2"></a> 178 <span class="phrase"><a name="geometry.design.dimension_agnosticism"></a></span><a class="link" href="design.html#geometry.design.dimension_agnosticism">Dimension 179 Agnosticism</a> 180 </h4> 181<p> 182 Now we can calculate the distance between points in 2D, points of any structure 183 or class. However, we wanted to have 3D as well. So we have to make it dimension 184 agnostic. This complicates our distance function. We can use a <code class="computeroutput"><span class="keyword">for</span></code> loop to walk through dimensions, but for 185 loops have another performance than the straightforward coordinate addition 186 which was there originally. However, we can make more usage of templates and 187 make the distance algorithm as following, more complex but attractive for template 188 fans: 189 </p> 190<pre class="programlisting"><span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">P1</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">P2</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">D</span><span class="special">></span> 191<span class="keyword">struct</span> <span class="identifier">pythagoras</span> 192<span class="special">{</span> 193 <span class="keyword">static</span> <span class="keyword">double</span> <span class="identifier">apply</span><span class="special">(</span><span class="identifier">P1</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">a</span><span class="special">,</span> <span class="identifier">P2</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">b</span><span class="special">)</span> 194 <span class="special">{</span> 195 <span class="keyword">double</span> <span class="identifier">d</span> <span class="special">=</span> <span class="identifier">get</span><span class="special"><</span><span class="identifier">D</span><span class="special">-</span><span class="number">1</span><span class="special">>(</span><span class="identifier">a</span><span class="special">)</span> <span class="special">-</span> <span class="identifier">get</span><span class="special"><</span><span class="identifier">D</span><span class="special">-</span><span class="number">1</span><span class="special">>(</span><span class="identifier">b</span><span class="special">);</span> 196 <span class="keyword">return</span> <span class="identifier">d</span> <span class="special">*</span> <span class="identifier">d</span> <span class="special">+</span> <span class="identifier">pythagoras</span><span class="special"><</span><span class="identifier">P1</span><span class="special">,</span> <span class="identifier">P2</span><span class="special">,</span> <span class="identifier">D</span><span class="special">-</span><span class="number">1</span><span class="special">>::</span><span class="identifier">apply</span><span class="special">(</span><span class="identifier">a</span><span class="special">,</span> <span class="identifier">b</span><span class="special">);</span> 197 <span class="special">}</span> 198<span class="special">};</span> 199 200<span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">P1</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">P2</span> <span class="special">></span> 201<span class="keyword">struct</span> <span class="identifier">pythagoras</span><span class="special"><</span><span class="identifier">P1</span><span class="special">,</span> <span class="identifier">P2</span><span class="special">,</span> <span class="number">0</span><span class="special">></span> 202<span class="special">{</span> 203 <span class="keyword">static</span> <span class="keyword">double</span> <span class="identifier">apply</span><span class="special">(</span><span class="identifier">P1</span> <span class="keyword">const</span><span class="special">&,</span> <span class="identifier">P2</span> <span class="keyword">const</span><span class="special">&)</span> 204 <span class="special">{</span> 205 <span class="keyword">return</span> <span class="number">0</span><span class="special">;</span> 206 <span class="special">}</span> 207<span class="special">};</span> 208</pre> 209<p> 210 The distance function is calling that <code class="computeroutput"><span class="identifier">pythagoras</span></code> 211 structure, specifying the number of dimensions: 212 </p> 213<pre class="programlisting"><span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">P1</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">P2</span><span class="special">></span> 214<span class="keyword">double</span> <span class="identifier">distance</span><span class="special">(</span><span class="identifier">P1</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">a</span><span class="special">,</span> <span class="identifier">P2</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">b</span><span class="special">)</span> 215<span class="special">{</span> 216 <span class="identifier">BOOST_STATIC_ASSERT</span><span class="special">((</span> <span class="identifier">dimension</span><span class="special"><</span><span class="identifier">P1</span><span class="special">>::</span><span class="identifier">value</span> <span class="special">==</span> <span class="identifier">dimension</span><span class="special"><</span><span class="identifier">P2</span><span class="special">>::</span><span class="identifier">value</span> <span class="special">));</span> 217 218 <span class="keyword">return</span> <span class="identifier">sqrt</span><span class="special">(</span><span class="identifier">pythagoras</span><span class="special"><</span><span class="identifier">P1</span><span class="special">,</span> <span class="identifier">P2</span><span class="special">,</span> <span class="identifier">dimension</span><span class="special"><</span><span class="identifier">P1</span><span class="special">>::</span><span class="identifier">value</span><span class="special">>::</span><span class="identifier">apply</span><span class="special">(</span><span class="identifier">a</span><span class="special">,</span> <span class="identifier">b</span><span class="special">));</span> 219<span class="special">}</span> 220</pre> 221<p> 222 The dimension which is referred to is defined using another traits class: 223 </p> 224<p> 225</p> 226<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">traits</span> 227<span class="special">{</span> 228 <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">P</span><span class="special">></span> 229 <span class="keyword">struct</span> <span class="identifier">dimension</span> <span class="special">{};</span> 230<span class="special">}</span> 231</pre> 232<p> 233 </p> 234<p> 235 which has to be specialized again for the <code class="computeroutput"><span class="keyword">struct</span> 236 <span class="identifier">mypoint</span></code>. 237 </p> 238<p> 239 Because it only has to publish a value, we conveniently derive it from the 240 Boost.MPL <code class="computeroutput"><span class="keyword">class</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">mpl</span><span class="special">::</span><span class="identifier">int_</span></code>: 241 </p> 242<p> 243</p> 244<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">traits</span> 245<span class="special">{</span> 246 <span class="keyword">template</span> <span class="special"><></span> 247 <span class="keyword">struct</span> <span class="identifier">dimension</span><span class="special"><</span><span class="identifier">mypoint</span><span class="special">></span> <span class="special">:</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">mpl</span><span class="special">::</span><span class="identifier">int_</span><span class="special"><</span><span class="number">2</span><span class="special">></span> 248 <span class="special">{};</span> 249<span class="special">}</span> 250</pre> 251<p> 252 </p> 253<p> 254 Like the free get function, the library also contains a dimension meta-function. 255 </p> 256<pre class="programlisting"><span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">P</span><span class="special">></span> 257<span class="keyword">struct</span> <span class="identifier">dimension</span> <span class="special">:</span> <span class="identifier">traits</span><span class="special">::</span><span class="identifier">dimension</span><span class="special"><</span><span class="identifier">P</span><span class="special">></span> 258<span class="special">{};</span> 259</pre> 260<p> 261 Below is explained why the extra declaration is useful. Now we have agnosticism 262 in the number of dimensions. Our more generic distance function now accepts 263 points of three or more dimensions. The compile-time assertion will prevent 264 point a having two dimension and point b having three dimensions. 265 </p> 266<h4> 267<a name="geometry.design.h3"></a> 268 <span class="phrase"><a name="geometry.design.coordinate_type"></a></span><a class="link" href="design.html#geometry.design.coordinate_type">Coordinate 269 Type</a> 270 </h4> 271<p> 272 We assumed double above. What if our points are in integer? 273 </p> 274<p> 275 We can easily add a traits class, and we will do that. However, the distance 276 between two integer coordinates can still be a fractionized value. Besides 277 that, a design goal was to avoid square roots. We handle these cases below, 278 in another paragraph. For the moment we keep returning double, but we allow 279 integer coordinates for our point types. To define the coordinate type, we 280 add another traits class, <code class="computeroutput"><span class="identifier">coordinate_type</span></code>, 281 which should be specialized by the library user: 282 </p> 283<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">traits</span> 284<span class="special">{</span> 285 <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">P</span><span class="special">></span> 286 <span class="keyword">struct</span> <span class="identifier">coordinate_type</span><span class="special">{};</span> 287 288 <span class="comment">// specialization for our mypoint</span> 289 <span class="keyword">template</span> <span class="special"><></span> 290 <span class="keyword">struct</span> <span class="identifier">coordinate_type</span><span class="special"><</span><span class="identifier">mypoint</span><span class="special">></span> 291 <span class="special">{</span> 292 <span class="keyword">typedef</span> <span class="keyword">double</span> <span class="identifier">type</span><span class="special">;</span> 293 <span class="special">};</span> 294<span class="special">}</span> 295</pre> 296<p> 297 Like the access function, where we had a free get function, we add a proxy 298 here as well. A longer version is presented later on, the short function would 299 look like this: 300 </p> 301<pre class="programlisting"><span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">P</span><span class="special">></span> 302<span class="keyword">struct</span> <span class="identifier">coordinate_type</span> <span class="special">:</span> <span class="identifier">traits</span><span class="special">::</span><span class="identifier">coordinate_type</span><span class="special"><</span><span class="identifier">P</span><span class="special">></span> <span class="special">{};</span> 303</pre> 304<p> 305 We now can modify our distance algorithm again. Because it still returns double, 306 we only modify the <code class="computeroutput"><span class="identifier">pythagoras</span></code> 307 computation class. It should return the coordinate type of its input. But, 308 it has two input, possibly different, point types. They might also differ in 309 their coordinate types. Not that that is very likely, but we’re designing 310 a generic library and we should handle those strange cases. We have to choose 311 one of the coordinate types and of course we select the one with the highest 312 precision. This is not worked out here, it would be too long, and it is not 313 related to geometry. We just assume that there is a meta-function <code class="computeroutput"><span class="identifier">select_most_precise</span></code> selecting the best type. 314 </p> 315<p> 316 So our computation class becomes: 317 </p> 318<pre class="programlisting"><span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">P1</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">P2</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">D</span><span class="special">></span> 319<span class="keyword">struct</span> <span class="identifier">pythagoras</span> 320<span class="special">{</span> 321 <span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">select_most_precise</span> 322 <span class="special"><</span> 323 <span class="keyword">typename</span> <span class="identifier">coordinate_type</span><span class="special"><</span><span class="identifier">P1</span><span class="special">>::</span><span class="identifier">type</span><span class="special">,</span> 324 <span class="keyword">typename</span> <span class="identifier">coordinate_type</span><span class="special"><</span><span class="identifier">P2</span><span class="special">>::</span><span class="identifier">type</span> 325 <span class="special">>::</span><span class="identifier">type</span> <span class="identifier">computation_type</span><span class="special">;</span> 326 327 <span class="keyword">static</span> <span class="identifier">computation_type</span> <span class="identifier">apply</span><span class="special">(</span><span class="identifier">P1</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">a</span><span class="special">,</span> <span class="identifier">P2</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">b</span><span class="special">)</span> 328 <span class="special">{</span> 329 <span class="identifier">computation_type</span> <span class="identifier">d</span> <span class="special">=</span> <span class="identifier">get</span><span class="special"><</span><span class="identifier">D</span><span class="special">-</span><span class="number">1</span><span class="special">>(</span><span class="identifier">a</span><span class="special">)</span> <span class="special">-</span> <span class="identifier">get</span><span class="special"><</span><span class="identifier">D</span><span class="special">-</span><span class="number">1</span><span class="special">>(</span><span class="identifier">b</span><span class="special">);</span> 330 <span class="keyword">return</span> <span class="identifier">d</span> <span class="special">*</span> <span class="identifier">d</span> <span class="special">+</span> <span class="identifier">pythagoras</span> <span class="special"><</span><span class="identifier">P1</span><span class="special">,</span> <span class="identifier">P2</span><span class="special">,</span> <span class="identifier">D</span><span class="special">-</span><span class="number">1</span><span class="special">></span> <span class="special">::</span><span class="identifier">apply</span><span class="special">(</span><span class="identifier">a</span><span class="special">,</span> <span class="identifier">b</span><span class="special">);</span> 331 <span class="special">}</span> 332<span class="special">};</span> 333</pre> 334<h4> 335<a name="geometry.design.h4"></a> 336 <span class="phrase"><a name="geometry.design.different_geometries"></a></span><a class="link" href="design.html#geometry.design.different_geometries">Different 337 Geometries</a> 338 </h4> 339<p> 340 We have designed a dimension agnostic system supporting any point type of any 341 coordinate type. There are still some tweaks but they will be worked out later. 342 Now we will see how we calculate the distance between a point and a polygon, 343 or between a point and a line-segment. These formulae are more complex, and 344 the influence on design is even larger. We don’t want to add a function with 345 another name: 346 </p> 347<pre class="programlisting"><span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">P</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">S</span><span class="special">></span> 348<span class="keyword">double</span> <span class="identifier">distance_point_segment</span><span class="special">(</span><span class="identifier">P</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">p</span><span class="special">,</span> <span class="identifier">S</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">s</span><span class="special">)</span> 349</pre> 350<p> 351 We want to be generic, the distance function has to be called from code not 352 knowing the type of geometry it handles, so it has to be named distance. We 353 also cannot create an overload because that would be ambiguous, having the 354 same template signature. There are two solutions: 355 </p> 356<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "> 357<li class="listitem"> 358 tag dispatching 359 </li> 360<li class="listitem"> 361 SFINAE 362 </li> 363</ul></div> 364<p> 365 We select tag dispatching because it fits into the traits system. The earlier 366 versions (previews) of Boost.Geometry used SFINAE but we found it had several 367 drawbacks for such a big design, so the switch to tag dispatching was made. 368 </p> 369<p> 370 With tag dispatching the distance algorithm inspects the type of geometry of 371 the input parameters. The distance function will be changed into this: 372 </p> 373<pre class="programlisting"><span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">G1</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">G2</span><span class="special">></span> 374<span class="keyword">double</span> <span class="identifier">distance</span><span class="special">(</span><span class="identifier">G1</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">g1</span><span class="special">,</span> <span class="identifier">G2</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">g2</span><span class="special">)</span> 375<span class="special">{</span> 376 <span class="keyword">return</span> <span class="identifier">dispatch</span><span class="special">::</span><span class="identifier">distance</span> 377 <span class="special"><</span> 378 <span class="keyword">typename</span> <span class="identifier">tag</span><span class="special"><</span><span class="identifier">G1</span><span class="special">>::</span><span class="identifier">type</span><span class="special">,</span> 379 <span class="keyword">typename</span> <span class="identifier">tag</span><span class="special"><</span><span class="identifier">G2</span><span class="special">>::</span><span class="identifier">type</span><span class="special">,</span> 380 <span class="identifier">G1</span><span class="special">,</span> <span class="identifier">G2</span> 381 <span class="special">>::</span><span class="identifier">apply</span><span class="special">(</span><span class="identifier">g1</span><span class="special">,</span> <span class="identifier">g2</span><span class="special">);</span> 382<span class="special">}</span> 383</pre> 384<p> 385 It is referring to the tag meta-function and forwarding the call to the <span class="bold"><strong>apply</strong></span> method of a <span class="emphasis"><em>dispatch::distance</em></span> 386 structure. The <span class="bold"><strong>tag</strong></span> meta-function is another 387 traits class, and should be specialized for per point type, both shown here: 388 </p> 389<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">traits</span> 390<span class="special">{</span> 391 <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">G</span><span class="special">></span> 392 <span class="keyword">struct</span> <span class="identifier">tag</span> <span class="special">{};</span> 393 394 <span class="comment">// specialization</span> 395 <span class="keyword">template</span> <span class="special"><></span> 396 <span class="keyword">struct</span> <span class="identifier">tag</span><span class="special"><</span><span class="identifier">mypoint</span><span class="special">></span> 397 <span class="special">{</span> 398 <span class="keyword">typedef</span> <span class="identifier">point_tag</span> <span class="identifier">type</span><span class="special">;</span> 399 <span class="special">};</span> 400<span class="special">}</span> 401</pre> 402<p> 403 Free meta-function, like coordinate_system and get: 404 </p> 405<pre class="programlisting"><span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">G</span><span class="special">></span> 406<span class="keyword">struct</span> <span class="identifier">tag</span> <span class="special">:</span> <span class="identifier">traits</span><span class="special">::</span><span class="identifier">tag</span><span class="special"><</span><span class="identifier">G</span><span class="special">></span> <span class="special">{};</span> 407</pre> 408<p> 409 <span class="bold"><strong>Tags</strong></span> (<code class="computeroutput"><span class="identifier">point_tag</span></code>, 410 <code class="computeroutput"><span class="identifier">segment_tag</span></code>, etc) are empty 411 structures with the purpose to specialize a dispatch struct. The dispatch struct 412 for distance, and its specializations, are all defined in a separate namespace 413 and look like the following: 414 </p> 415<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">dispatch</span> <span class="special">{</span> 416 <span class="keyword">template</span> <span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Tag1</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Tag2</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">G1</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">G2</span> <span class="special">></span> 417 <span class="keyword">struct</span> <span class="identifier">distance</span> 418 <span class="special">{};</span> 419 420 <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">P1</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">P2</span><span class="special">></span> 421 <span class="keyword">struct</span> <span class="identifier">distance</span> <span class="special"><</span> <span class="identifier">point_tag</span><span class="special">,</span> <span class="identifier">point_tag</span><span class="special">,</span> <span class="identifier">P1</span><span class="special">,</span> <span class="identifier">P2</span> <span class="special">></span> 422 <span class="special">{</span> 423 <span class="keyword">static</span> <span class="keyword">double</span> <span class="identifier">apply</span><span class="special">(</span><span class="identifier">P1</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">a</span><span class="special">,</span> <span class="identifier">P2</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">b</span><span class="special">)</span> 424 <span class="special">{</span> 425 <span class="comment">// here we call pythagoras</span> 426 <span class="comment">// exactly like we did before</span> 427 <span class="special">...</span> 428 <span class="special">}</span> 429 <span class="special">};</span> 430 431 <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">P</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">S</span><span class="special">></span> 432 <span class="keyword">struct</span> <span class="identifier">distance</span> 433 <span class="special"><</span> 434 <span class="identifier">point_tag</span><span class="special">,</span> <span class="identifier">segment_tag</span><span class="special">,</span> <span class="identifier">P</span><span class="special">,</span> <span class="identifier">S</span> 435 <span class="special">></span> 436 <span class="special">{</span> 437 <span class="keyword">static</span> <span class="keyword">double</span> <span class="identifier">apply</span><span class="special">(</span><span class="identifier">P</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">p</span><span class="special">,</span> <span class="identifier">S</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">s</span><span class="special">)</span> 438 <span class="special">{</span> 439 <span class="comment">// here we refer to another function</span> 440 <span class="comment">// implementing point-segment</span> 441 <span class="comment">// calculations in 2 or 3</span> 442 <span class="comment">// dimensions...</span> 443 <span class="special">...</span> 444 <span class="special">}</span> 445 <span class="special">};</span> 446 447 <span class="comment">// here we might have many more</span> 448 <span class="comment">// specializations,</span> 449 <span class="comment">// for point-polygon, box-circle, etc.</span> 450 451<span class="special">}</span> <span class="comment">// namespace</span> 452</pre> 453<p> 454 So yes, it is possible; the distance algorithm is generic now in the sense 455 that it also supports different geometry types. One drawback: we have to define 456 two dispatch specializations for point - segment and for segment - point separately. 457 That will also be solved, in the paragraph reversibility below. The example 458 below shows where we are now: different point types, geometry types, dimensions. 459 </p> 460<pre class="programlisting"><span class="identifier">point</span> <span class="identifier">a</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="number">1</span><span class="special">);</span> 461<span class="identifier">point</span> <span class="identifier">b</span><span class="special">(</span><span class="number">2</span><span class="special">,</span><span class="number">2</span><span class="special">);</span> 462<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">distance</span><span class="special">(</span><span class="identifier">a</span><span class="special">,</span><span class="identifier">b</span><span class="special">)</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> 463<span class="identifier">segment</span> <span class="identifier">s1</span><span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="number">0</span><span class="special">,</span><span class="number">5</span><span class="special">,</span><span class="number">3</span><span class="special">);</span> 464<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">distance</span><span class="special">(</span><span class="identifier">a</span><span class="special">,</span> <span class="identifier">s1</span><span class="special">)</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> 465<span class="identifier">rgb</span> <span class="identifier">red</span><span class="special">(</span><span class="number">255</span><span class="special">,</span> <span class="number">0</span><span class="special">,</span> <span class="number">0</span><span class="special">);</span> 466<span class="identifier">rbc</span> <span class="identifier">orange</span><span class="special">(</span><span class="number">255</span><span class="special">,</span> <span class="number">128</span><span class="special">,</span> <span class="number">0</span><span class="special">);</span> 467<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"color distance: "</span> <span class="special"><<</span> <span class="identifier">distance</span><span class="special">(</span><span class="identifier">red</span><span class="special">,</span> <span class="identifier">orange</span><span class="special">)</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> 468</pre> 469<h4> 470<a name="geometry.design.h5"></a> 471 <span class="phrase"><a name="geometry.design.kernel_revisited"></a></span><a class="link" href="design.html#geometry.design.kernel_revisited">Kernel 472 Revisited</a> 473 </h4> 474<p> 475 We described above that we had a traits class <code class="computeroutput"><span class="identifier">coordinate_type</span></code>, 476 defined in namespace traits, and defined a separate <code class="computeroutput"><span class="identifier">coordinate_type</span></code> 477 class as well. This was actually not really necessary before, because the only 478 difference was the namespace clause. But now that we have another geometry 479 type, a segment in this case, it is essential. We can call the <code class="computeroutput"><span class="identifier">coordinate_type</span></code> meta-function for any geometry 480 type, point, segment, polygon, etc, implemented again by tag dispatching: 481 </p> 482<pre class="programlisting"><span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">G</span><span class="special">></span> 483<span class="keyword">struct</span> <span class="identifier">coordinate_type</span> 484<span class="special">{</span> 485 <span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">dispatch</span><span class="special">::</span><span class="identifier">coordinate_type</span> 486 <span class="special"><</span> 487 <span class="keyword">typename</span> <span class="identifier">tag</span><span class="special"><</span><span class="identifier">G</span><span class="special">>::</span><span class="identifier">type</span><span class="special">,</span> <span class="identifier">G</span> 488 <span class="special">>::</span><span class="identifier">type</span> <span class="identifier">type</span><span class="special">;</span> 489<span class="special">};</span> 490</pre> 491<p> 492 Inside the dispatch namespace this meta-function is implemented twice: a generic 493 version and one specialization for points. The specialization for points calls 494 the traits class. The generic version calls the point specialization, as a 495 sort of recursive meta-function definition: 496 </p> 497<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">dispatch</span> 498<span class="special">{</span> 499 500 <span class="comment">// Version for any geometry:</span> 501 <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">GeometryTag</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">G</span><span class="special">></span> 502 <span class="keyword">struct</span> <span class="identifier">coordinate_type</span> 503 <span class="special">{</span> 504 <span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">point_type</span> 505 <span class="special"><</span> 506 <span class="identifier">GeometryTag</span><span class="special">,</span> <span class="identifier">G</span> 507 <span class="special">>::</span><span class="identifier">type</span> <span class="identifier">point_type</span><span class="special">;</span> 508 509 <span class="comment">// Call specialization on point-tag</span> 510 <span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">coordinate_type</span> <span class="special"><</span> <span class="identifier">point_tag</span><span class="special">,</span> <span class="identifier">point_type</span> <span class="special">>::</span><span class="identifier">type</span> <span class="identifier">type</span><span class="special">;</span> 511 <span class="special">};</span> 512 513 <span class="comment">// Specialization for point-type:</span> 514 <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">P</span><span class="special">></span> 515 <span class="keyword">struct</span> <span class="identifier">coordinate_type</span><span class="special"><</span><span class="identifier">point_tag</span><span class="special">,</span> <span class="identifier">P</span><span class="special">></span> 516 <span class="special">{</span> 517 <span class="keyword">typedef</span> <span class="keyword">typename</span> 518 <span class="identifier">traits</span><span class="special">::</span><span class="identifier">coordinate_type</span><span class="special"><</span><span class="identifier">P</span><span class="special">>::</span><span class="identifier">type</span> 519 <span class="identifier">type</span><span class="special">;</span> 520 <span class="special">};</span> 521<span class="special">}</span> 522</pre> 523<p> 524 So it calls another meta-function point_type. This is not elaborated in here 525 but realize that it is available for all geometry types, and typedefs the point 526 type which makes up the geometry, calling it type. 527 </p> 528<p> 529 The same applies for the meta-function dimension and for the upcoming meta-function 530 coordinate system. 531 </p> 532<h4> 533<a name="geometry.design.h6"></a> 534 <span class="phrase"><a name="geometry.design.coordinate_system"></a></span><a class="link" href="design.html#geometry.design.coordinate_system">Coordinate 535 System</a> 536 </h4> 537<p> 538 Until here we assumed a Cartesian system. But we know that the Earth is not 539 flat. Calculating a distance between two GPS-points with the system above would 540 result in nonsense. So we again extend our design. We define for each point 541 type a coordinate system type using the traits system again. Then we make the 542 calculation dependant on that coordinate system. 543 </p> 544<p> 545 Coordinate system is similar to coordinate type, a meta-function, calling a 546 dispatch function to have it for any geometry-type, forwarding to its point 547 specialization, and finally calling a traits class, defining a typedef type 548 with a coordinate system. We don’t show that all here again. We only show 549 the definition of a few coordinate systems: 550 </p> 551<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">cartesian</span> <span class="special">{};</span> 552 553<span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">DegreeOrRadian</span><span class="special">></span> 554<span class="keyword">struct</span> <span class="identifier">geographic</span> 555<span class="special">{</span> 556 <span class="keyword">typedef</span> <span class="identifier">DegreeOrRadian</span> <span class="identifier">units</span><span class="special">;</span> 557<span class="special">};</span> 558</pre> 559<p> 560 So Cartesian is simple, for geographic we can also select if its coordinates 561 are stored in degrees or in radians. 562 </p> 563<p> 564 The distance function will now change: it will select the computation method 565 for the corresponding coordinate system and then call the dispatch struct for 566 distance. We call the computation method specialized for coordinate systems 567 a strategy. So the new version of the distance function is: 568 </p> 569<pre class="programlisting"><span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">G1</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">G2</span><span class="special">></span> 570<span class="keyword">double</span> <span class="identifier">distance</span><span class="special">(</span><span class="identifier">G1</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">g1</span><span class="special">,</span> <span class="identifier">G2</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">g2</span><span class="special">)</span> 571<span class="special">{</span> 572 <span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">strategy_distance</span> 573 <span class="special"><</span> 574 <span class="keyword">typename</span> <span class="identifier">coordinate_system</span><span class="special"><</span><span class="identifier">G1</span><span class="special">>::</span><span class="identifier">type</span><span class="special">,</span> 575 <span class="keyword">typename</span> <span class="identifier">coordinate_system</span><span class="special"><</span><span class="identifier">G2</span><span class="special">>::</span><span class="identifier">type</span><span class="special">,</span> 576 <span class="keyword">typename</span> <span class="identifier">point_type</span><span class="special"><</span><span class="identifier">G1</span><span class="special">>::</span><span class="identifier">type</span><span class="special">,</span> 577 <span class="keyword">typename</span> <span class="identifier">point_type</span><span class="special"><</span><span class="identifier">G2</span><span class="special">>::</span><span class="identifier">type</span><span class="special">,</span> 578 <span class="identifier">dimension</span><span class="special"><</span><span class="identifier">G1</span><span class="special">>::</span><span class="identifier">value</span> 579 <span class="special">>::</span><span class="identifier">type</span> <span class="identifier">strategy</span><span class="special">;</span> 580 581 <span class="keyword">return</span> <span class="identifier">dispatch</span><span class="special">::</span><span class="identifier">distance</span> 582 <span class="special"><</span> 583 <span class="keyword">typename</span> <span class="identifier">tag</span><span class="special"><</span><span class="identifier">G1</span><span class="special">>::</span><span class="identifier">type</span><span class="special">,</span> 584 <span class="keyword">typename</span> <span class="identifier">tag</span><span class="special"><</span><span class="identifier">G2</span><span class="special">>::</span><span class="identifier">type</span><span class="special">,</span> 585 <span class="identifier">G1</span><span class="special">,</span> <span class="identifier">G2</span><span class="special">,</span> <span class="identifier">strategy</span> 586 <span class="special">>::</span><span class="identifier">apply</span><span class="special">(</span><span class="identifier">g1</span><span class="special">,</span> <span class="identifier">g2</span><span class="special">,</span> <span class="identifier">strategy</span><span class="special">());</span> 587<span class="special">}</span> 588</pre> 589<p> 590 The strategy_distance mentioned here is a struct with specializations for different 591 coordinate systems. 592 </p> 593<pre class="programlisting"><span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T1</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">T2</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">P1</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">P2</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">D</span><span class="special">></span> 594<span class="keyword">struct</span> <span class="identifier">strategy_distance</span> 595<span class="special">{</span> 596 <span class="keyword">typedef</span> <span class="keyword">void</span> <span class="identifier">type</span><span class="special">;</span> 597<span class="special">};</span> 598 599<span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">P1</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">P2</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">D</span><span class="special">></span> 600<span class="keyword">struct</span> <span class="identifier">strategy_distance</span><span class="special"><</span><span class="identifier">cartesian</span><span class="special">,</span> <span class="identifier">cartesian</span><span class="special">,</span> <span class="identifier">P1</span><span class="special">,</span> <span class="identifier">P2</span><span class="special">,</span> <span class="identifier">D</span><span class="special">></span> 601<span class="special">{</span> 602 <span class="keyword">typedef</span> <span class="identifier">pythagoras</span><span class="special"><</span><span class="identifier">P1</span><span class="special">,</span> <span class="identifier">P2</span><span class="special">,</span> <span class="identifier">D</span><span class="special">></span> <span class="identifier">type</span><span class="special">;</span> 603<span class="special">};</span> 604</pre> 605<p> 606 So, here is our <code class="computeroutput"><span class="identifier">pythagoras</span></code> 607 again, now defined as a strategy. The distance dispatch function just calls 608 its apply method. 609 </p> 610<p> 611 So this is an important step: for spherical or geographical coordinate systems, 612 another strategy (computation method) can be implemented. For spherical coordinate 613 systems have the haversine formula. So the dispatching traits struct is specialized 614 like this 615 </p> 616<pre class="programlisting"><span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">P1</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">P2</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">D</span> <span class="special">=</span> <span class="number">2</span><span class="special">></span> 617<span class="keyword">struct</span> <span class="identifier">strategy_distance</span><span class="special"><</span><span class="identifier">spherical</span><span class="special">,</span> <span class="identifier">spherical</span><span class="special">,</span> <span class="identifier">P1</span><span class="special">,</span> <span class="identifier">P2</span><span class="special">,</span> <span class="identifier">D</span><span class="special">></span> 618<span class="special">{</span> 619 <span class="keyword">typedef</span> <span class="identifier">haversine</span><span class="special"><</span><span class="identifier">P1</span><span class="special">,</span> <span class="identifier">P2</span><span class="special">></span> <span class="identifier">type</span><span class="special">;</span> 620<span class="special">};</span> 621 622<span class="comment">// struct haversine with apply function</span> 623<span class="comment">// is omitted here</span> 624</pre> 625<p> 626 For geography, we have some alternatives for distance calculation. There is 627 the Andoyer method, fast and precise, and there is the Vincenty method, slower 628 and more precise, and there are some less precise approaches as well. 629 </p> 630<p> 631 Per coordinate system, one strategy is defined as the default strategy. To 632 be able to use another strategy as well, we modify our design again and add 633 an overload for the distance algorithm, taking a strategy object as a third 634 parameter. 635 </p> 636<p> 637 This new overload distance function also has the advantage that the strategy 638 can be constructed outside the distance function. Because it was constructed 639 inside above, it could not have construction parameters. But for Andoyer or 640 Vincenty, or the haversine formula, it certainly makes sense to have a constructor 641 taking the radius of the earth as a parameter. 642 </p> 643<p> 644 So, the distance overloaded function is: 645 </p> 646<pre class="programlisting"><span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">G1</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">G2</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">S</span><span class="special">></span> 647<span class="keyword">double</span> <span class="identifier">distance</span><span class="special">(</span><span class="identifier">G1</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">g1</span><span class="special">,</span> <span class="identifier">G2</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">g2</span><span class="special">,</span> <span class="identifier">S</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">strategy</span><span class="special">)</span> 648<span class="special">{</span> 649 <span class="keyword">return</span> <span class="identifier">dispatch</span><span class="special">::</span><span class="identifier">distance</span> 650 <span class="special"><</span> 651 <span class="keyword">typename</span> <span class="identifier">tag</span><span class="special"><</span><span class="identifier">G1</span><span class="special">>::</span><span class="identifier">type</span><span class="special">,</span> 652 <span class="keyword">typename</span> <span class="identifier">tag</span><span class="special"><</span><span class="identifier">G2</span><span class="special">>::</span><span class="identifier">type</span><span class="special">,</span> 653 <span class="identifier">G1</span><span class="special">,</span> <span class="identifier">G2</span><span class="special">,</span> <span class="identifier">S</span> 654 <span class="special">>::</span><span class="identifier">apply</span><span class="special">(</span><span class="identifier">g1</span><span class="special">,</span> <span class="identifier">g2</span><span class="special">,</span> <span class="identifier">strategy</span><span class="special">);</span> 655<span class="special">}</span> 656</pre> 657<p> 658 The strategy has to have a method apply taking two points as arguments (for 659 points). It is not required that it is a static method. A strategy might define 660 a constructor, where a configuration value is passed and stored as a member 661 variable. In those cases a static method would be inconvenient. It can be implemented 662 as a normal method (with the const qualifier). 663 </p> 664<p> 665 We do not list all implementations here, Vincenty would cover half a page of 666 mathematics, but you will understand the idea. We can call distance like this: 667 </p> 668<pre class="programlisting"><span class="identifier">distance</span><span class="special">(</span><span class="identifier">c1</span><span class="special">,</span> <span class="identifier">c2</span><span class="special">)</span> 669</pre> 670<p> 671 where <code class="computeroutput"><span class="identifier">c1</span></code> and <code class="computeroutput"><span class="identifier">c2</span></code> are Cartesian points, or like this: 672 </p> 673<pre class="programlisting"><span class="identifier">distance</span><span class="special">(</span><span class="identifier">g1</span><span class="special">,</span> <span class="identifier">g2</span><span class="special">)</span> 674</pre> 675<p> 676 where <code class="computeroutput"><span class="identifier">g1</span></code> and <code class="computeroutput"><span class="identifier">g2</span></code> are Geographic points, calling the default 677 strategy for Geographic points (e.g. Andoyer), and like this: 678 </p> 679<pre class="programlisting"><span class="identifier">distance</span><span class="special">(</span><span class="identifier">g1</span><span class="special">,</span> <span class="identifier">g2</span><span class="special">,</span> <span class="identifier">vincenty</span><span class="special"><</span><span class="identifier">G1</span><span class="special">,</span> <span class="identifier">G2</span><span class="special">>(</span><span class="number">6275</span><span class="special">))</span> 680</pre> 681<p> 682 where a strategy is specified explicitly and constructed with a radius. 683 </p> 684<h4> 685<a name="geometry.design.h7"></a> 686 <span class="phrase"><a name="geometry.design.point_concept"></a></span><a class="link" href="design.html#geometry.design.point_concept">Point 687 Concept</a> 688 </h4> 689<p> 690 The five traits classes mentioned in the previous sections form together the 691 Point Concept. Any point type for which specializations are implemented in 692 the traits namespace should be accepted as a valid type. So the Point Concept 693 consists of: 694 </p> 695<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "> 696<li class="listitem"> 697 a specialization for <code class="computeroutput"><span class="identifier">traits</span><span class="special">::</span><span class="identifier">tag</span></code> 698 </li> 699<li class="listitem"> 700 a specialization for <code class="computeroutput"><span class="identifier">traits</span><span class="special">::</span><span class="identifier">coordinate_system</span></code> 701 </li> 702<li class="listitem"> 703 a specialization for <code class="computeroutput"><span class="identifier">traits</span><span class="special">::</span><span class="identifier">coordinate_type</span></code> 704 </li> 705<li class="listitem"> 706 a specialization for <code class="computeroutput"><span class="identifier">traits</span><span class="special">::</span><span class="identifier">dimension</span></code> 707 </li> 708<li class="listitem"> 709 a specialization for <code class="computeroutput"><span class="identifier">traits</span><span class="special">::</span><span class="identifier">access</span></code> 710 </li> 711</ul></div> 712<p> 713 The last one is a class, containing the method get and the (optional) method 714 set, the first four are metafunctions, either defining type or declaring a 715 value (conform MPL conventions). 716 </p> 717<p> 718 So we now have agnosticism for the number of dimensions, agnosticism for coordinate 719 systems; the design can handle any coordinate type, and it can handle different 720 geometry types. Furthermore we can specify our own strategies, the code will 721 not compile in case of two points with different dimensions (because of the 722 assertion), and it will not compile for two points with different coordinate 723 systems (because there is no specialization). A library can check if a point 724 type fulfills the requirements imposed by the concepts. This is handled in 725 the upcoming section Concept Checking. 726 </p> 727<h4> 728<a name="geometry.design.h8"></a> 729 <span class="phrase"><a name="geometry.design.return_type"></a></span><a class="link" href="design.html#geometry.design.return_type">Return 730 Type</a> 731 </h4> 732<p> 733 We promised that calling <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">sqrt</span></code> was 734 not always necessary. So we define a distance result <code class="computeroutput"><span class="keyword">struct</span></code> 735 that contains the squared value and is convertible to a double value. This, 736 however, only has to be done for <code class="computeroutput"><span class="identifier">pythagoras</span></code>. 737 The spherical distance functions do not take the square root so for them it 738 is not necessary to avoid the expensive square root call; they can just return 739 their distance. 740 </p> 741<p> 742 So the distance result struct is dependant on strategy, therefore made a member 743 type of the strategy. The result struct looks like this: 744 </p> 745<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T</span> <span class="special">=</span> <span class="keyword">double</span><span class="special">></span> 746<span class="keyword">struct</span> <span class="identifier">cartesian_distance</span> 747<span class="special">{</span> 748 <span class="identifier">T</span> <span class="identifier">sq</span><span class="special">;</span> 749 <span class="keyword">explicit</span> <span class="identifier">cartesian_distance</span><span class="special">(</span><span class="identifier">T</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">v</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">sq</span> <span class="special">(</span><span class="identifier">v</span><span class="special">)</span> <span class="special">{}</span> 750 751 <span class="keyword">inline</span> <span class="keyword">operator</span> <span class="identifier">T</span><span class="special">()</span> <span class="keyword">const</span> 752 <span class="special">{</span> 753 <span class="keyword">return</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">sqrt</span><span class="special">(</span><span class="identifier">sq</span><span class="special">);</span> 754 <span class="special">}</span> 755<span class="special">};</span> 756</pre> 757<p> 758 It also has operators defined to compare itself to other results without taking 759 the square root. 760 </p> 761<p> 762 Each strategy should define its return type, within the strategy class, for 763 example: 764 </p> 765<pre class="programlisting"><span class="keyword">typedef</span> <span class="identifier">cartesian_distance</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="identifier">return_type</span><span class="special">;</span> 766</pre> 767<p> 768 or: 769 </p> 770<pre class="programlisting"><span class="keyword">typedef</span> <span class="keyword">double</span> <span class="identifier">return_type</span><span class="special">;</span> 771</pre> 772<p> 773 for cartesian (pythagoras) and spherical, respectively. 774 </p> 775<p> 776 Again our distance function will be modified, as expected, to reflect the new 777 return type. For the overload with a strategy it is not complex: 778 </p> 779<pre class="programlisting"><span class="keyword">template</span> <span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">G1</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">G2</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Strategy</span> <span class="special">></span> 780<span class="keyword">typename</span> <span class="identifier">Strategy</span><span class="special">::</span><span class="identifier">return_type</span> <span class="identifier">distance</span><span class="special">(</span> <span class="identifier">G1</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">G1</span> <span class="special">,</span> <span class="identifier">G2</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">G2</span> <span class="special">,</span> <span class="identifier">S</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">strategy</span><span class="special">)</span> 781</pre> 782<p> 783 But for the one without strategy we have to select strategy, coordinate type, 784 etc. It would be spacious to do it in one line so we add a separate meta-function: 785 </p> 786<pre class="programlisting"><span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">G1</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">G2</span> <span class="special">=</span> <span class="identifier">G1</span><span class="special">></span> 787<span class="keyword">struct</span> <span class="identifier">distance_result</span> 788<span class="special">{</span> 789 <span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">point_type</span><span class="special"><</span><span class="identifier">G1</span><span class="special">>::</span><span class="identifier">type</span> <span class="identifier">P1</span><span class="special">;</span> 790 <span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">point_type</span><span class="special"><</span><span class="identifier">G2</span><span class="special">>::</span><span class="identifier">type</span> <span class="identifier">P2</span><span class="special">;</span> 791 <span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">strategy_distance</span> 792 <span class="special"><</span> 793 <span class="keyword">typename</span> <span class="identifier">cs_tag</span><span class="special"><</span><span class="identifier">P1</span><span class="special">>::</span><span class="identifier">type</span><span class="special">,</span> 794 <span class="keyword">typename</span> <span class="identifier">cs_tag</span><span class="special"><</span><span class="identifier">P2</span><span class="special">>::</span><span class="identifier">type</span><span class="special">,</span> 795 <span class="identifier">P1</span><span class="special">,</span> <span class="identifier">P2</span> 796 <span class="special">>::</span><span class="identifier">type</span> <span class="identifier">S</span><span class="special">;</span> 797 798 <span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">S</span><span class="special">::</span><span class="identifier">return_type</span> <span class="identifier">type</span><span class="special">;</span> 799<span class="special">};</span> 800</pre> 801<p> 802 and modify our distance function: 803 </p> 804<pre class="programlisting"><span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">G1</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">G2</span><span class="special">></span> 805<span class="keyword">inline</span> <span class="keyword">typename</span> <span class="identifier">distance_result</span><span class="special"><</span><span class="identifier">G1</span><span class="special">,</span> <span class="identifier">G2</span><span class="special">>::</span><span class="identifier">type</span> <span class="identifier">distance</span><span class="special">(</span><span class="identifier">G1</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">g1</span><span class="special">,</span> <span class="identifier">G2</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">g2</span><span class="special">)</span> 806<span class="special">{</span> 807 <span class="comment">// ...</span> 808<span class="special">}</span> 809</pre> 810<p> 811 Of course also the apply functions in the dispatch specializations will return 812 a result like this. They have a strategy as a template parameter everywhere, 813 making the less verbose version possible. 814 </p> 815<h4> 816<a name="geometry.design.h9"></a> 817 <span class="phrase"><a name="geometry.design.axis_order"></a></span><a class="link" href="design.html#geometry.design.axis_order">Axis 818 Order</a> 819 </h4> 820<p> 821 This is an important note for users who develop GIS applications, require compliance 822 with OGC standards or use variety of coordinate reference systems (CRS). 823 </p> 824<p> 825 Boost.Geometry convention is that coordinate values of 2D tuple is always given 826 according to mathematical axis order: X,Y. Considering GIS applications, that 827 always means easting,northing or, in terms of geographic coordinate system: 828 longitude,latitude. Boost.Geometry does not allow or respect coordinate values 829 listed in the axis order as specified by coordinate reference system (CRS). 830 </p> 831<p> 832 In practice, users may easily adapt point types with alternate axis ordering 833 and specify coordinate access in order as expected by Boost.Geometry. 834 </p> 835<h4> 836<a name="geometry.design.h10"></a> 837 <span class="phrase"><a name="geometry.design.summary"></a></span><a class="link" href="design.html#geometry.design.summary">Summary</a> 838 </h4> 839<p> 840 In this design rationale, Boost.Geometry is step by step designed using tag 841 dispatching, concepts, traits, and metaprogramming. We used the well-known 842 distance function to show the design. 843 </p> 844<p> 845 Boost.Geometry is designed like described here, with some more techniques as 846 automatically reversing template arguments, tag casting, and reusing implementation 847 classes or dispatch classes as policies in other dispatch classes. 848 </p> 849</div> 850<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> 851<td align="left"></td> 852<td align="right"><div class="copyright-footer">Copyright © 2009-2019 Barend Gehrels, Bruno Lalande, Mateusz Loskot, Adam 853 Wulkiewicz, Oracle and/or its affiliates<p> 854 Distributed under the Boost Software License, Version 1.0. (See accompanying 855 file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>) 856 </p> 857</div></td> 858</tr></table> 859<hr> 860<div class="spirit-nav"> 861<a accesskey="p" href="compilation.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="quickstart.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a> 862</div> 863</body> 864</html> 865