1 | // Boost.Geometry Index |
2 | // |
3 | // Spatial query predicates |
4 | // |
5 | // Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland. |
6 | // |
7 | // Use, modification and distribution is subject to the Boost Software License, |
8 | // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
9 | // http://www.boost.org/LICENSE_1_0.txt) |
10 | |
11 | #ifndef BOOST_GEOMETRY_INDEX_PREDICATES_HPP |
12 | #define BOOST_GEOMETRY_INDEX_PREDICATES_HPP |
13 | |
14 | #include <utility> |
15 | #include <boost/tuple/tuple.hpp> |
16 | #include <boost/mpl/assert.hpp> |
17 | |
18 | #include <boost/geometry/index/detail/predicates.hpp> |
19 | #include <boost/geometry/index/detail/tuples.hpp> |
20 | |
21 | /*! |
22 | \defgroup predicates Predicates (boost::geometry::index::) |
23 | */ |
24 | |
25 | namespace boost { namespace geometry { namespace index { |
26 | |
27 | /*! |
28 | \brief Generate \c contains() predicate. |
29 | |
30 | Generate a predicate defining Value and Geometry relationship. |
31 | Value will be returned by the query if <tt>bg::within(Geometry, Indexable)</tt> |
32 | returns true. |
33 | |
34 | \par Example |
35 | \verbatim |
36 | bgi::query(spatial_index, bgi::contains(box), std::back_inserter(result)); |
37 | \endverbatim |
38 | |
39 | \ingroup predicates |
40 | |
41 | \tparam Geometry The Geometry type. |
42 | |
43 | \param g The Geometry object. |
44 | */ |
45 | template <typename Geometry> inline |
46 | detail::predicates::spatial_predicate<Geometry, detail::predicates::contains_tag, false> |
47 | contains(Geometry const& g) |
48 | { |
49 | return detail::predicates::spatial_predicate |
50 | < |
51 | Geometry, |
52 | detail::predicates::contains_tag, |
53 | false |
54 | >(g); |
55 | } |
56 | |
57 | /*! |
58 | \brief Generate \c covered_by() predicate. |
59 | |
60 | Generate a predicate defining Value and Geometry relationship. |
61 | Value will be returned by the query if <tt>bg::covered_by(Indexable, Geometry)</tt> |
62 | returns true. |
63 | |
64 | \par Example |
65 | \verbatim |
66 | bgi::query(spatial_index, bgi::covered_by(box), std::back_inserter(result)); |
67 | \endverbatim |
68 | |
69 | \ingroup predicates |
70 | |
71 | \tparam Geometry The Geometry type. |
72 | |
73 | \param g The Geometry object. |
74 | */ |
75 | template <typename Geometry> inline |
76 | detail::predicates::spatial_predicate<Geometry, detail::predicates::covered_by_tag, false> |
77 | covered_by(Geometry const& g) |
78 | { |
79 | return detail::predicates::spatial_predicate |
80 | < |
81 | Geometry, |
82 | detail::predicates::covered_by_tag, |
83 | false |
84 | >(g); |
85 | } |
86 | |
87 | /*! |
88 | \brief Generate \c covers() predicate. |
89 | |
90 | Generate a predicate defining Value and Geometry relationship. |
91 | Value will be returned by the query if <tt>bg::covered_by(Geometry, Indexable)</tt> |
92 | returns true. |
93 | |
94 | \par Example |
95 | \verbatim |
96 | bgi::query(spatial_index, bgi::covers(box), std::back_inserter(result)); |
97 | \endverbatim |
98 | |
99 | \ingroup predicates |
100 | |
101 | \tparam Geometry The Geometry type. |
102 | |
103 | \param g The Geometry object. |
104 | */ |
105 | template <typename Geometry> inline |
106 | detail::predicates::spatial_predicate<Geometry, detail::predicates::covers_tag, false> |
107 | covers(Geometry const& g) |
108 | { |
109 | return detail::predicates::spatial_predicate |
110 | < |
111 | Geometry, |
112 | detail::predicates::covers_tag, |
113 | false |
114 | >(g); |
115 | } |
116 | |
117 | /*! |
118 | \brief Generate \c disjoint() predicate. |
119 | |
120 | Generate a predicate defining Value and Geometry relationship. |
121 | Value will be returned by the query if <tt>bg::disjoint(Indexable, Geometry)</tt> |
122 | returns true. |
123 | |
124 | \par Example |
125 | \verbatim |
126 | bgi::query(spatial_index, bgi::disjoint(box), std::back_inserter(result)); |
127 | \endverbatim |
128 | |
129 | \ingroup predicates |
130 | |
131 | \tparam Geometry The Geometry type. |
132 | |
133 | \param g The Geometry object. |
134 | */ |
135 | template <typename Geometry> inline |
136 | detail::predicates::spatial_predicate<Geometry, detail::predicates::disjoint_tag, false> |
137 | disjoint(Geometry const& g) |
138 | { |
139 | return detail::predicates::spatial_predicate |
140 | < |
141 | Geometry, |
142 | detail::predicates::disjoint_tag, |
143 | false |
144 | >(g); |
145 | } |
146 | |
147 | /*! |
148 | \brief Generate \c intersects() predicate. |
149 | |
150 | Generate a predicate defining Value and Geometry relationship. |
151 | Value will be returned by the query if <tt>bg::intersects(Indexable, Geometry)</tt> |
152 | returns true. |
153 | |
154 | \par Example |
155 | \verbatim |
156 | bgi::query(spatial_index, bgi::intersects(box), std::back_inserter(result)); |
157 | bgi::query(spatial_index, bgi::intersects(ring), std::back_inserter(result)); |
158 | bgi::query(spatial_index, bgi::intersects(polygon), std::back_inserter(result)); |
159 | \endverbatim |
160 | |
161 | \ingroup predicates |
162 | |
163 | \tparam Geometry The Geometry type. |
164 | |
165 | \param g The Geometry object. |
166 | */ |
167 | template <typename Geometry> inline |
168 | detail::predicates::spatial_predicate<Geometry, detail::predicates::intersects_tag, false> |
169 | intersects(Geometry const& g) |
170 | { |
171 | return detail::predicates::spatial_predicate |
172 | < |
173 | Geometry, |
174 | detail::predicates::intersects_tag, |
175 | false |
176 | >(g); |
177 | } |
178 | |
179 | /*! |
180 | \brief Generate \c overlaps() predicate. |
181 | |
182 | Generate a predicate defining Value and Geometry relationship. |
183 | Value will be returned by the query if <tt>bg::overlaps(Indexable, Geometry)</tt> |
184 | returns true. |
185 | |
186 | \par Example |
187 | \verbatim |
188 | bgi::query(spatial_index, bgi::overlaps(box), std::back_inserter(result)); |
189 | \endverbatim |
190 | |
191 | \ingroup predicates |
192 | |
193 | \tparam Geometry The Geometry type. |
194 | |
195 | \param g The Geometry object. |
196 | */ |
197 | template <typename Geometry> inline |
198 | detail::predicates::spatial_predicate<Geometry, detail::predicates::overlaps_tag, false> |
199 | overlaps(Geometry const& g) |
200 | { |
201 | return detail::predicates::spatial_predicate |
202 | < |
203 | Geometry, |
204 | detail::predicates::overlaps_tag, |
205 | false |
206 | >(g); |
207 | } |
208 | |
209 | #ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL |
210 | |
211 | /*! |
212 | \brief Generate \c touches() predicate. |
213 | |
214 | Generate a predicate defining Value and Geometry relationship. |
215 | Value will be returned by the query if <tt>bg::touches(Indexable, Geometry)</tt> |
216 | returns true. |
217 | |
218 | \ingroup predicates |
219 | |
220 | \tparam Geometry The Geometry type. |
221 | |
222 | \param g The Geometry object. |
223 | */ |
224 | template <typename Geometry> inline |
225 | detail::predicates::spatial_predicate<Geometry, detail::predicates::touches_tag, false> |
226 | touches(Geometry const& g) |
227 | { |
228 | return detail::predicates::spatial_predicate |
229 | < |
230 | Geometry, |
231 | detail::predicates::touches_tag, |
232 | false |
233 | >(g); |
234 | } |
235 | |
236 | #endif // BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL |
237 | |
238 | /*! |
239 | \brief Generate \c within() predicate. |
240 | |
241 | Generate a predicate defining Value and Geometry relationship. |
242 | Value will be returned by the query if <tt>bg::within(Indexable, Geometry)</tt> |
243 | returns true. |
244 | |
245 | \par Example |
246 | \verbatim |
247 | bgi::query(spatial_index, bgi::within(box), std::back_inserter(result)); |
248 | \endverbatim |
249 | |
250 | \ingroup predicates |
251 | |
252 | \tparam Geometry The Geometry type. |
253 | |
254 | \param g The Geometry object. |
255 | */ |
256 | template <typename Geometry> inline |
257 | detail::predicates::spatial_predicate<Geometry, detail::predicates::within_tag, false> |
258 | within(Geometry const& g) |
259 | { |
260 | return detail::predicates::spatial_predicate |
261 | < |
262 | Geometry, |
263 | detail::predicates::within_tag, |
264 | false |
265 | >(g); |
266 | } |
267 | |
268 | /*! |
269 | \brief Generate satisfies() predicate. |
270 | |
271 | A wrapper around user-defined UnaryPredicate checking if Value should be returned by spatial query. |
272 | |
273 | \par Example |
274 | \verbatim |
275 | bool is_red(Value const& v) { return v.is_red(); } |
276 | |
277 | struct is_red_o { |
278 | template <typename Value> bool operator()(Value const& v) { return v.is_red(); } |
279 | } |
280 | |
281 | // ... |
282 | |
283 | rt.query(index::intersects(box) && index::satisfies(is_red), |
284 | std::back_inserter(result)); |
285 | |
286 | rt.query(index::intersects(box) && index::satisfies(is_red_o()), |
287 | std::back_inserter(result)); |
288 | |
289 | #ifndef BOOST_NO_CXX11_LAMBDAS |
290 | rt.query(index::intersects(box) && index::satisfies([](Value const& v) { return v.is_red(); }), |
291 | std::back_inserter(result)); |
292 | #endif |
293 | \endverbatim |
294 | |
295 | \ingroup predicates |
296 | |
297 | \tparam UnaryPredicate A type of unary predicate function or function object. |
298 | |
299 | \param pred The unary predicate function or function object. |
300 | */ |
301 | template <typename UnaryPredicate> inline |
302 | detail::predicates::satisfies<UnaryPredicate, false> |
303 | satisfies(UnaryPredicate const& pred) |
304 | { |
305 | return detail::predicates::satisfies<UnaryPredicate, false>(pred); |
306 | } |
307 | |
308 | /*! |
309 | \brief Generate nearest() predicate. |
310 | |
311 | When nearest predicate is passed to the query, k-nearest neighbour search will be performed. |
312 | \c nearest() predicate takes a \c Geometry from which distances to \c Values are calculated |
313 | and the maximum number of \c Values that should be returned. Internally |
314 | boost::geometry::comparable_distance() is used to perform the calculation. |
315 | |
316 | \par Example |
317 | \verbatim |
318 | bgi::query(spatial_index, bgi::nearest(pt, 5), std::back_inserter(result)); |
319 | bgi::query(spatial_index, bgi::nearest(pt, 5) && bgi::intersects(box), std::back_inserter(result)); |
320 | bgi::query(spatial_index, bgi::nearest(box, 5), std::back_inserter(result)); |
321 | \endverbatim |
322 | |
323 | \warning |
324 | Only one \c nearest() predicate may be used in a query. |
325 | |
326 | \ingroup predicates |
327 | |
328 | \param geometry The geometry from which distance is calculated. |
329 | \param k The maximum number of values to return. |
330 | */ |
331 | template <typename Geometry> inline |
332 | detail::predicates::nearest<Geometry> |
333 | nearest(Geometry const& geometry, unsigned k) |
334 | { |
335 | return detail::predicates::nearest<Geometry>(geometry, k); |
336 | } |
337 | |
338 | #ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL |
339 | |
340 | /*! |
341 | \brief Generate path() predicate. |
342 | |
343 | When path predicate is passed to the query, the returned values are k values along the path closest to |
344 | its begin. \c path() predicate takes a \c Segment or a \c Linestring defining the path and the maximum |
345 | number of \c Values that should be returned. |
346 | |
347 | \par Example |
348 | \verbatim |
349 | bgi::query(spatial_index, bgi::path(segment, 5), std::back_inserter(result)); |
350 | bgi::query(spatial_index, bgi::path(linestring, 5) && bgi::intersects(box), std::back_inserter(result)); |
351 | \endverbatim |
352 | |
353 | \warning |
354 | Only one distance predicate (\c nearest() or \c path()) may be used in a query. |
355 | |
356 | \ingroup predicates |
357 | |
358 | \param linestring The path along which distance is calculated. |
359 | \param k The maximum number of values to return. |
360 | */ |
361 | template <typename SegmentOrLinestring> inline |
362 | detail::predicates::path<SegmentOrLinestring> |
363 | path(SegmentOrLinestring const& linestring, unsigned k) |
364 | { |
365 | return detail::predicates::path<SegmentOrLinestring>(linestring, k); |
366 | } |
367 | |
368 | #endif // BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL |
369 | |
370 | namespace detail { namespace predicates { |
371 | |
372 | // operator! generators |
373 | |
374 | template <typename Fun, bool Negated> inline |
375 | satisfies<Fun, !Negated> |
376 | operator!(satisfies<Fun, Negated> const& p) |
377 | { |
378 | return satisfies<Fun, !Negated>(p); |
379 | } |
380 | |
381 | template <typename Geometry, typename Tag, bool Negated> inline |
382 | spatial_predicate<Geometry, Tag, !Negated> |
383 | operator!(spatial_predicate<Geometry, Tag, Negated> const& p) |
384 | { |
385 | return spatial_predicate<Geometry, Tag, !Negated>(p.geometry); |
386 | } |
387 | |
388 | // operator&& generators |
389 | |
390 | template <typename Pred1, typename Pred2> inline |
391 | boost::tuples::cons< |
392 | Pred1, |
393 | boost::tuples::cons<Pred2, boost::tuples::null_type> |
394 | > |
395 | operator&&(Pred1 const& p1, Pred2 const& p2) |
396 | { |
397 | /*typedef typename boost::mpl::if_c<is_predicate<Pred1>::value, Pred1, Pred1 const&>::type stored1; |
398 | typedef typename boost::mpl::if_c<is_predicate<Pred2>::value, Pred2, Pred2 const&>::type stored2;*/ |
399 | namespace bt = boost::tuples; |
400 | |
401 | return |
402 | bt::cons< Pred1, bt::cons<Pred2, bt::null_type> > |
403 | ( p1, bt::cons<Pred2, bt::null_type>(p2, bt::null_type()) ); |
404 | } |
405 | |
406 | template <typename Head, typename Tail, typename Pred> inline |
407 | typename tuples::push_back< |
408 | boost::tuples::cons<Head, Tail>, Pred |
409 | >::type |
410 | operator&&(boost::tuples::cons<Head, Tail> const& t, Pred const& p) |
411 | { |
412 | //typedef typename boost::mpl::if_c<is_predicate<Pred>::value, Pred, Pred const&>::type stored; |
413 | namespace bt = boost::tuples; |
414 | |
415 | return |
416 | tuples::push_back< |
417 | bt::cons<Head, Tail>, Pred |
418 | >::apply(t, p); |
419 | } |
420 | |
421 | }} // namespace detail::predicates |
422 | |
423 | }}} // namespace boost::geometry::index |
424 | |
425 | #endif // BOOST_GEOMETRY_INDEX_PREDICATES_HPP |
426 | |