File indexing completed on 2025-09-16 08:34:34
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
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
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
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
0094
0095
0096
0097
0098
0099 template <typename PointOrRelation>
0100 struct nearest
0101 {
0102 nearest()
0103
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
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 }
0128
0129
0130
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
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
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
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
0320
0321
0322
0323
0324
0325
0326
0327
0328
0329
0330
0331
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
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
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
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
0384
0385
0386
0387
0388
0389
0390
0391
0392
0393
0394
0395
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
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
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
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
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
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
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
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
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
0612
0613
0614
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
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
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 }}}}
0703
0704 #endif