diff --git a/search/ftypes_matcher.cpp b/search/ftypes_matcher.cpp index abb0e1195c..2f9ba8e95a 100644 --- a/search/ftypes_matcher.cpp +++ b/search/ftypes_matcher.cpp @@ -73,57 +73,83 @@ IsLocalityChecker::IsLocalityChecker() { Classificator const & c = classif(); + // Note! The order should be equal with constants in Type enum (add other villages to the end). char const * arr[][2] = { { "place", "country" }, { "place", "state" }, { "place", "city" }, - { "place", "town" } + { "place", "town" }, + { "place", "village" }, + { "place", "hamlet" } }; for (size_t i = 0; i < ARRAY_SIZE(arr); ++i) m_types.push_back(c.GetTypeByPath(vector(arr[i], arr[i] + 2))); } -Type IsLocalityChecker::GetLocalityType(feature::TypesHolder const & types) const +Type IsLocalityChecker::GetType(feature::TypesHolder const & types) const { for (size_t i = 0; i < types.Size(); ++i) { uint32_t t = types[i]; ftype::TruncValue(t, 2); - if (t == m_types[0]) - return COUNTRY; - - if (t == m_types[1]) - return STATE; - - for (int j = 2; j < m_types.size(); ++j) + size_t j = COUNTRY; + for (; j < LOCALITY_COUNT; ++j) if (t == m_types[j]) - return CITY; + return static_cast(j); + + for (; j < m_types.size(); ++j) + if (t == m_types[j]) + return VILLAGE; } return NONE; } -Type IsLocalityChecker::GetLocalityType(const FeatureType & f) const +Type IsLocalityChecker::GetType(const FeatureType & f) const { feature::TypesHolder types(f); - return GetLocalityType(types); + return GetType(types); } -double GetLocationRadius(FeatureType const & ft) +IsLocalityChecker const & IsLocalityChecker::Instance() +{ + static IsLocalityChecker inst; + return inst; +} + +uint32_t GetPopulation(FeatureType const & ft) { uint32_t population = ft.GetPopulation(); if (population < 10) { - static IsLocalityChecker checker; - if (checker.GetLocalityType(ft) == CITY) + switch (IsLocalityChecker::Instance().GetType(ft)) + { + case CITY: + case TOWN: population = 10000; - /// @todo: process all cases of locality types + break; + case VILLAGE: + population = 100; + break; + default: + population = 0; + } } - return pow((double)population, 0.277778) * 550; + return population; +} + +double GetRadiusByPopulation(uint32_t p) +{ + return pow(static_cast(p), 0.277778) * 550.0; +} + +uint32_t GetPopulationByRadius(double r) +{ + return my::rounds(pow(r / 550.0, 3.6)); } } diff --git a/search/ftypes_matcher.hpp b/search/ftypes_matcher.hpp index 16dd222f75..6542674b3c 100644 --- a/search/ftypes_matcher.hpp +++ b/search/ftypes_matcher.hpp @@ -36,19 +36,26 @@ public: IsBuildingChecker(); }; -/// Type of locality (do not change values - they have detalization order) -/// COUNTRY < STATE < CITY -enum Type { NONE = -1, COUNTRY = 0, STATE, CITY }; +/// Type of locality (do not change values and order - they have detalization order) +/// COUNTRY < STATE < CITY < ... +enum Type { NONE = -1, COUNTRY = 0, STATE, CITY, TOWN, VILLAGE, LOCALITY_COUNT }; class IsLocalityChecker : public BaseChecker { public: IsLocalityChecker(); - Type GetLocalityType(feature::TypesHolder const & types) const; - Type GetLocalityType(FeatureType const & f) const; + Type GetType(feature::TypesHolder const & types) const; + Type GetType(FeatureType const & f) const; + + static IsLocalityChecker const & Instance(); }; -/// Get city radius (meters) -double GetLocationRadius(FeatureType const & ft); +/// @name Get city radius and population. +/// @param r Radius in meters. +//@{ +uint32_t GetPopulation(FeatureType const & ft); +double GetRadiusByPopulation(uint32_t p); +uint32_t GetPopulationByRadius(double r); +//@} } diff --git a/search/search_query.cpp b/search/search_query.cpp index 21adf7588f..5c22f889b5 100644 --- a/search/search_query.cpp +++ b/search/search_query.cpp @@ -724,8 +724,16 @@ void Query::SearchViewportPoints(Results & res) ftypes::Type Query::GetLocalityIndex(feature::TypesHolder const & types) const { - static ftypes::IsLocalityChecker checker; - return checker.GetLocalityType(types); + using namespace ftypes; + + // Inner logic of SearchAddress expects COUNTRY, STATE and CITY only. + Type const type = IsLocalityChecker::Instance().GetType(types); + switch (type) + { + case TOWN: return CITY; + case VILLAGE: return NONE; + default: return type; + } } void Query::RemoveStringPrefix(string const & str, string & res) const @@ -1703,14 +1711,16 @@ namespace impl FeatureType f; m_vector.Get(v.m_featureId, f); + using namespace ftypes; + // check, if feature is locality - ftypes::Type const index = m_query.GetLocalityIndex(feature::TypesHolder(f)); - if (index != ftypes::NONE) + Type const index = m_query.GetLocalityIndex(feature::TypesHolder(f)); + if (index != NONE) { Locality * loc = PushLocality(Locality(v, index)); if (loc) { - loc->m_radius = ftypes::GetLocationRadius(f); + loc->m_radius = GetRadiusByPopulation(GetPopulation(f)); // m_lang name should exist if we matched feature in search index for this language. VERIFY(f.GetName(m_lang, loc->m_name), ());