]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/geometry/algorithms/detail/relate/result.hpp
c7a83665bd49a22bf88351f2ccc46384fa856a66
[ceph.git] / ceph / src / boost / boost / geometry / algorithms / detail / relate / result.hpp
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2
3 // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
4 // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
5
6 // This file was modified by Oracle on 2013-2020.
7 // Modifications copyright (c) 2013-2020 Oracle and/or its affiliates.
8
9 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
10
11 // Use, modification and distribution is subject to the Boost Software License,
12 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
13 // http://www.boost.org/LICENSE_1_0.txt)
14
15 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_RESULT_HPP
16 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_RESULT_HPP
17
18 #include <algorithm>
19 #include <cstddef>
20 #include <cstring>
21 #include <string>
22 #include <type_traits>
23
24 #include <boost/throw_exception.hpp>
25 #include <boost/tuple/tuple.hpp>
26
27 #include <boost/geometry/core/assert.hpp>
28 #include <boost/geometry/core/coordinate_dimension.hpp>
29 #include <boost/geometry/core/exception.hpp>
30 #include <boost/geometry/core/static_assert.hpp>
31 #include <boost/geometry/util/condition.hpp>
32 #include <boost/geometry/util/sequence.hpp>
33
34 namespace boost { namespace geometry {
35
36 #ifndef DOXYGEN_NO_DETAIL
37 namespace detail { namespace relate {
38
39 enum field { interior = 0, boundary = 1, exterior = 2 };
40
41 // TODO: IF THE RESULT IS UPDATED WITH THE MAX POSSIBLE VALUE FOR SOME PAIR OF GEOEMTRIES
42 // THE VALUE ALREADY STORED MUSN'T BE CHECKED
43 // update() calls chould be replaced with set() in those cases
44 // but for safety reasons (STATIC_ASSERT) we should check if parameter D is valid and set() doesn't do that
45 // so some additional function could be added, e.g. set_dim()
46
47 // --------------- MATRIX ----------------
48
49 // matrix
50
51 template <std::size_t Height, std::size_t Width = Height>
52 class matrix
53 {
54 public:
55 typedef char value_type;
56 typedef std::size_t size_type;
57 typedef const char * const_iterator;
58 typedef const_iterator iterator;
59
60 static const std::size_t static_width = Width;
61 static const std::size_t static_height = Height;
62 static const std::size_t static_size = Width * Height;
63
64 inline matrix()
65 {
66 ::memset(m_array, 'F', static_size);
67 }
68
69 template <field F1, field F2>
70 inline char get() const
71 {
72 BOOST_STATIC_ASSERT(F1 < Height && F2 < Width);
73 static const std::size_t index = F1 * Width + F2;
74 BOOST_STATIC_ASSERT(index < static_size);
75 return m_array[index];
76 }
77
78 template <field F1, field F2, char V>
79 inline void set()
80 {
81 BOOST_STATIC_ASSERT(F1 < Height && F2 < Width);
82 static const std::size_t index = F1 * Width + F2;
83 BOOST_STATIC_ASSERT(index < static_size);
84 m_array[index] = V;
85 }
86
87 inline char operator[](std::size_t index) const
88 {
89 BOOST_GEOMETRY_ASSERT(index < static_size);
90 return m_array[index];
91 }
92
93 inline const_iterator begin() const
94 {
95 return m_array;
96 }
97
98 inline const_iterator end() const
99 {
100 return m_array + static_size;
101 }
102
103 inline static std::size_t size()
104 {
105 return static_size;
106 }
107
108 inline const char * data() const
109 {
110 return m_array;
111 }
112
113 inline std::string str() const
114 {
115 return std::string(m_array, static_size);
116 }
117
118 private:
119 char m_array[static_size];
120 };
121
122 // matrix_handler
123
124 template <typename Matrix>
125 class matrix_handler
126 {
127 public:
128 typedef Matrix result_type;
129
130 static const bool interrupt = false;
131
132 matrix_handler()
133 {}
134
135 result_type const& result() const
136 {
137 return m_matrix;
138 }
139
140 result_type const& matrix() const
141 {
142 return m_matrix;
143 }
144
145 result_type & matrix()
146 {
147 return m_matrix;
148 }
149
150 template <field F1, field F2, char D>
151 inline bool may_update() const
152 {
153 BOOST_STATIC_ASSERT('0' <= D && D <= '9');
154
155 char const c = m_matrix.template get<F1, F2>();
156 return D > c || c > '9';
157 }
158
159 template <field F1, field F2, char V>
160 inline void set()
161 {
162 static const bool in_bounds = F1 < Matrix::static_height
163 && F2 < Matrix::static_width;
164 typedef std::integral_constant<bool, in_bounds> in_bounds_t;
165 set_dispatch<F1, F2, V>(in_bounds_t());
166 }
167
168 template <field F1, field F2, char D>
169 inline void update()
170 {
171 static const bool in_bounds = F1 < Matrix::static_height
172 && F2 < Matrix::static_width;
173 typedef std::integral_constant<bool, in_bounds> in_bounds_t;
174 update_dispatch<F1, F2, D>(in_bounds_t());
175 }
176
177 private:
178 template <field F1, field F2, char V>
179 inline void set_dispatch(std::true_type)
180 {
181 static const std::size_t index = F1 * Matrix::static_width + F2;
182 BOOST_STATIC_ASSERT(index < Matrix::static_size);
183 BOOST_STATIC_ASSERT(('0' <= V && V <= '9') || V == 'T' || V == 'F');
184 m_matrix.template set<F1, F2, V>();
185 }
186 template <field F1, field F2, char V>
187 inline void set_dispatch(std::false_type)
188 {}
189
190 template <field F1, field F2, char D>
191 inline void update_dispatch(std::true_type)
192 {
193 static const std::size_t index = F1 * Matrix::static_width + F2;
194 BOOST_STATIC_ASSERT(index < Matrix::static_size);
195 BOOST_STATIC_ASSERT('0' <= D && D <= '9');
196 char const c = m_matrix.template get<F1, F2>();
197 if ( D > c || c > '9')
198 m_matrix.template set<F1, F2, D>();
199 }
200 template <field F1, field F2, char D>
201 inline void update_dispatch(std::false_type)
202 {}
203
204 Matrix m_matrix;
205 };
206
207 // --------------- RUN-TIME MASK ----------------
208
209 // run-time mask
210
211 template <std::size_t Height, std::size_t Width = Height>
212 class mask
213 {
214 public:
215 static const std::size_t static_width = Width;
216 static const std::size_t static_height = Height;
217 static const std::size_t static_size = Width * Height;
218
219 inline mask(const char * s)
220 {
221 char * it = m_array;
222 char * const last = m_array + static_size;
223 for ( ; it != last && *s != '\0' ; ++it, ++s )
224 {
225 char c = *s;
226 check_char(c);
227 *it = c;
228 }
229 if ( it != last )
230 {
231 ::memset(it, '*', last - it);
232 }
233 }
234
235 inline mask(const char * s, std::size_t count)
236 {
237 if ( count > static_size )
238 {
239 count = static_size;
240 }
241 if ( count > 0 )
242 {
243 std::for_each(s, s + count, check_char);
244 ::memcpy(m_array, s, count);
245 }
246 if ( count < static_size )
247 {
248 ::memset(m_array + count, '*', static_size - count);
249 }
250 }
251
252 template <field F1, field F2>
253 inline char get() const
254 {
255 BOOST_STATIC_ASSERT(F1 < Height && F2 < Width);
256 static const std::size_t index = F1 * Width + F2;
257 BOOST_STATIC_ASSERT(index < static_size);
258 return m_array[index];
259 }
260
261 private:
262 static inline void check_char(char c)
263 {
264 bool const is_valid = c == '*' || c == 'T' || c == 'F'
265 || ( c >= '0' && c <= '9' );
266 if ( !is_valid )
267 {
268 BOOST_THROW_EXCEPTION(geometry::invalid_input_exception());
269 }
270 }
271
272 char m_array[static_size];
273 };
274
275 // interrupt()
276
277 template <typename Mask, bool InterruptEnabled>
278 struct interrupt_dispatch
279 {
280 template <field F1, field F2, char V>
281 static inline bool apply(Mask const&)
282 {
283 return false;
284 }
285 };
286
287 template <typename Mask>
288 struct interrupt_dispatch<Mask, true>
289 {
290 template <field F1, field F2, char V>
291 static inline bool apply(Mask const& mask)
292 {
293 char m = mask.template get<F1, F2>();
294 return check_element<V>(m);
295 }
296
297 template <char V>
298 static inline bool check_element(char m)
299 {
300 if ( BOOST_GEOMETRY_CONDITION(V >= '0' && V <= '9') )
301 {
302 return m == 'F' || ( m < V && m >= '0' && m <= '9' );
303 }
304 else if ( BOOST_GEOMETRY_CONDITION(V == 'T') )
305 {
306 return m == 'F';
307 }
308 return false;
309 }
310 };
311
312 template <typename Masks, int I = 0, int N = std::tuple_size<Masks>::value>
313 struct interrupt_dispatch_tuple
314 {
315 template <field F1, field F2, char V>
316 static inline bool apply(Masks const& masks)
317 {
318 typedef typename std::tuple_element<I, Masks>::type mask_type;
319 mask_type const& mask = std::get<I>(masks);
320 return interrupt_dispatch<mask_type, true>::template apply<F1, F2, V>(mask)
321 && interrupt_dispatch_tuple<Masks, I+1>::template apply<F1, F2, V>(masks);
322 }
323 };
324
325 template <typename Masks, int N>
326 struct interrupt_dispatch_tuple<Masks, N, N>
327 {
328 template <field F1, field F2, char V>
329 static inline bool apply(Masks const& )
330 {
331 return true;
332 }
333 };
334
335 template <typename ...Masks>
336 struct interrupt_dispatch<std::tuple<Masks...>, true>
337 {
338 typedef std::tuple<Masks...> mask_type;
339
340 template <field F1, field F2, char V>
341 static inline bool apply(mask_type const& mask)
342 {
343 return interrupt_dispatch_tuple<mask_type>::template apply<F1, F2, V>(mask);
344 }
345 };
346
347 template <field F1, field F2, char V, bool InterruptEnabled, typename Mask>
348 inline bool interrupt(Mask const& mask)
349 {
350 return interrupt_dispatch<Mask, InterruptEnabled>
351 ::template apply<F1, F2, V>(mask);
352 }
353
354 // may_update()
355
356 template <typename Mask>
357 struct may_update_dispatch
358 {
359 template <field F1, field F2, char D, typename Matrix>
360 static inline bool apply(Mask const& mask, Matrix const& matrix)
361 {
362 BOOST_STATIC_ASSERT('0' <= D && D <= '9');
363
364 char const m = mask.template get<F1, F2>();
365
366 if ( m == 'F' )
367 {
368 return true;
369 }
370 else if ( m == 'T' )
371 {
372 char const c = matrix.template get<F1, F2>();
373 return c == 'F'; // if it's T or between 0 and 9, the result will be the same
374 }
375 else if ( m >= '0' && m <= '9' )
376 {
377 char const c = matrix.template get<F1, F2>();
378 return D > c || c > '9';
379 }
380
381 return false;
382 }
383 };
384
385 template <typename Masks, int I = 0, int N = std::tuple_size<Masks>::value>
386 struct may_update_dispatch_tuple
387 {
388 template <field F1, field F2, char D, typename Matrix>
389 static inline bool apply(Masks const& masks, Matrix const& matrix)
390 {
391 typedef typename std::tuple_element<I, Masks>::type mask_type;
392 mask_type const& mask = std::get<I>(masks);
393 return may_update_dispatch<mask_type>::template apply<F1, F2, D>(mask, matrix)
394 || may_update_dispatch_tuple<Masks, I+1>::template apply<F1, F2, D>(masks, matrix);
395 }
396 };
397
398 template <typename Masks, int N>
399 struct may_update_dispatch_tuple<Masks, N, N>
400 {
401 template <field F1, field F2, char D, typename Matrix>
402 static inline bool apply(Masks const& , Matrix const& )
403 {
404 return false;
405 }
406 };
407
408 template <typename ...Masks>
409 struct may_update_dispatch<std::tuple<Masks...>>
410 {
411 typedef std::tuple<Masks...> mask_type;
412
413 template <field F1, field F2, char D, typename Matrix>
414 static inline bool apply(mask_type const& mask, Matrix const& matrix)
415 {
416 return may_update_dispatch_tuple<mask_type>::template apply<F1, F2, D>(mask, matrix);
417 }
418 };
419
420 template <field F1, field F2, char D, typename Mask, typename Matrix>
421 inline bool may_update(Mask const& mask, Matrix const& matrix)
422 {
423 return may_update_dispatch<Mask>
424 ::template apply<F1, F2, D>(mask, matrix);
425 }
426
427 // check_matrix()
428
429 template <typename Mask>
430 struct check_dispatch
431 {
432 template <typename Matrix>
433 static inline bool apply(Mask const& mask, Matrix const& matrix)
434 {
435 return per_one<interior, interior>(mask, matrix)
436 && per_one<interior, boundary>(mask, matrix)
437 && per_one<interior, exterior>(mask, matrix)
438 && per_one<boundary, interior>(mask, matrix)
439 && per_one<boundary, boundary>(mask, matrix)
440 && per_one<boundary, exterior>(mask, matrix)
441 && per_one<exterior, interior>(mask, matrix)
442 && per_one<exterior, boundary>(mask, matrix)
443 && per_one<exterior, exterior>(mask, matrix);
444 }
445
446 template <field F1, field F2, typename Matrix>
447 static inline bool per_one(Mask const& mask, Matrix const& matrix)
448 {
449 const char mask_el = mask.template get<F1, F2>();
450 const char el = matrix.template get<F1, F2>();
451
452 if ( mask_el == 'F' )
453 {
454 return el == 'F';
455 }
456 else if ( mask_el == 'T' )
457 {
458 return el == 'T' || ( el >= '0' && el <= '9' );
459 }
460 else if ( mask_el >= '0' && mask_el <= '9' )
461 {
462 return el == mask_el;
463 }
464
465 return true;
466 }
467 };
468
469 template <typename Masks, int I = 0, int N = std::tuple_size<Masks>::value>
470 struct check_dispatch_tuple
471 {
472 template <typename Matrix>
473 static inline bool apply(Masks const& masks, Matrix const& matrix)
474 {
475 typedef typename std::tuple_element<I, Masks>::type mask_type;
476 mask_type const& mask = std::get<I>(masks);
477 return check_dispatch<mask_type>::apply(mask, matrix)
478 || check_dispatch_tuple<Masks, I+1>::apply(masks, matrix);
479 }
480 };
481
482 template <typename Masks, int N>
483 struct check_dispatch_tuple<Masks, N, N>
484 {
485 template <typename Matrix>
486 static inline bool apply(Masks const&, Matrix const&)
487 {
488 return false;
489 }
490 };
491
492 template <typename ...Masks>
493 struct check_dispatch<std::tuple<Masks...>>
494 {
495 typedef std::tuple<Masks...> mask_type;
496
497 template <typename Matrix>
498 static inline bool apply(mask_type const& mask, Matrix const& matrix)
499 {
500 return check_dispatch_tuple<mask_type>::apply(mask, matrix);
501 }
502 };
503
504 template <typename Mask, typename Matrix>
505 inline bool check_matrix(Mask const& mask, Matrix const& matrix)
506 {
507 return check_dispatch<Mask>::apply(mask, matrix);
508 }
509
510 // matrix_width
511
512 template <typename MatrixOrMask>
513 struct matrix_width
514 {
515 static const std::size_t value = MatrixOrMask::static_width;
516 };
517
518 template <typename Tuple,
519 int I = 0,
520 int N = std::tuple_size<Tuple>::value>
521 struct matrix_width_tuple
522 {
523 static const std::size_t
524 current = matrix_width<typename std::tuple_element<I, Tuple>::type>::value;
525 static const std::size_t
526 next = matrix_width_tuple<Tuple, I+1>::value;
527
528 static const std::size_t
529 value = current > next ? current : next;
530 };
531
532 template <typename Tuple, int N>
533 struct matrix_width_tuple<Tuple, N, N>
534 {
535 static const std::size_t value = 0;
536 };
537
538 template <typename ...Masks>
539 struct matrix_width<std::tuple<Masks...>>
540 {
541 static const std::size_t
542 value = matrix_width_tuple<std::tuple<Masks...>>::value;
543 };
544
545 // mask_handler
546
547 template <typename Mask, bool Interrupt>
548 class mask_handler
549 : private matrix_handler
550 <
551 relate::matrix<matrix_width<Mask>::value>
552 >
553 {
554 typedef matrix_handler
555 <
556 relate::matrix<matrix_width<Mask>::value>
557 > base_t;
558
559 public:
560 typedef bool result_type;
561
562 bool interrupt;
563
564 inline explicit mask_handler(Mask const& m)
565 : interrupt(false)
566 , m_mask(m)
567 {}
568
569 result_type result() const
570 {
571 return !interrupt
572 && check_matrix(m_mask, base_t::matrix());
573 }
574
575 template <field F1, field F2, char D>
576 inline bool may_update() const
577 {
578 return detail::relate::may_update<F1, F2, D>(
579 m_mask, base_t::matrix()
580 );
581 }
582
583 template <field F1, field F2, char V>
584 inline void set()
585 {
586 if ( relate::interrupt<F1, F2, V, Interrupt>(m_mask) )
587 {
588 interrupt = true;
589 }
590 else
591 {
592 base_t::template set<F1, F2, V>();
593 }
594 }
595
596 template <field F1, field F2, char V>
597 inline void update()
598 {
599 if ( relate::interrupt<F1, F2, V, Interrupt>(m_mask) )
600 {
601 interrupt = true;
602 }
603 else
604 {
605 base_t::template update<F1, F2, V>();
606 }
607 }
608
609 private:
610 Mask const& m_mask;
611 };
612
613 // --------------- FALSE MASK ----------------
614
615 struct false_mask {};
616
617 // --------------- COMPILE-TIME MASK ----------------
618
619 // static_check_characters
620 template <typename Seq>
621 struct static_check_characters {};
622
623 template <char C, char ...Cs>
624 struct static_check_characters<std::integer_sequence<char, C, Cs...>>
625 : static_check_characters<std::integer_sequence<char, Cs...>>
626 {
627 typedef std::integer_sequence<char, C, Cs...> type;
628 static const bool is_valid = (C >= '0' && C <= '9')
629 || C == 'T' || C == 'F' || C == '*';
630 BOOST_GEOMETRY_STATIC_ASSERT((is_valid),
631 "Invalid static mask character",
632 type);
633 };
634
635 template <char ...Cs>
636 struct static_check_characters<std::integral_constant<char, Cs...>>
637 {};
638
639 // static_mask
640
641 template <typename Seq, std::size_t Height, std::size_t Width = Height>
642 struct static_mask
643 {
644 static const std::size_t static_width = Width;
645 static const std::size_t static_height = Height;
646 static const std::size_t static_size = Width * Height;
647
648 BOOST_STATIC_ASSERT(
649 std::size_t(util::sequence_size<Seq>::value) == static_size);
650
651 template <detail::relate::field F1, detail::relate::field F2>
652 struct static_get
653 {
654 BOOST_STATIC_ASSERT(std::size_t(F1) < static_height);
655 BOOST_STATIC_ASSERT(std::size_t(F2) < static_width);
656
657 static const char value
658 = util::sequence_element<F1 * static_width + F2, Seq>::value;
659 };
660
661 private:
662 // check static_mask characters
663 enum { mask_check = sizeof(static_check_characters<Seq>) };
664 };
665
666 // static_should_handle_element
667
668 template
669 <
670 typename StaticMask, field F1, field F2,
671 bool IsSequence = util::is_sequence<StaticMask>::value
672 >
673 struct static_should_handle_element_dispatch
674 {
675 static const char mask_el = StaticMask::template static_get<F1, F2>::value;
676 static const bool value = mask_el == 'F'
677 || mask_el == 'T'
678 || ( mask_el >= '0' && mask_el <= '9' );
679 };
680
681 template
682 <
683 typename Seq, field F1, field F2,
684 std::size_t I = 0,
685 std::size_t N = util::sequence_size<Seq>::value
686 >
687 struct static_should_handle_element_sequence
688 {
689 typedef typename util::sequence_element<I, Seq>::type StaticMask;
690
691 static const bool value
692 = static_should_handle_element_dispatch
693 <
694 StaticMask, F1, F2
695 >::value
696 || static_should_handle_element_sequence
697 <
698 Seq, F1, F2, I + 1
699 >::value;
700 };
701
702 template <typename Seq, field F1, field F2, std::size_t N>
703 struct static_should_handle_element_sequence<Seq, F1, F2, N, N>
704 {
705 static const bool value = false;
706 };
707
708 template <typename StaticMask, field F1, field F2>
709 struct static_should_handle_element_dispatch<StaticMask, F1, F2, true>
710 {
711 static const bool value
712 = static_should_handle_element_sequence
713 <
714 StaticMask, F1, F2
715 >::value;
716 };
717
718 template <typename StaticMask, field F1, field F2>
719 struct static_should_handle_element
720 {
721 static const bool value
722 = static_should_handle_element_dispatch
723 <
724 StaticMask, F1, F2
725 >::value;
726 };
727
728 // static_interrupt
729
730 template
731 <
732 typename StaticMask, char V, field F1, field F2,
733 bool InterruptEnabled,
734 bool IsSequence = util::is_sequence<StaticMask>::value
735 >
736 struct static_interrupt_dispatch
737 {
738 static const bool value = false;
739 };
740
741 template <typename StaticMask, char V, field F1, field F2, bool IsSequence>
742 struct static_interrupt_dispatch<StaticMask, V, F1, F2, true, IsSequence>
743 {
744 static const char mask_el = StaticMask::template static_get<F1, F2>::value;
745
746 static const bool value
747 = ( V >= '0' && V <= '9' ) ?
748 ( mask_el == 'F' || ( mask_el < V && mask_el >= '0' && mask_el <= '9' ) ) :
749 ( ( V == 'T' ) ? mask_el == 'F' : false );
750 };
751
752 template
753 <
754 typename Seq, char V, field F1, field F2,
755 std::size_t I = 0,
756 std::size_t N = util::sequence_size<Seq>::value
757 >
758 struct static_interrupt_sequence
759 {
760 typedef typename util::sequence_element<I, Seq>::type StaticMask;
761
762 static const bool value
763 = static_interrupt_dispatch
764 <
765 StaticMask, V, F1, F2, true
766 >::value
767 && static_interrupt_sequence
768 <
769 Seq, V, F1, F2, I + 1
770 >::value;
771 };
772
773 template <typename Seq, char V, field F1, field F2, std::size_t N>
774 struct static_interrupt_sequence<Seq, V, F1, F2, N, N>
775 {
776 static const bool value = true;
777 };
778
779 template <typename StaticMask, char V, field F1, field F2>
780 struct static_interrupt_dispatch<StaticMask, V, F1, F2, true, true>
781 {
782 static const bool value
783 = static_interrupt_sequence
784 <
785 StaticMask, V, F1, F2
786 >::value;
787 };
788
789 template <typename StaticMask, char V, field F1, field F2, bool EnableInterrupt>
790 struct static_interrupt
791 {
792 static const bool value
793 = static_interrupt_dispatch
794 <
795 StaticMask, V, F1, F2, EnableInterrupt
796 >::value;
797 };
798
799 // static_may_update
800
801 template
802 <
803 typename StaticMask, char D, field F1, field F2,
804 bool IsSequence = util::is_sequence<StaticMask>::value
805 >
806 struct static_may_update_dispatch
807 {
808 static const char mask_el = StaticMask::template static_get<F1, F2>::value;
809 static const int version
810 = mask_el == 'F' ? 0
811 : mask_el == 'T' ? 1
812 : mask_el >= '0' && mask_el <= '9' ? 2
813 : 3;
814
815 // TODO: use std::enable_if_t instead of std::integral_constant
816
817 template <typename Matrix>
818 static inline bool apply(Matrix const& matrix)
819 {
820 return apply_dispatch(matrix, std::integral_constant<int, version>());
821 }
822
823 // mask_el == 'F'
824 template <typename Matrix>
825 static inline bool apply_dispatch(Matrix const& , std::integral_constant<int, 0>)
826 {
827 return true;
828 }
829 // mask_el == 'T'
830 template <typename Matrix>
831 static inline bool apply_dispatch(Matrix const& matrix, std::integral_constant<int, 1>)
832 {
833 char const c = matrix.template get<F1, F2>();
834 return c == 'F'; // if it's T or between 0 and 9, the result will be the same
835 }
836 // mask_el >= '0' && mask_el <= '9'
837 template <typename Matrix>
838 static inline bool apply_dispatch(Matrix const& matrix, std::integral_constant<int, 2>)
839 {
840 char const c = matrix.template get<F1, F2>();
841 return D > c || c > '9';
842 }
843 // else
844 template <typename Matrix>
845 static inline bool apply_dispatch(Matrix const&, std::integral_constant<int, 3>)
846 {
847 return false;
848 }
849 };
850
851 template
852 <
853 typename Seq, char D, field F1, field F2,
854 std::size_t I = 0,
855 std::size_t N = util::sequence_size<Seq>::value
856 >
857 struct static_may_update_sequence
858 {
859 typedef typename util::sequence_element<I, Seq>::type StaticMask;
860
861 template <typename Matrix>
862 static inline bool apply(Matrix const& matrix)
863 {
864 return static_may_update_dispatch
865 <
866 StaticMask, D, F1, F2
867 >::apply(matrix)
868 || static_may_update_sequence
869 <
870 Seq, D, F1, F2, I + 1
871 >::apply(matrix);
872 }
873 };
874
875 template <typename Seq, char D, field F1, field F2, std::size_t N>
876 struct static_may_update_sequence<Seq, D, F1, F2, N, N>
877 {
878 template <typename Matrix>
879 static inline bool apply(Matrix const& /*matrix*/)
880 {
881 return false;
882 }
883 };
884
885 template <typename StaticMask, char D, field F1, field F2>
886 struct static_may_update_dispatch<StaticMask, D, F1, F2, true>
887 {
888 template <typename Matrix>
889 static inline bool apply(Matrix const& matrix)
890 {
891 return static_may_update_sequence
892 <
893 StaticMask, D, F1, F2
894 >::apply(matrix);
895 }
896 };
897
898 template <typename StaticMask, char D, field F1, field F2>
899 struct static_may_update
900 {
901 template <typename Matrix>
902 static inline bool apply(Matrix const& matrix)
903 {
904 return static_may_update_dispatch
905 <
906 StaticMask, D, F1, F2
907 >::apply(matrix);
908 }
909 };
910
911 // static_check_matrix
912
913 template
914 <
915 typename StaticMask,
916 bool IsSequence = util::is_sequence<StaticMask>::value
917 >
918 struct static_check_dispatch
919 {
920 template <typename Matrix>
921 static inline bool apply(Matrix const& matrix)
922 {
923 return per_one<interior, interior>::apply(matrix)
924 && per_one<interior, boundary>::apply(matrix)
925 && per_one<interior, exterior>::apply(matrix)
926 && per_one<boundary, interior>::apply(matrix)
927 && per_one<boundary, boundary>::apply(matrix)
928 && per_one<boundary, exterior>::apply(matrix)
929 && per_one<exterior, interior>::apply(matrix)
930 && per_one<exterior, boundary>::apply(matrix)
931 && per_one<exterior, exterior>::apply(matrix);
932 }
933
934 template <field F1, field F2>
935 struct per_one
936 {
937 static const char mask_el = StaticMask::template static_get<F1, F2>::value;
938 static const int version
939 = mask_el == 'F' ? 0
940 : mask_el == 'T' ? 1
941 : mask_el >= '0' && mask_el <= '9' ? 2
942 : 3;
943
944 // TODO: use std::enable_if_t instead of std::integral_constant
945
946 template <typename Matrix>
947 static inline bool apply(Matrix const& matrix)
948 {
949 const char el = matrix.template get<F1, F2>();
950 return apply_dispatch(el, std::integral_constant<int, version>());
951 }
952
953 // mask_el == 'F'
954 static inline bool apply_dispatch(char el, std::integral_constant<int, 0>)
955 {
956 return el == 'F';
957 }
958 // mask_el == 'T'
959 static inline bool apply_dispatch(char el, std::integral_constant<int, 1>)
960 {
961 return el == 'T' || ( el >= '0' && el <= '9' );
962 }
963 // mask_el >= '0' && mask_el <= '9'
964 static inline bool apply_dispatch(char el, std::integral_constant<int, 2>)
965 {
966 return el == mask_el;
967 }
968 // else
969 static inline bool apply_dispatch(char /*el*/, std::integral_constant<int, 3>)
970 {
971 return true;
972 }
973 };
974 };
975
976 template
977 <
978 typename Seq,
979 std::size_t I = 0,
980 std::size_t N = util::sequence_size<Seq>::value
981 >
982 struct static_check_sequence
983 {
984 typedef typename util::sequence_element<I, Seq>::type StaticMask;
985
986 template <typename Matrix>
987 static inline bool apply(Matrix const& matrix)
988 {
989 return static_check_dispatch
990 <
991 StaticMask
992 >::apply(matrix)
993 || static_check_sequence
994 <
995 Seq, I + 1
996 >::apply(matrix);
997 }
998 };
999
1000 template <typename Seq, std::size_t N>
1001 struct static_check_sequence<Seq, N, N>
1002 {
1003 template <typename Matrix>
1004 static inline bool apply(Matrix const& /*matrix*/)
1005 {
1006 return false;
1007 }
1008 };
1009
1010 template <typename StaticMask>
1011 struct static_check_dispatch<StaticMask, true>
1012 {
1013 template <typename Matrix>
1014 static inline bool apply(Matrix const& matrix)
1015 {
1016 return static_check_sequence
1017 <
1018 StaticMask
1019 >::apply(matrix);
1020 }
1021 };
1022
1023 template <typename StaticMask>
1024 struct static_check_matrix
1025 {
1026 template <typename Matrix>
1027 static inline bool apply(Matrix const& matrix)
1028 {
1029 return static_check_dispatch
1030 <
1031 StaticMask
1032 >::apply(matrix);
1033 }
1034 };
1035
1036 // static_mask_handler
1037
1038 template <typename StaticMask, bool Interrupt>
1039 class static_mask_handler
1040 : private matrix_handler< matrix<3> >
1041 {
1042 typedef matrix_handler< relate::matrix<3> > base_type;
1043
1044 public:
1045 typedef bool result_type;
1046
1047 bool interrupt;
1048
1049 inline static_mask_handler()
1050 : interrupt(false)
1051 {}
1052
1053 inline explicit static_mask_handler(StaticMask const& /*dummy*/)
1054 : interrupt(false)
1055 {}
1056
1057 result_type result() const
1058 {
1059 return (!Interrupt || !interrupt)
1060 && static_check_matrix<StaticMask>::apply(base_type::matrix());
1061 }
1062
1063 template <field F1, field F2, char D>
1064 inline bool may_update() const
1065 {
1066 return static_may_update<StaticMask, D, F1, F2>::
1067 apply(base_type::matrix());
1068 }
1069
1070 template <field F1, field F2>
1071 static inline bool expects()
1072 {
1073 return static_should_handle_element<StaticMask, F1, F2>::value;
1074 }
1075
1076 template <field F1, field F2, char V>
1077 inline void set()
1078 {
1079 static const bool interrupt_c = static_interrupt<StaticMask, V, F1, F2, Interrupt>::value;
1080 static const bool should_handle = static_should_handle_element<StaticMask, F1, F2>::value;
1081 static const int version = interrupt_c ? 0
1082 : should_handle ? 1
1083 : 2;
1084
1085 set_dispatch<F1, F2, V>(integral_constant<int, version>());
1086 }
1087
1088 template <field F1, field F2, char V>
1089 inline void update()
1090 {
1091 static const bool interrupt_c = static_interrupt<StaticMask, V, F1, F2, Interrupt>::value;
1092 static const bool should_handle = static_should_handle_element<StaticMask, F1, F2>::value;
1093 static const int version = interrupt_c ? 0
1094 : should_handle ? 1
1095 : 2;
1096
1097 update_dispatch<F1, F2, V>(integral_constant<int, version>());
1098 }
1099
1100 private:
1101 // Interrupt && interrupt
1102 template <field F1, field F2, char V>
1103 inline void set_dispatch(integral_constant<int, 0>)
1104 {
1105 interrupt = true;
1106 }
1107 // else should_handle
1108 template <field F1, field F2, char V>
1109 inline void set_dispatch(integral_constant<int, 1>)
1110 {
1111 base_type::template set<F1, F2, V>();
1112 }
1113 // else
1114 template <field F1, field F2, char V>
1115 inline void set_dispatch(integral_constant<int, 2>)
1116 {}
1117
1118 // Interrupt && interrupt
1119 template <field F1, field F2, char V>
1120 inline void update_dispatch(integral_constant<int, 0>)
1121 {
1122 interrupt = true;
1123 }
1124 // else should_handle
1125 template <field F1, field F2, char V>
1126 inline void update_dispatch(integral_constant<int, 1>)
1127 {
1128 base_type::template update<F1, F2, V>();
1129 }
1130 // else
1131 template <field F1, field F2, char V>
1132 inline void update_dispatch(integral_constant<int, 2>)
1133 {}
1134 };
1135
1136 // --------------- UTIL FUNCTIONS ----------------
1137
1138 // set
1139
1140 template <field F1, field F2, char V, typename Result>
1141 inline void set(Result & res)
1142 {
1143 res.template set<F1, F2, V>();
1144 }
1145
1146 template <field F1, field F2, char V, bool Transpose>
1147 struct set_dispatch
1148 {
1149 template <typename Result>
1150 static inline void apply(Result & res)
1151 {
1152 res.template set<F1, F2, V>();
1153 }
1154 };
1155
1156 template <field F1, field F2, char V>
1157 struct set_dispatch<F1, F2, V, true>
1158 {
1159 template <typename Result>
1160 static inline void apply(Result & res)
1161 {
1162 res.template set<F2, F1, V>();
1163 }
1164 };
1165
1166 template <field F1, field F2, char V, bool Transpose, typename Result>
1167 inline void set(Result & res)
1168 {
1169 set_dispatch<F1, F2, V, Transpose>::apply(res);
1170 }
1171
1172 // update
1173
1174 template <field F1, field F2, char D, typename Result>
1175 inline void update(Result & res)
1176 {
1177 res.template update<F1, F2, D>();
1178 }
1179
1180 template <field F1, field F2, char D, bool Transpose>
1181 struct update_result_dispatch
1182 {
1183 template <typename Result>
1184 static inline void apply(Result & res)
1185 {
1186 update<F1, F2, D>(res);
1187 }
1188 };
1189
1190 template <field F1, field F2, char D>
1191 struct update_result_dispatch<F1, F2, D, true>
1192 {
1193 template <typename Result>
1194 static inline void apply(Result & res)
1195 {
1196 update<F2, F1, D>(res);
1197 }
1198 };
1199
1200 template <field F1, field F2, char D, bool Transpose, typename Result>
1201 inline void update(Result & res)
1202 {
1203 update_result_dispatch<F1, F2, D, Transpose>::apply(res);
1204 }
1205
1206 // may_update
1207
1208 template <field F1, field F2, char D, typename Result>
1209 inline bool may_update(Result const& res)
1210 {
1211 return res.template may_update<F1, F2, D>();
1212 }
1213
1214 template <field F1, field F2, char D, bool Transpose>
1215 struct may_update_result_dispatch
1216 {
1217 template <typename Result>
1218 static inline bool apply(Result const& res)
1219 {
1220 return may_update<F1, F2, D>(res);
1221 }
1222 };
1223
1224 template <field F1, field F2, char D>
1225 struct may_update_result_dispatch<F1, F2, D, true>
1226 {
1227 template <typename Result>
1228 static inline bool apply(Result const& res)
1229 {
1230 return may_update<F2, F1, D>(res);
1231 }
1232 };
1233
1234 template <field F1, field F2, char D, bool Transpose, typename Result>
1235 inline bool may_update(Result const& res)
1236 {
1237 return may_update_result_dispatch<F1, F2, D, Transpose>::apply(res);
1238 }
1239
1240 // result_dimension
1241
1242 template <typename Geometry>
1243 struct result_dimension
1244 {
1245 BOOST_STATIC_ASSERT(geometry::dimension<Geometry>::value >= 0);
1246 static const char value
1247 = ( geometry::dimension<Geometry>::value <= 9 ) ?
1248 ( '0' + geometry::dimension<Geometry>::value ) :
1249 'T';
1250 };
1251
1252 }} // namespace detail::relate
1253 #endif // DOXYGEN_NO_DETAIL
1254
1255 }} // namespace boost::geometry
1256
1257 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_RESULT_HPP