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