interface.hpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
  3. // Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
  4. // Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
  5. // Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
  6. // This file was modified by Oracle on 2013, 2014, 2015, 2017.
  7. // Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
  8. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  9. // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
  10. // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
  11. // Use, modification and distribution is subject to the Boost Software License,
  12. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  13. // http://www.boost.org/LICENSE_1_0.txt)
  14. #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_TOUCHES_INTERFACE_HPP
  15. #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_TOUCHES_INTERFACE_HPP
  16. #include <deque>
  17. #include <boost/variant/apply_visitor.hpp>
  18. #include <boost/variant/static_visitor.hpp>
  19. #include <boost/variant/variant_fwd.hpp>
  20. #include <boost/geometry/core/reverse_dispatch.hpp>
  21. #include <boost/geometry/core/tag.hpp>
  22. #include <boost/geometry/core/tag_cast.hpp>
  23. #include <boost/geometry/core/tags.hpp>
  24. #include <boost/geometry/geometries/concepts/check.hpp>
  25. #include <boost/geometry/strategies/default_strategy.hpp>
  26. #include <boost/geometry/strategies/relate.hpp>
  27. namespace boost { namespace geometry
  28. {
  29. #ifndef DOXYGEN_NO_DISPATCH
  30. namespace dispatch {
  31. // TODO: Since CastedTags are used is Reverse needed?
  32. template
  33. <
  34. typename Geometry1,
  35. typename Geometry2,
  36. typename Tag1 = typename tag<Geometry1>::type,
  37. typename Tag2 = typename tag<Geometry2>::type,
  38. typename CastedTag1 = typename tag_cast<Tag1, pointlike_tag, linear_tag, areal_tag>::type,
  39. typename CastedTag2 = typename tag_cast<Tag2, pointlike_tag, linear_tag, areal_tag>::type,
  40. bool Reverse = reverse_dispatch<Geometry1, Geometry2>::type::value
  41. >
  42. struct touches
  43. : not_implemented<Tag1, Tag2>
  44. {};
  45. // If reversal is needed, perform it
  46. template
  47. <
  48. typename Geometry1, typename Geometry2,
  49. typename Tag1, typename Tag2,
  50. typename CastedTag1, typename CastedTag2
  51. >
  52. struct touches<Geometry1, Geometry2, Tag1, Tag2, CastedTag1, CastedTag2, true>
  53. : touches<Geometry2, Geometry1, Tag2, Tag1, CastedTag2, CastedTag1, false>
  54. {
  55. template <typename Strategy>
  56. static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
  57. {
  58. return touches<Geometry2, Geometry1>::apply(g2, g1, strategy);
  59. }
  60. };
  61. } // namespace dispatch
  62. #endif // DOXYGEN_NO_DISPATCH
  63. namespace resolve_strategy
  64. {
  65. struct touches
  66. {
  67. template <typename Geometry1, typename Geometry2, typename Strategy>
  68. static inline bool apply(Geometry1 const& geometry1,
  69. Geometry2 const& geometry2,
  70. Strategy const& strategy)
  71. {
  72. return dispatch::touches
  73. <
  74. Geometry1, Geometry2
  75. >::apply(geometry1, geometry2, strategy);
  76. }
  77. template <typename Geometry1, typename Geometry2>
  78. static inline bool apply(Geometry1 const& geometry1,
  79. Geometry2 const& geometry2,
  80. default_strategy)
  81. {
  82. typedef typename strategy::relate::services::default_strategy
  83. <
  84. Geometry1,
  85. Geometry2
  86. >::type strategy_type;
  87. return dispatch::touches
  88. <
  89. Geometry1, Geometry2
  90. >::apply(geometry1, geometry2, strategy_type());
  91. }
  92. };
  93. } // namespace resolve_strategy
  94. namespace resolve_variant {
  95. template <typename Geometry1, typename Geometry2>
  96. struct touches
  97. {
  98. template <typename Strategy>
  99. static bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
  100. {
  101. concepts::check<Geometry1 const>();
  102. concepts::check<Geometry2 const>();
  103. return resolve_strategy::touches::apply(geometry1, geometry2, strategy);
  104. }
  105. };
  106. template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
  107. struct touches<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
  108. {
  109. template <typename Strategy>
  110. struct visitor: boost::static_visitor<bool>
  111. {
  112. Geometry2 const& m_geometry2;
  113. Strategy const& m_strategy;
  114. visitor(Geometry2 const& geometry2, Strategy const& strategy)
  115. : m_geometry2(geometry2)
  116. , m_strategy(strategy)
  117. {}
  118. template <typename Geometry1>
  119. bool operator()(Geometry1 const& geometry1) const
  120. {
  121. return touches<Geometry1, Geometry2>::apply(geometry1, m_geometry2, m_strategy);
  122. }
  123. };
  124. template <typename Strategy>
  125. static inline bool apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
  126. Geometry2 const& geometry2,
  127. Strategy const& strategy)
  128. {
  129. return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
  130. }
  131. };
  132. template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
  133. struct touches<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
  134. {
  135. template <typename Strategy>
  136. struct visitor: boost::static_visitor<bool>
  137. {
  138. Geometry1 const& m_geometry1;
  139. Strategy const& m_strategy;
  140. visitor(Geometry1 const& geometry1, Strategy const& strategy)
  141. : m_geometry1(geometry1)
  142. , m_strategy(strategy)
  143. {}
  144. template <typename Geometry2>
  145. bool operator()(Geometry2 const& geometry2) const
  146. {
  147. return touches<Geometry1, Geometry2>::apply(m_geometry1, geometry2, m_strategy);
  148. }
  149. };
  150. template <typename Strategy>
  151. static inline bool apply(Geometry1 const& geometry1,
  152. boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
  153. Strategy const& strategy)
  154. {
  155. return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
  156. }
  157. };
  158. template <BOOST_VARIANT_ENUM_PARAMS(typename T1),
  159. BOOST_VARIANT_ENUM_PARAMS(typename T2)>
  160. struct touches<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
  161. boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
  162. {
  163. template <typename Strategy>
  164. struct visitor: boost::static_visitor<bool>
  165. {
  166. Strategy const& m_strategy;
  167. visitor(Strategy const& strategy)
  168. : m_strategy(strategy)
  169. {}
  170. template <typename Geometry1, typename Geometry2>
  171. bool operator()(Geometry1 const& geometry1,
  172. Geometry2 const& geometry2) const
  173. {
  174. return touches<Geometry1, Geometry2>::apply(geometry1, geometry2, m_strategy);
  175. }
  176. };
  177. template <typename Strategy>
  178. static inline bool apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
  179. boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
  180. Strategy const& strategy)
  181. {
  182. return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
  183. }
  184. };
  185. template <typename Geometry>
  186. struct self_touches;
  187. template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
  188. struct self_touches<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
  189. {
  190. struct visitor: boost::static_visitor<bool>
  191. {
  192. template <typename Geometry>
  193. bool operator()(Geometry const& geometry) const
  194. {
  195. return self_touches<Geometry>::apply(geometry);
  196. }
  197. };
  198. static inline bool
  199. apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry)
  200. {
  201. return boost::apply_visitor(visitor(), geometry);
  202. }
  203. };
  204. } // namespace resolve_variant
  205. /*!
  206. \brief \brief_check{has at least one touching point (self-tangency)}
  207. \note This function can be called for one geometry (self-tangency) and
  208. also for two geometries (touch)
  209. \ingroup touches
  210. \tparam Geometry \tparam_geometry
  211. \param geometry \param_geometry
  212. \return \return_check{is self-touching}
  213. \qbk{distinguish,one geometry}
  214. \qbk{[def __one_parameter__]}
  215. \qbk{[include reference/algorithms/touches.qbk]}
  216. */
  217. template <typename Geometry>
  218. inline bool touches(Geometry const& geometry)
  219. {
  220. return resolve_variant::self_touches<Geometry>::apply(geometry);
  221. }
  222. /*!
  223. \brief \brief_check2{have at least one touching point (tangent - non overlapping)}
  224. \ingroup touches
  225. \tparam Geometry1 \tparam_geometry
  226. \tparam Geometry2 \tparam_geometry
  227. \param geometry1 \param_geometry
  228. \param geometry2 \param_geometry
  229. \return \return_check2{touch each other}
  230. \qbk{distinguish,two geometries}
  231. \qbk{[include reference/algorithms/touches.qbk]}
  232. */
  233. template <typename Geometry1, typename Geometry2>
  234. inline bool touches(Geometry1 const& geometry1, Geometry2 const& geometry2)
  235. {
  236. return resolve_variant::touches
  237. <
  238. Geometry1, Geometry2
  239. >::apply(geometry1, geometry2, default_strategy());
  240. }
  241. /*!
  242. \brief \brief_check2{have at least one touching point (tangent - non overlapping)}
  243. \ingroup touches
  244. \tparam Geometry1 \tparam_geometry
  245. \tparam Geometry2 \tparam_geometry
  246. \tparam Strategy \tparam_strategy{Touches}
  247. \param geometry1 \param_geometry
  248. \param geometry2 \param_geometry
  249. \param strategy \param_strategy{touches}
  250. \return \return_check2{touch each other}
  251. \qbk{distinguish,with strategy}
  252. \qbk{[include reference/algorithms/touches.qbk]}
  253. */
  254. template <typename Geometry1, typename Geometry2, typename Strategy>
  255. inline bool touches(Geometry1 const& geometry1,
  256. Geometry2 const& geometry2,
  257. Strategy const& strategy)
  258. {
  259. return resolve_variant::touches
  260. <
  261. Geometry1, Geometry2
  262. >::apply(geometry1, geometry2, strategy);
  263. }
  264. }} // namespace boost::geometry
  265. #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_TOUCHES_INTERFACE_HPP