// Boost.Geometry Index // // Spatial query predicates definition and checks. // // Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland. // // This file was modified by Oracle on 2019-2020. // Modifications copyright (c) 2019-2020 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_GEOMETRY_INDEX_DETAIL_PREDICATES_HPP #define BOOST_GEOMETRY_INDEX_DETAIL_PREDICATES_HPP #include #include //#include #include #include namespace boost { namespace geometry { namespace index { namespace detail { namespace predicates { // ------------------------------------------------------------------ // // predicates // ------------------------------------------------------------------ // template struct satisfies_impl { satisfies_impl() : fun(NULL) {} satisfies_impl(Fun f) : fun(f) {} Fun * fun; }; template struct satisfies_impl { satisfies_impl() {} satisfies_impl(Fun const& f) : fun(f) {} Fun fun; }; template struct satisfies : satisfies_impl::value> { typedef satisfies_impl::value> base; satisfies() {} satisfies(Fun const& f) : base(f) {} satisfies(base const& b) : base(b) {} }; // ------------------------------------------------------------------ // struct contains_tag {}; struct covered_by_tag {}; struct covers_tag {}; struct disjoint_tag {}; struct intersects_tag {}; struct overlaps_tag {}; struct touches_tag {}; struct within_tag {}; template struct spatial_predicate { spatial_predicate() {} spatial_predicate(Geometry const& g) : geometry(g) {} Geometry geometry; }; // ------------------------------------------------------------------ // // CONSIDER: separated nearest<> and path<> may be replaced by // nearest_predicate // where Tag = point_tag | path_tag // IMPROVEMENT: user-defined nearest predicate allowing to define // all or only geometrical aspects of the search template struct nearest { nearest() // : count(0) {} nearest(PointOrRelation const& por, unsigned k) : point_or_relation(por) , count(k) {} PointOrRelation point_or_relation; unsigned count; }; template struct path { path() // : count(0) {} path(SegmentOrLinestring const& g, unsigned k) : geometry(g) , count(k) {} SegmentOrLinestring geometry; unsigned count; }; } // namespace predicates // ------------------------------------------------------------------ // // predicate_check // ------------------------------------------------------------------ // template struct predicate_check { BOOST_GEOMETRY_STATIC_ASSERT_FALSE( "Not implemented for this Predicate or Tag.", Predicate, Tag); }; // ------------------------------------------------------------------ // template struct predicate_check, value_tag> { template static inline bool apply(predicates::satisfies const& p, Value const& v, Indexable const& , Strategy const&) { return p.fun(v); } }; template struct predicate_check, value_tag> { template static inline bool apply(predicates::satisfies const& p, Value const& v, Indexable const& , Strategy const&) { return !p.fun(v); } }; // ------------------------------------------------------------------ // template struct spatial_predicate_call { BOOST_GEOMETRY_STATIC_ASSERT_FALSE( "Not implemented for this Tag.", Tag); }; template <> struct spatial_predicate_call { template static inline bool apply(G1 const& g1, G2 const& g2, S const&) { return geometry::within(g2, g1); } }; template <> struct spatial_predicate_call { template static inline bool apply(G1 const& g1, G2 const& g2, S const&) { return geometry::covered_by(g1, g2); } }; template <> struct spatial_predicate_call { template static inline bool apply(G1 const& g1, G2 const& g2, S const&) { return geometry::covered_by(g2, g1); } }; template <> struct spatial_predicate_call { template static inline bool apply(G1 const& g1, G2 const& g2, S const&) { return geometry::disjoint(g1, g2); } }; // TEMP: used to implement CS-specific intersects predicate for certain // combinations of geometries until umbrella strategies are implemented template < typename G1, typename G2, typename Tag1 = typename tag::type, typename Tag2 = typename tag::type > struct spatial_predicate_intersects { template static inline bool apply(G1 const& g1, G2 const& g2, S const&) { return geometry::intersects(g1, g2); } }; // TEMP: used in within and relate template struct spatial_predicate_intersects { static inline bool apply(G1 const& g1, G2 const& g2, default_strategy const&) { return geometry::intersects(g1, g2); } template static inline bool apply(G1 const& g1, G2 const& g2, S const& s) { return geometry::intersects(g1, g2, s); } }; template <> struct spatial_predicate_call { template static inline bool apply(G1 const& g1, G2 const& g2, S const& s) { return spatial_predicate_intersects::apply(g1, g2, s); } }; template <> struct spatial_predicate_call { template static inline bool apply(G1 const& g1, G2 const& g2, S const&) { return geometry::overlaps(g1, g2); } }; template <> struct spatial_predicate_call { template static inline bool apply(G1 const& g1, G2 const& g2, S const&) { return geometry::touches(g1, g2); } }; template <> struct spatial_predicate_call { template static inline bool apply(G1 const& g1, G2 const& g2, S const&) { return geometry::within(g1, g2); } }; // ------------------------------------------------------------------ // // spatial predicate template struct predicate_check, value_tag> { typedef predicates::spatial_predicate Pred; template static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s) { return spatial_predicate_call::apply(i, p.geometry, s); } }; // negated spatial predicate template struct predicate_check, value_tag> { typedef predicates::spatial_predicate Pred; template static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s) { return !spatial_predicate_call::apply(i, p.geometry, s); } }; // ------------------------------------------------------------------ // template struct predicate_check, value_tag> { template static inline bool apply(predicates::nearest const&, Value const&, Box const&, Strategy const&) { return true; } }; template struct predicate_check, value_tag> { template static inline bool apply(predicates::path const&, Value const&, Box const&, Strategy const&) { return true; } }; // ------------------------------------------------------------------ // // predicates_check for bounds // ------------------------------------------------------------------ // template struct predicate_check, bounds_tag> { template static bool apply(predicates::satisfies const&, Value const&, Box const&, Strategy const&) { return true; } }; // ------------------------------------------------------------------ // // NOT NEGATED // value_tag bounds_tag // --------------------------- // contains(I,G) covers(I,G) // covered_by(I,G) intersects(I,G) // covers(I,G) covers(I,G) // disjoint(I,G) !covered_by(I,G) // intersects(I,G) intersects(I,G) // 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 // touches(I,G) intersects(I,G) // 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 // spatial predicate - default template struct predicate_check, bounds_tag> { typedef predicates::spatial_predicate Pred; template static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s) { return spatial_predicate_call::apply(i, p.geometry, s); } }; // spatial predicate - contains template struct predicate_check, bounds_tag> { typedef predicates::spatial_predicate Pred; template static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s) { return spatial_predicate_call::apply(i, p.geometry, s); } }; // spatial predicate - covers template struct predicate_check, bounds_tag> { typedef predicates::spatial_predicate Pred; template static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s) { return spatial_predicate_call::apply(i, p.geometry, s); } }; // spatial predicate - disjoint template struct predicate_check, bounds_tag> { typedef predicates::spatial_predicate Pred; template static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s) { return !spatial_predicate_call::apply(i, p.geometry, s); } }; // NEGATED // value_tag bounds_tag // --------------------------- // !contains(I,G) TRUE // !covered_by(I,G) !covered_by(I,G) // !covers(I,G) TRUE // !disjoint(I,G) !disjoint(I,G) // !intersects(I,G) !covered_by(I,G) // !overlaps(I,G) TRUE // !touches(I,G) !intersects(I,G) // !within(I,G) !within(I,G) // negated spatial predicate - default template struct predicate_check, bounds_tag> { typedef predicates::spatial_predicate Pred; template static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s) { return !spatial_predicate_call::apply(i, p.geometry, s); } }; // negated spatial predicate - contains template struct predicate_check, bounds_tag> { typedef predicates::spatial_predicate Pred; template static inline bool apply(Pred const& , Value const&, Indexable const&, Strategy const&) { return true; } }; // negated spatial predicate - covers template struct predicate_check, bounds_tag> { typedef predicates::spatial_predicate Pred; template static inline bool apply(Pred const& , Value const&, Indexable const&, Strategy const&) { return true; } }; // negated spatial predicate - intersects template struct predicate_check, bounds_tag> { typedef predicates::spatial_predicate Pred; template static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s) { return !spatial_predicate_call::apply(i, p.geometry, s); } }; // negated spatial predicate - overlaps template struct predicate_check, bounds_tag> { typedef predicates::spatial_predicate Pred; template static inline bool apply(Pred const& , Value const&, Indexable const&, Strategy const&) { return true; } }; // negated spatial predicate - touches template struct predicate_check, bounds_tag> { typedef predicates::spatial_predicate Pred; template static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const&) { return !spatial_predicate_call::apply(i, p.geometry); } }; // ------------------------------------------------------------------ // template struct predicate_check, bounds_tag> { template static inline bool apply(predicates::nearest const&, Value const&, Box const&, Strategy const&) { return true; } }; template struct predicate_check, bounds_tag> { template static inline bool apply(predicates::path const&, Value const&, Box const&, Strategy const&) { return true; } }; // ------------------------------------------------------------------ // // predicates_length // ------------------------------------------------------------------ // template struct predicates_length { static const unsigned value = 1; }; template struct predicates_length> { static const unsigned value = std::tuple_size>::value; }; // ------------------------------------------------------------------ // // predicates_element // ------------------------------------------------------------------ // template struct predicates_element { BOOST_GEOMETRY_STATIC_ASSERT((I < 1), "Invalid I index.", std::integral_constant); typedef T type; static type const& get(T const& p) { return p; } }; template struct predicates_element> { typedef std::tuple predicate_type; typedef typename std::tuple_element::type type; static type const& get(predicate_type const& p) { return std::get(p); } }; // ------------------------------------------------------------------ // // predicates_check // ------------------------------------------------------------------ // template struct predicates_check_tuple { template static inline bool apply(TuplePredicates const& p, Value const& v, Indexable const& i, Strategy const& s) { return predicate_check < typename std::tuple_element::type, Tag >::apply(std::get(p), v, i, s) && predicates_check_tuple::apply(p, v, i, s); } }; template struct predicates_check_tuple { template static inline bool apply(TuplePredicates const& , Value const& , Indexable const& , Strategy const& ) { return true; } }; template struct predicates_check_impl { static const bool check = First < 1 && Last <= 1 && First <= Last; BOOST_GEOMETRY_STATIC_ASSERT((check), "Invalid First or Last index.", std::integer_sequence); template static inline bool apply(Predicate const& p, Value const& v, Indexable const& i, Strategy const& s) { return predicate_check::apply(p, v, i, s); } }; template struct predicates_check_impl, Tag, First, Last> { typedef std::tuple predicates_type; static const unsigned pred_len = std::tuple_size::value; static const bool check = First < pred_len && Last <= pred_len && First <= Last; BOOST_GEOMETRY_STATIC_ASSERT((check), "Invalid First or Last index.", std::integer_sequence); template static inline bool apply(predicates_type const& p, Value const& v, Indexable const& i, Strategy const& s) { return predicates_check_tuple < predicates_type, Tag, First, Last >::apply(p, v, i, s); } }; template inline bool predicates_check(Predicates const& p, Value const& v, Indexable const& i, Strategy const& s) { return detail::predicates_check_impl ::apply(p, v, i, s); } // ------------------------------------------------------------------ // // nearest predicate helpers // ------------------------------------------------------------------ // // predicates_is_nearest template struct predicates_is_distance { static const unsigned value = 0; }; template struct predicates_is_distance< predicates::nearest > { static const unsigned value = 1; }; template struct predicates_is_distance< predicates::path > { static const unsigned value = 1; }; // predicates_count_nearest template struct predicates_count_distance { static const unsigned value = predicates_is_distance::value; }; template struct predicates_count_distance_tuple { static const unsigned value = predicates_is_distance::type>::value + predicates_count_distance_tuple::value; }; template struct predicates_count_distance_tuple { static const unsigned value = predicates_is_distance::type>::value; }; template struct predicates_count_distance> { static const unsigned value = predicates_count_distance_tuple< std::tuple, std::tuple_size>::value >::value; }; // predicates_find_nearest template struct predicates_find_distance { static const unsigned value = predicates_is_distance::value ? 0 : 1; }; template struct predicates_find_distance_tuple { static const bool is_found = predicates_find_distance_tuple::is_found || predicates_is_distance::type>::value; static const unsigned value = predicates_find_distance_tuple::is_found ? predicates_find_distance_tuple::value : (predicates_is_distance::type>::value ? N-1 : std::tuple_size::value); }; template struct predicates_find_distance_tuple { static const bool is_found = predicates_is_distance::type>::value; static const unsigned value = is_found ? 0 : std::tuple_size::value; }; template struct predicates_find_distance> { static const unsigned value = predicates_find_distance_tuple< std::tuple, std::tuple_size>::value >::value; }; }}}} // namespace boost::geometry::index::detail #endif // BOOST_GEOMETRY_INDEX_DETAIL_PREDICATES_HPP