1 // Boost.Geometry Index
2 //
3 // Spatial query predicates definition and checks.
4 //
5 // Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
6 //
7 // Use, modification and distribution is subject to the Boost Software License,
8 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
9 // http://www.boost.org/LICENSE_1_0.txt)
10 
11 #ifndef BOOST_GEOMETRY_INDEX_DETAIL_PREDICATES_HPP
12 #define BOOST_GEOMETRY_INDEX_DETAIL_PREDICATES_HPP
13 
14 //#include <utility>
15 
16 #include <boost/mpl/assert.hpp>
17 #include <boost/tuple/tuple.hpp>
18 
19 #include <boost/geometry/index/detail/tags.hpp>
20 
21 namespace boost { namespace geometry { namespace index { namespace detail {
22 
23 namespace predicates {
24 
25 // ------------------------------------------------------------------ //
26 // predicates
27 // ------------------------------------------------------------------ //
28 
29 template <typename Fun, bool IsFunction>
30 struct satisfies_impl
31 {
satisfies_implboost::geometry::index::detail::predicates::satisfies_impl32     satisfies_impl() : fun(NULL) {}
satisfies_implboost::geometry::index::detail::predicates::satisfies_impl33     satisfies_impl(Fun f) : fun(f) {}
34     Fun * fun;
35 };
36 
37 template <typename Fun>
38 struct satisfies_impl<Fun, false>
39 {
satisfies_implboost::geometry::index::detail::predicates::satisfies_impl40     satisfies_impl() {}
satisfies_implboost::geometry::index::detail::predicates::satisfies_impl41     satisfies_impl(Fun const& f) : fun(f) {}
42     Fun fun;
43 };
44 
45 template <typename Fun, bool Negated>
46 struct satisfies
47     : satisfies_impl<Fun, ::boost::is_function<Fun>::value>
48 {
49     typedef satisfies_impl<Fun, ::boost::is_function<Fun>::value> base;
50 
satisfiesboost::geometry::index::detail::predicates::satisfies51     satisfies() {}
satisfiesboost::geometry::index::detail::predicates::satisfies52     satisfies(Fun const& f) : base(f) {}
satisfiesboost::geometry::index::detail::predicates::satisfies53     satisfies(base const& b) : base(b) {}
54 };
55 
56 // ------------------------------------------------------------------ //
57 
58 struct contains_tag {};
59 struct covered_by_tag {};
60 struct covers_tag {};
61 struct disjoint_tag {};
62 struct intersects_tag {};
63 struct overlaps_tag {};
64 struct touches_tag {};
65 struct within_tag {};
66 
67 template <typename Geometry, typename Tag, bool Negated>
68 struct spatial_predicate
69 {
spatial_predicateboost::geometry::index::detail::predicates::spatial_predicate70     spatial_predicate() {}
spatial_predicateboost::geometry::index::detail::predicates::spatial_predicate71     spatial_predicate(Geometry const& g) : geometry(g) {}
72     Geometry geometry;
73 };
74 
75 // ------------------------------------------------------------------ //
76 
77 // CONSIDER: separated nearest<> and path<> may be replaced by
78 //           nearest_predicate<Geometry, Tag>
79 //           where Tag = point_tag | path_tag
80 // IMPROVEMENT: user-defined nearest predicate allowing to define
81 //              all or only geometrical aspects of the search
82 
83 template <typename PointOrRelation>
84 struct nearest
85 {
nearestboost::geometry::index::detail::predicates::nearest86     nearest()
87 //        : count(0)
88     {}
nearestboost::geometry::index::detail::predicates::nearest89     nearest(PointOrRelation const& por, unsigned k)
90         : point_or_relation(por)
91         , count(k)
92     {}
93     PointOrRelation point_or_relation;
94     unsigned count;
95 };
96 
97 template <typename SegmentOrLinestring>
98 struct path
99 {
pathboost::geometry::index::detail::predicates::path100     path()
101 //        : count(0)
102     {}
pathboost::geometry::index::detail::predicates::path103     path(SegmentOrLinestring const& g, unsigned k)
104         : geometry(g)
105         , count(k)
106     {}
107     SegmentOrLinestring geometry;
108     unsigned count;
109 };
110 
111 } // namespace predicates
112 
113 // ------------------------------------------------------------------ //
114 // predicate_check
115 // ------------------------------------------------------------------ //
116 
117 template <typename Predicate, typename Tag>
118 struct predicate_check
119 {
120     BOOST_MPL_ASSERT_MSG(
121         (false),
122         NOT_IMPLEMENTED_FOR_THIS_PREDICATE_OR_TAG,
123         (predicate_check));
124 };
125 
126 // ------------------------------------------------------------------ //
127 
128 template <typename Fun>
129 struct predicate_check<predicates::satisfies<Fun, false>, value_tag>
130 {
131     template <typename Value, typename Indexable>
applyboost::geometry::index::detail::predicate_check132     static inline bool apply(predicates::satisfies<Fun, false> const& p, Value const& v, Indexable const&)
133     {
134         return p.fun(v);
135     }
136 };
137 
138 template <typename Fun>
139 struct predicate_check<predicates::satisfies<Fun, true>, value_tag>
140 {
141     template <typename Value, typename Indexable>
applyboost::geometry::index::detail::predicate_check142     static inline bool apply(predicates::satisfies<Fun, true> const& p, Value const& v, Indexable const&)
143     {
144         return !p.fun(v);
145     }
146 };
147 
148 // ------------------------------------------------------------------ //
149 
150 template <typename Tag>
151 struct spatial_predicate_call
152 {
153     BOOST_MPL_ASSERT_MSG(false, NOT_IMPLEMENTED_FOR_THIS_TAG, (Tag));
154 };
155 
156 template <>
157 struct spatial_predicate_call<predicates::contains_tag>
158 {
159     template <typename G1, typename G2>
applyboost::geometry::index::detail::spatial_predicate_call160     static inline bool apply(G1 const& g1, G2 const& g2)
161     {
162         return geometry::within(g2, g1);
163     }
164 };
165 
166 template <>
167 struct spatial_predicate_call<predicates::covered_by_tag>
168 {
169     template <typename G1, typename G2>
applyboost::geometry::index::detail::spatial_predicate_call170     static inline bool apply(G1 const& g1, G2 const& g2)
171     {
172         return geometry::covered_by(g1, g2);
173     }
174 };
175 
176 template <>
177 struct spatial_predicate_call<predicates::covers_tag>
178 {
179     template <typename G1, typename G2>
applyboost::geometry::index::detail::spatial_predicate_call180     static inline bool apply(G1 const& g1, G2 const& g2)
181     {
182         return geometry::covered_by(g2, g1);
183     }
184 };
185 
186 template <>
187 struct spatial_predicate_call<predicates::disjoint_tag>
188 {
189     template <typename G1, typename G2>
applyboost::geometry::index::detail::spatial_predicate_call190     static inline bool apply(G1 const& g1, G2 const& g2)
191     {
192         return geometry::disjoint(g1, g2);
193     }
194 };
195 
196 template <>
197 struct spatial_predicate_call<predicates::intersects_tag>
198 {
199     template <typename G1, typename G2>
applyboost::geometry::index::detail::spatial_predicate_call200     static inline bool apply(G1 const& g1, G2 const& g2)
201     {
202         return geometry::intersects(g1, g2);
203     }
204 };
205 
206 template <>
207 struct spatial_predicate_call<predicates::overlaps_tag>
208 {
209     template <typename G1, typename G2>
applyboost::geometry::index::detail::spatial_predicate_call210     static inline bool apply(G1 const& g1, G2 const& g2)
211     {
212         return geometry::overlaps(g1, g2);
213     }
214 };
215 
216 template <>
217 struct spatial_predicate_call<predicates::touches_tag>
218 {
219     template <typename G1, typename G2>
applyboost::geometry::index::detail::spatial_predicate_call220     static inline bool apply(G1 const& g1, G2 const& g2)
221     {
222         return geometry::touches(g1, g2);
223     }
224 };
225 
226 template <>
227 struct spatial_predicate_call<predicates::within_tag>
228 {
229     template <typename G1, typename G2>
applyboost::geometry::index::detail::spatial_predicate_call230     static inline bool apply(G1 const& g1, G2 const& g2)
231     {
232         return geometry::within(g1, g2);
233     }
234 };
235 
236 // ------------------------------------------------------------------ //
237 
238 // spatial predicate
239 template <typename Geometry, typename Tag>
240 struct predicate_check<predicates::spatial_predicate<Geometry, Tag, false>, value_tag>
241 {
242     typedef predicates::spatial_predicate<Geometry, Tag, false> Pred;
243 
244     template <typename Value, typename Indexable>
applyboost::geometry::index::detail::predicate_check245     static inline bool apply(Pred const& p, Value const&, Indexable const& i)
246     {
247         return spatial_predicate_call<Tag>::apply(i, p.geometry);
248     }
249 };
250 
251 // negated spatial predicate
252 template <typename Geometry, typename Tag>
253 struct predicate_check<predicates::spatial_predicate<Geometry, Tag, true>, value_tag>
254 {
255     typedef predicates::spatial_predicate<Geometry, Tag, true> Pred;
256 
257     template <typename Value, typename Indexable>
applyboost::geometry::index::detail::predicate_check258     static inline bool apply(Pred const& p, Value const&, Indexable const& i)
259     {
260         return !spatial_predicate_call<Tag>::apply(i, p.geometry);
261     }
262 };
263 
264 // ------------------------------------------------------------------ //
265 
266 template <typename DistancePredicates>
267 struct predicate_check<predicates::nearest<DistancePredicates>, value_tag>
268 {
269     template <typename Value, typename Box>
applyboost::geometry::index::detail::predicate_check270     static inline bool apply(predicates::nearest<DistancePredicates> const&, Value const&, Box const&)
271     {
272         return true;
273     }
274 };
275 
276 template <typename Linestring>
277 struct predicate_check<predicates::path<Linestring>, value_tag>
278 {
279     template <typename Value, typename Box>
applyboost::geometry::index::detail::predicate_check280     static inline bool apply(predicates::path<Linestring> const&, Value const&, Box const&)
281     {
282         return true;
283     }
284 };
285 
286 // ------------------------------------------------------------------ //
287 // predicates_check for bounds
288 // ------------------------------------------------------------------ //
289 
290 template <typename Fun, bool Negated>
291 struct predicate_check<predicates::satisfies<Fun, Negated>, bounds_tag>
292 {
293     template <typename Value, typename Box>
applyboost::geometry::index::detail::predicate_check294     static bool apply(predicates::satisfies<Fun, Negated> const&, Value const&, Box const&)
295     {
296         return true;
297     }
298 };
299 
300 // ------------------------------------------------------------------ //
301 
302 // NOT NEGATED
303 // value_tag        bounds_tag
304 // ---------------------------
305 // contains(I,G)    covers(I,G)
306 // covered_by(I,G)  intersects(I,G)
307 // covers(I,G)      covers(I,G)
308 // disjoint(I,G)    !covered_by(I,G)
309 // intersects(I,G)  intersects(I,G)
310 // overlaps(I,G)    intersects(I,G)  - possibly change to the version without border case, e.g. intersects_without_border(0,0x1,1, 1,1x2,2) should give false
311 // touches(I,G)     intersects(I,G)
312 // within(I,G)      intersects(I,G)  - possibly change to the version without border case, e.g. intersects_without_border(0,0x1,1, 1,1x2,2) should give false
313 
314 // spatial predicate - default
315 template <typename Geometry, typename Tag>
316 struct predicate_check<predicates::spatial_predicate<Geometry, Tag, false>, bounds_tag>
317 {
318     typedef predicates::spatial_predicate<Geometry, Tag, false> Pred;
319 
320     template <typename Value, typename Indexable>
applyboost::geometry::index::detail::predicate_check321     static inline bool apply(Pred const& p, Value const&, Indexable const& i)
322     {
323         return spatial_predicate_call<predicates::intersects_tag>::apply(i, p.geometry);
324     }
325 };
326 
327 // spatial predicate - contains
328 template <typename Geometry>
329 struct predicate_check<predicates::spatial_predicate<Geometry, predicates::contains_tag, false>, bounds_tag>
330 {
331     typedef predicates::spatial_predicate<Geometry, predicates::contains_tag, false> Pred;
332 
333     template <typename Value, typename Indexable>
applyboost::geometry::index::detail::predicate_check334     static inline bool apply(Pred const& p, Value const&, Indexable const& i)
335     {
336         return spatial_predicate_call<predicates::covers_tag>::apply(i, p.geometry);
337     }
338 };
339 
340 // spatial predicate - covers
341 template <typename Geometry>
342 struct predicate_check<predicates::spatial_predicate<Geometry, predicates::covers_tag, false>, bounds_tag>
343 {
344     typedef predicates::spatial_predicate<Geometry, predicates::covers_tag, false> Pred;
345 
346     template <typename Value, typename Indexable>
applyboost::geometry::index::detail::predicate_check347     static inline bool apply(Pred const& p, Value const&, Indexable const& i)
348     {
349         return spatial_predicate_call<predicates::covers_tag>::apply(i, p.geometry);
350     }
351 };
352 
353 // spatial predicate - disjoint
354 template <typename Geometry>
355 struct predicate_check<predicates::spatial_predicate<Geometry, predicates::disjoint_tag, false>, bounds_tag>
356 {
357     typedef predicates::spatial_predicate<Geometry, predicates::disjoint_tag, false> Pred;
358 
359     template <typename Value, typename Indexable>
applyboost::geometry::index::detail::predicate_check360     static inline bool apply(Pred const& p, Value const&, Indexable const& i)
361     {
362         return !spatial_predicate_call<predicates::covered_by_tag>::apply(i, p.geometry);
363     }
364 };
365 
366 // NEGATED
367 // value_tag        bounds_tag
368 // ---------------------------
369 // !contains(I,G)   TRUE
370 // !covered_by(I,G) !covered_by(I,G)
371 // !covers(I,G)     TRUE
372 // !disjoint(I,G)   !disjoint(I,G)
373 // !intersects(I,G) !covered_by(I,G)
374 // !overlaps(I,G)   TRUE
375 // !touches(I,G)    !intersects(I,G)
376 // !within(I,G)     !within(I,G)
377 
378 // negated spatial predicate - default
379 template <typename Geometry, typename Tag>
380 struct predicate_check<predicates::spatial_predicate<Geometry, Tag, true>, bounds_tag>
381 {
382     typedef predicates::spatial_predicate<Geometry, Tag, true> Pred;
383 
384     template <typename Value, typename Indexable>
applyboost::geometry::index::detail::predicate_check385     static inline bool apply(Pred const& p, Value const&, Indexable const& i)
386     {
387         return !spatial_predicate_call<Tag>::apply(i, p.geometry);
388     }
389 };
390 
391 // negated spatial predicate - contains
392 template <typename Geometry>
393 struct predicate_check<predicates::spatial_predicate<Geometry, predicates::contains_tag, true>, bounds_tag>
394 {
395     typedef predicates::spatial_predicate<Geometry, predicates::contains_tag, true> Pred;
396 
397     template <typename Value, typename Indexable>
applyboost::geometry::index::detail::predicate_check398     static inline bool apply(Pred const& , Value const&, Indexable const& )
399     {
400         return true;
401     }
402 };
403 
404 // negated spatial predicate - covers
405 template <typename Geometry>
406 struct predicate_check<predicates::spatial_predicate<Geometry, predicates::covers_tag, true>, bounds_tag>
407 {
408     typedef predicates::spatial_predicate<Geometry, predicates::covers_tag, true> Pred;
409 
410     template <typename Value, typename Indexable>
applyboost::geometry::index::detail::predicate_check411     static inline bool apply(Pred const& , Value const&, Indexable const& )
412     {
413         return true;
414     }
415 };
416 
417 // negated spatial predicate - intersects
418 template <typename Geometry>
419 struct predicate_check<predicates::spatial_predicate<Geometry, predicates::intersects_tag, true>, bounds_tag>
420 {
421     typedef predicates::spatial_predicate<Geometry, predicates::intersects_tag, true> Pred;
422 
423     template <typename Value, typename Indexable>
applyboost::geometry::index::detail::predicate_check424     static inline bool apply(Pred const& p, Value const&, Indexable const& i)
425     {
426         return !spatial_predicate_call<predicates::covered_by_tag>::apply(i, p.geometry);
427     }
428 };
429 
430 // negated spatial predicate - overlaps
431 template <typename Geometry>
432 struct predicate_check<predicates::spatial_predicate<Geometry, predicates::overlaps_tag, true>, bounds_tag>
433 {
434     typedef predicates::spatial_predicate<Geometry, predicates::overlaps_tag, true> Pred;
435 
436     template <typename Value, typename Indexable>
applyboost::geometry::index::detail::predicate_check437     static inline bool apply(Pred const& , Value const&, Indexable const& )
438     {
439         return true;
440     }
441 };
442 
443 // negated spatial predicate - touches
444 template <typename Geometry>
445 struct predicate_check<predicates::spatial_predicate<Geometry, predicates::touches_tag, true>, bounds_tag>
446 {
447     typedef predicates::spatial_predicate<Geometry, predicates::touches_tag, true> Pred;
448 
449     template <typename Value, typename Indexable>
applyboost::geometry::index::detail::predicate_check450     static inline bool apply(Pred const& p, Value const&, Indexable const& i)
451     {
452         return !spatial_predicate_call<predicates::intersects_tag>::apply(i, p.geometry);
453     }
454 };
455 
456 // ------------------------------------------------------------------ //
457 
458 template <typename DistancePredicates>
459 struct predicate_check<predicates::nearest<DistancePredicates>, bounds_tag>
460 {
461     template <typename Value, typename Box>
applyboost::geometry::index::detail::predicate_check462     static inline bool apply(predicates::nearest<DistancePredicates> const&, Value const&, Box const&)
463     {
464         return true;
465     }
466 };
467 
468 template <typename Linestring>
469 struct predicate_check<predicates::path<Linestring>, bounds_tag>
470 {
471     template <typename Value, typename Box>
applyboost::geometry::index::detail::predicate_check472     static inline bool apply(predicates::path<Linestring> const&, Value const&, Box const&)
473     {
474         return true;
475     }
476 };
477 
478 // ------------------------------------------------------------------ //
479 // predicates_length
480 // ------------------------------------------------------------------ //
481 
482 template <typename T>
483 struct predicates_length
484 {
485     static const unsigned value = 1;
486 };
487 
488 //template <typename F, typename S>
489 //struct predicates_length< std::pair<F, S> >
490 //{
491 //    static const unsigned value = 2;
492 //};
493 
494 //template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
495 //struct predicates_length< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >
496 //{
497 //    static const unsigned value = boost::tuples::length< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >::value;
498 //};
499 
500 template <typename Head, typename Tail>
501 struct predicates_length< boost::tuples::cons<Head, Tail> >
502 {
503     static const unsigned value = boost::tuples::length< boost::tuples::cons<Head, Tail> >::value;
504 };
505 
506 // ------------------------------------------------------------------ //
507 // predicates_element
508 // ------------------------------------------------------------------ //
509 
510 template <unsigned I, typename T>
511 struct predicates_element
512 {
513     BOOST_MPL_ASSERT_MSG((I < 1), INVALID_INDEX, (predicates_element));
514     typedef T type;
getboost::geometry::index::detail::predicates_element515     static type const& get(T const& p) { return p; }
516 };
517 
518 //template <unsigned I, typename F, typename S>
519 //struct predicates_element< I, std::pair<F, S> >
520 //{
521 //    BOOST_MPL_ASSERT_MSG((I < 2), INVALID_INDEX, (predicates_element));
522 //
523 //    typedef F type;
524 //    static type const& get(std::pair<F, S> const& p) { return p.first; }
525 //};
526 //
527 //template <typename F, typename S>
528 //struct predicates_element< 1, std::pair<F, S> >
529 //{
530 //    typedef S type;
531 //    static type const& get(std::pair<F, S> const& p) { return p.second; }
532 //};
533 //
534 //template <unsigned I, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
535 //struct predicates_element< I, boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >
536 //{
537 //    typedef boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> predicate_type;
538 //
539 //    typedef typename boost::tuples::element<I, predicate_type>::type type;
540 //    static type const& get(predicate_type const& p) { return boost::get<I>(p); }
541 //};
542 
543 template <unsigned I, typename Head, typename Tail>
544 struct predicates_element< I, boost::tuples::cons<Head, Tail> >
545 {
546     typedef boost::tuples::cons<Head, Tail> predicate_type;
547 
548     typedef typename boost::tuples::element<I, predicate_type>::type type;
getboost::geometry::index::detail::predicates_element549     static type const& get(predicate_type const& p) { return boost::get<I>(p); }
550 };
551 
552 // ------------------------------------------------------------------ //
553 // predicates_check
554 // ------------------------------------------------------------------ //
555 
556 //template <typename PairPredicates, typename Tag, unsigned First, unsigned Last>
557 //struct predicates_check_pair {};
558 //
559 //template <typename PairPredicates, typename Tag, unsigned I>
560 //struct predicates_check_pair<PairPredicates, Tag, I, I>
561 //{
562 //    template <typename Value, typename Indexable>
563 //    static inline bool apply(PairPredicates const& , Value const& , Indexable const& )
564 //    {
565 //        return true;
566 //    }
567 //};
568 //
569 //template <typename PairPredicates, typename Tag>
570 //struct predicates_check_pair<PairPredicates, Tag, 0, 1>
571 //{
572 //    template <typename Value, typename Indexable>
573 //    static inline bool apply(PairPredicates const& p, Value const& v, Indexable const& i)
574 //    {
575 //        return predicate_check<typename PairPredicates::first_type, Tag>::apply(p.first, v, i);
576 //    }
577 //};
578 //
579 //template <typename PairPredicates, typename Tag>
580 //struct predicates_check_pair<PairPredicates, Tag, 1, 2>
581 //{
582 //    template <typename Value, typename Indexable>
583 //    static inline bool apply(PairPredicates const& p, Value const& v, Indexable const& i)
584 //    {
585 //        return predicate_check<typename PairPredicates::second_type, Tag>::apply(p.second, v, i);
586 //    }
587 //};
588 //
589 //template <typename PairPredicates, typename Tag>
590 //struct predicates_check_pair<PairPredicates, Tag, 0, 2>
591 //{
592 //    template <typename Value, typename Indexable>
593 //    static inline bool apply(PairPredicates const& p, Value const& v, Indexable const& i)
594 //    {
595 //        return predicate_check<typename PairPredicates::first_type, Tag>::apply(p.first, v, i)
596 //            && predicate_check<typename PairPredicates::second_type, Tag>::apply(p.second, v, i);
597 //    }
598 //};
599 
600 template <typename TuplePredicates, typename Tag, unsigned First, unsigned Last>
601 struct predicates_check_tuple
602 {
603     template <typename Value, typename Indexable>
applyboost::geometry::index::detail::predicates_check_tuple604     static inline bool apply(TuplePredicates const& p, Value const& v, Indexable const& i)
605     {
606         return
607         predicate_check<
608             typename boost::tuples::element<First, TuplePredicates>::type,
609             Tag
610         >::apply(boost::get<First>(p), v, i) &&
611         predicates_check_tuple<TuplePredicates, Tag, First+1, Last>::apply(p, v, i);
612     }
613 };
614 
615 template <typename TuplePredicates, typename Tag, unsigned First>
616 struct predicates_check_tuple<TuplePredicates, Tag, First, First>
617 {
618     template <typename Value, typename Indexable>
applyboost::geometry::index::detail::predicates_check_tuple619     static inline bool apply(TuplePredicates const& , Value const& , Indexable const& )
620     {
621         return true;
622     }
623 };
624 
625 template <typename Predicate, typename Tag, unsigned First, unsigned Last>
626 struct predicates_check_impl
627 {
628     static const bool check = First < 1 && Last <= 1 && First <= Last;
629     BOOST_MPL_ASSERT_MSG((check), INVALID_INDEXES, (predicates_check_impl));
630 
631     template <typename Value, typename Indexable>
applyboost::geometry::index::detail::predicates_check_impl632     static inline bool apply(Predicate const& p, Value const& v, Indexable const& i)
633     {
634         return predicate_check<Predicate, Tag>::apply(p, v, i);
635     }
636 };
637 
638 //template <typename Predicate1, typename Predicate2, typename Tag, size_t First, size_t Last>
639 //struct predicates_check_impl<std::pair<Predicate1, Predicate2>, Tag, First, Last>
640 //{
641 //    BOOST_MPL_ASSERT_MSG((First < 2 && Last <= 2 && First <= Last), INVALID_INDEXES, (predicates_check_impl));
642 //
643 //    template <typename Value, typename Indexable>
644 //    static inline bool apply(std::pair<Predicate1, Predicate2> const& p, Value const& v, Indexable const& i)
645 //    {
646 //        return predicate_check<Predicate1, Tag>::apply(p.first, v, i)
647 //            && predicate_check<Predicate2, Tag>::apply(p.second, v, i);
648 //    }
649 //};
650 //
651 //template <
652 //    typename T0, typename T1, typename T2, typename T3, typename T4,
653 //    typename T5, typename T6, typename T7, typename T8, typename T9,
654 //    typename Tag, unsigned First, unsigned Last
655 //>
656 //struct predicates_check_impl<
657 //    boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>,
658 //    Tag, First, Last
659 //>
660 //{
661 //    typedef boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> predicates_type;
662 //
663 //    static const unsigned pred_len = boost::tuples::length<predicates_type>::value;
664 //    BOOST_MPL_ASSERT_MSG((First < pred_len && Last <= pred_len && First <= Last), INVALID_INDEXES, (predicates_check_impl));
665 //
666 //    template <typename Value, typename Indexable>
667 //    static inline bool apply(predicates_type const& p, Value const& v, Indexable const& i)
668 //    {
669 //        return predicates_check_tuple<
670 //            predicates_type,
671 //            Tag, First, Last
672 //        >::apply(p, v, i);
673 //    }
674 //};
675 
676 template <typename Head, typename Tail, typename Tag, unsigned First, unsigned Last>
677 struct predicates_check_impl<
678     boost::tuples::cons<Head, Tail>,
679     Tag, First, Last
680 >
681 {
682     typedef boost::tuples::cons<Head, Tail> predicates_type;
683 
684     static const unsigned pred_len = boost::tuples::length<predicates_type>::value;
685     static const bool check = First < pred_len && Last <= pred_len && First <= Last;
686     BOOST_MPL_ASSERT_MSG((check), INVALID_INDEXES, (predicates_check_impl));
687 
688     template <typename Value, typename Indexable>
applyboost::geometry::index::detail::predicates_check_impl689     static inline bool apply(predicates_type const& p, Value const& v, Indexable const& i)
690     {
691         return predicates_check_tuple<
692             predicates_type,
693             Tag, First, Last
694         >::apply(p, v, i);
695     }
696 };
697 
698 template <typename Tag, unsigned First, unsigned Last, typename Predicates, typename Value, typename Indexable>
predicates_check(Predicates const & p,Value const & v,Indexable const & i)699 inline bool predicates_check(Predicates const& p, Value const& v, Indexable const& i)
700 {
701     return detail::predicates_check_impl<Predicates, Tag, First, Last>
702         ::apply(p, v, i);
703 }
704 
705 // ------------------------------------------------------------------ //
706 // nearest predicate helpers
707 // ------------------------------------------------------------------ //
708 
709 // predicates_is_nearest
710 
711 template <typename P>
712 struct predicates_is_distance
713 {
714     static const unsigned value = 0;
715 };
716 
717 template <typename DistancePredicates>
718 struct predicates_is_distance< predicates::nearest<DistancePredicates> >
719 {
720     static const unsigned value = 1;
721 };
722 
723 template <typename Linestring>
724 struct predicates_is_distance< predicates::path<Linestring> >
725 {
726     static const unsigned value = 1;
727 };
728 
729 // predicates_count_nearest
730 
731 template <typename T>
732 struct predicates_count_distance
733 {
734     static const unsigned value = predicates_is_distance<T>::value;
735 };
736 
737 //template <typename F, typename S>
738 //struct predicates_count_distance< std::pair<F, S> >
739 //{
740 //    static const unsigned value = predicates_is_distance<F>::value
741 //                                + predicates_is_distance<S>::value;
742 //};
743 
744 template <typename Tuple, unsigned N>
745 struct predicates_count_distance_tuple
746 {
747     static const unsigned value =
748         predicates_is_distance<typename boost::tuples::element<N-1, Tuple>::type>::value
749         + predicates_count_distance_tuple<Tuple, N-1>::value;
750 };
751 
752 template <typename Tuple>
753 struct predicates_count_distance_tuple<Tuple, 1>
754 {
755     static const unsigned value =
756         predicates_is_distance<typename boost::tuples::element<0, Tuple>::type>::value;
757 };
758 
759 //template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
760 //struct predicates_count_distance< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >
761 //{
762 //    static const unsigned value = predicates_count_distance_tuple<
763 //        boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>,
764 //        boost::tuples::length< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >::value
765 //    >::value;
766 //};
767 
768 template <typename Head, typename Tail>
769 struct predicates_count_distance< boost::tuples::cons<Head, Tail> >
770 {
771     static const unsigned value = predicates_count_distance_tuple<
772         boost::tuples::cons<Head, Tail>,
773         boost::tuples::length< boost::tuples::cons<Head, Tail> >::value
774     >::value;
775 };
776 
777 // predicates_find_nearest
778 
779 template <typename T>
780 struct predicates_find_distance
781 {
782     static const unsigned value = predicates_is_distance<T>::value ? 0 : 1;
783 };
784 
785 //template <typename F, typename S>
786 //struct predicates_find_distance< std::pair<F, S> >
787 //{
788 //    static const unsigned value = predicates_is_distance<F>::value ? 0 :
789 //                                    (predicates_is_distance<S>::value ? 1 : 2);
790 //};
791 
792 template <typename Tuple, unsigned N>
793 struct predicates_find_distance_tuple
794 {
795     static const bool is_found = predicates_find_distance_tuple<Tuple, N-1>::is_found
796                                 || predicates_is_distance<typename boost::tuples::element<N-1, Tuple>::type>::value;
797 
798     static const unsigned value = predicates_find_distance_tuple<Tuple, N-1>::is_found ?
799         predicates_find_distance_tuple<Tuple, N-1>::value :
800         (predicates_is_distance<typename boost::tuples::element<N-1, Tuple>::type>::value ?
801             N-1 : boost::tuples::length<Tuple>::value);
802 };
803 
804 template <typename Tuple>
805 struct predicates_find_distance_tuple<Tuple, 1>
806 {
807     static const bool is_found = predicates_is_distance<typename boost::tuples::element<0, Tuple>::type>::value;
808     static const unsigned value = is_found ? 0 : boost::tuples::length<Tuple>::value;
809 };
810 
811 //template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
812 //struct predicates_find_distance< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >
813 //{
814 //    static const unsigned value = predicates_find_distance_tuple<
815 //        boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>,
816 //        boost::tuples::length< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >::value
817 //    >::value;
818 //};
819 
820 template <typename Head, typename Tail>
821 struct predicates_find_distance< boost::tuples::cons<Head, Tail> >
822 {
823     static const unsigned value = predicates_find_distance_tuple<
824         boost::tuples::cons<Head, Tail>,
825         boost::tuples::length< boost::tuples::cons<Head, Tail> >::value
826     >::value;
827 };
828 
829 }}}} // namespace boost::geometry::index::detail
830 
831 #endif // BOOST_GEOMETRY_INDEX_DETAIL_PREDICATES_HPP
832