说我有以下设置:
我有一个boost::geometry::index::rtree
,它用一个二维盒子作为键,并用一个点作为值。
实际上,框的第一个维度将应用于(实值封闭)区间,而第二个维度仅指向点。
所以我的盒子看起来像:
using namespace std;
typedef bg::model::point<unsigned long, 2, bg::cs::cartesian> _pt_t;
typedef bg::model::box<_pt_t> _box_t;
typedef pair<_box_t, unsigned long> tree_v_t;
typedef bgi::rtree<tree_v_t, bgi::quadratic<16> > rtree_t;
将始终使用以下方式初始化框:
_box_t _mb(unsigned long i, unsigned long s, unsigned long d){
_box_t b(_pt_t(s, i), _pt_t(s + d, i));
return b;
}
现在让我们说我已经初始化了rtree,我想做两种复杂的查询:
si
的集合set<pair<unsigned int, unsigned int> >
和点sp
的集合set<unsigned int>
的情况下,我想迭代以下< strong>伪代码查询:any(si, intersect(rtree_level1)) && any(sp, contains(rtree_level2)) && value in ps
换句话说,我希望rtree的子树包含si
中包含的区间和sp
中包含的点的交集,并且其值也位于sp
。如果愿意,可以假定si中的所有间隔都是不相交的。
spi
的点和间隔set<unsigned int, pair<unsigned int, unsigned int> >
,我想迭代以下 pseudocode 查询所产生的所有值:any(spi, intersect(rtree_level1)(spi.interval) && contains(rtree_level2)(spi.point) && value in spi.point )
换句话说,我想要来自spi
每个元素的所有子树的联合,对于这些子树,它们是给定区间的交集它们包含,这些点既是键(第二级)又是值。如果 si 和 sp 都具有一个元素,则这就像 union 从查询1 生成的所有R树
我可以理解如何使用satisfy
谓词并将transform
应用于qbegin
产生的迭代器,但是,
最有效的方式是什么?
答案 0 :(得分:0)
这是一个具有双索引(R树和std :: map)的基本程序,它执行双向索引:从char到box / interval,从box / interval到char:
包括,iostream
仅用于输出。
#include <boost/geometry.hpp>
#include <map>
#include <vector>
#include <iostream>
为方便起见,命名空间。
namespace bg = boost::geometry;
namespace bgi = boost::geometry::index;
基本双向索引允许插入box / interval-char对,并基于char查找基于box的字符或基于box(相交)的chars向量。 insert()
根据需要合并框。
template <typename Box, typename T>
class rtree_map_index
{
typedef std::map<T, Box> map_type;
typedef typename map_type::iterator map_iterator;
typedef typename map_type::const_iterator map_const_iterator;
typedef std::pair<Box, map_iterator> rtree_value;
typedef bgi::rtree<rtree_value, bgi::rstar<4> > rtree_type;
public:
void insert(Box const& box, T const& v)
{
std::pair<map_iterator, bool>
p = m_map.insert(std::make_pair(v, box));
map_iterator map_it = p.first;
T const& map_val = map_it->first;
Box & map_box = map_it->second;
// new key,value inserted into map
if (p.second)
{
// insert it to the r-tree
m_rtree.insert(rtree_value(map_box, map_it));
}
// key already exists in map and box has to be expanded
else if (! bg::covered_by(box, map_box))
{
// calculate expanded box
Box new_box = map_box;
bg::expand(new_box, box);
// update r-tree
m_rtree.remove(rtree_value(map_box, map_it));
m_rtree.insert(rtree_value(new_box, map_it));
// update map
map_box = new_box;
}
}
bool find(T const& v, Box & result) const
{
map_const_iterator it = m_map.find(v);
if (it != m_map.end())
{
result = it->second;
return true;
}
return false;
}
void find(Box const& box, std::vector<char> & result) const
{
std::vector<rtree_value> res;
m_rtree.query(bgi::intersects(box), std::back_inserter(res));
result.resize(res.size());
for (size_t i = 0; i < res.size(); ++i)
result[i] = res[i].second->first;
}
private:
rtree_type m_rtree;
map_type m_map;
};
具有基本用例的主要功能。
int main()
{
用于存储在r树中的二维数据(框)。
{
typedef bg::model::point<double, 2, bg::cs::cartesian> point;
typedef bg::model::box<point> box;
rtree_map_index<box, char> index;
index.insert(box(point(0, 0), point(3, 3)), 'a');
index.insert(box(point(1, 1), point(4, 4)), 'a');
index.insert(box(point(5, 5), point(6, 6)), 'b');
box res1;
index.find('a', res1);
std::cout << bg::wkt(res1) << std::endl;
std::vector<char> res2;
index.find(box(point(4, 4), point(5, 5)), res2);
BOOST_ASSERT(res2.size() == 2);
std::cout << res2[0] << std::endl;
std::cout << res2[1] << std::endl;
}
用于存储在r树中的一维数据(间隔)
{
typedef bg::model::point<double, 1, bg::cs::cartesian> point;
typedef bg::model::box<point> box;
rtree_map_index<box, char> index;
index.insert(box(point(0), point(3)), 'a');
index.insert(box(point(1), point(4)), 'a');
index.insert(box(point(5), point(6)), 'b');
box res1;
index.find('a', res1);
std::cout << "(" << bg::get<0, 0>(res1) << ", " << bg::get<1, 0>(res1) << ")" << std::endl;
std::vector<char> res2;
index.find(box(point(4), point(5)), res2);
BOOST_ASSERT(res2.size() == 2);
std::cout << res2[0] << std::endl;
std::cout << res2[1] << std::endl;
}
结束。
return 0;
}
请注意,您可以使用rtree
代替interval_map
。您应该能够在rtree_map_index
之上构建。您可以添加一个构造函数,以从类型为std::pair<Box, T>
的元素容器中创建映射和rtree,以利用r-tree打包算法的优势。您可以实现所需的任何find()
函数。等等