interface.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  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.
  8. // Modifications copyright (c) 2014, Oracle and/or its affiliates.
  9. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
  10. // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
  11. // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
  12. // Use, modification and distribution is subject to the Boost Software License,
  13. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  14. // http://www.boost.org/LICENSE_1_0.txt)
  15. #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_INTERFACE_HPP
  16. #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_INTERFACE_HPP
  17. #include <boost/concept_check.hpp>
  18. #include <boost/mpl/always.hpp>
  19. #include <boost/mpl/bool.hpp>
  20. #include <boost/mpl/vector.hpp>
  21. #include <boost/geometry/core/point_type.hpp>
  22. #include <boost/geometry/geometries/concepts/check.hpp>
  23. #include <boost/geometry/strategies/default_strategy.hpp>
  24. #include <boost/geometry/strategies/distance.hpp>
  25. #include <boost/geometry/strategies/default_distance_result.hpp>
  26. #include <boost/geometry/strategies/distance_result.hpp>
  27. #include <boost/geometry/algorithms/detail/throw_on_empty_input.hpp>
  28. #include <boost/geometry/algorithms/detail/distance/default_strategies.hpp>
  29. #include <boost/geometry/algorithms/dispatch/distance.hpp>
  30. namespace boost { namespace geometry
  31. {
  32. #ifndef DOXYGEN_NO_DISPATCH
  33. namespace dispatch
  34. {
  35. // If reversal is needed, perform it
  36. template
  37. <
  38. typename Geometry1, typename Geometry2, typename Strategy,
  39. typename Tag1, typename Tag2, typename StrategyTag
  40. >
  41. struct distance
  42. <
  43. Geometry1, Geometry2, Strategy,
  44. Tag1, Tag2, StrategyTag,
  45. true
  46. >
  47. : distance<Geometry2, Geometry1, Strategy, Tag2, Tag1, StrategyTag, false>
  48. {
  49. typedef typename strategy::distance::services::return_type
  50. <
  51. Strategy,
  52. typename point_type<Geometry2>::type,
  53. typename point_type<Geometry1>::type
  54. >::type return_type;
  55. static inline return_type apply(
  56. Geometry1 const& g1,
  57. Geometry2 const& g2,
  58. Strategy const& strategy)
  59. {
  60. return distance
  61. <
  62. Geometry2, Geometry1, Strategy,
  63. Tag2, Tag1, StrategyTag,
  64. false
  65. >::apply(g2, g1, strategy);
  66. }
  67. };
  68. } // namespace dispatch
  69. #endif // DOXYGEN_NO_DISPATCH
  70. namespace resolve_strategy
  71. {
  72. struct distance
  73. {
  74. template <typename Geometry1, typename Geometry2, typename Strategy>
  75. static inline typename distance_result<Geometry1, Geometry2, Strategy>::type
  76. apply(Geometry1 const& geometry1,
  77. Geometry2 const& geometry2,
  78. Strategy const& strategy)
  79. {
  80. return dispatch::distance
  81. <
  82. Geometry1, Geometry2, Strategy
  83. >::apply(geometry1, geometry2, strategy);
  84. }
  85. template <typename Geometry1, typename Geometry2>
  86. static inline
  87. typename distance_result<Geometry1, Geometry2, default_strategy>::type
  88. apply(Geometry1 const& geometry1,
  89. Geometry2 const& geometry2,
  90. default_strategy)
  91. {
  92. typedef typename detail::distance::default_strategy
  93. <
  94. Geometry1, Geometry2
  95. >::type strategy_type;
  96. return dispatch::distance
  97. <
  98. Geometry1, Geometry2, strategy_type
  99. >::apply(geometry1, geometry2, strategy_type());
  100. }
  101. };
  102. } // namespace resolve_strategy
  103. namespace resolve_variant
  104. {
  105. template <typename Geometry1, typename Geometry2>
  106. struct distance
  107. {
  108. template <typename Strategy>
  109. static inline typename distance_result<Geometry1, Geometry2, Strategy>::type
  110. apply(Geometry1 const& geometry1,
  111. Geometry2 const& geometry2,
  112. Strategy const& strategy)
  113. {
  114. return
  115. resolve_strategy::distance::apply(geometry1, geometry2, strategy);
  116. }
  117. };
  118. template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
  119. struct distance<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
  120. {
  121. template <typename Strategy>
  122. struct visitor: static_visitor
  123. <
  124. typename distance_result
  125. <
  126. variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
  127. Geometry2,
  128. Strategy
  129. >::type
  130. >
  131. {
  132. Geometry2 const& m_geometry2;
  133. Strategy const& m_strategy;
  134. visitor(Geometry2 const& geometry2,
  135. Strategy const& strategy)
  136. : m_geometry2(geometry2),
  137. m_strategy(strategy)
  138. {}
  139. template <typename Geometry1>
  140. typename distance_result<Geometry1, Geometry2, Strategy>::type
  141. operator()(Geometry1 const& geometry1) const
  142. {
  143. return distance
  144. <
  145. Geometry1,
  146. Geometry2
  147. >::template apply
  148. <
  149. Strategy
  150. >(geometry1, m_geometry2, m_strategy);
  151. }
  152. };
  153. template <typename Strategy>
  154. static inline typename distance_result
  155. <
  156. variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
  157. Geometry2,
  158. Strategy
  159. >::type
  160. apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
  161. Geometry2 const& geometry2,
  162. Strategy const& strategy)
  163. {
  164. return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
  165. }
  166. };
  167. template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
  168. struct distance<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
  169. {
  170. template <typename Strategy>
  171. struct visitor: static_visitor
  172. <
  173. typename distance_result
  174. <
  175. Geometry1,
  176. variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
  177. Strategy
  178. >::type
  179. >
  180. {
  181. Geometry1 const& m_geometry1;
  182. Strategy const& m_strategy;
  183. visitor(Geometry1 const& geometry1,
  184. Strategy const& strategy)
  185. : m_geometry1(geometry1),
  186. m_strategy(strategy)
  187. {}
  188. template <typename Geometry2>
  189. typename distance_result<Geometry1, Geometry2, Strategy>::type
  190. operator()(Geometry2 const& geometry2) const
  191. {
  192. return distance
  193. <
  194. Geometry1,
  195. Geometry2
  196. >::template apply
  197. <
  198. Strategy
  199. >(m_geometry1, geometry2, m_strategy);
  200. }
  201. };
  202. template <typename Strategy>
  203. static inline typename distance_result
  204. <
  205. Geometry1,
  206. variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
  207. Strategy
  208. >::type
  209. apply(
  210. Geometry1 const& geometry1,
  211. const variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry2,
  212. Strategy const& strategy)
  213. {
  214. return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
  215. }
  216. };
  217. template
  218. <
  219. BOOST_VARIANT_ENUM_PARAMS(typename T1),
  220. BOOST_VARIANT_ENUM_PARAMS(typename T2)
  221. >
  222. struct distance
  223. <
  224. boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
  225. boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
  226. >
  227. {
  228. template <typename Strategy>
  229. struct visitor: static_visitor
  230. <
  231. typename distance_result
  232. <
  233. boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
  234. boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>,
  235. Strategy
  236. >::type
  237. >
  238. {
  239. Strategy const& m_strategy;
  240. visitor(Strategy const& strategy)
  241. : m_strategy(strategy)
  242. {}
  243. template <typename Geometry1, typename Geometry2>
  244. typename distance_result<Geometry1, Geometry2, Strategy>::type
  245. operator()(Geometry1 const& geometry1, Geometry2 const& geometry2) const
  246. {
  247. return distance
  248. <
  249. Geometry1,
  250. Geometry2
  251. >::template apply
  252. <
  253. Strategy
  254. >(geometry1, geometry2, m_strategy);
  255. }
  256. };
  257. template <typename Strategy>
  258. static inline typename distance_result
  259. <
  260. boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
  261. boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>,
  262. Strategy
  263. >::type
  264. apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
  265. boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
  266. Strategy const& strategy)
  267. {
  268. return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
  269. }
  270. };
  271. } // namespace resolve_variant
  272. /*!
  273. \brief \brief_calc2{distance} \brief_strategy
  274. \ingroup distance
  275. \details
  276. \details \details_calc{area}. \brief_strategy. \details_strategy_reasons
  277. \tparam Geometry1 \tparam_geometry
  278. \tparam Geometry2 \tparam_geometry
  279. \tparam Strategy \tparam_strategy{Distance}
  280. \param geometry1 \param_geometry
  281. \param geometry2 \param_geometry
  282. \param strategy \param_strategy{distance}
  283. \return \return_calc{distance}
  284. \note The strategy can be a point-point strategy. In case of distance point-line/point-polygon
  285. it may also be a point-segment strategy.
  286. \qbk{distinguish,with strategy}
  287. \qbk{
  288. [heading Available Strategies]
  289. \* [link geometry.reference.strategies.strategy_distance_pythagoras Pythagoras (cartesian)]
  290. \* [link geometry.reference.strategies.strategy_distance_haversine Haversine (spherical)]
  291. \* [link geometry.reference.strategies.strategy_distance_cross_track Cross track (spherical\, point-to-segment)]
  292. \* [link geometry.reference.strategies.strategy_distance_projected_point Projected point (cartesian\, point-to-segment)]
  293. \* more (currently extensions): Vincenty\, Andoyer (geographic)
  294. }
  295. */
  296. /*
  297. Note, in case of a Compilation Error:
  298. if you get:
  299. - "Failed to specialize function template ..."
  300. - "error: no matching function for call to ..."
  301. for distance, it is probably so that there is no specialization
  302. for return_type<...> for your strategy.
  303. */
  304. template <typename Geometry1, typename Geometry2, typename Strategy>
  305. inline typename distance_result<Geometry1, Geometry2, Strategy>::type
  306. distance(Geometry1 const& geometry1,
  307. Geometry2 const& geometry2,
  308. Strategy const& strategy)
  309. {
  310. concepts::check<Geometry1 const>();
  311. concepts::check<Geometry2 const>();
  312. detail::throw_on_empty_input(geometry1);
  313. detail::throw_on_empty_input(geometry2);
  314. return resolve_variant::distance
  315. <
  316. Geometry1,
  317. Geometry2
  318. >::apply(geometry1, geometry2, strategy);
  319. }
  320. /*!
  321. \brief \brief_calc2{distance}
  322. \ingroup distance
  323. \details The default strategy is used, corresponding to the coordinate system of the geometries
  324. \tparam Geometry1 \tparam_geometry
  325. \tparam Geometry2 \tparam_geometry
  326. \param geometry1 \param_geometry
  327. \param geometry2 \param_geometry
  328. \return \return_calc{distance}
  329. \qbk{[include reference/algorithms/distance.qbk]}
  330. */
  331. template <typename Geometry1, typename Geometry2>
  332. inline typename default_distance_result<Geometry1, Geometry2>::type
  333. distance(Geometry1 const& geometry1,
  334. Geometry2 const& geometry2)
  335. {
  336. concepts::check<Geometry1 const>();
  337. concepts::check<Geometry2 const>();
  338. return geometry::distance(geometry1, geometry2, default_strategy());
  339. }
  340. }} // namespace boost::geometry
  341. #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_INTERFACE_HPP