diff options
author | Ilya Zverev <zverik@textual.ru> | 2017-03-30 12:17:22 +0300 |
---|---|---|
committer | Ilya Zverev <zverik@textual.ru> | 2017-04-05 14:06:04 +0300 |
commit | 008e27dee3830c2dab0383773918e6f63ad4a9e7 (patch) | |
tree | eeda7340d013e8774914268f0d7299c9621fdd76 /indexer/road_shields_parser.cpp | |
parent | 60a583044afd78f89f4dfab29d356f4b86f16019 (diff) |
[shields] Process road networks on relations
Diffstat (limited to 'indexer/road_shields_parser.cpp')
-rw-r--r-- | indexer/road_shields_parser.cpp | 329 |
1 files changed, 261 insertions, 68 deletions
diff --git a/indexer/road_shields_parser.cpp b/indexer/road_shields_parser.cpp index cead636a21..50fe93fc28 100644 --- a/indexer/road_shields_parser.cpp +++ b/indexer/road_shields_parser.cpp @@ -16,9 +16,7 @@ using ftypes::RoadShieldType; uint32_t constexpr kMaxRoadShieldBytesSize = 8; -std::array<std::string, 3> const kFederalCode = {{ - "US", "SR", "FSR" -}}; +std::array<std::string, 3> const kFederalCode = {{"US", "SR", "FSR"}}; std::array<std::string, 60> const kStatesCode = {{ "AL", "AK", "AZ", "AR", "CA", "CO", "CT", "DE", "DC", "FL", "GA", "HI", "ID", "IL", "IN", @@ -27,29 +25,92 @@ std::array<std::string, 60> const kStatesCode = {{ "VT", "VA", "WA", "WV", "WI", "WY", "AS", "GU", "MP", "PR", "VI", "UM", "FM", "MH", "PW", }}; -std::array<std::string, 13> const kModifiers = {{ - "alt", "alternate", "bus", "business", "bypass", "historic", "connector", - "loop", "scenic", "spur", "temporary", "toll", "truck" -}}; +std::array<std::string, 13> const kModifiers = {{"alt", "alternate", "bus", "business", "bypass", + "historic", "connector", "loop", "scenic", "spur", + "temporary", "toll", "truck"}}; + +// Shields based on a network tag in a route=road relation. +std::unordered_map<std::string, RoadShieldType> const kRoadNetworkShields = { + // International road networks. + {"e-road", RoadShieldType::Generic_Green}, // E 105 + {"asianhighway", RoadShieldType::Hidden}, // AH8. Blue, but usually not posted. + // National and regional networks for some countries. + {"ru:national", RoadShieldType::Generic_Blue}, + {"ru:regional", RoadShieldType::Generic_Blue}, + {"bg:national", RoadShieldType::Generic_Green}, + {"bg:regional", RoadShieldType::Generic_Blue}, + {"by:national", RoadShieldType::Generic_Red}, + {"by:regional", RoadShieldType::Generic_Red}, + {"co:national", RoadShieldType::Generic_White}, + {"cz:national", RoadShieldType::Generic_Red}, + {"cz:regional", RoadShieldType::Generic_Blue}, + {"ee:national", RoadShieldType::Generic_Red}, + {"ee:regional", RoadShieldType::Generic_White}, + {"fr:a-road", RoadShieldType::Generic_Red}, + {"jp:national", RoadShieldType::Generic_Blue}, + {"jp:regional", RoadShieldType::Generic_Blue}, + {"jp:prefectural", RoadShieldType::Generic_Blue}, + {"lt:national", RoadShieldType::Generic_Red}, + {"lt:regional", RoadShieldType::Generic_Blue}, + {"lv:national", RoadShieldType::Generic_Red}, + {"lv:regional", RoadShieldType::Generic_Blue}, + {"pl:national", RoadShieldType::Generic_Red}, + {"pl:regional", RoadShieldType::Generic_Orange}, + {"pl:local", RoadShieldType::Generic_White}, + {"ua:national", RoadShieldType::Generic_Blue}, + {"ua:regional", RoadShieldType::Generic_Blue}, + {"ua:territorial", RoadShieldType::Generic_White}, + {"ua:local", RoadShieldType::Generic_White}, + {"za:national", RoadShieldType::Generic_White}, + {"za:regional", RoadShieldType::Generic_White}, + // United States road networks. + {"us:i", RoadShieldType::US_Interstate}, + {"us:us", RoadShieldType::US_Highway}, + {"us:sr", RoadShieldType::US_Highway}, + {"us:fsr", RoadShieldType::US_Highway}, +}; class RoadShieldParser { public: - RoadShieldParser(std::string const & baseRoadNumber) - : m_baseRoadNumber(baseRoadNumber) - {} - virtual ~RoadShieldParser(){} - virtual RoadShield ParseRoadShield(std::string const & rawText) = 0; + explicit RoadShieldParser(std::string const & baseRoadNumber) : m_baseRoadNumber(baseRoadNumber) {} + virtual ~RoadShieldParser() {} + virtual RoadShield ParseRoadShield(std::string const & rawText) const = 0; + + RoadShieldType FindNetworkShield(std::string network) const + { + // Minimum length for the network tag is 4 (US:I). + if (network.size() > 4) + { + strings::AsciiToLower(network); - std::vector<RoadShield> GetRoadShields() + // Cut off suffixes after a semicolon repeatedly, until we find a relevant shield. + auto semicolonPos = network.size(); + while (semicolonPos != std::string::npos) + { + network.resize(semicolonPos); // cut off the ":xxx" suffix + auto const it = kRoadNetworkShields.find(network); + if (it != kRoadNetworkShields.cend()) + return it->second; + semicolonPos = network.rfind(':'); + } + } + return RoadShieldType::Default; + } + + std::set<RoadShield> GetRoadShields() const { - std::vector<RoadShield> result; + std::set<RoadShield> result; std::vector<std::string> shieldsRawTests = strings::Tokenize(m_baseRoadNumber, ";"); for (std::string const & rawText : shieldsRawTests) { - RoadShield shield = ParseRoadShield(rawText); - if (!shield.m_name.empty()) - result.push_back(std::move(shield)); + auto slashPos = rawText.find('/'); + RoadShield shield = slashPos == std::string::npos + ? ParseRoadShield(rawText) + : RoadShield{FindNetworkShield(rawText.substr(0, slashPos)), + rawText.substr(slashPos + 1)}; + if (!shield.m_name.empty() && shield.m_type != RoadShieldType::Hidden) + result.insert(std::move(shield)); } return result; } @@ -61,11 +122,8 @@ protected: class USRoadShieldParser : public RoadShieldParser { public: - USRoadShieldParser(std::string const & baseRoadNumber) - : RoadShieldParser(baseRoadNumber) - {} - - RoadShield ParseRoadShield(std::string const & rawText) override + USRoadShieldParser(std::string const & baseRoadNumber) : RoadShieldParser(baseRoadNumber) {} + RoadShield ParseRoadShield(std::string const & rawText) const override { std::string shieldText = rawText; @@ -94,7 +152,8 @@ public: if (shieldParts.size() <= 1) return RoadShield(RoadShieldType::Default, rawText); - std::string const & roadType = shieldParts[0]; // 'I' for interstates and kFederalCode/kStatesCode for highways. + std::string const & roadType = + shieldParts[0]; // 'I' for interstates and kFederalCode/kStatesCode for highways. std::string roadNumber = shieldParts[1]; std::string additionalInfo; if (shieldParts.size() >= 3) @@ -115,23 +174,44 @@ public: return RoadShield(RoadShieldType::US_Highway, roadNumber, additionalInfo); if (std::find(kStatesCode.begin(), kStatesCode.end(), shieldParts[0]) != kStatesCode.end()) - return RoadShield(RoadShieldType::Default, roadNumber, additionalInfo); + return RoadShield(RoadShieldType::Generic_White, roadNumber, additionalInfo); return RoadShield(RoadShieldType::Default, rawText); } }; +class DefaultTypeRoadShieldParser : public RoadShieldParser +{ +public: + DefaultTypeRoadShieldParser(std::string const & baseRoadNumber, + RoadShieldType const & defaultType) + : RoadShieldParser(baseRoadNumber), m_type(defaultType) + { + } + + RoadShield ParseRoadShield(std::string const & rawText) const override + { + if (rawText.size() > kMaxRoadShieldBytesSize) + return RoadShield(); + + return RoadShield(m_type, rawText); + } + +private: + RoadShieldType const m_type; +}; + class SimpleRoadShieldParser : public RoadShieldParser { public: using ShieldTypes = std::unordered_map<char, RoadShieldType>; SimpleRoadShieldParser(std::string const & baseRoadNumber, ShieldTypes const & types) - : RoadShieldParser(baseRoadNumber) - , m_types(types) - {} + : RoadShieldParser(baseRoadNumber), m_types(types) + { + } - RoadShield ParseRoadShield(std::string const & rawText) override + RoadShield ParseRoadShield(std::string const & rawText) const override { if (rawText.size() > kMaxRoadShieldBytesSize) return RoadShield(); @@ -149,32 +229,38 @@ private: ShieldTypes const m_types; }; -class UKRoadShieldParser : public SimpleRoadShieldParser +class NumericRoadShieldParser : public RoadShieldParser { public: - UKRoadShieldParser(std::string const & baseRoadNumber) - : SimpleRoadShieldParser(baseRoadNumber, {{'M', RoadShieldType::Generic_Blue}, {'A', RoadShieldType::UK_Highway}}) - {} -}; + // A map of {lower_bound, higher_bound} -> RoadShieldType. + using ShieldTypes = + std::vector<std::pair<std::pair<std::uint16_t, std::uint16_t>, RoadShieldType>>; -class RussiaRoadShieldParser : public RoadShieldParser -{ -public: - RussiaRoadShieldParser(std::string const & baseRoadNumber) - : RoadShieldParser(baseRoadNumber) - {} + NumericRoadShieldParser(std::string const & baseRoadNumber, ShieldTypes const & types) + : RoadShieldParser(baseRoadNumber), m_types(types) + { + } - RoadShield ParseRoadShield(std::string const & rawText) override + RoadShield ParseRoadShield(std::string const & rawText) const override { if (rawText.size() > kMaxRoadShieldBytesSize) return RoadShield(); - strings::UniString s = strings::MakeUniString(rawText); - if (s[0] == 'E' || s[0] == strings::UniChar(1045)) // Latin and cyrillic. - return RoadShield(RoadShieldType::Generic_Green, rawText); + std::uint64_t ref; + if (strings::to_uint64(rawText, ref)) + { + for (auto const & p : m_types) + { + if (p.first.first <= ref && ref <= p.first.second) + return RoadShield(p.second, rawText); + } + } - return RoadShield(RoadShieldType::Generic_Blue, rawText); + return RoadShield(RoadShieldType::Default, rawText); } + +private: + ShieldTypes const m_types; }; class SimpleUnicodeRoadShieldParser : public RoadShieldParser @@ -183,7 +269,7 @@ public: struct Name { Name(std::string const & simpleName, string const & unicodeName) - : m_simpleName(simpleName), m_unicodeName(strings::MakeUniString(unicodeName)) + : m_simpleName(simpleName), m_unicodeName(strings::MakeUniString(unicodeName)) { } @@ -194,11 +280,11 @@ public: using ShieldTypes = std::vector<std::pair<Name, RoadShieldType>>; SimpleUnicodeRoadShieldParser(std::string const & baseRoadNumber, ShieldTypes const & types) - : RoadShieldParser(baseRoadNumber), m_types(types) + : RoadShieldParser(baseRoadNumber), m_types(types) { } - RoadShield ParseRoadShield(std::string const & rawText) override + RoadShield ParseRoadShield(std::string const & rawText) const override { uint32_t constexpr kMaxRoadShieldSymbolsSize = 4 * kMaxRoadShieldBytesSize; @@ -215,7 +301,8 @@ public: auto const rawUnicode = strings::MakeUniString(rawText); auto const & unicodeName = name.m_unicodeName; - auto const it = std::search(rawUnicode.begin(), rawUnicode.end(), unicodeName.begin(), unicodeName.end()); + auto const it = + std::search(rawUnicode.begin(), rawUnicode.end(), unicodeName.begin(), unicodeName.end()); if (it != rawUnicode.end()) return RoadShield(type, rawText); } @@ -227,14 +314,56 @@ private: ShieldTypes const m_types; }; +// Implementations of "ref" parses for some countries. + +class RussiaRoadShieldParser : public DefaultTypeRoadShieldParser +{ +public: + RussiaRoadShieldParser(std::string const & baseRoadNumber) + : DefaultTypeRoadShieldParser(baseRoadNumber, RoadShieldType::Generic_Blue) + { + } +}; + +class SpainRoadShieldParser : public DefaultTypeRoadShieldParser +{ +public: + SpainRoadShieldParser(std::string const & baseRoadNumber) + : DefaultTypeRoadShieldParser(baseRoadNumber, RoadShieldType::Generic_Blue) + { + } +}; + +class UKRoadShieldParser : public SimpleRoadShieldParser +{ +public: + UKRoadShieldParser(std::string const & baseRoadNumber) + : SimpleRoadShieldParser( + baseRoadNumber, {{'M', RoadShieldType::Generic_Blue}, {'A', RoadShieldType::UK_Highway}}) + { + } +}; + class FranceRoadShieldParser : public SimpleRoadShieldParser { public: FranceRoadShieldParser(std::string const & baseRoadNumber) - : SimpleRoadShieldParser(baseRoadNumber, {{'A', RoadShieldType::Generic_Red}, - {'N', RoadShieldType::Generic_Red}, - {'E', RoadShieldType::Generic_Green}, - {'D', RoadShieldType::Generic_Orange}}) + : SimpleRoadShieldParser(baseRoadNumber, {{'A', RoadShieldType::Generic_Red}, + {'N', RoadShieldType::Generic_Red}, + {'E', RoadShieldType::Generic_Green}, + {'D', RoadShieldType::Generic_Orange}}) + { + } +}; + +class GermanyRoadShieldParser : public SimpleRoadShieldParser +{ +public: + GermanyRoadShieldParser(std::string const & baseRoadNumber) + : SimpleRoadShieldParser(baseRoadNumber, {{'A', RoadShieldType::Generic_Blue}, + {'B', RoadShieldType::Generic_Orange}, + {'L', RoadShieldType::Generic_White}, + {'K', RoadShieldType::Generic_White}}) { } }; @@ -244,10 +373,11 @@ class UkraineRoadShieldParser : public SimpleUnicodeRoadShieldParser public: // The second parameter in the constructor is a cyrillic symbol. UkraineRoadShieldParser(std::string const & baseRoadNumber) - : SimpleUnicodeRoadShieldParser(baseRoadNumber, {{Name("M", "М"), RoadShieldType::Generic_Blue}, - {Name("H", "Н"), RoadShieldType::Generic_Blue}, - {Name("P", "Р"), RoadShieldType::Generic_Blue}, - {Name("E", "Е"), RoadShieldType::Generic_Green}}) + : SimpleUnicodeRoadShieldParser(baseRoadNumber, + {{Name("M", "М"), RoadShieldType::Generic_Blue}, + {Name("H", "Н"), RoadShieldType::Generic_Blue}, + {Name("P", "Р"), RoadShieldType::Generic_Blue}, + {Name("E", "Е"), RoadShieldType::Generic_Green}}) { } }; @@ -257,9 +387,10 @@ class BelarusRoadShieldParser : public SimpleUnicodeRoadShieldParser public: // The second parameter in the constructor is a cyrillic symbol. BelarusRoadShieldParser(std::string const & baseRoadNumber) - : SimpleUnicodeRoadShieldParser(baseRoadNumber, {{Name("M", "М"), RoadShieldType::Generic_Red}, - {Name("P", "Р"), RoadShieldType::Generic_Red}, - {Name("E", "Е"), RoadShieldType::Generic_Green}}) + : SimpleUnicodeRoadShieldParser(baseRoadNumber, + {{Name("M", "М"), RoadShieldType::Generic_Red}, + {Name("P", "Р"), RoadShieldType::Generic_Red}, + {Name("E", "Е"), RoadShieldType::Generic_Green}}) { } }; @@ -268,9 +399,9 @@ class LatviaRoadShieldParser : public SimpleRoadShieldParser { public: LatviaRoadShieldParser(std::string const & baseRoadNumber) - : SimpleRoadShieldParser(baseRoadNumber, {{'A', RoadShieldType::Generic_Red}, - {'E', RoadShieldType::Generic_Green}, - {'P', RoadShieldType::Generic_Blue}}) + : SimpleRoadShieldParser(baseRoadNumber, {{'A', RoadShieldType::Generic_Red}, + {'E', RoadShieldType::Generic_Green}, + {'P', RoadShieldType::Generic_Blue}}) { } }; @@ -279,20 +410,48 @@ class NetherlandsRoadShieldParser : public SimpleRoadShieldParser { public: NetherlandsRoadShieldParser(std::string const & baseRoadNumber) - : SimpleRoadShieldParser(baseRoadNumber, {{'A', RoadShieldType::Generic_Red}, - {'E', RoadShieldType::Generic_Green}, - {'N', RoadShieldType::Generic_Orange}}) - {} + : SimpleRoadShieldParser(baseRoadNumber, {{'A', RoadShieldType::Generic_Red}, + {'E', RoadShieldType::Generic_Green}, + {'N', RoadShieldType::Generic_Orange}}) + { + } +}; + +class FinlandRoadShieldParser : public NumericRoadShieldParser +{ +public: + FinlandRoadShieldParser(std::string const & baseRoadNumber) + : NumericRoadShieldParser(baseRoadNumber, {{{1, 30}, RoadShieldType::Generic_Red}, + {{40, 99}, RoadShieldType::Generic_Orange}, + {{100, 999}, RoadShieldType::Generic_White}, + {{1000, 9999}, RoadShieldType::Generic_Blue}, + {{10000, 60000}, RoadShieldType::Hidden}}) + { + } +}; + +class EstoniaRoadShieldParser : public NumericRoadShieldParser +{ +public: + EstoniaRoadShieldParser(std::string const & baseRoadNumber) + : NumericRoadShieldParser(baseRoadNumber, {{{1, 11}, RoadShieldType::Generic_Red}, + {{12, 91}, RoadShieldType::Generic_Orange}, + {{92, 92}, RoadShieldType::Generic_Red}, + {{93, 95}, RoadShieldType::Generic_Orange}, + {{96, 999}, RoadShieldType::Generic_White}, + {{1000, 60000}, RoadShieldType::Hidden}}) + { + } }; } // namespace namespace ftypes { -std::vector<RoadShield> GetRoadShields(FeatureType const & f) +std::set<RoadShield> GetRoadShields(FeatureType const & f) { std::string const roadNumber = f.GetRoadNumber(); if (roadNumber.empty()) - return std::vector<RoadShield>(); + return std::set<RoadShield>(); // Find out country name. std::string mwmName = f.GetID().GetMwmName(); @@ -309,6 +468,10 @@ std::vector<RoadShield> GetRoadShields(FeatureType const & f) return RussiaRoadShieldParser(roadNumber).GetRoadShields(); if (mwmName == "France") return FranceRoadShieldParser(roadNumber).GetRoadShields(); + if (mwmName == "Germany") + return GermanyRoadShieldParser(roadNumber).GetRoadShields(); + if (mwmName == "Spain") + return SpainRoadShieldParser(roadNumber).GetRoadShields(); if (mwmName == "Ukraine") return UkraineRoadShieldParser(roadNumber).GetRoadShields(); if (mwmName == "Belarus") @@ -317,7 +480,37 @@ std::vector<RoadShield> GetRoadShields(FeatureType const & f) return LatviaRoadShieldParser(roadNumber).GetRoadShields(); if (mwmName == "Netherlands") return NetherlandsRoadShieldParser(roadNumber).GetRoadShields(); + if (mwmName == "Finland") + return FinlandRoadShieldParser(roadNumber).GetRoadShields(); + if (mwmName == "Estonia") + return EstoniaRoadShieldParser(roadNumber).GetRoadShields(); return SimpleRoadShieldParser(roadNumber, SimpleRoadShieldParser::ShieldTypes()).GetRoadShields(); } + +std::string DebugPrint(RoadShieldType shieldType) +{ + using ftypes::RoadShieldType; + switch (shieldType) + { + case RoadShieldType::Default: return "default"; + case RoadShieldType::Generic_White: return "white"; + case RoadShieldType::Generic_Blue: return "blue"; + case RoadShieldType::Generic_Green: return "green"; + case RoadShieldType::Generic_Orange: return "orange"; + case RoadShieldType::Generic_Red: return "red"; + case RoadShieldType::US_Interstate: return "US interstate"; + case RoadShieldType::US_Highway: return "US highway"; + case RoadShieldType::UK_Highway: return "UK highway"; + case RoadShieldType::Hidden: return "hidden"; + case RoadShieldType::Count: CHECK(false, ("RoadShieldType::Count is not to be used as a type")); + } + return string(); +} + +std::string DebugPrint(RoadShield const & shield) +{ + return DebugPrint(shield.m_type) + "/" + shield.m_name + + (shield.m_additionalText.empty() ? "" : " (" + shield.m_additionalText + ")"); +} } // namespace ftypes |