How to inherit from boost::geometry::model::point?

无人久伴 提交于 2019-12-22 09:05:56

问题


I'd like to inherit from bg::model::point to extend it with own functionality. The *point*s shall be stored in an rtree.

The following minimal example fails to compile the usage of my derived point (boost 1.54, gcc 4.7.2):

#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/index/rtree.hpp>
#include <iostream>
#include <boost/shared_ptr.hpp>

namespace bg = boost::geometry;
namespace bgi = boost::geometry::index;

namespace boost { namespace geometry { namespace index {

// apparently necessary:
template <typename Box>
struct indexable< boost::shared_ptr<Box> >
{
    typedef boost::shared_ptr<Box> V;

    typedef Box const& result_type;
    result_type operator()(V const& v) const { return *v; }
};

}}} // namespace boost::geometry::index


namespace { // anonymous namespace

// myPoint
template<typename CoordinateType, std::size_t DimensionCount, typename CoordinateSystem>
class myPoint : public bg::model::point<CoordinateType, DimensionCount, CoordinateSystem>{
public:
    void sayHello(void);
};

template<typename CoordinateType, std::size_t DimensionCount, typename CoordinateSystem>
void myPoint< CoordinateType, DimensionCount, CoordinateSystem >::sayHello() {
    std::cout<<"Hello!"<<std::endl;
}

} // end anonymous namespace

int main(void)
{
    typedef bg::model::point<float, 2, bg::cs::cartesian> point; // boost point version
    typedef myPoint<float, 2, bg::cs::cartesian> mypoint; // custom point version

    // create the rtree using default constructor
    bgi::rtree< boost::shared_ptr<point>, bgi::rstar<16, 4> > rtree; // that works
    bgi::rtree< boost::shared_ptr<mypoint>, bgi::rstar<16, 4> > myrtree; // that doesn't works

    return 0;
}

how can i derive from bg::model::point? or, instead of inheriting, is there a better approach?

thanks!


回答1:


Boost.Geometry requires that your Point type is adapted to the Point Concept described here:

http://www.boost.org/doc/libs/1_54_0/libs/geometry/doc/html/geometry/reference/concepts/concept_point.html

Your derived type myPoint must also be adapted because it's a different type than your base type, model::pointer<>. The reason for this is that the library allows to adapt legacy classes and use them as Geometries without the need for modification.

To adapt it you must either use one of the registration macros or specialize all required traits by yourself. Besides the exmaple mentioned in the comment, see those:

http://www.boost.org/doc/libs/1_54_0/libs/geometry/doc/html/geometry/examples.html

In the second one the Point type is adapted by manual specialization of all required traits, which is the most flexible approach. In your case this would look like this:

namespace boost { namespace geometry { namespace traits {

template <typename C, std::size_t D, typename S>
struct tag< myPoint<C, D, S> >
{
    typedef point_tag type;
};
template <typename C, std::size_t D, typename S>
struct coordinate_type< myPoint<C, D, S> >
{
    typedef C type;
};
template <typename C, std::size_t D, typename S>
struct coordinate_system< myPoint<C, D, S> >
{
    typedef S type;
};
template <typename C, std::size_t D, typename S>
struct dimension< myPoint<C, D, S> >
{
    static const std::size_t value = D;
};
template <typename C, std::size_t D, typename S, std::size_t I>
struct access<myPoint<C, D, S>, I>
{
    static inline C get(myPoint<C, D, S> const& p)
    {
        return p.template get<I>();
    }

    static inline void set(myPoint<C, D, S> & p, C const& v)
    {
        p.template set<I>(v);
    }
};

}}}

Just paste it after your Point definition and you're done.



来源:https://stackoverflow.com/questions/18061728/how-to-inherit-from-boostgeometrymodelpoint

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!