繁体   English   中英

如何使用模板 class 设置 Boost RTree 节点

[英]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<>实现
  • 提供你自己的 IndexableGetter

显示第二个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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM