File indexing completed on 2024-11-15 09:10:52
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&)
0178 {
0179 return geometry::within(g2, g1);
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&)
0188 {
0189 return geometry::covered_by(g1, g2);
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&)
0198 {
0199 return geometry::covered_by(g2, g1);
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&)
0208 {
0209 return geometry::disjoint(g1, g2);
0210 }
0211 };
0212
0213
0214
0215 template
0216 <
0217 typename G1, typename G2,
0218 typename Tag1 = typename tag<G1>::type,
0219 typename Tag2 = typename tag<G2>::type
0220 >
0221 struct spatial_predicate_intersects
0222 {
0223 template <typename S>
0224 static inline bool apply(G1 const& g1, G2 const& g2, S const&)
0225 {
0226 return geometry::intersects(g1, g2);
0227 }
0228 };
0229
0230 template <typename G1, typename G2>
0231 struct spatial_predicate_intersects<G1, G2, box_tag, point_tag>
0232 {
0233 static inline bool apply(G1 const& g1, G2 const& g2, default_strategy const&)
0234 {
0235 return geometry::intersects(g1, g2);
0236 }
0237
0238 template <typename S>
0239 static inline bool apply(G1 const& g1, G2 const& g2, S const& s)
0240 {
0241 return geometry::intersects(g1, g2, s);
0242 }
0243 };
0244
0245 template <>
0246 struct spatial_predicate_call<predicates::intersects_tag>
0247 {
0248 template <typename G1, typename G2, typename S>
0249 static inline bool apply(G1 const& g1, G2 const& g2, S const& s)
0250 {
0251 return spatial_predicate_intersects<G1, G2>::apply(g1, g2, s);
0252 }
0253 };
0254
0255 template <>
0256 struct spatial_predicate_call<predicates::overlaps_tag>
0257 {
0258 template <typename G1, typename G2, typename S>
0259 static inline bool apply(G1 const& g1, G2 const& g2, S const&)
0260 {
0261 return geometry::overlaps(g1, g2);
0262 }
0263 };
0264
0265 template <>
0266 struct spatial_predicate_call<predicates::touches_tag>
0267 {
0268 template <typename G1, typename G2, typename S>
0269 static inline bool apply(G1 const& g1, G2 const& g2, S const&)
0270 {
0271 return geometry::touches(g1, g2);
0272 }
0273 };
0274
0275 template <>
0276 struct spatial_predicate_call<predicates::within_tag>
0277 {
0278 template <typename G1, typename G2, typename S>
0279 static inline bool apply(G1 const& g1, G2 const& g2, S const&)
0280 {
0281 return geometry::within(g1, g2);
0282 }
0283 };
0284
0285
0286
0287
0288 template <typename Geometry, typename Tag>
0289 struct predicate_check<predicates::spatial_predicate<Geometry, Tag, false>, value_tag>
0290 {
0291 typedef predicates::spatial_predicate<Geometry, Tag, false> Pred;
0292
0293 template <typename Value, typename Indexable, typename Strategy>
0294 static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s)
0295 {
0296 return spatial_predicate_call<Tag>::apply(i, p.geometry, s);
0297 }
0298 };
0299
0300
0301 template <typename Geometry, typename Tag>
0302 struct predicate_check<predicates::spatial_predicate<Geometry, Tag, true>, value_tag>
0303 {
0304 typedef predicates::spatial_predicate<Geometry, Tag, true> Pred;
0305
0306 template <typename Value, typename Indexable, typename Strategy>
0307 static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s)
0308 {
0309 return !spatial_predicate_call<Tag>::apply(i, p.geometry, s);
0310 }
0311 };
0312
0313
0314
0315 template <typename DistancePredicates>
0316 struct predicate_check<predicates::nearest<DistancePredicates>, value_tag>
0317 {
0318 template <typename Value, typename Box, typename Strategy>
0319 static inline bool apply(predicates::nearest<DistancePredicates> const&, Value const&, Box const&, Strategy const&)
0320 {
0321 return true;
0322 }
0323 };
0324
0325 template <typename Linestring>
0326 struct predicate_check<predicates::path<Linestring>, value_tag>
0327 {
0328 template <typename Value, typename Box, typename Strategy>
0329 static inline bool apply(predicates::path<Linestring> const&, Value const&, Box const&, Strategy const&)
0330 {
0331 return true;
0332 }
0333 };
0334
0335
0336
0337
0338
0339 template <typename Fun, bool Negated>
0340 struct predicate_check<predicates::satisfies<Fun, Negated>, bounds_tag>
0341 {
0342 template <typename Value, typename Box, typename Strategy>
0343 static bool apply(predicates::satisfies<Fun, Negated> const&, Value const&, Box const&, Strategy const&)
0344 {
0345 return true;
0346 }
0347 };
0348
0349
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364 template <typename Geometry, typename Tag>
0365 struct predicate_check<predicates::spatial_predicate<Geometry, Tag, false>, bounds_tag>
0366 {
0367 typedef predicates::spatial_predicate<Geometry, Tag, false> Pred;
0368
0369 template <typename Value, typename Indexable, typename Strategy>
0370 static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s)
0371 {
0372 return spatial_predicate_call<predicates::intersects_tag>::apply(i, p.geometry, s);
0373 }
0374 };
0375
0376
0377 template <typename Geometry>
0378 struct predicate_check<predicates::spatial_predicate<Geometry, predicates::contains_tag, false>, bounds_tag>
0379 {
0380 typedef predicates::spatial_predicate<Geometry, predicates::contains_tag, false> Pred;
0381
0382 template <typename Value, typename Indexable, typename Strategy>
0383 static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s)
0384 {
0385 return spatial_predicate_call<predicates::covers_tag>::apply(i, p.geometry, s);
0386 }
0387 };
0388
0389
0390 template <typename Geometry>
0391 struct predicate_check<predicates::spatial_predicate<Geometry, predicates::covers_tag, false>, bounds_tag>
0392 {
0393 typedef predicates::spatial_predicate<Geometry, predicates::covers_tag, false> Pred;
0394
0395 template <typename Value, typename Indexable, typename Strategy>
0396 static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s)
0397 {
0398 return spatial_predicate_call<predicates::covers_tag>::apply(i, p.geometry, s);
0399 }
0400 };
0401
0402
0403 template <typename Geometry>
0404 struct predicate_check<predicates::spatial_predicate<Geometry, predicates::disjoint_tag, false>, bounds_tag>
0405 {
0406 typedef predicates::spatial_predicate<Geometry, predicates::disjoint_tag, false> Pred;
0407
0408 template <typename Value, typename Indexable, typename Strategy>
0409 static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s)
0410 {
0411 return !spatial_predicate_call<predicates::covered_by_tag>::apply(i, p.geometry, s);
0412 }
0413 };
0414
0415
0416
0417
0418
0419
0420
0421
0422
0423
0424
0425
0426
0427
0428 template <typename Geometry, typename Tag>
0429 struct predicate_check<predicates::spatial_predicate<Geometry, Tag, true>, bounds_tag>
0430 {
0431 typedef predicates::spatial_predicate<Geometry, Tag, true> Pred;
0432
0433 template <typename Value, typename Indexable, typename Strategy>
0434 static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s)
0435 {
0436 return !spatial_predicate_call<Tag>::apply(i, p.geometry, s);
0437 }
0438 };
0439
0440
0441 template <typename Geometry>
0442 struct predicate_check<predicates::spatial_predicate<Geometry, predicates::contains_tag, true>, bounds_tag>
0443 {
0444 typedef predicates::spatial_predicate<Geometry, predicates::contains_tag, true> Pred;
0445
0446 template <typename Value, typename Indexable, typename Strategy>
0447 static inline bool apply(Pred const& , Value const&, Indexable const&, Strategy const&)
0448 {
0449 return true;
0450 }
0451 };
0452
0453
0454 template <typename Geometry>
0455 struct predicate_check<predicates::spatial_predicate<Geometry, predicates::covers_tag, true>, bounds_tag>
0456 {
0457 typedef predicates::spatial_predicate<Geometry, predicates::covers_tag, true> Pred;
0458
0459 template <typename Value, typename Indexable, typename Strategy>
0460 static inline bool apply(Pred const& , Value const&, Indexable const&, Strategy const&)
0461 {
0462 return true;
0463 }
0464 };
0465
0466
0467 template <typename Geometry>
0468 struct predicate_check<predicates::spatial_predicate<Geometry, predicates::intersects_tag, true>, bounds_tag>
0469 {
0470 typedef predicates::spatial_predicate<Geometry, predicates::intersects_tag, true> Pred;
0471
0472 template <typename Value, typename Indexable, typename Strategy>
0473 static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s)
0474 {
0475 return !spatial_predicate_call<predicates::covered_by_tag>::apply(i, p.geometry, s);
0476 }
0477 };
0478
0479
0480 template <typename Geometry>
0481 struct predicate_check<predicates::spatial_predicate<Geometry, predicates::overlaps_tag, true>, bounds_tag>
0482 {
0483 typedef predicates::spatial_predicate<Geometry, predicates::overlaps_tag, true> Pred;
0484
0485 template <typename Value, typename Indexable, typename Strategy>
0486 static inline bool apply(Pred const& , Value const&, Indexable const&, Strategy const&)
0487 {
0488 return true;
0489 }
0490 };
0491
0492
0493 template <typename Geometry>
0494 struct predicate_check<predicates::spatial_predicate<Geometry, predicates::touches_tag, true>, bounds_tag>
0495 {
0496 typedef predicates::spatial_predicate<Geometry, predicates::touches_tag, true> Pred;
0497
0498 template <typename Value, typename Indexable, typename Strategy>
0499 static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const&)
0500 {
0501 return !spatial_predicate_call<predicates::intersects_tag>::apply(i, p.geometry);
0502 }
0503 };
0504
0505
0506
0507 template <typename DistancePredicates>
0508 struct predicate_check<predicates::nearest<DistancePredicates>, bounds_tag>
0509 {
0510 template <typename Value, typename Box, typename Strategy>
0511 static inline bool apply(predicates::nearest<DistancePredicates> const&, Value const&, Box const&, Strategy const&)
0512 {
0513 return true;
0514 }
0515 };
0516
0517 template <typename Linestring>
0518 struct predicate_check<predicates::path<Linestring>, bounds_tag>
0519 {
0520 template <typename Value, typename Box, typename Strategy>
0521 static inline bool apply(predicates::path<Linestring> const&, Value const&, Box const&, Strategy const&)
0522 {
0523 return true;
0524 }
0525 };
0526
0527
0528
0529
0530
0531 template <typename T>
0532 struct predicates_length
0533 {
0534 static const std::size_t value = 1;
0535 };
0536
0537 template <typename ...Ts>
0538 struct predicates_length<std::tuple<Ts...>>
0539 {
0540 static const std::size_t value = std::tuple_size<std::tuple<Ts...>>::value;
0541 };
0542
0543
0544
0545
0546
0547 template <std::size_t I, typename T>
0548 struct predicates_element
0549 {
0550 BOOST_GEOMETRY_STATIC_ASSERT((I < 1),
0551 "Invalid I index.",
0552 std::integral_constant<std::size_t, I>);
0553
0554 typedef T type;
0555 static type const& get(T const& p) { return p; }
0556 };
0557
0558 template <std::size_t I, typename ...Ts>
0559 struct predicates_element<I, std::tuple<Ts...>>
0560 {
0561 typedef std::tuple<Ts...> predicate_type;
0562
0563 typedef typename std::tuple_element<I, predicate_type>::type type;
0564 static type const& get(predicate_type const& p) { return std::get<I>(p); }
0565 };
0566
0567
0568
0569
0570
0571 template <typename TuplePredicates, typename Tag, std::size_t First, std::size_t Last>
0572 struct predicates_check_tuple
0573 {
0574 template <typename Value, typename Indexable, typename Strategy>
0575 static inline bool apply(TuplePredicates const& p, Value const& v, Indexable const& i, Strategy const& s)
0576 {
0577 return predicate_check
0578 <
0579 typename std::tuple_element<First, TuplePredicates>::type,
0580 Tag
0581 >::apply(std::get<First>(p), v, i, s)
0582 && predicates_check_tuple<TuplePredicates, Tag, First+1, Last>::apply(p, v, i, s);
0583 }
0584 };
0585
0586 template <typename TuplePredicates, typename Tag, std::size_t First>
0587 struct predicates_check_tuple<TuplePredicates, Tag, First, First>
0588 {
0589 template <typename Value, typename Indexable, typename Strategy>
0590 static inline bool apply(TuplePredicates const& , Value const& , Indexable const& , Strategy const& )
0591 {
0592 return true;
0593 }
0594 };
0595
0596 template <typename Predicate, typename Tag, std::size_t First, std::size_t Last>
0597 struct predicates_check_impl
0598 {
0599 static const bool check = First < 1 && Last <= 1 && First <= Last;
0600 BOOST_GEOMETRY_STATIC_ASSERT((check),
0601 "Invalid First or Last index.",
0602 std::integer_sequence<std::size_t, First, Last>);
0603
0604 template <typename Value, typename Indexable, typename Strategy>
0605 static inline bool apply(Predicate const& p, Value const& v, Indexable const& i, Strategy const& s)
0606 {
0607 return predicate_check<Predicate, Tag>::apply(p, v, i, s);
0608 }
0609 };
0610
0611 template <typename ...Ts, typename Tag, std::size_t First, std::size_t Last>
0612 struct predicates_check_impl<std::tuple<Ts...>, Tag, First, Last>
0613 {
0614 typedef std::tuple<Ts...> predicates_type;
0615
0616 static const std::size_t pred_len = std::tuple_size<predicates_type>::value;
0617 static const bool check = First < pred_len && Last <= pred_len && First <= Last;
0618 BOOST_GEOMETRY_STATIC_ASSERT((check),
0619 "Invalid First or Last index.",
0620 std::integer_sequence<std::size_t, First, Last>);
0621
0622 template <typename Value, typename Indexable, typename Strategy>
0623 static inline bool apply(predicates_type const& p, Value const& v, Indexable const& i, Strategy const& s)
0624 {
0625 return predicates_check_tuple
0626 <
0627 predicates_type,
0628 Tag, First, Last
0629 >::apply(p, v, i, s);
0630 }
0631 };
0632
0633 template <typename Tag, typename Predicates, typename Value, typename Indexable, typename Strategy>
0634 inline bool predicates_check(Predicates const& p, Value const& v, Indexable const& i, Strategy const& s)
0635 {
0636 return detail::predicates_check_impl
0637 <
0638 Predicates, Tag, 0, predicates_length<Predicates>::value
0639 >::apply(p, v, i, s);
0640 }
0641
0642
0643
0644
0645
0646
0647
0648 template <typename P>
0649 struct predicates_is_distance
0650 {
0651 static const std::size_t value = 0;
0652 };
0653
0654 template <typename DistancePredicates>
0655 struct predicates_is_distance< predicates::nearest<DistancePredicates> >
0656 {
0657 static const std::size_t value = 1;
0658 };
0659
0660 template <typename Linestring>
0661 struct predicates_is_distance< predicates::path<Linestring> >
0662 {
0663 static const std::size_t value = 1;
0664 };
0665
0666
0667
0668 template <typename T>
0669 struct predicates_count_distance
0670 {
0671 static const std::size_t value = predicates_is_distance<T>::value;
0672 };
0673
0674 template <typename Tuple, std::size_t N>
0675 struct predicates_count_distance_tuple
0676 {
0677 static const std::size_t value =
0678 predicates_is_distance<typename std::tuple_element<N-1, Tuple>::type>::value
0679 + predicates_count_distance_tuple<Tuple, N-1>::value;
0680 };
0681
0682 template <typename Tuple>
0683 struct predicates_count_distance_tuple<Tuple, 1>
0684 {
0685 static const std::size_t value =
0686 predicates_is_distance<typename std::tuple_element<0, Tuple>::type>::value;
0687 };
0688
0689 template <typename ...Ts>
0690 struct predicates_count_distance<std::tuple<Ts...>>
0691 {
0692 static const std::size_t value = predicates_count_distance_tuple<
0693 std::tuple<Ts...>,
0694 std::tuple_size<std::tuple<Ts...>>::value
0695 >::value;
0696 };
0697
0698
0699
0700 template <typename T>
0701 struct predicates_find_distance
0702 {
0703 static const std::size_t value = predicates_is_distance<T>::value ? 0 : 1;
0704 };
0705
0706 template <typename Tuple, std::size_t N>
0707 struct predicates_find_distance_tuple
0708 {
0709 static const bool is_found = predicates_find_distance_tuple<Tuple, N-1>::is_found
0710 || predicates_is_distance<typename std::tuple_element<N-1, Tuple>::type>::value;
0711
0712 static const std::size_t value = predicates_find_distance_tuple<Tuple, N-1>::is_found ?
0713 predicates_find_distance_tuple<Tuple, N-1>::value :
0714 (predicates_is_distance<typename std::tuple_element<N-1, Tuple>::type>::value ?
0715 N-1 : std::tuple_size<Tuple>::value);
0716 };
0717
0718 template <typename Tuple>
0719 struct predicates_find_distance_tuple<Tuple, 1>
0720 {
0721 static const bool is_found = predicates_is_distance<typename std::tuple_element<0, Tuple>::type>::value;
0722 static const std::size_t value = is_found ? 0 : std::tuple_size<Tuple>::value;
0723 };
0724
0725 template <typename ...Ts>
0726 struct predicates_find_distance<std::tuple<Ts...>>
0727 {
0728 static const std::size_t value = predicates_find_distance_tuple<
0729 std::tuple<Ts...>,
0730 std::tuple_size<std::tuple<Ts...>>::value
0731 >::value;
0732 };
0733
0734 }}}}
0735
0736 #endif