cartesian.hpp 14 KB

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