diff --git a/generator/altitude_generator.cpp b/generator/altitude_generator.cpp index 2a282ece0d..c8eb5e2d81 100644 --- a/generator/altitude_generator.cpp +++ b/generator/altitude_generator.cpp @@ -15,11 +15,10 @@ #include "coding/reader.hpp" #include "coding/succinct_mapper.hpp" #include "coding/varint.hpp" +#include "coding/internal/file_data.hpp" #include "geometry/latlon.hpp" -#include "coding/internal/file_data.hpp" - #include "base/assert.hpp" #include "base/logging.hpp" #include "base/scope_guard.hpp" @@ -43,14 +42,12 @@ namespace { using namespace routing; -AltitudeHeader::TAltitudeSectionVersion constexpr kAltitudeSectionVersion = 0; - -class SrtmGetter : public IAltitudeGetter +class SrtmGetter : public AltitudeGetter { public: - SrtmGetter(string const & srtmPath) : m_srtmManager(srtmPath) {} + SrtmGetter(string const & srtmDir) : m_srtmManager(srtmDir) {} - // IAltitudeGetter overrides: + // AltitudeGetter overrides: feature::TAltitude GetAltitude(m2::PointD const & p) override { return m_srtmManager.GetHeight(MercatorBounds::ToLatLon(p)); @@ -63,10 +60,21 @@ private: class Processor { public: - using TFeatureAltitude = pair; - using TFeatureAltitudes = vector; + struct FeatureAltitude + { + FeatureAltitude() : m_featureId(0) {} + FeatureAltitude(uint32_t featureId, Altitudes const & altitudes) + : m_featureId(featureId), m_altitudes(altitudes) + { + } - Processor(IAltitudeGetter & altitudeGetter) + uint32_t m_featureId; + Altitudes m_altitudes; + }; + + using TFeatureAltitudes = vector; + + Processor(AltitudeGetter & altitudeGetter) : m_altitudeGetter(altitudeGetter), m_minAltitude(kInvalidAltitude) { } @@ -89,7 +97,7 @@ public: } bool hasAltitude = false; - MY_SCOPE_GUARD(removeTmpDir, [&] () + MY_SCOPE_GUARD(altitudeAvailabilityBuilding, [&] () { m_altitudeAvailabilityBuilder.push_back(hasAltitude); }); @@ -103,16 +111,12 @@ public: return; TAltitudes altitudes; - bool valid = true; TAltitude minFeatureAltitude = kInvalidAltitude; for (size_t i = 0; i < pointsCount; ++i) { TAltitude const a = m_altitudeGetter.GetAltitude(f.GetPoint(i)); if (a == kInvalidAltitude) - { - valid = false; return; - } if (minFeatureAltitude == kInvalidAltitude) minFeatureAltitude = a; @@ -121,11 +125,9 @@ public: altitudes.push_back(a); } - if (!valid) - return; hasAltitude = true; - m_featureAltitudes.push_back(make_pair(id, Altitude(move(altitudes)))); + m_featureAltitudes.emplace_back(id, Altitudes(move(altitudes))); if (m_minAltitude == kInvalidAltitude) m_minAltitude = minFeatureAltitude; @@ -141,22 +143,20 @@ public: bool IsFeatureAltitudesSorted() { return is_sorted(m_featureAltitudes.begin(), m_featureAltitudes.end(), - my::LessBy(&Processor::TFeatureAltitude::first)); + my::LessBy(&Processor::FeatureAltitude::m_featureId)); } private: - IAltitudeGetter & m_altitudeGetter; + AltitudeGetter & m_altitudeGetter; TFeatureAltitudes m_featureAltitudes; succinct::bit_vector_builder m_altitudeAvailabilityBuilder; TAltitude m_minAltitude; }; } // namespace -static_assert(sizeof(AltitudeHeader) == 16, "Wrong header size of altitude section."); - namespace routing { -void BuildRoadAltitudes(string const & mwmPath, IAltitudeGetter & altitudeGetter) +void BuildRoadAltitudes(string const & mwmPath, AltitudeGetter & altitudeGetter) { try { @@ -174,8 +174,10 @@ void BuildRoadAltitudes(string const & mwmPath, IAltitudeGetter & altitudeGetter FilesContainerW cont(mwmPath, FileWriter::OP_WRITE_EXISTING); FileWriter w = cont.GetWriter(ALTITUDES_FILE_TAG); + AltitudeHeader header; - header.minAltitude = processor.GetMinAltitude(); + header.m_minAltitude = processor.GetMinAltitude(); + int64_t const startOffset = w.Pos(); header.Serialize(w); { @@ -184,7 +186,7 @@ void BuildRoadAltitudes(string const & mwmPath, IAltitudeGetter & altitudeGetter succinct::bit_vector_builder & builder = processor.GetAltitudeAvailabilityBuilder(); succinct::rs_bit_vector(&builder).map(visitor); } - header.featureTableOffset = w.Pos() - startOffset; + header.m_featureTableOffset = w.Pos() - startOffset; vector offsets; vector deltas; @@ -195,7 +197,7 @@ void BuildRoadAltitudes(string const & mwmPath, IAltitudeGetter & altitudeGetter for (auto const & a : featureAltitudes) { offsets.push_back(writer.Pos()); - a.second.Serialize(header.minAltitude, writer); + a.m_altitudes.Serialize(header.m_minAltitude, writer); } } { @@ -211,27 +213,27 @@ void BuildRoadAltitudes(string const & mwmPath, IAltitudeGetter & altitudeGetter succinct::elias_fano(&builder).map(visitor); } // Writing altitude info. - header.altitudeInfoOffset = w.Pos() - startOffset; + header.m_altitudesOffset = w.Pos() - startOffset; w.Write(deltas.data(), deltas.size()); - header.endOffset = w.Pos() - startOffset; + header.m_endOffset = w.Pos() - startOffset; // Rewriting header info. - header.version = kAltitudeSectionVersion; int64_t const endOffset = w.Pos(); w.Seek(startOffset); header.Serialize(w); w.Seek(endOffset); + LOG(LINFO, (ALTITUDES_FILE_TAG, "section is ready. The size is", endOffset - startOffset)); } catch (RootException const & e) { - LOG(LERROR, ("An exception happened while creating", ALTITUDES_FILE_TAG, "section. ", e.what())); + LOG(LERROR, ("An exception happened while creating", ALTITUDES_FILE_TAG, "section:", e.what())); } } -void BuildRoadAltitudes(string const & mwmPath, string const & srtmPath) +void BuildRoadAltitudes(string const & mwmPath, string const & srtmDir) { - LOG(LINFO, ("mwmPath =", mwmPath, "srtmPath =", srtmPath)); - SrtmGetter srtmGetter(srtmPath); + LOG(LINFO, ("mwmPath =", mwmPath, "srtmDir =", srtmDir)); + SrtmGetter srtmGetter(srtmDir); BuildRoadAltitudes(mwmPath, srtmGetter); } } // namespace routing diff --git a/generator/altitude_generator.hpp b/generator/altitude_generator.hpp index 2dbd7cf147..6cecdd99e2 100644 --- a/generator/altitude_generator.hpp +++ b/generator/altitude_generator.hpp @@ -8,7 +8,7 @@ namespace routing { -class IAltitudeGetter +class AltitudeGetter { public: virtual feature::TAltitude GetAltitude(m2::PointD const & p) = 0; @@ -22,8 +22,8 @@ public: /// 8 altitude info offset 4 /// 12 end of section 4 /// 16 altitude availability feat. table offset - 16 -/// feat. table offset feature table alt. info offset - f. table offset -/// alt. info offset altitude info alt. info offset - end of section -void BuildRoadAltitudes(string const & mwmPath, IAltitudeGetter & altitudeGetter); -void BuildRoadAltitudes(string const & mwmPath, string const & srtmPath); +/// feat. table offset feature table alt. info offset - feat. table offset +/// alt. info offset altitude info end of section - alt. info offset +void BuildRoadAltitudes(string const & mwmPath, AltitudeGetter & altitudeGetter); +void BuildRoadAltitudes(string const & mwmPath, string const & srtmDir); } // namespace routing diff --git a/generator/generator_tests/altitude_test.cpp b/generator/generator_tests/altitude_test.cpp index a6f407ef34..935794630e 100644 --- a/generator/generator_tests/altitude_test.cpp +++ b/generator/generator_tests/altitude_test.cpp @@ -1,7 +1,6 @@ #include "testing/testing.hpp" #include "generator/altitude_generator.hpp" - #include "generator/generator_tests_support/test_feature.hpp" #include "generator/generator_tests_support/test_mwm_builder.hpp" @@ -19,7 +18,8 @@ #include "platform/country_file.hpp" #include "platform/platform.hpp" - +#include "platform/platform_tests_support/scoped_dir.hpp" +#include "platform/platform_tests_support/scoped_file.hpp" #include "platform/platform_tests_support/writable_dir_changer.hpp" #include "base/logging.hpp" @@ -31,12 +31,11 @@ using namespace feature; using namespace generator; using namespace platform; using namespace routing; -using namespace tests_support; namespace { // These tests generate mwms with altitude sections and then check if altitudes -// in the mwms are correct. The mwms are inited with different sets of features defined below. +// in the mwms are correct. The mwms are initialized with different sets of features. // There are several restrictions for these features: // * all of them are linear // * all coords of these features should be integer (it's necessary for easy implementation of MockAltitudeGetter) @@ -49,29 +48,29 @@ string const kTestDir = "altitude_generation_test"; // Temporary mwm name for testing. string const kTestMwm = "test"; -struct Rounded3DPoint +struct Point3D { - Rounded3DPoint(int32_t x, int32_t y, TAltitude a) : point2D(x, y), altitude(a) {} + Point3D(int32_t x, int32_t y, TAltitude a) : m_point(x, y), m_altitude(a) {} - m2::PointI point2D; - TAltitude altitude; + m2::PointI m_point; + TAltitude m_altitude; }; -using TRounded3DGeom = vector; +using TPoint3DList = vector; -TRounded3DGeom const kRoad1 = {{0, -1, -1}, {0, 0, 0}, {0, 1, 1}}; -TRounded3DGeom const kRoad2 = {{0, 1, 1}, {5, 1, 1}, {10, 1, 1}}; -TRounded3DGeom const kRoad3 = {{10, 1, 1}, {15, 6, 100}, {20, 11, 110}}; -TRounded3DGeom const kRoad4 = {{-10, 1, -1}, {-20, 6, -100}, {-20, -11, -110}}; +TPoint3DList const kRoad1 = {{0, -1, -1}, {0, 0, 0}, {0, 1, 1}}; +TPoint3DList const kRoad2 = {{0, 1, 1}, {5, 1, 1}, {10, 1, 1}}; +TPoint3DList const kRoad3 = {{10, 1, 1}, {15, 6, 100}, {20, 11, 110}}; +TPoint3DList const kRoad4 = {{-10, 1, -1}, {-20, 6, -100}, {-20, -11, -110}}; -class MockAltitudeGetter : public IAltitudeGetter +class MockAltitudeGetter : public AltitudeGetter { public: using TMockAltitudes = map; MockAltitudeGetter(TMockAltitudes && altitudes) : m_altitudes(altitudes) {} - // IAltitudeGetter overrides: + // AltitudeGetter overrides: TAltitude GetAltitude(m2::PointD const & p) override { m2::PointI const rounded(static_cast(round(p.x)), static_cast(round(p.y))); @@ -86,57 +85,43 @@ private: TMockAltitudes const & m_altitudes; }; -template -vector ConvertTo2DGeom(TRounded3DGeom const & geom3D) +vector ExtractPoints(TPoint3DList const & geom3D) { - vector dv; - dv.clear(); - for (Rounded3DPoint const & p : geom3D) - dv.push_back(T(p.point2D)); - return dv; + vector result; + for (Point3D const & p : geom3D) + result.push_back(m2::PointD(p.m_point)); + return result; } -TAltitudes ConvertToAltitudes(TRounded3DGeom const & geom3D) -{ - TAltitudes altitudes; - altitudes.clear(); - for (Rounded3DPoint const & p : geom3D) - altitudes.push_back(p.altitude); - return altitudes; -} - -void FillAltitudes(vector const & roadFeatures, +void FillAltitudes(vector const & roads, MockAltitudeGetter::TMockAltitudes & altitudes) { - for (TRounded3DGeom const & geom3D : roadFeatures) + for (TPoint3DList const & geom3D : roads) { - vector const featureGeom = ConvertTo2DGeom(geom3D); - TAltitudes const featureAlt = ConvertToAltitudes(geom3D); - CHECK_EQUAL(featureGeom.size(), featureAlt.size(), ()); - for (size_t i = 0; i < featureGeom.size(); ++i) + for (size_t i = 0; i < geom3D.size(); ++i) { - auto it = altitudes.find(featureGeom[i]); + auto it = altitudes.find(geom3D[i].m_point); if (it != altitudes.end()) { - CHECK_EQUAL(it->second, featureAlt[i], ("Point", it->first, "is set with two different altitudes.")); + CHECK_EQUAL(it->second, geom3D[i].m_altitude, ("Point", it->first, "is set with two different altitudes.")); continue; } - altitudes[featureGeom[i]] = featureAlt[i]; + altitudes[geom3D[i].m_point] = geom3D[i].m_altitude; } } } -void BuildMwmWithoutAltitude(vector const & roadFeatures, LocalCountryFile & country) +void BuildMwmWithoutAltitudes(vector const & roads, LocalCountryFile & country) { - TestMwmBuilder builder(country, feature::DataHeader::country); + generator::tests_support::TestMwmBuilder builder(country, feature::DataHeader::country); - for (TRounded3DGeom const & geom3D : roadFeatures) - builder.Add(TestStreet(ConvertTo2DGeom(geom3D), string(), string())); + for (TPoint3DList const & geom3D : roads) + builder.Add(generator::tests_support::TestStreet(ExtractPoints(geom3D), string(), string())); } -void ReadAndTestAltitudeInfo(MwmValue const & mwmValue, string const & mwmPath, MockAltitudeGetter & altitudeGetter) +void TestAltitudes(MwmValue const & mwmValue, string const & mwmPath, MockAltitudeGetter & altitudeGetter) { - AltitudeLoader const loader(mwmValue); + AltitudeLoader loader(mwmValue); auto processor = [&altitudeGetter, &loader](FeatureType const & f, uint32_t const & id) { @@ -158,75 +143,71 @@ void ReadAndTestAltitudeInfo(MwmValue const & mwmValue, string const & mwmPath, feature::ForEachFromDat(mwmPath, processor); } -void TestAltitudeSection(vector const & roadFeatures) +void TestAltitudesBuilding(vector const & roads) { classificator::Load(); Platform & platform = GetPlatform(); string const testDirFullPath = my::JoinFoldersToPath(platform.WritableDir(), kTestDir); - MY_SCOPE_GUARD(removeTmpDir, [&] () - { - GetPlatform().RmDirRecursively(testDirFullPath); - }); - // Building mwm without altitude section. - platform.MkDir(testDirFullPath); LocalCountryFile country(testDirFullPath, CountryFile(kTestMwm), 1); - BuildMwmWithoutAltitude(roadFeatures, country); + platform::tests_support::ScopedDir testScopedDir(kTestDir); + platform::tests_support::ScopedFile testScopedMwm(country.GetPath(MapOptions::Map)); + BuildMwmWithoutAltitudes(roads, country); // Creating MockAltitudeGetter. MockAltitudeGetter::TMockAltitudes altitudes; - FillAltitudes(roadFeatures, altitudes); + FillAltitudes(roads, altitudes); MockAltitudeGetter altitudeGetter(move(altitudes)); // Adding altitude section to mwm. string const mwmPath = my::JoinFoldersToPath(testDirFullPath, kTestMwm + DATA_FILE_EXTENSION); BuildRoadAltitudes(mwmPath, altitudeGetter); - // Reading from mwm and testing altitue information. + // Reading from mwm and testing altitude information. Index index; - pair regResult = index.RegisterMap(country); + auto const regResult = index.RegisterMap(country); TEST_EQUAL(regResult.second, MwmSet::RegResult::Success, ()); MwmSet::MwmHandle mwmHandle = index.GetMwmHandleById(regResult.first); - CHECK(mwmHandle.IsAlive(), ()); + TEST(mwmHandle.IsAlive(), ()); - ReadAndTestAltitudeInfo(*mwmHandle.GetValue(), mwmPath, altitudeGetter); + TestAltitudes(*mwmHandle.GetValue(), mwmPath, altitudeGetter); +} + +UNIT_TEST(AltitudeGenerationTest_ZeroFeatures) +{ + vector const roads = {}; + TestAltitudesBuilding(roads); +} + +UNIT_TEST(AltitudeGenerationTest_OneRoad) +{ + vector const roads = {kRoad1}; + TestAltitudesBuilding(roads); +} + +UNIT_TEST(AltitudeGenerationTest_TwoConnectedRoads) +{ + vector const roads = {kRoad1, kRoad2}; + TestAltitudesBuilding(roads); +} + +UNIT_TEST(AltitudeGenerationTest_TwoDisconnectedRoads) +{ + vector const roads = {kRoad1, kRoad3}; + TestAltitudesBuilding(roads); +} + +UNIT_TEST(AltitudeGenerationTest_ThreeRoads) +{ + vector const roads = {kRoad1, kRoad2, kRoad3}; + TestAltitudesBuilding(roads); +} + +UNIT_TEST(AltitudeGenerationTest_FourRoads) +{ + vector const roads = {kRoad1, kRoad2, kRoad3, kRoad4}; + TestAltitudesBuilding(roads); } } // namespace - -UNIT_TEST(ZeroFeatures_AltitudeGenerationTest) -{ - vector const roadFeatures = {}; - TestAltitudeSection(roadFeatures); -} - -UNIT_TEST(OneRoad_AltitudeGenerationTest) -{ - vector const roadFeatures = {kRoad1}; - TestAltitudeSection(roadFeatures); -} - -UNIT_TEST(TwoConnectedRoads_AltitudeGenerationTest) -{ - vector const roadFeatures = {kRoad1, kRoad2}; - TestAltitudeSection(roadFeatures); -} - -UNIT_TEST(TwoDisconnectedRoads_AltitudeGenerationTest) -{ - vector const roadFeatures = {kRoad1, kRoad3}; - TestAltitudeSection(roadFeatures); -} - -UNIT_TEST(ThreeRoads_AltitudeGenerationTest) -{ - vector const roadFeatures = {kRoad1, kRoad2, kRoad3}; - TestAltitudeSection(roadFeatures); -} - -UNIT_TEST(FourRoads_AltitudeGenerationTest) -{ - vector const roadFeatures = {kRoad1, kRoad2, kRoad3, kRoad4}; - TestAltitudeSection(roadFeatures); -} diff --git a/generator/generator_tests/generator_tests.pro b/generator/generator_tests/generator_tests.pro index b782763808..a3f1a229c1 100644 --- a/generator/generator_tests/generator_tests.pro +++ b/generator/generator_tests/generator_tests.pro @@ -4,7 +4,8 @@ CONFIG -= app_bundle TEMPLATE = app ROOT_DIR = ../.. -DEPENDENCIES = generator_tests_support generator drape_frontend routing search storage indexer drape map platform editor geometry \ +DEPENDENCIES = generator_tests_support platform_tests_support generator drape_frontend routing search storage \ + indexer drape map platform editor geometry \ coding base freetype expat fribidi tomcrypt jansson protobuf osrm stats_client \ minizip succinct pugixml tess2 gflags oauthcpp diff --git a/generator/generator_tool/generator_tool.cpp b/generator/generator_tool/generator_tool.cpp index 653b8cea5e..a7f372b320 100644 --- a/generator/generator_tool/generator_tool.cpp +++ b/generator/generator_tool/generator_tool.cpp @@ -212,9 +212,12 @@ int main(int argc, char ** argv) if (!search::RankTableBuilder::CreateIfNotExists(datFile)) LOG(LCRITICAL, ("Error generating rank table.")); } + + if (!FLAGS_srtm_path.empty()) + routing::BuildRoadAltitudes(datFile, FLAGS_srtm_path); } - string const datFile = path + FLAGS_output + DATA_FILE_EXTENSION; + string const datFile = my::JoinFoldersToPath(path, FLAGS_output + DATA_FILE_EXTENSION); if (FLAGS_calc_statistics) { @@ -249,12 +252,6 @@ int main(int argc, char ** argv) if (FLAGS_dump_feature_names != "") feature::DumpFeatureNames(datFile, FLAGS_dump_feature_names); - if (!FLAGS_srtm_path.empty()) - { - string const mwmPath = my::JoinFoldersToPath(path, FLAGS_output + DATA_FILE_EXTENSION); - routing::BuildRoadAltitudes(FLAGS_srtm_path, mwmPath); - } - if (FLAGS_unpack_mwm) UnpackMwm(datFile); diff --git a/indexer/altitude_loader.cpp b/indexer/altitude_loader.cpp index 6eab7b38e8..d01c719d5d 100644 --- a/indexer/altitude_loader.cpp +++ b/indexer/altitude_loader.cpp @@ -14,8 +14,8 @@ namespace { template -void Map(size_t dataSize, ReaderSource & src, - TCont & cont, unique_ptr & region) +void LoadAndMap(size_t dataSize, ReaderSource & src, + TCont & cont, unique_ptr & region) { vector data(dataSize); src.Read(data.data(), data.size()); @@ -41,8 +41,9 @@ AltitudeLoader::AltitudeLoader(MwmValue const & mwmValue) ReaderSource src(*m_reader); m_header.Deserialize(src); - Map(m_header.GetAltitudeAvailabilitySize(), src, m_altitudeAvailability, m_altitudeAvailabilityRegion); - Map(m_header.GetFeatureTableSize(), src, m_featureTable, m_featureTableRegion); + LoadAndMap(m_header.GetAltitudeAvailabilitySize(), src, m_altitudeAvailability, + m_altitudeAvailabilityRegion); + LoadAndMap(m_header.GetFeatureTableSize(), src, m_featureTable, m_featureTableRegion); } catch (Reader::OpenException const & e) { @@ -51,16 +52,16 @@ AltitudeLoader::AltitudeLoader(MwmValue const & mwmValue) } } -bool AltitudeLoader::IsAvailable() const +bool AltitudeLoader::HasAltitudes() const { - return m_header.minAltitude != kInvalidAltitude; + return m_header.m_minAltitude != kInvalidAltitude; } -TAltitudes const & AltitudeLoader::GetAltitudes(uint32_t featureId, size_t pointCount) const +TAltitudes const & AltitudeLoader::GetAltitudes(uint32_t featureId, size_t pointCount) { - if (!IsAvailable()) + if (!HasAltitudes()) { - // The version of mwm is less then version::Format::v8 or there's no altitude section in mwm. + // The version of mwm is less than version::Format::v8 or there's no altitude section in mwm. return m_dummy; } @@ -71,7 +72,7 @@ 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.")); - return m_cache.insert(make_pair(featureId, TAltitudes())).first->second; + return m_cache.insert(make_pair(featureId, m_dummy)).first->second; } uint64_t const r = m_altitudeAvailability.rank(featureId); @@ -79,22 +80,22 @@ TAltitudes const & AltitudeLoader::GetAltitudes(uint32_t featureId, size_t point uint64_t const offset = m_featureTable.select(r); CHECK_LESS_OR_EQUAL(offset, m_featureTable.size(), (featureId)); - uint64_t const altitudeInfoOffsetInSection = m_header.altitudeInfoOffset + offset; + uint64_t const altitudeInfoOffsetInSection = m_header.m_altitudesOffset + offset; CHECK_LESS(altitudeInfoOffsetInSection, m_reader->Size(), ()); try { - Altitude a; + Altitudes a; ReaderSource src(*m_reader); src.Skip(altitudeInfoOffsetInSection); - a.Deserialize(m_header.minAltitude, pointCount, src); + a.Deserialize(m_header.m_minAltitude, pointCount, src); return m_cache.insert(make_pair(featureId, a.GetAltitudes())).first->second; } catch (Reader::OpenException const & e) { - LOG(LERROR, ("Error while getting mwm data", e.Msg())); - return m_cache.insert(make_pair(featureId, TAltitudes())).first->second; + LOG(LERROR, ("Error while getting altitude data", e.Msg())); + return m_cache.insert(make_pair(featureId, m_dummy)).first->second; } } } // namespace feature diff --git a/indexer/altitude_loader.hpp b/indexer/altitude_loader.hpp index 964b19bc5a..cce768df67 100644 --- a/indexer/altitude_loader.hpp +++ b/indexer/altitude_loader.hpp @@ -16,8 +16,8 @@ class AltitudeLoader public: explicit AltitudeLoader(MwmValue const & mwmValue); - TAltitudes const & GetAltitudes(uint32_t featureId, size_t pointCount) const; - bool IsAvailable() const; + TAltitudes const & GetAltitudes(uint32_t featureId, size_t pointCount); + bool HasAltitudes() const; private: unique_ptr m_altitudeAvailabilityRegion; @@ -27,7 +27,7 @@ private: succinct::elias_fano m_featureTable; unique_ptr m_reader; - mutable map m_cache; + map m_cache; TAltitudes const m_dummy; AltitudeHeader m_header; }; diff --git a/indexer/feature_altitude.hpp b/indexer/feature_altitude.hpp index 3b225d04ee..f72966b967 100644 --- a/indexer/feature_altitude.hpp +++ b/indexer/feature_altitude.hpp @@ -1,5 +1,7 @@ #pragma once +#include "coding/reader.hpp" #include "coding/varint.hpp" +#include "coding/write_to_sink.hpp" #include "base/assert.hpp" @@ -11,7 +13,6 @@ namespace feature { using TAltitude = int16_t; using TAltitudes = vector; -using TAltitudeSectionOffset = uint32_t; TAltitude constexpr kInvalidAltitude = numeric_limits::min(); @@ -27,58 +28,58 @@ struct AltitudeHeader template void Serialize(TSink & sink) const { - sink.Write(&version, sizeof(version)); - sink.Write(&minAltitude, sizeof(minAltitude)); - sink.Write(&featureTableOffset, sizeof(featureTableOffset)); - sink.Write(&altitudeInfoOffset, sizeof(altitudeInfoOffset)); - sink.Write(&endOffset, sizeof(endOffset)); + WriteToSink(sink, m_version); + WriteToSink(sink, m_minAltitude); + WriteToSink(sink, m_featureTableOffset); + WriteToSink(sink, m_altitudesOffset); + WriteToSink(sink, m_endOffset); } template void Deserialize(TSource & src) { - src.Read(&version, sizeof(version)); - src.Read(&minAltitude, sizeof(minAltitude)); - src.Read(&featureTableOffset, sizeof(featureTableOffset)); - src.Read(&altitudeInfoOffset, sizeof(altitudeInfoOffset)); - src.Read(&endOffset, sizeof(endOffset)); + m_version = ReadPrimitiveFromSource(src); + m_minAltitude = ReadPrimitiveFromSource(src); + m_featureTableOffset = ReadPrimitiveFromSource(src); + m_altitudesOffset = ReadPrimitiveFromSource(src); + m_endOffset = ReadPrimitiveFromSource(src); } // Methods below return sizes of parts of altitude section in bytes. - static size_t GetHeaderSize() { return sizeof(AltitudeHeader); } - - size_t GetAltitudeAvailabilitySize() const { return featureTableOffset - GetHeaderSize(); } - size_t GetFeatureTableSize() const { return altitudeInfoOffset - featureTableOffset; } - size_t GetAltitudeInfo() const { return endOffset - altitudeInfoOffset; } + size_t GetAltitudeAvailabilitySize() const { return m_featureTableOffset - sizeof(AltitudeHeader); } + size_t GetFeatureTableSize() const { return m_altitudesOffset - m_featureTableOffset; } + size_t GetAltitudeInfo() const { return m_endOffset - m_altitudesOffset; } void Reset() { - version = 1; - minAltitude = kInvalidAltitude; - featureTableOffset = 0; - altitudeInfoOffset = 0; - endOffset = 0; + m_version = 0; + m_minAltitude = kInvalidAltitude; + m_featureTableOffset = 0; + m_altitudesOffset = 0; + m_endOffset = 0; } - TAltitudeSectionVersion version; - TAltitude minAltitude; - TAltitudeSectionOffset featureTableOffset; - TAltitudeSectionOffset altitudeInfoOffset; - TAltitudeSectionOffset endOffset; + TAltitudeSectionVersion m_version; + TAltitude m_minAltitude; + uint32_t m_featureTableOffset; + uint32_t m_altitudesOffset; + uint32_t m_endOffset; }; -class Altitude +static_assert(sizeof(AltitudeHeader) == 16, "Wrong header size of altitude section."); + +class Altitudes { public: - Altitude() = default; - explicit Altitude(TAltitudes const & altitudes) : m_altitudes(altitudes) {} + Altitudes() = default; + explicit Altitudes(TAltitudes const & altitudes) : m_altitudes(altitudes) {} template void Serialize(TAltitude minAltitude, TSink & sink) const { CHECK(!m_altitudes.empty(), ()); - WriteVarInt(sink, static_cast(m_altitudes[0] - static_cast(minAltitude))); + WriteVarInt(sink, static_cast(m_altitudes[0]) - static_cast(minAltitude)); for (size_t i = 1; i < m_altitudes.size(); ++i) WriteVarInt(sink, static_cast(m_altitudes[i]) - static_cast(m_altitudes[i - 1])); } @@ -94,17 +95,17 @@ public: } m_altitudes.resize(pointCount); - TAltitude prevPntAltitude = minAltitude; + TAltitude prevAltitude = minAltitude; for (size_t i = 0; i < pointCount; ++i) { - m_altitudes[i] = static_cast(ReadVarInt(src) + prevPntAltitude); + m_altitudes[i] = static_cast(ReadVarInt(src) + prevAltitude); if (m_altitudes[i] < minAltitude) { ASSERT(false, ()); m_altitudes.clear(); return; } - prevPntAltitude = m_altitudes[i]; + prevAltitude = m_altitudes[i]; } } @@ -114,7 +115,7 @@ public: } private: - /// \note |m_altitudes| is a vector of feature point altitudes. There's two posibilities: + /// \note |m_altitudes| is a vector of feature point altitudes. There's two possibilities: /// * |m_altitudes| is empty. It means there is no altitude information for this feature. /// * size of |m_pointAlt| is equal to the number of this feature's points. /// In this case the i'th element of |m_pointAlt| corresponds to the altitude of the diff --git a/routing/features_road_graph.cpp b/routing/features_road_graph.cpp index 1dc3c38a25..f915d4c3ab 100644 --- a/routing/features_road_graph.cpp +++ b/routing/features_road_graph.cpp @@ -38,6 +38,14 @@ string GetFeatureCountryName(FeatureID const featureId) } } // namespace +FeaturesRoadGraph::Value::Value(MwmSet::MwmHandle && handle) + : m_mwmHandle(move(handle)) +{ + if (!m_mwmHandle.IsAlive()) + return; + + m_altitudeLoader = make_unique(*m_mwmHandle.GetValue()); +} FeaturesRoadGraph::CrossCountryVehicleModel::CrossCountryVehicleModel(unique_ptr && vehicleModelFactory) : m_vehicleModelFactory(move(vehicleModelFactory)) @@ -257,24 +265,25 @@ double FeaturesRoadGraph::GetSpeedKMPHFromFt(FeatureType const & ft) const void FeaturesRoadGraph::ExtractRoadInfo(FeatureID const & featureId, FeatureType const & ft, double speedKMPH, RoadInfo & ri) const { - Value const & value = LockFeatureMwm(featureId); + Value const & value = LockMwm(featureId.m_mwmId); if (!value.IsAlive()) - { - ASSERT(false, ()); return; - } ri.m_bidirectional = !IsOneWay(ft); ri.m_speedKMPH = speedKMPH; ft.ParseGeometry(FeatureType::BEST_GEOMETRY); - feature::TAltitudes altitudes = value.altitudeLoader->GetAltitudes(featureId.m_index, ft.GetPointsCount()); - size_t const pointsCount = ft.GetPointsCount(); - if (altitudes.size() != pointsCount) + + feature::TAltitudes altitudes; + if (value.HasAltitudeLoader()) { - ASSERT(false, ("altitudes.size is different from ft.GetPointsCount()")); - altitudes.clear(); + altitudes = value.m_altitudeLoader->GetAltitudes(featureId.m_index, ft.GetPointsCount()); + if (altitudes.size() != pointsCount) + { + ASSERT(false, ("altitudes.size() is different from ft.GetPointsCount()")); + altitudes.clear(); + } } ri.m_junctions.clear(); @@ -325,9 +334,8 @@ IRoadGraph::RoadInfo const & FeaturesRoadGraph::GetCachedRoadInfo(FeatureID cons return ri; } -FeaturesRoadGraph::Value const & FeaturesRoadGraph::LockFeatureMwm(FeatureID const & featureId) const +FeaturesRoadGraph::Value const & FeaturesRoadGraph::LockMwm(MwmSet::MwmId const & mwmId) const { - MwmSet::MwmId mwmId = featureId.m_mwmId; ASSERT(mwmId.IsAlive(), ()); auto const itr = m_mwmLocks.find(mwmId); diff --git a/routing/features_road_graph.hpp b/routing/features_road_graph.hpp index e45495adf3..63800328b5 100644 --- a/routing/features_road_graph.hpp +++ b/routing/features_road_graph.hpp @@ -82,24 +82,20 @@ private: struct Value { Value() = default; - explicit Value(MwmSet::MwmHandle && handle) - : mwmHandle(move(handle)) - { - if (!mwmHandle.IsAlive()) - { - ASSERT(false, ()); - return; - } - altitudeLoader = make_unique(*mwmHandle.GetValue()); - } + explicit Value(MwmSet::MwmHandle && handle); bool IsAlive() const { - return mwmHandle.IsAlive() && altitudeLoader && altitudeLoader->IsAvailable(); + return m_mwmHandle.IsAlive(); } - MwmSet::MwmHandle mwmHandle; - unique_ptr altitudeLoader; + bool HasAltitudeLoader() const + { + return m_altitudeLoader && m_altitudeLoader->HasAltitudes(); + } + + MwmSet::MwmHandle m_mwmHandle; + unique_ptr m_altitudeLoader; }; bool IsRoad(FeatureType const & ft) const; @@ -116,7 +112,7 @@ private: void ExtractRoadInfo(FeatureID const & featureId, FeatureType const & ft, double speedKMPH, RoadInfo & ri) const; - Value const & LockFeatureMwm(FeatureID const & featureId) const; + Value const & LockMwm(MwmSet::MwmId const & mwmId) const; Index const & m_index; IRoadGraph::Mode const m_mode; diff --git a/routing/road_graph.cpp b/routing/road_graph.cpp index c362365400..db32e7d486 100644 --- a/routing/road_graph.cpp +++ b/routing/road_graph.cpp @@ -390,12 +390,10 @@ void IRoadGraph::GetEdgeTypes(Edge const & edge, feature::TypesHolder & types) c IRoadGraph::RoadInfo MakeRoadInfoForTesting(bool bidirectional, double speedKMPH, initializer_list const & points) { - buffer_vector junctions; - for (auto const & p : points) - junctions.emplace_back(MakeJunctionForTesting(p)); - IRoadGraph::RoadInfo ri(bidirectional, speedKMPH, {}); - ri.m_junctions.swap(junctions); + for (auto const & p : points) + ri.m_junctions.emplace_back(MakeJunctionForTesting(p)); + return ri; } } // namespace routing