#pragma once #include "geometry_coding.hpp" #include "tesselator_decl.hpp" #include "point_to_int64.hpp" #include "coding_params.hpp" #include "../geometry/point2d.hpp" #include "../coding/reader.hpp" #include "../coding/writer.hpp" #include "../coding/varint.hpp" #include "../std/algorithm.hpp" #include "../std/bind.hpp" #include "../base/buffer_vector.hpp" #include "../base/stl_add.hpp" namespace serial { template inline void WriteVarUintArray(TCont const & v, TSink & sink) { for (size_t i = 0; i != v.size(); ++i) WriteVarUint(sink, v[i]); } /// @name Encode and Decode function types. //@{ typedef void (*EncodeFunT)( geo_coding::InPointsT const &, m2::PointU const &, m2::PointU const &, geo_coding::OutDeltasT &); typedef void (*DecodeFunT)( geo_coding::InDeltasT const &, m2::PointU const &, m2::PointU const &, geo_coding::OutPointsT &); //@} typedef buffer_vector DeltasT; typedef buffer_vector OutPointsT; void Encode(EncodeFunT fn, vector const & points, CodingParams const & params, DeltasT & deltas); /// @name Overloads for different out container types. //@{ void Decode(DecodeFunT fn, DeltasT const & deltas, CodingParams const & params, OutPointsT & points, size_t reserveF = 1); void Decode(DecodeFunT fn, DeltasT const & deltas, CodingParams const & params, vector & points, size_t reserveF = 1); //@} template void SavePoint(TSink & sink, m2::PointD const & pt, CodingParams const & cp) { WriteVarUint(sink, EncodeDelta(PointD2PointU(pt.x, pt.y, cp.GetCoordBits()), cp.GetBasePoint())); } template m2::PointD LoadPoint(TSource & src, CodingParams const & cp) { CoordPointT const c = PointU2PointD( DecodeDelta(ReadVarUint(src), cp.GetBasePoint()), cp.GetCoordBits()); return m2::PointD(c.first, c.second); } template void SaveInner(EncodeFunT fn, vector const & points, CodingParams const & params, TSink & sink) { DeltasT deltas; Encode(fn, points, params, deltas); WriteVarUintArray(deltas, sink); } template void WriteBufferToSink(vector const & buffer, TSink & sink) { uint32_t const count = static_cast(buffer.size()); WriteVarUint(sink, count); sink.Write(&buffer[0], count); } template void SaveOuter(EncodeFunT fn, vector const & points, CodingParams const & params, TSink & sink) { DeltasT deltas; Encode(fn, points, params, deltas); vector buffer; MemWriter > writer(buffer); WriteVarUintArray(deltas, writer); WriteBufferToSink(buffer, sink); } void const * LoadInner(DecodeFunT fn, void const * pBeg, size_t count, CodingParams const & params, OutPointsT & points); template void LoadOuter(DecodeFunT fn, TSource & src, CodingParams const & params, TPoints & points, size_t reserveF = 1) { uint32_t const count = ReadVarUint(src); vector buffer(count); char * p = &buffer[0]; src.Read(p, count); DeltasT deltas; deltas.reserve(count / 2); ReadVarUint64Array(p, p + count, MakeBackInsertFunctor(deltas)); Decode(fn, deltas, params, points, reserveF); } /// @name Paths. //@{ template void SaveInnerPath(vector const & points, CodingParams const & params, TSink & sink) { SaveInner(&geo_coding::EncodePolyline, points, params, sink); } template void SaveOuterPath(vector const & points, CodingParams const & params, TSink & sink) { SaveOuter(&geo_coding::EncodePolyline, points, params, sink); } inline void const * LoadInnerPath(void const * pBeg, size_t count, CodingParams const & params, OutPointsT & points) { return LoadInner(&geo_coding::DecodePolyline, pBeg, count, params, points); } template void LoadOuterPath(TSource & src, CodingParams const & params, TPoints & points) { LoadOuter(&geo_coding::DecodePolyline, src, params, points); } //@} /// @name Triangles. //@{ template void SaveInnerTriangles(vector const & points, CodingParams const & params, TSink & sink) { SaveInner(&geo_coding::EncodeTriangleStrip, points, params, sink); } inline void const * LoadInnerTriangles(void const * pBeg, size_t count, CodingParams const & params, OutPointsT & points) { return LoadInner(&geo_coding::DecodeTriangleStrip, pBeg, count, params, points); } class TrianglesChainSaver { typedef m2::PointU PointT; typedef tesselator::Edge EdgeT; typedef vector BufferT; PointT m_base, m_max; list m_buffers; public: explicit TrianglesChainSaver(CodingParams const & params); PointT GetBasePoint() const { return m_base; } PointT GetMaxPoint() const { return m_max; } void operator() (PointT arr[3], vector edges); size_t GetBufferSize() const { size_t sz = 0; for (list::const_iterator i = m_buffers.begin(); i != m_buffers.end(); ++i) sz += i->size(); return sz; } template void Save(TSink & sink) { // assume that 2 byte is enough for triangles count size_t const count = m_buffers.size(); CHECK_LESS_OR_EQUAL(count, 0x3FFF, ()); WriteVarUint(sink, static_cast(count)); for_each(m_buffers.begin(), m_buffers.end(), bind(&WriteBufferToSink, _1, ref(sink))); } }; void DecodeTriangles(geo_coding::InDeltasT const & deltas, m2::PointU const & basePoint, m2::PointU const & maxPoint, geo_coding::OutPointsT & triangles); template void LoadOuterTriangles(TSource & src, CodingParams const & params, OutPointsT & triangles) { int const count = ReadVarUint(src); for (int i = 0; i < count; ++i) LoadOuter(&DecodeTriangles, src, params, triangles, 3); } //@} }