1 // Boost.Geometry (aka GGL, Generic Geometry Library)
3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
5 // This file was modified by Oracle on 2013, 2014.
6 // Modifications copyright (c) 2013, 2014 Oracle and/or its affiliates.
8 // Use, modification and distribution is subject to the Boost Software License,
9 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
10 // http://www.boost.org/LICENSE_1_0.txt)
12 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
14 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_RESULT_HPP
15 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_RESULT_HPP
17 #include <boost/tuple/tuple.hpp>
19 #include <boost/mpl/is_sequence.hpp>
20 #include <boost/mpl/begin.hpp>
21 #include <boost/mpl/end.hpp>
22 #include <boost/mpl/next.hpp>
23 #include <boost/mpl/at.hpp>
24 #include <boost/mpl/vector_c.hpp>
26 #include <boost/geometry/core/topological_dimension.hpp>
28 // TEMP - move this header to geometry/detail
29 #include <boost/geometry/index/detail/tuples.hpp>
31 namespace boost { namespace geometry {
33 #ifndef DOXYGEN_NO_DETAIL
34 namespace detail { namespace relate {
36 enum field { interior = 0, boundary = 1, exterior = 2 };
38 // TODO: IF THE RESULT IS UPDATED WITH THE MAX POSSIBLE VALUE FOR SOME PAIR OF GEOEMTRIES
39 // THE VALUE ALREADY STORED MUSN'T BE CHECKED
40 // update() calls chould be replaced with set() in those cases
41 // but for safety reasons (STATIC_ASSERT) we should check if parameter D is valid and set() doesn't do that
42 // so some additional function could be added, e.g. set_dim()
48 template <std::size_t Width>
51 BOOST_STATIC_ASSERT(Width == 2 || Width == 3);
55 static const std::size_t size = Width * Width;
59 ::memset(m_array, 'F', size);
62 template <field F1, field F2>
63 inline char get() const
65 static const bool in_bounds = F1 * Width + F2 < size;
66 return get_dispatch<F1, F2>(integral_constant<bool, in_bounds>());
69 template <field F1, field F2, char V>
72 static const bool in_bounds = F1 * Width + F2 < size;
73 set_dispatch<F1, F2, V>(integral_constant<bool, in_bounds>());
76 template <field F1, field F2, char D>
79 static const bool in_bounds = F1 * Width + F2 < size;
80 update_dispatch<F1, F2, D>(integral_constant<bool, in_bounds>());
83 inline const char * data() const
89 template <field F1, field F2>
90 inline char get_dispatch(integral_constant<bool, true>) const
92 return m_array[F1 * Width + F2];
94 template <field F1, field F2>
95 inline char get_dispatch(integral_constant<bool, false>) const
100 template <field F1, field F2, char V>
101 inline void set_dispatch(integral_constant<bool, true>)
103 BOOST_STATIC_ASSERT(('0' <= V && V <= '9') || V == 'T' || V == 'F');
104 m_array[F1 * Width + F2] = V;
106 template <field F1, field F2, char V>
107 inline void set_dispatch(integral_constant<bool, false>)
110 template <field F1, field F2, char D>
111 inline void update_dispatch(integral_constant<bool, true>)
113 BOOST_STATIC_ASSERT('0' <= D && D <= '9');
114 char c = m_array[F1 * Width + F2];
115 if ( D > c || c > '9')
116 m_array[F1 * Width + F2] = D;
118 template <field F1, field F2, char D>
119 inline void update_dispatch(integral_constant<bool, false>)
125 // TODO add EnableDimensions parameter?
132 template <typename MatrixOrMask>
134 : not_implemented<MatrixOrMask>
138 struct matrix_width<matrix9>
140 static const std::size_t value = 3;
145 template <typename Matrix>
147 : private matrix<matrix_width<Matrix>::value>
149 typedef matrix<matrix_width<Matrix>::value> base_t;
152 typedef std::string result_type;
154 static const bool interrupt = false;
156 matrix_handler(Matrix const&)
159 result_type result() const
161 return std::string(this->data(),
162 this->data() + base_t::size);
165 template <field F1, field F2, char D>
166 inline bool may_update() const
168 BOOST_STATIC_ASSERT('0' <= D && D <= '9');
170 char const c = static_cast<base_t const&>(*this).template get<F1, F2>();
171 return D > c || c > '9';
174 //template <field F1, field F2>
175 //inline char get() const
177 // return static_cast<base_t const&>(*this).template get<F1, F2>();
180 template <field F1, field F2, char V>
183 static_cast<base_t&>(*this).template set<F1, F2, V>();
186 template <field F1, field F2, char D>
189 static_cast<base_t&>(*this).template update<F1, F2, D>();
200 static const std::size_t width = 3; // TEMP
202 inline mask9(std::string const& de9im_mask)
204 // TODO: throw an exception here?
205 BOOST_ASSERT(de9im_mask.size() == 9);
206 ::memcpy(m_mask, de9im_mask.c_str(), 9);
209 template <field F1, field F2>
210 inline char get() const
212 return m_mask[F1 * 3 + F2];
221 template <typename Mask, bool InterruptEnabled>
222 struct interrupt_dispatch
224 template <field F1, field F2, char V>
225 static inline bool apply(Mask const&)
231 template <typename Mask>
232 struct interrupt_dispatch<Mask, true>
234 template <field F1, field F2, char V>
235 static inline bool apply(Mask const& mask)
237 char m = mask.template get<F1, F2>();
242 static inline bool check(char m)
244 if ( V >= '0' && V <= '9' )
246 return m == 'F' || ( m < V && m >= '0' && m <= '9' );
256 template <typename Masks, int I = 0, int N = boost::tuples::length<Masks>::value>
257 struct interrupt_dispatch_tuple
259 template <field F1, field F2, char V>
260 static inline bool apply(Masks const& masks)
262 typedef typename boost::tuples::element<I, Masks>::type mask_type;
263 mask_type const& mask = boost::get<I>(masks);
264 return interrupt_dispatch<mask_type, true>::template apply<F1, F2, V>(mask)
265 && interrupt_dispatch_tuple<Masks, I+1>::template apply<F1, F2, V>(masks);
269 template <typename Masks, int N>
270 struct interrupt_dispatch_tuple<Masks, N, N>
272 template <field F1, field F2, char V>
273 static inline bool apply(Masks const& )
279 template <typename T0, typename T1, typename T2, typename T3, typename T4,
280 typename T5, typename T6, typename T7, typename T8, typename T9>
281 struct interrupt_dispatch<boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>, true>
283 typedef boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> mask_type;
285 template <field F1, field F2, char V>
286 static inline bool apply(mask_type const& mask)
288 return interrupt_dispatch_tuple<mask_type>::template apply<F1, F2, V>(mask);
292 template <typename Head, typename Tail>
293 struct interrupt_dispatch<boost::tuples::cons<Head, Tail>, true>
295 typedef boost::tuples::cons<Head, Tail> mask_type;
297 template <field F1, field F2, char V>
298 static inline bool apply(mask_type const& mask)
300 return interrupt_dispatch_tuple<mask_type>::template apply<F1, F2, V>(mask);
304 template <field F1, field F2, char V, bool InterruptEnabled, typename Mask>
305 inline bool interrupt(Mask const& mask)
307 return interrupt_dispatch<Mask, InterruptEnabled>
308 ::template apply<F1, F2, V>(mask);
313 template <typename Mask>
314 struct may_update_dispatch
316 template <field F1, field F2, char D, typename Matrix>
317 static inline bool apply(Mask const& mask, Matrix const& matrix)
319 BOOST_STATIC_ASSERT('0' <= D && D <= '9');
321 char const m = mask.template get<F1, F2>();
329 char const c = matrix.template get<F1, F2>();
330 return c == 'F'; // if it's T or between 0 and 9, the result will be the same
332 else if ( m >= '0' && m <= '9' )
334 char const c = matrix.template get<F1, F2>();
335 return D > c || c > '9';
342 template <typename Masks, int I = 0, int N = boost::tuples::length<Masks>::value>
343 struct may_update_dispatch_tuple
345 template <field F1, field F2, char D, typename Matrix>
346 static inline bool apply(Masks const& masks, Matrix const& matrix)
348 typedef typename boost::tuples::element<I, Masks>::type mask_type;
349 mask_type const& mask = boost::get<I>(masks);
350 return may_update_dispatch<mask_type>::template apply<F1, F2, D>(mask, matrix)
351 || may_update_dispatch_tuple<Masks, I+1>::template apply<F1, F2, D>(masks, matrix);
355 template <typename Masks, int N>
356 struct may_update_dispatch_tuple<Masks, N, N>
358 template <field F1, field F2, char D, typename Matrix>
359 static inline bool apply(Masks const& , Matrix const& )
365 template <typename T0, typename T1, typename T2, typename T3, typename T4,
366 typename T5, typename T6, typename T7, typename T8, typename T9>
367 struct may_update_dispatch< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >
369 typedef boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> mask_type;
371 template <field F1, field F2, char D, typename Matrix>
372 static inline bool apply(mask_type const& mask, Matrix const& matrix)
374 return may_update_dispatch_tuple<mask_type>::template apply<F1, F2, D>(mask, matrix);
378 template <typename Head, typename Tail>
379 struct may_update_dispatch< boost::tuples::cons<Head, Tail> >
381 typedef boost::tuples::cons<Head, Tail> mask_type;
383 template <field F1, field F2, char D, typename Matrix>
384 static inline bool apply(mask_type const& mask, Matrix const& matrix)
386 return may_update_dispatch_tuple<mask_type>::template apply<F1, F2, D>(mask, matrix);
390 template <field F1, field F2, char D, typename Mask, typename Matrix>
391 inline bool may_update(Mask const& mask, Matrix const& matrix)
393 return may_update_dispatch<Mask>
394 ::template apply<F1, F2, D>(mask, matrix);
399 template <typename Mask>
400 struct check_dispatch
402 template <typename Matrix>
403 static inline bool apply(Mask const& mask, Matrix const& matrix)
405 return per_one<interior, interior>(mask, matrix)
406 && per_one<interior, boundary>(mask, matrix)
407 && per_one<interior, exterior>(mask, matrix)
408 && per_one<boundary, interior>(mask, matrix)
409 && per_one<boundary, boundary>(mask, matrix)
410 && per_one<boundary, exterior>(mask, matrix)
411 && per_one<exterior, interior>(mask, matrix)
412 && per_one<exterior, boundary>(mask, matrix)
413 && per_one<exterior, exterior>(mask, matrix);
416 template <field F1, field F2, typename Matrix>
417 static inline bool per_one(Mask const& mask, Matrix const& matrix)
419 const char mask_el = mask.template get<F1, F2>();
420 const char el = matrix.template get<F1, F2>();
422 if ( mask_el == 'F' )
426 else if ( mask_el == 'T' )
428 return el == 'T' || ( el >= '0' && el <= '9' );
430 else if ( mask_el >= '0' && mask_el <= '9' )
432 return el == mask_el;
439 template <typename Masks, int I = 0, int N = boost::tuples::length<Masks>::value>
440 struct check_dispatch_tuple
442 template <typename Matrix>
443 static inline bool apply(Masks const& masks, Matrix const& matrix)
445 typedef typename boost::tuples::element<I, Masks>::type mask_type;
446 mask_type const& mask = boost::get<I>(masks);
447 return check_dispatch<mask_type>::apply(mask, matrix)
448 || check_dispatch_tuple<Masks, I+1>::apply(masks, matrix);
452 template <typename Masks, int N>
453 struct check_dispatch_tuple<Masks, N, N>
455 template <typename Matrix>
456 static inline bool apply(Masks const&, Matrix const&)
462 template <typename T0, typename T1, typename T2, typename T3, typename T4,
463 typename T5, typename T6, typename T7, typename T8, typename T9>
464 struct check_dispatch< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >
466 typedef boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> mask_type;
468 template <typename Matrix>
469 static inline bool apply(mask_type const& mask, Matrix const& matrix)
471 return check_dispatch_tuple<mask_type>::apply(mask, matrix);
475 template <typename Head, typename Tail>
476 struct check_dispatch< boost::tuples::cons<Head, Tail> >
478 typedef boost::tuples::cons<Head, Tail> mask_type;
480 template <typename Matrix>
481 static inline bool apply(mask_type const& mask, Matrix const& matrix)
483 return check_dispatch_tuple<mask_type>::apply(mask, matrix);
487 template <typename Mask, typename Matrix>
488 inline bool check(Mask const& mask, Matrix const& matrix)
490 return check_dispatch<Mask>::apply(mask, matrix);
496 struct matrix_width<mask9>
498 static const std::size_t value = 3;
501 template <typename Tuple,
503 int N = boost::tuples::length<Tuple>::value>
504 struct matrix_width_tuple
506 static const std::size_t
507 current = matrix_width<typename boost::tuples::element<I, Tuple>::type>::value;
508 static const std::size_t
509 next = matrix_width_tuple<Tuple, I+1>::value;
511 static const std::size_t
512 value = current > next ? current : next;
515 template <typename Tuple, int N>
516 struct matrix_width_tuple<Tuple, N, N>
518 static const std::size_t value = 0;
521 template <typename Head, typename Tail>
522 struct matrix_width< boost::tuples::cons<Head, Tail> >
524 static const std::size_t
525 value = matrix_width_tuple< boost::tuples::cons<Head, Tail> >::value;
530 template <typename Mask, bool Interrupt>
532 : private matrix<matrix_width<Mask>::value>
534 typedef matrix<matrix_width<Mask>::value> base_t;
537 typedef bool result_type;
541 inline mask_handler(Mask const& m)
546 result_type result() const
549 && check(m_mask, static_cast<base_t const&>(*this));
552 template <field F1, field F2, char D>
553 inline bool may_update() const
555 return detail::relate::may_update<F1, F2, D>(
556 m_mask, static_cast<base_t const&>(*this)
560 //template <field F1, field F2>
561 //inline char get() const
563 // return static_cast<base_t const&>(*this).template get<F1, F2>();
566 template <field F1, field F2, char V>
569 if ( relate::interrupt<F1, F2, V, Interrupt>(m_mask) )
575 base_t::template set<F1, F2, V>();
579 template <field F1, field F2, char V>
582 if ( relate::interrupt<F1, F2, V, Interrupt>(m_mask) )
588 base_t::template update<F1, F2, V>();
600 template <char II, char IB, char IE,
601 char BI, char BB, char BE,
602 char EI, char EB, char EE>
605 typedef boost::mpl::vector_c
607 char, II, IB, IE, BI, BB, BE, EI, EB, EE
611 template <field F1, field F2>
614 BOOST_STATIC_ASSERT(F1 * 3 + F2 < boost::mpl::size<vector_type>::value);
616 static const char value
617 = boost::mpl::at_c<vector_type, F1 * 3 + F2>::type::value;
621 // static_should_handle_element
623 template <typename StaticMask, field F1, field F2, bool IsSequence>
624 struct static_should_handle_element_dispatch
626 static const char mask_el = StaticMask::template get<F1, F2>::value;
627 static const bool value = mask_el == 'F'
629 || ( mask_el >= '0' && mask_el <= '9' );
632 template <typename First, typename Last, field F1, field F2>
633 struct static_should_handle_element_sequence
635 typedef typename boost::mpl::deref<First>::type StaticMask;
637 static const bool value
638 = static_should_handle_element_dispatch
642 boost::mpl::is_sequence<StaticMask>::value
644 || static_should_handle_element_sequence
646 typename boost::mpl::next<First>::type,
652 template <typename Last, field F1, field F2>
653 struct static_should_handle_element_sequence<Last, Last, F1, F2>
655 static const bool value = false;
658 template <typename StaticMask, field F1, field F2>
659 struct static_should_handle_element_dispatch<StaticMask, F1, F2, true>
661 static const bool value
662 = static_should_handle_element_sequence
664 typename boost::mpl::begin<StaticMask>::type,
665 typename boost::mpl::end<StaticMask>::type,
670 template <typename StaticMask, field F1, field F2>
671 struct static_should_handle_element
673 static const bool value
674 = static_should_handle_element_dispatch
678 boost::mpl::is_sequence<StaticMask>::value
684 template <typename StaticMask, char V, field F1, field F2, bool InterruptEnabled, bool IsSequence>
685 struct static_interrupt_dispatch
687 static const bool value = false;
690 template <typename StaticMask, char V, field F1, field F2, bool IsSequence>
691 struct static_interrupt_dispatch<StaticMask, V, F1, F2, true, IsSequence>
693 static const char mask_el = StaticMask::template get<F1, F2>::value;
695 static const bool value
696 = ( V >= '0' && V <= '9' ) ?
697 ( mask_el == 'F' || ( mask_el < V && mask_el >= '0' && mask_el <= '9' ) ) :
698 ( ( V == 'T' ) ? mask_el == 'F' : false );
701 template <typename First, typename Last, char V, field F1, field F2>
702 struct static_interrupt_sequence
704 typedef typename boost::mpl::deref<First>::type StaticMask;
706 static const bool value
707 = static_interrupt_dispatch
712 boost::mpl::is_sequence<StaticMask>::value
714 && static_interrupt_sequence
716 typename boost::mpl::next<First>::type,
722 template <typename Last, char V, field F1, field F2>
723 struct static_interrupt_sequence<Last, Last, V, F1, F2>
725 static const bool value = true;
728 template <typename StaticMask, char V, field F1, field F2>
729 struct static_interrupt_dispatch<StaticMask, V, F1, F2, true, true>
731 static const bool value
732 = static_interrupt_sequence
734 typename boost::mpl::begin<StaticMask>::type,
735 typename boost::mpl::end<StaticMask>::type,
740 template <typename StaticMask, char V, field F1, field F2, bool EnableInterrupt>
741 struct static_interrupt
743 static const bool value
744 = static_interrupt_dispatch
749 boost::mpl::is_sequence<StaticMask>::value
755 template <typename StaticMask, char D, field F1, field F2, bool IsSequence>
756 struct static_may_update_dispatch
758 static const char mask_el = StaticMask::template get<F1, F2>::value;
759 static const int version
762 : mask_el >= '0' && mask_el <= '9' ? 2
765 template <typename Matrix>
766 static inline bool apply(Matrix const& matrix)
768 return apply_dispatch(matrix, integral_constant<int, version>());
772 template <typename Matrix>
773 static inline bool apply_dispatch(Matrix const& , integral_constant<int, 0>)
778 template <typename Matrix>
779 static inline bool apply_dispatch(Matrix const& matrix, integral_constant<int, 1>)
781 char const c = matrix.template get<F1, F2>();
782 return c == 'F'; // if it's T or between 0 and 9, the result will be the same
784 // mask_el >= '0' && mask_el <= '9'
785 template <typename Matrix>
786 static inline bool apply_dispatch(Matrix const& matrix, integral_constant<int, 2>)
788 char const c = matrix.template get<F1, F2>();
789 return D > c || c > '9';
792 template <typename Matrix>
793 static inline bool apply_dispatch(Matrix const&, integral_constant<int, 3>)
799 template <typename First, typename Last, char D, field F1, field F2>
800 struct static_may_update_sequence
802 typedef typename boost::mpl::deref<First>::type StaticMask;
804 template <typename Matrix>
805 static inline bool apply(Matrix const& matrix)
807 return static_may_update_dispatch
811 boost::mpl::is_sequence<StaticMask>::value
813 || static_may_update_sequence
815 typename boost::mpl::next<First>::type,
822 template <typename Last, char D, field F1, field F2>
823 struct static_may_update_sequence<Last, Last, D, F1, F2>
825 template <typename Matrix>
826 static inline bool apply(Matrix const& /*matrix*/)
832 template <typename StaticMask, char D, field F1, field F2>
833 struct static_may_update_dispatch<StaticMask, D, F1, F2, true>
835 template <typename Matrix>
836 static inline bool apply(Matrix const& matrix)
838 return static_may_update_sequence
840 typename boost::mpl::begin<StaticMask>::type,
841 typename boost::mpl::end<StaticMask>::type,
847 template <typename StaticMask, char D, field F1, field F2>
848 struct static_may_update
850 template <typename Matrix>
851 static inline bool apply(Matrix const& matrix)
853 return static_may_update_dispatch
857 boost::mpl::is_sequence<StaticMask>::value
864 template <typename StaticMask, bool IsSequence>
865 struct static_check_dispatch
867 template <typename Matrix>
868 static inline bool apply(Matrix const& matrix)
870 return per_one<interior, interior>::apply(matrix)
871 && per_one<interior, boundary>::apply(matrix)
872 && per_one<interior, exterior>::apply(matrix)
873 && per_one<boundary, interior>::apply(matrix)
874 && per_one<boundary, boundary>::apply(matrix)
875 && per_one<boundary, exterior>::apply(matrix)
876 && per_one<exterior, interior>::apply(matrix)
877 && per_one<exterior, boundary>::apply(matrix)
878 && per_one<exterior, exterior>::apply(matrix);
881 template <field F1, field F2>
884 static const char mask_el = StaticMask::template get<F1, F2>::value;
885 static const int version
888 : mask_el >= '0' && mask_el <= '9' ? 2
891 template <typename Matrix>
892 static inline bool apply(Matrix const& matrix)
894 const char el = matrix.template get<F1, F2>();
895 return apply_dispatch(el, integral_constant<int, version>());
899 static inline bool apply_dispatch(char el, integral_constant<int, 0>)
904 static inline bool apply_dispatch(char el, integral_constant<int, 1>)
906 return el == 'T' || ( el >= '0' && el <= '9' );
908 // mask_el >= '0' && mask_el <= '9'
909 static inline bool apply_dispatch(char el, integral_constant<int, 2>)
911 return el == mask_el;
914 static inline bool apply_dispatch(char /*el*/, integral_constant<int, 3>)
921 template <typename First, typename Last>
922 struct static_check_sequence
924 typedef typename boost::mpl::deref<First>::type StaticMask;
926 template <typename Matrix>
927 static inline bool apply(Matrix const& matrix)
929 return static_check_dispatch
932 boost::mpl::is_sequence<StaticMask>::value
934 || static_check_sequence
936 typename boost::mpl::next<First>::type,
942 template <typename Last>
943 struct static_check_sequence<Last, Last>
945 template <typename Matrix>
946 static inline bool apply(Matrix const& /*matrix*/)
952 template <typename StaticMask>
953 struct static_check_dispatch<StaticMask, true>
955 template <typename Matrix>
956 static inline bool apply(Matrix const& matrix)
958 return static_check_sequence
960 typename boost::mpl::begin<StaticMask>::type,
961 typename boost::mpl::end<StaticMask>::type
966 template <typename StaticMask>
969 template <typename Matrix>
970 static inline bool apply(Matrix const& matrix)
972 return static_check_dispatch
975 boost::mpl::is_sequence<StaticMask>::value
980 // static_mask_handler
982 template <typename StaticMask, bool Interrupt>
983 class static_mask_handler
986 typedef matrix<3> base_t;
989 typedef bool result_type;
993 inline static_mask_handler(StaticMask const& /*dummy*/)
997 result_type result() const
999 return (!Interrupt || !interrupt)
1000 && static_check<StaticMask>::
1001 apply(static_cast<base_t const&>(*this));
1004 template <field F1, field F2, char D>
1005 inline bool may_update() const
1007 return static_may_update<StaticMask, D, F1, F2>::
1008 apply(static_cast<base_t const&>(*this));
1011 template <field F1, field F2>
1012 static inline bool expects()
1014 return static_should_handle_element<StaticMask, F1, F2>::value;
1017 //template <field F1, field F2>
1018 //inline char get() const
1020 // return base_t::template get<F1, F2>();
1023 template <field F1, field F2, char V>
1026 static const bool interrupt_c = static_interrupt<StaticMask, V, F1, F2, Interrupt>::value;
1027 static const bool should_handle = static_should_handle_element<StaticMask, F1, F2>::value;
1028 static const int version = interrupt_c ? 0
1032 set_dispatch<F1, F2, V>(integral_constant<int, version>());
1035 template <field F1, field F2, char V>
1036 inline void update()
1038 static const bool interrupt_c = static_interrupt<StaticMask, V, F1, F2, Interrupt>::value;
1039 static const bool should_handle = static_should_handle_element<StaticMask, F1, F2>::value;
1040 static const int version = interrupt_c ? 0
1044 update_dispatch<F1, F2, V>(integral_constant<int, version>());
1048 // Interrupt && interrupt
1049 template <field F1, field F2, char V>
1050 inline void set_dispatch(integral_constant<int, 0>)
1054 // else should_handle
1055 template <field F1, field F2, char V>
1056 inline void set_dispatch(integral_constant<int, 1>)
1058 base_t::template set<F1, F2, V>();
1061 template <field F1, field F2, char V>
1062 inline void set_dispatch(integral_constant<int, 2>)
1065 // Interrupt && interrupt
1066 template <field F1, field F2, char V>
1067 inline void update_dispatch(integral_constant<int, 0>)
1071 // else should_handle
1072 template <field F1, field F2, char V>
1073 inline void update_dispatch(integral_constant<int, 1>)
1075 base_t::template update<F1, F2, V>();
1078 template <field F1, field F2, char V>
1079 inline void update_dispatch(integral_constant<int, 2>)
1085 template <typename Mask1, typename Mask2> inline
1086 boost::tuples::cons<
1088 boost::tuples::cons<Mask2, boost::tuples::null_type>
1090 operator||(Mask1 const& m1, Mask2 const& m2)
1092 namespace bt = boost::tuples;
1095 bt::cons< Mask1, bt::cons<Mask2, bt::null_type> >
1096 ( m1, bt::cons<Mask2, bt::null_type>(m2, bt::null_type()) );
1099 template <typename Head, typename Tail, typename Mask> inline
1100 typename index::detail::tuples::push_back<
1101 boost::tuples::cons<Head, Tail>, Mask
1103 operator||(boost::tuples::cons<Head, Tail> const& t, Mask const& m)
1105 namespace bt = boost::tuples;
1108 index::detail::tuples::push_back<
1109 bt::cons<Head, Tail>, Mask
1116 // 1. specialize for simplified masks if available
1117 // e.g. for TOUCHES use 1 mask for A/A
1118 // 2. Think about dimensions > 2 e.g. should TOUCHES be true
1119 // if the interior of the Areal overlaps the boundary of the Volumetric
1120 // like it's true for Linear/Areal
1123 template <typename Geometry1, typename Geometry2>
1124 struct static_mask_equals_type
1126 typedef static_mask<'T', '*', 'F', '*', '*', 'F', 'F', 'F', '*'> type; // wikipedia
1127 //typedef static_mask<'T', 'F', 'F', 'F', 'T', 'F', 'F', 'F', 'T'> type; // OGC
1131 typedef static_mask<'F', 'F', '*', 'F', 'F', '*', '*', '*', '*'> static_mask_disjoint;
1133 // TOUCHES - NOT P/P
1134 template <typename Geometry1,
1136 std::size_t Dim1 = topological_dimension<Geometry1>::value,
1137 std::size_t Dim2 = topological_dimension<Geometry2>::value>
1138 struct static_mask_touches_impl
1140 typedef boost::mpl::vector<
1141 static_mask<'F', 'T', '*', '*', '*', '*', '*', '*', '*'>,
1142 static_mask<'F', '*', '*', 'T', '*', '*', '*', '*', '*'>,
1143 static_mask<'F', '*', '*', '*', 'T', '*', '*', '*', '*'>
1146 // According to OGC, doesn't apply to P/P
1147 // Using the above mask the result would be always false
1148 template <typename Geometry1, typename Geometry2>
1149 struct static_mask_touches_impl<Geometry1, Geometry2, 0, 0>
1150 : not_implemented<typename geometry::tag<Geometry1>::type,
1151 typename geometry::tag<Geometry2>::type>
1154 template <typename Geometry1, typename Geometry2>
1155 struct static_mask_touches_type
1156 : static_mask_touches_impl<Geometry1, Geometry2>
1160 typedef static_mask<'T', '*', 'F', '*', '*', 'F', '*', '*', '*'> static_mask_within;
1162 // COVERED_BY (non OGC)
1163 typedef boost::mpl::vector<
1164 static_mask<'T', '*', 'F', '*', '*', 'F', '*', '*', '*'>,
1165 static_mask<'*', 'T', 'F', '*', '*', 'F', '*', '*', '*'>,
1166 static_mask<'*', '*', 'F', 'T', '*', 'F', '*', '*', '*'>,
1167 static_mask<'*', '*', 'F', '*', 'T', 'F', '*', '*', '*'>
1168 > static_mask_covered_by;
1171 // dim(G1) < dim(G2) - P/L P/A L/A
1172 template <typename Geometry1,
1174 std::size_t Dim1 = topological_dimension<Geometry1>::value,
1175 std::size_t Dim2 = topological_dimension<Geometry2>::value,
1176 bool D1LessD2 = (Dim1 < Dim2)
1178 struct static_mask_crosses_impl
1180 typedef static_mask<'T', '*', 'T', '*', '*', '*', '*', '*', '*'> type;
1182 // TODO: I'm not sure if this one below should be available!
1183 // dim(G1) > dim(G2) - L/P A/P A/L
1184 template <typename Geometry1, typename Geometry2,
1185 std::size_t Dim1, std::size_t Dim2
1187 struct static_mask_crosses_impl<Geometry1, Geometry2, Dim1, Dim2, false>
1189 typedef static_mask<'T', '*', '*', '*', '*', '*', 'T', '*', '*'> type;
1191 // dim(G1) == dim(G2) - P/P A/A
1192 template <typename Geometry1, typename Geometry2,
1195 struct static_mask_crosses_impl<Geometry1, Geometry2, Dim, Dim, false>
1196 : not_implemented<typename geometry::tag<Geometry1>::type,
1197 typename geometry::tag<Geometry2>::type>
1199 // dim(G1) == 1 && dim(G2) == 1 - L/L
1200 template <typename Geometry1, typename Geometry2>
1201 struct static_mask_crosses_impl<Geometry1, Geometry2, 1, 1, false>
1203 typedef static_mask<'0', '*', '*', '*', '*', '*', '*', '*', '*'> type;
1206 template <typename Geometry1, typename Geometry2>
1207 struct static_mask_crosses_type
1208 : static_mask_crosses_impl<Geometry1, Geometry2>
1213 // dim(G1) != dim(G2) - NOT P/P, L/L, A/A
1214 template <typename Geometry1,
1216 std::size_t Dim1 = topological_dimension<Geometry1>::value,
1217 std::size_t Dim2 = topological_dimension<Geometry2>::value
1219 struct static_mask_overlaps_impl
1220 : not_implemented<typename geometry::tag<Geometry1>::type,
1221 typename geometry::tag<Geometry2>::type>
1223 // dim(G1) == D && dim(G2) == D - P/P A/A
1224 template <typename Geometry1, typename Geometry2, std::size_t Dim>
1225 struct static_mask_overlaps_impl<Geometry1, Geometry2, Dim, Dim>
1227 typedef static_mask<'T', '*', 'T', '*', '*', '*', 'T', '*', '*'> type;
1229 // dim(G1) == 1 && dim(G2) == 1 - L/L
1230 template <typename Geometry1, typename Geometry2>
1231 struct static_mask_overlaps_impl<Geometry1, Geometry2, 1, 1>
1233 typedef static_mask<'1', '*', 'T', '*', '*', '*', 'T', '*', '*'> type;
1236 template <typename Geometry1, typename Geometry2>
1237 struct static_mask_overlaps_type
1238 : static_mask_overlaps_impl<Geometry1, Geometry2>
1241 // RESULTS/HANDLERS UTILS
1243 template <field F1, field F2, char V, typename Result>
1244 inline void set(Result & res)
1246 res.template set<F1, F2, V>();
1249 template <field F1, field F2, char V, bool Transpose>
1252 template <typename Result>
1253 static inline void apply(Result & res)
1255 res.template set<F1, F2, V>();
1259 template <field F1, field F2, char V>
1260 struct set_dispatch<F1, F2, V, true>
1262 template <typename Result>
1263 static inline void apply(Result & res)
1265 res.template set<F2, F1, V>();
1269 template <field F1, field F2, char V, bool Transpose, typename Result>
1270 inline void set(Result & res)
1272 set_dispatch<F1, F2, V, Transpose>::apply(res);
1275 template <char V, typename Result>
1276 inline void set(Result & res)
1278 res.template set<interior, interior, V>();
1279 res.template set<interior, boundary, V>();
1280 res.template set<interior, exterior, V>();
1281 res.template set<boundary, interior, V>();
1282 res.template set<boundary, boundary, V>();
1283 res.template set<boundary, exterior, V>();
1284 res.template set<exterior, interior, V>();
1285 res.template set<exterior, boundary, V>();
1286 res.template set<exterior, exterior, V>();
1289 template <char II, char IB, char IE, char BI, char BB, char BE, char EI, char EB, char EE, typename Result>
1290 inline void set(Result & res)
1292 res.template set<interior, interior, II>();
1293 res.template set<interior, boundary, IB>();
1294 res.template set<interior, exterior, IE>();
1295 res.template set<boundary, interior, BI>();
1296 res.template set<boundary, boundary, BB>();
1297 res.template set<boundary, exterior, BE>();
1298 res.template set<exterior, interior, EI>();
1299 res.template set<exterior, boundary, EB>();
1300 res.template set<exterior, exterior, EE>();
1303 template <field F1, field F2, char D, typename Result>
1304 inline void update(Result & res)
1306 res.template update<F1, F2, D>();
1309 template <field F1, field F2, char D, bool Transpose>
1310 struct update_result_dispatch
1312 template <typename Result>
1313 static inline void apply(Result & res)
1315 update<F1, F2, D>(res);
1319 template <field F1, field F2, char D>
1320 struct update_result_dispatch<F1, F2, D, true>
1322 template <typename Result>
1323 static inline void apply(Result & res)
1325 update<F2, F1, D>(res);
1329 template <field F1, field F2, char D, bool Transpose, typename Result>
1330 inline void update(Result & res)
1332 update_result_dispatch<F1, F2, D, Transpose>::apply(res);
1335 template <field F1, field F2, char D, typename Result>
1336 inline bool may_update(Result const& res)
1338 return res.template may_update<F1, F2, D>();
1341 template <field F1, field F2, char D, bool Transpose>
1342 struct may_update_result_dispatch
1344 template <typename Result>
1345 static inline bool apply(Result const& res)
1347 return may_update<F1, F2, D>(res);
1351 template <field F1, field F2, char D>
1352 struct may_update_result_dispatch<F1, F2, D, true>
1354 template <typename Result>
1355 static inline bool apply(Result const& res)
1357 return may_update<F2, F1, D>(res);
1361 template <field F1, field F2, char D, bool Transpose, typename Result>
1362 inline bool may_update(Result const& res)
1364 return may_update_result_dispatch<F1, F2, D, Transpose>::apply(res);
1367 template <typename Result, char II, char IB, char IE, char BI, char BB, char BE, char EI, char EB, char EE>
1368 inline Result return_result()
1371 set<II, IB, IE, BI, BB, BE, EI, EB, EE>(res);
1375 template <typename Geometry>
1376 struct result_dimension
1378 BOOST_STATIC_ASSERT(geometry::dimension<Geometry>::value >= 0);
1379 static const char value
1380 = ( geometry::dimension<Geometry>::value <= 9 ) ?
1381 ( '0' + geometry::dimension<Geometry>::value ) :
1385 }} // namespace detail::relate
1386 #endif // DOXYGEN_NO_DETAIL
1388 }} // namespace boost::geometry
1390 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_RESULT_HPP