diff --git a/generator/altitude_generator.cpp b/generator/altitude_generator.cpp index 27732297ef..156e6bb717 100644 --- a/generator/altitude_generator.cpp +++ b/generator/altitude_generator.cpp @@ -79,12 +79,14 @@ public: } TFeatureAltitudes const & GetFeatureAltitudes() const { return m_featureAltitudes; } + succinct::bit_vector_builder & GetAltitudeAvailabilityBuilder() { return m_altitudeAvailabilityBuilder; } TAltitude GetMinAltitude() const { return m_minAltitude; } + void operator()(FeatureType const & f, uint32_t const & id) { if (id != m_altitudeAvailabilityBuilder.size()) diff --git a/indexer/altitude_loader.cpp b/indexer/altitude_loader.cpp index 7109338fcf..7624ae2d33 100644 --- a/indexer/altitude_loader.cpp +++ b/indexer/altitude_loader.cpp @@ -53,12 +53,13 @@ AltitudeLoader::AltitudeLoader(MwmValue const & mwmValue) } bool AltitudeLoader::HasAltitudes() const { return m_header.m_minAltitude != kInvalidAltitude; } + TAltitudes const & AltitudeLoader::GetAltitudes(uint32_t featureId, size_t pointCount) { if (!HasAltitudes()) { // The version of mwm is less than version::Format::v8 or there's no altitude section in mwm. - return m_dummy; + return m_cache.insert(make_pair(featureId, TAltitudes(pointCount, kDefautlAltitudeMeters))).first->second; } auto const it = m_cache.find(featureId); @@ -68,7 +69,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, m_dummy)).first->second; + return m_cache.insert(make_pair(featureId, TAltitudes(pointCount, m_header.m_minAltitude))).first->second; } uint64_t const r = m_altitudeAvailability.rank(featureId); @@ -81,17 +82,26 @@ TAltitudes const & AltitudeLoader::GetAltitudes(uint32_t featureId, size_t point try { - Altitudes a; + Altitudes altitudes; ReaderSource src(*m_reader); src.Skip(altitudeInfoOffsetInSection); - a.Deserialize(m_header.m_minAltitude, pointCount, src); + altitudes.Deserialize(m_header.m_minAltitude, pointCount, src); - return m_cache.insert(make_pair(featureId, a.GetAltitudes())).first->second; + TAltitudes pntAlt = altitudes.GetAltitudes(); + bool const isResultValid = none_of(pntAlt.begin(), pntAlt.end(), + [](TAltitude a) { return a == kInvalidAltitude; }); + if (!isResultValid) + { + ASSERT(false, (pntAlt)); + return m_cache.insert(make_pair(featureId, TAltitudes(pointCount, m_header.m_minAltitude))).first->second; + } + + return m_cache.insert(make_pair(featureId, move(pntAlt))).first->second; } catch (Reader::OpenException const & e) { LOG(LERROR, ("Error while getting altitude data", e.Msg())); - return m_cache.insert(make_pair(featureId, m_dummy)).first->second; + return m_cache.insert(make_pair(featureId, TAltitudes(pointCount, m_header.m_minAltitude))).first->second; } } } // namespace feature diff --git a/indexer/altitude_loader.hpp b/indexer/altitude_loader.hpp index 15abf0cb73..a411512667 100644 --- a/indexer/altitude_loader.hpp +++ b/indexer/altitude_loader.hpp @@ -16,10 +16,13 @@ class AltitudeLoader public: explicit AltitudeLoader(MwmValue const & mwmValue); + /// \returns altitude of feature with |featureId|. All items of the returned vertor are valid + /// or the returned vertor is empty. TAltitudes const & GetAltitudes(uint32_t featureId, size_t pointCount); - bool HasAltitudes() const; private: + bool HasAltitudes() const; + unique_ptr m_altitudeAvailabilityRegion; unique_ptr m_featureTableRegion; @@ -28,7 +31,6 @@ private: unique_ptr m_reader; map m_cache; - TAltitudes const m_dummy; AltitudeHeader m_header; }; } // namespace feature diff --git a/indexer/feature_altitude.hpp b/indexer/feature_altitude.hpp index 2c4c6c140b..45874fc5ff 100644 --- a/indexer/feature_altitude.hpp +++ b/indexer/feature_altitude.hpp @@ -15,6 +15,7 @@ using TAltitude = int16_t; using TAltitudes = vector; TAltitude constexpr kInvalidAltitude = numeric_limits::min(); +feature::TAltitude constexpr kDefautlAltitudeMeters = 0; struct AltitudeHeader { @@ -50,10 +51,11 @@ struct AltitudeHeader size_t GetFeatureTableSize() const { return m_altitudesOffset - m_featureTableOffset; } size_t GetAltitudeInfo() const { return m_endOffset - m_altitudesOffset; } + void Reset() { m_version = 0; - m_minAltitude = kInvalidAltitude; + m_minAltitude = kDefautlAltitudeMeters; m_featureTableOffset = 0; m_altitudesOffset = 0; m_endOffset = 0; @@ -117,10 +119,8 @@ public: private: /// \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 - /// i'th point of the feature and is set to kInvalidAltitude when there is no information about - /// the point. + /// * size of |m_pointAlt| is equal to the number of this feature's points. If so + /// all items of |m_altitudes| have valid value. TAltitudes m_altitudes; }; } // namespace feature diff --git a/routing/features_road_graph.cpp b/routing/features_road_graph.cpp index df7f85c325..eee98a85ee 100644 --- a/routing/features_road_graph.cpp +++ b/routing/features_road_graph.cpp @@ -275,25 +275,23 @@ void FeaturesRoadGraph::ExtractRoadInfo(FeatureID const & featureId, FeatureType size_t const pointsCount = ft.GetPointsCount(); feature::TAltitudes altitudes; - if (value.HasAltitudeLoader()) + if (value.m_altitudeLoader) { 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(); - } + } + else + { + ASSERT(false, ()); + altitudes = feature::TAltitudes(ft.GetPointsCount(), feature::kDefautlAltitudeMeters); } - ri.m_junctions.clear(); + CHECK_EQUAL(altitudes.size(), pointsCount, + ("altitudeLoader->GetAltitudes(", featureId.m_index, "...) returns wrong alititudes:", + altitudes)); + ri.m_junctions.resize(pointsCount); for (size_t i = 0; i < pointsCount; ++i) - { - if (altitudes.empty()) - ri.m_junctions[i] = Junction(ft.GetPoint(i), feature::kInvalidAltitude); - else - ri.m_junctions[i] = Junction(ft.GetPoint(i), altitudes[i]); - } + ri.m_junctions[i] = Junction(ft.GetPoint(i), altitudes[i]); } IRoadGraph::RoadInfo const & FeaturesRoadGraph::GetCachedRoadInfo(FeatureID const & featureId) const diff --git a/routing/features_road_graph.hpp b/routing/features_road_graph.hpp index d160f941e4..59309e7bfb 100644 --- a/routing/features_road_graph.hpp +++ b/routing/features_road_graph.hpp @@ -86,8 +86,6 @@ private: bool IsAlive() const { return m_mwmHandle.IsAlive(); } - bool HasAltitudeLoader() const { return m_altitudeLoader && m_altitudeLoader->HasAltitudes(); } - MwmSet::MwmHandle m_mwmHandle; unique_ptr m_altitudeLoader; }; diff --git a/routing/routing_algorithm.cpp b/routing/routing_algorithm.cpp index 3495ef8b02..773bd38be3 100644 --- a/routing/routing_algorithm.cpp +++ b/routing/routing_algorithm.cpp @@ -19,13 +19,11 @@ double constexpr KMPH2MPS = 1000.0 / (60 * 60); inline double TimeBetweenSec(Junction const & j1, Junction const & j2, double speedMPS) { ASSERT(speedMPS > 0.0, ()); - double const distanceM = MercatorBounds::DistanceOnEarth(j1.GetPoint(), j2.GetPoint()); - feature::TAltitude const j1Altitude = j1.GetAltitude(); - feature::TAltitude const j2Altitude = j2.GetAltitude(); - if (j1Altitude == feature::kInvalidAltitude || j2Altitude == feature::kInvalidAltitude) - return distanceM / speedMPS; + ASSERT_NOT_EQUAL(j1.GetAltitude(), feature::kInvalidAltitude, ()); + ASSERT_NOT_EQUAL(j2.GetAltitude(), feature::kInvalidAltitude, ()); - feature::TAltitude const altidudeDiffM = j2Altitude - j1Altitude; + double const distanceM = MercatorBounds::DistanceOnEarth(j1.GetPoint(), j2.GetPoint()); + feature::TAltitude const altidudeDiffM = j2.GetAltitude() - j1.GetAltitude(); return sqrt(distanceM * distanceM + altidudeDiffM * altidudeDiffM) / speedMPS; }