]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Boost.Geometry (aka GGL, Generic Geometry Library) |
2 | ||
3 | // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. | |
b32b8144 | 4 | // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. |
7c673cae | 5 | |
20effc67 TL |
6 | // This file was modified by Oracle on 2013-2020. |
7 | // Modifications copyright (c) 2013-2020 Oracle and/or its affiliates. | |
7c673cae FG |
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 | ||
20effc67 | 18 | #include <algorithm> |
7c673cae | 19 | #include <cstddef> |
92f5a8d4 | 20 | #include <cstring> |
1e59de90 | 21 | #include <string> |
20effc67 | 22 | #include <type_traits> |
7c673cae | 23 | |
b32b8144 | 24 | #include <boost/throw_exception.hpp> |
7c673cae | 25 | #include <boost/tuple/tuple.hpp> |
7c673cae FG |
26 | |
27 | #include <boost/geometry/core/assert.hpp> | |
28 | #include <boost/geometry/core/coordinate_dimension.hpp> | |
29 | #include <boost/geometry/core/exception.hpp> | |
20effc67 | 30 | #include <boost/geometry/core/static_assert.hpp> |
7c673cae | 31 | #include <boost/geometry/util/condition.hpp> |
20effc67 | 32 | #include <boost/geometry/util/sequence.hpp> |
7c673cae FG |
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; | |
20effc67 | 164 | typedef std::integral_constant<bool, in_bounds> in_bounds_t; |
7c673cae FG |
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; | |
20effc67 | 173 | typedef std::integral_constant<bool, in_bounds> in_bounds_t; |
7c673cae FG |
174 | update_dispatch<F1, F2, D>(in_bounds_t()); |
175 | } | |
176 | ||
177 | private: | |
178 | template <field F1, field F2, char V> | |
20effc67 | 179 | inline void set_dispatch(std::true_type) |
7c673cae FG |
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> | |
20effc67 | 187 | inline void set_dispatch(std::false_type) |
7c673cae FG |
188 | {} |
189 | ||
190 | template <field F1, field F2, char D> | |
20effc67 | 191 | inline void update_dispatch(std::true_type) |
7c673cae FG |
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> | |
20effc67 | 201 | inline void update_dispatch(std::false_type) |
7c673cae FG |
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 | { | |
b32b8144 | 268 | BOOST_THROW_EXCEPTION(geometry::invalid_input_exception()); |
7c673cae FG |
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 | ||
20effc67 | 312 | template <typename Masks, int I = 0, int N = std::tuple_size<Masks>::value> |
7c673cae FG |
313 | struct interrupt_dispatch_tuple |
314 | { | |
315 | template <field F1, field F2, char V> | |
316 | static inline bool apply(Masks const& masks) | |
317 | { | |
20effc67 TL |
318 | typedef typename std::tuple_element<I, Masks>::type mask_type; |
319 | mask_type const& mask = std::get<I>(masks); | |
7c673cae FG |
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 | ||
20effc67 TL |
335 | template <typename ...Masks> |
336 | struct interrupt_dispatch<std::tuple<Masks...>, true> | |
7c673cae | 337 | { |
20effc67 | 338 | typedef std::tuple<Masks...> mask_type; |
7c673cae FG |
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 | ||
20effc67 | 385 | template <typename Masks, int I = 0, int N = std::tuple_size<Masks>::value> |
7c673cae FG |
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 | { | |
20effc67 TL |
391 | typedef typename std::tuple_element<I, Masks>::type mask_type; |
392 | mask_type const& mask = std::get<I>(masks); | |
7c673cae FG |
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 | ||
20effc67 TL |
408 | template <typename ...Masks> |
409 | struct may_update_dispatch<std::tuple<Masks...>> | |
7c673cae | 410 | { |
20effc67 | 411 | typedef std::tuple<Masks...> mask_type; |
7c673cae FG |
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 | ||
20effc67 | 469 | template <typename Masks, int I = 0, int N = std::tuple_size<Masks>::value> |
7c673cae FG |
470 | struct check_dispatch_tuple |
471 | { | |
472 | template <typename Matrix> | |
473 | static inline bool apply(Masks const& masks, Matrix const& matrix) | |
474 | { | |
20effc67 TL |
475 | typedef typename std::tuple_element<I, Masks>::type mask_type; |
476 | mask_type const& mask = std::get<I>(masks); | |
7c673cae FG |
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 | ||
20effc67 TL |
492 | template <typename ...Masks> |
493 | struct check_dispatch<std::tuple<Masks...>> | |
7c673cae | 494 | { |
20effc67 | 495 | typedef std::tuple<Masks...> mask_type; |
7c673cae FG |
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, | |
20effc67 | 520 | int N = std::tuple_size<Tuple>::value> |
7c673cae FG |
521 | struct matrix_width_tuple |
522 | { | |
523 | static const std::size_t | |
20effc67 | 524 | current = matrix_width<typename std::tuple_element<I, Tuple>::type>::value; |
7c673cae FG |
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 | ||
20effc67 TL |
538 | template <typename ...Masks> |
539 | struct matrix_width<std::tuple<Masks...>> | |
7c673cae FG |
540 | { |
541 | static const std::size_t | |
20effc67 | 542 | value = matrix_width_tuple<std::tuple<Masks...>>::value; |
7c673cae FG |
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 | ||
92f5a8d4 TL |
613 | // --------------- FALSE MASK ---------------- |
614 | ||
615 | struct false_mask {}; | |
616 | ||
7c673cae FG |
617 | // --------------- COMPILE-TIME MASK ---------------- |
618 | ||
619 | // static_check_characters | |
20effc67 TL |
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...>> | |
7c673cae | 626 | { |
20effc67 TL |
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); | |
7c673cae FG |
633 | }; |
634 | ||
20effc67 TL |
635 | template <char ...Cs> |
636 | struct static_check_characters<std::integral_constant<char, Cs...>> | |
7c673cae FG |
637 | {}; |
638 | ||
639 | // static_mask | |
640 | ||
20effc67 | 641 | template <typename Seq, std::size_t Height, std::size_t Width = Height> |
7c673cae FG |
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( | |
20effc67 | 649 | std::size_t(util::sequence_size<Seq>::value) == static_size); |
7c673cae FG |
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 | |
20effc67 | 658 | = util::sequence_element<F1 * static_width + F2, Seq>::value; |
7c673cae FG |
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 | ||
20effc67 TL |
668 | template |
669 | < | |
670 | typename StaticMask, field F1, field F2, | |
671 | bool IsSequence = util::is_sequence<StaticMask>::value | |
672 | > | |
7c673cae FG |
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 | ||
20effc67 TL |
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 | > | |
7c673cae FG |
687 | struct static_should_handle_element_sequence |
688 | { | |
20effc67 | 689 | typedef typename util::sequence_element<I, Seq>::type StaticMask; |
7c673cae FG |
690 | |
691 | static const bool value | |
692 | = static_should_handle_element_dispatch | |
693 | < | |
20effc67 | 694 | StaticMask, F1, F2 |
7c673cae FG |
695 | >::value |
696 | || static_should_handle_element_sequence | |
697 | < | |
20effc67 | 698 | Seq, F1, F2, I + 1 |
7c673cae FG |
699 | >::value; |
700 | }; | |
701 | ||
20effc67 TL |
702 | template <typename Seq, field F1, field F2, std::size_t N> |
703 | struct static_should_handle_element_sequence<Seq, F1, F2, N, N> | |
7c673cae FG |
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 | < | |
20effc67 | 714 | StaticMask, F1, F2 |
7c673cae FG |
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 | < | |
20effc67 | 724 | StaticMask, F1, F2 |
7c673cae FG |
725 | >::value; |
726 | }; | |
727 | ||
728 | // static_interrupt | |
729 | ||
20effc67 TL |
730 | template |
731 | < | |
732 | typename StaticMask, char V, field F1, field F2, | |
733 | bool InterruptEnabled, | |
734 | bool IsSequence = util::is_sequence<StaticMask>::value | |
735 | > | |
7c673cae FG |
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 | ||
20effc67 TL |
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 | > | |
7c673cae FG |
758 | struct static_interrupt_sequence |
759 | { | |
20effc67 | 760 | typedef typename util::sequence_element<I, Seq>::type StaticMask; |
7c673cae FG |
761 | |
762 | static const bool value | |
763 | = static_interrupt_dispatch | |
764 | < | |
20effc67 | 765 | StaticMask, V, F1, F2, true |
7c673cae FG |
766 | >::value |
767 | && static_interrupt_sequence | |
768 | < | |
20effc67 | 769 | Seq, V, F1, F2, I + 1 |
7c673cae FG |
770 | >::value; |
771 | }; | |
772 | ||
20effc67 TL |
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> | |
7c673cae FG |
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 | < | |
20effc67 | 785 | StaticMask, V, F1, F2 |
7c673cae FG |
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 | < | |
20effc67 | 795 | StaticMask, V, F1, F2, EnableInterrupt |
7c673cae FG |
796 | >::value; |
797 | }; | |
798 | ||
799 | // static_may_update | |
800 | ||
20effc67 TL |
801 | template |
802 | < | |
803 | typename StaticMask, char D, field F1, field F2, | |
804 | bool IsSequence = util::is_sequence<StaticMask>::value | |
805 | > | |
7c673cae FG |
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 | ||
20effc67 TL |
815 | // TODO: use std::enable_if_t instead of std::integral_constant |
816 | ||
7c673cae FG |
817 | template <typename Matrix> |
818 | static inline bool apply(Matrix const& matrix) | |
819 | { | |
20effc67 | 820 | return apply_dispatch(matrix, std::integral_constant<int, version>()); |
7c673cae FG |
821 | } |
822 | ||
823 | // mask_el == 'F' | |
824 | template <typename Matrix> | |
20effc67 | 825 | static inline bool apply_dispatch(Matrix const& , std::integral_constant<int, 0>) |
7c673cae FG |
826 | { |
827 | return true; | |
828 | } | |
829 | // mask_el == 'T' | |
830 | template <typename Matrix> | |
20effc67 | 831 | static inline bool apply_dispatch(Matrix const& matrix, std::integral_constant<int, 1>) |
7c673cae FG |
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> | |
20effc67 | 838 | static inline bool apply_dispatch(Matrix const& matrix, std::integral_constant<int, 2>) |
7c673cae FG |
839 | { |
840 | char const c = matrix.template get<F1, F2>(); | |
841 | return D > c || c > '9'; | |
842 | } | |
843 | // else | |
844 | template <typename Matrix> | |
20effc67 | 845 | static inline bool apply_dispatch(Matrix const&, std::integral_constant<int, 3>) |
7c673cae FG |
846 | { |
847 | return false; | |
848 | } | |
849 | }; | |
850 | ||
20effc67 TL |
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 | > | |
7c673cae FG |
857 | struct static_may_update_sequence |
858 | { | |
20effc67 | 859 | typedef typename util::sequence_element<I, Seq>::type StaticMask; |
7c673cae FG |
860 | |
861 | template <typename Matrix> | |
862 | static inline bool apply(Matrix const& matrix) | |
863 | { | |
864 | return static_may_update_dispatch | |
865 | < | |
20effc67 | 866 | StaticMask, D, F1, F2 |
7c673cae FG |
867 | >::apply(matrix) |
868 | || static_may_update_sequence | |
869 | < | |
20effc67 | 870 | Seq, D, F1, F2, I + 1 |
7c673cae FG |
871 | >::apply(matrix); |
872 | } | |
873 | }; | |
874 | ||
20effc67 TL |
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> | |
7c673cae FG |
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 | < | |
20effc67 | 893 | StaticMask, D, F1, F2 |
7c673cae FG |
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 | < | |
20effc67 | 906 | StaticMask, D, F1, F2 |
7c673cae FG |
907 | >::apply(matrix); |
908 | } | |
909 | }; | |
910 | ||
911 | // static_check_matrix | |
912 | ||
20effc67 TL |
913 | template |
914 | < | |
915 | typename StaticMask, | |
916 | bool IsSequence = util::is_sequence<StaticMask>::value | |
917 | > | |
7c673cae FG |
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 | ||
20effc67 TL |
944 | // TODO: use std::enable_if_t instead of std::integral_constant |
945 | ||
7c673cae FG |
946 | template <typename Matrix> |
947 | static inline bool apply(Matrix const& matrix) | |
948 | { | |
949 | const char el = matrix.template get<F1, F2>(); | |
20effc67 | 950 | return apply_dispatch(el, std::integral_constant<int, version>()); |
7c673cae FG |
951 | } |
952 | ||
953 | // mask_el == 'F' | |
20effc67 | 954 | static inline bool apply_dispatch(char el, std::integral_constant<int, 0>) |
7c673cae FG |
955 | { |
956 | return el == 'F'; | |
957 | } | |
958 | // mask_el == 'T' | |
20effc67 | 959 | static inline bool apply_dispatch(char el, std::integral_constant<int, 1>) |
7c673cae FG |
960 | { |
961 | return el == 'T' || ( el >= '0' && el <= '9' ); | |
962 | } | |
963 | // mask_el >= '0' && mask_el <= '9' | |
20effc67 | 964 | static inline bool apply_dispatch(char el, std::integral_constant<int, 2>) |
7c673cae FG |
965 | { |
966 | return el == mask_el; | |
967 | } | |
968 | // else | |
20effc67 | 969 | static inline bool apply_dispatch(char /*el*/, std::integral_constant<int, 3>) |
7c673cae FG |
970 | { |
971 | return true; | |
972 | } | |
973 | }; | |
974 | }; | |
975 | ||
20effc67 TL |
976 | template |
977 | < | |
978 | typename Seq, | |
979 | std::size_t I = 0, | |
980 | std::size_t N = util::sequence_size<Seq>::value | |
981 | > | |
7c673cae FG |
982 | struct static_check_sequence |
983 | { | |
20effc67 | 984 | typedef typename util::sequence_element<I, Seq>::type StaticMask; |
7c673cae FG |
985 | |
986 | template <typename Matrix> | |
987 | static inline bool apply(Matrix const& matrix) | |
988 | { | |
989 | return static_check_dispatch | |
990 | < | |
20effc67 | 991 | StaticMask |
7c673cae FG |
992 | >::apply(matrix) |
993 | || static_check_sequence | |
994 | < | |
20effc67 | 995 | Seq, I + 1 |
7c673cae FG |
996 | >::apply(matrix); |
997 | } | |
998 | }; | |
999 | ||
20effc67 TL |
1000 | template <typename Seq, std::size_t N> |
1001 | struct static_check_sequence<Seq, N, N> | |
7c673cae FG |
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 | < | |
20effc67 | 1018 | StaticMask |
7c673cae FG |
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 | < | |
20effc67 | 1031 | StaticMask |
7c673cae FG |
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 |