Boost::geometry 查询返回索引
Boost::geometry query returning indexes
我想要 class,它使用 boost::geometry::index::rtree
作为空间索引器。仅此 class 应该知道 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));
???
}
我不知道如何正确查询(请不要复制这个糟糕的向量return,它只是为了举例) .我可以这样做:
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;
}
我想知道,我怎样才能摆脱内部副本(不是return副本,results.emplace_back(p.second);
- 这个)。因为我可以在 result_s
中获得超过 10k 个结果,这将是一种浪费。
谢谢!
更新评论
如果一开始就担心临时向量,那就不要使用它。您可以使用来自 boost::geometry::index
:
的 qbegin()
/qend()
免费函数
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 是常量,您甚至可以直接 return 惰性范围,甚至不分配单个向量。
original/old 回答正文如下:
没有引用计数就不能复制共享指针。
当然,您可以更改 value
对以包含对 shared_ptr 的 引用 ,但是您可以使用原始引用 ( std::reference_wrapper) 或 weak_ptr
.
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>
这里和weak_ptr<>
一样。有人可能会争辩说这并不能解决很多问题(因为引用计数仍在进行)但至少需要的工作更少。
#include <iostream>
#include <memory>
#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;
};
auto a = std::make_shared<VeryImportantInfo>(VeryImportantInfo{2, 2});
auto b = std::make_shared<VeryImportantInfo>(VeryImportantInfo{3, 3});
auto c = std::make_shared<VeryImportantInfo>(VeryImportantInfo{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::weak_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::weak_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::weak_ptr<VeryImportantInfo> > results;
results.reserve(result_s.size());
for(auto& p : result_s) {
results.push_back(p.second);
}
return results;
}
int main() {
Catalogue cat;
for (auto& vii_p : cat.FindIn(1,2,3,4))
if (auto vii = vii_p.lock())
std::cout << vii->x << ", " << vii->y << "\n";
}
我想要 class,它使用 boost::geometry::index::rtree
作为空间索引器。仅此 class 应该知道 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));
???
}
我不知道如何正确查询(请不要复制这个糟糕的向量return,它只是为了举例) .我可以这样做:
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;
}
我想知道,我怎样才能摆脱内部副本(不是return副本,results.emplace_back(p.second);
- 这个)。因为我可以在 result_s
中获得超过 10k 个结果,这将是一种浪费。
谢谢!
更新评论
如果一开始就担心临时向量,那就不要使用它。您可以使用来自 boost::geometry::index
:
qbegin()
/qend()
免费函数
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 是常量,您甚至可以直接 return 惰性范围,甚至不分配单个向量。
original/old 回答正文如下:
没有引用计数就不能复制共享指针。
当然,您可以更改 value
对以包含对 shared_ptr 的 引用 ,但是您可以使用原始引用 ( std::reference_wrapper) 或 weak_ptr
.
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>
这里和weak_ptr<>
一样。有人可能会争辩说这并不能解决很多问题(因为引用计数仍在进行)但至少需要的工作更少。
#include <iostream>
#include <memory>
#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;
};
auto a = std::make_shared<VeryImportantInfo>(VeryImportantInfo{2, 2});
auto b = std::make_shared<VeryImportantInfo>(VeryImportantInfo{3, 3});
auto c = std::make_shared<VeryImportantInfo>(VeryImportantInfo{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::weak_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::weak_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::weak_ptr<VeryImportantInfo> > results;
results.reserve(result_s.size());
for(auto& p : result_s) {
results.push_back(p.second);
}
return results;
}
int main() {
Catalogue cat;
for (auto& vii_p : cat.FindIn(1,2,3,4))
if (auto vii = vii_p.lock())
std::cout << vii->x << ", " << vii->y << "\n";
}