mirror of
https://codeberg.org/comaps/comaps
synced 2025-12-19 13:03:36 +00:00
[feature] Added Feature V1 version with free Header2 bits.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
This commit is contained in:
committed by
Konstantin Pastbin
parent
588028c9eb
commit
550455a14a
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user