用于空间搜索的 Boost R 树

Posted

技术标签:

【中文标题】用于空间搜索的 Boost R 树【英文标题】:Boost R tree for spatial search 【发布时间】:2019-02-20 17:49:05 【问题描述】:

我正在尝试使用将存储 2D 几何点的打包算法创建一个 boost r 树。为了清楚起见,我不需要 kNN 搜索,但我需要的是找到位于同一 r 树成员的点的地平线一侧的点(地平线将是半径)。到目前为止,我发现的是使用随机点(不是 r-tree 成员的点)进行距离搜索的示例。我使用 bg::index::satisfies 进行了距离和索引检查,方法是传递一个检查索引是否不同并且距离小于半径的方法。我也使用 inside(box),但我不确定这是使用 r 树空间搜索作为同一 r 树成员的点的正确方法。因为据我所知,r-tree 中的点知道包含它的框的索引,所以没有办法只查询点和距离,但最终还是不会搜索整个树!?

这是我的代码

#include "stdafx.h"
#include <boost/function_output_iterator.hpp>
#include <boost/geometry/index/rtree.hpp>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <vector>
#include <iostream>


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

typedef bg::model::point <double, 2, bg::cs::cartesian> point;
typedef std::pair<point, std::size_t> pointI;
typedef bg::model::box<point> box;
typedef std::pair<point, unsigned> value;

bool CheckIndexAndDist(pointI i, pointI j, size_t dist);

std::vector<uint64_t> res;
struct StoreDataCallback

    template <typename Value>
    void operator()(Value const& v)
    
        res.push_back(v.second);
    
;


int _tmain(int argc, _TCHAR* argv[])

    std::vector<point> contourCenters; // has some value
    std::vector<pointI> cloud;

    int horizon = 3;
    double dX = 0;
    double length = 20;
    double width = 20;
    dX = length/10.0;

    for(int i = 0; i < length; i++)
    
        for(int j = 0; j < width; j++)
        
            point p;
            p.set<0>((-1.0 * length / 2.0) + dX  + j * dX);
            p.set<1>((-1.0 * width / 2.0) + dX  + i * dX);
            contourCenters.push_back(p);
        
    
    size_t id_gen = 0;
    std::transform(
            contourCenters.begin(), contourCenters.end(),
            back_inserter(cloud), 
            [&](point const& p)  return std::make_pair(p, id_gen++); 
        );

     bgi::rtree<pointI, bgi::quadratic<16> > rtree(cloud);

     // spatial search
    box query_box(point(cloud[10].first.get<0>() - 3.2*dX, cloud[10].first.get<1>() - 3.2*dX),point(cloud[10].first.get<0>() + 3.2*dX, cloud[10].first.get<1>() + 3.2*dX));
    StoreDataCallback callback;


    res.clear();
    rtree.query(
    bgi::within(query_box) &&
    bgi::satisfies([&](value const& v) return CheckIndexAndDist(v, cloud[10],3.015*dX);),
    boost::make_function_output_iterator(callback));

    return 0;


bool CheckIndexAndDist(pointI i, pointI j, size_t dist)

    if( i.second != j.second &&  (bg::distance(i.first, j.first) < dist))
        return true;
    else
        return false;

【问题讨论】:

【参考方案1】:

我也使用 inside(box),但我不确定这是正确的方法

这是正确的,即在谓词内是一个空间谓词,允许 R-tree 在几何查询期间过滤掉点,并在此之上检查是否满足谓词。如果 Boost.Geometry 有圆/球概念,您可以将其直接传递到 inside 谓词中,并且不需要满足,但由于不是这种情况,您必须在圆周围传递一个框。

官方界面不支持您要执行的查询类型。为了做一些不同的事情,您必须实现自己的 R-tree 访问者并使用 boost::geometry::index::detail::rtree::utilities::view 将其应用于 R-tree。请查看this directory 了解更多详情。

R-tree 不知道可以在其结构中的哪个位置找到该点。因此,如果您想选择一个任意点并获取其周围某个半径内的所有点,您仍然必须遍历 R-tree 以首先找到它的位置,然后在它周围搜索。因此,如果您想对 R-tree 中包含的大于 1 个元素执行这种搜索,那么这种搜索将是有意义的,因为这样您就必须有效地遍历 R-tree 的一部分,然后遍历每个元素您将在本地执行半径搜索。边缘情况将针对所有点执行此操作,自上而下遍历整个 R-tree,然后在 R-tree 结构中局部向上返回每个点以获取周围的其他点。

【讨论】:

以上是关于用于空间搜索的 Boost R 树的主要内容,如果未能解决你的问题,请参考以下文章

R树空间索引

R树空间索引

R树空间索引

C ++中的排名树

查找树(搜索树)

`@geodist` 如何在 Sphinx 中实现排序/搜索?