From 5b533632a61ffe61840de3e9fea9d21ed1409f41 Mon Sep 17 00:00:00 2001 From: vng Date: Tue, 1 Feb 2011 22:48:50 +0200 Subject: [PATCH] Add parallelogramm prediction for strips serialization. --- indexer/feature.cpp | 70 +++++--------------- indexer/feature.hpp | 1 - indexer/geometry_coding.cpp | 100 +++++++++++++++++++++++------ indexer/geometry_coding.hpp | 22 ++++--- indexer/geometry_serialization.cpp | 12 ++-- indexer/geometry_serialization.hpp | 63 +++++++++++++++--- 6 files changed, 169 insertions(+), 99 deletions(-) diff --git a/indexer/feature.cpp b/indexer/feature.cpp index 6d05895b9e..511a621bda 100644 --- a/indexer/feature.cpp +++ b/indexer/feature.cpp @@ -355,37 +355,6 @@ namespace m_pos += count; } }; - - /// @name Rearrange strips for optimal save size. - /// Save in this order: 0, 2, 4, ..., 15, 13, ..., 1 - //@{ - void RearrangeStripsSave(vector const & src, vector & dest) - { - size_t const count = src.size(); - dest.resize(count); - for (size_t i = 0; i < count; ++i) - { - if (i & 1) - dest[count-1 - (i/2)] = src[i]; - else - dest[i/2] = src[i]; - } - } - - void RearrangeStripsLoad( buffer_vector const & src, - buffer_vector & dest) - { - size_t const count = src.size(); - dest.resize(count); - for (size_t i = 0; i < count; ++i) - { - if (i & 1) - dest[i] = src[count-1 - (i/2)]; - else - dest[i] = src[i/2]; - } - } - //@} } void FeatureBuilder2::Serialize(buffers_holder_t & data, int64_t base) @@ -451,11 +420,7 @@ void FeatureBuilder2::Serialize(buffers_holder_t & data, int64_t base) if (m_bArea) { if (trgCount > 0) - { - vector toSave; - RearrangeStripsSave(data.m_innerTrg, toSave); - feature::SavePointsSimple(toSave, base, sink); - } + serial::SaveInnerTriangles(data.m_innerTrg, base, sink); else { // offsets was pushed from high scale index to low @@ -813,9 +778,8 @@ void FeatureType::ParseHeader2() const char const * start = static_cast(src.Ptr()); - points_t toLoad, points; - ReadInnerPoints(src, toLoad, trgCount); - RearrangeStripsLoad(toLoad, points); + points_t points; + src = ArrayByteSource(serial::LoadInnerTriangles(src.Ptr(), trgCount, m_base, points)); m_InnerStats.m_Strips = static_cast(src.Ptr()) - start; @@ -894,19 +858,23 @@ uint32_t FeatureType::ParseTriangles(int scale) const ParseHeader2(); uint32_t sz = 0; - if (m_Triangles.empty() && Header() & HEADER_IS_AREA) + if (Header() & HEADER_IS_AREA) { - uint32_t const ind = GetScaleIndex(scale, m_trgOffsets); - if (ind != -1) + if (m_Triangles.empty()) { - ReaderSource src( - m_cont->GetReader(feature::GetTagForIndex(TRIANGLE_FILE_TAG, ind))); - src.Skip(m_trgOffsets[ind]); - feature::LoadTriangles(m_Triangles, m_base, src); + uint32_t const ind = GetScaleIndex(scale, m_trgOffsets); + if (ind != -1) + { + ReaderSource src( + m_cont->GetReader(feature::GetTagForIndex(TRIANGLE_FILE_TAG, ind))); + src.Skip(m_trgOffsets[ind]); + feature::LoadTriangles(m_Triangles, m_base, src); - CalcRect(m_Triangles, m_LimitRect); - sz = static_cast(src.Pos() - m_trgOffsets[ind]); + sz = static_cast(src.Pos() - m_trgOffsets[ind]); + } } + + CalcRect(m_Triangles, m_LimitRect); } m_bTrianglesParsed = true; @@ -926,12 +894,6 @@ void FeatureType::ReadOffsets(ArrayByteSource & src, uint8_t mask, offsets_t & o } } -void FeatureType::ReadInnerPoints(ArrayByteSource & src, points_t & points, uint8_t count) const -{ - src = ArrayByteSource(feature::LoadPointsSimple(src.Ptr(), count, m_base, points)); - CalcRect(points, m_LimitRect); -} - void FeatureType::ParseAll(int scale) const { if (!m_bPointsParsed) diff --git a/indexer/feature.hpp b/indexer/feature.hpp index c598b73b7e..4b056abd52 100644 --- a/indexer/feature.hpp +++ b/indexer/feature.hpp @@ -475,7 +475,6 @@ private: typedef array offsets_t; // should be synchronized with ARRAY_SIZE(g_arrScales) static void ReadOffsets(ArrayByteSource & src, uint8_t mask, offsets_t & offsets); - void ReadInnerPoints(ArrayByteSource & src, points_t & points, uint8_t count) const; static int GetScaleIndex(int scale); static int GetScaleIndex(int scale, offsets_t const & offset); diff --git a/indexer/geometry_coding.cpp b/indexer/geometry_coding.cpp index d0a8a7e701..e8eb674ef2 100644 --- a/indexer/geometry_coding.cpp +++ b/indexer/geometry_coding.cpp @@ -77,11 +77,11 @@ void EncodePolylinePrev1(InPointsT const & points, m2::PointU const & /*maxPoint*/, DeltasT & deltas) { - deltas.reserve(points.size()); - if (points.size() > 0) + size_t const count = points.size(); + if (count > 0) { deltas.push_back(EncodeDelta(points[0], basePoint)); - for (size_t i = 1; i < points.size(); ++i) + for (size_t i = 1; i < count; ++i) deltas.push_back(EncodeDelta(points[i], points[i-1])); } @@ -93,10 +93,11 @@ void DecodePolylinePrev1(DeltasT const & deltas, m2::PointU const & /*maxPoint*/, OutPointsT & points) { - if (deltas.size() > 0) + size_t const count = deltas.size(); + if (count > 0) { points.push_back(DecodeDelta(deltas[0], basePoint)); - for (size_t i = 1; i < deltas.size(); ++i) + for (size_t i = 1; i < count; ++i) points.push_back(DecodeDelta(deltas[i], points.back())); } } @@ -106,13 +107,14 @@ void EncodePolylinePrev2(InPointsT const & points, m2::PointU const & maxPoint, DeltasT & deltas) { - if (points.size() > 0) + size_t const count = points.size(); + if (count > 0) { deltas.push_back(EncodeDelta(points[0], basePoint)); - if (points.size() > 1) + if (count > 1) { deltas.push_back(EncodeDelta(points[1], points[0])); - for (size_t i = 2; i < points.size(); ++i) + for (size_t i = 2; i < count; ++i) deltas.push_back(EncodeDelta(points[i], PredictPointInPolyline(maxPoint, points[i-1], points[i-2]))); } @@ -126,13 +128,14 @@ void DecodePolylinePrev2(DeltasT const & deltas, m2::PointU const & maxPoint, OutPointsT & points) { - if (deltas.size() > 0) + size_t const count = deltas.size(); + if (count > 0) { points.push_back(DecodeDelta(deltas[0], basePoint)); - if (deltas.size() > 1) + if (count > 1) { points.push_back(DecodeDelta(deltas[1], points.back())); - for (size_t i = 2; i < deltas.size(); ++i) + for (size_t i = 2; i < count; ++i) { size_t const n = points.size(); points.push_back(DecodeDelta(deltas[i], @@ -150,17 +153,18 @@ void EncodePolylinePrev3(InPointsT const & points, ASSERT_LESS_OR_EQUAL(basePoint.x, maxPoint.x, (basePoint, maxPoint)); ASSERT_LESS_OR_EQUAL(basePoint.y, maxPoint.y, (basePoint, maxPoint)); - if (points.size() > 0) + size_t const count = points.size(); + if (count > 0) { deltas.push_back(EncodeDelta(points[0], basePoint)); - if (points.size() > 1) + if (count > 1) { deltas.push_back(EncodeDelta(points[1], points[0])); - if (points.size() > 2) + if (count > 2) { m2::PointU const prediction = PredictPointInPolyline(maxPoint, points[1], points[0]); deltas.push_back(EncodeDelta(points[2], prediction)); - for (size_t i = 3; i < points.size(); ++i) + for (size_t i = 3; i < count; ++i) { m2::PointU const prediction = PredictPointInPolyline(maxPoint, points[i-1], points[i-2], points[i-3]); @@ -181,18 +185,19 @@ void DecodePolylinePrev3(DeltasT const & deltas, ASSERT_LESS_OR_EQUAL(basePoint.x, maxPoint.x, (basePoint, maxPoint)); ASSERT_LESS_OR_EQUAL(basePoint.y, maxPoint.y, (basePoint, maxPoint)); - if (deltas.size() > 0) + size_t const count = deltas.size(); + if (count> 0) { points.push_back(DecodeDelta(deltas[0], basePoint)); - if (deltas.size() > 1) + if (count > 1) { m2::PointU const pt0 = points.back(); points.push_back(DecodeDelta(deltas[1], pt0)); - if (deltas.size() > 2) + if (count > 2) { points.push_back(DecodeDelta(deltas[2], PredictPointInPolyline(maxPoint, points.back(), pt0))); - for (size_t i = 3; i < deltas.size(); ++i) + for (size_t i = 3; i < count; ++i) { size_t const n = points.size(); m2::PointU const prediction = @@ -204,4 +209,61 @@ void DecodePolylinePrev3(DeltasT const & deltas, } } + +m2::PointU PredictPointInTriangle(m2::PointU const & maxPoint, + m2::PointU const & p1, + m2::PointU const & p2, + m2::PointU const & p3) +{ + // parallelogramm prediction + return ClampPoint(maxPoint, p2 + p3 - p1); +} + +void EncodeTriangleStrip(InPointsT const & points, + m2::PointU const & basePoint, + m2::PointU const & maxPoint, + DeltasT & deltas) +{ + size_t const count = points.size(); + if (count > 0) + { + ASSERT_GREATER(count, 2, ()); + + deltas.push_back(EncodeDelta(points[0], basePoint)); + deltas.push_back(EncodeDelta(points[1], points[0])); + deltas.push_back(EncodeDelta(points[2], points[1])); + + for (size_t i = 3; i < count; ++i) + { + m2::PointU const prediction = + PredictPointInTriangle(maxPoint, points[i-1], points[i-2], points[i-3]); + deltas.push_back(EncodeDelta(points[i], prediction)); + } + } +} + +void DecodeTriangleStrip(DeltasT const & deltas, + m2::PointU const & basePoint, + m2::PointU const & maxPoint, + OutPointsT & points) +{ + size_t const count = deltas.size(); + if (count > 0) + { + ASSERT_GREATER(count, 2, ()); + + points.push_back(DecodeDelta(deltas[0], basePoint)); + points.push_back(DecodeDelta(deltas[1], points.back())); + points.push_back(DecodeDelta(deltas[2], points.back())); + + for (size_t i = 3; i < count; ++i) + { + size_t const n = points.size(); + m2::PointU const prediction = + PredictPointInTriangle(maxPoint, points[n-1], points[n-2], points[n-3]); + points.push_back(DecodeDelta(deltas[i], prediction)); + } + } +} + } diff --git a/indexer/geometry_coding.hpp b/indexer/geometry_coding.hpp index 746488388a..373cd5199c 100644 --- a/indexer/geometry_coding.hpp +++ b/indexer/geometry_coding.hpp @@ -84,25 +84,27 @@ inline void DecodePolyline(DeltasT const & deltas, DecodePolylinePrev2(deltas, basePoint, maxPoint, points); } -void EncodeTriangles(vector const & points, - vector > const & triangles, +typedef vector > TrianglesT; + +void EncodeTriangles(InPointsT const & points, + TrianglesT const & triangles, m2::PointU const & basePoint, m2::PointU const & maxPoint, - vector & serialOutput); + DeltasT & deltas); -void DecodeTriangles(char const * pBeg, char const * pEnd, +void DecodeTriangles(DeltasT const & deltas, m2::PointU const & basePoint, m2::PointU const & maxPoint, - vector & points, - vector > & triangles); + OutPointsT & points, + TrianglesT & triangles); -void EncodeTriangleStrip(vector const & points, +void EncodeTriangleStrip(InPointsT const & points, m2::PointU const & basePoint, m2::PointU const & maxPoint, - vector & serialOutput); + DeltasT & deltas); -void DecodeTriangleStrip(char const * pBeg, char const * pEnd, +void DecodeTriangleStrip(DeltasT const & deltas, m2::PointU const & basePoint, m2::PointU const & maxPoint, - vector & points); + OutPointsT & points); } diff --git a/indexer/geometry_serialization.cpp b/indexer/geometry_serialization.cpp index 63086a8776..6738417d76 100644 --- a/indexer/geometry_serialization.cpp +++ b/indexer/geometry_serialization.cpp @@ -35,35 +35,35 @@ namespace serial } } - void EncodePath(vector const & points, int64_t base, vector & deltas) + void Encode(EncodeFunT fn, vector const & points, int64_t base, vector & deltas) { vector upoints; upoints.reserve(points.size()); transform(points.begin(), points.end(), back_inserter(upoints), &pts::D2U); - geo_coding::EncodePolyline(upoints, pts::GetBasePoint(base), pts::GetMaxPoint(), deltas); + (*fn)(upoints, pts::GetBasePoint(base), pts::GetMaxPoint(), deltas); } - void DecodePath(vector const & deltas, int64_t base, OutPointsT & points) + void Decode(DecodeFunT fn, vector const & deltas, int64_t base, OutPointsT & points) { vector upoints; upoints.reserve(deltas.size()); - geo_coding::DecodePolyline(deltas, pts::GetBasePoint(base), pts::GetMaxPoint(), upoints); + (*fn)(deltas, pts::GetBasePoint(base), pts::GetMaxPoint(), upoints); points.reserve(upoints.size()); transform(upoints.begin(), upoints.end(), back_inserter(points), &pts::U2D); } - void const * LoadInnerPath(void const * pBeg, size_t count, int64_t base, OutPointsT & points) + void const * LoadInner(DecodeFunT fn, void const * pBeg, size_t count, int64_t base, OutPointsT & points) { vector deltas; deltas.reserve(count); void const * ret = ReadVarUint64Array(static_cast(pBeg), count, MakeBackInsertFunctor(deltas)); - DecodePath(deltas, base, points); + Decode(fn, deltas, base, points); return ret; } } diff --git a/indexer/geometry_serialization.hpp b/indexer/geometry_serialization.hpp index 974a3c1b9a..28608ddd89 100644 --- a/indexer/geometry_serialization.hpp +++ b/indexer/geometry_serialization.hpp @@ -1,5 +1,7 @@ #pragma once +#include "geometry_coding.hpp" + #include "../geometry/point2d.hpp" #include "../coding/writer.hpp" @@ -18,24 +20,27 @@ namespace serial WriteVarUint(sink, v[i]); } - void EncodePath(vector const & points, int64_t base, vector & deltas); + typedef void (*EncodeFunT)(vector const &, m2::PointU const &, m2::PointU const &, vector &); + typedef void (*DecodeFunT)(vector const &, m2::PointU const &, m2::PointU const &, vector &); + + void Encode(EncodeFunT fn, vector const & points, int64_t base, vector & deltas); typedef buffer_vector OutPointsT; - void DecodePath(vector const & deltas, int64_t base, OutPointsT & points); + void Decode(DecodeFunT fn, vector const & deltas, int64_t base, OutPointsT & points); template - void SaveInnerPath(vector const & points, int64_t base, TSink & sink) + void SaveInner(EncodeFunT fn, vector const & points, int64_t base, TSink & sink) { vector deltas; - EncodePath(points, base, deltas); + Encode(fn, points, base, deltas); WriteVarUintArray(deltas, sink); } template - void SaveOuterPath(vector const & points, int64_t base, TSink & sink) + void SaveOuter(EncodeFunT fn, vector const & points, int64_t base, TSink & sink) { vector deltas; - EncodePath(points, base, deltas); + Encode(fn, points, base, deltas); vector buffer; MemWriter > writer(buffer); @@ -46,10 +51,10 @@ namespace serial sink.Write(&buffer[0], count); } - void const * LoadInnerPath(void const * pBeg, size_t count, int64_t base, OutPointsT & points); + void const * LoadInner(DecodeFunT fn, void const * pBeg, size_t count, int64_t base, OutPointsT & points); template - void LoadOuterPath(TSource & src, int64_t base, OutPointsT & points) + void LoadOuter(DecodeFunT fn, TSource & src, int64_t base, OutPointsT & points) { uint32_t const count = ReadVarUint(src); vector buffer(count); @@ -60,6 +65,46 @@ namespace serial deltas.reserve(count / 2); ReadVarUint64Array(p, p + count, MakeBackInsertFunctor(deltas)); - DecodePath(deltas, base, points); + Decode(fn, deltas, base, points); } + + + /// @name Pathes. + //@{ + template + void SaveInnerPath(vector const & points, int64_t base, TSink & sink) + { + SaveInner(&geo_coding::EncodePolyline, points, base, sink); + } + template + void SaveOuterPath(vector const & points, int64_t base, TSink & sink) + { + SaveOuter(&geo_coding::EncodePolyline, points, base, sink); + } + + inline void const * LoadInnerPath(void const * pBeg, size_t count, int64_t base, OutPointsT & points) + { + return LoadInner(&geo_coding::DecodePolyline, pBeg, count, base, points); + } + + template + void LoadOuterPath(TSource & src, int64_t base, OutPointsT & points) + { + LoadOuter(&geo_coding::DecodePolyline, src, base, points); + } + //@} + + /// @name Triangles. + //@{ + template + void SaveInnerTriangles(vector const & points, int64_t base, TSink & sink) + { + SaveInner(&geo_coding::EncodeTriangleStrip, points, base, sink); + } + + inline void const * LoadInnerTriangles(void const * pBeg, size_t count, int64_t base, OutPointsT & points) + { + return LoadInner(&geo_coding::DecodeTriangleStrip, pBeg, count, base, points); + } + //@} }