Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: pass umbrella strategies in rtree spatial predicates #1368

Merged
merged 3 commits into from
Jan 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 14 additions & 46 deletions include/boost/geometry/index/detail/predicates.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,71 +174,39 @@ template <>
struct spatial_predicate_call<predicates::contains_tag>
{
template <typename G1, typename G2, typename S>
static inline bool apply(G1 const& g1, G2 const& g2, S const&)
static inline bool apply(G1 const& g1, G2 const& g2, S const& s)
{
return geometry::within(g2, g1);
return geometry::within(g2, g1, s);
}
};

template <>
struct spatial_predicate_call<predicates::covered_by_tag>
{
template <typename G1, typename G2, typename S>
static inline bool apply(G1 const& g1, G2 const& g2, S const&)
static inline bool apply(G1 const& g1, G2 const& g2, S const& s)
{
return geometry::covered_by(g1, g2);
return geometry::covered_by(g1, g2, s);
}
};

template <>
struct spatial_predicate_call<predicates::covers_tag>
{
template <typename G1, typename G2, typename S>
static inline bool apply(G1 const& g1, G2 const& g2, S const&)
static inline bool apply(G1 const& g1, G2 const& g2, S const& s)
{
return geometry::covered_by(g2, g1);
return geometry::covered_by(g2, g1, s);
}
};

template <>
struct spatial_predicate_call<predicates::disjoint_tag>
{
template <typename G1, typename G2, typename S>
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 = tag_t<G1>,
typename Tag2 = tag_t<G2>
>
struct spatial_predicate_intersects
{
template <typename S>
static inline bool apply(G1 const& g1, G2 const& g2, S const&)
{
return geometry::intersects(g1, g2);
}
};
// TEMP: used in within and relate
template <typename G1, typename G2>
struct spatial_predicate_intersects<G1, G2, box_tag, point_tag>
{
static inline bool apply(G1 const& g1, G2 const& g2, default_strategy const&)
{
return geometry::intersects(g1, g2);
}

template <typename S>
static inline bool apply(G1 const& g1, G2 const& g2, S const& s)
{
return geometry::intersects(g1, g2, s);
return geometry::disjoint(g1, g2, s);
}
};

Expand All @@ -248,37 +216,37 @@ struct spatial_predicate_call<predicates::intersects_tag>
template <typename G1, typename G2, typename S>
static inline bool apply(G1 const& g1, G2 const& g2, S const& s)
{
return spatial_predicate_intersects<G1, G2>::apply(g1, g2, s);
return geometry::intersects(g1, g2, s);
}
};

template <>
struct spatial_predicate_call<predicates::overlaps_tag>
{
template <typename G1, typename G2, typename S>
static inline bool apply(G1 const& g1, G2 const& g2, S const&)
static inline bool apply(G1 const& g1, G2 const& g2, S const& s)
{
return geometry::overlaps(g1, g2);
return geometry::overlaps(g1, g2, s);
}
};

template <>
struct spatial_predicate_call<predicates::touches_tag>
{
template <typename G1, typename G2, typename S>
static inline bool apply(G1 const& g1, G2 const& g2, S const&)
static inline bool apply(G1 const& g1, G2 const& g2, S const& s)
{
return geometry::touches(g1, g2);
return geometry::touches(g1, g2, s);
}
};

template <>
struct spatial_predicate_call<predicates::within_tag>
{
template <typename G1, typename G2, typename S>
static inline bool apply(G1 const& g1, G2 const& g2, S const&)
static inline bool apply(G1 const& g1, G2 const& g2, S const& s)
{
return geometry::within(g1, g2);
return geometry::within(g1, g2, s);
}
};

Expand Down
2 changes: 2 additions & 0 deletions index/test/rtree/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Boost.Geometry
# Copyright (c) 2025 Adam Wulkiewicz, Lodz, Poland.
# Copyright (c) 2024, Oracle and/or its affiliates.
# Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
# Use, modification and distribution is subject to the Boost Software License,
Expand All @@ -13,6 +14,7 @@ foreach(item IN ITEMS
rtree_move_pack
rtree_non_cartesian
rtree_values
rtree_with_strategies
#compile-fail rtree_values_invalid
)
boost_geometry_add_unit_test("index" ${item})
Expand Down
3 changes: 2 additions & 1 deletion index/test/rtree/Jamfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Boost.Geometry Index
#
# Copyright (c) 2011-2016 Adam Wulkiewicz, Lodz, Poland.
# Copyright (c) 2011-2025 Adam Wulkiewicz, Lodz, Poland.
#
# Use, modification and distribution is subject to the Boost Software License,
# Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
Expand All @@ -19,5 +19,6 @@ test-suite boost-geometry-index-rtree
[ run rtree_move_pack.cpp ]
[ run rtree_non_cartesian.cpp ]
[ run rtree_values.cpp ]
[ compile rtree_with_strategies.cpp ]
[ compile-fail rtree_values_invalid.cpp ]
;
160 changes: 160 additions & 0 deletions index/test/rtree/rtree_with_strategies.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
// Boost.Geometry Index
// Unit Test

// Copyright (c) 2025 Adam Wulkiewicz, Lodz, Poland.

// 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)

#include <vector>

#define BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL_PREDICATES
awulkiew marked this conversation as resolved.
Show resolved Hide resolved

#include <geometry_index_test_common.hpp>

#include <boost/geometry/geometries/register/point.hpp>
#include <boost/geometry/geometries/register/box.hpp>
#include <boost/geometry/geometries/register/segment.hpp>

struct point { double x, y; };
struct box { point mi, ma; };
struct segment { point first, second; };

BOOST_GEOMETRY_REGISTER_POINT_2D(point, double, cs::undefined, x, y)
BOOST_GEOMETRY_REGISTER_BOX(box, point, mi, ma)
BOOST_GEOMETRY_REGISTER_SEGMENT(segment, point, first, second)

template <typename QueryValue, typename Rtree>
constexpr bool is_bp_or_bb_v = (bg::util::is_box<QueryValue>::value
&& bg::util::is_point<typename Rtree::value_type>::value)
|| (bg::util::is_box<QueryValue>::value
&& bg::util::is_box<typename Rtree::value_type>::value);

template <typename QueryValue, typename Rtree>
constexpr bool is_pb_or_bb_v = (bg::util::is_point<QueryValue>::value
&& bg::util::is_box<typename Rtree::value_type>::value)
|| (bg::util::is_box<QueryValue>::value
&& bg::util::is_box<typename Rtree::value_type>::value);

template <typename QueryValue, typename Rtree>
constexpr bool is_pp_or_bb_v = (bg::util::is_point<QueryValue>::value
&& bg::util::is_point<typename Rtree::value_type>::value)
|| (bg::util::is_box<QueryValue>::value
&& bg::util::is_box<typename Rtree::value_type>::value);

template
<
typename QueryValue, typename Rtree,
std::enable_if_t<is_bp_or_bb_v<QueryValue, Rtree>, int> = 0
>
void test_queries_bp_bb(Rtree const& rtree)
{
// These predicates use algorithms that are not implemented for
// some geometry combinations
std::vector<typename Rtree::value_type> values;
rtree.query(bgi::covered_by(QueryValue{}), std::back_inserter(values));
rtree.query(bgi::disjoint(QueryValue{}), std::back_inserter(values));
rtree.query(bgi::within(QueryValue{}), std::back_inserter(values));
}

template
<
typename QueryValue, typename Rtree,
std::enable_if_t<(!is_bp_or_bb_v<QueryValue, Rtree>), int> = 0
>
void test_queries_bp_bb(Rtree const& ) {}

template
<
typename QueryValue, typename Rtree,
std::enable_if_t<is_pb_or_bb_v<QueryValue, Rtree>, int> = 0
>
void test_queries_pb_bb(Rtree const& rtree)
{
// These predicates use algorithms that are not implemented for
// some geometry combinations
vissarion marked this conversation as resolved.
Show resolved Hide resolved
std::vector<typename Rtree::value_type> values;
rtree.query(bgi::contains(QueryValue{}), std::back_inserter(values));
rtree.query(bgi::covers(QueryValue{}), std::back_inserter(values));
}

template
<
typename QueryValue, typename Rtree,
std::enable_if_t<(!is_pb_or_bb_v<QueryValue, Rtree>), int> = 0
>
void test_queries_pb_bb(Rtree const& ) {}

template
<
typename QueryValue, typename Rtree,
std::enable_if_t<is_pp_or_bb_v<QueryValue, Rtree>, int> = 0
>
void test_queries_pp_bb(Rtree const& rtree)
{
// These predicates use algorithms that are not implemented for
// some geometry combinations
std::vector<typename Rtree::value_type> values;
rtree.query(bgi::overlaps(QueryValue{}), std::back_inserter(values));
rtree.query(bgi::touches(QueryValue{}), std::back_inserter(values));
}

template
<
typename QueryValue, typename Rtree,
std::enable_if_t<(!is_pp_or_bb_v<QueryValue, Rtree>), int> = 0
>
void test_queries_pp_bb(Rtree const& ) {}

template <typename QueryValue, typename Rtree>
void test_queries(Rtree const& rtree)
{
std::vector<typename Rtree::value_type> values;
rtree.query(bgi::intersects(QueryValue{}), std::back_inserter(values));
rtree.query(bgi::nearest(QueryValue{}, 1), std::back_inserter(values));
test_queries_bp_bb<QueryValue>(rtree);
test_queries_pb_bb<QueryValue>(rtree);
test_queries_pp_bb<QueryValue>(rtree);
}

template <typename Value, typename Params, typename Strategies>
void test_strategies()
{
std::vector<Value> values;
bgi::rtree<Value, bgi::parameters<Params, Strategies>> rtree{values};
rtree.insert(Value{});
rtree.remove(Value{});

test_queries<point>(rtree);
test_queries<box>(rtree);
test_queries<segment>(rtree);
}

template <typename Value, typename Params>
void test_params()
{
test_strategies<Value, Params, bg::strategies::index::cartesian<>>();
test_strategies<Value, Params, bg::strategies::cartesian<>>();
awulkiew marked this conversation as resolved.
Show resolved Hide resolved
test_strategies<Value, Params, bg::strategies::index::spherical<>>();
test_strategies<Value, Params, bg::strategies::spherical<>>();
test_strategies<Value, Params, bg::strategies::index::geographic<>>();
test_strategies<Value, Params, bg::strategies::geographic<>>();
}

template <typename Value>
void test_value()
{
test_params<Value, bgi::linear<4>>();
test_params<Value, bgi::quadratic<4>>();
test_params<Value, bgi::rstar<4>>();
awulkiew marked this conversation as resolved.
Show resolved Hide resolved
}

int test_main(int, char* [])
{
test_value<point>();
test_value<box>();
test_value<segment>();

return 0;
}
Loading