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

View File

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

View File

@@ -297,7 +297,6 @@ void FeatureType::ParseCommon()
if (m_parsed.m_common)
return;
CHECK(m_loadInfo, ());
ParseTypes();
ArrayByteSource source(m_data.data() + m_offsets.m_common);
@@ -342,21 +341,35 @@ void FeatureType::ParseHeader2()
if (m_parsed.m_header2)
return;
CHECK(m_loadInfo, ());
ParseCommon();
uint8_t elemsCount = 0, geomScalesMask = 0;
BitSource bitSource(m_data.data() + m_offsets.m_header2);
auto const headerGeomType = static_cast<HeaderGeomType>(Header(m_data) & HEADER_MASK_GEOMTYPE);
m_parsed.m_header2 = true;
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 inner geometry remaining 4 bits are not used.
if (elemsCount == 0)
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());
serial::GeometryCodingParams const & cp = m_loadInfo->GetDefGeometryCodingParams();
@@ -370,7 +383,8 @@ void FeatureType::ParseHeader2()
// first and last points are never simplified/discarded,
// 2 bits are used per each other point, i.e.
// 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, ());
for (int i = 0; i < count; ++i)
@@ -393,8 +407,9 @@ void FeatureType::ParseHeader2()
ReadOffsets(*m_loadInfo, src, geomScalesMask, m_offsets.m_pts);
}
}
else if (headerGeomType == HeaderGeomType::Area)
else
{
ASSERT(headerGeomType == HeaderGeomType::Area, ());
if (elemsCount > 0)
{
// Inner geometry (strips).
@@ -413,7 +428,6 @@ void FeatureType::ParseHeader2()
// Size of the whole header incl. inner geometry / triangles.
m_innerStats.m_size = CalcOffset(src, m_data.data());
m_parsed.m_header2 = true;
}
void FeatureType::ResetGeometry()
@@ -438,7 +452,6 @@ void FeatureType::ParseGeometry(int scale)
{
if (!m_parsed.m_points)
{
CHECK(m_loadInfo, ());
ParseHeader2();
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)
{
CHECK(m_loadInfo, ());
ParseHeader2();
auto const headerGeomType = static_cast<HeaderGeomType>(Header(m_data) & HEADER_MASK_GEOMTYPE);

View File

@@ -21,7 +21,8 @@ void FeaturesVector::InitRecordsReader()
feature::DatSectionHeader header;
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));
}

View File

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