[英]How to set Boost RTree Node with template class
我有两个文件:header.h 和 code.cpp,我不能在 code.cpp 上写任何 boost 命名空间,所以所有的“boost::geometry::etc...”在 Z099FB995346F31C95E3F6 上调用 go。 这个想法是实现两个模板类:一个用于 RTree,另一个用于 RTree 节点,这样用户可以包含 header.h 文件并使用 header.h 上的两个模板类在 code.cpp 上实现 RTree。 这是我到目前为止所拥有的:
header.h:
template< class TT > class Node
{
using PointType = boost::geometry::model::d2::point_xy< TT >;
using BoxType = boost::geometry::model::box< PointType >;
using NodeType = std::pair< BoxType, std::string >;
NodeType node;
public:
Node(){}
template< class T >
Node( const BBox< T > &box, const std::string nodeName ){
node = std::make_pair( BoxType{ PointType{ box.xLo(), box.yLo() },
PointType{ box.xHi(), box.yHi() } }, nodeName );
}
};
template< class TT > class RTree
{
using RTreeType = boost::geometry::index::rtree< TT, boost::geometry::index::quadratic< 16 > >;
RTreeType rtree;
public:
RTree(){}
template< T >
void insertBox( const BBox< T > &box, const std::string nodeName ) {
rtree.insert( Node< T >( box, nodeName ) );
}
template< T >
void query( const BBox< T > &box, std::vector< Node< T > > &queryResult ) {
rtree.query( boost::geometry::index::intersects( Node< T >( box, "" ) ),
std::back_inserter( queryResult ) );
}
};
我得到的一些错误:
error: could not convert 'boost::geometry::index::detail::indexable<Node<int>, false>::NOT_VALID_INDEXABLE_TYPE31::assert_arg()' from 'mpl_::failed************(boost::geometry::index::detail::indexable<Node<int>, false>::NOT_VALID_INDEXABLE_TYPE::************)(Node<int>)' to 'mpl_::assert<false>::type' {aka 'mpl_::assert<false>'}
31 | BOOST_MPL_ASSERT_MSG(
| ^
| |
| mpl_::failed************ (boost::geometry::index::detail::indexable<Node<int>, false>::NOT_VALID_INDEXABLE_TYPE::************)(Node<int>)
...
error: could not convert 'boost::geometry::traits::point_type<Node<int> >::NOT_IMPLEMENTED_FOR_THIS_POINT_TYPE45::assert_arg()' from 'mpl_::failed************ (boost::geometry::traits::point_type<Node<int> >::NOT_IMPLEMENTED_FOR_THIS_POINT_TYPE::************)(mpl_::assert_::types<Node<int>, mpl_::na, mpl_::na, mpl_::na>)' to 'mpl_::assert<false>::type' {aka 'mpl_::assert<false>'}
45 | BOOST_MPL_ASSERT_MSG
| ^
| |
| mpl_::failed************ (boost::geometry::traits::point_type<Node<int> >::NOT_IMPLEMENTED_FOR_THIS_POINT_TYPE::************)(mpl_::assert_::types<Node<int>, mpl_::na, mpl_::na, mpl_::na>)
...
error: no type named 'type' in 'struct boost::geometry::traits::point_type<Node<int> >'
66 | >::type type;
| ^~~~
在我看来,我必须使用indexable 。 虽然我不确定我应该如何使用我已经拥有的代码来做到这一点。 欢迎任何帮助,在此先感谢。
我们不得不猜测 BBox 是什么。 但总而言之,看起来您“只是”想要一棵带有(框,名称)节点的树。
我建议跳过Node
class (以及所有 generics 无论如何都不起作用,因为您将转换硬编码为Node<T>
无论如何,这只适用于几何可转换(盒子和盒子不相互转换)。
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/index/rtree.hpp>
namespace bg = boost::geometry;
namespace bgi = boost::geometry::index;
namespace detail {
template <typename Coord> using Point = bg::model::d2::point_xy<Coord>;
template <typename Coord> using BBox = bg::model::box<Point<Coord>>;
template <class Coord> using Node = std::pair<BBox<Coord>, std::string>;
}
template <class Coord> struct RTree {
using Point = detail::Point<Coord>;
using Box = detail::BBox<Coord>;
using Node = detail::Node<Coord>;
using RTreeType = bgi::rtree<Node, bgi::quadratic<16>>;
void insertBox(Box box, const std::string nodeName) {
rtree.insert(Node(box, nodeName));
}
using Result = std::vector<Node>;
void query(Box box, Result& queryResult) {
rtree.query(bgi::intersects(box), back_inserter(queryResult));
}
private:
RTreeType rtree;
};
int main() {
using Tree = RTree<double>;
Tree x;
x.insertBox({{1.0, 2.0}, {7.0, 8.0}}, "first");
x.insertBox({{2.0, 3.0}, {6.0, 7.0}}, "second");
Tree::Result v;
x.query({{3.0, 4.0}, {5.0, 6.0}}, v);
for (auto& [box,name] : v)
std::cout << std::quoted(name) << ": " << bg::wkt(box) << "\n";
}
印刷
"first": POLYGON((1 2,1 8,7 8,7 2,1 2))
"second": POLYGON((2 3,2 7,6 7,6 3,2 3))
如果您确实没有显示完整的图片,并且您需要Node<T>
超过显示,请考虑
std::pair
派生并使用现有的indexable<>
实现显示第二个Live On Coliru :
namespace detail {
template <typename Coord> using Point = bg::model::d2::point_xy<Coord>;
template <typename Coord> using BBox = bg::model::box<Point<Coord>>;
template <class Coord> struct Node {
using Indexable = BBox<Coord>;
using Id = std::string;
Indexable box;
Id name;
Node(Indexable b, Id n) : box(std::move(b)), name(std::move(n)) {}
struct Getter {
using result_type = Indexable const&;
result_type operator()(Node const& v) const { return v.box; }
};
};
}
template <typename Coord>
struct bgi::indexable<::detail::Node<Coord>>
: ::detail::Node<Coord>::Getter {};
没有进一步的变化,仍在打印
"first": POLYGON((1 2,1 8,7 8,7 2,1 2))
"second": POLYGON((2 3,2 7,6 7,6 3,2 3))
备查。
我很难理解 Boost 如何为用户设置接口以将他们自己的 object 定义为 RTree 节点。 似乎有不止一种方法可以做到这一点(例如使用宏)。 其中之一是@sehe 通过使用 Indexable functor指出的方式。 所以这个带有 function 描述的笨拙的结构 Getter 是一个重载() operator
的函子,这就是 Boost 知道如何从我自己的 class 获取坐标的方式。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.