• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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">&amp;</span> <span class="identifier">a</span><span class="special">,</span> <span class="identifier">mypoint</span> <span class="keyword">const</span><span class="special">&amp;</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">&lt;</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">&gt;</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">&amp;</span> <span class="identifier">a</span><span class="special">,</span> <span class="identifier">P2</span> <span class="keyword">const</span><span class="special">&amp;</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">&lt;</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">&gt;</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">&amp;</span> <span class="identifier">a</span><span class="special">,</span> <span class="identifier">P2</span> <span class="keyword">const</span><span class="special">&amp;</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">&lt;</span><span class="number">0</span><span class="special">&gt;(</span><span class="identifier">a</span><span class="special">)</span> <span class="special">-</span> <span class="identifier">get</span><span class="special">&lt;</span><span class="number">0</span><span class="special">&gt;(</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">&lt;</span><span class="number">1</span><span class="special">&gt;(</span><span class="identifier">a</span><span class="special">)</span> <span class="special">-</span> <span class="identifier">get</span><span class="special">&lt;</span><span class="number">1</span><span class="special">&gt;(</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">&lt;</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">&gt;</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">&lt;&gt;</span>
145    <span class="keyword">struct</span> <span class="identifier">access</span><span class="special">&lt;</span><span class="identifier">mypoint</span><span class="special">,</span> <span class="number">0</span><span class="special">&gt;</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">&amp;</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">&lt;</span><span class="identifier">mypoint</span><span class="special">,</span> <span class="number">0</span><span class="special">&gt;::</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">&lt;</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">&gt;</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">&amp;</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">&lt;</span><span class="identifier">P</span><span class="special">,</span> <span class="identifier">D</span><span class="special">&gt;::</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">&lt;</span><span class="number">0</span><span class="special">&gt;(</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">&lt;</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">&gt;</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">&amp;</span> <span class="identifier">a</span><span class="special">,</span> <span class="identifier">P2</span> <span class="keyword">const</span><span class="special">&amp;</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">&lt;</span><span class="identifier">D</span><span class="special">-</span><span class="number">1</span><span class="special">&gt;(</span><span class="identifier">a</span><span class="special">)</span> <span class="special">-</span> <span class="identifier">get</span><span class="special">&lt;</span><span class="identifier">D</span><span class="special">-</span><span class="number">1</span><span class="special">&gt;(</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">&lt;</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">&gt;::</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">&lt;</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">&gt;</span>
201<span class="keyword">struct</span> <span class="identifier">pythagoras</span><span class="special">&lt;</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">&gt;</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">&amp;,</span> <span class="identifier">P2</span> <span class="keyword">const</span><span class="special">&amp;)</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">&lt;</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">&gt;</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">&amp;</span> <span class="identifier">a</span><span class="special">,</span> <span class="identifier">P2</span> <span class="keyword">const</span><span class="special">&amp;</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">&lt;</span><span class="identifier">P1</span><span class="special">&gt;::</span><span class="identifier">value</span> <span class="special">==</span> <span class="identifier">dimension</span><span class="special">&lt;</span><span class="identifier">P2</span><span class="special">&gt;::</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">&lt;</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">&lt;</span><span class="identifier">P1</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&gt;::</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">&lt;</span><span class="keyword">typename</span> <span class="identifier">P</span><span class="special">&gt;</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">&lt;&gt;</span>
247    <span class="keyword">struct</span> <span class="identifier">dimension</span><span class="special">&lt;</span><span class="identifier">mypoint</span><span class="special">&gt;</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">&lt;</span><span class="number">2</span><span class="special">&gt;</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">&lt;</span><span class="keyword">typename</span> <span class="identifier">P</span><span class="special">&gt;</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">&lt;</span><span class="identifier">P</span><span class="special">&gt;</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">&lt;</span><span class="keyword">typename</span> <span class="identifier">P</span><span class="special">&gt;</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">&lt;&gt;</span>
290    <span class="keyword">struct</span> <span class="identifier">coordinate_type</span><span class="special">&lt;</span><span class="identifier">mypoint</span><span class="special">&gt;</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">&lt;</span><span class="keyword">typename</span> <span class="identifier">P</span><span class="special">&gt;</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">&lt;</span><span class="identifier">P</span><span class="special">&gt;</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">&lt;</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">&gt;</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">&lt;</span>
323            <span class="keyword">typename</span> <span class="identifier">coordinate_type</span><span class="special">&lt;</span><span class="identifier">P1</span><span class="special">&gt;::</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">&lt;</span><span class="identifier">P2</span><span class="special">&gt;::</span><span class="identifier">type</span>
325        <span class="special">&gt;::</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">&amp;</span> <span class="identifier">a</span><span class="special">,</span> <span class="identifier">P2</span> <span class="keyword">const</span><span class="special">&amp;</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">&lt;</span><span class="identifier">D</span><span class="special">-</span><span class="number">1</span><span class="special">&gt;(</span><span class="identifier">a</span><span class="special">)</span> <span class="special">-</span> <span class="identifier">get</span><span class="special">&lt;</span><span class="identifier">D</span><span class="special">-</span><span class="number">1</span><span class="special">&gt;(</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">&lt;</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">&gt;</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">&lt;</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">&gt;</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">&amp;</span> <span class="identifier">p</span><span class="special">,</span> <span class="identifier">S</span> <span class="keyword">const</span><span class="special">&amp;</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">&lt;</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">&gt;</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">&amp;</span> <span class="identifier">g1</span><span class="special">,</span> <span class="identifier">G2</span> <span class="keyword">const</span><span class="special">&amp;</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">&lt;</span>
378            <span class="keyword">typename</span> <span class="identifier">tag</span><span class="special">&lt;</span><span class="identifier">G1</span><span class="special">&gt;::</span><span class="identifier">type</span><span class="special">,</span>
379            <span class="keyword">typename</span> <span class="identifier">tag</span><span class="special">&lt;</span><span class="identifier">G2</span><span class="special">&gt;::</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">&gt;::</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">&lt;</span><span class="keyword">typename</span> <span class="identifier">G</span><span class="special">&gt;</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">&lt;&gt;</span>
396    <span class="keyword">struct</span> <span class="identifier">tag</span><span class="special">&lt;</span><span class="identifier">mypoint</span><span class="special">&gt;</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">&lt;</span><span class="keyword">typename</span> <span class="identifier">G</span><span class="special">&gt;</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">&lt;</span><span class="identifier">G</span><span class="special">&gt;</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">&lt;</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">&gt;</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">&lt;</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">&gt;</span>
421    <span class="keyword">struct</span> <span class="identifier">distance</span> <span class="special">&lt;</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">&gt;</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">&amp;</span> <span class="identifier">a</span><span class="special">,</span> <span class="identifier">P2</span> <span class="keyword">const</span><span class="special">&amp;</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">&lt;</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">&gt;</span>
432    <span class="keyword">struct</span> <span class="identifier">distance</span>
433    <span class="special">&lt;</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">&gt;</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">&amp;</span> <span class="identifier">p</span><span class="special">,</span> <span class="identifier">S</span> <span class="keyword">const</span><span class="special">&amp;</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">&lt;&lt;</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">&lt;&lt;</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">&lt;&lt;</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">&lt;&lt;</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">&lt;&lt;</span> <span class="string">"color distance: "</span> <span class="special">&lt;&lt;</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">&lt;&lt;</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">&lt;</span><span class="keyword">typename</span> <span class="identifier">G</span><span class="special">&gt;</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">&lt;</span>
487            <span class="keyword">typename</span> <span class="identifier">tag</span><span class="special">&lt;</span><span class="identifier">G</span><span class="special">&gt;::</span><span class="identifier">type</span><span class="special">,</span> <span class="identifier">G</span>
488        <span class="special">&gt;::</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">&lt;</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">&gt;</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">&lt;</span>
506                <span class="identifier">GeometryTag</span><span class="special">,</span> <span class="identifier">G</span>
507            <span class="special">&gt;::</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">&lt;</span> <span class="identifier">point_tag</span><span class="special">,</span> <span class="identifier">point_type</span> <span class="special">&gt;::</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">&lt;</span><span class="keyword">typename</span> <span class="identifier">P</span><span class="special">&gt;</span>
515    <span class="keyword">struct</span> <span class="identifier">coordinate_type</span><span class="special">&lt;</span><span class="identifier">point_tag</span><span class="special">,</span> <span class="identifier">P</span><span class="special">&gt;</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">&lt;</span><span class="identifier">P</span><span class="special">&gt;::</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">&lt;</span><span class="keyword">typename</span> <span class="identifier">DegreeOrRadian</span><span class="special">&gt;</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">&lt;</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">&gt;</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">&amp;</span> <span class="identifier">g1</span><span class="special">,</span> <span class="identifier">G2</span> <span class="keyword">const</span><span class="special">&amp;</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">&lt;</span>
574            <span class="keyword">typename</span> <span class="identifier">coordinate_system</span><span class="special">&lt;</span><span class="identifier">G1</span><span class="special">&gt;::</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">&lt;</span><span class="identifier">G2</span><span class="special">&gt;::</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">&lt;</span><span class="identifier">G1</span><span class="special">&gt;::</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">&lt;</span><span class="identifier">G2</span><span class="special">&gt;::</span><span class="identifier">type</span><span class="special">,</span>
578            <span class="identifier">dimension</span><span class="special">&lt;</span><span class="identifier">G1</span><span class="special">&gt;::</span><span class="identifier">value</span>
579        <span class="special">&gt;::</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">&lt;</span>
583            <span class="keyword">typename</span> <span class="identifier">tag</span><span class="special">&lt;</span><span class="identifier">G1</span><span class="special">&gt;::</span><span class="identifier">type</span><span class="special">,</span>
584            <span class="keyword">typename</span> <span class="identifier">tag</span><span class="special">&lt;</span><span class="identifier">G2</span><span class="special">&gt;::</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">&gt;::</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">&lt;</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">&gt;</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">&lt;</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">&gt;</span>
600<span class="keyword">struct</span> <span class="identifier">strategy_distance</span><span class="special">&lt;</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">&gt;</span>
601<span class="special">{</span>
602    <span class="keyword">typedef</span> <span class="identifier">pythagoras</span><span class="special">&lt;</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">&gt;</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">&lt;</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">&gt;</span>
617<span class="keyword">struct</span> <span class="identifier">strategy_distance</span><span class="special">&lt;</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">&gt;</span>
618<span class="special">{</span>
619    <span class="keyword">typedef</span> <span class="identifier">haversine</span><span class="special">&lt;</span><span class="identifier">P1</span><span class="special">,</span> <span class="identifier">P2</span><span class="special">&gt;</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">&lt;</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">&gt;</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">&amp;</span> <span class="identifier">g1</span><span class="special">,</span> <span class="identifier">G2</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">g2</span><span class="special">,</span> <span class="identifier">S</span> <span class="keyword">const</span><span class="special">&amp;</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">&lt;</span>
651            <span class="keyword">typename</span> <span class="identifier">tag</span><span class="special">&lt;</span><span class="identifier">G1</span><span class="special">&gt;::</span><span class="identifier">type</span><span class="special">,</span>
652            <span class="keyword">typename</span> <span class="identifier">tag</span><span class="special">&lt;</span><span class="identifier">G2</span><span class="special">&gt;::</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">&gt;::</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">&lt;</span><span class="identifier">G1</span><span class="special">,</span> <span class="identifier">G2</span><span class="special">&gt;(</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">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span> <span class="special">=</span> <span class="keyword">double</span><span class="special">&gt;</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">&amp;</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">&lt;</span><span class="identifier">T</span><span class="special">&gt;</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">&lt;</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">&gt;</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">&amp;</span> <span class="identifier">G1</span> <span class="special">,</span> <span class="identifier">G2</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">G2</span> <span class="special">,</span> <span class="identifier">S</span> <span class="keyword">const</span><span class="special">&amp;</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">&lt;</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">&gt;</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">&lt;</span><span class="identifier">G1</span><span class="special">&gt;::</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">&lt;</span><span class="identifier">G2</span><span class="special">&gt;::</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">&lt;</span>
793            <span class="keyword">typename</span> <span class="identifier">cs_tag</span><span class="special">&lt;</span><span class="identifier">P1</span><span class="special">&gt;::</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">&lt;</span><span class="identifier">P2</span><span class="special">&gt;::</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">&gt;::</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">&lt;</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">&gt;</span>
805<span class="keyword">inline</span> <span class="keyword">typename</span> <span class="identifier">distance_result</span><span class="special">&lt;</span><span class="identifier">G1</span><span class="special">,</span> <span class="identifier">G2</span><span class="special">&gt;::</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">&amp;</span> <span class="identifier">g1</span><span class="special">,</span> <span class="identifier">G2</span> <span class="keyword">const</span><span class="special">&amp;</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