• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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