interface.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
  3. // Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
  4. // Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
  5. // Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
  6. // Copyright (c) 2014 Samuel Debionne, Grenoble, France.
  7. // This file was modified by Oracle on 2014-2021.
  8. // Modifications copyright (c) 2014-2021, Oracle and/or its affiliates.
  9. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
  10. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  11. // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
  12. // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
  13. // Use, modification and distribution is subject to the Boost Software License,
  14. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  15. // http://www.boost.org/LICENSE_1_0.txt)
  16. #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_INTERFACE_HPP
  17. #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_INTERFACE_HPP
  18. #include <boost/concept_check.hpp>
  19. #include <boost/geometry/algorithms/detail/throw_on_empty_input.hpp>
  20. #include <boost/geometry/algorithms/dispatch/distance.hpp>
  21. #include <boost/geometry/core/point_type.hpp>
  22. #include <boost/geometry/core/visit.hpp>
  23. #include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
  24. #include <boost/geometry/geometries/concepts/check.hpp>
  25. // TODO: move these to algorithms
  26. #include <boost/geometry/strategies/default_distance_result.hpp>
  27. #include <boost/geometry/strategies/distance_result.hpp>
  28. #include <boost/geometry/strategies/default_strategy.hpp>
  29. #include <boost/geometry/strategies/detail.hpp>
  30. #include <boost/geometry/strategies/distance/services.hpp>
  31. namespace boost { namespace geometry
  32. {
  33. #ifndef DOXYGEN_NO_DISPATCH
  34. namespace dispatch
  35. {
  36. // If reversal is needed, perform it
  37. template
  38. <
  39. typename Geometry1, typename Geometry2, typename Strategy,
  40. typename Tag1, typename Tag2, typename StrategyTag
  41. >
  42. struct distance
  43. <
  44. Geometry1, Geometry2, Strategy,
  45. Tag1, Tag2, StrategyTag,
  46. true
  47. >
  48. : distance<Geometry2, Geometry1, Strategy, Tag2, Tag1, StrategyTag, false>
  49. {
  50. static inline auto apply(Geometry1 const& g1, Geometry2 const& g2,
  51. Strategy const& strategy)
  52. {
  53. return distance
  54. <
  55. Geometry2, Geometry1, Strategy,
  56. Tag2, Tag1, StrategyTag,
  57. false
  58. >::apply(g2, g1, strategy);
  59. }
  60. };
  61. } // namespace dispatch
  62. #endif // DOXYGEN_NO_DISPATCH
  63. namespace resolve_strategy
  64. {
  65. template
  66. <
  67. typename Strategy,
  68. bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
  69. >
  70. struct distance
  71. {
  72. template <typename Geometry1, typename Geometry2>
  73. static inline auto apply(Geometry1 const& geometry1,
  74. Geometry2 const& geometry2,
  75. Strategy const& strategy)
  76. {
  77. return dispatch::distance
  78. <
  79. Geometry1, Geometry2, Strategy
  80. >::apply(geometry1, geometry2, strategy);
  81. }
  82. };
  83. template <typename Strategy>
  84. struct is_strategy_converter_specialized
  85. {
  86. typedef strategies::distance::services::strategy_converter<Strategy> converter;
  87. static const bool value = ! std::is_same
  88. <
  89. decltype(converter::get(std::declval<Strategy>())),
  90. strategies::detail::not_implemented
  91. >::value;
  92. };
  93. template <typename Strategy>
  94. struct distance<Strategy, false>
  95. {
  96. template
  97. <
  98. typename Geometry1, typename Geometry2, typename S,
  99. std::enable_if_t<is_strategy_converter_specialized<S>::value, int> = 0
  100. >
  101. static inline auto apply(Geometry1 const& geometry1,
  102. Geometry2 const& geometry2,
  103. S const& strategy)
  104. {
  105. typedef strategies::distance::services::strategy_converter<Strategy> converter;
  106. typedef decltype(converter::get(strategy)) strategy_type;
  107. return dispatch::distance
  108. <
  109. Geometry1, Geometry2, strategy_type
  110. >::apply(geometry1, geometry2, converter::get(strategy));
  111. }
  112. template
  113. <
  114. typename Geometry1, typename Geometry2, typename S,
  115. std::enable_if_t<! is_strategy_converter_specialized<S>::value, int> = 0
  116. >
  117. static inline auto apply(Geometry1 const& geometry1,
  118. Geometry2 const& geometry2,
  119. S const& strategy)
  120. {
  121. typedef strategies::distance::services::custom_strategy_converter
  122. <
  123. Geometry1, Geometry2, Strategy
  124. > converter;
  125. typedef decltype(converter::get(strategy)) strategy_type;
  126. return dispatch::distance
  127. <
  128. Geometry1, Geometry2, strategy_type
  129. >::apply(geometry1, geometry2, converter::get(strategy));
  130. }
  131. };
  132. template <>
  133. struct distance<default_strategy, false>
  134. {
  135. template <typename Geometry1, typename Geometry2>
  136. static inline auto apply(Geometry1 const& geometry1,
  137. Geometry2 const& geometry2,
  138. default_strategy)
  139. {
  140. typedef typename strategies::distance::services::default_strategy
  141. <
  142. Geometry1, Geometry2
  143. >::type strategy_type;
  144. return dispatch::distance
  145. <
  146. Geometry1, Geometry2, strategy_type
  147. >::apply(geometry1, geometry2, strategy_type());
  148. }
  149. };
  150. } // namespace resolve_strategy
  151. namespace resolve_dynamic
  152. {
  153. template
  154. <
  155. typename Geometry1, typename Geometry2,
  156. typename Tag1 = typename geometry::tag<Geometry1>::type,
  157. typename Tag2 = typename geometry::tag<Geometry2>::type
  158. >
  159. struct distance
  160. {
  161. template <typename Strategy>
  162. static inline auto apply(Geometry1 const& geometry1,
  163. Geometry2 const& geometry2,
  164. Strategy const& strategy)
  165. {
  166. return resolve_strategy::distance
  167. <
  168. Strategy
  169. >::apply(geometry1, geometry2, strategy);
  170. }
  171. };
  172. template <typename DynamicGeometry1, typename Geometry2, typename Tag2>
  173. struct distance<DynamicGeometry1, Geometry2, dynamic_geometry_tag, Tag2>
  174. {
  175. template <typename Strategy>
  176. static inline auto apply(DynamicGeometry1 const& geometry1,
  177. Geometry2 const& geometry2,
  178. Strategy const& strategy)
  179. {
  180. using result_t = typename geometry::distance_result<DynamicGeometry1, Geometry2, Strategy>::type;
  181. result_t result = 0;
  182. traits::visit<DynamicGeometry1>::apply([&](auto const& g1)
  183. {
  184. result = resolve_strategy::distance
  185. <
  186. Strategy
  187. >::apply(g1, geometry2, strategy);
  188. }, geometry1);
  189. return result;
  190. }
  191. };
  192. template <typename Geometry1, typename DynamicGeometry2, typename Tag1>
  193. struct distance<Geometry1, DynamicGeometry2, Tag1, dynamic_geometry_tag>
  194. {
  195. template <typename Strategy>
  196. static inline auto apply(Geometry1 const& geometry1,
  197. DynamicGeometry2 const& geometry2,
  198. Strategy const& strategy)
  199. {
  200. using result_t = typename geometry::distance_result<Geometry1, DynamicGeometry2, Strategy>::type;
  201. result_t result = 0;
  202. traits::visit<DynamicGeometry2>::apply([&](auto const& g2)
  203. {
  204. result = resolve_strategy::distance
  205. <
  206. Strategy
  207. >::apply(geometry1, g2, strategy);
  208. }, geometry2);
  209. return result;
  210. }
  211. };
  212. template <typename DynamicGeometry1, typename DynamicGeometry2>
  213. struct distance<DynamicGeometry1, DynamicGeometry2, dynamic_geometry_tag, dynamic_geometry_tag>
  214. {
  215. template <typename Strategy>
  216. static inline auto apply(DynamicGeometry1 const& geometry1,
  217. DynamicGeometry2 const& geometry2,
  218. Strategy const& strategy)
  219. {
  220. using result_t = typename geometry::distance_result<DynamicGeometry1, DynamicGeometry2, Strategy>::type;
  221. result_t result = 0;
  222. traits::visit<DynamicGeometry1, DynamicGeometry2>::apply([&](auto const& g1, auto const& g2)
  223. {
  224. result = resolve_strategy::distance
  225. <
  226. Strategy
  227. >::apply(g1, g2, strategy);
  228. }, geometry1, geometry2);
  229. return result;
  230. }
  231. };
  232. } // namespace resolve_dynamic
  233. /*!
  234. \brief Calculate the distance between two geometries \brief_strategy
  235. \ingroup distance
  236. \details
  237. \details The free function distance calculates the distance between two geometries \brief_strategy. \details_strategy_reasons
  238. \tparam Geometry1 \tparam_geometry
  239. \tparam Geometry2 \tparam_geometry
  240. \tparam Strategy \tparam_strategy{Distance}
  241. \param geometry1 \param_geometry
  242. \param geometry2 \param_geometry
  243. \param strategy \param_strategy{distance}
  244. \return \return_calc{distance}
  245. \note The strategy can be a point-point strategy. In case of distance point-line/point-polygon
  246. it may also be a point-segment strategy.
  247. \qbk{distinguish,with strategy}
  248. \qbk{
  249. [heading Available Strategies]
  250. \* [link geometry.reference.strategies.strategy_distance_pythagoras Pythagoras (cartesian)]
  251. \* [link geometry.reference.strategies.strategy_distance_haversine Haversine (spherical)]
  252. \* [link geometry.reference.strategies.strategy_distance_cross_track Cross track (spherical\, point-to-segment)]
  253. \* [link geometry.reference.strategies.strategy_distance_projected_point Projected point (cartesian\, point-to-segment)]
  254. \* more (currently extensions): Vincenty\, Andoyer (geographic)
  255. }
  256. */
  257. /*
  258. Note, in case of a Compilation Error:
  259. if you get:
  260. - "Failed to specialize function template ..."
  261. - "error: no matching function for call to ..."
  262. for distance, it is probably so that there is no specialization
  263. for return_type<...> for your strategy.
  264. */
  265. template <typename Geometry1, typename Geometry2, typename Strategy>
  266. inline auto distance(Geometry1 const& geometry1,
  267. Geometry2 const& geometry2,
  268. Strategy const& strategy)
  269. {
  270. concepts::check<Geometry1 const>();
  271. concepts::check<Geometry2 const>();
  272. detail::throw_on_empty_input(geometry1);
  273. detail::throw_on_empty_input(geometry2);
  274. return resolve_dynamic::distance
  275. <
  276. Geometry1,
  277. Geometry2
  278. >::apply(geometry1, geometry2, strategy);
  279. }
  280. /*!
  281. \brief Calculate the distance between two geometries.
  282. \ingroup distance
  283. \details The free function distance calculates the distance between two geometries. \details_default_strategy
  284. \tparam Geometry1 \tparam_geometry
  285. \tparam Geometry2 \tparam_geometry
  286. \param geometry1 \param_geometry
  287. \param geometry2 \param_geometry
  288. \return \return_calc{distance}
  289. \qbk{[include reference/algorithms/distance.qbk]}
  290. */
  291. template <typename Geometry1, typename Geometry2>
  292. inline auto distance(Geometry1 const& geometry1,
  293. Geometry2 const& geometry2)
  294. {
  295. return geometry::distance(geometry1, geometry2, default_strategy());
  296. }
  297. }} // namespace boost::geometry
  298. #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_INTERFACE_HPP