diff --git a/libs/drape_frontend/rule_drawer.cpp b/libs/drape_frontend/rule_drawer.cpp index a59e4180c..d82670128 100644 --- a/libs/drape_frontend/rule_drawer.cpp +++ b/libs/drape_frontend/rule_drawer.cpp @@ -353,7 +353,7 @@ void RuleDrawer::ProcessLineStyle(FeatureType & f, Stylist const & s, TInsertSha df::RoadClass m_roadClass; }; static Checker const checkers[] = { - {{HighwayClass::Trunk, HighwayClass::Primary}, kRoadClass0ZoomLevel, df::RoadClass::Class0}, + {{HighwayClass::Motorway, HighwayClass::Trunk, HighwayClass::Primary}, kRoadClass0ZoomLevel, df::RoadClass::Class0}, {{HighwayClass::Secondary, HighwayClass::Tertiary}, kRoadClass1ZoomLevel, df::RoadClass::Class1}, {{HighwayClass::LivingStreet, HighwayClass::Service, HighwayClass::ServiceMinor}, kRoadClass2ZoomLevel, diff --git a/libs/indexer/ftypes_matcher.cpp b/libs/indexer/ftypes_matcher.cpp index 5cced2376..ef32d51e6 100644 --- a/libs/indexer/ftypes_matcher.cpp +++ b/libs/indexer/ftypes_matcher.cpp @@ -30,8 +30,8 @@ public: m_map[c.GetTypeByPath({"route", "ferry"})] = HighwayClass::Transported; m_map[c.GetTypeByPath({"route", "shuttle_train"})] = HighwayClass::Transported; - m_map[c.GetTypeByPath({"highway", "motorway"})] = HighwayClass::Trunk; - m_map[c.GetTypeByPath({"highway", "motorway_link"})] = HighwayClass::Trunk; + m_map[c.GetTypeByPath({"highway", "motorway"})] = HighwayClass::Motorway; + m_map[c.GetTypeByPath({"highway", "motorway_link"})] = HighwayClass::Motorway; m_map[c.GetTypeByPath({"highway", "trunk"})] = HighwayClass::Trunk; m_map[c.GetTypeByPath({"highway", "trunk_link"})] = HighwayClass::Trunk; @@ -83,6 +83,7 @@ char const * HighwayClassToString(HighwayClass const cls) { case HighwayClass::Undefined: return "Undefined"; case HighwayClass::Transported: return "Transported"; + case HighwayClass::Motorway: return "Motorway"; case HighwayClass::Trunk: return "Trunk"; case HighwayClass::Primary: return "Primary"; case HighwayClass::Secondary: return "Secondary"; diff --git a/libs/indexer/ftypes_matcher.hpp b/libs/indexer/ftypes_matcher.hpp index 008ca54c0..94bd2eafe 100644 --- a/libs/indexer/ftypes_matcher.hpp +++ b/libs/indexer/ftypes_matcher.hpp @@ -674,6 +674,7 @@ uint64_t GetPopulationByRadius(double r); enum class HighwayClass { Undefined = 0, // There has not been any attempt of calculating HighwayClass. + Motorway, Trunk, Primary, Secondary, diff --git a/libs/indexer/indexer_tests/checker_test.cpp b/libs/indexer/indexer_tests/checker_test.cpp index 7b3d1c18d..d09058027 100644 --- a/libs/indexer/indexer_tests/checker_test.cpp +++ b/libs/indexer/indexer_tests/checker_test.cpp @@ -107,7 +107,7 @@ UNIT_TEST(GetHighwayClassTest) feature::TypesHolder types2; types2.Add(c.GetTypeByPath({"highway", "motorway_link", "tunnel"})); - TEST_EQUAL(ftypes::GetHighwayClass(types2), ftypes::HighwayClass::Trunk, ()); + TEST_EQUAL(ftypes::GetHighwayClass(types2), ftypes::HighwayClass::Motorway, ()); feature::TypesHolder types3; types3.Add(c.GetTypeByPath({"highway", "unclassified"})); diff --git a/libs/indexer/road_shields_parser.cpp b/libs/indexer/road_shields_parser.cpp index af8cfb325..2fae4f449 100644 --- a/libs/indexer/road_shields_parser.cpp +++ b/libs/indexer/road_shields_parser.cpp @@ -94,7 +94,7 @@ class RoadShieldParser public: explicit RoadShieldParser(std::string const & baseRoadNumber) : m_baseRoadNumber(baseRoadNumber) {} virtual ~RoadShieldParser() = default; - virtual RoadShield ParseRoadShield(std::string_view rawText) const = 0; + virtual RoadShield ParseRoadShield(std::string_view rawText, uint8_t index) const = 0; RoadShieldType FindNetworkShield(std::string network) const { @@ -127,18 +127,20 @@ public: RoadShieldsSetT GetRoadShields() const { RoadShieldsSetT result, defaultShields; - + + uint8_t index = 0; strings::Tokenize(m_baseRoadNumber, ";", [&](std::string_view rawText) { + ++index; RoadShield shield; auto slashPos = rawText.find('/'); if (slashPos == std::string::npos) { - shield = ParseRoadShield(rawText); + shield = ParseRoadShield(rawText, index); } else { - shield = ParseRoadShield(rawText.substr(slashPos + 1)); + shield = ParseRoadShield(rawText.substr(slashPos + 1), index); // TODO: use a network-based shield type override only if a parser couldn't make it // more specific than country's default shield type. // E.g. "94" is set to Generic_Orange by Estonia parser, but then @@ -176,7 +178,7 @@ class USRoadShieldParser : public RoadShieldParser { public: explicit USRoadShieldParser(std::string const & baseRoadNumber) : RoadShieldParser(baseRoadNumber) {} - RoadShield ParseRoadShield(std::string_view rawText) const override + RoadShield ParseRoadShield(std::string_view rawText, uint8_t index) const override { std::string shieldText(rawText); @@ -236,7 +238,7 @@ class IndiaRoadShieldParser : public RoadShieldParser { public: explicit IndiaRoadShieldParser(std::string const & baseRoadNumber) : RoadShieldParser(baseRoadNumber) {} - RoadShield ParseRoadShield(std::string_view rawText) const override + RoadShield ParseRoadShield(std::string_view rawText, uint8_t index) const override { std::string shieldText(rawText); @@ -269,7 +271,7 @@ public: , m_type(defaultType) {} - RoadShield ParseRoadShield(std::string_view rawText) const override + RoadShield ParseRoadShield(std::string_view rawText, uint8_t index) const override { if (rawText.size() > kMaxRoadShieldBytesSize) return RoadShield(); @@ -304,7 +306,7 @@ public: , m_defaultType(defaultType) {} - RoadShield ParseRoadShield(std::string_view rawText) const override + RoadShield ParseRoadShield(std::string_view rawText, uint8_t index) const override { if (rawText.size() > kMaxRoadShieldBytesSize) return RoadShield(); @@ -329,6 +331,72 @@ private: RoadShieldType const m_defaultType; }; +// Matches by a list of given highway classes for the first shield. +// Falls back to matching by a list of given substrings (identical to SimpleRoadShieldParser) for all other shields. +class HighwayClassRoadShieldParser : public RoadShieldParser +{ +public: + struct Entry + { + Entry() = default; + Entry(std::string_view name, HighwayClass highwayClass, RoadShieldType type, bool isRedundant = false) : m_name(name), m_highwayClass(highwayClass), m_type(type), m_isRedundant(isRedundant) {} + + std::string_view m_name; + HighwayClass m_highwayClass = HighwayClass::Undefined; + RoadShieldType m_type = RoadShieldType::Default; + /* Hides a specific secondary etc. sign, if there is a primary one */ + bool m_isRedundant = false; + }; + + using ShieldTypes = buffer_vector; + + HighwayClassRoadShieldParser(std::string const & baseRoadNumber, HighwayClass highwayClass, ShieldTypes && types, RoadShieldType defaultType = RoadShieldType::Default) + : RoadShieldParser(baseRoadNumber) + , m_highwayClass(highwayClass) + , m_types(std::move(types)) + , m_defaultType(defaultType) + {} + + RoadShield ParseRoadShield(std::string_view rawText, uint8_t index) const override + { + if (rawText.size() > kMaxRoadShieldBytesSize) + return RoadShield(); + + RoadShieldType type = m_defaultType; + if (index == 1) { + for (auto const & p : m_types) + { + if (p.m_highwayClass == m_highwayClass) + { + return RoadShield(p.m_type, rawText); + } + } + } else { + size_t idx = std::numeric_limits::max(); + for (auto const & p : m_types) + { + auto const i = rawText.find(p.m_name); + if (i != std::string::npos && i < idx) + { + if (p.m_isRedundant) { + type = RoadShieldType::Hidden; + } else { + type = p.m_type; + } + idx = i; + } + } + } + + return {type, rawText}; + } + +private: + HighwayClass const m_highwayClass; + ShieldTypes const m_types; + RoadShieldType const m_defaultType; +}; + uint16_t constexpr kAnyHigherRoadNumber = std::numeric_limits::max(); // Matches by a list of numeric ranges (a first matching range is used). @@ -354,7 +422,7 @@ public: , m_types(std::move(types)) {} - RoadShield ParseRoadShield(std::string_view rawText) const override + RoadShield ParseRoadShield(std::string_view rawText, uint8_t index) const override { if (rawText.size() > kMaxRoadShieldBytesSize) return RoadShield(); @@ -403,7 +471,7 @@ public: , m_defaultType(defaultType) {} - RoadShield ParseRoadShield(std::string_view rawText) const override + RoadShield ParseRoadShield(std::string_view rawText, uint8_t index) const override { uint32_t constexpr kMaxRoadShieldSymbolsSize = 4 * kMaxRoadShieldBytesSize; @@ -429,14 +497,15 @@ private: // Implementations of "ref" parses for some countries. -class AustriaRoadShieldParser : public SimpleRoadShieldParser +class AustriaRoadShieldParser : public HighwayClassRoadShieldParser { public: - explicit AustriaRoadShieldParser(std::string const & baseRoadNumber) - : SimpleRoadShieldParser(baseRoadNumber, {{"A", RoadShieldType::Generic_Blue_Bordered}, - {"S", RoadShieldType::Generic_Blue_Bordered}, - {"B", RoadShieldType::Generic_Blue}, - {"L", RoadShieldType::Generic_Pill_White_Bordered}}) + explicit AustriaRoadShieldParser(std::string const & baseRoadNumber, HighwayClass const & highwayClass) + : HighwayClassRoadShieldParser(baseRoadNumber, highwayClass, + {{"A", HighwayClass::Motorway, RoadShieldType::Generic_Blue_Bordered}, + {"S", HighwayClass::Trunk, RoadShieldType::Generic_Blue_Bordered}, + {"B", HighwayClass::Primary, RoadShieldType::Generic_Blue}, + {"L", HighwayClass::Secondary, RoadShieldType::Generic_Pill_White_Bordered}}) {} }; @@ -585,11 +654,16 @@ public: {} }; -class UKRoadShieldParser : public SimpleRoadShieldParser +class UKRoadShieldParser : public HighwayClassRoadShieldParser { public: - explicit UKRoadShieldParser(std::string const & baseRoadNumber) - : SimpleRoadShieldParser(baseRoadNumber, {{"M", RoadShieldType::Generic_Blue}, {"A", RoadShieldType::UK_Highway}}) + explicit UKRoadShieldParser(std::string const & baseRoadNumber, HighwayClass const & highwayClass) + : HighwayClassRoadShieldParser(baseRoadNumber, highwayClass, + {{"M", HighwayClass::Motorway, RoadShieldType::Generic_Blue, true}, + {"E", HighwayClass::Motorway, RoadShieldType::Hidden}, + {"A", HighwayClass::Trunk, RoadShieldType::UK_Highway, true}, + {"A", HighwayClass::Primary, RoadShieldType::Generic_White_Bordered}, + {"B", HighwayClass::Secondary, RoadShieldType::Generic_White_Bordered}}) {} }; @@ -605,14 +679,17 @@ public: {} }; -class GermanyRoadShieldParser : public SimpleRoadShieldParser +class GermanyRoadShieldParser : public HighwayClassRoadShieldParser { public: - explicit GermanyRoadShieldParser(std::string const & baseRoadNumber) - : SimpleRoadShieldParser(baseRoadNumber, {{"A", RoadShieldType::Highway_Hexagon_Blue}, - {"B", RoadShieldType::Generic_Orange_Bordered}, - {"L", RoadShieldType::Generic_White_Bordered}, - {"K", RoadShieldType::Generic_White_Bordered}}) + explicit GermanyRoadShieldParser(std::string const & baseRoadNumber, HighwayClass const & highwayClass) + : HighwayClassRoadShieldParser(baseRoadNumber, highwayClass, + {{"A", HighwayClass::Motorway, RoadShieldType::Highway_Hexagon_Blue}, + {"D", HighwayClass::Motorway, RoadShieldType::Hidden}, + {"B", HighwayClass::Trunk, RoadShieldType::Generic_Orange_Bordered}, + {"B", HighwayClass::Primary, RoadShieldType::Generic_Orange_Bordered}, + {"L", HighwayClass::Secondary, RoadShieldType::Generic_White_Bordered}, + {"K", HighwayClass::Secondary, RoadShieldType::Generic_White_Bordered}}) {} }; @@ -719,7 +796,7 @@ class MexicoRoadShieldParser : public RoadShieldParser public: explicit MexicoRoadShieldParser(std::string const & baseRoadNumber) : RoadShieldParser(baseRoadNumber) {} - RoadShield ParseRoadShield(std::string_view rawText) const override + RoadShield ParseRoadShield(std::string_view rawText, uint8_t index) const override { std::string shieldText(rawText); @@ -762,6 +839,10 @@ RoadShieldsSetT GetRoadShields(FeatureType & f) if (ref.empty()) return {}; + auto const & highwayClass = ftypes::GetHighwayClass(feature::TypesHolder(f)); + if (highwayClass == HighwayClass::Undefined) + return {}; + // Find out country name. std::string mwmName = f.GetID().GetMwmName(); ASSERT(!mwmName.empty(), (f.GetID())); @@ -770,19 +851,19 @@ RoadShieldsSetT GetRoadShields(FeatureType & f) if (underlinePos != std::string::npos) mwmName = mwmName.substr(0, underlinePos); - return GetRoadShields(mwmName, ref); + return GetRoadShields(mwmName, ref, highwayClass); } -RoadShieldsSetT GetRoadShields(std::string const & mwmName, std::string const & roadNumber) +RoadShieldsSetT GetRoadShields(std::string const & mwmName, std::string const & roadNumber, HighwayClass const & highwayClass) { if (mwmName == "US") return USRoadShieldParser(roadNumber).GetRoadShields(); if (mwmName == "UK") - return UKRoadShieldParser(roadNumber).GetRoadShields(); + return UKRoadShieldParser(roadNumber, highwayClass).GetRoadShields(); if (mwmName == "India") return IndiaRoadShieldParser(roadNumber).GetRoadShields(); if (mwmName == "Austria") - return AustriaRoadShieldParser(roadNumber).GetRoadShields(); + return AustriaRoadShieldParser(roadNumber, highwayClass).GetRoadShields(); if (mwmName == "Belgium") return BelgiumRoadShieldParser(roadNumber).GetRoadShields(); if (mwmName == "Greece") @@ -816,7 +897,7 @@ RoadShieldsSetT GetRoadShields(std::string const & mwmName, std::string const & if (mwmName == "France") return FranceRoadShieldParser(roadNumber).GetRoadShields(); if (mwmName == "Germany") - return GermanyRoadShieldParser(roadNumber).GetRoadShields(); + return GermanyRoadShieldParser(roadNumber, highwayClass).GetRoadShields(); if (mwmName == "Spain") return SpainRoadShieldParser(roadNumber).GetRoadShields(); if (mwmName == "Ukraine") diff --git a/libs/indexer/road_shields_parser.hpp b/libs/indexer/road_shields_parser.hpp index 30c5eff85..5d93f32db 100644 --- a/libs/indexer/road_shields_parser.hpp +++ b/libs/indexer/road_shields_parser.hpp @@ -1,6 +1,7 @@ #pragma once #include "indexer/feature.hpp" +#include "indexer/ftypes_matcher.hpp" #include "geometry/rect2d.hpp" @@ -79,7 +80,7 @@ struct RoadShield // Use specific country road shield styles based on mwm feature belongs to. using RoadShieldsSetT = buffer_vector; RoadShieldsSetT GetRoadShields(FeatureType & f); -RoadShieldsSetT GetRoadShields(std::string const & mwmName, std::string const & roadNumber); +RoadShieldsSetT GetRoadShields(std::string const & mwmName, std::string const & roadNumber, HighwayClass const & highwayClass); // Simple parsing without specific country styles. RoadShieldsSetT GetRoadShields(std::string const & rawRoadNumber); diff --git a/libs/routing/turns_generator_utils.cpp b/libs/routing/turns_generator_utils.cpp index d2bfee835..c1ac92785 100644 --- a/libs/routing/turns_generator_utils.cpp +++ b/libs/routing/turns_generator_utils.cpp @@ -14,7 +14,7 @@ using namespace ftypes; bool IsHighway(HighwayClass hwClass, bool isLink) { - return (hwClass == HighwayClass::Trunk || hwClass == HighwayClass::Primary) && !isLink; + return (hwClass == HighwayClass::Motorway || hwClass == HighwayClass::Trunk || hwClass == HighwayClass::Primary) && !isLink; } bool IsSmallRoad(HighwayClass hwClass) @@ -102,6 +102,7 @@ double CalcEstimatedTimeToPass(double const distanceMeters, HighwayClass const h double speedKmph = 0; switch (highwayClass) { + case HighwayClass::Motorway: speedKmph = 100.0; break; case HighwayClass::Trunk: speedKmph = 100.0; break; case HighwayClass::Primary: speedKmph = 70.0; break; case HighwayClass::Secondary: speedKmph = 70.0; break; diff --git a/tools/openlr/helpers.cpp b/tools/openlr/helpers.cpp index 52e9959b2..af13d7cfb 100644 --- a/tools/openlr/helpers.cpp +++ b/tools/openlr/helpers.cpp @@ -21,6 +21,7 @@ openlr::FunctionalRoadClass HighwayClassToFunctionalRoadClass(ftypes::HighwayCla { switch (hwClass) { + case ftypes::HighwayClass::Motorway: return openlr::FunctionalRoadClass::FRC0; case ftypes::HighwayClass::Trunk: return openlr::FunctionalRoadClass::FRC0; case ftypes::HighwayClass::Primary: return openlr::FunctionalRoadClass::FRC1; case ftypes::HighwayClass::Secondary: return openlr::FunctionalRoadClass::FRC2; @@ -48,11 +49,10 @@ optional GetFrcScore(Graph::Edge const & e, FunctionalRoadClass functiona switch (functionalRoadClass) { case FunctionalRoadClass::FRC0: - // Note. HighwayClass::Trunk means motorway, motorway_link, trunk or trunk_link. - return hwClass == HighwayClass::Trunk ? optional(kMaxScoreForFrc) : nullopt; + return hwClass == HighwayClass::Motorway || hwClass == HighwayClass::Trunk ? optional(kMaxScoreForFrc) : nullopt; case FunctionalRoadClass::FRC1: - return (hwClass == HighwayClass::Trunk || hwClass == HighwayClass::Primary) ? optional(kMaxScoreForFrc) + return (HighwayClass::Motorway || hwClass == HighwayClass::Trunk || hwClass == HighwayClass::Primary) ? optional(kMaxScoreForFrc) : nullopt; case FunctionalRoadClass::FRC2: