Search code examples
boostboost-serializationboost-geometry

Boost Polygon Serialization


I am using boost geometry in my project, and I need to serialize polygons. I have been using boost serialization without problems for many boost data types, but boost geometry seems that currently does not support serialization, as I cannot find any header inside serialization folder.

Is there any well known method to achieve this?

Thanks.

EDIT: Binary Serialization Example in: Boost Polygon Serialization: Ring


Solution

  • I agree, it is weird that Boost.Geometry does not support Boost.Serialization. Probably it is hard to support all possible combinations of template parameters, or maybe they did not bother as WKT is already provided.

    At least in the case of "default" container types it is trivial to add such functionality. The code below implements it and is fully functional.

    Below I assume you use a custom class (QPoint from Qt) as your point class. Code for other point types will be almost identical to mine.

    First, you add a serialization for the Point class:

    #include <QPoint>
    
    #include <boost/geometry/geometry.hpp>
    #include <boost/geometry/geometries/register/point.hpp>
    
    BOOST_GEOMETRY_REGISTER_POINT_2D_GET_SET(QPoint, int, cs::cartesian, x, y, setX, setY);
    typedef QPoint MyPoint;
    
    
    namespace  boost {
    namespace serialization {
    
    template<class Archive>
    void serialize(Archive & ar, MyPoint& pt, const unsigned int version) {
        ar &  boost::serialization::make_nvp("x", pt.rx() );
        ar &  boost::serialization::make_nvp("y", pt.ry() );
    }
    } //namespace serialization
    } //namespace boost
    

    Next you add serialization for Ring and Polygon. Here I use the fact that Ring and Polygon are essentially std::vector(s) of points and rings respectively and the serialization for std::vector is built-in in Boost.Serialization.

    #include <boost/serialization/vector.hpp>
    #include <boost/geometry/geometries/polygon.hpp>
    #include <boost/geometry/geometries/ring.hpp>
    
    //change template flags as you are pleased but ring and polygon has to be
    //in correspondence w.r.t. to "closed" and "clockwise" policies
    typedef boost::geometry::model::ring<MyPoint, false, true> MyRing;
    typedef boost::geometry::model::polygon<MyPoint, false, true> MyPolygon; 
    
    namespace  boost {
    namespace serialization {
    
    //Default ring<MyPoint> simply inherits from std::vector<MyPoint>, 
    //its serialization is trivial and no implementation is needed. 
    
    //Default polygon<MyPoint> gives direct access to outer ring and the container of inner rings
    template<class Archive>
    void serialize(Archive & ar, MyPolygon& poly, const unsigned int version) {
        ar &  boost::serialization::make_nvp("outer", poly.outer());
        ar &  boost::serialization::make_nvp("inners", poly.inners());
    }
    
    
    } //namespace serialization
    } //namespace boost
    

    That's it, you are done, now you can use MyPolygon with Boost.Serialize as any other class:

    #include <boost/archive/xml_iarchive.hpp>
    #include <boost/archive/xml_oarchive.hpp>
    
    void foo_out(std::ostream & oss, const MyPolygon & poly)
    {
        boost::archive::xml_oarchive oa(oss);
        oa & BOOST_SERIALIZATION_NVP(poly);
    }
    
    void foo_in(std::istream & iss, MyPolygon & poly)
    {
        boost::archive::xml_iarchive ia(iss);
        ia & BOOST_SERIALIZATION_NVP(poly);
    }
    

    Enjoy!