如何在r树的内部节点存储一些信息?

时间:2019-04-10 08:31:34

标签: c++

我是Boost和C ++的新手。我正在尝试使用Boost库对r树进行编码。在我的代码中,我想在每个内部节点存储一些信息x。我现在有两个问题。

1)如何在r星树中执行遍历(深度优先)?

2)假设我可以遍历树的节点。需要为Box(INTERNAL node)类定义一些成员变量,在其中我可以在每个节点上存储x。什么是合适且有效的方法?

1 个答案:

答案 0 :(得分:0)

通过阅读您的评论,我得到的印象是,您只想在R树中存储的点中存储其他数据,而不想在R树的内部节点中存储其他数据。因此,这里有一个示例,显示了如何存储带有附加数据的点以及如何执行查询以获取其中的一些数据。在示例中,我还展示了如何使用std::pair保持一个点以及默认情况下可以工作的一些其他数据来实现相同目的,而您不必注册自己的点类型。

包括:

#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/geometries/register/point.hpp>
#include <boost/geometry/index/rtree.hpp>
#include <vector>
#include <iostream>

为方便起见,命名空间:

namespace bg = boost::geometry;
namespace bgi = boost::geometry::index;

使用二维坐标和其他数据(颜色)定义自己的点类型:

enum color {red, green, blue};

struct my_point
{
    double x, y;
    color c;
};

使用宏将my_point适配到Boost.Geometry Point概念,因此库知道该结构是二维Point以及如何获取坐标:

BOOST_GEOMETRY_REGISTER_POINT_2D(my_point, double, bg::cs::cartesian, x, y)

还将使用一些Boost.Geometry模型:

typedef bg::model::point<double, 2, bg::cs::cartesian> bg_point;
typedef bg::model::box<bg_point> bg_box;

主要:

int main()
{
    {

创建R树并插入几个点:

        bgi::rtree<my_point, bgi::rstar<4> > rtree;
        rtree.insert(my_point{ 0, 0, red });
        rtree.insert(my_point{ 1, 1, green });
        rtree.insert(my_point{ 2, 5, blue });
        rtree.insert(my_point{ 7, 3, red });
        rtree.insert(my_point{ 8, 8, green });
        rtree.insert(my_point{ 1, 9, blue });

查询与以下框相交且为红色的点:

        std::vector<my_point> res;
        rtree.query(bgi::intersects(bg_box{ {1, 1}, {8, 8} })
                 && bgi::satisfies([](my_point const& p) {
                        return p.c == red;
                    }),
                    std::back_inserter(res));

打印结果:

        for (my_point const& p : res)
            std::cout << bg::wkt(p) << std::endl;
    }

使用相同但使用std::pair<bg_point, color>代替my_point,因此不需要注册:

    {
        bgi::rtree<std::pair<bg_point, color>, bgi::rstar<4> > rtree;
        rtree.insert(std::pair<bg_point, color>{ {0, 0}, red });
        rtree.insert(std::pair<bg_point, color>{ {1, 1}, green });
        rtree.insert(std::pair<bg_point, color>{ {2, 5}, blue });
        rtree.insert(std::pair<bg_point, color>{ {7, 3}, red });
        rtree.insert(std::pair<bg_point, color>{ {8, 8}, green });
        rtree.insert(std::pair<bg_point, color>{ {1, 9}, blue });

        std::vector<std::pair<bg_point, color> > res;
        rtree.query(bgi::intersects(bg_box{ { 1, 1 },{ 8, 8 } })
                 && bgi::satisfies([](std::pair<bg_point, color> const& p) {
                        return p.second == red;
                    }),
                    std::back_inserter(res));

        for (std::pair<bg_point, color> const& p : res)
            std::cout << bg::wkt(p.first) << std::endl;
    }
}

上面的程序两次打印以下行:

POINT(7 3)

这是与盒子相交的唯一一个红点。


原始答案(如果您确实要修改R树的内部结构):

公共R-tree界面不支持您要执行的操作。您必须使用将来可能会发生变化的内部组件。

  1. Here是一个线程,解释了如何编写访问者以遍历R树节点。

  2. 使用您自己的节点类型比较困难。您必须:

    1. 添加新的节点标签like this
    2. 专门为此标签like in this file
    3. 内部和叶节点(在节点中添加您喜欢的成员)和所有其他必需的类
    4. 实现您自己的R树参数类型,例如基于bgi::rstarlike this
    5. 专门化bgi::detail::rtree::options_type以便告诉R树您的参数类型应使用哪些节点like this

    另请参阅this node implementation用于R树测试。这是一个可能在构造上引发异常的节点。它用于测试异常安全性。