diff --git a/search/cities_boundaries_table.hpp b/search/cities_boundaries_table.hpp index fbe60ffe01..0dac064cf9 100644 --- a/search/cities_boundaries_table.hpp +++ b/search/cities_boundaries_table.hpp @@ -48,6 +48,23 @@ public: // |*this|. bool HasPoint(m2::PointD const & p) const; + m2::RectD GetLimitRect() const + { + m2::RectD rect; + for (auto const & boundary : m_boundaries) + { + for (auto const & p : boundary.m_bbox.Points()) + rect.Add(p); + + for (auto const & p : boundary.m_cbox.Points()) + rect.Add(p); + + for (auto const & p : boundary.m_dbox.Points()) + rect.Add(p); + } + return rect; + } + std::vector const & GetBoundariesForTesting() const { return m_boundaries; } friend std::string DebugPrint(Boundaries const & boundaries) diff --git a/search/geocoder.cpp b/search/geocoder.cpp index 78fc247e36..d3a8a361dd 100644 --- a/search/geocoder.cpp +++ b/search/geocoder.cpp @@ -329,7 +329,8 @@ size_t OrderCountries(m2::RectD const & pivot, vector> & inf // Geocoder::Geocoder ------------------------------------------------------------------------------ Geocoder::Geocoder(DataSource const & dataSource, storage::CountryInfoGetter const & infoGetter, - CategoriesHolder const & categories, PreRanker & preRanker, + CategoriesHolder const & categories, + CitiesBoundariesTable const & citiesBoundaries, PreRanker & preRanker, VillagesCache & villagesCache, ::base::Cancellable const & cancellable) : m_dataSource(dataSource) , m_infoGetter(infoGetter) @@ -339,6 +340,7 @@ Geocoder::Geocoder(DataSource const & dataSource, storage::CountryInfoGetter con , m_hotelsCache(cancellable) , m_hotelsFilter(m_hotelsCache) , m_cancellable(cancellable) + , m_citiesBoundaries(citiesBoundaries) , m_pivotRectsCache(kPivotRectsCacheSize, m_cancellable, Processor::kMaxViewportRadiusM) , m_localityRectsCache(kLocalityRectsCacheSize, m_cancellable) , m_filter(nullptr) @@ -667,16 +669,31 @@ void Geocoder::FillLocalitiesTable(BaseContext const & ctx) { ++numCities; - auto const center = feature::GetCenter(ft); - auto const population = ftypes::GetPopulation(ft); - auto const radius = ftypes::GetRadiusByPopulation(population); - City city(l, Model::TYPE_CITY); - city.m_rect = MercatorBounds::RectByCenterXYAndSizeInMeters(center, radius); + + CitiesBoundariesTable::Boundaries boundaries; + bool haveBoundary = false; + if (m_citiesBoundaries.Has(ft.GetID()) && m_citiesBoundaries.Get(ft.GetID(), boundaries)) + { + city.m_rect = boundaries.GetLimitRect(); + haveBoundary = true; + } + else + { + auto const center = feature::GetCenter(ft); + auto const population = ftypes::GetPopulation(ft); + auto const radius = ftypes::GetRadiusByPopulation(population); + city.m_rect = MercatorBounds::RectByCenterXYAndSizeInMeters(center, radius); + } #if defined(DEBUG) ft.GetName(StringUtf8Multilang::kDefaultCode, city.m_defaultName); - LOG(LINFO, ("City =", city.m_defaultName, "radius =", radius)); + LOG(LINFO, + ("City =", city.m_defaultName, "rect =", city.m_rect, "rect source:", haveBoundary ? "table" : "population", + "sizeX =", + MercatorBounds::DistanceOnEarth(city.m_rect.LeftTop(), city.m_rect.RightTop()), + "sizeY =", + MercatorBounds::DistanceOnEarth(city.m_rect.LeftTop(), city.m_rect.LeftBottom()))); #endif m_cities[city.m_tokenRange].push_back(city); diff --git a/search/geocoder.hpp b/search/geocoder.hpp index fd49e3408f..698601a2e9 100644 --- a/search/geocoder.hpp +++ b/search/geocoder.hpp @@ -3,6 +3,7 @@ #include "search/cancel_exception.hpp" #include "search/categories_cache.hpp" #include "search/cbv.hpp" +#include "search/cities_boundaries_table.hpp" #include "search/feature_offset_match.hpp" #include "search/features_layer.hpp" #include "search/features_layer_path_finder.hpp" @@ -87,8 +88,9 @@ public: }; Geocoder(DataSource const & dataSource, storage::CountryInfoGetter const & infoGetter, - CategoriesHolder const & categories, PreRanker & preRanker, - VillagesCache & villagesCache, ::base::Cancellable const & cancellable); + CategoriesHolder const & categories, CitiesBoundariesTable const & citiesBoundaries, + PreRanker & preRanker, VillagesCache & villagesCache, + ::base::Cancellable const & cancellable); ~Geocoder(); // Sets search query params. @@ -268,6 +270,7 @@ private: // and small villages and hamlets that are not. LocalitiesCache m_cities; LocalitiesCache m_regions[Region::TYPE_COUNT]; + CitiesBoundariesTable const & m_citiesBoundaries; // Caches of features in rects. These caches are separated from // TLocalitiesCache because the latter are quite lightweight and not diff --git a/search/processor.cpp b/search/processor.cpp index 9737bbb8a7..4abd006769 100644 --- a/search/processor.cpp +++ b/search/processor.cpp @@ -153,7 +153,7 @@ Processor::Processor(DataSource const & dataSource, CategoriesHolder const & cat , m_ranker(dataSource, m_citiesBoundaries, infoGetter, m_keywordsScorer, m_emitter, categories, suggests, m_villagesCache, static_cast<::base::Cancellable const &>(*this)) , m_preRanker(dataSource, m_ranker) - , m_geocoder(dataSource, infoGetter, categories, m_preRanker, m_villagesCache, + , m_geocoder(dataSource, infoGetter, categories, m_citiesBoundaries, m_preRanker, m_villagesCache, static_cast<::base::Cancellable const &>(*this)) , m_bookmarksProcessor(m_emitter, static_cast<::base::Cancellable const &>(*this)) {