diff --git a/search/features_layer_matcher.hpp b/search/features_layer_matcher.hpp index be8f8365d7..86e0f0f217 100644 --- a/search/features_layer_matcher.hpp +++ b/search/features_layer_matcher.hpp @@ -82,8 +82,6 @@ public: case Model::TYPE_STATE: case Model::TYPE_COUNTRY: case Model::TYPE_UNCLASSIFIED: - // todo(@t.yan): match pois and buildings with suburbs - case Model::TYPE_SUBURB: case Model::TYPE_COUNT: ASSERT(false, ("Invalid parent layer type:", parent.m_type)); break; @@ -99,6 +97,11 @@ public: else MatchBuildingsWithStreets(child, parent, std::forward(fn)); break; + case Model::TYPE_SUBURB: + // todo(@t.yan): match pois and buildings with suburbs + ASSERT(child.m_type == Model::TYPE_STREET, ("Invalid child layer type:", child.m_type)); + MatchStreetsWithSuburbs(child, parent, std::forward(fn)); + break; } } @@ -367,6 +370,18 @@ private: } } + template + void MatchStreetsWithSuburbs(FeaturesLayer const & child, FeaturesLayer const & parent, Fn && fn) + { + // We have pre-matched streets from geocoder. + auto const & streets = *child.m_sortedFeatures; + CHECK_EQUAL(parent.m_sortedFeatures->size(), 1, ()); + auto const & suburb = parent.m_sortedFeatures->front(); + + for (auto const & street : streets) + fn(street, suburb); + } + // Returns id of a street feature corresponding to a |houseId|/|houseFeature|, or // kInvalidId if there're not such street. uint32_t GetMatchingStreet(uint32_t houseId); diff --git a/search/geocoder.cpp b/search/geocoder.cpp index db693c69b7..4634207080 100644 --- a/search/geocoder.cpp +++ b/search/geocoder.cpp @@ -1090,18 +1090,24 @@ void Geocoder::GreedilyMatchStreetsWithSuburbs(BaseContext & ctx) vector suburbs; StreetsMatcher::Go(ctx, ctx.m_suburbs, *m_filter, m_params, suburbs); - for (auto const & s : suburbs) + for (auto const & suburb : suburbs) { - ScopedMarkTokens mark(ctx.m_tokens, BaseContext::TOKEN_TYPE_SUBURB, s.m_tokenRange); + ScopedMarkTokens mark(ctx.m_tokens, BaseContext::TOKEN_TYPE_SUBURB, suburb.m_tokenRange); - s.m_features.ForEach([&](uint64_t suburbId) { + suburb.m_features.ForEach([&](uint64_t suburbId) { auto ft = m_context->GetFeature(static_cast(suburbId)); if (!ft) return; - Suburb suburb(ft->GetID(), s.m_tokenRange); - ctx.m_suburb = &suburb; - SCOPE_GUARD(cleanup, [&ctx]() { ctx.m_suburb = nullptr; }); + auto & layers = ctx.m_layers; + ASSERT(layers.empty(), ()); + layers.emplace_back(); + SCOPE_GUARD(cleanupGuard, bind(&vector::pop_back, &layers)); + + auto & layer = layers.back(); + InitLayer(Model::TYPE_SUBURB, suburb.m_tokenRange, layer); + vector suburbFeatures = {ft->GetID().m_index}; + layer.m_sortedFeatures = &suburbFeatures; auto const rect = mercator::RectByCenterXYAndSizeInMeters(feature::GetCenter(*ft), kMaxSuburbRadiusM); @@ -1121,7 +1127,6 @@ void Geocoder::CreateStreetsLayerAndMatchLowerLayers(BaseContext & ctx, StreetsMatcher::Prediction const & prediction) { auto & layers = ctx.m_layers; - ASSERT(layers.empty(), ()); layers.emplace_back(); SCOPE_GUARD(cleanupGuard, bind(&vector::pop_back, &layers)); @@ -1507,12 +1512,6 @@ void Geocoder::EmitResult(BaseContext & ctx, MwmSet::MwmId const & mwmId, uint32 info.m_cityId = FeatureID(city.m_countryId, city.m_featureId); } - if (ctx.m_suburb) - { - info.m_tokenRange[Model::TYPE_SUBURB] = ctx.m_suburb->m_tokenRange; - info.m_suburbId = ctx.m_suburb->m_featureId; - } - if (geoParts) info.m_geoParts = *geoParts; diff --git a/search/geocoder_context.hpp b/search/geocoder_context.hpp index 9f0c5124e0..26b74d7444 100644 --- a/search/geocoder_context.hpp +++ b/search/geocoder_context.hpp @@ -70,8 +70,6 @@ struct BaseContext City const * m_city = nullptr; - Suburb const * m_suburb = nullptr; - // This vector is used to indicate what tokens were already matched // and can't be re-used during the geocoding process. std::vector m_tokens; diff --git a/search/intersection_result.cpp b/search/intersection_result.cpp index ed41c0bfcd..1cd4a5cccf 100644 --- a/search/intersection_result.cpp +++ b/search/intersection_result.cpp @@ -14,7 +14,7 @@ void IntersectionResult::Set(Model::Type type, uint32_t id) case Model::TYPE_POI: m_poi = id; break; case Model::TYPE_BUILDING: m_building = id; break; case Model::TYPE_STREET: m_street = id; break; - case Model::TYPE_SUBURB: + case Model::TYPE_SUBURB: m_suburb = id; break; case Model::TYPE_CITY: case Model::TYPE_VILLAGE: case Model::TYPE_STATE: @@ -32,6 +32,8 @@ uint32_t IntersectionResult::InnermostResult() const return m_building; if (m_street != kInvalidId) return m_street; + if (m_suburb != kInvalidId) + return m_suburb; return kInvalidId; } @@ -40,6 +42,7 @@ void IntersectionResult::Clear() m_poi = kInvalidId; m_building = kInvalidId; m_street = kInvalidId; + m_suburb = kInvalidId; } std::string DebugPrint(IntersectionResult const & result) @@ -52,6 +55,8 @@ std::string DebugPrint(IntersectionResult const & result) os << "BUILDING:" << result.m_building << " "; if (result.m_street != IntersectionResult::kInvalidId) os << "STREET:" << result.m_street << " "; + if (result.m_suburb != IntersectionResult::kInvalidId) + os << "SUBURB:" << result.m_suburb << " "; os << "]"; return os.str(); } diff --git a/search/intersection_result.hpp b/search/intersection_result.hpp index 2f630ef9aa..e8f9814a2e 100644 --- a/search/intersection_result.hpp +++ b/search/intersection_result.hpp @@ -29,6 +29,7 @@ struct IntersectionResult uint32_t m_poi = kInvalidId; uint32_t m_building = kInvalidId; uint32_t m_street = kInvalidId; + uint32_t m_suburb = kInvalidId; }; std::string DebugPrint(IntersectionResult const & result); diff --git a/search/pre_ranking_info.hpp b/search/pre_ranking_info.hpp index 2ede4ec395..e472ce449c 100644 --- a/search/pre_ranking_info.hpp +++ b/search/pre_ranking_info.hpp @@ -45,9 +45,6 @@ struct PreRankingInfo // building and street ids are in |m_geoParts|. IntersectionResult m_geoParts; - // Id of the matched suburb, if any. - FeatureID m_suburbId; - // Id of the matched city, if any. FeatureID m_cityId; diff --git a/search/ranker.cpp b/search/ranker.cpp index b8170b0529..7072719d37 100644 --- a/search/ranker.cpp +++ b/search/ranker.cpp @@ -395,9 +395,11 @@ class RankerResultMaker } } - if (info.m_type != Model::TYPE_SUBURB && preInfo.m_suburbId.IsValid()) + if (info.m_type != Model::TYPE_SUBURB && + preInfo.m_geoParts.m_suburb != IntersectionResult::kInvalidId) { - auto suburb = LoadFeature(preInfo.m_suburbId); + auto const & mwmId = ft.GetID().m_mwmId; + auto suburb = LoadFeature(FeatureID(mwmId, preInfo.m_geoParts.m_suburb)); if (suburb) { auto const type = Model::TYPE_SUBURB;