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 76 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 struct distance 99 { 100 template <typename Geometry1, typename Geometry2, typename Strategy> 101 static inline typename distance_result<Geometry1, Geometry2, Strategy>::type 102 apply(Geometry1 const& geometry1, 103 Geometry2 const& geometry2, 104 Strategy const& strategy) 105 { 106 return dispatch::distance 107 < 108 Geometry1, Geometry2, Strategy 109 >::apply(geometry1, geometry2, strategy); 110 } 111 112 template <typename Geometry1, typename Geometry2> 113 static inline 114 typename distance_result<Geometry1, Geometry2, default_strategy>::type 115 apply(Geometry1 const& geometry1, 116 Geometry2 const& geometry2, 117 default_strategy) 118 { 119 typedef typename detail::distance::default_strategy 120 < 121 Geometry1, Geometry2 122 >::type strategy_type; 123 124 return dispatch::distance 125 < 126 Geometry1, Geometry2, strategy_type 127 >::apply(geometry1, geometry2, strategy_type()); 128 } 129 }; 130 131 } // namespace resolve_strategy 132 133 134 namespace resolve_variant 135 { 136 137 138 template <typename Geometry1, typename Geometry2> 139 struct distance 140 { 141 template <typename Strategy> 142 static inline typename distance_result<Geometry1, Geometry2, Strategy>::type 143 apply(Geometry1 const& geometry1, 144 Geometry2 const& geometry2, 145 Strategy const& strategy) 146 { 147 return 148 resolve_strategy::distance::apply(geometry1, geometry2, strategy); 149 } 150 }; 151 152 153 template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2> 154 struct distance<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2> 155 { 156 template <typename Strategy> 157 struct visitor: static_visitor 158 < 159 typename distance_result 160 < 161 variant<BOOST_VARIANT_ENUM_PARAMS(T)>, 162 Geometry2, 163 Strategy 164 >::type 165 > 166 { 167 Geometry2 const& m_geometry2; 168 Strategy const& m_strategy; 169 170 visitor(Geometry2 const& geometry2, 171 Strategy const& strategy) 172 : m_geometry2(geometry2), 173 m_strategy(strategy) 174 {} 175 176 template <typename Geometry1> 177 typename distance_result<Geometry1, Geometry2, Strategy>::type 178 operator()(Geometry1 const& geometry1) const 179 { 180 return distance 181 < 182 Geometry1, 183 Geometry2 184 >::template apply 185 < 186 Strategy 187 >(geometry1, m_geometry2, m_strategy); 188 } 189 }; 190 191 template <typename Strategy> 192 static inline typename distance_result 193 < 194 variant<BOOST_VARIANT_ENUM_PARAMS(T)>, 195 Geometry2, 196 Strategy 197 >::type 198 apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1, 199 Geometry2 const& geometry2, 200 Strategy const& strategy) 201 { 202 return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1); 203 } 204 }; 205 206 207 template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)> 208 struct distance<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> > 209 { 210 template <typename Strategy> 211 struct visitor: static_visitor 212 < 213 typename distance_result 214 < 215 Geometry1, 216 variant<BOOST_VARIANT_ENUM_PARAMS(T)>, 217 Strategy 218 >::type 219 > 220 { 221 Geometry1 const& m_geometry1; 222 Strategy const& m_strategy; 223 224 visitor(Geometry1 const& geometry1, 225 Strategy const& strategy) 226 : m_geometry1(geometry1), 227 m_strategy(strategy) 228 {} 229 230 template <typename Geometry2> 231 typename distance_result<Geometry1, Geometry2, Strategy>::type 232 operator()(Geometry2 const& geometry2) const 233 { 234 return distance 235 < 236 Geometry1, 237 Geometry2 238 >::template apply 239 < 240 Strategy 241 >(m_geometry1, geometry2, m_strategy); 242 } 243 }; 244 245 template <typename Strategy> 246 static inline typename distance_result 247 < 248 Geometry1, 249 variant<BOOST_VARIANT_ENUM_PARAMS(T)>, 250 Strategy 251 >::type 252 apply( 253 Geometry1 const& geometry1, 254 const variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry2, 255 Strategy const& strategy) 256 { 257 return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2); 258 } 259 }; 260 261 262 template 263 < 264 BOOST_VARIANT_ENUM_PARAMS(typename T1), 265 BOOST_VARIANT_ENUM_PARAMS(typename T2) 266 > 267 struct distance 268 < 269 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, 270 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> 271 > 272 { 273 template <typename Strategy> 274 struct visitor: static_visitor 275 < 276 typename distance_result 277 < 278 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, 279 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>, 280 Strategy 281 >::type 282 > 283 { 284 Strategy const& m_strategy; 285 286 visitor(Strategy const& strategy) 287 : m_strategy(strategy) 288 {} 289 290 template <typename Geometry1, typename Geometry2> 291 typename distance_result<Geometry1, Geometry2, Strategy>::type 292 operator()(Geometry1 const& geometry1, Geometry2 const& geometry2) const 293 { 294 return distance 295 < 296 Geometry1, 297 Geometry2 298 >::template apply 299 < 300 Strategy 301 >(geometry1, geometry2, m_strategy); 302 } 303 }; 304 305 template <typename Strategy> 306 static inline typename distance_result 307 < 308 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, 309 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>, 310 Strategy 311 >::type 312 apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1, 313 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2, 314 Strategy const& strategy) 315 { 316 return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2); 317 } 318 }; 319 320 } // namespace resolve_variant 321 322 323 /*! 324 \brief Calculate the distance between two geometries \brief_strategy 325 \ingroup distance 326 \details 327 \details The free function distance calculates the distance between two geometries \brief_strategy. \details_strategy_reasons 328 329 \tparam Geometry1 \tparam_geometry 330 \tparam Geometry2 \tparam_geometry 331 \tparam Strategy \tparam_strategy{Distance} 332 \param geometry1 \param_geometry 333 \param geometry2 \param_geometry 334 \param strategy \param_strategy{distance} 335 \return \return_calc{distance} 336 \note The strategy can be a point-point strategy. In case of distance point-line/point-polygon 337 it may also be a point-segment strategy. 338 339 \qbk{distinguish,with strategy} 340 341 \qbk{ 342 [heading Available Strategies] 343 \* [link geometry.reference.strategies.strategy_distance_pythagoras Pythagoras (cartesian)] 344 \* [link geometry.reference.strategies.strategy_distance_haversine Haversine (spherical)] 345 \* [link geometry.reference.strategies.strategy_distance_cross_track Cross track (spherical\, point-to-segment)] 346 \* [link geometry.reference.strategies.strategy_distance_projected_point Projected point (cartesian\, point-to-segment)] 347 \* more (currently extensions): Vincenty\, Andoyer (geographic) 348 } 349 */ 350 351 /* 352 Note, in case of a Compilation Error: 353 if you get: 354 - "Failed to specialize function template ..." 355 - "error: no matching function for call to ..." 356 for distance, it is probably so that there is no specialization 357 for return_type<...> for your strategy. 358 */ 359 template <typename Geometry1, typename Geometry2, typename Strategy> 360 inline typename distance_result<Geometry1, Geometry2, Strategy>::type 361 distance(Geometry1 const& geometry1, 362 Geometry2 const& geometry2, 363 Strategy const& strategy) 364 { 365 concepts::check<Geometry1 const>(); 366 concepts::check<Geometry2 const>(); 367 368 detail::throw_on_empty_input(geometry1); 369 detail::throw_on_empty_input(geometry2); 370 371 return resolve_variant::distance 372 < 373 Geometry1, 374 Geometry2 375 >::apply(geometry1, geometry2, strategy); 376 } 377 378 379 /*! 380 \brief Calculate the distance between two geometries. 381 \ingroup distance 382 \details The free function distance calculates the distance between two geometries. \details_default_strategy 383 384 \tparam Geometry1 \tparam_geometry 385 \tparam Geometry2 \tparam_geometry 386 \param geometry1 \param_geometry 387 \param geometry2 \param_geometry 388 \return \return_calc{distance} 389 390 \qbk{[include reference/algorithms/distance.qbk]} 391 */ 392 template <typename Geometry1, typename Geometry2> 393 inline typename default_distance_result<Geometry1, Geometry2>::type 394 distance(Geometry1 const& geometry1, 395 Geometry2 const& geometry2) 396 { 397 concepts::check<Geometry1 const>(); 398 concepts::check<Geometry2 const>(); 399 400 return geometry::distance(geometry1, geometry2, default_strategy()); 401 } 402 403 }} // namespace boost::geometry 404 405 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_INTERFACE_HPP 406