1 // Boost.Geometry (aka GGL, Generic Geometry Library)
3 // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
5 // This file was modified by Oracle on 2013, 2014, 2015, 2019.
6 // Modifications copyright (c) 2013-2019 Oracle and/or its affiliates.
8 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
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)
14 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_DE9IM_HPP
15 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_DE9IM_HPP
17 #include <boost/mpl/is_sequence.hpp>
18 #include <boost/mpl/push_back.hpp>
19 #include <boost/mpl/vector.hpp>
20 #include <boost/mpl/vector_c.hpp>
21 #include <boost/static_assert.hpp>
22 #include <boost/tuple/tuple.hpp>
24 #include <boost/geometry/algorithms/detail/relate/result.hpp>
25 #include <boost/geometry/core/topological_dimension.hpp>
26 #include <boost/geometry/core/tag.hpp>
28 #include <boost/geometry/util/tuples.hpp>
30 namespace boost { namespace geometry
37 \brief DE-9IM model intersection matrix.
39 \details This matrix can be used to express spatial relations as defined in
40 Dimensionally Extended 9-Intersection Model.
42 \qbk{[heading See also]}
43 \qbk{* [link geometry.reference.algorithms.relation relation]}
46 : public detail::relate::matrix<3, 3>
48 #ifdef DOXYGEN_INVOKED
51 \brief Initializes all of the matrix elements to F
55 \brief Subscript operator
56 \param index The index of the element
59 char operator[](std::size_t index) const;
61 \brief Returns the iterator to the first element
62 \return const RandomAccessIterator
64 const_iterator begin() const;
66 \brief Returns the iterator past the last element
67 \return const RandomAccessIterator
69 const_iterator end() const;
71 \brief Returns the number of elements
74 static std::size_t size();
76 \brief Returns raw pointer to elements
77 \return const pointer to array of elements
79 inline const char * data() const;
81 \brief Returns std::string containing elements
82 \return string containing elements
84 inline std::string str() const;
89 \brief DE-9IM model intersection mask.
91 \details This mask can be used to check spatial relations as defined in
92 Dimensionally Extended 9-Intersection Model.
94 \qbk{[heading See also]}
95 \qbk{* [link geometry.reference.algorithms.relate relate]}
98 : public detail::relate::mask<3, 3>
100 typedef detail::relate::mask<3, 3> base_type;
104 \brief The constructor.
105 \param code The mask pattern.
107 inline explicit mask(const char* code)
112 \brief The constructor.
113 \param code The mask pattern.
115 inline explicit mask(std::string const& code)
116 : base_type(code.c_str(), code.size())
123 \brief DE-9IM model intersection mask (static version).
125 \details This mask can be used to check spatial relations as defined in
126 Dimensionally Extended 9-Intersection Model.
127 \tparam II Interior/Interior intersection mask element
128 \tparam IB Interior/Boundary intersection mask element
129 \tparam IE Interior/Exterior intersection mask element
130 \tparam BI Boundary/Interior intersection mask element
131 \tparam BB Boundary/Boundary intersection mask element
132 \tparam BE Boundary/Exterior intersection mask element
133 \tparam EI Exterior/Interior intersection mask element
134 \tparam EB Exterior/Boundary intersection mask element
135 \tparam EE Exterior/Exterior intersection mask element
137 \qbk{[heading See also]}
138 \qbk{* [link geometry.reference.algorithms.relate relate]}
142 char II = '*', char IB = '*', char IE = '*',
143 char BI = '*', char BB = '*', char BE = '*',
144 char EI = '*', char EB = '*', char EE = '*'
147 : public detail::relate::static_mask
151 char, II, IB, IE, BI, BB, BE, EI, EB, EE
159 namespace detail { namespace de9im
162 // a small helper util for ORing static masks
168 bool IsSeq = boost::mpl::is_sequence<Seq>::value
172 typedef typename boost::mpl::push_back
179 template <typename Seq, typename T>
180 struct push_back<Seq, T, false>
183 }} // namespace detail::de9im
192 boost::tuples::cons<mask, boost::tuples::null_type>
194 operator||(mask const& m1, mask const& m2)
196 namespace bt = boost::tuples;
198 return bt::cons<mask, bt::cons<mask, bt::null_type> >
199 ( m1, bt::cons<mask, bt::null_type>(m2, bt::null_type()) );
202 template <typename Tail>
204 typename geometry::tuples::push_back
206 boost::tuples::cons<mask, Tail>,
209 operator||(boost::tuples::cons<mask, Tail> const& t, mask const& m)
211 namespace bt = boost::tuples;
213 return geometry::tuples::push_back
215 bt::cons<mask, Tail>,
222 char II1, char IB1, char IE1,
223 char BI1, char BB1, char BE1,
224 char EI1, char EB1, char EE1,
225 char II2, char IB2, char IE2,
226 char BI2, char BB2, char BE2,
227 char EI2, char EB2, char EE2
231 static_mask<II1, IB1, IE1, BI1, BB1, BE1, EI1, EB1, EE1>,
232 static_mask<II2, IB2, IE2, BI2, BB2, BE2, EI2, EB2, EE2>
234 operator||(static_mask<II1, IB1, IE1, BI1, BB1, BE1, EI1, EB1, EE1> const& ,
235 static_mask<II2, IB2, IE2, BI2, BB2, BE2, EI2, EB2, EE2> const& )
237 return boost::mpl::vector
239 static_mask<II1, IB1, IE1, BI1, BB1, BE1, EI1, EB1, EE1>,
240 static_mask<II2, IB2, IE2, BI2, BB2, BE2, EI2, EB2, EE2>
247 char II, char IB, char IE,
248 char BI, char BB, char BE,
249 char EI, char EB, char EE
252 typename detail::de9im::push_back
255 static_mask<II, IB, IE, BI, BB, BE, EI, EB, EE>
257 operator||(Seq const& ,
258 static_mask<II, IB, IE, BI, BB, BE, EI, EB, EE> const& )
260 return typename detail::de9im::push_back
263 static_mask<II, IB, IE, BI, BB, BE, EI, EB, EE>
270 #ifndef DOXYGEN_NO_DETAIL
271 namespace detail { namespace de9im
277 // 1. specialize for simplified masks if available
278 // e.g. for TOUCHES use 1 mask for A/A
279 // 2. Think about dimensions > 2 e.g. should TOUCHES be true
280 // if the interior of the Areal overlaps the boundary of the Volumetric
281 // like it's true for Linear/Areal
284 template <typename Geometry1, typename Geometry2>
285 struct static_mask_equals_type
287 typedef geometry::de9im::static_mask<'T', '*', 'F', '*', '*', 'F', 'F', 'F', '*'> type; // wikipedia
288 //typedef geometry::de9im::static_mask<'T', 'F', 'F', 'F', 'T', 'F', 'F', 'F', 'T'> type; // OGC
292 template <typename Geometry1, typename Geometry2>
293 struct static_mask_disjoint_type
295 typedef geometry::de9im::static_mask<'F', 'F', '*', 'F', 'F', '*', '*', '*', '*'> type;
303 std::size_t Dim1 = geometry::topological_dimension<Geometry1>::value,
304 std::size_t Dim2 = geometry::topological_dimension<Geometry2>::value
306 struct static_mask_touches_impl
308 typedef boost::mpl::vector
310 geometry::de9im::static_mask<'F', 'T', '*', '*', '*', '*', '*', '*', '*'>,
311 geometry::de9im::static_mask<'F', '*', '*', 'T', '*', '*', '*', '*', '*'>,
312 geometry::de9im::static_mask<'F', '*', '*', '*', 'T', '*', '*', '*', '*'>
315 // According to OGC, doesn't apply to P/P
316 // Using the above mask the result would be always false
317 template <typename Geometry1, typename Geometry2>
318 struct static_mask_touches_impl<Geometry1, Geometry2, 0, 0>
320 typedef geometry::detail::relate::false_mask type;
323 template <typename Geometry1, typename Geometry2>
324 struct static_mask_touches_type
325 : static_mask_touches_impl<Geometry1, Geometry2>
329 template <typename Geometry1, typename Geometry2>
330 struct static_mask_within_type
332 typedef geometry::de9im::static_mask<'T', '*', 'F', '*', '*', 'F', '*', '*', '*'> type;
335 // COVERED_BY (non OGC)
336 template <typename Geometry1, typename Geometry2>
337 struct static_mask_covered_by_type
339 typedef boost::mpl::vector
341 geometry::de9im::static_mask<'T', '*', 'F', '*', '*', 'F', '*', '*', '*'>,
342 geometry::de9im::static_mask<'*', 'T', 'F', '*', '*', 'F', '*', '*', '*'>,
343 geometry::de9im::static_mask<'*', '*', 'F', 'T', '*', 'F', '*', '*', '*'>,
344 geometry::de9im::static_mask<'*', '*', 'F', '*', 'T', 'F', '*', '*', '*'>
349 // dim(G1) < dim(G2) - P/L P/A L/A
354 std::size_t Dim1 = geometry::topological_dimension<Geometry1>::value,
355 std::size_t Dim2 = geometry::topological_dimension<Geometry2>::value,
356 bool D1LessD2 = (Dim1 < Dim2)
358 struct static_mask_crosses_impl
360 typedef geometry::de9im::static_mask<'T', '*', 'T', '*', '*', '*', '*', '*', '*'> type;
362 // TODO: I'm not sure if this one below should be available!
363 // dim(G1) > dim(G2) - L/P A/P A/L
366 typename Geometry1, typename Geometry2, std::size_t Dim1, std::size_t Dim2
368 struct static_mask_crosses_impl<Geometry1, Geometry2, Dim1, Dim2, false>
370 typedef geometry::de9im::static_mask<'T', '*', '*', '*', '*', '*', 'T', '*', '*'> type;
372 // dim(G1) == dim(G2) - P/P A/A
375 typename Geometry1, typename Geometry2, std::size_t Dim
377 struct static_mask_crosses_impl<Geometry1, Geometry2, Dim, Dim, false>
379 typedef geometry::detail::relate::false_mask type;
381 // dim(G1) == 1 && dim(G2) == 1 - L/L
382 template <typename Geometry1, typename Geometry2>
383 struct static_mask_crosses_impl<Geometry1, Geometry2, 1, 1, false>
385 typedef geometry::de9im::static_mask<'0', '*', '*', '*', '*', '*', '*', '*', '*'> type;
388 template <typename Geometry1, typename Geometry2>
389 struct static_mask_crosses_type
390 : static_mask_crosses_impl<Geometry1, Geometry2>
395 // dim(G1) != dim(G2) - NOT P/P, L/L, A/A
400 std::size_t Dim1 = geometry::topological_dimension<Geometry1>::value,
401 std::size_t Dim2 = geometry::topological_dimension<Geometry2>::value
403 struct static_mask_overlaps_impl
405 typedef geometry::detail::relate::false_mask type;
407 // dim(G1) == D && dim(G2) == D - P/P A/A
408 template <typename Geometry1, typename Geometry2, std::size_t Dim>
409 struct static_mask_overlaps_impl<Geometry1, Geometry2, Dim, Dim>
411 typedef geometry::de9im::static_mask<'T', '*', 'T', '*', '*', '*', 'T', '*', '*'> type;
413 // dim(G1) == 1 && dim(G2) == 1 - L/L
414 template <typename Geometry1, typename Geometry2>
415 struct static_mask_overlaps_impl<Geometry1, Geometry2, 1, 1>
417 typedef geometry::de9im::static_mask<'1', '*', 'T', '*', '*', '*', 'T', '*', '*'> type;
420 template <typename Geometry1, typename Geometry2>
421 struct static_mask_overlaps_type
422 : static_mask_overlaps_impl<Geometry1, Geometry2>
425 }} // namespace detail::de9im
426 #endif // DOXYGEN_NO_DETAIL
429 }} // namespace boost::geometry
431 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_DE9IM_HPP