Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-16 08:34:34

0001 // Boost.Geometry Index
0002 //
0003 // Spatial query predicates definition and checks.
0004 //
0005 // Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
0006 //
0007 // This file was modified by Oracle on 2019-2023.
0008 // Modifications copyright (c) 2019-2023 Oracle and/or its affiliates.
0009 // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
0010 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
0011 //
0012 // Use, modification and distribution is subject to the Boost Software License,
0013 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0014 // http://www.boost.org/LICENSE_1_0.txt)
0015 
0016 #ifndef BOOST_GEOMETRY_INDEX_DETAIL_PREDICATES_HPP
0017 #define BOOST_GEOMETRY_INDEX_DETAIL_PREDICATES_HPP
0018 
0019 #include <tuple>
0020 #include <type_traits>
0021 //#include <utility>
0022 
0023 #include <boost/geometry/algorithms/detail/covered_by/interface.hpp>
0024 #include <boost/geometry/algorithms/detail/disjoint/interface.hpp>
0025 #include <boost/geometry/algorithms/detail/intersects/interface.hpp>
0026 #include <boost/geometry/algorithms/detail/overlaps/interface.hpp>
0027 #include <boost/geometry/algorithms/detail/touches/interface.hpp>
0028 #include <boost/geometry/algorithms/detail/within/interface.hpp>
0029 
0030 #include <boost/geometry/core/static_assert.hpp>
0031 #include <boost/geometry/core/tag.hpp>
0032 #include <boost/geometry/core/tags.hpp>
0033 
0034 #include <boost/geometry/index/detail/tags.hpp>
0035 
0036 #include <boost/geometry/strategies/default_strategy.hpp>
0037 
0038 namespace boost { namespace geometry { namespace index { namespace detail {
0039 
0040 namespace predicates {
0041 
0042 // ------------------------------------------------------------------ //
0043 // predicates
0044 // ------------------------------------------------------------------ //
0045 
0046 template <typename Fun, bool IsFunction = std::is_function<Fun>::value>
0047 struct satisfies_impl
0048 {
0049     satisfies_impl() : fun(nullptr) {}
0050     satisfies_impl(Fun f) : fun(f) {}
0051     Fun * fun;
0052 };
0053 
0054 template <typename Fun>
0055 struct satisfies_impl<Fun, false>
0056 {
0057     satisfies_impl() = default;
0058     satisfies_impl(Fun const& f) : fun(f) {}
0059     Fun fun;
0060 };
0061 
0062 template <typename Fun, bool Negated>
0063 struct satisfies : satisfies_impl<Fun>
0064 {
0065     using base_t = satisfies_impl<Fun>;
0066 
0067     satisfies() = default;
0068     satisfies(Fun const& f) : base_t(f) {}
0069     satisfies(base_t const& b) : base_t(b) {}
0070 };
0071 
0072 // ------------------------------------------------------------------ //
0073 
0074 struct contains_tag {};
0075 struct covered_by_tag {};
0076 struct covers_tag {};
0077 struct disjoint_tag {};
0078 struct intersects_tag {};
0079 struct overlaps_tag {};
0080 struct touches_tag {};
0081 struct within_tag {};
0082 
0083 template <typename Geometry, typename Tag, bool Negated>
0084 struct spatial_predicate
0085 {
0086     spatial_predicate() {}
0087     spatial_predicate(Geometry const& g) : geometry(g) {}
0088     Geometry geometry;
0089 };
0090 
0091 // ------------------------------------------------------------------ //
0092 
0093 // CONSIDER: separated nearest<> and path<> may be replaced by
0094 //           nearest_predicate<Geometry, Tag>
0095 //           where Tag = point_tag | path_tag
0096 // IMPROVEMENT: user-defined nearest predicate allowing to define
0097 //              all or only geometrical aspects of the search
0098 
0099 template <typename PointOrRelation>
0100 struct nearest
0101 {
0102     nearest()
0103 //        : count(0)
0104     {}
0105     nearest(PointOrRelation const& por, std::size_t k)
0106         : point_or_relation(por)
0107         , count(k)
0108     {}
0109     PointOrRelation point_or_relation;
0110     std::size_t count;
0111 };
0112 
0113 template <typename SegmentOrLinestring>
0114 struct path
0115 {
0116     path()
0117 //        : count(0)
0118     {}
0119     path(SegmentOrLinestring const& g, std::size_t k)
0120         : geometry(g)
0121         , count(k)
0122     {}
0123     SegmentOrLinestring geometry;
0124     std::size_t count;
0125 };
0126 
0127 } // namespace predicates
0128 
0129 // ------------------------------------------------------------------ //
0130 // predicate_check
0131 // ------------------------------------------------------------------ //
0132 
0133 template <typename Predicate, typename Tag>
0134 struct predicate_check
0135 {
0136     BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
0137         "Not implemented for this Predicate or Tag.",
0138         Predicate, Tag);
0139 };
0140 
0141 // ------------------------------------------------------------------ //
0142 
0143 template <typename Fun>
0144 struct predicate_check<predicates::satisfies<Fun, false>, value_tag>
0145 {
0146     template <typename Value, typename Indexable, typename Strategy>
0147     static inline bool apply(predicates::satisfies<Fun, false> const& p, Value const& v, Indexable const& , Strategy const&)
0148     {
0149         return p.fun(v);
0150     }
0151 };
0152 
0153 template <typename Fun>
0154 struct predicate_check<predicates::satisfies<Fun, true>, value_tag>
0155 {
0156     template <typename Value, typename Indexable, typename Strategy>
0157     static inline bool apply(predicates::satisfies<Fun, true> const& p, Value const& v, Indexable const& , Strategy const&)
0158     {
0159         return !p.fun(v);
0160     }
0161 };
0162 
0163 // ------------------------------------------------------------------ //
0164 
0165 template <typename Tag>
0166 struct spatial_predicate_call
0167 {
0168     BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
0169         "Not implemented for this Tag.",
0170         Tag);
0171 };
0172 
0173 template <>
0174 struct spatial_predicate_call<predicates::contains_tag>
0175 {
0176     template <typename G1, typename G2, typename S>
0177     static inline bool apply(G1 const& g1, G2 const& g2, S const& s)
0178     {
0179         return geometry::within(g2, g1, s);
0180     }
0181 };
0182 
0183 template <>
0184 struct spatial_predicate_call<predicates::covered_by_tag>
0185 {
0186     template <typename G1, typename G2, typename S>
0187     static inline bool apply(G1 const& g1, G2 const& g2, S const& s)
0188     {
0189         return geometry::covered_by(g1, g2, s);
0190     }
0191 };
0192 
0193 template <>
0194 struct spatial_predicate_call<predicates::covers_tag>
0195 {
0196     template <typename G1, typename G2, typename S>
0197     static inline bool apply(G1 const& g1, G2 const& g2, S const& s)
0198     {
0199         return geometry::covered_by(g2, g1, s);
0200     }
0201 };
0202 
0203 template <>
0204 struct spatial_predicate_call<predicates::disjoint_tag>
0205 {
0206     template <typename G1, typename G2, typename S>
0207     static inline bool apply(G1 const& g1, G2 const& g2, S const& s)
0208     {
0209         return geometry::disjoint(g1, g2, s);
0210     }
0211 };
0212 
0213 template <>
0214 struct spatial_predicate_call<predicates::intersects_tag>
0215 {
0216     template <typename G1, typename G2, typename S>
0217     static inline bool apply(G1 const& g1, G2 const& g2, S const& s)
0218     {
0219         return geometry::intersects(g1, g2, s);
0220     }
0221 };
0222 
0223 template <>
0224 struct spatial_predicate_call<predicates::overlaps_tag>
0225 {
0226     template <typename G1, typename G2, typename S>
0227     static inline bool apply(G1 const& g1, G2 const& g2, S const& s)
0228     {
0229         return geometry::overlaps(g1, g2, s);
0230     }
0231 };
0232 
0233 template <>
0234 struct spatial_predicate_call<predicates::touches_tag>
0235 {
0236     template <typename G1, typename G2, typename S>
0237     static inline bool apply(G1 const& g1, G2 const& g2, S const& s)
0238     {
0239         return geometry::touches(g1, g2, s);
0240     }
0241 };
0242 
0243 template <>
0244 struct spatial_predicate_call<predicates::within_tag>
0245 {
0246     template <typename G1, typename G2, typename S>
0247     static inline bool apply(G1 const& g1, G2 const& g2, S const& s)
0248     {
0249         return geometry::within(g1, g2, s);
0250     }
0251 };
0252 
0253 // ------------------------------------------------------------------ //
0254 
0255 // spatial predicate
0256 template <typename Geometry, typename Tag>
0257 struct predicate_check<predicates::spatial_predicate<Geometry, Tag, false>, value_tag>
0258 {
0259     typedef predicates::spatial_predicate<Geometry, Tag, false> Pred;
0260 
0261     template <typename Value, typename Indexable, typename Strategy>
0262     static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s)
0263     {
0264         return spatial_predicate_call<Tag>::apply(i, p.geometry, s);
0265     }
0266 };
0267 
0268 // negated spatial predicate
0269 template <typename Geometry, typename Tag>
0270 struct predicate_check<predicates::spatial_predicate<Geometry, Tag, true>, value_tag>
0271 {
0272     typedef predicates::spatial_predicate<Geometry, Tag, true> Pred;
0273 
0274     template <typename Value, typename Indexable, typename Strategy>
0275     static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s)
0276     {
0277         return !spatial_predicate_call<Tag>::apply(i, p.geometry, s);
0278     }
0279 };
0280 
0281 // ------------------------------------------------------------------ //
0282 
0283 template <typename DistancePredicates>
0284 struct predicate_check<predicates::nearest<DistancePredicates>, value_tag>
0285 {
0286     template <typename Value, typename Box, typename Strategy>
0287     static inline bool apply(predicates::nearest<DistancePredicates> const&, Value const&, Box const&, Strategy const&)
0288     {
0289         return true;
0290     }
0291 };
0292 
0293 template <typename Linestring>
0294 struct predicate_check<predicates::path<Linestring>, value_tag>
0295 {
0296     template <typename Value, typename Box, typename Strategy>
0297     static inline bool apply(predicates::path<Linestring> const&, Value const&, Box const&, Strategy const&)
0298     {
0299         return true;
0300     }
0301 };
0302 
0303 // ------------------------------------------------------------------ //
0304 // predicates_check for bounds
0305 // ------------------------------------------------------------------ //
0306 
0307 template <typename Fun, bool Negated>
0308 struct predicate_check<predicates::satisfies<Fun, Negated>, bounds_tag>
0309 {
0310     template <typename Value, typename Box, typename Strategy>
0311     static bool apply(predicates::satisfies<Fun, Negated> const&, Value const&, Box const&, Strategy const&)
0312     {
0313         return true;
0314     }
0315 };
0316 
0317 // ------------------------------------------------------------------ //
0318 
0319 // NOT NEGATED
0320 // value_tag        bounds_tag
0321 // ---------------------------
0322 // contains(I,G)    covers(I,G)
0323 // covered_by(I,G)  intersects(I,G)
0324 // covers(I,G)      covers(I,G)
0325 // disjoint(I,G)    !covered_by(I,G)
0326 // intersects(I,G)  intersects(I,G)
0327 // 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
0328 // touches(I,G)     intersects(I,G)
0329 // 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
0330 
0331 // spatial predicate - default
0332 template <typename Geometry, typename Tag>
0333 struct predicate_check<predicates::spatial_predicate<Geometry, Tag, false>, bounds_tag>
0334 {
0335     typedef predicates::spatial_predicate<Geometry, Tag, false> Pred;
0336 
0337     template <typename Value, typename Indexable, typename Strategy>
0338     static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s)
0339     {
0340         return spatial_predicate_call<predicates::intersects_tag>::apply(i, p.geometry, s);
0341     }
0342 };
0343 
0344 // spatial predicate - contains
0345 template <typename Geometry>
0346 struct predicate_check<predicates::spatial_predicate<Geometry, predicates::contains_tag, false>, bounds_tag>
0347 {
0348     typedef predicates::spatial_predicate<Geometry, predicates::contains_tag, false> Pred;
0349 
0350     template <typename Value, typename Indexable, typename Strategy>
0351     static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s)
0352     {
0353         return spatial_predicate_call<predicates::covers_tag>::apply(i, p.geometry, s);
0354     }
0355 };
0356 
0357 // spatial predicate - covers
0358 template <typename Geometry>
0359 struct predicate_check<predicates::spatial_predicate<Geometry, predicates::covers_tag, false>, bounds_tag>
0360 {
0361     typedef predicates::spatial_predicate<Geometry, predicates::covers_tag, false> Pred;
0362 
0363     template <typename Value, typename Indexable, typename Strategy>
0364     static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s)
0365     {
0366         return spatial_predicate_call<predicates::covers_tag>::apply(i, p.geometry, s);
0367     }
0368 };
0369 
0370 // spatial predicate - disjoint
0371 template <typename Geometry>
0372 struct predicate_check<predicates::spatial_predicate<Geometry, predicates::disjoint_tag, false>, bounds_tag>
0373 {
0374     typedef predicates::spatial_predicate<Geometry, predicates::disjoint_tag, false> Pred;
0375 
0376     template <typename Value, typename Indexable, typename Strategy>
0377     static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s)
0378     {
0379         return !spatial_predicate_call<predicates::covered_by_tag>::apply(i, p.geometry, s);
0380     }
0381 };
0382 
0383 // NEGATED
0384 // value_tag        bounds_tag
0385 // ---------------------------
0386 // !contains(I,G)   TRUE
0387 // !covered_by(I,G) !covered_by(I,G)
0388 // !covers(I,G)     TRUE
0389 // !disjoint(I,G)   !disjoint(I,G)
0390 // !intersects(I,G) !covered_by(I,G)
0391 // !overlaps(I,G)   TRUE
0392 // !touches(I,G)    !intersects(I,G)
0393 // !within(I,G)     !within(I,G)
0394 
0395 // negated spatial predicate - default
0396 template <typename Geometry, typename Tag>
0397 struct predicate_check<predicates::spatial_predicate<Geometry, Tag, true>, bounds_tag>
0398 {
0399     typedef predicates::spatial_predicate<Geometry, Tag, true> Pred;
0400 
0401     template <typename Value, typename Indexable, typename Strategy>
0402     static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s)
0403     {
0404         return !spatial_predicate_call<Tag>::apply(i, p.geometry, s);
0405     }
0406 };
0407 
0408 // negated spatial predicate - contains
0409 template <typename Geometry>
0410 struct predicate_check<predicates::spatial_predicate<Geometry, predicates::contains_tag, true>, bounds_tag>
0411 {
0412     typedef predicates::spatial_predicate<Geometry, predicates::contains_tag, true> Pred;
0413 
0414     template <typename Value, typename Indexable, typename Strategy>
0415     static inline bool apply(Pred const& , Value const&, Indexable const&, Strategy const&)
0416     {
0417         return true;
0418     }
0419 };
0420 
0421 // negated spatial predicate - covers
0422 template <typename Geometry>
0423 struct predicate_check<predicates::spatial_predicate<Geometry, predicates::covers_tag, true>, bounds_tag>
0424 {
0425     typedef predicates::spatial_predicate<Geometry, predicates::covers_tag, true> Pred;
0426 
0427     template <typename Value, typename Indexable, typename Strategy>
0428     static inline bool apply(Pred const& , Value const&, Indexable const&, Strategy const&)
0429     {
0430         return true;
0431     }
0432 };
0433 
0434 // negated spatial predicate - intersects
0435 template <typename Geometry>
0436 struct predicate_check<predicates::spatial_predicate<Geometry, predicates::intersects_tag, true>, bounds_tag>
0437 {
0438     typedef predicates::spatial_predicate<Geometry, predicates::intersects_tag, true> Pred;
0439 
0440     template <typename Value, typename Indexable, typename Strategy>
0441     static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s)
0442     {
0443         return !spatial_predicate_call<predicates::covered_by_tag>::apply(i, p.geometry, s);
0444     }
0445 };
0446 
0447 // negated spatial predicate - overlaps
0448 template <typename Geometry>
0449 struct predicate_check<predicates::spatial_predicate<Geometry, predicates::overlaps_tag, true>, bounds_tag>
0450 {
0451     typedef predicates::spatial_predicate<Geometry, predicates::overlaps_tag, true> Pred;
0452 
0453     template <typename Value, typename Indexable, typename Strategy>
0454     static inline bool apply(Pred const& , Value const&, Indexable const&, Strategy const&)
0455     {
0456         return true;
0457     }
0458 };
0459 
0460 // negated spatial predicate - touches
0461 template <typename Geometry>
0462 struct predicate_check<predicates::spatial_predicate<Geometry, predicates::touches_tag, true>, bounds_tag>
0463 {
0464     typedef predicates::spatial_predicate<Geometry, predicates::touches_tag, true> Pred;
0465 
0466     template <typename Value, typename Indexable, typename Strategy>
0467     static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const&)
0468     {
0469         return !spatial_predicate_call<predicates::intersects_tag>::apply(i, p.geometry);
0470     }
0471 };
0472 
0473 // ------------------------------------------------------------------ //
0474 
0475 template <typename DistancePredicates>
0476 struct predicate_check<predicates::nearest<DistancePredicates>, bounds_tag>
0477 {
0478     template <typename Value, typename Box, typename Strategy>
0479     static inline bool apply(predicates::nearest<DistancePredicates> const&, Value const&, Box const&, Strategy const&)
0480     {
0481         return true;
0482     }
0483 };
0484 
0485 template <typename Linestring>
0486 struct predicate_check<predicates::path<Linestring>, bounds_tag>
0487 {
0488     template <typename Value, typename Box, typename Strategy>
0489     static inline bool apply(predicates::path<Linestring> const&, Value const&, Box const&, Strategy const&)
0490     {
0491         return true;
0492     }
0493 };
0494 
0495 // ------------------------------------------------------------------ //
0496 // predicates_length
0497 // ------------------------------------------------------------------ //
0498 
0499 template <typename T>
0500 struct predicates_length
0501 {
0502     static const std::size_t value = 1;
0503 };
0504 
0505 template <typename ...Ts>
0506 struct predicates_length<std::tuple<Ts...>>
0507 {
0508     static const std::size_t value = std::tuple_size<std::tuple<Ts...>>::value;
0509 };
0510 
0511 // ------------------------------------------------------------------ //
0512 // predicates_element
0513 // ------------------------------------------------------------------ //
0514 
0515 template <std::size_t I, typename T>
0516 struct predicates_element
0517 {
0518     BOOST_GEOMETRY_STATIC_ASSERT((I < 1),
0519         "Invalid I index.",
0520         std::integral_constant<std::size_t, I>);
0521 
0522     typedef T type;
0523     static type const& get(T const& p) { return p; }
0524 };
0525 
0526 template <std::size_t I, typename ...Ts>
0527 struct predicates_element<I, std::tuple<Ts...>>
0528 {
0529     typedef std::tuple<Ts...> predicate_type;
0530 
0531     typedef typename std::tuple_element<I, predicate_type>::type type;
0532     static type const& get(predicate_type const& p) { return std::get<I>(p); }
0533 };
0534 
0535 // ------------------------------------------------------------------ //
0536 // predicates_check
0537 // ------------------------------------------------------------------ //
0538 
0539 template <typename TuplePredicates, typename Tag, std::size_t First, std::size_t Last>
0540 struct predicates_check_tuple
0541 {
0542     template <typename Value, typename Indexable, typename Strategy>
0543     static inline bool apply(TuplePredicates const& p, Value const& v, Indexable const& i, Strategy const& s)
0544     {
0545         return predicate_check
0546                 <
0547                     typename std::tuple_element<First, TuplePredicates>::type,
0548                     Tag
0549                 >::apply(std::get<First>(p), v, i, s)
0550             && predicates_check_tuple<TuplePredicates, Tag, First+1, Last>::apply(p, v, i, s);
0551     }
0552 };
0553 
0554 template <typename TuplePredicates, typename Tag, std::size_t First>
0555 struct predicates_check_tuple<TuplePredicates, Tag, First, First>
0556 {
0557     template <typename Value, typename Indexable, typename Strategy>
0558     static inline bool apply(TuplePredicates const& , Value const& , Indexable const& , Strategy const& )
0559     {
0560         return true;
0561     }
0562 };
0563 
0564 template <typename Predicate, typename Tag, std::size_t First, std::size_t Last>
0565 struct predicates_check_impl
0566 {
0567     static const bool check = First < 1 && Last <= 1 && First <= Last;
0568     BOOST_GEOMETRY_STATIC_ASSERT((check),
0569         "Invalid First or Last index.",
0570         std::integer_sequence<std::size_t, First, Last>);
0571 
0572     template <typename Value, typename Indexable, typename Strategy>
0573     static inline bool apply(Predicate const& p, Value const& v, Indexable const& i, Strategy const& s)
0574     {
0575         return predicate_check<Predicate, Tag>::apply(p, v, i, s);
0576     }
0577 };
0578 
0579 template <typename ...Ts, typename Tag, std::size_t First, std::size_t Last>
0580 struct predicates_check_impl<std::tuple<Ts...>, Tag, First, Last>
0581 {
0582     typedef std::tuple<Ts...> predicates_type;
0583 
0584     static const std::size_t pred_len = std::tuple_size<predicates_type>::value;
0585     static const bool check = First < pred_len && Last <= pred_len && First <= Last;
0586     BOOST_GEOMETRY_STATIC_ASSERT((check),
0587         "Invalid First or Last index.",
0588         std::integer_sequence<std::size_t, First, Last>);
0589 
0590     template <typename Value, typename Indexable, typename Strategy>
0591     static inline bool apply(predicates_type const& p, Value const& v, Indexable const& i, Strategy const& s)
0592     {
0593         return predicates_check_tuple
0594                 <
0595                     predicates_type,
0596                     Tag, First, Last
0597                 >::apply(p, v, i, s);
0598     }
0599 };
0600 
0601 template <typename Tag, typename Predicates, typename Value, typename Indexable, typename Strategy>
0602 inline bool predicates_check(Predicates const& p, Value const& v, Indexable const& i, Strategy const& s)
0603 {
0604     return detail::predicates_check_impl
0605         <
0606             Predicates, Tag, 0, predicates_length<Predicates>::value
0607         >::apply(p, v, i, s);
0608 }
0609 
0610 // ------------------------------------------------------------------ //
0611 // nearest predicate helpers
0612 // ------------------------------------------------------------------ //
0613 
0614 // predicates_is_nearest
0615 
0616 template <typename P>
0617 struct predicates_is_distance
0618 {
0619     static const std::size_t value = 0;
0620 };
0621 
0622 template <typename DistancePredicates>
0623 struct predicates_is_distance< predicates::nearest<DistancePredicates> >
0624 {
0625     static const std::size_t value = 1;
0626 };
0627 
0628 template <typename Linestring>
0629 struct predicates_is_distance< predicates::path<Linestring> >
0630 {
0631     static const std::size_t value = 1;
0632 };
0633 
0634 // predicates_count_nearest
0635 
0636 template <typename T>
0637 struct predicates_count_distance
0638 {
0639     static const std::size_t value = predicates_is_distance<T>::value;
0640 };
0641 
0642 template <typename Tuple, std::size_t N>
0643 struct predicates_count_distance_tuple
0644 {
0645     static const std::size_t value =
0646         predicates_is_distance<typename std::tuple_element<N-1, Tuple>::type>::value
0647         + predicates_count_distance_tuple<Tuple, N-1>::value;
0648 };
0649 
0650 template <typename Tuple>
0651 struct predicates_count_distance_tuple<Tuple, 1>
0652 {
0653     static const std::size_t value =
0654         predicates_is_distance<typename std::tuple_element<0, Tuple>::type>::value;
0655 };
0656 
0657 template <typename ...Ts>
0658 struct predicates_count_distance<std::tuple<Ts...>>
0659 {
0660     static const std::size_t value = predicates_count_distance_tuple<
0661         std::tuple<Ts...>,
0662         std::tuple_size<std::tuple<Ts...>>::value
0663     >::value;
0664 };
0665 
0666 // predicates_find_nearest
0667 
0668 template <typename T>
0669 struct predicates_find_distance
0670 {
0671     static const std::size_t value = predicates_is_distance<T>::value ? 0 : 1;
0672 };
0673 
0674 template <typename Tuple, std::size_t N>
0675 struct predicates_find_distance_tuple
0676 {
0677     static const bool is_found = predicates_find_distance_tuple<Tuple, N-1>::is_found
0678                                 || predicates_is_distance<typename std::tuple_element<N-1, Tuple>::type>::value;
0679 
0680     static const std::size_t value = predicates_find_distance_tuple<Tuple, N-1>::is_found ?
0681         predicates_find_distance_tuple<Tuple, N-1>::value :
0682         (predicates_is_distance<typename std::tuple_element<N-1, Tuple>::type>::value ?
0683             N-1 : std::tuple_size<Tuple>::value);
0684 };
0685 
0686 template <typename Tuple>
0687 struct predicates_find_distance_tuple<Tuple, 1>
0688 {
0689     static const bool is_found = predicates_is_distance<typename std::tuple_element<0, Tuple>::type>::value;
0690     static const std::size_t value = is_found ? 0 : std::tuple_size<Tuple>::value;
0691 };
0692 
0693 template <typename ...Ts>
0694 struct predicates_find_distance<std::tuple<Ts...>>
0695 {
0696     static const std::size_t value = predicates_find_distance_tuple<
0697         std::tuple<Ts...>,
0698         std::tuple_size<std::tuple<Ts...>>::value
0699     >::value;
0700 };
0701 
0702 }}}} // namespace boost::geometry::index::detail
0703 
0704 #endif // BOOST_GEOMETRY_INDEX_DETAIL_PREDICATES_HPP