diff --git a/indexer/ftypes_matcher.cpp b/indexer/ftypes_matcher.cpp index 1015d22979..dd42b10b6c 100644 --- a/indexer/ftypes_matcher.cpp +++ b/indexer/ftypes_matcher.cpp @@ -294,9 +294,45 @@ IsSquareChecker::IsSquareChecker() IsSuburbChecker::IsSuburbChecker() { Classificator const & c = classif(); - m_types.push_back(c.GetTypeByPath({"landuse", "residential"})); - m_types.push_back(c.GetTypeByPath({"place", "neighbourhood"})); - m_types.push_back(c.GetTypeByPath({"place", "suburb"})); + auto const residentialType = c.GetTypeByPath({"landuse", "residential"}); + auto const neighbourhoodType = c.GetTypeByPath({"place", "neighbourhood"}); + auto const suburbType = c.GetTypeByPath({"place", "suburb"}); + m_types.push_back(residentialType); + m_types.push_back(neighbourhoodType); + m_types.push_back(suburbType); + CHECK(m_types[static_cast(SuburbType::Residential)] == residentialType, ()); + CHECK(m_types[static_cast(SuburbType::Neighbourhood)] == neighbourhoodType, ()); + CHECK(m_types[static_cast(SuburbType::Suburb)] == suburbType, ()); +} + +SuburbType IsSuburbChecker::GetType(uint32_t t) const +{ + ftype::TruncValue(t, 2); + + for (size_t i = 0; i < m_types.size(); ++i) + { + if (m_types[i] == t) + return static_cast(i); + } + + return SuburbType::None; +} + +SuburbType IsSuburbChecker::GetType(feature::TypesHolder const & types) const +{ + for (uint32_t t : types) + { + auto const type = GetType(t); + if (type != SuburbType::None) + return type; + } + return SuburbType::None; +} + +SuburbType IsSuburbChecker::GetType(FeatureType & f) const +{ + feature::TypesHolder types(f); + return GetType(types); } IsWayChecker::IsWayChecker() diff --git a/indexer/ftypes_matcher.hpp b/indexer/ftypes_matcher.hpp index f05d8ce883..4c1ac63788 100644 --- a/indexer/ftypes_matcher.hpp +++ b/indexer/ftypes_matcher.hpp @@ -136,11 +136,32 @@ public: DECLARE_CHECKER_INSTANCE(IsSquareChecker); }; +/// Type of locality (do not change values and order - they have detalization order) +/// Suburb > Neighbourhood > Residential +enum class SuburbType +{ + None = -1, + Residential = 0, + Neighbourhood, + Suburb, + Count +}; + +static_assert(base::Underlying(SuburbType::Residential) < + base::Underlying(SuburbType::Neighbourhood), + ""); +static_assert(base::Underlying(SuburbType::Neighbourhood) < base::Underlying(SuburbType::Suburb), + ""); + class IsSuburbChecker : public BaseChecker { IsSuburbChecker(); public: + SuburbType GetType(uint32_t t) const; + SuburbType GetType(feature::TypesHolder const & types) const; + SuburbType GetType(FeatureType & f) const; + DECLARE_CHECKER_INSTANCE(IsSuburbChecker); }; diff --git a/search/geocoder.cpp b/search/geocoder.cpp index 400d357890..ad4bb011c2 100644 --- a/search/geocoder.cpp +++ b/search/geocoder.cpp @@ -68,6 +68,8 @@ size_t constexpr kMaxNumCountries = 10; double constexpr kMaxViewportRadiusM = 50.0 * 1000; double constexpr kMaxPostcodeRadiusM = 1000; double constexpr kMaxSuburbRadiusM = 2000; +double constexpr kMaxNeighbourhoodRadiusM = 500; +double constexpr kMaxResidentialRadiusM = 500; size_t constexpr kPivotRectsCacheSize = 10; size_t constexpr kPostcodesRectsCacheSize = 10; @@ -1228,8 +1230,17 @@ void Geocoder::GreedilyMatchStreetsWithSuburbs(BaseContext & ctx, vector suburbFeatures = {ft->GetID().m_index}; layer.m_sortedFeatures = &suburbFeatures; - auto const rect = - mercator::RectByCenterXYAndSizeInMeters(feature::GetCenter(*ft), kMaxSuburbRadiusM); + auto const suburbType = ftypes::IsSuburbChecker::Instance().GetType(*ft); + double radius = 0.0; + switch (suburbType) + { + case ftypes::SuburbType::Residential: radius = kMaxResidentialRadiusM; break; + case ftypes::SuburbType::Neighbourhood: radius = kMaxNeighbourhoodRadiusM; break; + case ftypes::SuburbType::Suburb: radius = kMaxSuburbRadiusM; break; + default: CHECK(false, ("Bad suburb type:", base::Underlying(suburbType))); + } + + auto const rect = mercator::RectByCenterXYAndSizeInMeters(feature::GetCenter(*ft), radius); auto const suburbCBV = RetrieveGeometryFeatures(*m_context, rect, RectId::Suburb); auto const suburbStreets = ctx.m_streets.Intersect(suburbCBV);