Skip to content

Commit eeeb75a

Browse files
authored
Merge pull request #1368 from awulkiew/fix/rtree_strategies
fix: pass umbrella strategies in rtree spatial predicates
2 parents b935617 + 4178bec commit eeeb75a

File tree

4 files changed

+178
-47
lines changed

4 files changed

+178
-47
lines changed

include/boost/geometry/index/detail/predicates.hpp

+14-46
Original file line numberDiff line numberDiff line change
@@ -174,71 +174,39 @@ template <>
174174
struct spatial_predicate_call<predicates::contains_tag>
175175
{
176176
template <typename G1, typename G2, typename S>
177-
static inline bool apply(G1 const& g1, G2 const& g2, S const&)
177+
static inline bool apply(G1 const& g1, G2 const& g2, S const& s)
178178
{
179-
return geometry::within(g2, g1);
179+
return geometry::within(g2, g1, s);
180180
}
181181
};
182182

183183
template <>
184184
struct spatial_predicate_call<predicates::covered_by_tag>
185185
{
186186
template <typename G1, typename G2, typename S>
187-
static inline bool apply(G1 const& g1, G2 const& g2, S const&)
187+
static inline bool apply(G1 const& g1, G2 const& g2, S const& s)
188188
{
189-
return geometry::covered_by(g1, g2);
189+
return geometry::covered_by(g1, g2, s);
190190
}
191191
};
192192

193193
template <>
194194
struct spatial_predicate_call<predicates::covers_tag>
195195
{
196196
template <typename G1, typename G2, typename S>
197-
static inline bool apply(G1 const& g1, G2 const& g2, S const&)
197+
static inline bool apply(G1 const& g1, G2 const& g2, S const& s)
198198
{
199-
return geometry::covered_by(g2, g1);
199+
return geometry::covered_by(g2, g1, s);
200200
}
201201
};
202202

203203
template <>
204204
struct spatial_predicate_call<predicates::disjoint_tag>
205205
{
206206
template <typename G1, typename G2, typename S>
207-
static inline bool apply(G1 const& g1, G2 const& g2, S const&)
208-
{
209-
return geometry::disjoint(g1, g2);
210-
}
211-
};
212-
213-
// TEMP: used to implement CS-specific intersects predicate for certain
214-
// combinations of geometries until umbrella strategies are implemented
215-
template
216-
<
217-
typename G1, typename G2,
218-
typename Tag1 = tag_t<G1>,
219-
typename Tag2 = tag_t<G2>
220-
>
221-
struct spatial_predicate_intersects
222-
{
223-
template <typename S>
224-
static inline bool apply(G1 const& g1, G2 const& g2, S const&)
225-
{
226-
return geometry::intersects(g1, g2);
227-
}
228-
};
229-
// TEMP: used in within and relate
230-
template <typename G1, typename G2>
231-
struct spatial_predicate_intersects<G1, G2, box_tag, point_tag>
232-
{
233-
static inline bool apply(G1 const& g1, G2 const& g2, default_strategy const&)
234-
{
235-
return geometry::intersects(g1, g2);
236-
}
237-
238-
template <typename S>
239207
static inline bool apply(G1 const& g1, G2 const& g2, S const& s)
240208
{
241-
return geometry::intersects(g1, g2, s);
209+
return geometry::disjoint(g1, g2, s);
242210
}
243211
};
244212

@@ -248,37 +216,37 @@ struct spatial_predicate_call<predicates::intersects_tag>
248216
template <typename G1, typename G2, typename S>
249217
static inline bool apply(G1 const& g1, G2 const& g2, S const& s)
250218
{
251-
return spatial_predicate_intersects<G1, G2>::apply(g1, g2, s);
219+
return geometry::intersects(g1, g2, s);
252220
}
253221
};
254222

255223
template <>
256224
struct spatial_predicate_call<predicates::overlaps_tag>
257225
{
258226
template <typename G1, typename G2, typename S>
259-
static inline bool apply(G1 const& g1, G2 const& g2, S const&)
227+
static inline bool apply(G1 const& g1, G2 const& g2, S const& s)
260228
{
261-
return geometry::overlaps(g1, g2);
229+
return geometry::overlaps(g1, g2, s);
262230
}
263231
};
264232

265233
template <>
266234
struct spatial_predicate_call<predicates::touches_tag>
267235
{
268236
template <typename G1, typename G2, typename S>
269-
static inline bool apply(G1 const& g1, G2 const& g2, S const&)
237+
static inline bool apply(G1 const& g1, G2 const& g2, S const& s)
270238
{
271-
return geometry::touches(g1, g2);
239+
return geometry::touches(g1, g2, s);
272240
}
273241
};
274242

275243
template <>
276244
struct spatial_predicate_call<predicates::within_tag>
277245
{
278246
template <typename G1, typename G2, typename S>
279-
static inline bool apply(G1 const& g1, G2 const& g2, S const&)
247+
static inline bool apply(G1 const& g1, G2 const& g2, S const& s)
280248
{
281-
return geometry::within(g1, g2);
249+
return geometry::within(g1, g2, s);
282250
}
283251
};
284252

index/test/rtree/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# Boost.Geometry
2+
# Copyright (c) 2025 Adam Wulkiewicz, Lodz, Poland.
23
# Copyright (c) 2024, Oracle and/or its affiliates.
34
# Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
45
# Use, modification and distribution is subject to the Boost Software License,
@@ -13,6 +14,7 @@ foreach(item IN ITEMS
1314
rtree_move_pack
1415
rtree_non_cartesian
1516
rtree_values
17+
rtree_with_strategies
1618
#compile-fail rtree_values_invalid
1719
)
1820
boost_geometry_add_unit_test("index" ${item})

index/test/rtree/Jamfile

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Boost.Geometry Index
22
#
3-
# Copyright (c) 2011-2016 Adam Wulkiewicz, Lodz, Poland.
3+
# Copyright (c) 2011-2025 Adam Wulkiewicz, Lodz, Poland.
44
#
55
# Use, modification and distribution is subject to the Boost Software License,
66
# Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -19,5 +19,6 @@ test-suite boost-geometry-index-rtree
1919
[ run rtree_move_pack.cpp ]
2020
[ run rtree_non_cartesian.cpp ]
2121
[ run rtree_values.cpp ]
22+
[ compile rtree_with_strategies.cpp ]
2223
[ compile-fail rtree_values_invalid.cpp ]
2324
;
+160
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
// Boost.Geometry Index
2+
// Unit Test
3+
4+
// Copyright (c) 2025 Adam Wulkiewicz, Lodz, Poland.
5+
6+
// Use, modification and distribution is subject to the Boost Software License,
7+
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
8+
// http://www.boost.org/LICENSE_1_0.txt)
9+
10+
#include <vector>
11+
12+
#define BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL_PREDICATES
13+
14+
#include <geometry_index_test_common.hpp>
15+
16+
#include <boost/geometry/geometries/register/point.hpp>
17+
#include <boost/geometry/geometries/register/box.hpp>
18+
#include <boost/geometry/geometries/register/segment.hpp>
19+
20+
struct point { double x, y; };
21+
struct box { point mi, ma; };
22+
struct segment { point first, second; };
23+
24+
BOOST_GEOMETRY_REGISTER_POINT_2D(point, double, cs::undefined, x, y)
25+
BOOST_GEOMETRY_REGISTER_BOX(box, point, mi, ma)
26+
BOOST_GEOMETRY_REGISTER_SEGMENT(segment, point, first, second)
27+
28+
template <typename QueryValue, typename Rtree>
29+
constexpr bool is_bp_or_bb_v = (bg::util::is_box<QueryValue>::value
30+
&& bg::util::is_point<typename Rtree::value_type>::value)
31+
|| (bg::util::is_box<QueryValue>::value
32+
&& bg::util::is_box<typename Rtree::value_type>::value);
33+
34+
template <typename QueryValue, typename Rtree>
35+
constexpr bool is_pb_or_bb_v = (bg::util::is_point<QueryValue>::value
36+
&& bg::util::is_box<typename Rtree::value_type>::value)
37+
|| (bg::util::is_box<QueryValue>::value
38+
&& bg::util::is_box<typename Rtree::value_type>::value);
39+
40+
template <typename QueryValue, typename Rtree>
41+
constexpr bool is_pp_or_bb_v = (bg::util::is_point<QueryValue>::value
42+
&& bg::util::is_point<typename Rtree::value_type>::value)
43+
|| (bg::util::is_box<QueryValue>::value
44+
&& bg::util::is_box<typename Rtree::value_type>::value);
45+
46+
template
47+
<
48+
typename QueryValue, typename Rtree,
49+
std::enable_if_t<is_bp_or_bb_v<QueryValue, Rtree>, int> = 0
50+
>
51+
void test_queries_bp_bb(Rtree const& rtree)
52+
{
53+
// These predicates use algorithms that are not implemented for
54+
// some geometry combinations
55+
std::vector<typename Rtree::value_type> values;
56+
rtree.query(bgi::covered_by(QueryValue{}), std::back_inserter(values));
57+
rtree.query(bgi::disjoint(QueryValue{}), std::back_inserter(values));
58+
rtree.query(bgi::within(QueryValue{}), std::back_inserter(values));
59+
}
60+
61+
template
62+
<
63+
typename QueryValue, typename Rtree,
64+
std::enable_if_t<(!is_bp_or_bb_v<QueryValue, Rtree>), int> = 0
65+
>
66+
void test_queries_bp_bb(Rtree const& ) {}
67+
68+
template
69+
<
70+
typename QueryValue, typename Rtree,
71+
std::enable_if_t<is_pb_or_bb_v<QueryValue, Rtree>, int> = 0
72+
>
73+
void test_queries_pb_bb(Rtree const& rtree)
74+
{
75+
// These predicates use algorithms that are not implemented for
76+
// some geometry combinations
77+
std::vector<typename Rtree::value_type> values;
78+
rtree.query(bgi::contains(QueryValue{}), std::back_inserter(values));
79+
rtree.query(bgi::covers(QueryValue{}), std::back_inserter(values));
80+
}
81+
82+
template
83+
<
84+
typename QueryValue, typename Rtree,
85+
std::enable_if_t<(!is_pb_or_bb_v<QueryValue, Rtree>), int> = 0
86+
>
87+
void test_queries_pb_bb(Rtree const& ) {}
88+
89+
template
90+
<
91+
typename QueryValue, typename Rtree,
92+
std::enable_if_t<is_pp_or_bb_v<QueryValue, Rtree>, int> = 0
93+
>
94+
void test_queries_pp_bb(Rtree const& rtree)
95+
{
96+
// These predicates use algorithms that are not implemented for
97+
// some geometry combinations
98+
std::vector<typename Rtree::value_type> values;
99+
rtree.query(bgi::overlaps(QueryValue{}), std::back_inserter(values));
100+
rtree.query(bgi::touches(QueryValue{}), std::back_inserter(values));
101+
}
102+
103+
template
104+
<
105+
typename QueryValue, typename Rtree,
106+
std::enable_if_t<(!is_pp_or_bb_v<QueryValue, Rtree>), int> = 0
107+
>
108+
void test_queries_pp_bb(Rtree const& ) {}
109+
110+
template <typename QueryValue, typename Rtree>
111+
void test_queries(Rtree const& rtree)
112+
{
113+
std::vector<typename Rtree::value_type> values;
114+
rtree.query(bgi::intersects(QueryValue{}), std::back_inserter(values));
115+
rtree.query(bgi::nearest(QueryValue{}, 1), std::back_inserter(values));
116+
test_queries_bp_bb<QueryValue>(rtree);
117+
test_queries_pb_bb<QueryValue>(rtree);
118+
test_queries_pp_bb<QueryValue>(rtree);
119+
}
120+
121+
template <typename Value, typename Params, typename Strategies>
122+
void test_strategies()
123+
{
124+
std::vector<Value> values;
125+
bgi::rtree<Value, bgi::parameters<Params, Strategies>> rtree{values};
126+
rtree.insert(Value{});
127+
rtree.remove(Value{});
128+
129+
test_queries<point>(rtree);
130+
test_queries<box>(rtree);
131+
test_queries<segment>(rtree);
132+
}
133+
134+
template <typename Value, typename Params>
135+
void test_params()
136+
{
137+
test_strategies<Value, Params, bg::strategies::index::cartesian<>>();
138+
test_strategies<Value, Params, bg::strategies::cartesian<>>();
139+
test_strategies<Value, Params, bg::strategies::index::spherical<>>();
140+
test_strategies<Value, Params, bg::strategies::spherical<>>();
141+
test_strategies<Value, Params, bg::strategies::index::geographic<>>();
142+
test_strategies<Value, Params, bg::strategies::geographic<>>();
143+
}
144+
145+
template <typename Value>
146+
void test_value()
147+
{
148+
test_params<Value, bgi::linear<4>>();
149+
test_params<Value, bgi::quadratic<4>>();
150+
test_params<Value, bgi::rstar<4>>();
151+
}
152+
153+
int test_main(int, char* [])
154+
{
155+
test_value<point>();
156+
test_value<box>();
157+
test_value<segment>();
158+
159+
return 0;
160+
}

0 commit comments

Comments
 (0)