diff --git a/doc/html/geometry_index/r_tree/creation_and_modification.html b/doc/html/geometry_index/r_tree/creation_and_modification.html index 50c29f984..8725a9e0f 100644 --- a/doc/html/geometry_index/r_tree/creation_and_modification.html +++ b/doc/html/geometry_index/r_tree/creation_and_modification.html @@ -83,11 +83,10 @@ Indexables. Each type adapted to Point or Box concept is an Indexable. Default Translator - index::translator::def<Value> - is able to handle Point, - Box, - std::pair<...>, - pointer, iterator or smart pointer. + index::translator::def<Value> is able to handle Point, + Box + or std::pair<...> + Values.

+

+ If comparison of two Values is required, the default translator + compares both components of the std::pair<...>. If the second one is a Geometry, geometry::equals() function is used. For other types it + uses operator==(). +

Examples of Value types:

diff --git a/doc/html/geometry_index/r_tree/exception_safety.html b/doc/html/geometry_index/r_tree/exception_safety.html index 0d19fcbb5..6b34a74f4 100644 --- a/doc/html/geometry_index/r_tree/exception_safety.html +++ b/doc/html/geometry_index/r_tree/exception_safety.html @@ -36,7 +36,11 @@ Exception-safe copy constructor of the Value.
  • - Exception-safe copy constructor of the CoordinateType. + Exception-safe copy constructor of the CoordinateType + used in the Indexable. +
  • +
  • + Nonthrowing copy constructor of the Translator.
  • @@ -65,8 +69,7 @@ @@ -139,8 +142,7 @@ @@ -153,7 +155,19 @@ + + + + @@ -293,7 +307,8 @@ @@ -336,22 +351,12 @@

    - nothrow (default) or strong - [a] + nothrow

    - nothrow (default) or strong - [b] + nothrow

    nothrow or strong - [c] + [a] +

    +
    +

    + swap(rtree &) +

    +
    +

    + nothrow

    - nothrow + nothrow or strong + [b]

    [a] - nothrow - if Translator - has nonthrowing copy constructor (default), strong - - if Translator - has throwing copy constructor + nothrow - if allocators are equal, strong - otherwise

    [b] - nothrow - if Translator - has nonthrowing copy constructor (default), strong - - if Translator - has throwing copy constructor -

    -

    [c] - nothrow - if allocators are equal and Translator has nonthrowing - copy constructor (default), strong - - if allocators aren't equal or Translator - has throwing copy constructor + nothrow - if CoordinateType + has nonthrowing copy constructor, strong + - otherwise

    diff --git a/doc/html/geometry_index/r_tree/introduction.html b/doc/html/geometry_index/r_tree/introduction.html index ec8a37d4a..4f362b0d4 100644 --- a/doc/html/geometry_index/r_tree/introduction.html +++ b/doc/html/geometry_index/r_tree/introduction.html @@ -27,12 +27,191 @@ Introduction

    - R-tree is a self-balancing search tree. Each tree's node store a box descring - 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 - each node are user defined. + R-tree is a tree data structure used for spatial searching. It was proposed + by Antonin Guttman in 1984 [1] as an expansion of B-tree for multi-dimensional data. It may + be used to store points or volumetric data in order to perform a spatial + query later. This query may return objects that are inside some area or are + close to some point in space.

    +

    + The R-tree structure is presented on the image below. Each R-tree's node + store a box descring the space occupied by its children nodes. At the bottom + of the structure, there are leaf-nodes which contains values (geometric objects + representations). +

    +

    + rstar +

    +

    + The number of maximum and mininimum node's elements must be specified by + the user. If the number of elements reaches it's maximum the new node is + created and elements are split between nodes. If the number of elements in + node is too small, the node is deleted and elements are reinserted into the + tree. +

    +

    + The R-tree is a self-balanced data structure. The key part of balancing algorithm + is node splitting algorithm [2] [3]. Each algorithm would produce different splits so the internal + structure of a tree may be different for each one of them. In general more + complex algorithms analyses elements better and produces less overlapping + nodes. This is a "better" split because later, in the searching + process less nodes must be traversed in order to find desired obejcts. On + the other hand more complex analysis takes more time. In general faster inserting + will result in slower searching and vice versa. Example structures of trees + created by use of three different algorithms and operations time are presented + below. +

    +
    ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +

    + linear algorithm +

    +
    +

    + quadratic algorithm +

    +
    +

    + R*-tree +

    +
    +

    + Structure +

    +
    +

    + linear +

    +
    +

    + quadratic +

    +
    +

    + rstar +

    +
    +

    + 1M Values inserts +

    +
    +

    + 1.85s +

    +
    +

    + 3.10s +

    +
    +

    + 24.52s +

    +
    +

    + 1M spatial queries +

    +
    +

    + 8.60s +

    +
    +

    + 2.74s +

    +
    +

    + 1.31s +

    +
    +

    + 100k knn queries +

    +
    +

    + 3.49s +

    +
    +

    + 1.59s +

    +
    +

    + 0.84s +

    +
    +

    + Key features of this implementation of the R-tree are: +

    +
    +
    +

    +

    [1] + Guttman, A. (1984). R-Trees: A Dynamic Index Structure for Spatial + Searching +

    +

    [2] + Greene, D. (1989). An implementation and performance analysis + of spatial data access methods +

    +

    [3] + Beckmann, N.; Kriegel, H. P.; Schneider, R.; Seeger, B. (1990). The + R*-tree: an efficient and robust access method for points and rectangles +

    +
    diff --git a/doc/html/geometry_index/r_tree/nearest_neighbours_queries.html b/doc/html/geometry_index/r_tree/nearest_neighbours_queries.html index 6a2482203..497577ccc 100644 --- a/doc/html/geometry_index/r_tree/nearest_neighbours_queries.html +++ b/doc/html/geometry_index/r_tree/nearest_neighbours_queries.html @@ -37,6 +37,55 @@
    Using spatial predicates
    +

    + Nearest neighbours queries returns Values + which are closest to some point in space. Additionally it is possible to + pass distance predicates in order to define how the distance to the Value should be calculated or minimal and + maximal distances. The examples of some knn queries may be found in the table + below. All queries returns 5 closest Values. + The query point, region and result Values are orange. +

    +
    +++++ + + + + + + + + + + +
    +

    + Basic knn query +

    +
    +

    + knn in a ring (Value's furthest point) +

    +
    +

    + knn in a ring (Value's closest point) +

    +
    +

    + knn +

    +
    +

    + knn_inters +

    +
    +

    + knn_cover +

    +

    k diff --git a/doc/html/geometry_index/r_tree/rtree_quickstart.html b/doc/html/geometry_index/r_tree/rtree_quickstart.html index 34499d5f8..5e2471181 100644 --- a/doc/html/geometry_index/r_tree/rtree_quickstart.html +++ b/doc/html/geometry_index/r_tree/rtree_quickstart.html @@ -35,23 +35,32 @@

    -
    #include <vector>
    -
    -#include <boost/geometry.hpp>
    +
    #include <boost/geometry.hpp>
     #include <boost/geometry/geometries/point_xy.hpp>
     #include <boost/geometry/geometries/box.hpp>
     
     #include <boost/geometry/extensions/index/rtree/rtree.hpp>
     
    +// to store queries results
    +#include <vector>
    +
    +// just for output
    +#include <iostream>
    +#include <boost/foreach.hpp>
    +
     namespace bg = boost::geometry;
     namespace bgi = boost::geometry::index;
     

    - It is possible to store user-defined types in the R-tree. To keep it simple - we will use predefined Point - and Box. + Typically you'll store e.g. std::pair<Box, MyGeometryId> in the R-tree. MyGeometryId + will be some indentifier of a complex Geometry + stored in other container, e.g. index type of a Polygon + stored in the vector or an iterator of list of Rings. + To keep it simple to define Value + we will use predefined Box + and unsigned int.

    @@ -62,48 +71,80 @@

    - R-tree may be created using various algorithm and parameters. In this example - we will use quadratic algorithm. Maximum number of elements in nodes are - set to 32, minimum to 8. + R-tree may be created using various algorithm and parameters. You should + choose the algorithm you'll find the best for your purpose. In this example + we will use quadratic algorithm. Parameters are passed as template parameters. + Maximum number of elements in nodes are set to 32, minimum to 8.

    -
    bgi::rtree< value, bgi::quadratic<32, 8> > rtree;
    +
    // create the rtree using default constructor
    +bgi::rtree< value, bgi::quadratic<32, 8> > rtree;
     

    - Inserting values into the R-tree may be done by calling insert() method. + Typically Values will be + generated in a loop from e.g. Polygons + stored in some other container. In this case Box + objects will probably be created with geometry::make_envelope() function. But to keep it simple lets just + generate some boxes manually and insert them into the R-tree by using insert() + method.

    -
    // create some box
    -// this typically will be an envelope of some geometry
    -box b(point(0, 0), point(10, 10));
    -// insert new value
    -rtree.insert(std::make_pair(b, 0));
    +
    // create some values
    +for ( unsigned i = 0 ; i < 10 ; ++i )
    +{
    +    // create a box
    +    box b(point(i, i), point(i + 0.5f, i + 0.5f));
    +    // insert new value
    +    rtree.insert(std::make_pair(b, i));
    +}
     

    There are various types of spatial queries that may be performed, they can - be even combined together in one call. For simplicity, default one is used. + be even combined together in one call. For simplicity, we use the default + one. The following query return values intersecting a box. The sequence of + Values in the result is not + specified.

    -
    // find values intersecting a box
    -std::vector<value> result;
    -rtree.spatial_query(b, std::back_inserter(result));
    +
    // find values intersecting some area defined by a box
    +box query_box(point(0, 0), point(5, 5));
    +std::vector<value> result_s;
    +rtree.spatial_query(query_box, std::back_inserter(result_s));
     

    - Default k-nearest neighbors query may be performed as follows. + Other type of query is k-nearest neighbor search. It returns some number + of values nearest to some point in space. The default knn query may be performed + as follows. The sequence of Values + in the result is not specified.

    // find 5 nearest values to a point
    -rtree.nearest_query(point(0, 0), 5, std::back_inserter(result));
    +std::vector<value> result_n;
    +rtree.nearest_query(point(0, 0), 5, std::back_inserter(result_n));
    +
    +

    +

    +

    + At the end we'll print results. +

    +

    +

    +
    std::cout << "spatial query result:" << std::endl;
    +BOOST_FOREACH(value const& v, result_s)
    +    std::cout << bg::wkt<box>(v.first) << " - " << v.second << std::endl;
    +std::cout << "knn query result:" << std::endl;
    +BOOST_FOREACH(value const& v, result_n)
    +    std::cout << bg::wkt<box>(v.first) << " - " << v.second << std::endl;
     

    diff --git a/doc/html/geometry_index/r_tree/spatial_queries.html b/doc/html/geometry_index/r_tree/spatial_queries.html index 910bf2c5b..7076a9506 100644 --- a/doc/html/geometry_index/r_tree/spatial_queries.html +++ b/doc/html/geometry_index/r_tree/spatial_queries.html @@ -32,6 +32,76 @@
    Spatial predicates

    +

    + Spatial queries returns Values + which meets some predicates. For instance it may be used to retrieve Values + intersecting some area or are within some other area. The examples of some + basic queries may be found in the table below. The query region and result + Values are orange. +

    +
    +++++++ + + + + + + + + + + + + + + +
    +

    + intersects (default) +

    +
    +

    + covered_by +

    +
    +

    + disjoint +

    +
    +

    + overlaps +

    +
    +

    + within +

    +
    +

    + intersects +

    +
    +

    + within +

    +
    +

    + disjoint +

    +
    +

    + overlaps +

    +
    +

    + within +

    +
    - +

    Last revised: November 21, 2012 at 16:05:59 GMT

    Last revised: November 25, 2012 at 21:34:09 GMT


    diff --git a/doc/images/disjoint.png b/doc/images/disjoint.png new file mode 100644 index 000000000..131a91586 Binary files /dev/null and b/doc/images/disjoint.png differ diff --git a/doc/images/intersects.png b/doc/images/intersects.png new file mode 100644 index 000000000..066a1dd80 Binary files /dev/null and b/doc/images/intersects.png differ diff --git a/doc/images/knn.png b/doc/images/knn.png new file mode 100644 index 000000000..f142919d8 Binary files /dev/null and b/doc/images/knn.png differ diff --git a/doc/images/knn_cover.png b/doc/images/knn_cover.png new file mode 100644 index 000000000..39e69e4ce Binary files /dev/null and b/doc/images/knn_cover.png differ diff --git a/doc/images/knn_inters.png b/doc/images/knn_inters.png new file mode 100644 index 000000000..c32c6474c Binary files /dev/null and b/doc/images/knn_inters.png differ diff --git a/doc/images/linear.png b/doc/images/linear.png new file mode 100644 index 000000000..a8cc786a0 Binary files /dev/null and b/doc/images/linear.png differ diff --git a/doc/images/overlaps.png b/doc/images/overlaps.png new file mode 100644 index 000000000..70d77a120 Binary files /dev/null and b/doc/images/overlaps.png differ diff --git a/doc/images/quadratic.png b/doc/images/quadratic.png new file mode 100644 index 000000000..9fedf85a7 Binary files /dev/null and b/doc/images/quadratic.png differ diff --git a/doc/images/rstar.png b/doc/images/rstar.png new file mode 100644 index 000000000..45308b361 Binary files /dev/null and b/doc/images/rstar.png differ diff --git a/doc/images/within.png b/doc/images/within.png new file mode 100644 index 000000000..44ab19e48 Binary files /dev/null and b/doc/images/within.png differ diff --git a/doc/rtree/creation.qbk b/doc/rtree/creation.qbk index c83f23de8..3025132e5 100644 --- a/doc/rtree/creation.qbk +++ b/doc/rtree/creation.qbk @@ -31,13 +31,15 @@ __rtree__ may store `__value__`s of any type as long the `__translator__` is passed as parameter. It knows how to interpret those `__value__`s and extract an object understandable by the __rtree__. Those objects are called `__indexable__`s. Each type adapted to `__point__` or `__box__` concept is an `__indexable__`. -Default `__translator__` `index::translator::def` -is able to handle `__point__`, `__box__`, `std::pair<...>`, pointer, iterator -or smart pointer. +Default `__translator__` `index::translator::def<__value__>` +is able to handle `__point__`, `__box__` or `std::pair<...>` `__value__`s. * `__indexable__ = __point__ | __box__` -* `BasicValue = Indexable | std::pair<__indexable__, T> | std::pair` -* `__value__ = BasicValue | BasicValue* | Iterator | SmartPtr` +* `__value__ = Indexable | std::pair<__indexable__, T>` + +If comparison of two `__value__`s is required, the default translator compares +both components of the `std::pair<...>`. If the second one is a `Geometry`, +`geometry::equals()` function is used. For other types it uses `operator==()`. Examples of `__value__` types: diff --git a/doc/rtree/exception_safety.qbk b/doc/rtree/exception_safety.qbk index f98ec3c15..3b9847480 100644 --- a/doc/rtree/exception_safety.qbk +++ b/doc/rtree/exception_safety.qbk @@ -14,22 +14,22 @@ In order to be exception-safe the __rtree__ requires: * Nonthrowing destructor of the `__value__`. * Exception-safe copy constructor of the `__value__`. -* Exception-safe copy constructor of the `CoordinateType`. +* Exception-safe copy constructor of the `CoordinateType` used in the `Indexable`. +* Nonthrowing copy constructor of the `Translator`. [table [[Operation] [exception-safety]] -[[`rtree()`] [ /nothrow (default)/ or *strong* -[footnote /nothrow/ - if `Translator` has nonthrowing copy constructor (default), *strong* - if `Translator` has throwing copy constructor]]] +[[`rtree()`] [ /nothrow/ ]] [[`rtree(first, last)`] [ *strong* ]] [[`~rtree()`] [ /nothrow/ ]] [[][]] [[`rtree(rtree const&)`] [ *strong* ]] [[`operator=(rtree const&)`] [ *strong* ]] [[][]] -[[`rtree(rtree &&)`] [ /nothrow (default)/ or *strong* -[footnote /nothrow/ - if `Translator` has nonthrowing copy constructor (default), *strong* - if `Translator` has throwing copy constructor]]] +[[`rtree(rtree &&)`] [ /nothrow/ ]] [[`operator=(rtree &&)`] [ /nothrow/ or *strong* -[footnote /nothrow/ - if allocators are equal and `Translator` has nonthrowing copy constructor (default), *strong* - if allocators aren't equal or `Translator` has throwing copy constructor]]] +[footnote /nothrow/ - if allocators are equal, *strong* - otherwise]]] +[[`swap(rtree &)`] [ /nothrow/ ]] [[][]] [[`insert(__value__)`] [ basic ]] [[`insert(first, last)`] [ basic ]] @@ -42,7 +42,8 @@ In order to be exception-safe the __rtree__ requires: [[`size()`] [ /nothrow/ ]] [[`empty()`] [ /nothrow/ ]] [[`clear()`] [ /nothrow/ ]] -[[`box()`] [ /nothrow/ ]] +[[`box()`] [ /nothrow/ or *strong* +[footnote /nothrow/ - if `CoordinateType` has nonthrowing copy constructor, *strong* - otherwise]]] [[`get_allocator()`] [ /nothrow/ ]] [[`parameters()`] [ /nothrow/ ]] [[`translator()`] [ /nothrow/ ]] diff --git a/doc/rtree/introduction.qbk b/doc/rtree/introduction.qbk index dc283360f..d3482b919 100644 --- a/doc/rtree/introduction.qbk +++ b/doc/rtree/introduction.qbk @@ -10,9 +10,45 @@ [section Introduction] -__rtree__ is a self-balancing search tree. Each tree's node store a box descring 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 each node are user defined. +__rtree__ is a tree data structure used for spatial searching. It was proposed by +Antonin Guttman in 1984 [footnote Guttman, A. (1984). /R-Trees: A Dynamic Index Structure for Spatial Searching/] +as an expansion of B-tree for multi-dimensional data. It may be used to store points or volumetric data in order to +perform a spatial query later. This query may return objects that are inside some area or are close to some point in space. + +The __rtree__ structure is presented on the image below. Each __rtree__'s node store a box descring the space occupied by +its children nodes. At the bottom of the structure, there are leaf-nodes which contains values +(geometric objects representations). + +[$../images/rstar.png] + +The number of maximum and mininimum node's elements must be specified by the user. If the number of elements reaches it's maximum +the new node is created and elements are split between nodes. If the number of elements in node is too small, the node is deleted +and elements are reinserted into the tree. + +The __rtree__ is a self-balanced data structure. The key part of balancing algorithm is node splitting algorithm +[footnote Greene, D. (1989). /An implementation and performance analysis of spatial data access methods/] +[footnote Beckmann, N.; Kriegel, H. P.; Schneider, R.; Seeger, B. (1990). /The R*-tree: an efficient and robust access method for points and rectangles/]. +Each algorithm would produce different splits so the internal structure of a tree may be different for each one of them. +In general more complex algorithms analyses elements better and produces less overlapping nodes. This is a "better" split because +later, in the searching process less nodes must be traversed in order to find desired obejcts. On the other hand more complex analysis +takes more time. In general faster inserting will result in slower searching and vice versa. Example structures of trees created by use +of three different algorithms and operations time are presented below. + +[table +[[] [linear algorithm] [quadratic algorithm] [R*-tree]] +[[*Structure*][[$../images/linear.png]] [[$../images/quadratic.png]] [[$../images/rstar.png]]] +[[*1M Values inserts*] [1.85s] [3.10s] [24.52s]] +[[*1M spatial queries*][8.60s] [2.74s] [1.31s]] +[[*100k knn queries*] [3.49s] [1.59s] [0.84s]] +] + +Key features of this implementation of the __rtree__ are: + +* three different creation algorithms - linear, quadratic or rstar, +* parameters (including maximal and minimal number of elements) may be passed as compile- or run-time parameters - compile-time version is faster, +* capable to store arbitrary __value__ type, +* sophisticated queries - e.g. search for 5 nearest values intersecting some region but not within the other one. [endsect] + + diff --git a/doc/rtree/nearest_query.qbk b/doc/rtree/nearest_query.qbk index d5eb85748..d3ba7fc69 100644 --- a/doc/rtree/nearest_query.qbk +++ b/doc/rtree/nearest_query.qbk @@ -10,6 +10,17 @@ [section Nearest neighbours queries] +Nearest neighbours queries returns `Value`s which are closest to some point in space. +Additionally it is possible to pass distance predicates in order to define how the distance +to the `Value` should be calculated or minimal and maximal distances. The examples of some knn +queries may be found in the table below. All queries returns 5 closest `Values`. +The query point, region and result Values are orange. + +[table +[[Basic knn query] [knn in a ring (Value's furthest point)] [knn in a ring (Value's closest point)]] +[[[$../images/knn.png]] [[$../images/knn_inters.png]] [[$../images/knn_cover.png]]] +] + [section k nearest neighbours] There are three ways of performing knn queries. Following queries returns diff --git a/doc/rtree/quickstart.qbk b/doc/rtree/quickstart.qbk index 822aa43d7..0f28622b8 100644 --- a/doc/rtree/quickstart.qbk +++ b/doc/rtree/quickstart.qbk @@ -17,29 +17,41 @@ The code below assumes that following files are included and namespaces used. [rtree_quickstart_include] -It is possible to store user-defined types in the R-tree. To keep it simple we will -use predefined __point__ and __box__. +Typically you'll store e.g. `std::pair` in the __rtree__. `MyGeometryId` +will be some indentifier of a complex `Geometry` stored in other container, e.g. index type +of a `Polygon` stored in the vector or an iterator of list of `Ring`s. To keep it simple to +define `Value` we will use predefined __box__ and unsigned int. [rtree_quickstart_valuetype] -R-tree may be created using various algorithm and parameters. In this example we will -use quadratic algorithm. Maximum number of elements in nodes are set to 32, minimum to 8. +R-tree may be created using various algorithm and parameters. You should choose the algorithm you'll +find the best for your purpose. In this example we will use quadratic algorithm. Parameters are +passed as template parameters. Maximum number of elements in nodes are set to 32, minimum to 8. [rtree_quickstart_create] -Inserting values into the R-tree may be done by calling insert() method. +Typically `Value`s will be generated in a loop from e.g. `Polygon`s stored in some other container. +In this case `Box` objects will probably be created with `geometry::make_envelope()` function. +But to keep it simple lets just generate some boxes manually and insert them into the R-tree by +using `insert()` method. [rtree_quickstart_insert] There are various types of spatial queries that may be performed, they can be even combined together -in one call. For simplicity, default one is used. +in one call. For simplicity, we use the default one. The following query return values intersecting +a box. The sequence of `Values` in the result is not specified. [rtree_quickstart_spatial_query] -Default k-nearest neighbors query may be performed as follows. +Other type of query is k-nearest neighbor search. It returns some number of values nearest to some point +in space. The default knn query may be performed as follows. The sequence of `Values` in the result is not specified. [rtree_quickstart_nearest_query] +At the end we'll print results. + +[rtree_quickstart_output] + [h3 More] More information about the R-tree implementation, other algorithms and queries may be found in other parts of this documentation. diff --git a/doc/rtree/spatial_query.qbk b/doc/rtree/spatial_query.qbk index 6013a73fc..198c56b15 100644 --- a/doc/rtree/spatial_query.qbk +++ b/doc/rtree/spatial_query.qbk @@ -10,6 +10,15 @@ [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. The examples of some +basic queries may be found in the table below. The query region and result `Value`s are orange. + +[table +[[intersects (default)] [covered_by] [disjoint] [overlaps] [within]] +[[[$../images/intersects.png]] [[$../images/within.png]] [[$../images/disjoint.png]] [[$../images/overlaps.png]] [[$../images/within.png]]] +] + [section Basic queries] There are three ways to perform a spatial query. Following queries returns diff --git a/doc/src/examples/rtree/quick_start.cpp b/doc/src/examples/rtree/quick_start.cpp index 99f9fdd39..33eb2147f 100644 --- a/doc/src/examples/rtree/quick_start.cpp +++ b/doc/src/examples/rtree/quick_start.cpp @@ -10,14 +10,19 @@ //[rtree_quickstart_include -#include - #include #include #include #include +// to store queries results +#include + +// just for output +#include +#include + namespace bg = boost::geometry; namespace bgi = boost::geometry::index; //] @@ -31,26 +36,41 @@ int main(void) //] //[rtree_quickstart_create + // create the rtree using default constructor bgi::rtree< value, bgi::quadratic<32, 8> > rtree; //] //[rtree_quickstart_insert - // create some box - // this typically will be an envelope of some geometry - box b(point(0, 0), point(10, 10)); - // insert new value - rtree.insert(std::make_pair(b, 0)); + // create some values + for ( unsigned i = 0 ; i < 10 ; ++i ) + { + // create a box + box b(point(i, i), point(i + 0.5f, i + 0.5f)); + // insert new value + rtree.insert(std::make_pair(b, i)); + } //] //[rtree_quickstart_spatial_query - // find values intersecting a box - std::vector result; - rtree.spatial_query(b, std::back_inserter(result)); + // find values intersecting some area defined by a box + box query_box(point(0, 0), point(5, 5)); + std::vector result_s; + rtree.spatial_query(query_box, std::back_inserter(result_s)); //] //[rtree_quickstart_nearest_query // find 5 nearest values to a point - rtree.nearest_query(point(0, 0), 5, std::back_inserter(result)); + std::vector result_n; + rtree.nearest_query(point(0, 0), 5, std::back_inserter(result_n)); + //] + + //[rtree_quickstart_output + std::cout << "spatial query result:" << std::endl; + BOOST_FOREACH(value const& v, result_s) + std::cout << bg::wkt(v.first) << " - " << v.second << std::endl; + std::cout << "knn query result:" << std::endl; + BOOST_FOREACH(value const& v, result_n) + std::cout << bg::wkt(v.first) << " - " << v.second << std::endl; //] return 0; diff --git a/include/boost/geometry/extensions/index/rtree/rtree.hpp b/include/boost/geometry/extensions/index/rtree/rtree.hpp index b9fa0e9a3..452ee8a1b 100644 --- a/include/boost/geometry/extensions/index/rtree/rtree.hpp +++ b/include/boost/geometry/extensions/index/rtree/rtree.hpp @@ -103,15 +103,14 @@ public: /*! The constructor. - \note Exception-safety: nothrow (if translator has nonthrowing copy ctor), - strong (if translator has throwing copy ctor) + \note Exception-safety: nothrow \param parameters The parameters object. \param translator The translator object. \param allocator The allocator object. */ inline explicit rtree(Parameters parameters = Parameters(), translator_type const& translator = translator_type(), Allocator allocator = Allocator()) - : m_translator(translator) // MAY THROW (copy) + : m_translator(translator) // SHOULDN'T THROW , m_parameters(parameters) , m_allocators(allocator) , m_values_count(0) @@ -132,7 +131,7 @@ public: */ template inline rtree(Iterator first, Iterator last, Parameters parameters = Parameters(), translator_type const& translator = translator_type(), Allocator allocator = std::allocator()) - : m_translator(translator) // MAY THROW (copy) + : m_translator(translator) // SHOULDN'T THROW , m_parameters(parameters) , m_allocators(allocator) , m_values_count(0) @@ -166,7 +165,7 @@ public: \note Exception-safety: strong */ inline rtree(rtree const& src) - : m_translator(src.m_translator) // MAY THROW (copy) + : m_translator(src.m_translator) // SHOULDN'T THROW , m_parameters(src.m_parameters) , m_allocators(src.m_allocators) , m_values_count(0) @@ -184,7 +183,7 @@ public: \note Exception-safety: strong */ inline rtree(rtree const& src, Allocator const& allocator) - : m_translator(src.m_translator) // MAY THROW (copy) + : m_translator(src.m_translator) // SHOULDN'T THROW , m_parameters(src.m_parameters) , m_allocators(allocator) , m_values_count(0) @@ -197,11 +196,10 @@ public: /*! The moving constructor. - \note Exception-safety: nothrow (if translator has nonthrowing copy ctor), - strong (if translator has throwing copy ctor) + \note Exception-safety: nothrow */ inline rtree(BOOST_RV_REF(rtree) src) - : m_translator(src.m_translator) // MAY THROW (copy) + : m_translator(src.m_translator) // SHOULDN'T THROW , m_parameters(src.m_parameters) , m_allocators(src.m_allocators) , m_values_count(src.m_values_count) @@ -234,8 +232,8 @@ public: /*! The moving assignment. - \note Exception-safety: nothrow (if allocators are equal and translator has nonthrowing copy ctor), - strong (if allocators aren't equal or translator has throwing copy ctor) + \note Exception-safety: nothrow (if allocators are equal), + strong (if allocators aren't equal) */ inline rtree & operator=(BOOST_RV_REF(rtree) src) { @@ -246,7 +244,7 @@ public: if ( m_allocators.allocator == src.m_allocators.allocator ) { - m_translator = src.m_translator; // MAY THROW (copy) + m_translator = src.m_translator; // SHOULDN'T THROW m_parameters = src.m_parameters; //m_allocators = src.m_allocators; @@ -267,6 +265,24 @@ public: return *this; } + /*! + Swaps two rtrees. + + \note Exception-safety: nothrow + + \param other The other rtree. + */ + void swap(rtree & other) + { + std::swap(m_translator, other.m_translator); // SHOULDN'T THROW + std::swap(m_parameters, other.m_parameters); + std::swap(m_allocators, other.m_allocators); + + std::swap(m_values_count, other.m_values_count); + std::swap(m_leafs_level, other.m_leafs_level); + std::swap(m_root, other.m_root); + } + /*! Insert a value to the index. @@ -732,7 +748,7 @@ private: if ( copy_all_internals ) { - dst.m_translator = src.m_translator; // MAY THROW + dst.m_translator = src.m_translator; // SHOULDN'T THROW dst.m_parameters = src.m_parameters; //dst.m_allocators = dst.m_allocators; diff --git a/include/boost/geometry/extensions/index/rtree/visitors/gl_draw.hpp b/include/boost/geometry/extensions/index/rtree/visitors/gl_draw.hpp index 06cfb6c7c..cf8ec843a 100644 --- a/include/boost/geometry/extensions/index/rtree/visitors/gl_draw.hpp +++ b/include/boost/geometry/extensions/index/rtree/visitors/gl_draw.hpp @@ -122,17 +122,17 @@ struct gl_draw : public rtree::visitor const& tree, typedef typename rtree_type::box_type box_type; typedef typename rtree_type::allocators_type allocators_type; + if ( !tree.empty() ) + { + glColor3f(0.75f, 0.75f, 0.75f); + detail::rtree::visitors::detail::gl_draw_indexable(tree.box(), 0); + } + detail::rtree::visitors::gl_draw gl_draw_v(tree.translator(), level_first, level_last, z_coord_level_multiplier); diff --git a/include/boost/geometry/extensions/index/translator/def.hpp b/include/boost/geometry/extensions/index/translator/def.hpp index d880e2b13..5020a5b32 100644 --- a/include/boost/geometry/extensions/index/translator/def.hpp +++ b/include/boost/geometry/extensions/index/translator/def.hpp @@ -15,100 +15,164 @@ namespace boost { namespace geometry { namespace index { namespace translator { -namespace dispatch { - -// Distinguish between def, def and def - -// Geometry -template -struct def -{ - typedef typename detail::extract_indexable::type const& result_type; - - result_type operator()(Value const& v) const - { - return detail::extract_indexable::get(v); - } - - bool equals(Value const& v1, Value const& v2) const - { - return detail::equals::apply(v1, v2); - } -}; - -// Iterator -template -struct def -{ - typedef typename detail::extract_indexable::type const& result_type; - - result_type operator()(Value const& v) const - { - return detail::extract_indexable::get(*v); - } - - bool equals(Value const& v1, Value const& v2) const - { - return v1 == v2; - } -}; - -// SmartPtr -template -struct def -{ - typedef typename detail::extract_indexable::type const& result_type; - - result_type operator()(Value const& v) const - { - return detail::extract_indexable::get(*v); - } - - bool equals(Value const& v1, Value const& v2) const - { - return v1 == v2; - } -}; - -} // namespace dispatch +//namespace dispatch { +// +//// Distinguish between def, def and def +// +//// Geometry +//template +//struct def +//{ +// typedef typename detail::extract_indexable::type const& result_type; +// +// result_type operator()(Value const& v) const +// { +// return detail::extract_indexable::get(v); +// } +// +// bool equals(Value const& v1, Value const& v2) const +// { +// return detail::equals::apply(v1, v2); +// } +//}; +// +//// Iterator +//template +//struct def +//{ +// typedef typename detail::extract_indexable::type const& result_type; +// +// result_type operator()(Value const& v) const +// { +// return detail::extract_indexable::get(*v); +// } +// +// bool equals(Value const& v1, Value const& v2) const +// { +// return v1 == v2; +// } +//}; +// +//// SmartPtr +//template +//struct def +//{ +// typedef typename detail::extract_indexable::type const& result_type; +// +// result_type operator()(Value const& v) const +// { +// return detail::extract_indexable::get(*v); +// } +// +// bool equals(Value const& v1, Value const& v2) const +// { +// return v1 == v2; +// } +//}; +// +//} // namespace dispatch +// +///*! +//The default translator. It translates Value object to Indexable object. This is done in +//operator() which takes const reference to Value and returns const reference to Indexable. +// +//\tparam Value The Value type which the translator translates to Indexable. +//*/ +//template +//struct def +// : public dispatch::def +// < +// Value, +// detail::is_iterator::value, +// detail::is_smart_ptr::value +// > +//{ +//}; +// +///*! +//The default translator. It translates Value object to Indexable object. Since this is +//a specialization for pointers to Values operator() takes const ptr to Value and returns +//const reference to Indexable. +// +//\tparam Value The Value type which the translator translates to Indexable. +//*/ +//template +//struct def +//{ +// typedef typename detail::extract_indexable::type const& result_type; +// +// result_type operator()(const Value *v) const +// { +// return detail::extract_indexable::get(*v); +// } +// +// bool equals(const Value* v1, const Value* v2) const +// { +// return v1 == v2; +// } +//}; /*! -The default translator. It translates Value object to Indexable object. This is done in -operator() which takes const reference to Value and returns const reference to Indexable. +The default translator. It translates Value object to Indexable object. -\tparam Value The Value type which the translator translates to Indexable. +\tparam Value The Value type which may be translated directly to the Indexable. */ template struct def - : public dispatch::def - < - Value, - detail::is_iterator::value, - detail::is_smart_ptr::value - > { + BOOST_MPL_ASSERT_MSG( + (!detail::indexable_not_found_error< + typename traits::indexable_type::type + >::value), + NOT_VALID_INDEXABLE_TYPE, + (Value) + ); + + typedef Value const& result_type; + + result_type operator()(Value const& value) const + { + return value; + } + + bool equals(Value const& v1, Value const& v2) const + { + return geometry::equals(v1, v2); + } }; /*! -The default translator. It translates Value object to Indexable object. Since this is -a specialization for pointers to Values operator() takes const ptr to Value and returns -const reference to Indexable. +The default translator. This specialization translates from std::pair. -\tparam Value The Value type which the translator translates to Indexable. +\tparam Indexable The Indexable type. +\tparam Second The second type. */ -template -struct def +template +struct def< std::pair > { - typedef typename detail::extract_indexable::type const& result_type; + BOOST_MPL_ASSERT_MSG( + (!detail::indexable_not_found_error< + typename traits::indexable_type::type + >::value), + NOT_VALID_INDEXABLE_TYPE, + (Indexable) + ); - result_type operator()(const Value *v) const + typedef Indexable const& result_type; + + result_type operator()(std::pair const& value) const { - return detail::extract_indexable::get(*v); + return value.first; } - bool equals(const Value* v1, const Value* v2) const + bool equals(std::pair const& v1, std::pair const& v2) const { - return v1 == v2; + return geometry::equals(v1.first, v2.first) + && + dispatch::equals< + Second, + typename geometry::traits::tag::type + >::apply(v1.second, v2.second); } }; diff --git a/include/boost/geometry/extensions/index/translator/helpers.hpp b/include/boost/geometry/extensions/index/translator/helpers.hpp index 02610f31e..6f0ce2cfb 100644 --- a/include/boost/geometry/extensions/index/translator/helpers.hpp +++ b/include/boost/geometry/extensions/index/translator/helpers.hpp @@ -15,6 +15,7 @@ #include +#include #include #include diff --git a/test/rtree/test_rtree.hpp b/test/rtree/test_rtree.hpp index a5a8e65f8..d3ea2e8c4 100644 --- a/test/rtree/test_rtree.hpp +++ b/test/rtree/test_rtree.hpp @@ -533,7 +533,7 @@ void test_nearest_query_not_found(Rtree const& rtree, Point const& pt, Coordinat // rtree copying and moving template -void test_copy_assignment_move(bgi::rtree const& tree, Box const& qbox) +void test_copy_assignment_swap_move(bgi::rtree const& tree, Box const& qbox) { size_t s = tree.size(); @@ -560,25 +560,43 @@ void test_copy_assignment_move(bgi::rtree const& tree, Box const& q t1.spatial_query(qbox, std::back_inserter(output)); test_exactly_the_same_outputs(t1, output, expected_output); - // moving constructor - bgi::rtree t2(boost::move(t1)); + bgi::rtree t2(tree.parameters()); + t2.swap(t1); + BOOST_CHECK(tree.empty() == t2.empty()); + BOOST_CHECK(tree.size() == t2.size()); + BOOST_CHECK(true == t1.empty()); + BOOST_CHECK(0 == t1.size()); - BOOST_CHECK(t2.size() == s); - BOOST_CHECK(t1.size() == 0); + output.clear(); + t1.spatial_query(qbox, std::back_inserter(output)); + BOOST_CHECK(output.empty()); output.clear(); t2.spatial_query(qbox, std::back_inserter(output)); test_exactly_the_same_outputs(t2, output, expected_output); + t2.swap(t1); + + // moving constructor + bgi::rtree t3(boost::move(t1)); + + BOOST_CHECK(t3.size() == s); + BOOST_CHECK(t1.size() == 0); + + output.clear(); + t3.spatial_query(qbox, std::back_inserter(output)); + test_exactly_the_same_outputs(t3, output, expected_output); // moving assignment operator - t1 = boost::move(t2); + t1 = boost::move(t3); BOOST_CHECK(t1.size() == s); - BOOST_CHECK(t2.size() == 0); + BOOST_CHECK(t3.size() == 0); output.clear(); t1.spatial_query(qbox, std::back_inserter(output)); test_exactly_the_same_outputs(t1, output, expected_output); + + //TODO - test SWAP } // rtree removing @@ -634,7 +652,7 @@ void test_rtree_by_value(Parameters const& parameters) test_nearest_query_k(tree, input, pt, 10); test_nearest_query_not_found(tree, generate_outside_point

    ::apply(), 1, 3); - test_copy_assignment_move(tree, qbox); + test_copy_assignment_swap_move(tree, qbox); test_remove(tree, qbox); @@ -651,7 +669,7 @@ void test_rtree_by_value(Parameters const& parameters) test_nearest_query(empty_tree, empty_input, pt); test_nearest_query_k(empty_tree, empty_input, pt, 10); test_nearest_query_not_found(empty_tree, generate_outside_point

    ::apply(), 1, 3); - test_copy_assignment_move(empty_tree, qbox); + test_copy_assignment_swap_move(empty_tree, qbox); } // run all tests for one Algorithm for some number of rtrees diff --git a/tests/additional_glut_vis.cpp b/tests/additional_glut_vis.cpp index cd8eb5cc7..647b72b6b 100644 --- a/tests/additional_glut_vis.cpp +++ b/tests/additional_glut_vis.cpp @@ -9,6 +9,8 @@ #include +#define BOOST_GEOMETRY_INDEX_ENABLE_DEBUG_INTERFACE + #include #include @@ -31,9 +33,9 @@ std::vector vect; size_t found_count = 0; P search_point; -float min_distance = 20; +float min_distance = 10; float max_distance = 30; -size_t count = 10; +size_t count = 5; std::vector nearest_boxes; B search_box; @@ -50,11 +52,11 @@ void knn() search_point = P(x, y); nearest_boxes.clear(); - found_count = t.nearest( + found_count = t.nearest_query( bgi::bounded( search_point, - bgi::far(min_distance), - bgi::near(max_distance) + bgi::to_furthest(min_distance), + bgi::to_nearest(max_distance) ), count, std::back_inserter(nearest_boxes) @@ -87,13 +89,13 @@ void query() search_box = B(P(x - w, y - h), P(x + w, y + h)); nearest_boxes.clear(); - found_count = t.query(Predicate(search_box), std::back_inserter(nearest_boxes) ); + found_count = t.spatial_query(Predicate(search_box), std::back_inserter(nearest_boxes) ); } else { search_box = t.box(); nearest_boxes.clear(); - found_count = t.query(Predicate(search_box), std::back_inserter(nearest_boxes) ); + found_count = t.spatial_query(Predicate(search_box), std::back_inserter(nearest_boxes) ); } if ( found_count > 0 ) @@ -220,13 +222,23 @@ void resize(int w, int h) glViewport(0, 0, w, h); - gluPerspective(45, ratio, 1, 1000); + //gluPerspective(45, ratio, 1, 1000); + glOrtho(-150, 150, -150, 150, -150, 150); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - gluLookAt( + /*gluLookAt( 120.0f, 120.0f, 120.0f, 50.0f, 50.0f, -1.0f, + 0.0f, 1.0f, 0.0f);*/ + gluLookAt( + 50.0f, 50.0f, 75.0f, + 50.0f, 50.0f, -1.0f, 0.0f, 1.0f, 0.0f); + + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + glLineWidth(1.5f); + + srand(1); } void mouse(int button, int state, int x, int y) @@ -292,6 +304,33 @@ void keyboard(unsigned char key, int x, int y) { std::cout << "\n" << t << "\n"; } + else if ( current_line == "rand" ) + { + for ( size_t i = 0 ; i < 35 ; ++i ) + { + float x = ( rand() % 100 ); + float y = ( rand() % 100 ); + float w = ( rand() % 2 ) + 1; + float h = ( rand() % 2 ) + 1; + + B b(P(x - w, y - h),P(x + w, y + h)); + + boost::geometry::index::insert(t, b); + vect.push_back(b); + + std::cout << "inserted: "; + bgi::detail::rtree::visitors::detail::print_indexable(std::cout, b); + std::cout << '\n'; + } + + std::cout << ( bgi::are_boxes_ok(t) ? "boxes OK\n" : "WRONG BOXES!\n" ); + std::cout << ( bgi::are_levels_ok(t) ? "levels OK\n" : "WRONG LEVELS!\n" ); + std::cout << "\n"; + + search_valid = false; + + glutPostRedisplay(); + } else { if ( current_line == "knn" ) @@ -338,7 +377,7 @@ int main(int argc, char **argv) glutInit(&argc, argv); glutInitDisplayMode(GLUT_DEPTH | GLUT_SINGLE | GLUT_RGBA); glutInitWindowPosition(100,100); - glutInitWindowSize(800, 600); + glutInitWindowSize(600, 600); glutCreateWindow("boost::geometry::index::rtree GLUT test"); glutDisplayFunc(render_scene); diff --git a/tests/additional_speed.cpp b/tests/additional_speed.cpp index 5744e457b..71d669b90 100644 --- a/tests/additional_speed.cpp +++ b/tests/additional_speed.cpp @@ -21,7 +21,7 @@ int main() namespace bgi = bg::index; size_t values_count = 1000000; - size_t queries_count = 100000; + size_t queries_count = 1000000; std::vector< std::pair > coords;