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