Boost R树:计算满足查询的元素
Boost R-tree : counting elements satisfying a query
到目前为止,当我想计算R树中有多少元素满足特定的空间查询时,可以归结为运行查询,收集匹配项,然后计数,大致如下:
std::vector<my_type> results;
rtree_ptr->query(bgi::intersects(query_box), std::back_inserter(results));
int nbElements = results.size();
有没有更好的方法,即在不检索实际元素的情况下直接计数?我还没找到什么办法,但谁知道呢。(我正在用打包算法构建我的树,以防它有任何相关性。)
我的动机是注意到查询的速度取决于匹配的数量。如果有0个匹配项,则查询或多或少是即时的;如果有10000场比赛,需要几秒钟。由于可以很快确定是否有匹配,因此遍历树似乎非常快(至少在我创建的索引中);它收集了所有的结果,这使得在有很多匹配的情况下查询速度变慢。由于我对收集不感兴趣,只是简单地计数(至少对于一些查询),如果我可以跳过收集,那就太棒了。
我的脑电波很晚。甚至比使用function_output_iterator
更好的是使用boost::geometry::index
query_iterator。
原则上,它将导致与稍微简单的代码完全相同的行为:
box query_box;
auto r = boost::make_iterator_range(bgi::qbegin(tree, bgi::intersects(query_box)), {});
// in c++03, spell out the end iterator: bgi::qend(tree)
size_t nbElements = boost::distance(r);
注意:
size()
不可用,因为query_const_iterator
不属于随机访问类别。
但组合起来可能会稍微舒服一些。比如说,如果你想对每件物品进行额外的检查,你可以使用标准的库算法,比如:
size_t matching = std::count_if(r.begin(), r.end(), some_predicate);
我认为基于范围的解决方案更灵活(相同的代码可以用于实现其他算法,如partial_sort_copy
或std::transform
,这很难适应我之前回答中的输出迭代器习惯用法)。
您可以使用函数输出迭代器:
size_t cardinality = 0; // number of matches in set
auto count_only = boost::make_function_output_iterator([&cardinality] (Tree::value_type const&) { ++cardinality; });
这样使用:
使用lambda的C++11
在Coliru上直播
#include <boost/function_output_iterator.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/index/rtree.hpp>
namespace bgi = boost::geometry::index;
using point = boost::geometry::model::d2::point_xy<int, boost::geometry::cs::cartesian>;
using box = boost::geometry::model::box<point>;
int main()
{
using Tree = bgi::rtree<box, bgi::rstar<32> >;
Tree tree;
size_t cardinality = 0; // number of matches in set
auto count_only = boost::make_function_output_iterator([&cardinality] (Tree::value_type const&) { ++cardinality; });
box query_box;
tree.query(bgi::intersects(query_box), count_only);
int nbElements = cardinality;
return nbElements;
}
C++03使用函数对象
对于C++,您可以将lambda替换为(多态!)函数对象:
struct count_only_f {
count_only_f(size_t& card) : _cardinality(&card) { }
template <typename X>
void operator()(X) const {
++(*_cardinality);
}
private:
size_t *_cardinality;
};
// .... later:
boost::function_output_iterator<count_only_f> count_only(cardinality);
C++03使用Boost Phoenix
我认为这是一个使用Boost Phoenix:的好地方
#include <boost/phoenix.hpp>
// ...
size_t cardinality = 0; // number of matches in set
tree.query(bgi::intersects(query_box), boost::make_function_output_iterator(++boost::phoenix::ref(cardinality)));
或者,更典型的名称空间别名:
#include <boost/phoenix.hpp>
// ...
size_t cardinality = 0; // number of matches in set
tree.query(bgi::intersects(query_box), make_function_output_iterator(++phx::ref(cardinality)));
相关文章:
- Mongodb c++驱动程序:如何查询元素的数组
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 使用strcpy将char数组的元素复制到另一个数组
- 使用不带参数的函数访问结构元素
- 给定n个元素的m个集合.在C++中找到出现在最大集合数中的元素
- 查询SQLite数据库中的日期
- C++如何通过用户输入删除列表元素
- lower_bound()返回最后一个元素
- 基于多个条件处理地图中的所有元素
- 调整大小后指向元素值的指针unordered_map有效?
- 使用std::transform将一个范围的元素添加到另一个范围中
- 使用函数"remove"删除重复元素
- 具有最大子序列大小的序列,每个元素都相同
- 如何将两个不同矢量的同一位置的两个元素组合在一起
- 如何将元素添加到数组的线程安全函数?
- 对于多个查询,查找在 l 到 r 范围内具有相同元素的最长公共子数组
- MongoDB C 查询文档的子元素
- 从equal_range查询中筛选和修改 boost::multi_index 中的元素
- Boost R树:计算满足查询的元素
- 基于数组中移动元素的查询