[feature] Added Feature V1 version with free Header2 bits.

Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
This commit is contained in:
Viktor Govako
2025-06-25 22:04:39 -03:00
committed by Konstantin Pastbin
parent 588028c9eb
commit 550455a14a
5 changed files with 52 additions and 34 deletions

View File

@@ -11,16 +11,13 @@
#include "coding/byte_stream.hpp" #include "coding/byte_stream.hpp"
#include "coding/geometry_coding.hpp" #include "coding/geometry_coding.hpp"
#include "coding/read_write_utils.hpp" #include "coding/read_write_utils.hpp"
#include "coding/reader.hpp"
#include "geometry/region2d.hpp" #include "geometry/region2d.hpp"
#include "base/logging.hpp" #include "base/logging.hpp"
#include "base/math.hpp" #include "base/math.hpp"
#include "base/string_utils.hpp"
#include <algorithm> #include <algorithm>
#include <cstring>
#include <vector> #include <vector>
namespace feature namespace feature
@@ -630,7 +627,9 @@ void FeatureBuilder::SerializeForMwm(SupportingData & data, serial::GeometryCodi
PushBackByteSink<Buffer> sink(data.m_buffer); PushBackByteSink<Buffer> sink(data.m_buffer);
FeatureParams(m_params).Write(sink); FeatureParams(m_params).Write(sink);
if (m_params.GetGeomType() == GeomType::Point) GeomType const type = m_params.GetGeomType();
CHECK(type != GeomType::Undefined, ());
if (type == GeomType::Point)
{ {
serial::SavePoint(sink, m_center, params); serial::SavePoint(sink, m_center, params);
return; return;
@@ -640,26 +639,23 @@ void FeatureBuilder::SerializeForMwm(SupportingData & data, serial::GeometryCodi
uint8_t trgCount = base::asserted_cast<uint8_t>(data.m_innerTrg.size()); uint8_t trgCount = base::asserted_cast<uint8_t>(data.m_innerTrg.size());
if (trgCount > 0) if (trgCount > 0)
{ {
ASSERT_GREATER(trgCount, 2, ()); CHECK_GREATER(trgCount, 2, ());
trgCount -= 2; trgCount -= 2;
} }
GeomType const type = m_params.GetGeomType();
{ {
BitWriter<PushBackByteSink<Buffer>> bitSink(sink); BitWriter<PushBackByteSink<Buffer>> bitSink(sink);
if (type == GeomType::Line) if (type == GeomType::Line)
{ {
bitSink.Write(ptsCount, 4); bitSink.Write(ptsCount != 0 ? ptsCount : data.m_ptsMask, 4);
if (ptsCount == 0) bitSink.Write(ptsCount == 0 ? 1 : 0, 1);
bitSink.Write(data.m_ptsMask, 4);
} }
else if (type == GeomType::Area) else
{ {
bitSink.Write(trgCount, 4); CHECK_EQUAL(type, GeomType::Area, ());
if (trgCount == 0) bitSink.Write(trgCount != 0 ? trgCount : data.m_trgMask, 4);
bitSink.Write(data.m_trgMask, 4); bitSink.Write(trgCount == 0 ? 1 : 0, 1);
} }
} }
@@ -671,6 +667,7 @@ void FeatureBuilder::SerializeForMwm(SupportingData & data, serial::GeometryCodi
{ {
uint32_t v = data.m_ptsSimpMask; uint32_t v = data.m_ptsSimpMask;
int const count = (ptsCount - 2 + 3) / 4; int const count = (ptsCount - 2 + 3) / 4;
CHECK_LESS(count, 4, ());
for (int i = 0; i < count; ++i) for (int i = 0; i < count; ++i)
{ {
WriteToSink(sink, static_cast<uint8_t>(v)); WriteToSink(sink, static_cast<uint8_t>(v));
@@ -683,7 +680,7 @@ void FeatureBuilder::SerializeForMwm(SupportingData & data, serial::GeometryCodi
else else
{ {
auto const & poly = GetOuterGeometry(); auto const & poly = GetOuterGeometry();
ASSERT_GREATER(poly.size(), 2, ()); CHECK_GREATER(poly.size(), 2, ());
// Store first point once for outer linear features. // Store first point once for outer linear features.
serial::SavePoint(sink, poly[0], params); serial::SavePoint(sink, poly[0], params);
@@ -693,8 +690,10 @@ void FeatureBuilder::SerializeForMwm(SupportingData & data, serial::GeometryCodi
WriteVarUintArray(data.m_ptsOffset, sink); WriteVarUintArray(data.m_ptsOffset, sink);
} }
} }
else if (type == GeomType::Area) else
{ {
CHECK_EQUAL(type, GeomType::Area, ());
if (trgCount > 0) if (trgCount > 0)
serial::SaveInnerTriangles(data.m_innerTrg, params, sink); serial::SaveInnerTriangles(data.m_innerTrg, params, sink);
else else

View File

@@ -10,13 +10,13 @@ public:
enum class Version : uint8_t enum class Version : uint8_t
{ {
V0 = 0, V0 = 0,
Latest = V0 V1, // 2025.06, get some free bits in Feature::Header2
Latest = V1
}; };
template <typename Sink> template <typename Sink>
void Serialize(Sink & sink) const void Serialize(Sink & sink) const
{ {
CHECK_EQUAL(m_version, Version::V0, ());
WriteToSink(sink, static_cast<uint8_t>(m_version)); WriteToSink(sink, static_cast<uint8_t>(m_version));
WriteToSink(sink, m_featuresOffset); WriteToSink(sink, m_featuresOffset);
WriteToSink(sink, m_featuresSize); WriteToSink(sink, m_featuresSize);
@@ -26,7 +26,8 @@ public:
void Read(Source & source) void Read(Source & source)
{ {
m_version = static_cast<Version>(ReadPrimitiveFromSource<uint8_t>(source)); m_version = static_cast<Version>(ReadPrimitiveFromSource<uint8_t>(source));
CHECK_EQUAL(static_cast<uint8_t>(m_version), static_cast<uint8_t>(Version::V0), ()); CHECK(Version::V0 <= m_version && m_version <= Version::Latest, (m_version));
m_featuresOffset = ReadPrimitiveFromSource<uint32_t>(source); m_featuresOffset = ReadPrimitiveFromSource<uint32_t>(source);
m_featuresSize = ReadPrimitiveFromSource<uint32_t>(source); m_featuresSize = ReadPrimitiveFromSource<uint32_t>(source);
} }
@@ -39,7 +40,10 @@ public:
inline std::string DebugPrint(DatSectionHeader::Version v) inline std::string DebugPrint(DatSectionHeader::Version v)
{ {
CHECK(v == DatSectionHeader::Version::V0, ()); switch (v)
return "V0"; {
case DatSectionHeader::Version::V0: return "V0";
default: return "Latest(V1)";
}
} }
} // namespace feature } // namespace feature

View File

@@ -297,7 +297,6 @@ void FeatureType::ParseCommon()
if (m_parsed.m_common) if (m_parsed.m_common)
return; return;
CHECK(m_loadInfo, ());
ParseTypes(); ParseTypes();
ArrayByteSource source(m_data.data() + m_offsets.m_common); ArrayByteSource source(m_data.data() + m_offsets.m_common);
@@ -342,21 +341,35 @@ void FeatureType::ParseHeader2()
if (m_parsed.m_header2) if (m_parsed.m_header2)
return; return;
CHECK(m_loadInfo, ());
ParseCommon(); ParseCommon();
uint8_t elemsCount = 0, geomScalesMask = 0; m_parsed.m_header2 = true;
BitSource bitSource(m_data.data() + m_offsets.m_header2);
auto const headerGeomType = static_cast<HeaderGeomType>(Header(m_data) & HEADER_MASK_GEOMTYPE);
if (headerGeomType == HeaderGeomType::Line || headerGeomType == HeaderGeomType::Area) auto const headerGeomType = static_cast<HeaderGeomType>(Header(m_data) & HEADER_MASK_GEOMTYPE);
if (headerGeomType != HeaderGeomType::Line && headerGeomType != HeaderGeomType::Area)
return;
BitSource bitSource(m_data.data() + m_offsets.m_header2);
uint8_t elemsCount = bitSource.Read(4);
uint8_t geomScalesMask = 0;
if (m_loadInfo->m_version == DatSectionHeader::Version::V0)
{ {
elemsCount = bitSource.Read(4);
// For outer geometry read the geom scales (offsets) mask. // For outer geometry read the geom scales (offsets) mask.
// For inner geometry remaining 4 bits are not used. // For inner geometry remaining 4 bits are not used.
if (elemsCount == 0) if (elemsCount == 0)
geomScalesMask = bitSource.Read(4); geomScalesMask = bitSource.Read(4);
} }
else
{
ASSERT_EQUAL(m_loadInfo->m_version, DatSectionHeader::Version::V1, ());
bool const isOuter = (bitSource.Read(1) == 1);
if (isOuter)
{
geomScalesMask = elemsCount;
elemsCount = 0;
}
}
ArrayByteSource src(bitSource.RoundPtr()); ArrayByteSource src(bitSource.RoundPtr());
serial::GeometryCodingParams const & cp = m_loadInfo->GetDefGeometryCodingParams(); serial::GeometryCodingParams const & cp = m_loadInfo->GetDefGeometryCodingParams();
@@ -370,7 +383,8 @@ void FeatureType::ParseHeader2()
// first and last points are never simplified/discarded, // first and last points are never simplified/discarded,
// 2 bits are used per each other point, i.e. // 2 bits are used per each other point, i.e.
// 3-6 pts - 1 byte, 7-10 pts - 2b, 11-14 pts - 3b. // 3-6 pts - 1 byte, 7-10 pts - 2b, 11-14 pts - 3b.
int const count = ((elemsCount - 2) + 4 - 1) / 4; /// @see FeatureBuilder::SerializeForMwm
int const count = (elemsCount - 2 + 3) / 4;
ASSERT_LESS(count, 4, ()); ASSERT_LESS(count, 4, ());
for (int i = 0; i < count; ++i) for (int i = 0; i < count; ++i)
@@ -393,8 +407,9 @@ void FeatureType::ParseHeader2()
ReadOffsets(*m_loadInfo, src, geomScalesMask, m_offsets.m_pts); ReadOffsets(*m_loadInfo, src, geomScalesMask, m_offsets.m_pts);
} }
} }
else if (headerGeomType == HeaderGeomType::Area) else
{ {
ASSERT(headerGeomType == HeaderGeomType::Area, ());
if (elemsCount > 0) if (elemsCount > 0)
{ {
// Inner geometry (strips). // Inner geometry (strips).
@@ -413,7 +428,6 @@ void FeatureType::ParseHeader2()
// Size of the whole header incl. inner geometry / triangles. // Size of the whole header incl. inner geometry / triangles.
m_innerStats.m_size = CalcOffset(src, m_data.data()); m_innerStats.m_size = CalcOffset(src, m_data.data());
m_parsed.m_header2 = true;
} }
void FeatureType::ResetGeometry() void FeatureType::ResetGeometry()
@@ -438,7 +452,6 @@ void FeatureType::ParseGeometry(int scale)
{ {
if (!m_parsed.m_points) if (!m_parsed.m_points)
{ {
CHECK(m_loadInfo, ());
ParseHeader2(); ParseHeader2();
auto const headerGeomType = static_cast<HeaderGeomType>(Header(m_data) & HEADER_MASK_GEOMTYPE); auto const headerGeomType = static_cast<HeaderGeomType>(Header(m_data) & HEADER_MASK_GEOMTYPE);
@@ -539,7 +552,6 @@ void FeatureType::ParseTriangles(int scale)
{ {
if (!m_parsed.m_triangles) if (!m_parsed.m_triangles)
{ {
CHECK(m_loadInfo, ());
ParseHeader2(); ParseHeader2();
auto const headerGeomType = static_cast<HeaderGeomType>(Header(m_data) & HEADER_MASK_GEOMTYPE); auto const headerGeomType = static_cast<HeaderGeomType>(Header(m_data) & HEADER_MASK_GEOMTYPE);

View File

@@ -21,7 +21,8 @@ void FeaturesVector::InitRecordsReader()
feature::DatSectionHeader header; feature::DatSectionHeader header;
header.Read(src); header.Read(src);
CHECK_EQUAL(header.m_version, feature::DatSectionHeader::Version::V0, ()); m_loadInfo.m_version = header.m_version;
m_recordReader = std::make_unique<RecordReader>(reader.SubReader(header.m_featuresOffset, header.m_featuresSize)); m_recordReader = std::make_unique<RecordReader>(reader.SubReader(header.m_featuresOffset, header.m_featuresSize));
} }

View File

@@ -1,5 +1,6 @@
#pragma once #pragma once
#include "indexer/dat_section_header.hpp"
#include "indexer/data_header.hpp" #include "indexer/data_header.hpp"
#include "coding/files_container.hpp" #include "coding/files_container.hpp"
@@ -47,6 +48,7 @@ private:
public: public:
indexer::MetadataDeserializer * m_metaDeserializer; indexer::MetadataDeserializer * m_metaDeserializer;
feature::DatSectionHeader::Version m_version;
DISALLOW_COPY_AND_MOVE(SharedLoadInfo); DISALLOW_COPY_AND_MOVE(SharedLoadInfo);
}; };