问题
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