| 1007 | } |
| 1008 | |
| 1009 | void Geocoder::MatchCities(BaseContext & ctx) |
| 1010 | { |
| 1011 | TRACE(MatchCities); |
| 1012 | |
| 1013 | ASSERT(!ctx.m_city, ()); |
| 1014 | |
| 1015 | // Localities are ordered by (m_startToken, m_endToken) pairs. |
| 1016 | for (auto const & p : m_cities) |
| 1017 | { |
| 1018 | auto const & tokenRange = p.first; |
| 1019 | if (ctx.HasUsedTokensInRange(tokenRange)) |
| 1020 | continue; |
| 1021 | |
| 1022 | for (auto const & city : p.second) |
| 1023 | { |
| 1024 | BailIfCancelled(); |
| 1025 | |
| 1026 | if (!ctx.m_regions.empty() && !m_infoGetter.BelongsToAnyRegion(city.m_rect.Center(), ctx.m_regions.back()->m_ids)) |
| 1027 | continue; |
| 1028 | |
| 1029 | ScopedMarkTokens mark(ctx.m_tokens, BaseContext::FromModelType(city.m_type), tokenRange); |
| 1030 | ctx.m_city = &city; |
| 1031 | SCOPE_GUARD(cleanup, [&ctx]() { ctx.m_city = nullptr; }); |
| 1032 | |
| 1033 | if (ctx.AllTokensUsed()) |
| 1034 | { |
| 1035 | // City matches to search query, we need to emit it as is. |
| 1036 | EmitResult(ctx, city, tokenRange, true /* allTokensUsed */); |
| 1037 | continue; |
| 1038 | } |
| 1039 | |
| 1040 | // No need to search features in the World map. |
| 1041 | if (m_context->GetInfo()->GetType() == MwmInfo::WORLD) |
| 1042 | continue; |
| 1043 | |
| 1044 | auto cityFeatures = RetrieveGeometryFeatures(*m_context, city.m_rect, RectId::Locality); |
| 1045 | |
| 1046 | if (cityFeatures.IsEmpty()) |
| 1047 | continue; |
| 1048 | |
| 1049 | LocalityFilter filter(cityFeatures); |
| 1050 | |
| 1051 | size_t const numEmitted = ctx.m_numEmitted; |
| 1052 | |
| 1053 | CentersFilter centers; |
| 1054 | centers.Add(city.m_rect.Center()); |
| 1055 | LimitedSearch(ctx, filter, centers); |
| 1056 | |
| 1057 | /// @todo A bit controversial here. We don't emit relaxed city if it was matched with some address. |
| 1058 | /// But do emit others (less relevant) relaxed cities. Can't say for sure is it ok or not, but |
| 1059 | /// we don't emit less relevant relaxed streets (@see CreateStreetsLayerAndMatchLowerLayers). |
| 1060 | if (numEmitted == ctx.m_numEmitted && !ctx.AllTokensUsed()) |
| 1061 | { |
| 1062 | TRACE(Relaxed); |
| 1063 | EmitResult(ctx, *ctx.m_city, ctx.m_city->m_tokenRange, false /* allTokensUsed */); |
| 1064 | } |
| 1065 | } |
| 1066 | } |
nothing calls this directly
no test coverage detected