Templated hierarchical spatial trees designed for high-peformance.
Templated hierarchical spatial trees designed for high-performance and hierarchical spatial partitioning use cases.
There are two tree implementations, a multi-dimensional RTree and a two-dimensional QuadTree.
Some of the currently implemented features are:
The implementation is header only, it's only requirement is at least (C++03) support.
How to create and insert items to the trees:
spatial::QuadTree<int, Box2<int>, 2> qtree(bbox.min, bbox.max);
spatial::RTree<int, Box2<int>, 2> rtree;
const Box2<int> kBoxes[] = {...};
qtree.insert(kBoxes, kBoxes + sizeof(kBoxes) / sizeof(kBoxes[0]));
rtree.insert(kBoxes, kBoxes + sizeof(kBoxes) / sizeof(kBoxes[0]));
Box2<int> box = {{7, 3}, {14, 6}};
qtree.insert(box);
rtree.insert(box);
```
Conditional insert:
```cpp
const decltype(rtree)::bbox_type boxToAdd = {{7, 4}, {14, 6}};
bool wasAdded =
rtree.insert(boxToAdd, [&boxToAdd](const decltype(rtree)::bbox_type &bbox) {
return !bbox.overlaps(boxToAdd);
});
How to use the indexable getter:
struct Object {
spatial::BoundingBox<int, 2> bbox;
std::string name;
};
// helps to get the bounding of the items inserted
struct Indexable {
const int *min(const Object &value) const { return value.bbox.min; }
const int *max(const Object &value) const { return value.bbox.max; }
};
spatial::QuadTree<int, Object, 2, Indexable> qtree(bbox.min, bbox.max);
qtree.insert(objects.begin(), objects.end());
spatial::RTree<int, Object, 2, 4, 2, Indexable> rtree;
rtree.insert(objects.begin(), objects.end());
Leaf and depth traversal:
spatial::RTree<int, Object, 2, 4, 2, Indexable> rtree;
// gives the spatial partioning order within the tree
for (auto it = rtree.lbegin(); it.valid(); it.next()) {
std::cout << (*it).name << "\n";
}
assert(rtree.levels() > 0);
for (auto it = rtree.dbegin(); it.valid(); it.next()) {
// traverse current children of the parent node(i.e. upper level)
for (auto nodeIt = it.child(); nodeIt.valid(); nodeIt.next()) {
std::cout << "level: " << nodeIt.level() << " " << (*nodeIt).name
<< "\n";
}
// level of the current internal/hierachical node
std::cout << "level: " << it.level() << "\n";
}
How to use the search algorithms:
Box2<int> searchBox = {{0, 0}, {8, 31}};
std::vector<Box2<int>> results;
rtree.query(spatial::intersects<2>(searchBox.min, searchBox.max), std::back_inserter(results));
rtree.query(spatial::contains<2>(searchBox.min, searchBox.max), std::back_inserter(results));
// to be used only if inserted points into the tree
rtree.query(spatial::within<2>(searchBox.min, searchBox.max), std::back_inserter(results));
// hierachical query that will break the search if a node is fully contained
rtree.hierachical_query(spatial::intersects<2>(searchBox.min, searchBox.max), std::back_inserter(results));
// neatest neighbor search
rtree.nearest(point, radius, std::back_inserter(results));
How to use the ray query:
rayOrigin = Point<float>({ 62, 70 });
rayDir = Point<float>({ 0, -2 });
rtree.rayQuery(rayOrigin.data, rayDir.data, std::back_inserter(results), fnTestPredicate);
// can also provide a filter predicate
auto fnFilterPredicate = [](const Box2<int>& box) {return box.min[0] == 0; };
rtree.rayQuery(rayOrigin.data, rayDir.data, std::back_inserter(results), fnFilterPredicate);
Be sure to check the test folder for more detailed usage and examples.
Benchmark setup is based on spatial_index_benchmark by Mateusz Loskot and Adam Wulkiewicz.
Complete set of result logs in results directory.
HW: Intel(R) Core(TM) i7-4870HQ CPU @ 2.50GHz, 16 GB RAM; OS: macOS Sierra 10.12.16
For more detailed benchmark results check the benchmark directory.
bgi
- boost::geometry::index, compile timethst
- thstct
- compile-time specification of rtree parametersrt
(or non suffix) - Boost.Geometry-only, run-time specification of rtree parametersL
- linearQ
- quadraticQT
- quadtreeR
- rstaritr (or no suffix)
- iterative insertion method of building rtreeblk
- bulk loading method of building R-tree (custom algorithm for bgi
)custom
- custom allocator variant for thst(cache friendly, linear memory)sphere
- sphere volume for computing the boxes's volume, better splitting but costlierPossible improvements are:
Based on:
Bug reports and pull requests are welcome on GitHub at https://github.com/tuxalin/thst.
The code is available as open source under the terms of the MIT License.