+
+ inline double s_calcLineLength( const GVOShipRoute::Line & line )
+ {
+ double length = 0.0;
+
+ for ( auto it = line.begin(); it != line.end(); ++it ) {
+ auto p1 = *it;
+ if ( std::next(it) == line.end() ) {
+ break;
+ }
+ auto p2 = *std::next( it );
+ auto vector = GVOVector( s_denormalizedPoint( p1 ), s_denormalizedPoint( p2 ) );
+ length += vector.length();
+ }
+ return length;
+ }
+}
+
+
+std::ostream & operator << (std::ostream& os, GVOShipRoute& shipRoute)
+{
+ _ASSERT( os.good() );
+ if ( !os.good() ) {
+ throw std::runtime_error( "output stream error." );
+ }
+
+ ChunkHeader header;
+ header.lineCount = shipRoute.getLines().size();
+ os.write( reinterpret_cast<const char *>(&header), sizeof(header) );
+
+ for ( const auto & line : shipRoute.getLines() ) {
+ const size_t count = line.size();
+ os.write( reinterpret_cast<const char *>(&count), sizeof(count) );
+ if ( !line.empty() ) {
+ os.write( reinterpret_cast<const char *>(&line[0]), sizeof(line[0]) * line.size() );
+ }
+ }
+
+ _ASSERT( os.good() );
+ return os;
+}
+
+
+std::istream & operator >> (std::istream& is, GVOShipRoute& shipRoute)
+{
+ _ASSERT( is.good() );
+ if ( !is.good() ) {
+ throw std::runtime_error( "input stream error." );
+ }
+
+ ChunkHeader header;
+ is.read( reinterpret_cast<char *>(&header), sizeof(header) );
+
+ if ( header.version != ChunkHeader::k_Version1 ) {
+ throw std::runtime_error( "unknown file version." );
+ }
+
+ shipRoute.setFavorite( true );
+ shipRoute.setFix( true );
+
+ for ( size_t k = 0; k < header.lineCount; ++k ) {
+ size_t pointCount = 0;
+ is.read( reinterpret_cast<char *>(&pointCount), sizeof(pointCount) );
+ if ( 0 < pointCount ) {
+ GVOShipRoute::Line tmp( pointCount );
+ is.read( reinterpret_cast<char *>(&tmp[0]), sizeof(tmp[0]) * tmp.size() );
+ if ( !shipRoute.getLines().empty() && !tmp.empty() ) {
+ auto p1 = shipRoute.getLines().back().back();
+ auto p2 = tmp.front();
+ shipRoute.m_length += GVOVector( s_denormalizedPoint( p1 ), s_denormalizedPoint( p2 ) ).length();
+ }
+ shipRoute.m_length += s_calcLineLength( tmp );
+ shipRoute.addLine( std::move( tmp ) );
+ }
+ }
+
+ _ASSERT( is.good() );
+ return is;