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