boost::geometry::Index::rtree
Boost::Geometry扩展
Boost::Geometry 包含可实例化的几何类,但库用户也可以使用自己的几何类。使用注册宏或特征类,可以调整它们的几何形状来实现 Boost::Geometry 概念。 Boost::Geometry 可用于几何发挥作用的所有领域:地图和 GIS、游戏开发、计算机图形和小部件、机器人、天文学等。核心被设计为尽可能通用并支持这些领域。目前,开发主要以 GIS 为主
-
编译要求
c++ 14
-
头文件
#include <boost/geometry.hpp>
快速入门
1. boost::geometry::Index
旨在收集称为空间索引的数据结构,这些结构可用于加速搜索空间中的对象。通常,空间索引存储几何对象的表示,并允许搜索占据某个空间或靠近空间中某个点的对象。 目前,仅实现一个空间索引 - R 树
2. R-tree
2.1 定义
空间数据的建模
基于实体的模型(基于对象)Entity-based models (or object based)
- 0-dimensional objects : 一般使用点point来表示那些对于不需要使用到形状信息的实体。
- 1-dimensional objects or linear objects: 用于表示一些路网的边,一般用于表示道路road。 (polyline)
- 2-dimensional objects or surfacic objects: 用于表示有区域面积的实体。 (polygon)
- 对于B/B+-Trees 由于它的线性特点,通常用来索引一维数据
R树是b树的多维版
R 树是用于空间搜索的树数据结构。它是由Antonin Guttman在1984年提出的,作为多维数据的B树的扩展。它可用于存储点或体积数据,以便执行空间查询。例如,此查询可以返回位于某个区域内或靠近空间中某个点 的对象。可以插入新对象或删除已存储的对象。 R 树结构如下图所示。每个 R 树的节点都存储一个框,描述其子节点所占用的空间。在结构的底部,有包含值(几何对象表示)的叶节点。
性质
- 自平衡数据结构。
- R 树的性能取决于平衡插入容器中的算法、参数和数据。( 更快的插入将导致更慢的搜索,反之亦然。)

更多原理分析
2.2 性能
不同算法构建树的流程
[运行机器](Intel(R) Core(TM) i7 870 @ 2.93GHz, 8GB RAM, MS Windows 7 x64*. The code was compiled with optimization for speed (O2).)
| 线性算法 | 二次规划算法 | R*-tree | 装箱算法 | |
|---|---|---|---|---|
| 示例结构 | ![]() | ![]() | ![]() | ![]() |
| 1M 数据插入 | 1.76s | 2.47s | 6.19s | 0.64s |
| 100k 数据查询 | 2.21s | 0.51s | 0.12s | 0.07s |
| 100k knn 查询 | 6.37s | 2.09s | 0.64s | 0.52s |
knn:( k-nearest neighbor )k个最近邻近查询
2.3 可查询关系
2.3.1 空间几何
rt.query(index::contains(box), std::back_inserter(result));
rt.query(index::covered_by(box), std::back_inserter(result));
rt.query(index::covers(box), std::back_inserter(result));
rt.query(index::disjont(box), std::back_inserter(result));
rt.query(index::intersects(box), std::back_inserter(result));
rt.query(index::overlaps(box), std::back_inserter(result));
rt.query(index::within(box), std::back_inserter(result));
2.3.2 最近邻查询
std::vector<Value> returned_values;
Point pt(/*...*/);
rt.query(bgi::nearest(pt, k), std::back_inserter(returned_values));//返回最近的k个空间索引
Segment seg(/*...*/);
rt.query(bgi::nearest(seg, k), std::back_inserter(returned_values));
2.3.3 函数查询
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));
//lambda表达式
#ifndef BOOST_NO_CXX11_LAMBDAS
rt.query(index::intersects(box) && index::satisfies([](Value const& v) { return v.is_red(); }),
std::back_inserter(result));
#endif
2.4 创建和使用
- 可索引类型
Indexable = Point | Box | SegmentValue = Indexable | std::pair<Indexable, T> | boost::tuple<Indexable, ...> [ | std::tuple<Indexable, ...> ]
| rtree<Point, ...> | rtree<Box, ...> | rtree<Segment, ...> |
|---|---|---|
![]() | ![]() | ![]() |
-
支持三种平衡算法
-
编译时
//线性 index::rtree< Value, index::linear<16> > rt; //二次规划 index::rtree< Value, index::quadratic<16> > rt; //R* index::rtree< Value, index::rstar<16> > rt; -
运行时
//线性 index::rtree<Value, index::dynamic_linear>rt(index::dynamic_linear(16)); //二次规划 index::rtree<Value, index::dynamic_quadratic>rt(index::dynamic_quadratic(16)); //R* index::rtree<Value, index::dynamic_rstar> rt(index::dynamic_rstar(16));
-
-
插入和删除
Value v = std::make_pair(Box(...), 0); rt.insert(v); rt.remove(v); -
迭代器插入
namespace bgi = boost::geometry::index; typedef std::pair<Box, int> Value; typedef bgi::rtree< Value, bgi::linear<32> > RTree; std::vector<Value> values; /* vector filling code, here */ // create R-tree and insert values from the vector RTree rt1; std::copy(values.begin(), values.end(), bgi::inserter(rt1)); // create R-tree and insert values returned by a query RTree rt2; rt1.spatial_query(Box(/*...*/), bgi::inserter(rt2));
2.5 实例
//导入头文件
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/index/rtree.hpp>
#include <vector>
#include <iostream>
#include <boost/foreach.hpp>
namespace bg = boost::geometry;
namespace bgi = boost::geometry::index;
/*
MyGeometryId 将是存储在其他容器中的复杂几何图形的某个标识符,
例如存储在向量中的多边形的索引类型或环列表的迭代器。
为了简化定义 Value 的过程,我们将使用预定义的 Box 和 unsigned int。
*/
typedef bg::model::point<float, 2, bg::cs::cartesian> point;
typedef bg::model::box<point> box;
typedef std::pair<box, unsigned> value;
/*
可以使用各种算法和参数创建R树。您应该选择最适合您目的的算法。
在此示例中,我们将使用二次算法。参数作为模板参数传递。节点中的最大元素数设置为 16
*/
bgi::rtree< value, bgi::quadratic<16> > rtree;
//手动生成一些框,并使用 insert() 方法将它们插入到 R 树中
for ( unsigned i = 0 ; i < 10 ; ++i )
{
// create a box
box b(point(i + 0.0f, i + 0.0f), point(i + 0.5f, i + 0.5f));
// insert new value
rtree.insert(std::make_pair(b, i));
}
/*
可以执行各种类型的空间查询,甚至可以在一次调用中将它们组合在一起。
为简单起见,我们使用默认的。以下查询返回与框相交的值。未指定结果中值的顺序。
*/
box query_box(point(0, 0), point(5, 5));
std::vector<value> result_s;
rtree.query(bgi::intersects(query_box), std::back_inserter(result_s));
// KNN 查询
std::vector<value> result_n;
rtree.query(bgi::nearest(point(0, 0), 5), std::back_inserter(result_n));
//查询结果打印
// display results
std::cout << "spatial query box:" << std::endl;
std::cout << bg::wkt<box>(query_box) << std::endl;
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 point:" << std::endl;
std::cout << bg::wkt<point>(point(0, 0)) << 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;
本文由博客一文多发平台 OpenWrite 发布!




