interface.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  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, 2018.
  8. // Modifications copyright (c) 2014-2018, 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/mpl/always.hpp>
  20. #include <boost/mpl/bool.hpp>
  21. #include <boost/mpl/vector.hpp>
  22. #include <boost/geometry/core/point_type.hpp>
  23. #include <boost/geometry/geometries/concepts/check.hpp>
  24. #include <boost/geometry/strategies/default_strategy.hpp>
  25. #include <boost/geometry/strategies/distance.hpp>
  26. #include <boost/geometry/strategies/default_distance_result.hpp>
  27. #include <boost/geometry/strategies/distance_result.hpp>
  28. #include <boost/geometry/algorithms/detail/throw_on_empty_input.hpp>
  29. #include <boost/geometry/algorithms/detail/distance/default_strategies.hpp>
  30. #include <boost/geometry/algorithms/dispatch/distance.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. typedef typename strategy::distance::services::return_type
  51. <
  52. Strategy,
  53. typename point_type<Geometry2>::type,
  54. typename point_type<Geometry1>::type
  55. >::type return_type;
  56. static inline return_type apply(
  57. Geometry1 const& g1,
  58. Geometry2 const& g2,
  59. Strategy const& strategy)
  60. {
  61. return distance
  62. <
  63. Geometry2, Geometry1, Strategy,
  64. Tag2, Tag1, StrategyTag,
  65. false
  66. >::apply(g2, g1, strategy);
  67. }
  68. };
  69. } // namespace dispatch
  70. #endif // DOXYGEN_NO_DISPATCH
  71. namespace resolve_strategy
  72. {
  73. template <typename Strategy>
  74. struct distance
  75. {
  76. template <typename Geometry1, typename Geometry2>
  77. static inline typename distance_result<Geometry1, Geometry2, Strategy>::type
  78. apply(Geometry1 const& geometry1,
  79. Geometry2 const& geometry2,
  80. Strategy const& strategy)
  81. {
  82. return dispatch::distance
  83. <
  84. Geometry1, Geometry2, Strategy
  85. >::apply(geometry1, geometry2, strategy);
  86. }
  87. };
  88. template <>
  89. struct distance<default_strategy>
  90. {
  91. template <typename Geometry1, typename Geometry2>
  92. static inline
  93. typename distance_result<Geometry1, Geometry2, default_strategy>::type
  94. apply(Geometry1 const& geometry1,
  95. Geometry2 const& geometry2,
  96. default_strategy)
  97. {
  98. typedef typename detail::distance::default_strategy
  99. <
  100. Geometry1, Geometry2
  101. >::type strategy_type;
  102. return dispatch::distance
  103. <
  104. Geometry1, Geometry2, strategy_type
  105. >::apply(geometry1, geometry2, strategy_type());
  106. }
  107. };
  108. } // namespace resolve_strategy
  109. namespace resolve_variant
  110. {
  111. template <typename Geometry1, typename Geometry2>
  112. struct distance
  113. {
  114. template <typename Strategy>
  115. static inline typename distance_result<Geometry1, Geometry2, Strategy>::type
  116. apply(Geometry1 const& geometry1,
  117. Geometry2 const& geometry2,
  118. Strategy const& strategy)
  119. {
  120. return resolve_strategy::distance
  121. <
  122. Strategy
  123. >::apply(geometry1, geometry2, strategy);
  124. }
  125. };
  126. template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
  127. struct distance<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
  128. {
  129. template <typename Strategy>
  130. struct visitor: static_visitor
  131. <
  132. typename distance_result
  133. <
  134. variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
  135. Geometry2,
  136. Strategy
  137. >::type
  138. >
  139. {
  140. Geometry2 const& m_geometry2;
  141. Strategy const& m_strategy;
  142. visitor(Geometry2 const& geometry2,
  143. Strategy const& strategy)
  144. : m_geometry2(geometry2),
  145. m_strategy(strategy)
  146. {}
  147. template <typename Geometry1>
  148. typename distance_result<Geometry1, Geometry2, Strategy>::type
  149. operator()(Geometry1 const& geometry1) const
  150. {
  151. return distance
  152. <
  153. Geometry1,
  154. Geometry2
  155. >::template apply
  156. <
  157. Strategy
  158. >(geometry1, m_geometry2, m_strategy);
  159. }
  160. };
  161. template <typename Strategy>
  162. static inline typename distance_result
  163. <
  164. variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
  165. Geometry2,
  166. Strategy
  167. >::type
  168. apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
  169. Geometry2 const& geometry2,
  170. Strategy const& strategy)
  171. {
  172. return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
  173. }
  174. };
  175. template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
  176. struct distance<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
  177. {
  178. template <typename Strategy>
  179. struct visitor: static_visitor
  180. <
  181. typename distance_result
  182. <
  183. Geometry1,
  184. variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
  185. Strategy
  186. >::type
  187. >
  188. {
  189. Geometry1 const& m_geometry1;
  190. Strategy const& m_strategy;
  191. visitor(Geometry1 const& geometry1,
  192. Strategy const& strategy)
  193. : m_geometry1(geometry1),
  194. m_strategy(strategy)
  195. {}
  196. template <typename Geometry2>
  197. typename distance_result<Geometry1, Geometry2, Strategy>::type
  198. operator()(Geometry2 const& geometry2) const
  199. {
  200. return distance
  201. <
  202. Geometry1,
  203. Geometry2
  204. >::template apply
  205. <
  206. Strategy
  207. >(m_geometry1, geometry2, m_strategy);
  208. }
  209. };
  210. template <typename Strategy>
  211. static inline typename distance_result
  212. <
  213. Geometry1,
  214. variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
  215. Strategy
  216. >::type
  217. apply(
  218. Geometry1 const& geometry1,
  219. const variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry2,
  220. Strategy const& strategy)
  221. {
  222. return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
  223. }
  224. };
  225. template
  226. <
  227. BOOST_VARIANT_ENUM_PARAMS(typename T1),
  228. BOOST_VARIANT_ENUM_PARAMS(typename T2)
  229. >
  230. struct distance
  231. <
  232. boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
  233. boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
  234. >
  235. {
  236. template <typename Strategy>
  237. struct visitor: static_visitor
  238. <
  239. typename distance_result
  240. <
  241. boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
  242. boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>,
  243. Strategy
  244. >::type
  245. >
  246. {
  247. Strategy const& m_strategy;
  248. visitor(Strategy const& strategy)
  249. : m_strategy(strategy)
  250. {}
  251. template <typename Geometry1, typename Geometry2>
  252. typename distance_result<Geometry1, Geometry2, Strategy>::type
  253. operator()(Geometry1 const& geometry1, Geometry2 const& geometry2) const
  254. {
  255. return distance
  256. <
  257. Geometry1,
  258. Geometry2
  259. >::template apply
  260. <
  261. Strategy
  262. >(geometry1, geometry2, m_strategy);
  263. }
  264. };
  265. template <typename Strategy>
  266. static inline typename distance_result
  267. <
  268. boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
  269. boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>,
  270. Strategy
  271. >::type
  272. apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
  273. boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
  274. Strategy const& strategy)
  275. {
  276. return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
  277. }
  278. };
  279. } // namespace resolve_variant
  280. /*!
  281. \brief Calculate the distance between two geometries \brief_strategy
  282. \ingroup distance
  283. \details
  284. \details The free function distance calculates the distance between two geometries \brief_strategy. \details_strategy_reasons
  285. \tparam Geometry1 \tparam_geometry
  286. \tparam Geometry2 \tparam_geometry
  287. \tparam Strategy \tparam_strategy{Distance}
  288. \param geometry1 \param_geometry
  289. \param geometry2 \param_geometry
  290. \param strategy \param_strategy{distance}
  291. \return \return_calc{distance}
  292. \note The strategy can be a point-point strategy. In case of distance point-line/point-polygon
  293. it may also be a point-segment strategy.
  294. \qbk{distinguish,with strategy}
  295. \qbk{
  296. [heading Available Strategies]
  297. \* [link geometry.reference.strategies.strategy_distance_pythagoras Pythagoras (cartesian)]
  298. \* [link geometry.reference.strategies.strategy_distance_haversine Haversine (spherical)]
  299. \* [link geometry.reference.strategies.strategy_distance_cross_track Cross track (spherical\, point-to-segment)]
  300. \* [link geometry.reference.strategies.strategy_distance_projected_point Projected point (cartesian\, point-to-segment)]
  301. \* more (currently extensions): Vincenty\, Andoyer (geographic)
  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>
  313. inline typename distance_result<Geometry1, Geometry2, Strategy>::type
  314. distance(Geometry1 const& geometry1,
  315. Geometry2 const& geometry2,
  316. Strategy const& strategy)
  317. {
  318. concepts::check<Geometry1 const>();
  319. concepts::check<Geometry2 const>();
  320. detail::throw_on_empty_input(geometry1);
  321. detail::throw_on_empty_input(geometry2);
  322. return resolve_variant::distance
  323. <
  324. Geometry1,
  325. Geometry2
  326. >::apply(geometry1, geometry2, strategy);
  327. }
  328. /*!
  329. \brief Calculate the distance between two geometries.
  330. \ingroup distance
  331. \details The free function distance calculates the distance between two geometries. \details_default_strategy
  332. \tparam Geometry1 \tparam_geometry
  333. \tparam Geometry2 \tparam_geometry
  334. \param geometry1 \param_geometry
  335. \param geometry2 \param_geometry
  336. \return \return_calc{distance}
  337. \qbk{[include reference/algorithms/distance.qbk]}
  338. */
  339. template <typename Geometry1, typename Geometry2>
  340. inline typename default_distance_result<Geometry1, Geometry2>::type
  341. distance(Geometry1 const& geometry1,
  342. Geometry2 const& geometry2)
  343. {
  344. concepts::check<Geometry1 const>();
  345. concepts::check<Geometry2 const>();
  346. return geometry::distance(geometry1, geometry2, default_strategy());
  347. }
  348. }} // namespace boost::geometry
  349. #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_INTERFACE_HPP