diff --git a/generator/altitude_generator.cpp b/generator/altitude_generator.cpp index 4b3d0e7088..d90a6d008f 100644 --- a/generator/altitude_generator.cpp +++ b/generator/altitude_generator.cpp @@ -213,6 +213,7 @@ void BuildRoadAltitudes(string const & mwmPath, AltitudeGetter & altitudeGetter) // Writing altitude info. header.m_altitudesOffset = w.Pos() - startOffset; w.Write(deltas.data(), deltas.size()); + w.WritePaddingByEnd(8); header.m_endOffset = w.Pos() - startOffset; // Rewriting header info. @@ -220,8 +221,7 @@ void BuildRoadAltitudes(string const & mwmPath, AltitudeGetter & altitudeGetter) w.Seek(startOffset); header.Serialize(w); w.Seek(endOffset); - LOG(LINFO, (ALTITUDES_FILE_TAG, "section is ready. The size is", endOffset - startOffset, - "min altitude is", processor.GetMinAltitude())); + LOG(LINFO, (ALTITUDES_FILE_TAG, "section is ready. The size is", header.m_endOffset)); if (processor.HasAltitudeInfo()) LOG(LINFO, ("Min altitude is", processor.GetMinAltitude())); else diff --git a/indexer/altitude_loader.cpp b/indexer/altitude_loader.cpp index a794c96537..cb05bc4cf6 100644 --- a/indexer/altitude_loader.cpp +++ b/indexer/altitude_loader.cpp @@ -31,6 +31,8 @@ namespace feature { AltitudeLoader::AltitudeLoader(MwmValue const & mwmValue) { + m_countryFileName = mwmValue.GetCountryFileName(); + if (mwmValue.GetHeader().GetFormat() < version::Format::v8) return; @@ -50,7 +52,7 @@ AltitudeLoader::AltitudeLoader(MwmValue const & mwmValue) catch (Reader::OpenException const & e) { m_header.Reset(); - LOG(LERROR, ("Error while reading", ALTITUDES_FILE_TAG, "section.", e.Msg())); + LOG(LERROR, ("File", m_countryFileName, "Error while reading", ALTITUDES_FILE_TAG, "section.", e.Msg())); } } @@ -73,31 +75,34 @@ TAltitudes const & AltitudeLoader::GetAltitudes(uint32_t featureId, size_t point if (!m_altitudeAvailability[featureId]) { - LOG(LINFO, ("Feature featureId =", featureId, "does not contain any altitude information.")); + LOG(LDEBUG, ("Feature Id", featureId, "of", m_countryFileName, + "does not contain any altitude information.")); return m_cache.insert(make_pair(featureId, TAltitudes(pointCount, m_header.m_minAltitude))).first->second; } uint64_t const r = m_altitudeAvailability.rank(featureId); - CHECK_LESS(r, m_altitudeAvailability.size(), (featureId)); + CHECK_LESS(r, m_altitudeAvailability.size(), ("Feature Id", featureId, "of", m_countryFileName)); uint64_t const offset = m_featureTable.select(r); - CHECK_LESS_OR_EQUAL(offset, m_featureTable.size(), (featureId)); + CHECK_LESS_OR_EQUAL(offset, m_featureTable.size(), ("Feature Id", featureId, "of", m_countryFileName)); uint64_t const altitudeInfoOffsetInSection = m_header.m_altitudesOffset + offset; - CHECK_LESS(altitudeInfoOffsetInSection, m_reader->Size(), ()); + CHECK_LESS(altitudeInfoOffsetInSection, m_reader->Size(), ("Feature Id", featureId, "of", m_countryFileName)); try { Altitudes altitudes; ReaderSource src(*m_reader); src.Skip(altitudeInfoOffsetInSection); - bool const isDeserialized = altitudes.Deserialize(m_header.m_minAltitude, pointCount, src); + bool const isDeserialized = altitudes.Deserialize(m_header.m_minAltitude, pointCount, + m_countryFileName, featureId, src); bool const allValid = isDeserialized && none_of(altitudes.m_altitudes.begin(), altitudes.m_altitudes.end(), [](TAltitude a) { return a == kInvalidAltitude; }); if (!allValid) { - ASSERT(false, (altitudes.m_altitudes)); + LOG(LERROR, ("Only a part point of a feature has a valid altitdue. Altitudes: ", altitudes.m_altitudes, + ". Feature Id", featureId, "of", m_countryFileName)); return m_cache.insert(make_pair(featureId, TAltitudes(pointCount, m_header.m_minAltitude))).first->second; } @@ -105,7 +110,7 @@ TAltitudes const & AltitudeLoader::GetAltitudes(uint32_t featureId, size_t point } catch (Reader::OpenException const & e) { - LOG(LERROR, ("Error while getting altitude data", e.Msg())); + LOG(LERROR, ("Feature Id", featureId, "of", m_countryFileName, ". Error while getting altitude data:", e.Msg())); return m_cache.insert(make_pair(featureId, TAltitudes(pointCount, m_header.m_minAltitude))).first->second; } } diff --git a/indexer/altitude_loader.hpp b/indexer/altitude_loader.hpp index ff76fd9ba9..0586fa2d33 100644 --- a/indexer/altitude_loader.hpp +++ b/indexer/altitude_loader.hpp @@ -4,6 +4,7 @@ #include "coding/memory_region.hpp" +#include "std/string.hpp" #include "std/unique_ptr.hpp" #include "std/vector.hpp" @@ -32,5 +33,6 @@ private: unique_ptr m_reader; map m_cache; AltitudeHeader m_header; + string m_countryFileName; }; } // namespace feature diff --git a/indexer/feature_altitude.hpp b/indexer/feature_altitude.hpp index 81b0c918ed..41f1f3a7da 100644 --- a/indexer/feature_altitude.hpp +++ b/indexer/feature_altitude.hpp @@ -1,9 +1,13 @@ #pragma once + +#include "coding/bit_streams.hpp" +#include "coding/elias_coder.hpp" #include "coding/reader.hpp" #include "coding/varint.hpp" #include "coding/write_to_sink.hpp" #include "base/assert.hpp" +#include "base/bits.hpp" #include "std/cstdint.hpp" #include "std/limits.hpp" @@ -51,7 +55,7 @@ struct AltitudeHeader size_t GetFeatureTableSize() const { return m_altitudesOffset - m_featureTableOffset; } - size_t GetAltitudeInfo() const { return m_endOffset - m_altitudesOffset; } + size_t GetAltitudeInfoSize() const { return m_endOffset - m_altitudesOffset; } void Reset() { @@ -83,32 +87,46 @@ public: { CHECK(!m_altitudes.empty(), ()); - WriteVarInt(sink, static_cast(m_altitudes[0]) - static_cast(minAltitude)); - for (size_t i = 1; i < m_altitudes.size(); ++i) + BitWriter bits(sink); + TAltitude prevAltitude = minAltitude; + for (auto const altitude : m_altitudes) { - WriteVarInt(sink, - static_cast(m_altitudes[i]) - static_cast(m_altitudes[i - 1])); + CHECK_LESS_OR_EQUAL(minAltitude, altitude, ("A point altitude is less than min mwm altitude")); + uint32_t const delta = bits::ZigZagEncode(static_cast(altitude) - + static_cast(prevAltitude)); + coding::DeltaCoder::Encode(bits, delta + 1 /* making it greater than zero */); + prevAltitude = altitude; } } template - bool Deserialize(TAltitude minAltitude, size_t pointCount, TSource & src) + bool Deserialize(TAltitude minAltitude, size_t pointCount, string const & countryFileName, + uint32_t featureId, TSource & src) { - m_altitudes.clear(); - if (pointCount == 0) - { - ASSERT(false, ()); - return false; - } + ASSERT_NOT_EQUAL(pointCount, 0, ()); - m_altitudes.resize(pointCount); + BitReader bits(src); TAltitude prevAltitude = minAltitude; + m_altitudes.resize(pointCount); + for (size_t i = 0; i < pointCount; ++i) { - m_altitudes[i] = static_cast(ReadVarInt(src) + prevAltitude); + uint32_t const biasedDelta = coding::DeltaCoder::Decode(bits); + if (biasedDelta == 0) + { + LOG(LERROR, ("Decoded altitude delta is zero. File", countryFileName, + ". Feature Id", featureId, ". Point number in the feature", i, ".")); + m_altitudes.clear(); + return false; + } + uint32_t const delta = biasedDelta - 1; + + m_altitudes[i] = static_cast(bits::ZigZagDecode(delta) + prevAltitude); if (m_altitudes[i] < minAltitude) { - ASSERT(false, ()); + LOG(LERROR, ("A point altitude read from file(", m_altitudes[i], + ") is less than min mwm altitude(", minAltitude, "). File ", + countryFileName, ". Feature Id", featureId, ". Point number in the feature", i, ".")); m_altitudes.clear(); return false; }