Boost Polygon Serialization: Ring

boost, boost-geometry, boost-serialization, c++, serialization

Solution

Even when partial specialization for serialzation exists for `std:vector<T>` this does not imply it will work for subclasses, so you have to add a serialization method for `ring`:

template<class Archive>
inline void serialize(Archive & ar, ring &t, const unsigned int file_version)
{
    // Impl
}

So what's in the implementation? As `geometry` is not built to be serialized, you cannot access types that would be useful for the serialization (for example, to select the correct default implementation for the container `ring` inherits), so you can force this somehow. For example, this seems to work:

template<class Archive>
inline void serialize(Archive & ar, ring &t, const unsigned int file_version)
{
     std::cout << "Ring: Serializing a ring" << std::endl;
     serialize(ar, static_cast< std::vector<point>& >(t), file_version);
}

You can also try to write some base class serialization call:

template<class Archive>
inline void serialize(Archive & ar, ring &t, const unsigned int file_version)
{
     std::cout << "Ring: Serializing a ring" << std::endl;
     ar & boost::serialization::make_nvp( "Base",
              boost::serialization::base_object<std::vector<point> >(t));
}

but again, the problem is that you should be able to access that inherited class from within `ring`. In fact, it is in the definition of `ring`, as `base_type`, but it is private to the class. If it was public, you could write the not so bad code using `ring::base_type` as a parameter for the serialization (instead of the bare `std::vector<point>` above).

Maybe knowing the inners of the serialization library you can "tie" the serialization machinery so that two calls are not neccessary, specializing some partial specialization for the `ring` class itself, but I doubt this would be portable.

Problem

According to this related question (Boost Polygon Serialization). I am trying to serialize polygons with Boost. The problem I have now is that I am trying to compile an example using polygons of custom X, Y, points, but the compiler throws this error at compile time: ``` error: 'class boost::geometry::model::ring<boost::geometry::model::d2::point_xy<double> >' has no member named 'serialize' ``` Like there is no defined any function to serialize a ring. Since a Ring extends from std::vector, and as stated in the related question, it is not necessary to define a method for its serialization. But the compiler complains. Here I have a full example about defining polygons, and its serialization: ``` #include <fstream> #include <boost/serialization/vector.hpp> #include <boost/serialization/nvp.hpp> #include <boost/serialization/version.hpp> #include <boost/serialization/tracking.hpp> #include <boost/geometry/geometry.hpp> #include <boost/geometry/geometries/polygon.hpp> #include <boost/geometry/geometries/point_xy.hpp> #include <boost/geometry/io/wkt/wkt.hpp> #include <boost/geometry/multi/geometries/multi_polygon.hpp> #include <boost/geometry/geometries/ring.hpp> #include <boost/archive/xml_iarchive.hpp> #include <boost/archive/xml_oarchive.hpp> typedef boost::geometry::model::d2::point_xy< double > point; typedef boost::geometry::model::ring< point > ring; typedef boost::geometry::model::polygon< point > polygon; namespace boost{ namespace serialization{ template<class Archive> inline void serialize(Archive & ar, point &point, const unsigned int file_version) { std::cout << "Point: Serializing point" << std::endl; ar & boost::serialization::make_nvp("x", point.x()); ar & boost::serialization::make_nvp("y", point.y()); } template<class Archive> inline void serialize(Archive & ar, polygon &t, const unsigned int file_version) { std::cout << "Polygon: Serializing outer ring" << std::endl; ar & boost::serialization::make_nvp("outer", t.outer()); std::cout << "Polygon: Serializing inner rings" << std::endl; ar & boost::serialization::make_nvp("inners", t.inners()); } } } using namespace boost::geometry; using namespace boost::archive; using namespace std; int main() { polygon poly; append(poly, make<point>(0.0, 0.0)); append(poly, make<point>(5.0, 5.0)); append(poly, make<point>(5.0, 0.0)); correct(poly); ofstream ofs("polygon.xml"); xml_oarchive oa(ofs); oa << BOOST_SERIALIZATION_NVP(poly); } ``` Any idea about how to get this working? EDIT: Fully functional code about polygon serialization ``` #include <fstream> #include <vector> #include <boost/serialization/vector.hpp> #include <boost/serialization/nvp.hpp> #include <boost/serialization/version.hpp> #include <boost/serialization/tracking.hpp> #include <boost/foreach.hpp> #include <boost/geometry/geometry.hpp> #include <boost/geometry/geometries/polygon.hpp> #include <boost/geometry/geometries/point_xy.hpp> #include <boost/geometry/geometries/ring.hpp> #include <boost/archive/binary_oarchive.hpp> #include <boost/archive/binary_iarchive.hpp> typedef boost::geometry::model::d2::point_xy< double > point; typedef boost::geometry::model::ring< point > ring; typedef boost::geometry::model::polygon< point > polygon; namespace boost{ namespace serialization{ template<class Archive> inline void serialize(Archive & ar, point &point, const unsigned int file_version) { std::cout << "Point: Serializing point" << std::endl; ar & const_cast<double &>(point.x()); ar & const_cast<double &>(point.y()); } template<class Archive> inline void serialize(Archive & ar, ring &ring, const unsigned int file_version) { std::cout << "Ring: Serializing ring" << std::endl; ar & static_cast<std::vector<point>& >(ring); } template<class Archive> inline void serialize(Archive & ar, polygon &t, const unsigned int file_version) { std::cout << "Polygon: Serializing outer ring" << std::endl; ar & t.outer(); std::cout << "Polygon: Serializing inner rings" << std::endl; ar & t.inners(); } } } using namespace boost::geometry; using namespace boost::archive; using namespace std; int main() { polygon poly; append(poly, make<point>(0.0, 0.0)); append(poly, make<point>(5.0, 5.0)); append(poly, make<point>(5.0, 0.0)); correct(poly); BOOST_FOREACH(point& p, poly.outer()) { std::cout << "point " << p.x() << "," << p.y() << std::endl; } ofstream ofs("polygon.dat"); binary_oarchive oa(ofs); oa << poly; ofs.close(); polygon polyFromFile; ifstream ifs("polygon.dat"); binary_iarchive ia(ifs); ia >> polyFromFile; BOOST_FOREACH(point& p, polyFromFile.outer()) { std::cout << "point " << p.x() << "," << p.y() << std::endl; } ifs.close(); } ```

Original source

Related problems