within_concept.hpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
  3. // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
  4. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
  5. // This file was modified by Oracle on 2018-2020.
  6. // Modifications copyright (c) 2018-2020 Oracle and/or its affiliates.
  7. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  8. // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
  9. // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
  10. // Use, modification and distribution is subject to the Boost Software License,
  11. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  12. // http://www.boost.org/LICENSE_1_0.txt)
  13. #ifndef BOOST_GEOMETRY_STRATEGIES_CONCEPTS_WITHIN_CONCEPT_HPP
  14. #define BOOST_GEOMETRY_STRATEGIES_CONCEPTS_WITHIN_CONCEPT_HPP
  15. #include <type_traits>
  16. #include <boost/concept_check.hpp>
  17. #include <boost/core/ignore_unused.hpp>
  18. #include <boost/function_types/result_type.hpp>
  19. #include <boost/geometry/core/static_assert.hpp>
  20. #include <boost/geometry/core/tag.hpp>
  21. #include <boost/geometry/core/tag_cast.hpp>
  22. #include <boost/geometry/core/tags.hpp>
  23. #include <boost/geometry/geometries/concepts/box_concept.hpp>
  24. #include <boost/geometry/geometries/concepts/point_concept.hpp>
  25. #include <boost/geometry/strategies/detail.hpp>
  26. #include <boost/geometry/util/parameter_type_of.hpp>
  27. namespace boost { namespace geometry { namespace concepts
  28. {
  29. namespace detail
  30. {
  31. template
  32. <
  33. typename Point, typename Geometry, typename Strategy,
  34. bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
  35. >
  36. struct relate_strategy_dispatch
  37. {
  38. using type = decltype(std::declval<Strategy>().relate(
  39. std::declval<Point>(), std::declval<Geometry>()));
  40. };
  41. template <typename Point, typename Geometry, typename Strategy>
  42. struct relate_strategy_dispatch<Point, Geometry, Strategy, false>
  43. {
  44. using type = Strategy;
  45. };
  46. template
  47. <
  48. typename Point, typename Geometry, typename Strategy,
  49. bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
  50. >
  51. struct within_strategy_dispatch
  52. {
  53. using type = decltype(std::declval<Strategy>().within(
  54. std::declval<Point>(), std::declval<Geometry>()));
  55. };
  56. template <typename Point, typename Geometry, typename Strategy>
  57. struct within_strategy_dispatch<Point, Geometry, Strategy, false>
  58. {
  59. using type = Strategy;
  60. };
  61. } // namespace detail
  62. /*!
  63. \brief Checks strategy for within (point-in-polygon)
  64. \ingroup within
  65. */
  66. template <typename Point, typename Polygonal, typename Strategy>
  67. class WithinStrategyPolygonal
  68. {
  69. #ifndef DOXYGEN_NO_CONCEPT_MEMBERS
  70. typedef typename geometry::point_type<Polygonal>::type point_of_segment;
  71. // 0)
  72. typedef typename concepts::detail::relate_strategy_dispatch
  73. <
  74. Point, Polygonal, Strategy
  75. >::type strategy_type;
  76. // 1) must define state_type
  77. typedef typename strategy_type::state_type state_type;
  78. struct checker
  79. {
  80. template <typename ApplyMethod, typename ResultMethod>
  81. static void apply(ApplyMethod, ResultMethod)
  82. {
  83. typedef typename parameter_type_of
  84. <
  85. ApplyMethod, 0
  86. >::type point_type;
  87. typedef typename parameter_type_of
  88. <
  89. ApplyMethod, 1
  90. >::type segment_point_type;
  91. // CHECK: apply-arguments should both fulfill point concept
  92. BOOST_CONCEPT_ASSERT
  93. (
  94. (concepts::ConstPoint<point_type>)
  95. );
  96. BOOST_CONCEPT_ASSERT
  97. (
  98. (concepts::ConstPoint<segment_point_type>)
  99. );
  100. // CHECK: return types (result: int, apply: bool)
  101. BOOST_GEOMETRY_STATIC_ASSERT
  102. (
  103. (std::is_same
  104. <
  105. bool, typename boost::function_types::result_type<ApplyMethod>::type
  106. >::value),
  107. "Wrong return type of apply().",
  108. bool, ApplyMethod
  109. );
  110. BOOST_GEOMETRY_STATIC_ASSERT
  111. (
  112. (std::is_same
  113. <
  114. int, typename boost::function_types::result_type<ResultMethod>::type
  115. >::value),
  116. "Wrong return type of result().",
  117. int, ResultMethod
  118. );
  119. // CHECK: calling method apply and result
  120. strategy_type const* str = 0;
  121. state_type* st = 0;
  122. point_type const* p = 0;
  123. segment_point_type const* sp = 0;
  124. bool b = str->apply(*p, *sp, *sp, *st);
  125. int r = str->result(*st);
  126. boost::ignore_unused(r, b, str);
  127. }
  128. };
  129. public :
  130. BOOST_CONCEPT_USAGE(WithinStrategyPolygonal)
  131. {
  132. checker::apply(&strategy_type::template apply<Point, point_of_segment>,
  133. &strategy_type::result);
  134. }
  135. #endif
  136. };
  137. template <typename Point, typename Box, typename Strategy>
  138. class WithinStrategyPointBox
  139. {
  140. #ifndef DOXYGEN_NO_CONCEPT_MEMBERS
  141. // 0)
  142. typedef typename concepts::detail::within_strategy_dispatch
  143. <
  144. Point, Box, Strategy
  145. >::type strategy_type;
  146. struct checker
  147. {
  148. template <typename ApplyMethod>
  149. static void apply(ApplyMethod)
  150. {
  151. typedef typename parameter_type_of
  152. <
  153. ApplyMethod, 0
  154. >::type point_type;
  155. typedef typename parameter_type_of
  156. <
  157. ApplyMethod, 1
  158. >::type box_type;
  159. // CHECK: apply-arguments should fulfill point/box concept
  160. BOOST_CONCEPT_ASSERT
  161. (
  162. (concepts::ConstPoint<point_type>)
  163. );
  164. BOOST_CONCEPT_ASSERT
  165. (
  166. (concepts::ConstBox<box_type>)
  167. );
  168. // CHECK: return types (apply: bool)
  169. BOOST_GEOMETRY_STATIC_ASSERT
  170. (
  171. (std::is_same
  172. <
  173. bool,
  174. typename boost::function_types::result_type<ApplyMethod>::type
  175. >::value),
  176. "Wrong return type of apply().",
  177. bool, ApplyMethod
  178. );
  179. // CHECK: calling method apply
  180. strategy_type const* str = 0;
  181. point_type const* p = 0;
  182. box_type const* bx = 0;
  183. bool b = str->apply(*p, *bx);
  184. boost::ignore_unused(b, str);
  185. }
  186. };
  187. public :
  188. BOOST_CONCEPT_USAGE(WithinStrategyPointBox)
  189. {
  190. checker::apply(&strategy_type::template apply<Point, Box>);
  191. }
  192. #endif
  193. };
  194. template <typename Box1, typename Box2, typename Strategy>
  195. class WithinStrategyBoxBox
  196. {
  197. #ifndef DOXYGEN_NO_CONCEPT_MEMBERS
  198. // 0)
  199. typedef typename concepts::detail::within_strategy_dispatch
  200. <
  201. Box1, Box2, Strategy
  202. >::type strategy_type;
  203. struct checker
  204. {
  205. template <typename ApplyMethod>
  206. static void apply(ApplyMethod const&)
  207. {
  208. typedef typename parameter_type_of
  209. <
  210. ApplyMethod, 0
  211. >::type box_type1;
  212. typedef typename parameter_type_of
  213. <
  214. ApplyMethod, 1
  215. >::type box_type2;
  216. // CHECK: apply-arguments should both fulfill box concept
  217. BOOST_CONCEPT_ASSERT
  218. (
  219. (concepts::ConstBox<box_type1>)
  220. );
  221. BOOST_CONCEPT_ASSERT
  222. (
  223. (concepts::ConstBox<box_type2>)
  224. );
  225. // CHECK: return types (apply: bool)
  226. BOOST_GEOMETRY_STATIC_ASSERT
  227. (
  228. (std::is_same
  229. <
  230. bool,
  231. typename boost::function_types::result_type<ApplyMethod>::type
  232. >::value),
  233. "Wrong return type of apply().",
  234. bool, ApplyMethod
  235. );
  236. // CHECK: calling method apply
  237. strategy_type const* str = 0;
  238. box_type1 const* b1 = 0;
  239. box_type2 const* b2 = 0;
  240. bool b = str->apply(*b1, *b2);
  241. boost::ignore_unused(b, str);
  242. }
  243. };
  244. public :
  245. BOOST_CONCEPT_USAGE(WithinStrategyBoxBox)
  246. {
  247. checker::apply(&strategy_type::template apply<Box1, Box2>);
  248. }
  249. #endif
  250. };
  251. // So now: boost::geometry::concepts::within
  252. namespace within
  253. {
  254. #ifndef DOXYGEN_NO_DISPATCH
  255. namespace dispatch
  256. {
  257. template
  258. <
  259. typename Geometry1, typename Geometry2,
  260. typename FirstTag, typename SecondTag, typename CastedTag,
  261. typename Strategy
  262. >
  263. struct check_within
  264. {};
  265. template
  266. <
  267. typename Geometry1, typename Geometry2,
  268. typename AnyTag,
  269. typename Strategy
  270. >
  271. struct check_within<Geometry1, Geometry2, point_tag, AnyTag, areal_tag, Strategy>
  272. {
  273. BOOST_CONCEPT_ASSERT( (WithinStrategyPolygonal<Geometry1, Geometry2, Strategy>) );
  274. };
  275. template <typename Geometry1, typename Geometry2, typename Strategy>
  276. struct check_within<Geometry1, Geometry2, point_tag, box_tag, areal_tag, Strategy>
  277. {
  278. BOOST_CONCEPT_ASSERT( (WithinStrategyPointBox<Geometry1, Geometry2, Strategy>) );
  279. };
  280. template <typename Geometry1, typename Geometry2, typename Strategy>
  281. struct check_within<Geometry1, Geometry2, box_tag, box_tag, areal_tag, Strategy>
  282. {
  283. BOOST_CONCEPT_ASSERT( (WithinStrategyBoxBox<Geometry1, Geometry2, Strategy>) );
  284. };
  285. } // namespace dispatch
  286. #endif
  287. /*!
  288. \brief Checks, in compile-time, the concept of any within-strategy
  289. \ingroup concepts
  290. */
  291. template <typename Geometry1, typename Geometry2, typename Strategy>
  292. inline void check()
  293. {
  294. dispatch::check_within
  295. <
  296. Geometry1,
  297. Geometry2,
  298. typename tag<Geometry1>::type,
  299. typename tag<Geometry2>::type,
  300. typename tag_cast<typename tag<Geometry2>::type, areal_tag>::type,
  301. Strategy
  302. > c;
  303. boost::ignore_unused(c);
  304. }
  305. }}}} // namespace boost::geometry::concepts::within
  306. #endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_WITHIN_CONCEPT_HPP