diff options
author | r.kuznetsov <r.kuznetsov@corp.mail.ru> | 2017-02-01 15:43:20 +0300 |
---|---|---|
committer | r.kuznetsov <r.kuznetsov@corp.mail.ru> | 2017-02-01 15:43:20 +0300 |
commit | 5013336567ac1c1d115745b99c471b17c2700ca6 (patch) | |
tree | 5700b066163d31e9eb37ae022f2305f37b9f819a /indexer | |
parent | e487db8556bc8fc775f4cd6c452493f6a220c7b8 (diff) |
Added road shields rendering
Diffstat (limited to 'indexer')
-rw-r--r-- | indexer/drawing_rules.cpp | 17 | ||||
-rw-r--r-- | indexer/drawing_rules.hpp | 2 | ||||
-rw-r--r-- | indexer/ftypes_matcher.cpp | 191 | ||||
-rw-r--r-- | indexer/ftypes_matcher.hpp | 29 |
4 files changed, 217 insertions, 22 deletions
diff --git a/indexer/drawing_rules.cpp b/indexer/drawing_rules.cpp index 774743528a..2a8d66dd9e 100644 --- a/indexer/drawing_rules.cpp +++ b/indexer/drawing_rules.cpp @@ -95,11 +95,6 @@ text_type_t BaseRule::GetCaptionTextType(int) const return text_type_name; } -CircleRuleProto const * BaseRule::GetCircle() const -{ - return 0; -} - ShieldRuleProto const * BaseRule::GetShield() const { return nullptr; @@ -295,15 +290,6 @@ namespace typedef CaptionT<CaptionRuleProto> Caption; typedef CaptionT<PathTextRuleProto> PathText; - class Circle : public BaseRule - { - CircleRuleProto m_circle; - public: - Circle(CircleRuleProto const & r) : m_circle(r) {} - - virtual CircleRuleProto const * GetCircle() const { return &m_circle; } - }; - class Shield : public BaseRule { ShieldRuleProto m_shield; @@ -444,9 +430,6 @@ namespace if (de.has_caption()) AddRule<Caption>(p, de.scale(), caption, de.caption(), apply_if); - if (de.has_circle()) - AddRule<Circle>(p, de.scale(), circle, de.circle(), apply_if); - if (de.has_path_text()) AddRule<PathText>(p, de.scale(), pathtext, de.path_text(), apply_if); diff --git a/indexer/drawing_rules.hpp b/indexer/drawing_rules.hpp index 6870cb869e..317e971ed5 100644 --- a/indexer/drawing_rules.hpp +++ b/indexer/drawing_rules.hpp @@ -19,7 +19,6 @@ class LineDefProto; class AreaRuleProto; class SymbolRuleProto; class CaptionDefProto; -class CircleRuleProto; class ShieldRuleProto; class ContainerProto; class FeatureType; @@ -56,7 +55,6 @@ namespace drule virtual SymbolRuleProto const * GetSymbol() const; virtual CaptionDefProto const * GetCaption(int) const; virtual text_type_t GetCaptionTextType(int) const; - virtual CircleRuleProto const * GetCircle() const; virtual ShieldRuleProto const * GetShield() const; // Test feature by runtime feature style selector diff --git a/indexer/ftypes_matcher.cpp b/indexer/ftypes_matcher.cpp index ec939f1880..c327d50fae 100644 --- a/indexer/ftypes_matcher.cpp +++ b/indexer/ftypes_matcher.cpp @@ -4,9 +4,11 @@ #include "indexer/feature_data.hpp" #include "indexer/classificator.hpp" -#include "std/map.hpp" -#include "std/sstream.hpp" -#include "std/utility.hpp" +#include <algorithm> +#include <map> +#include <sstream> +#include <unordered_map> +#include <utility> namespace { @@ -543,4 +545,187 @@ bool IsTypeConformed(uint32_t type, StringIL const & path) } return true; } + +class RoadShieldParser +{ +public: + RoadShieldParser(std::string const & baseRoadNumber) + : m_baseRoadNumber(baseRoadNumber) + {} + virtual ~RoadShieldParser(){} + virtual RoadShield ParseRoadShield(std::string const & rawText) = 0; + + std::vector<RoadShield> GetRoadShields() + { + std::vector<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)); + } + return result; + } + +protected: + std::string const m_baseRoadNumber; +}; + +uint32_t constexpr kMaxRoadShieldTextSize = 8; + +class USRoadShieldParser : public RoadShieldParser +{ +public: + USRoadShieldParser(std::string const & baseRoadNumber) + : RoadShieldParser(baseRoadNumber) + {} + + RoadShield ParseRoadShield(std::string const & rawText) override + { + static std::vector<std::string> kStatesCode = { + "US", "SR", "FSR", "AL", "AK", "AZ", "AR", "CA", "CO", "CT", "DE", "DC", "FL", "GA", + "HI", "ID", "IL", "IN", "IA", "KS", "KY", "LA", "ME", "MD", "MA", "MI", "MN", "MS", + "MO", "MT", "NE", "NV", "NH", "NJ", "NM", "NY", "NC", "ND", "OH", "OK", "OR", "PA", + "RI", "SC", "SD", "TN", "TX", "UT", "VT", "VA", "WA", "WV", "WI", "WY", "AS", "GU", + "MP", "PR", "VI", "UM", "FM", "MH", "PW", + }; + + static std::vector<std::string> kModifiers = { + "alt", "alternate", "bus", "business", "bypass", "historic", "connector", "loop", + "scenic", "spur", "temporary", "toll", "truck" + }; + + std::string shieldText = rawText; + + std::replace(shieldText.begin(), shieldText.end(), '-', ' '); + auto const shieldParts = strings::Tokenize(shieldText, " "); + + // Process long road shield titles to skip invalid data. + if (shieldText.size() > kMaxRoadShieldTextSize) + { + std::string lowerShieldText = shieldText; + strings::AsciiToLower(lowerShieldText); + + bool modifierFound = false; + for (auto const & modifier : kModifiers) + { + if (lowerShieldText.find(modifier) != std::string::npos) + { + modifierFound = true; + break; + } + } + if (!modifierFound) + return RoadShield(); + } + + if (shieldParts.size() <= 1) + { + return RoadShield(RoadShieldType::Default, rawText); + } + else + { + std::string const & roadType = shieldParts[0]; // 'I' for interstates and kStatesCode for highways. + std::string roadNumber = shieldParts[1]; + std::string additionalInfo; + if (shieldParts.size() >= 3) + { + additionalInfo = shieldParts[2]; + // Process cases like "US Loop 16". + if (!strings::is_number(shieldParts[1]) && strings::is_number(shieldParts[2])) + { + roadNumber = shieldParts[2]; + additionalInfo = shieldParts[1]; + } + } + if (roadType == "I") + return RoadShield(RoadShieldType::US_Interstate, roadNumber, additionalInfo); + else if (std::find(kStatesCode.begin(), kStatesCode.end(), shieldParts[0]) !=kStatesCode.end()) + return RoadShield(RoadShieldType::US_Highway, roadNumber, additionalInfo); + + return RoadShield(RoadShieldType::Default, rawText); + } + } +}; + +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) + {} + + RoadShield ParseRoadShield(std::string const & rawText) override + { + if (rawText.size() > kMaxRoadShieldTextSize) + return RoadShield(); + + for (auto const & p : m_types) + { + if (rawText.find(p.first) != std::string::npos) + return RoadShield(p.second, rawText); + } + + return RoadShield(RoadShieldType::Default, rawText); + } + +private: + ShieldTypes const m_types; +}; + +class UKRoadShieldParser : public SimpleRoadShieldParser +{ +public: + UKRoadShieldParser(std::string const & baseRoadNumber) + : SimpleRoadShieldParser(baseRoadNumber, {{'M', RoadShieldType::UK_Motorway}, + {'A', RoadShieldType::UK_Highway}}) + {} +}; + +class RussiaRoadShieldParser : public RoadShieldParser +{ +public: + RussiaRoadShieldParser(std::string const & baseRoadNumber) + : RoadShieldParser(baseRoadNumber) + {} + + RoadShield ParseRoadShield(std::string const & rawText) override + { + if (rawText.size() > kMaxRoadShieldTextSize) + return RoadShield(); + + strings::UniString s = strings::MakeUniString(rawText); + if (s[0] == 'E' || s[0] == strings::UniChar(1045)) // Latin and cyrillic. + return RoadShield(RoadShieldType::Russia_Motorway, rawText); + + return RoadShield(RoadShieldType::Russia_Highway, rawText); + } +}; + +std::vector<RoadShield> GetRoadShields(FeatureType const & f) +{ + std::string const roadNumber = f.GetRoadNumber(); + if (roadNumber.empty()) + return std::vector<RoadShield>(); + + // Find out country name. + std::string mwmName = f.GetID().GetMwmName(); + ASSERT_NOT_EQUAL(mwmName, FeatureID::kInvalidFileName, ()); + auto const underlinePos = mwmName.find('_'); + if (underlinePos != std::string::npos) + mwmName = mwmName.substr(0, underlinePos); + + if (mwmName == "US") + return USRoadShieldParser(roadNumber).GetRoadShields(); + if (mwmName == "UK") + return UKRoadShieldParser(roadNumber).GetRoadShields(); + if (mwmName == "Russia") + return RussiaRoadShieldParser(roadNumber).GetRoadShields(); + + return std::vector<RoadShield>{RoadShield(RoadShieldType::Default, roadNumber)}; +} } // namespace ftypes diff --git a/indexer/ftypes_matcher.hpp b/indexer/ftypes_matcher.hpp index c3d6e02d5d..a63267e7be 100644 --- a/indexer/ftypes_matcher.hpp +++ b/indexer/ftypes_matcher.hpp @@ -240,4 +240,33 @@ enum class HighwayClass string DebugPrint(HighwayClass const cls); HighwayClass GetHighwayClass(feature::TypesHolder const & types); + +enum class RoadShieldType +{ + Default = 0, + US_Interstate, + US_Highway, + UK_Motorway, + UK_Highway, + Russia_Motorway, + Russia_Highway, + Count +}; + +struct RoadShield +{ + RoadShieldType m_type; + std::string m_name; + std::string m_additionalText; + + RoadShield() = default; + RoadShield(RoadShieldType const & type, std::string const & name) + : m_type(type), m_name(name) + {} + RoadShield(RoadShieldType const & type, std::string const & name, std::string const & additionalText) + : m_type(type), m_name(name), m_additionalText(additionalText) + {} +}; + +std::vector<RoadShield> GetRoadShields(FeatureType const & f); } // namespace ftypes |