de9im.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
  3. // Copyright (c) 2022 Adam Wulkiewicz, Lodz, Poland.
  4. // This file was modified by Oracle on 2013-2022.
  5. // Modifications copyright (c) 2013-2022 Oracle and/or its affiliates.
  6. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  7. // Use, modification and distribution is subject to the Boost Software License,
  8. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_DE9IM_HPP
  11. #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_DE9IM_HPP
  12. #include <tuple>
  13. #include <boost/geometry/algorithms/detail/relate/result.hpp>
  14. #include <boost/geometry/core/topological_dimension.hpp>
  15. #include <boost/geometry/core/tag.hpp>
  16. #include <boost/geometry/util/sequence.hpp>
  17. #include <boost/geometry/util/tuples.hpp>
  18. namespace boost { namespace geometry
  19. {
  20. namespace de9im
  21. {
  22. /*!
  23. \brief DE-9IM model intersection matrix.
  24. \ingroup de9im
  25. \details This matrix can be used to express spatial relations as defined in
  26. Dimensionally Extended 9-Intersection Model.
  27. \qbk{[heading See also]}
  28. \qbk{* [link geometry.reference.algorithms.relation relation]}
  29. */
  30. class matrix
  31. : public detail::relate::matrix<3, 3>
  32. {
  33. #ifdef DOXYGEN_INVOKED
  34. public:
  35. /*!
  36. \brief Initializes all of the matrix elements to F
  37. */
  38. matrix();
  39. /*!
  40. \brief Subscript operator
  41. \param index The index of the element
  42. \return The element
  43. */
  44. char operator[](std::size_t index) const;
  45. /*!
  46. \brief Returns the iterator to the first element
  47. \return const RandomAccessIterator
  48. */
  49. const_iterator begin() const;
  50. /*!
  51. \brief Returns the iterator past the last element
  52. \return const RandomAccessIterator
  53. */
  54. const_iterator end() const;
  55. /*!
  56. \brief Returns the number of elements
  57. \return 9
  58. */
  59. static std::size_t size();
  60. /*!
  61. \brief Returns raw pointer to elements
  62. \return const pointer to array of elements
  63. */
  64. inline const char * data() const;
  65. /*!
  66. \brief Returns std::string containing elements
  67. \return string containing elements
  68. */
  69. inline std::string str() const;
  70. #endif
  71. };
  72. /*!
  73. \brief DE-9IM model intersection mask.
  74. \ingroup de9im
  75. \details This mask can be used to check spatial relations as defined in
  76. Dimensionally Extended 9-Intersection Model.
  77. \qbk{[heading See also]}
  78. \qbk{* [link geometry.reference.algorithms.relate relate]}
  79. */
  80. class mask
  81. : public detail::relate::mask<3, 3>
  82. {
  83. typedef detail::relate::mask<3, 3> base_type;
  84. public:
  85. /*!
  86. \brief The constructor.
  87. \param code The mask pattern.
  88. */
  89. inline explicit mask(const char* code)
  90. : base_type(code)
  91. {}
  92. /*!
  93. \brief The constructor.
  94. \param code The mask pattern.
  95. */
  96. inline explicit mask(std::string const& code)
  97. : base_type(code.c_str(), code.size())
  98. {}
  99. };
  100. // static_mask
  101. /*!
  102. \brief DE-9IM model intersection mask (static version).
  103. \ingroup de9im
  104. \details This mask can be used to check spatial relations as defined in
  105. Dimensionally Extended 9-Intersection Model.
  106. \tparam II Interior/Interior intersection mask element
  107. \tparam IB Interior/Boundary intersection mask element
  108. \tparam IE Interior/Exterior intersection mask element
  109. \tparam BI Boundary/Interior intersection mask element
  110. \tparam BB Boundary/Boundary intersection mask element
  111. \tparam BE Boundary/Exterior intersection mask element
  112. \tparam EI Exterior/Interior intersection mask element
  113. \tparam EB Exterior/Boundary intersection mask element
  114. \tparam EE Exterior/Exterior intersection mask element
  115. \qbk{[heading See also]}
  116. \qbk{* [link geometry.reference.algorithms.relate relate]}
  117. */
  118. template
  119. <
  120. char II = '*', char IB = '*', char IE = '*',
  121. char BI = '*', char BB = '*', char BE = '*',
  122. char EI = '*', char EB = '*', char EE = '*'
  123. >
  124. class static_mask
  125. : public detail::relate::static_mask
  126. <
  127. std::integer_sequence
  128. <
  129. char, II, IB, IE, BI, BB, BE, EI, EB, EE
  130. >,
  131. 3, 3
  132. >
  133. {};
  134. inline
  135. std::tuple<mask, mask>
  136. operator||(mask const& m1, mask const& m2)
  137. {
  138. return std::tuple<mask, mask>(m1, m2);
  139. }
  140. template <typename ...Masks>
  141. inline
  142. std::tuple<Masks..., mask>
  143. operator||(std::tuple<Masks...> const& t, mask const& m)
  144. {
  145. return geometry::tuples::push_back
  146. <
  147. std::tuple<Masks...>,
  148. mask
  149. >::apply(t, m);
  150. }
  151. template
  152. <
  153. char II1, char IB1, char IE1,
  154. char BI1, char BB1, char BE1,
  155. char EI1, char EB1, char EE1,
  156. char II2, char IB2, char IE2,
  157. char BI2, char BB2, char BE2,
  158. char EI2, char EB2, char EE2
  159. >
  160. inline
  161. util::type_sequence
  162. <
  163. static_mask<II1, IB1, IE1, BI1, BB1, BE1, EI1, EB1, EE1>,
  164. static_mask<II2, IB2, IE2, BI2, BB2, BE2, EI2, EB2, EE2>
  165. >
  166. operator||(static_mask<II1, IB1, IE1, BI1, BB1, BE1, EI1, EB1, EE1> const& ,
  167. static_mask<II2, IB2, IE2, BI2, BB2, BE2, EI2, EB2, EE2> const& )
  168. {
  169. return util::type_sequence
  170. <
  171. static_mask<II1, IB1, IE1, BI1, BB1, BE1, EI1, EB1, EE1>,
  172. static_mask<II2, IB2, IE2, BI2, BB2, BE2, EI2, EB2, EE2>
  173. >();
  174. }
  175. template
  176. <
  177. typename ...StaticMasks,
  178. char II, char IB, char IE,
  179. char BI, char BB, char BE,
  180. char EI, char EB, char EE
  181. >
  182. inline
  183. util::type_sequence
  184. <
  185. StaticMasks...,
  186. static_mask<II, IB, IE, BI, BB, BE, EI, EB, EE>
  187. >
  188. operator||(util::type_sequence<StaticMasks...> const& ,
  189. static_mask<II, IB, IE, BI, BB, BE, EI, EB, EE> const& )
  190. {
  191. return util::type_sequence
  192. <
  193. StaticMasks...,
  194. static_mask<II, IB, IE, BI, BB, BE, EI, EB, EE>
  195. >();
  196. }
  197. } // namespace de9im
  198. #ifndef DOXYGEN_NO_DETAIL
  199. namespace detail { namespace de9im
  200. {
  201. // PREDEFINED MASKS
  202. // TODO:
  203. // 1. specialize for simplified masks if available
  204. // e.g. for TOUCHES use 1 mask for A/A
  205. // 2. Think about dimensions > 2 e.g. should TOUCHES be true
  206. // if the interior of the Areal overlaps the boundary of the Volumetric
  207. // like it's true for Linear/Areal
  208. // EQUALS
  209. template <typename Geometry1, typename Geometry2>
  210. struct static_mask_equals_type
  211. {
  212. typedef geometry::de9im::static_mask<'T', '*', 'F', '*', '*', 'F', 'F', 'F', '*'> type; // wikipedia
  213. //typedef geometry::de9im::static_mask<'T', 'F', 'F', 'F', 'T', 'F', 'F', 'F', 'T'> type; // OGC
  214. };
  215. // DISJOINT
  216. template <typename Geometry1, typename Geometry2>
  217. struct static_mask_disjoint_type
  218. {
  219. typedef geometry::de9im::static_mask<'F', 'F', '*', 'F', 'F', '*', '*', '*', '*'> type;
  220. };
  221. // TOUCHES - NOT P/P
  222. template
  223. <
  224. typename Geometry1,
  225. typename Geometry2,
  226. std::size_t Dim1 = geometry::topological_dimension<Geometry1>::value,
  227. std::size_t Dim2 = geometry::topological_dimension<Geometry2>::value
  228. >
  229. struct static_mask_touches_impl
  230. {
  231. typedef util::type_sequence
  232. <
  233. geometry::de9im::static_mask<'F', 'T', '*', '*', '*', '*', '*', '*', '*'>,
  234. geometry::de9im::static_mask<'F', '*', '*', 'T', '*', '*', '*', '*', '*'>,
  235. geometry::de9im::static_mask<'F', '*', '*', '*', 'T', '*', '*', '*', '*'>
  236. > type;
  237. };
  238. // According to OGC, doesn't apply to P/P
  239. // Using the above mask the result would be always false
  240. template <typename Geometry1, typename Geometry2>
  241. struct static_mask_touches_impl<Geometry1, Geometry2, 0, 0>
  242. {
  243. typedef geometry::detail::relate::false_mask type;
  244. };
  245. template <typename Geometry1, typename Geometry2>
  246. struct static_mask_touches_not_pp_type
  247. : static_mask_touches_impl<Geometry1, Geometry2, 2, 2> // dummy dimensions
  248. {};
  249. template <typename Geometry1, typename Geometry2>
  250. struct static_mask_touches_type
  251. : static_mask_touches_impl<Geometry1, Geometry2>
  252. {};
  253. // WITHIN
  254. template <typename Geometry1, typename Geometry2>
  255. struct static_mask_within_type
  256. {
  257. typedef geometry::de9im::static_mask<'T', '*', 'F', '*', '*', 'F', '*', '*', '*'> type;
  258. };
  259. // COVERED_BY (non OGC)
  260. template <typename Geometry1, typename Geometry2>
  261. struct static_mask_covered_by_type
  262. {
  263. typedef util::type_sequence
  264. <
  265. geometry::de9im::static_mask<'T', '*', 'F', '*', '*', 'F', '*', '*', '*'>,
  266. geometry::de9im::static_mask<'*', 'T', 'F', '*', '*', 'F', '*', '*', '*'>,
  267. geometry::de9im::static_mask<'*', '*', 'F', 'T', '*', 'F', '*', '*', '*'>,
  268. geometry::de9im::static_mask<'*', '*', 'F', '*', 'T', 'F', '*', '*', '*'>
  269. > type;
  270. };
  271. // CROSSES
  272. // dim(G1) < dim(G2) - P/L P/A L/A
  273. template
  274. <
  275. typename Geometry1,
  276. typename Geometry2,
  277. std::size_t Dim1 = geometry::topological_dimension<Geometry1>::value,
  278. std::size_t Dim2 = geometry::topological_dimension<Geometry2>::value,
  279. bool D1LessD2 = (Dim1 < Dim2)
  280. >
  281. struct static_mask_crosses_impl
  282. {
  283. typedef geometry::de9im::static_mask<'T', '*', 'T', '*', '*', '*', '*', '*', '*'> type;
  284. };
  285. // TODO: I'm not sure if this one below should be available!
  286. // dim(G1) > dim(G2) - L/P A/P A/L
  287. template
  288. <
  289. typename Geometry1, typename Geometry2, std::size_t Dim1, std::size_t Dim2
  290. >
  291. struct static_mask_crosses_impl<Geometry1, Geometry2, Dim1, Dim2, false>
  292. {
  293. typedef geometry::de9im::static_mask<'T', '*', '*', '*', '*', '*', 'T', '*', '*'> type;
  294. };
  295. // dim(G1) == dim(G2) - P/P A/A
  296. template
  297. <
  298. typename Geometry1, typename Geometry2, std::size_t Dim
  299. >
  300. struct static_mask_crosses_impl<Geometry1, Geometry2, Dim, Dim, false>
  301. {
  302. typedef geometry::detail::relate::false_mask type;
  303. };
  304. // dim(G1) == 1 && dim(G2) == 1 - L/L
  305. template <typename Geometry1, typename Geometry2>
  306. struct static_mask_crosses_impl<Geometry1, Geometry2, 1, 1, false>
  307. {
  308. typedef geometry::de9im::static_mask<'0', '*', '*', '*', '*', '*', '*', '*', '*'> type;
  309. };
  310. template <typename Geometry1, typename Geometry2>
  311. struct static_mask_crosses_type
  312. : static_mask_crosses_impl<Geometry1, Geometry2>
  313. {};
  314. template <typename Geometry1, typename Geometry2>
  315. struct static_mask_crosses_d1_le_d2_type // specific dimensions are not important here
  316. : static_mask_crosses_impl<Geometry1, Geometry2, 0, 1>
  317. {};
  318. template <typename Geometry1, typename Geometry2>
  319. struct static_mask_crosses_d2_le_d1_type // specific dimensions are not important here
  320. : static_mask_crosses_impl<Geometry1, Geometry2, 1, 0>
  321. {};
  322. template <typename Geometry1, typename Geometry2>
  323. struct static_mask_crosses_d1_1_d2_1_type
  324. : static_mask_crosses_impl<Geometry1, Geometry2, 1, 1>
  325. {};
  326. // OVERLAPS
  327. // dim(G1) != dim(G2) - NOT P/P, L/L, A/A
  328. template
  329. <
  330. typename Geometry1,
  331. typename Geometry2,
  332. std::size_t Dim1 = geometry::topological_dimension<Geometry1>::value,
  333. std::size_t Dim2 = geometry::topological_dimension<Geometry2>::value
  334. >
  335. struct static_mask_overlaps_impl
  336. {
  337. typedef geometry::detail::relate::false_mask type;
  338. };
  339. // dim(G1) == D && dim(G2) == D - P/P A/A
  340. template <typename Geometry1, typename Geometry2, std::size_t Dim>
  341. struct static_mask_overlaps_impl<Geometry1, Geometry2, Dim, Dim>
  342. {
  343. typedef geometry::de9im::static_mask<'T', '*', 'T', '*', '*', '*', 'T', '*', '*'> type;
  344. };
  345. // dim(G1) == 1 && dim(G2) == 1 - L/L
  346. template <typename Geometry1, typename Geometry2>
  347. struct static_mask_overlaps_impl<Geometry1, Geometry2, 1, 1>
  348. {
  349. typedef geometry::de9im::static_mask<'1', '*', 'T', '*', '*', '*', 'T', '*', '*'> type;
  350. };
  351. template <typename Geometry1, typename Geometry2>
  352. struct static_mask_overlaps_type
  353. : static_mask_overlaps_impl<Geometry1, Geometry2>
  354. {};
  355. template <typename Geometry1, typename Geometry2>
  356. struct static_mask_overlaps_d1_eq_d2_type
  357. : static_mask_overlaps_impl<Geometry1, Geometry2, 2, 2>
  358. {};
  359. template <typename Geometry1, typename Geometry2>
  360. struct static_mask_overlaps_d1_1_d2_1_type
  361. : static_mask_overlaps_impl<Geometry1, Geometry2, 1, 1>
  362. {};
  363. }} // namespace detail::de9im
  364. #endif // DOXYGEN_NO_DETAIL
  365. }} // namespace boost::geometry
  366. #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_DE9IM_HPP