1// Boost.Geometry (aka GGL, Generic Geometry Library)
2
3// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
4// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
5// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
6// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
7// Copyright (c) 2014 Samuel Debionne, Grenoble, France.
8
9// This file was modified by Oracle on 2014.
10// Modifications copyright (c) 2014, Oracle and/or its affiliates.
11
12// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
13
14// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
15// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
16
17// Use, modification and distribution is subject to the Boost Software License,
18// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
19// http://www.boost.org/LICENSE_1_0.txt)
20
21#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_INTERFACE_HPP
22#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_INTERFACE_HPP
23
24#include <boost/concept_check.hpp>
25
26#include <boost/mpl/always.hpp>
27#include <boost/mpl/bool.hpp>
28#include <boost/mpl/vector.hpp>
29
30#include <boost/geometry/core/point_type.hpp>
31
32#include <boost/geometry/geometries/concepts/check.hpp>
33
34#include <boost/geometry/strategies/default_strategy.hpp>
35#include <boost/geometry/strategies/distance.hpp>
36#include <boost/geometry/strategies/default_distance_result.hpp>
37#include <boost/geometry/strategies/distance_result.hpp>
38
39#include <boost/geometry/algorithms/detail/throw_on_empty_input.hpp>
40#include <boost/geometry/algorithms/detail/distance/default_strategies.hpp>
41
42#include <boost/geometry/algorithms/dispatch/distance.hpp>
43
44
45namespace boost { namespace geometry
46{
47
48
49#ifndef DOXYGEN_NO_DISPATCH
50namespace dispatch
51{
52
53
54// If reversal is needed, perform it
55template
56<
57 typename Geometry1, typename Geometry2, typename Strategy,
58 typename Tag1, typename Tag2, typename StrategyTag
59>
60struct distance
61<
62 Geometry1, Geometry2, Strategy,
63 Tag1, Tag2, StrategyTag,
64 true
65>
66 : distance<Geometry2, Geometry1, Strategy, Tag2, Tag1, StrategyTag, false>
67{
68 typedef typename strategy::distance::services::return_type
69 <
70 Strategy,
71 typename point_type<Geometry2>::type,
72 typename point_type<Geometry1>::type
73 >::type return_type;
74
75 static inline return_type apply(
76 Geometry1 const& g1,
77 Geometry2 const& g2,
78 Strategy const& strategy)
79 {
80 return distance
81 <
82 Geometry2, Geometry1, Strategy,
83 Tag2, Tag1, StrategyTag,
84 false
85 >::apply(g2, g1, strategy);
86 }
87};
88
89
90} // namespace dispatch
91#endif // DOXYGEN_NO_DISPATCH
92
93
94namespace resolve_strategy
95{
96
97struct distance
98{
99 template <typename Geometry1, typename Geometry2, typename Strategy>
100 static inline typename distance_result<Geometry1, Geometry2, Strategy>::type
101 apply(Geometry1 const& geometry1,
102 Geometry2 const& geometry2,
103 Strategy const& strategy)
104 {
105 return dispatch::distance
106 <
107 Geometry1, Geometry2, Strategy
108 >::apply(geometry1, geometry2, strategy);
109 }
110
111 template <typename Geometry1, typename Geometry2>
112 static inline
113 typename distance_result<Geometry1, Geometry2, default_strategy>::type
114 apply(Geometry1 const& geometry1,
115 Geometry2 const& geometry2,
116 default_strategy)
117 {
118 typedef typename detail::distance::default_strategy
119 <
120 Geometry1, Geometry2
121 >::type strategy_type;
122
123 return dispatch::distance
124 <
125 Geometry1, Geometry2, strategy_type
126 >::apply(geometry1, geometry2, strategy_type());
127 }
128};
129
130} // namespace resolve_strategy
131
132
133namespace resolve_variant
134{
135
136
137template <typename Geometry1, typename Geometry2>
138struct distance
139{
140 template <typename Strategy>
141 static inline typename distance_result<Geometry1, Geometry2, Strategy>::type
142 apply(Geometry1 const& geometry1,
143 Geometry2 const& geometry2,
144 Strategy const& strategy)
145 {
146 return
147 resolve_strategy::distance::apply(geometry1, geometry2, strategy);
148 }
149};
150
151
152template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
153struct distance<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
154{
155 template <typename Strategy>
156 struct visitor: static_visitor
157 <
158 typename distance_result
159 <
160 variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
161 Geometry2,
162 Strategy
163 >::type
164 >
165 {
166 Geometry2 const& m_geometry2;
167 Strategy const& m_strategy;
168
169 visitor(Geometry2 const& geometry2,
170 Strategy const& strategy)
171 : m_geometry2(geometry2),
172 m_strategy(strategy)
173 {}
174
175 template <typename Geometry1>
176 typename distance_result<Geometry1, Geometry2, Strategy>::type
177 operator()(Geometry1 const& geometry1) const
178 {
179 return distance
180 <
181 Geometry1,
182 Geometry2
183 >::template apply
184 <
185 Strategy
186 >(geometry1, m_geometry2, m_strategy);
187 }
188 };
189
190 template <typename Strategy>
191 static inline typename distance_result
192 <
193 variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
194 Geometry2,
195 Strategy
196 >::type
197 apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
198 Geometry2 const& geometry2,
199 Strategy const& strategy)
200 {
201 return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
202 }
203};
204
205
206template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
207struct distance<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
208{
209 template <typename Strategy>
210 struct visitor: static_visitor
211 <
212 typename distance_result
213 <
214 Geometry1,
215 variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
216 Strategy
217 >::type
218 >
219 {
220 Geometry1 const& m_geometry1;
221 Strategy const& m_strategy;
222
223 visitor(Geometry1 const& geometry1,
224 Strategy const& strategy)
225 : m_geometry1(geometry1),
226 m_strategy(strategy)
227 {}
228
229 template <typename Geometry2>
230 typename distance_result<Geometry1, Geometry2, Strategy>::type
231 operator()(Geometry2 const& geometry2) const
232 {
233 return distance
234 <
235 Geometry1,
236 Geometry2
237 >::template apply
238 <
239 Strategy
240 >(m_geometry1, geometry2, m_strategy);
241 }
242 };
243
244 template <typename Strategy>
245 static inline typename distance_result
246 <
247 Geometry1,
248 variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
249 Strategy
250 >::type
251 apply(
252 Geometry1 const& geometry1,
253 const variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry2,
254 Strategy const& strategy)
255 {
256 return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
257 }
258};
259
260
261template
262<
263 BOOST_VARIANT_ENUM_PARAMS(typename T1),
264 BOOST_VARIANT_ENUM_PARAMS(typename T2)
265>
266struct distance
267 <
268 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
269 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
270 >
271{
272 template <typename Strategy>
273 struct visitor: static_visitor
274 <
275 typename distance_result
276 <
277 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
278 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>,
279 Strategy
280 >::type
281 >
282 {
283 Strategy const& m_strategy;
284
285 visitor(Strategy const& strategy)
286 : m_strategy(strategy)
287 {}
288
289 template <typename Geometry1, typename Geometry2>
290 typename distance_result<Geometry1, Geometry2, Strategy>::type
291 operator()(Geometry1 const& geometry1, Geometry2 const& geometry2) const
292 {
293 return distance
294 <
295 Geometry1,
296 Geometry2
297 >::template apply
298 <
299 Strategy
300 >(geometry1, geometry2, m_strategy);
301 }
302 };
303
304 template <typename Strategy>
305 static inline typename distance_result
306 <
307 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
308 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>,
309 Strategy
310 >::type
311 apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
312 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
313 Strategy const& strategy)
314 {
315 return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
316 }
317};
318
319} // namespace resolve_variant
320
321
322/*!
323\brief \brief_calc2{distance} \brief_strategy
324\ingroup distance
325\details
326\details \details_calc{area}. \brief_strategy. \details_strategy_reasons
327
328\tparam Geometry1 \tparam_geometry
329\tparam Geometry2 \tparam_geometry
330\tparam Strategy \tparam_strategy{Distance}
331\param geometry1 \param_geometry
332\param geometry2 \param_geometry
333\param strategy \param_strategy{distance}
334\return \return_calc{distance}
335\note The strategy can be a point-point strategy. In case of distance point-line/point-polygon
336 it may also be a point-segment strategy.
337
338\qbk{distinguish,with strategy}
339
340\qbk{
341[heading Available Strategies]
342\* [link geometry.reference.strategies.strategy_distance_pythagoras Pythagoras (cartesian)]
343\* [link geometry.reference.strategies.strategy_distance_haversine Haversine (spherical)]
344\* [link geometry.reference.strategies.strategy_distance_cross_track Cross track (spherical\, point-to-segment)]
345\* [link geometry.reference.strategies.strategy_distance_projected_point Projected point (cartesian\, point-to-segment)]
346\* more (currently extensions): Vincenty\, Andoyer (geographic)
347}
348 */
349
350/*
351Note, in case of a Compilation Error:
352if you get:
353 - "Failed to specialize function template ..."
354 - "error: no matching function for call to ..."
355for distance, it is probably so that there is no specialization
356for return_type<...> for your strategy.
357*/
358template <typename Geometry1, typename Geometry2, typename Strategy>
359inline typename distance_result<Geometry1, Geometry2, Strategy>::type
360distance(Geometry1 const& geometry1,
361 Geometry2 const& geometry2,
362 Strategy const& strategy)
363{
364 concept::check<Geometry1 const>();
365 concept::check<Geometry2 const>();
366
367 detail::throw_on_empty_input(geometry1);
368 detail::throw_on_empty_input(geometry2);
369
370 return resolve_variant::distance
371 <
372 Geometry1,
373 Geometry2
374 >::apply(geometry1, geometry2, strategy);
375}
376
377
378/*!
379\brief \brief_calc2{distance}
380\ingroup distance
381\details The default strategy is used, corresponding to the coordinate system of the geometries
382\tparam Geometry1 \tparam_geometry
383\tparam Geometry2 \tparam_geometry
384\param geometry1 \param_geometry
385\param geometry2 \param_geometry
386\return \return_calc{distance}
387
388\qbk{[include reference/algorithms/distance.qbk]}
389 */
390template <typename Geometry1, typename Geometry2>
391inline typename default_distance_result<Geometry1, Geometry2>::type
392distance(Geometry1 const& geometry1,
393 Geometry2 const& geometry2)
394{
395 concept::check<Geometry1 const>();
396 concept::check<Geometry2 const>();
397
398 return geometry::distance(geometry1, geometry2, default_strategy());
399}
400
401}} // namespace boost::geometry
402
403#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_INTERFACE_HPP
404

source code of boost/boost/geometry/algorithms/detail/distance/interface.hpp