Files
geometry/doc/rtree/spatial_query.qbk
Adam Wulkiewicz 3f1d769d9f Added MultiPolygon spatial query picture to docs.
Added MultiPolygon query to GLUT Vis.

[SVN r81921]
2012-12-13 22:37:06 +00:00

143 lines
5.0 KiB
Plaintext

[/============================================================================
Boost.Geometry Index
Copyright (c) 2011-2012 Adam Wulkiewicz.
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)
=============================================================================/]
[section Spatial queries]
Spatial queries returns `Value`s which meets some predicates. For instance it may be used to
retrieve Values intersecting some area or are within some other area. Names of predicates
corresponds to names of __boost_geometry__ algorithms. The examples of some
basic queries may be found in tables below. The query region and result `Value`s are orange.
[table
[[intersects(Box) - default] [covered_by(Box)] [disjoint(Box)] [overlaps(Box)] [within(Box)]]
[[[$../images/intersects.png]] [[$../images/within.png]] [[$../images/disjoint.png]] [[$../images/overlaps.png]] [[$../images/within.png]]]
]
[table
[[intersects(Ring)] [intersects(Polygon)] [intersects(MultiPolygon)]]
[[[$../images/intersects_ring.png]] [[$../images/intersects_poly.png]] [[$../images/intersects_mpoly.png]]]
]
[section Basic queries]
There are three ways to perform a spatial query. Following queries returns
`__value__`s intersecting some region defined as a box in this example.
Method call
std::vector<__value__> returned_values;
__box__ box_region(...);
rt.spatial_query(box_region, std::back_inserter(returned_values));
Function call
std::vector<__value__> returned_values;
__box__ box_region(...);
index::spatial_query(rt, box_region, std::back_inserter(returned_values));
Use of pipe operator generating a range
__box__ box_region(...);
BOOST_FOREACH(__value__ & v, rt | index::adaptors::spatial_queried(box_region))
; // do something with v
[endsect]
[section Spatial predicates]
To explicitly define one of the predicates one may pass it to the `spatial_query()` as
the first argument.
rt.spatial_query(box, std::back_inserter(result)); // default case - intersects
rt.spatial_query(index::intersects(box), std::back_inserter(result)); // the same as default
rt.spatial_query(index::covered_by(box), std::back_inserter(result));
rt.spatial_query(index::disjont(box), std::back_inserter(result));
rt.spatial_query(index::overlaps(box), std::back_inserter(result));
rt.spatial_query(index::within(box), std::back_inserter(result));
All predicates may be negated, e.g.:
rt.spatial_query(!index::intersects(box), std::back_inserter(result));
// the same as
rt.spatial_query(index::disjoint(box), std::back_inserter(result));
[endsect]
[section Connecting predicates]
It's possible to use some number of predicates in one time by passing `std::pair<Pred1, Pred2>`
or `boost::tuple<Pred1, Pred2, Pred3, ...>`. These predicates are connected by logical AND.
Passing all predicates together not only makes possible to construct advanced queries but is also
faster than separate calls because the tree is traversed only once. Traversing is continued and
`Value`s are returned only if all predicates are met. Predicates are checked left-to-right so placing
most restictive predicates first should accelerate the search.
rt.spatial_query(
std::make_pair(
index::intersects(box1), !index::within(box2) ),
std::back_inserter(result));
rt.spatial_query(
boost::make_tuple(
index::intersects(box1), !index::within(box2), index::overlaps(box3) ),
std::back_inserter(result));
[endsect]
[section Value predicate]
There is also a unique predicate `index::value(...)` taking user-defined function/functor
which checks if `__value__` should be returned by the query.
bool fun(__value__ const& v)
{
return v.is_red();
}
// ...
rt.spatial_query(
boost::make_pair(
index::intersects(box), index::value(fun) ),
std::back_inserter(result));
[endsect]
[section Inserting query results into the other R-tree]
There are several ways of inserting Values returned by a query to the other R-tree container.
The most basic way is creating a temporary container for Values and insert them later.
namespace bgi = boost::geometry::index;
typedef std::pair<Box, int> __value__;
typedef bgi::rtree< __value__, bgi::linear<32, 8> > RTree;
RTree rt1;
/* some inserting into the tree */
std::vector<Value> result;
rt1.spatial_query(Box(/*...*/), std::back_inserter(result));
RTree rt2(result.begin(), result.end());
However there are better ways. One of these methods is mentioned in the "Creation and modification" section.
The insert iterator may be passed directly to the query, which will be the fastest way of inserting
query results because temporary container won't be used.
RTree rt3;
rt1.spatial_query(Box(/*...*/), bgi::inserter(rt3));
If you like Boost.Range you'll appreciate the third option. You may pass the result Range directly to the
constructor.
RTree rt4(rt1 | bgi::adaptors::spatial_queried(Box(/*...*/)));
[endsect]
[endsect] [/ Spatial queries /]