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