R树上的多级查询(交集,并集)

时间:2018-11-20 18:32:50

标签: c++ boost boost-geometry r-tree

说我有以下设置:

我有一个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,我想做两种复杂的查询:

  1. 给定间隔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中的所有间隔都是不相交的。

  1. 给定了一组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产生的迭代器,但是, 最有效的方式是什么?

1 个答案:

答案 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()函数。等等

相关问题