]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | ||
1e59de90 TL |
9 | // This file was modified by Oracle on 2014-2021. |
10 | // Modifications copyright (c) 2014-2021, Oracle and/or its affiliates. | |
7c673cae | 11 | // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle |
92f5a8d4 | 12 | // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle |
7c673cae FG |
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 | ||
1e59de90 TL |
26 | #include <boost/geometry/algorithms/detail/throw_on_empty_input.hpp> |
27 | #include <boost/geometry/algorithms/dispatch/distance.hpp> | |
28 | ||
7c673cae | 29 | #include <boost/geometry/core/point_type.hpp> |
1e59de90 | 30 | #include <boost/geometry/core/visit.hpp> |
7c673cae | 31 | |
1e59de90 | 32 | #include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility |
7c673cae FG |
33 | #include <boost/geometry/geometries/concepts/check.hpp> |
34 | ||
1e59de90 | 35 | // TODO: move these to algorithms |
7c673cae FG |
36 | #include <boost/geometry/strategies/default_distance_result.hpp> |
37 | #include <boost/geometry/strategies/distance_result.hpp> | |
38 | ||
1e59de90 TL |
39 | #include <boost/geometry/strategies/default_strategy.hpp> |
40 | #include <boost/geometry/strategies/detail.hpp> | |
41 | #include <boost/geometry/strategies/distance/services.hpp> | |
7c673cae FG |
42 | |
43 | ||
44 | namespace boost { namespace geometry | |
45 | { | |
46 | ||
47 | ||
48 | #ifndef DOXYGEN_NO_DISPATCH | |
49 | namespace dispatch | |
50 | { | |
51 | ||
52 | ||
53 | // If reversal is needed, perform it | |
54 | template | |
55 | < | |
56 | typename Geometry1, typename Geometry2, typename Strategy, | |
57 | typename Tag1, typename Tag2, typename StrategyTag | |
58 | > | |
59 | struct distance | |
60 | < | |
61 | Geometry1, Geometry2, Strategy, | |
62 | Tag1, Tag2, StrategyTag, | |
63 | true | |
64 | > | |
65 | : distance<Geometry2, Geometry1, Strategy, Tag2, Tag1, StrategyTag, false> | |
66 | { | |
1e59de90 TL |
67 | static inline auto apply(Geometry1 const& g1, Geometry2 const& g2, |
68 | Strategy const& strategy) | |
7c673cae FG |
69 | { |
70 | return distance | |
71 | < | |
72 | Geometry2, Geometry1, Strategy, | |
73 | Tag2, Tag1, StrategyTag, | |
74 | false | |
75 | >::apply(g2, g1, strategy); | |
76 | } | |
77 | }; | |
78 | ||
79 | ||
80 | } // namespace dispatch | |
81 | #endif // DOXYGEN_NO_DISPATCH | |
82 | ||
83 | ||
84 | namespace resolve_strategy | |
85 | { | |
86 | ||
1e59de90 TL |
87 | template |
88 | < | |
89 | typename Strategy, | |
90 | bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value | |
91 | > | |
7c673cae FG |
92 | struct distance |
93 | { | |
92f5a8d4 | 94 | template <typename Geometry1, typename Geometry2> |
1e59de90 TL |
95 | static inline auto apply(Geometry1 const& geometry1, |
96 | Geometry2 const& geometry2, | |
97 | Strategy const& strategy) | |
7c673cae FG |
98 | { |
99 | return dispatch::distance | |
100 | < | |
101 | Geometry1, Geometry2, Strategy | |
102 | >::apply(geometry1, geometry2, strategy); | |
103 | } | |
92f5a8d4 | 104 | }; |
7c673cae | 105 | |
1e59de90 TL |
106 | template <typename Strategy> |
107 | struct is_strategy_converter_specialized | |
108 | { | |
109 | typedef strategies::distance::services::strategy_converter<Strategy> converter; | |
110 | static const bool value = ! std::is_same | |
111 | < | |
112 | decltype(converter::get(std::declval<Strategy>())), | |
113 | strategies::detail::not_implemented | |
114 | >::value; | |
115 | }; | |
116 | ||
117 | template <typename Strategy> | |
118 | struct distance<Strategy, false> | |
119 | { | |
120 | template | |
121 | < | |
122 | typename Geometry1, typename Geometry2, typename S, | |
123 | std::enable_if_t<is_strategy_converter_specialized<S>::value, int> = 0 | |
124 | > | |
125 | static inline auto apply(Geometry1 const& geometry1, | |
126 | Geometry2 const& geometry2, | |
127 | S const& strategy) | |
128 | { | |
129 | typedef strategies::distance::services::strategy_converter<Strategy> converter; | |
130 | typedef decltype(converter::get(strategy)) strategy_type; | |
131 | ||
132 | return dispatch::distance | |
133 | < | |
134 | Geometry1, Geometry2, strategy_type | |
135 | >::apply(geometry1, geometry2, converter::get(strategy)); | |
136 | } | |
137 | ||
138 | template | |
139 | < | |
140 | typename Geometry1, typename Geometry2, typename S, | |
141 | std::enable_if_t<! is_strategy_converter_specialized<S>::value, int> = 0 | |
142 | > | |
143 | static inline auto apply(Geometry1 const& geometry1, | |
144 | Geometry2 const& geometry2, | |
145 | S const& strategy) | |
146 | { | |
147 | typedef strategies::distance::services::custom_strategy_converter | |
148 | < | |
149 | Geometry1, Geometry2, Strategy | |
150 | > converter; | |
151 | typedef decltype(converter::get(strategy)) strategy_type; | |
152 | ||
153 | return dispatch::distance | |
154 | < | |
155 | Geometry1, Geometry2, strategy_type | |
156 | >::apply(geometry1, geometry2, converter::get(strategy)); | |
157 | } | |
158 | }; | |
159 | ||
92f5a8d4 | 160 | template <> |
1e59de90 | 161 | struct distance<default_strategy, false> |
92f5a8d4 | 162 | { |
7c673cae | 163 | template <typename Geometry1, typename Geometry2> |
1e59de90 TL |
164 | static inline auto apply(Geometry1 const& geometry1, |
165 | Geometry2 const& geometry2, | |
166 | default_strategy) | |
7c673cae | 167 | { |
1e59de90 | 168 | typedef typename strategies::distance::services::default_strategy |
7c673cae FG |
169 | < |
170 | Geometry1, Geometry2 | |
171 | >::type strategy_type; | |
172 | ||
173 | return dispatch::distance | |
174 | < | |
175 | Geometry1, Geometry2, strategy_type | |
176 | >::apply(geometry1, geometry2, strategy_type()); | |
177 | } | |
178 | }; | |
179 | ||
180 | } // namespace resolve_strategy | |
181 | ||
182 | ||
1e59de90 | 183 | namespace resolve_dynamic |
7c673cae FG |
184 | { |
185 | ||
186 | ||
1e59de90 TL |
187 | template |
188 | < | |
189 | typename Geometry1, typename Geometry2, | |
190 | typename Tag1 = typename geometry::tag<Geometry1>::type, | |
191 | typename Tag2 = typename geometry::tag<Geometry2>::type | |
192 | > | |
7c673cae FG |
193 | struct distance |
194 | { | |
195 | template <typename Strategy> | |
1e59de90 TL |
196 | static inline auto apply(Geometry1 const& geometry1, |
197 | Geometry2 const& geometry2, | |
198 | Strategy const& strategy) | |
7c673cae | 199 | { |
92f5a8d4 TL |
200 | return resolve_strategy::distance |
201 | < | |
202 | Strategy | |
203 | >::apply(geometry1, geometry2, strategy); | |
7c673cae FG |
204 | } |
205 | }; | |
206 | ||
207 | ||
1e59de90 TL |
208 | template <typename DynamicGeometry1, typename Geometry2, typename Tag2> |
209 | struct distance<DynamicGeometry1, Geometry2, dynamic_geometry_tag, Tag2> | |
7c673cae FG |
210 | { |
211 | template <typename Strategy> | |
1e59de90 TL |
212 | static inline auto apply(DynamicGeometry1 const& geometry1, |
213 | Geometry2 const& geometry2, | |
214 | Strategy const& strategy) | |
7c673cae | 215 | { |
1e59de90 TL |
216 | using result_t = typename geometry::distance_result<DynamicGeometry1, Geometry2, Strategy>::type; |
217 | result_t result = 0; | |
218 | traits::visit<DynamicGeometry1>::apply([&](auto const& g1) | |
7c673cae | 219 | { |
1e59de90 TL |
220 | result = resolve_strategy::distance |
221 | < | |
222 | Strategy | |
223 | >::apply(g1, geometry2, strategy); | |
224 | }, geometry1); | |
225 | return result; | |
7c673cae FG |
226 | } |
227 | }; | |
228 | ||
229 | ||
1e59de90 TL |
230 | template <typename Geometry1, typename DynamicGeometry2, typename Tag1> |
231 | struct distance<Geometry1, DynamicGeometry2, Tag1, dynamic_geometry_tag> | |
7c673cae FG |
232 | { |
233 | template <typename Strategy> | |
1e59de90 TL |
234 | static inline auto apply(Geometry1 const& geometry1, |
235 | DynamicGeometry2 const& geometry2, | |
236 | Strategy const& strategy) | |
7c673cae | 237 | { |
1e59de90 TL |
238 | using result_t = typename geometry::distance_result<Geometry1, DynamicGeometry2, Strategy>::type; |
239 | result_t result = 0; | |
240 | traits::visit<DynamicGeometry2>::apply([&](auto const& g2) | |
7c673cae | 241 | { |
1e59de90 TL |
242 | result = resolve_strategy::distance |
243 | < | |
244 | Strategy | |
245 | >::apply(geometry1, g2, strategy); | |
246 | }, geometry2); | |
247 | return result; | |
7c673cae FG |
248 | } |
249 | }; | |
250 | ||
251 | ||
1e59de90 TL |
252 | template <typename DynamicGeometry1, typename DynamicGeometry2> |
253 | struct distance<DynamicGeometry1, DynamicGeometry2, dynamic_geometry_tag, dynamic_geometry_tag> | |
7c673cae FG |
254 | { |
255 | template <typename Strategy> | |
1e59de90 TL |
256 | static inline auto apply(DynamicGeometry1 const& geometry1, |
257 | DynamicGeometry2 const& geometry2, | |
258 | Strategy const& strategy) | |
7c673cae | 259 | { |
1e59de90 TL |
260 | using result_t = typename geometry::distance_result<DynamicGeometry1, DynamicGeometry2, Strategy>::type; |
261 | result_t result = 0; | |
262 | traits::visit<DynamicGeometry1, DynamicGeometry2>::apply([&](auto const& g1, auto const& g2) | |
7c673cae | 263 | { |
1e59de90 TL |
264 | result = resolve_strategy::distance |
265 | < | |
266 | Strategy | |
267 | >::apply(g1, g2, strategy); | |
268 | }, geometry1, geometry2); | |
269 | return result; | |
7c673cae FG |
270 | } |
271 | }; | |
272 | ||
1e59de90 | 273 | } // namespace resolve_dynamic |
7c673cae FG |
274 | |
275 | ||
276 | /*! | |
92f5a8d4 | 277 | \brief Calculate the distance between two geometries \brief_strategy |
7c673cae FG |
278 | \ingroup distance |
279 | \details | |
92f5a8d4 | 280 | \details The free function distance calculates the distance between two geometries \brief_strategy. \details_strategy_reasons |
7c673cae FG |
281 | |
282 | \tparam Geometry1 \tparam_geometry | |
283 | \tparam Geometry2 \tparam_geometry | |
284 | \tparam Strategy \tparam_strategy{Distance} | |
285 | \param geometry1 \param_geometry | |
286 | \param geometry2 \param_geometry | |
287 | \param strategy \param_strategy{distance} | |
288 | \return \return_calc{distance} | |
289 | \note The strategy can be a point-point strategy. In case of distance point-line/point-polygon | |
290 | it may also be a point-segment strategy. | |
291 | ||
292 | \qbk{distinguish,with strategy} | |
293 | ||
294 | \qbk{ | |
295 | [heading Available Strategies] | |
296 | \* [link geometry.reference.strategies.strategy_distance_pythagoras Pythagoras (cartesian)] | |
297 | \* [link geometry.reference.strategies.strategy_distance_haversine Haversine (spherical)] | |
298 | \* [link geometry.reference.strategies.strategy_distance_cross_track Cross track (spherical\, point-to-segment)] | |
299 | \* [link geometry.reference.strategies.strategy_distance_projected_point Projected point (cartesian\, point-to-segment)] | |
300 | \* more (currently extensions): Vincenty\, Andoyer (geographic) | |
301 | } | |
302 | */ | |
303 | ||
304 | /* | |
305 | Note, in case of a Compilation Error: | |
306 | if you get: | |
307 | - "Failed to specialize function template ..." | |
308 | - "error: no matching function for call to ..." | |
309 | for distance, it is probably so that there is no specialization | |
310 | for return_type<...> for your strategy. | |
311 | */ | |
312 | template <typename Geometry1, typename Geometry2, typename Strategy> | |
1e59de90 TL |
313 | inline auto distance(Geometry1 const& geometry1, |
314 | Geometry2 const& geometry2, | |
315 | Strategy const& strategy) | |
7c673cae FG |
316 | { |
317 | concepts::check<Geometry1 const>(); | |
318 | concepts::check<Geometry2 const>(); | |
319 | ||
320 | detail::throw_on_empty_input(geometry1); | |
321 | detail::throw_on_empty_input(geometry2); | |
322 | ||
1e59de90 | 323 | return resolve_dynamic::distance |
7c673cae FG |
324 | < |
325 | Geometry1, | |
326 | Geometry2 | |
327 | >::apply(geometry1, geometry2, strategy); | |
328 | } | |
329 | ||
330 | ||
331 | /*! | |
92f5a8d4 | 332 | \brief Calculate the distance between two geometries. |
7c673cae | 333 | \ingroup distance |
92f5a8d4 TL |
334 | \details The free function distance calculates the distance between two geometries. \details_default_strategy |
335 | ||
7c673cae FG |
336 | \tparam Geometry1 \tparam_geometry |
337 | \tparam Geometry2 \tparam_geometry | |
338 | \param geometry1 \param_geometry | |
339 | \param geometry2 \param_geometry | |
340 | \return \return_calc{distance} | |
341 | ||
342 | \qbk{[include reference/algorithms/distance.qbk]} | |
343 | */ | |
344 | template <typename Geometry1, typename Geometry2> | |
1e59de90 TL |
345 | inline auto distance(Geometry1 const& geometry1, |
346 | Geometry2 const& geometry2) | |
7c673cae | 347 | { |
7c673cae FG |
348 | return geometry::distance(geometry1, geometry2, default_strategy()); |
349 | } | |
350 | ||
351 | }} // namespace boost::geometry | |
352 | ||
353 | #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_INTERFACE_HPP |