c++boostboost-geometry

How to assign boost geometry derived point type correctly?


In my application I want to use a boost geometry point derived type to carry additional data but fail to do so:

#include <boost/geometry.hpp>
#include <boost/geometry/geometries/geometries.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
namespace bg = boost::geometry;

using point_t = bg::model::d2::point_xy<double>;

struct taggedPoint_t : point_t
{
    taggedPoint_t(void* data) : mData(data) {}
    void* mData;
};

int main()
{
    point_t p1;
    bg::assign_values(p1, 1.0, 2.0); // OK

    taggedPoint_t p2(nullptr);
    bg::assign_values(p2, 2.0, 3.0); // Fails
}

Can someone shed some light on it how to do it correctly? I also tried to register the point type:

BOOST_GEOMETRY_REGISTER_POINT_2D(taggedPoint_t, double, cs::cartesian, x, y)

But that also failed.

Sample code on Coliru


Solution

  • Indeed, the right way to adapt your point is to ignore it derived from a known geometry type and just adapt the public interface:

    #include <boost/geometry/geometries/register/point.hpp>
    BOOST_GEOMETRY_REGISTER_POINT_2D_GET_SET(taggedPoint_t, double, bg::cs::cartesian, x, y, x, y)
    

    This works: Live On Coliru

    Of course you can also supply all the required traits and generalize:

    template <typename Base> struct taggedPoint : Base {
        using base_type = Base;
    
        taggedPoint(void* data) : mData(data) {}
        void* mData;
    };
    

    Which you can them make "inherit" all the traits explicitly:

    namespace boost::geometry::traits {
        template <typename B> struct tag<taggedPoint<B>>               : tag<B>               {};
        template <typename B> struct dimension<taggedPoint<B>>         : dimension<B>         {};
        template <typename B> struct coordinate_type<taggedPoint<B>>   : coordinate_type<B>   {};
        template <typename B> struct coordinate_system<taggedPoint<B>> : coordinate_system<B> {};
        template <typename B> struct access<taggedPoint<B>, 0> : access<B, 0> {};
        template <typename B> struct access<taggedPoint<B>, 1> : access<B, 1> {};
        template <typename B> struct access<taggedPoint<B>, 2> : access<B, 2> {};
    } // namespace boost::geometry::traits
    

    Now you can use it without further registration: Live On Coliru

    Caveat

    ID field intermittently lost in custom point class - your "rich point" data will usually be lost when used with standard Boost Geometry algorithms. See Adam's answer for hints on how to maybe use custom strategies (that's too advanced for me)