Boost :: geometry查询返回索引

时间:2015-05-07 12:53:48

标签: c++ c++11 boost boost-geometry

我希望有一个类,它使用boost::geometry::index::rtree作为空间索引器。这个类本身应该知道boost,所以我使用这样的东西:

struct VeryImportantInfo
{
    ...
    float x;
    float y;
}

class Catalogue
{
    ...
public:
    std::vector<std::shared_ptr<VeryImportantInfo> > FindIn(float x1, float x2, float y1, float y2);

protected:
    using point = bg::model::point<float, 2, bg::cs::cartesian>;
    using value = std::pair<point, std::shared_ptr<VeryImportantInfo> >;
    using box = bg::model::box<point>;        

    boost::geometry::index::rtree< value, bgi::quadratic<16> > rtree;
}

std::vector<std::shared_ptr<VeryImportantInfo> > Catalogue::FindIn(float x1, float y1, float x2, float y2)
{
    box query_box(point(x1, y1), point(x2, y2));
    ???
}

我不知道如何正确地进行查询(请不要通过副本查看这个糟糕的矢量返回,这只是为了清酒)。我可以这样做:

std::vector<std::shared_ptr<VeryImportantInfo> > Catalogue::FindIn(float x1, float y1, float x2, float y2)
{
    box query_box(point(x1, y1), point(x2, y2));
    std::vector<value> result_s;
    rtree.query(bgi::intersects(query_box), std::back_inserter(result_s));
    std::vector<std::shared_ptr<VeryImportantInfo> > results;
    results.reserve(result_s.size());
    for( auto& p : result_s)
    {
        results.emplace_back(p.second);
    }
    return results;
}

我想知道,我怎样才能摆脱内部副本(不返回副本,results.emplace_back(p.second); - 这个)。因为result_s我可以获得10k以上的结果,这将是一种浪费。

谢谢!

1 个答案:

答案 0 :(得分:2)

更新到评论

如果首先担心临时矢量,请不要使用。您可以使用qbegin()中的qend() / boost::geometry::index免费功能:

std::vector<std::shared_ptr<VeryImportantInfo> > Catalogue::FindIn(float x1, float y1, float x2, float y2)
{
    box query_box(point(x1, y1), point(x2, y2));

    auto b = bgi::qbegin(rtree, bgi::intersects(query_box)), 
        e = bgi::qend(rtree);

    auto range  = boost::make_iterator_range(b, e);

    using namespace boost::adaptors;
    return boost::copy_range<std::vector<std::shared_ptr<VeryImportantInfo>>>(
            range | transformed([](value const& p) { return p.second; }));
}

事实上,如果知道rtree是常数,你甚至可以直接返回惰性范围,甚至不分配单个向量。

原始/旧答案文字如下:

如果没有引用计数,则无法复制共享指针。

当然,您可以将value对更改为包含引用到shared_ptr,但您可以使用原始引用(std :: reference_wrapper)或{{1 }}

weak_ptr

以下是我对原始引用的看法(只保留重要数据):)

<强> Live On Coliru

std::reference_wrapper<T>

#include <iostream> #include <vector> #include <boost/geometry/geometries/point_xy.hpp> #include <boost/geometry/index/rtree.hpp> namespace bg = boost::geometry; namespace bgi = bg::index; struct VeryImportantInfo { float x; float y; }; VeryImportantInfo a = { 2, 2 }; VeryImportantInfo b = { 3, 3 }; VeryImportantInfo c = { 4, 4 }; class Catalogue { public: Catalogue() { rtree.insert(value(point(a.x, a.y), a)); rtree.insert(value(point(b.x, b.y), b)); rtree.insert(value(point(c.x, c.y), c)); } std::vector<std::reference_wrapper<VeryImportantInfo> > FindIn(float x1, float x2, float y1, float y2); protected: using point = bg::model::point<float, 2, bg::cs::cartesian>; using value = std::pair<point, std::reference_wrapper<VeryImportantInfo> >; using box = bg::model::box<point>; boost::geometry::index::rtree< value, bgi::quadratic<16> > rtree; }; std::vector<std::reference_wrapper<VeryImportantInfo> > Catalogue::FindIn(float x1, float y1, float x2, float y2) { box query_box(point(x1, y1), point(x2, y2)); std::vector<value> result_s; rtree.query(bgi::intersects(query_box), std::back_inserter(result_s)); std::vector<std::reference_wrapper<VeryImportantInfo> > results; results.reserve(result_s.size()); for(auto& p : result_s) { results.push_back(p.second); } return results; } int main() { Catalogue cat; for (VeryImportantInfo& vii : cat.FindIn(1,2,3,4)) std::cout << vii.x << ", " << vii.y << "\n"; }

这与std::weak_ptr<T>相同。有人可能会说这并没有解决太多问题(因为重新计算仍在进行中),但至少需要减少工作量。

<强> Live On Coliru

weak_ptr<>