Files
geometry/doc/rtree.qbk
Adam Wulkiewicz 6079b53ff8 naming error fixed
[SVN r75749]
2011-11-30 13:40:14 +00:00

318 lines
9.7 KiB
Plaintext

[/============================================================================
Boost.Geometry Index (Spatial Indexes)
Copyright (c) 2008 Federico J. Fernandez.
Copyright (c) 2011 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 R-tree]
[section Introduction]
__rtree__ is a self-balancing search tree with nodes stored with their axis aligned
bounding boxes. Each node's box describes the space occupied by children nodes.
At the bottom of the structure, there are leaf-nodes which contains values
(geometric objects representations). Minimal and maximal numbers of values/children
which may be stored inside the node are user defined.
In order to use the __rtree__ one must include folowing file.
#include <boost/geometry/extensions/index/rtree/rtree.hpp>
[endsect]
[section R-tree creation]
[section Quick start]
In order to create a __rtree__ object storing values of type `std::pair<__box__, size_t>`
one may use the following code:
using namespace __cboost__::__cgeometry__;
typedef std::pair<__box__, size_t> Value;
index::rtree< Value, index::quadratic<32, 8> > rt;
[endsect]
[section R-tree template parameters]
__rtree__ has 4 parameters:
rtree<Value, Parameters, Translator, Allocator>
* `Value` - type of object which will be stored in the container.
* `Parameters` - compile-time parameters, e.g. inserting/splitting
algorithm with min and max nodes' elements numbers.
* `Translator` - type of object translating `Value` objects to
`Indexable` objects (`__point__` or `__box__`) which __rtree__ can handle.
* `Allocator` - the allocator.
[endsect]
[section Values, Indexables and default Translator]
__rtree__ may store `__value__`s of any type as long as there is passed
the `__translator__` which knows how to interpret those `__value__`s
and extract an object understandable by the __rtree__. Those objects are called
`__indexable__`s and they are simply of type adapted to `__point__`
or `__box__` concept. Default `__translator__` `index::translator::def<Value>`
is able to handle `__point__`, `__box__`, `std::pair<...>`, pointer, iterator
or smart pointer.
* `__indexable__ = __point__ | __box__`
* `BasicValue = Indexable | std::pair<__indexable__, T> | std::pair<T, __indexable__>`
* `__value__ = BasicValue | BasicValue* | Iterator<BasicValue> | SmartPtr<BasicValue>`
Examples of `__value__` types:
geometry::model::point<...>
geometry::model::point_xy<...>
geometry::model::box<...>
std::pair<geometry::model::box<...>, size_t>
[endsect]
[section Inserting and splitting algorithms]
`__value__`s may be inserted to the __rtree__ in many various ways. Final structure of nodes depends
on algorithms used in the process, especially nodes' splitting algorithm. Currently, three
well-known types of R-trees may be created.
Linear - classic __rtree__ using splitting algorithm of linear complexity
index::rtree< __value__, index::linear<32, 8> > rt;
Quadratic - classic __rtree__ using splitting algorithm of quadratic complexity
index::rtree< __value__, index::quadratic<32, 8> > rt;
R*-tree - splitting algorithm minimizing nodes' overlap with forced reinsertions
index::rtree< __value__, index::rstar<32, 8> > rt;
[endsect]
[endsect] [/ R-tree creation /]
[section Inserting and removing Values]
Create
using namespace boost::geometry;
typedef std::pair<Box, int> __value__;
index::rtree< __value__, index::quadratic<32, 8> > rt;
Insert and remove by method call
__value__ v = std::make_pair(__box__(...), 0);
rt.insert(v);
rt.remove(v);
or by function call
__value__ v = std::make_pair(__box__(...), 0);
index::insert(rt, v);
index::remove(rt, v);
[endsect]
[section Spatial queries]
[section Basic queries]
There are three ways to perform a spatial query. Following queries returns
`__value__`s intersecting some box_region.
Method call
std::vector<__value__> returned_values;
__box__ box_region(...);
rt.query(box_region, std::back_inserter(returned_values));
Function call
std::vector<__value__> returned_values;
__box__ box_region(...);
index::query(rt, box_region, std::back_inserter(returned_values));
Use of `operator |` (as with ranges)
__box__ box_region(...);
BOOST_FOREACH(__value__ & v, rt | index::query_filtered(box_region))
; // do something with v
[endsect]
[section Spatial predicates]
It is possible to define other relations between queried `__value__`s and region/regions
of interest. Names of predicates corresponds to names of __boost_geometry__ algorithms.
rt.query(box, std::back_inserter(result)); // default case - intersects
rt.query(index::intersects(box), std::back_inserter(result)); // same as default
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::not_intersects(box), std::back_inserter(result));
// or
rt.query(!index::intersects(box), std::back_inserter(result));
// the same as
rt.query(index::disjoint(box), std::back_inserter(result));
It's possible to use some number of predicates by passing `std::pair<Pred1, Pred2>`
rt.query(
std::make_pair(index::intersects(box1), !index::within(box2))
, std::back_inserter(result));
or `boost::tuple<Pred1, Pred2, Pred3, ...>`
rt.query(
boost::make_tuple(
index::intersects(box1), !index::within(box2), index::overlaps(box3))
, std::back_inserter(result));
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.query(
boost::make_pair(index::intersects(box), index::value(fun))
, std::back_inserter(result));
[endsect]
[endsect] [/ Spatial queries /]
[section Nearest neighbors queries]
[section k nearest neighbors]
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 closest point of a `__box__` is taken into account by default.
Method call
std::vector<__value__> returned_values;
__point__ pt(...);
rt.nearest(pt, k, std::back_inserter(returned_values));
Function call
std::vector<__value__> returned_values;
__point__ pt(...);
index::nearest(rt, pt, k, std::back_inserter(returned_values));
Use of `operator |`
__point__ pt(...);
BOOST_FOREACH(__value__ & v, rt | index::nearest_filtered(pt, k))
; // do something with v
[endsect]
[section One nearest neighbor]
Another type of nearest neighbor query is searching for the one closest `__value__`.
If it is found, 1 is returned by the method or function. This kind of query
has only two forms.
Method call
__value__ returned_value;
__point__ pt(...);
size_t n = rt.nearest(pt, returned_value);
Function call
__value__ Value returned_value;
__point__ pt(...);
size_t n = index::nearest(rt, pt, returned_value);
[endsect]
[section Distances predicates]
It is possible to define if calculated distance between query point and `__value__` should be
greater, lesser or between some other distances. Those are called `DistancesPredicate`s and
may be defined as follows.
std::vector<__Value__> returned_values;
__point__ pt(...);
/* default - without bounds */
index::nearest(rt, pt, k, std::back_inserter(returned_values));
/* same as default */
index::nearest(rt, index::unbounded(pt), k, std::back_inserter(returned_values));
/* distance must be greater than or equal to 10 */
index::nearest(rt, index::min_bounded(pt, 10), k, std::back_inserter(returned_values));
/* distance must be lesser than or equal to 500 */
index::nearest(rt, index::max_bounded(pt, 500), k, std::back_inserter(returned_values));
/* distance must be between 10 and 500 */
index::nearest(rt, index::bounded(pt, 10, 500), k, std::back_inserter(returned_values));
Furthermore, it's possible to define if the closest, furthest or centroidal point of the
non-point `__indexable__` should be taken into account in the routine calculating distance.
std::vector<__value__> returned_values;
__point__ pt(...);
/* default - distance between Indexable's closest point and a query point
must be greater than 10 */
index::nearest(rt, index::min_bounded(pt, 10), k, std::back_inserter(returned_values));
/* same as default - distance between Indexable's closest point and a query point
must be greater than 10 */
index::nearest(rt, index::min_bounded(pt, index::near(10)), k, std::back_inserter(returned_values));
/* distance between Indexable's furthest point and a query point
must be greater than 10 */
index::nearest(rt, index::min_bounded(pt, index::far(10)), k, std::back_inserter(returned_values));
/* distance between Indexable's centroid and a query point
must be greater than 10 */
index::nearest(rt, index::min_bounded(pt, index::centroid(10)), k, std::back_inserter(returned_values));
[endsect]
[section Using spatial predicates]
It is possible to use spatial predicates described before in nearest neighbors queries.
__value__ returned_value;
std::vector<__value__> returned_values;
__point__ pt(...);
__box__ b(...);
size_t n1 = rt.nearest(index::bounded(pt, index::far(1), 10), index::intersects(b), returned_value);
size_t n2 = index::nearest(rt, pt, k, index::within(b), std::back_inserter(returned_values));
BOOST_FOREACH(Value & v, rt | index::nearest_filtered(pt, k, index::covered_by(b)))
; // do something with v
[endsect]
[endsect] [/ Nearest neighbors queries /]
[endsect] [/ R-tree /]