mirror of
https://github.com/boostorg/geometry.git
synced 2025-05-11 13:34:10 +00:00
222 lines
7.9 KiB
Plaintext
222 lines
7.9 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 Queries]
|
|
|
|
Queries returns `__value__`s which meets some predicates. Currently supported are three types of predicates:
|
|
|
|
* spatial predicates - defining relationship between stored Values and some Geometry,
|
|
* nearest predicate - defining relationship between stored Values and some Point,
|
|
* user-defined unary predicate - function, function object or lambda expression checking user-defined condition.
|
|
|
|
For example queries may be used to retrieve Values:
|
|
|
|
* intersecting some area but not within other area,
|
|
* are nearest to some point,
|
|
* overlapping a box and has user-defined property.
|
|
|
|
[section Performing a query]
|
|
|
|
There are three ways to perform a query presented below. All of them returns `__value__`s intersecting some
|
|
region defined as a `__box__`.
|
|
|
|
Method call
|
|
|
|
std::vector<__value__> returned_values;
|
|
__box__ box_region(...);
|
|
rt.query(bgi::intersects(box_region), std::back_inserter(returned_values));
|
|
|
|
Function call
|
|
|
|
std::vector<__value__> returned_values;
|
|
__box__ box_region(...);
|
|
index::query(rt, bgi::intersects(box_region), std::back_inserter(returned_values));
|
|
|
|
Use of pipe operator generating a range
|
|
|
|
__box__ box_region(...);
|
|
BOOST_FOREACH(__value__ & v, rt | index::adaptors::queried(bgi::intersects(box_region)))
|
|
; // do something with v
|
|
|
|
[endsect]
|
|
|
|
[section Spatial queries]
|
|
|
|
Spatial query returns `__value__`s which are related somehow to some Geometry - box, polygon, etc.
|
|
Names of spatial predicates corresponds to names of __boost_geometry__ algorithms. 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)]]
|
|
[[[$img/index/rtree/intersects.png]] [[$img/index/rtree/within.png]] [[$img/index/rtree/disjoint.png]] [[$img/index/rtree/overlaps.png]] [[$img/index/rtree/within.png]]]
|
|
]
|
|
|
|
[table
|
|
[[intersects(Ring)] [intersects(Polygon)] [intersects(MultiPolygon)]]
|
|
[[[$img/index/rtree/intersects_ring.png]] [[$img/index/rtree/intersects_poly.png]] [[$img/index/rtree/intersects_mpoly.png]]]
|
|
]
|
|
|
|
To use a spatial predicate one may use one of the functions defined in `boost::geometry::index` namespace.
|
|
|
|
rt.query(index::intersects(box), std::back_inserter(result));
|
|
rt.query(index::covered_by(box), std::back_inserter(result));
|
|
rt.query(index::disjont(box), std::back_inserter(result));
|
|
rt.query(index::overlaps(box), std::back_inserter(result));
|
|
rt.query(index::within(box), std::back_inserter(result));
|
|
|
|
All predicates may be negated, e.g.:
|
|
|
|
rt.query(!index::intersects(box), std::back_inserter(result));
|
|
// the same as
|
|
rt.query(index::disjoint(box), std::back_inserter(result));
|
|
|
|
[endsect]
|
|
|
|
[section Nearest neighbours queries]
|
|
|
|
Nearest neighbours queries returns `__value__`s which are closest to some point in space.
|
|
Additionally it is possible to define how the distance to the `Value` should be calculated.
|
|
The example of knn query is presented below. 5 `__value__`s nearest to some point are orange.
|
|
|
|
[$img/index/rtree/knn.png]
|
|
|
|
[section k nearest neighbours]
|
|
|
|
There are three ways of performing knn queries. Following queries returns
|
|
`k` `__value__`s closest to some point in space. For `__box__`es
|
|
`__indexable__`s the distance to the nearest point is calculated by default.
|
|
|
|
Method call
|
|
|
|
std::vector<__value__> returned_values;
|
|
__point__ pt(...);
|
|
rt.query(index::nearest(pt, k), std::back_inserter(returned_values));
|
|
|
|
Function call
|
|
|
|
std::vector<__value__> returned_values;
|
|
__point__ pt(...);
|
|
index::query(rt, index::nearest(pt, k), std::back_inserter(returned_values));
|
|
|
|
Use of `operator |`
|
|
|
|
__point__ pt(...);
|
|
BOOST_FOREACH(__value__ & v, rt | index::adaptors::queried(index::nearest(pt, k)))
|
|
; // do something with v
|
|
|
|
[endsect]
|
|
|
|
[section Distance calculation]
|
|
|
|
It is possible to define how distance to the non-point `__value__` should be calculated. To do this one may pass
|
|
a relation object generated as follows:
|
|
|
|
/* caluclate distance to the Indexables' nearest points */
|
|
tree::query(index::nearest(index::to_nearest(pt), k), std::back_inserter(returned_values)); // default
|
|
/* caluclate distance to the Indexables' centroid */
|
|
tree::query(index::nearest(index::to_centroid(pt), k), std::back_inserter(returned_values));
|
|
/* caluclate distance to the Indexables' furthest points */
|
|
tree::query(index::nearest(index::to_furthest(pt), k), std::back_inserter(returned_values));
|
|
|
|
[endsect]
|
|
|
|
[endsect]
|
|
|
|
[section User-defined unary predicate]
|
|
|
|
The user may pass a `UnaryPredicate` - function, function object or lambda expression taking const reference to Value and returning bool.
|
|
This object may be passed to the query in order to check if `__value__` should be returned by the query. To do it one
|
|
may use `index::satisfies()` function like on the example below:
|
|
|
|
bool is_red(__value__ const& v)
|
|
{
|
|
return v.is_red();
|
|
}
|
|
|
|
struct is_red_o
|
|
{
|
|
template <typename Value>
|
|
bool operator()(__value__ const& v)
|
|
{
|
|
return v.is_red();
|
|
}
|
|
}
|
|
|
|
// ...
|
|
|
|
rt.query(index::intersects(box) && index::satisfies(is_red),
|
|
std::back_inserter(result));
|
|
|
|
rt.query(index::intersects(box) && index::satisfies(is_red_o()),
|
|
std::back_inserter(result));
|
|
|
|
#ifndef BOOST_NO_CXX11_LAMBDAS
|
|
rt.query(index::intersects(box) && index::satisfies([](__value__ const& v) { return v.is_red(); }),
|
|
std::back_inserter(result));
|
|
#endif
|
|
|
|
[endsect]
|
|
|
|
[section Passing a set of predicates]
|
|
|
|
It's possible to use some number of predicates in one query by connecting them with `operator&&` e.g. `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.query(index::intersects(box1) && !index::within(box2),
|
|
std::back_inserter(result));
|
|
|
|
rt.query(index::intersects(box1) && !index::within(box2) && index::overlaps(box3),
|
|
std::back_inserter(result));
|
|
|
|
Of course it's possible to connect different types of predicates together.
|
|
|
|
index::query(rt, index::nearest(pt, k) && index::within(b), std::back_inserter(returned_values));
|
|
|
|
BOOST_FOREACH(Value & v, rt | index::adaptors::queried(index::nearest(pt, k) && index::covered_by(b)))
|
|
; // do something with v
|
|
|
|
[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.query(bgi::intersects(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.query(bgi::intersects(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. However in this case the temporary container is created.
|
|
|
|
RTree rt4(rt1 | bgi::adaptors::queried(bgi::intersects(Box(/*...*/)))));
|
|
|
|
[endsect]
|
|
|
|
[endsect] [/ Queries /]
|