cartesian.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. // Boost.Geometry
  2. // Copyright (c) 2020, Oracle and/or its affiliates.
  3. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  4. // Licensed under the Boost Software License version 1.0.
  5. // http://www.boost.org/users/license.html
  6. #ifndef BOOST_GEOMETRY_STRATEGIES_RELATE_CARTESIAN_HPP
  7. #define BOOST_GEOMETRY_STRATEGIES_RELATE_CARTESIAN_HPP
  8. // TEMP - move to strategy
  9. #include <boost/geometry/strategies/agnostic/point_in_box_by_side.hpp>
  10. #include <boost/geometry/strategies/cartesian/intersection.hpp>
  11. #include <boost/geometry/strategies/cartesian/box_in_box.hpp>
  12. #include <boost/geometry/strategies/cartesian/point_in_point.hpp>
  13. #include <boost/geometry/strategies/cartesian/point_in_poly_crossings_multiply.hpp>
  14. #include <boost/geometry/strategies/cartesian/point_in_poly_franklin.hpp>
  15. #include <boost/geometry/strategies/cartesian/point_in_poly_winding.hpp>
  16. #include <boost/geometry/strategies/cartesian/disjoint_box_box.hpp>
  17. #include <boost/geometry/strategies/envelope/cartesian.hpp>
  18. #include <boost/geometry/strategies/relate/services.hpp>
  19. #include <boost/geometry/strategies/detail.hpp>
  20. #include <boost/geometry/strategy/cartesian/area.hpp>
  21. #include <boost/geometry/strategy/cartesian/side_robust.hpp>
  22. #include <boost/geometry/strategy/cartesian/side_by_triangle.hpp>
  23. #include <boost/geometry/strategy/cartesian/area_box.hpp>
  24. #include <boost/geometry/util/type_traits.hpp>
  25. namespace boost { namespace geometry
  26. {
  27. namespace strategies { namespace relate
  28. {
  29. template <typename CalculationType = void>
  30. class cartesian
  31. : public strategies::envelope::cartesian<CalculationType>
  32. {
  33. public:
  34. //area
  35. template <typename Geometry>
  36. static auto area(Geometry const&,
  37. std::enable_if_t<! util::is_box<Geometry>::value> * = nullptr)
  38. {
  39. return strategy::area::cartesian<CalculationType>();
  40. }
  41. template <typename Geometry>
  42. static auto area(Geometry const&,
  43. std::enable_if_t<util::is_box<Geometry>::value> * = nullptr)
  44. {
  45. return strategy::area::cartesian_box<CalculationType>();
  46. }
  47. // covered_by
  48. template <typename Geometry1, typename Geometry2>
  49. static auto covered_by(Geometry1 const&, Geometry2 const&,
  50. std::enable_if_t
  51. <
  52. util::is_pointlike<Geometry1>::value
  53. && util::is_box<Geometry2>::value
  54. > * = nullptr)
  55. {
  56. return strategy::covered_by::cartesian_point_box();
  57. }
  58. template <typename Geometry1, typename Geometry2>
  59. static auto covered_by(Geometry1 const&, Geometry2 const&,
  60. std::enable_if_t
  61. <
  62. util::is_box<Geometry1>::value
  63. && util::is_box<Geometry2>::value
  64. > * = nullptr)
  65. {
  66. return strategy::covered_by::cartesian_box_box();
  67. }
  68. // disjoint
  69. template <typename Geometry1, typename Geometry2>
  70. static auto disjoint(Geometry1 const&, Geometry2 const&,
  71. std::enable_if_t
  72. <
  73. util::is_box<Geometry1>::value
  74. && util::is_box<Geometry2>::value
  75. > * = nullptr)
  76. {
  77. return strategy::disjoint::cartesian_box_box();
  78. }
  79. template <typename Geometry1, typename Geometry2>
  80. static auto disjoint(Geometry1 const&, Geometry2 const&,
  81. std::enable_if_t
  82. <
  83. util::is_segment<Geometry1>::value
  84. && util::is_box<Geometry2>::value
  85. > * = nullptr)
  86. {
  87. // NOTE: Inconsistent name.
  88. return strategy::disjoint::segment_box();
  89. }
  90. // relate
  91. template <typename Geometry1, typename Geometry2>
  92. static auto relate(Geometry1 const&, Geometry2 const&,
  93. std::enable_if_t
  94. <
  95. util::is_pointlike<Geometry1>::value
  96. && util::is_pointlike<Geometry2>::value
  97. > * = nullptr)
  98. {
  99. return strategy::within::cartesian_point_point();
  100. }
  101. template <typename Geometry1, typename Geometry2>
  102. static auto relate(Geometry1 const&, Geometry2 const&,
  103. std::enable_if_t
  104. <
  105. util::is_pointlike<Geometry1>::value
  106. && ( util::is_linear<Geometry2>::value
  107. || util::is_polygonal<Geometry2>::value )
  108. > * = nullptr)
  109. {
  110. return strategy::within::cartesian_winding<void, void, CalculationType>();
  111. }
  112. // The problem is that this strategy is often used with non-geometry ranges.
  113. // So dispatching only by geometry categories is impossible.
  114. // In the past it was taking two segments, now it takes 3-point sub-ranges.
  115. // So dispatching by segments is impossible.
  116. // It could be dispatched by (linear || polygonal || non-geometry point range).
  117. // For now implement as 0-parameter, special case relate.
  118. //template <typename Geometry1, typename Geometry2>
  119. static auto relate(/*Geometry1 const&, Geometry2 const&,
  120. std::enable_if_t
  121. <
  122. ( util::is_linear<Geometry1>::value
  123. || util::is_polygonal<Geometry1>::value )
  124. && ( util::is_linear<Geometry2>::value
  125. || util::is_polygonal<Geometry2>::value )
  126. > * = nullptr*/)
  127. {
  128. return strategy::intersection::cartesian_segments<CalculationType>();
  129. }
  130. // side
  131. static auto side()
  132. {
  133. using side_strategy_type
  134. = typename strategy::side::services::default_strategy
  135. <cartesian_tag, CalculationType>::type;
  136. return side_strategy_type();
  137. }
  138. // within
  139. template <typename Geometry1, typename Geometry2>
  140. static auto within(Geometry1 const&, Geometry2 const&,
  141. std::enable_if_t
  142. <
  143. util::is_pointlike<Geometry1>::value
  144. && util::is_box<Geometry2>::value
  145. > * = nullptr)
  146. {
  147. return strategy::within::cartesian_point_box();
  148. }
  149. template <typename Geometry1, typename Geometry2>
  150. static auto within(Geometry1 const&, Geometry2 const&,
  151. std::enable_if_t
  152. <
  153. util::is_box<Geometry1>::value
  154. && util::is_box<Geometry2>::value
  155. > * = nullptr)
  156. {
  157. return strategy::within::cartesian_box_box();
  158. }
  159. };
  160. namespace services
  161. {
  162. template <typename Geometry1, typename Geometry2>
  163. struct default_strategy<Geometry1, Geometry2, cartesian_tag, cartesian_tag>
  164. {
  165. using type = strategies::relate::cartesian<>;
  166. };
  167. template <>
  168. struct strategy_converter<strategy::within::cartesian_point_point>
  169. {
  170. static auto get(strategy::within::cartesian_point_point const& )
  171. {
  172. return strategies::relate::cartesian<>();
  173. }
  174. };
  175. template <>
  176. struct strategy_converter<strategy::within::cartesian_point_box>
  177. {
  178. static auto get(strategy::within::cartesian_point_box const&)
  179. {
  180. return strategies::relate::cartesian<>();
  181. }
  182. };
  183. template <>
  184. struct strategy_converter<strategy::covered_by::cartesian_point_box>
  185. {
  186. static auto get(strategy::covered_by::cartesian_point_box const&)
  187. {
  188. return strategies::relate::cartesian<>();
  189. }
  190. };
  191. template <>
  192. struct strategy_converter<strategy::covered_by::cartesian_box_box>
  193. {
  194. static auto get(strategy::covered_by::cartesian_box_box const&)
  195. {
  196. return strategies::relate::cartesian<>();
  197. }
  198. };
  199. template <>
  200. struct strategy_converter<strategy::disjoint::cartesian_box_box>
  201. {
  202. static auto get(strategy::disjoint::cartesian_box_box const&)
  203. {
  204. return strategies::relate::cartesian<>();
  205. }
  206. };
  207. template <>
  208. struct strategy_converter<strategy::disjoint::segment_box>
  209. {
  210. static auto get(strategy::disjoint::segment_box const&)
  211. {
  212. return strategies::relate::cartesian<>();
  213. }
  214. };
  215. template <>
  216. struct strategy_converter<strategy::within::cartesian_box_box>
  217. {
  218. static auto get(strategy::within::cartesian_box_box const&)
  219. {
  220. return strategies::relate::cartesian<>();
  221. }
  222. };
  223. template <typename P1, typename P2, typename CalculationType>
  224. struct strategy_converter<strategy::within::cartesian_winding<P1, P2, CalculationType>>
  225. {
  226. static auto get(strategy::within::cartesian_winding<P1, P2, CalculationType> const& )
  227. {
  228. return strategies::relate::cartesian<CalculationType>();
  229. }
  230. };
  231. template <typename CalculationType>
  232. struct strategy_converter<strategy::intersection::cartesian_segments<CalculationType>>
  233. {
  234. static auto get(strategy::intersection::cartesian_segments<CalculationType> const& )
  235. {
  236. return strategies::relate::cartesian<CalculationType>();
  237. }
  238. };
  239. template <typename CalculationType>
  240. struct strategy_converter<strategy::within::cartesian_point_box_by_side<CalculationType>>
  241. {
  242. struct altered_strategy
  243. : strategies::relate::cartesian<CalculationType>
  244. {
  245. template <typename Geometry1, typename Geometry2>
  246. static auto covered_by(Geometry1 const&, Geometry2 const&,
  247. std::enable_if_t
  248. <
  249. util::is_pointlike<Geometry1>::value
  250. && util::is_box<Geometry2>::value
  251. > * = nullptr)
  252. {
  253. return strategy::covered_by::cartesian_point_box_by_side<CalculationType>();
  254. }
  255. template <typename Geometry1, typename Geometry2>
  256. static auto within(Geometry1 const&, Geometry2 const&,
  257. std::enable_if_t
  258. <
  259. util::is_pointlike<Geometry1>::value
  260. && util::is_box<Geometry2>::value
  261. > * = nullptr)
  262. {
  263. return strategy::within::cartesian_point_box_by_side<CalculationType>();
  264. }
  265. };
  266. static auto get(strategy::covered_by::cartesian_point_box_by_side<CalculationType> const&)
  267. {
  268. return altered_strategy();
  269. }
  270. static auto get(strategy::within::cartesian_point_box_by_side<CalculationType> const&)
  271. {
  272. return altered_strategy();
  273. }
  274. };
  275. template <typename CalculationType>
  276. struct strategy_converter<strategy::covered_by::cartesian_point_box_by_side<CalculationType>>
  277. : strategy_converter<strategy::within::cartesian_point_box_by_side<CalculationType>>
  278. {};
  279. template <typename P1, typename P2, typename CalculationType>
  280. struct strategy_converter<strategy::within::franklin<P1, P2, CalculationType>>
  281. {
  282. struct altered_strategy
  283. : strategies::relate::cartesian<CalculationType>
  284. {
  285. template <typename Geometry1, typename Geometry2>
  286. static auto relate(Geometry1 const&, Geometry2 const&,
  287. std::enable_if_t
  288. <
  289. util::is_pointlike<Geometry1>::value
  290. && ( util::is_linear<Geometry2>::value
  291. || util::is_polygonal<Geometry2>::value )
  292. > * = nullptr)
  293. {
  294. return strategy::within::franklin<void, void, CalculationType>();
  295. }
  296. };
  297. static auto get(strategy::within::franklin<P1, P2, CalculationType> const&)
  298. {
  299. return altered_strategy();
  300. }
  301. };
  302. template <typename P1, typename P2, typename CalculationType>
  303. struct strategy_converter<strategy::within::crossings_multiply<P1, P2, CalculationType>>
  304. {
  305. struct altered_strategy
  306. : strategies::relate::cartesian<CalculationType>
  307. {
  308. template <typename Geometry1, typename Geometry2>
  309. static auto relate(Geometry1 const&, Geometry2 const&,
  310. std::enable_if_t
  311. <
  312. util::is_pointlike<Geometry1>::value
  313. && ( util::is_linear<Geometry2>::value
  314. || util::is_polygonal<Geometry2>::value )
  315. > * = nullptr)
  316. {
  317. return strategy::within::crossings_multiply<void, void, CalculationType>();
  318. }
  319. };
  320. static auto get(strategy::within::crossings_multiply<P1, P2, CalculationType> const&)
  321. {
  322. return altered_strategy();
  323. }
  324. };
  325. // TEMP used in distance segment/box
  326. template <typename CalculationType>
  327. struct strategy_converter<strategy::side::side_by_triangle<CalculationType>>
  328. {
  329. static auto get(strategy::side::side_by_triangle<CalculationType> const&)
  330. {
  331. return strategies::relate::cartesian<CalculationType>();
  332. }
  333. };
  334. template <typename CalculationType>
  335. struct strategy_converter<strategy::side::side_robust<CalculationType>>
  336. {
  337. static auto get(strategy::side::side_robust<CalculationType> const&)
  338. {
  339. return strategies::relate::cartesian<CalculationType>();
  340. }
  341. };
  342. } // namespace services
  343. }} // namespace strategies::relate
  344. }} // namespace boost::geometry
  345. #endif // BOOST_GEOMETRY_STRATEGIES_RELATE_CARTESIAN_HPP