2014-01-29 29 views
4

根據此相關問題(Boost Polygon Serialization)。我正在嘗試使用Boost序列化多邊形。我現在的問題是,我試圖編譯使用自定義的X,Y,點的多邊形的例子,但是編譯器在編譯的時候拋出這個錯誤:Boost多邊形序列化:環

error: 'class boost::geometry::model::ring<boost::geometry::model::d2::point_xy<double> >' has no member named 'serialize' 

好像沒有定義任何函數序列化戒指。由於一個環從std :: vector擴展而來,並且如相關問題所述,所以沒有必要爲它的序列化定義一個方法。但編譯器抱怨。

這裏我有關定義多邊形一個完整的例子,它的序列化:

#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); 
} 

如何得到這個工作任何想法?

編輯:關於多邊形系列化全功能代碼

#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(); 
} 

回答

6

即使存在std:vector<T>爲serialzation偏特,這並不意味着它會爲子類的工作,所以你必須增加一個序列化方法爲ring

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

那麼執行什麼?由於geometry未構建爲序列化,因此無法訪問對序列化有用的類型(例如,爲容器ring繼承選擇正確的默認實現),因此您可以以某種方式強制執行此操作。例如,這似乎工作:

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); 
} 

您也可以嘗試寫一些基礎類的序列化的呼叫:

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)); 
} 

但同樣的,問題是,你應該能夠訪問繼承類從ring。實際上,它中的ring的定義,如base_type,但它對這個類是私有的。如果它是公開的,你可以使用ring::base_type作爲序列化的參數(而不是上面的裸露的std::vector<point>)來編寫不那麼糟糕的代碼。

也許知道序列化庫的內部,你可以「綁定」序列化機制,這樣兩個調用就不是必需的,專門爲ring類本身專門化了一些局部特化,但是我懷疑這是否便攜。

+0

很有洞察力。我喜歡你最後的想法。完全可能值得向Boost Geometry提供建議的那種東西 – sehe

+0

完美的答案!謝謝!我和你的解決方案非常接近,但是我使用「ar&static_cast ...」序列化了這個環,而不是調用序列化方法......它編譯的序列化正常,但是沒有使用反常序錯誤的反序列化代碼進行編譯 –

+0

The與我的方法相同的問題,當調用序列化與靜態轉換時,序列化的代碼似乎工作,但添加反序列化時,它會拋出另一個錯誤,如'basic_binary_iprimiteve.hpp:88:9:錯誤:無效轉換'const void * 'to'void *' –

0

正如@Diego Sevilla指出的那樣,主要障礙在於base_type在ring<...>中聲明爲private。由於繼承事實上是公開的,這有點奇怪。

不過,一個可以稍微用幾何模型::詳細定義::環

namespace boost { 
namespace serialization{ 
    template<class Archive, //other template params are from model::ring 
      typename Point, 
      bool ClockWise , bool Closed , 
      template<typename, typename> class Container, //= std::vector, 
      template<typename> class Allocator// = std::allocator 
      > 
    void serialize(Archive & ar, 
        geometry::model::ring<Point, ClockWise, 
             Closed, Container, Allocator> & rng, 
        const unsigned int version) 
    { 
     typedef Container<Point, Allocator<Point> > ring_base_type; 
     ring_base_type & contour = rng; 
     ar & BOOST_SERIALIZATION_NVP(contour); 
    } 
} //namespace serialization 
} //namespace boost 

應該正常工作升壓::幾何模型::幾乎所有變種概括他的解決方案::環。

+0

我明白了,但你實際上將定義與'ring'的* exact *實現聯繫起來。它可能在未來發生變化。 –

+0

同意。至於未來,還有兩種選擇。首先,可以更改序列號以匹配類「環<...>」。其次,可以使用基於ring的__concept__的更通用的序列化;這意味着必須保存和加載一個通用的隨機訪問範圍點。不過,效率會稍差。 –