diff --git a/search/locality_finder.cpp b/search/locality_finder.cpp index 0831ca6c46..6ddb30ff3e 100644 --- a/search/locality_finder.cpp +++ b/search/locality_finder.cpp @@ -1,27 +1,25 @@ #include "search/locality_finder.hpp" +#include "search/v2/mwm_context.hpp" #include "indexer/ftypes_matcher.hpp" -#include "indexer/features_vector.hpp" namespace search { -double const MAX_RADIUS_CITY = 30000.0; +double const kMaxCityRadiusMeters = 30000.0; +double const kInflateRectMercator = 1.0E-3; class DoLoader { public: - DoLoader(LocalityFinder const & finder, FeaturesVector const & loader, LocalityFinder::Cache & cache) - : m_finder(finder), m_loader(loader), m_cache(cache) + DoLoader(LocalityFinder const & finder, LocalityFinder::Cache & cache) + : m_finder(finder), m_cache(cache) { } - void operator() (uint32_t id) const + void operator() (FeatureType & ft) const { - FeatureType ft; - m_loader.GetByIndex(id, ft); - if (ft.GetFeatureType() != feature::GEOM_POINT) return; @@ -35,8 +33,10 @@ public: return; } + uint32_t const id = ft.GetID().m_index; + if (m_cache.m_loaded.count(id) > 0) - return; // already loaded + return; uint32_t const population = ftypes::GetPopulation(ft); if (population == 0) @@ -60,7 +60,6 @@ public: private: LocalityFinder const & m_finder; - FeaturesVector const & m_loader; LocalityFinder::Cache & m_cache; }; @@ -109,114 +108,69 @@ LocalityFinder::LocalityFinder(Index const * pIndex) { } -void LocalityFinder::CorrectMinimalRect(m2::RectD & rect) const +void LocalityFinder::UpdateCache(Cache & cache, m2::PointD const & pt) const { - m2::RectD const rlt = MercatorBounds::RectByCenterXYAndSizeInMeters(rect.LeftTop(), MAX_RADIUS_CITY); - m2::RectD const rrb = MercatorBounds::RectByCenterXYAndSizeInMeters(rect.RightBottom(), MAX_RADIUS_CITY); - rect = m2::RectD(MercatorBounds::ClampX(rlt.minX()), - MercatorBounds::ClampY(rrb.minY()), - MercatorBounds::ClampX(rrb.maxX()), - MercatorBounds::ClampY(rlt.maxY())); -} + m2::RectD rect = MercatorBounds::RectByCenterXYAndSizeInMeters(pt, kMaxCityRadiusMeters); + if (cache.m_rect.IsRectInside(rect)) + return; + + rect.Add(cache.m_rect); + rect.Inflate(kInflateRectMercator, kInflateRectMercator); -void LocalityFinder::RecreateCache(Cache & cache, m2::RectD rect) const -{ vector> mwmsInfo; m_pIndex->GetMwmsInfo(mwmsInfo); - - cache.Clear(); - - CorrectMinimalRect(rect); - covering::CoveringGetter cov(rect, covering::ViewportWithLowLevels); - - for (shared_ptr & info : mwmsInfo) + for (auto const & info : mwmsInfo) { - typedef feature::DataHeader HeaderT; - MwmSet::MwmId mwmId(info); - Index::MwmHandle const mwmHandle = m_pIndex->GetMwmHandleById(mwmId); - MwmValue const * pMwm = mwmHandle.GetValue(); - if (pMwm && pMwm->GetHeader().GetType() == HeaderT::world) + Index::MwmHandle handle = m_pIndex->GetMwmHandleById(info); + MwmValue const * pMwm = handle.GetValue(); + if (pMwm && pMwm->GetHeader().GetType() == feature::DataHeader::world) { - HeaderT const & header = pMwm->GetHeader(); - - int const scale = header.GetLastScale(); // scales::GetUpperWorldScale() - covering::IntervalsT const & interval = cov.Get(scale); - - ScaleIndex index(pMwm->m_cont.GetReader(INDEX_FILE_TAG), pMwm->m_factory); - - FeaturesVector loader(pMwm->m_cont, header, pMwm->m_table); - DoLoader doLoader(*this, loader, cache); cache.m_rect = rect; - - for (size_t i = 0; i < interval.size(); ++i) - index.ForEachInIntervalAndScale(doLoader, interval[i].first, interval[i].second, scale); - } - } -} - -void LocalityFinder::SetViewportByIndex(m2::RectD const & viewport, size_t idx) -{ - ASSERT_LESS(idx, (size_t)MAX_VIEWPORT_COUNT, ()); - RecreateCache(m_cache[idx], viewport); -} - -void LocalityFinder::SetReservedViewportIfNeeded(m2::RectD const & viewport) -{ - size_t constexpr kReservedIndex = 2; - if (m_cache[kReservedIndex].m_rect.IsValid() && - m_cache[kReservedIndex].m_rect.IsRectInside(viewport)) - { - return; - } - - SetViewportByIndex(viewport, kReservedIndex); -} - -void LocalityFinder::GetLocalityInViewport(m2::PointD const & pt, string & name) const -{ - name.clear(); - for (size_t i = 0; i < MAX_VIEWPORT_COUNT; ++i) - { - m_cache[i].GetLocality(pt, name); - if (!name.empty()) + v2::MwmContext(move(handle)).ForEachFeature(rect, DoLoader(*this, cache)); break; + } } } -void LocalityFinder::GetLocalityCreateCache(m2::PointD const & pt, string & name) +void LocalityFinder::GetLocality(m2::PointD const & pt, string & name) { - // search in temporary caches and find most unused cache - size_t minUsageIdx = 0; - size_t minUsage = numeric_limits::max(); - for (size_t idx = 0; idx < MAX_VIEWPORT_COUNT; ++idx) - { - Cache const & cache = m_cache[idx]; - cache.GetLocality(pt, name); - if (!name.empty()) - return; + Cache * pWorking = nullptr; - if (cache.m_usage < minUsage) + // Find suitable cache that includes needed point. + for (auto & cache : m_caches) + { + if (cache.m_rect.IsPointInside(pt)) { - minUsage = cache.m_usage; - minUsageIdx = idx; + pWorking = &cache; + break; } } - Cache & cache = m_cache[minUsageIdx]; - RecreateCache(cache, MercatorBounds::RectByCenterXYAndSizeInMeters(pt, MAX_RADIUS_CITY)); - cache.GetLocality(pt, name); + if (pWorking == nullptr) + { + // Find most unused cache. + size_t minUsage = numeric_limits::max(); + for (auto & cache : m_caches) + { + if (cache.m_usage < minUsage) + { + pWorking = &cache; + minUsage = cache.m_usage; + } + } + + pWorking->Clear(); + } + + ASSERT(pWorking, ()); + UpdateCache(*pWorking, pt); + pWorking->GetLocality(pt, name); } -void LocalityFinder::ClearCacheAll() +void LocalityFinder::ClearCache() { - for (size_t i = 0; i < MAX_VIEWPORT_COUNT; ++i) - ClearCache(i); -} - -void LocalityFinder::ClearCache(size_t idx) -{ - ASSERT_LESS(idx, (size_t)MAX_VIEWPORT_COUNT, ()); - m_cache[idx].Clear(); + for (auto & cache : m_caches) + cache.Clear(); } void LocalityFinder::Cache::Clear() @@ -224,13 +178,11 @@ void LocalityFinder::Cache::Clear() m_usage = 0; m_tree.Clear(); m_loaded.clear(); + m_rect.MakeEmpty(); } -void LocalityFinder::Cache::GetLocality(m2::PointD const & pt, string & name) const +void LocalityFinder::Cache::GetLocality(m2::PointD const & pt, string & name) { - if (!m_rect.IsPointInside(pt)) - return; - ++m_usage; m_tree.ForEachInRectEx(m2::RectD(pt, pt), DoSelectLocality(name, pt)); } diff --git a/search/locality_finder.hpp b/search/locality_finder.hpp index b898818a28..0b3cae1af7 100644 --- a/search/locality_finder.hpp +++ b/search/locality_finder.hpp @@ -33,13 +33,13 @@ class LocalityFinder { m4::Tree m_tree; set m_loaded; - mutable uint32_t m_usage; + size_t m_usage; m2::RectD m_rect; Cache() : m_usage(0) {} void Clear(); - void GetLocality(m2::PointD const & pt, string & name) const; + void GetLocality(m2::PointD const & pt, string & name); }; public: @@ -49,34 +49,23 @@ public: { if (m_lang != lang) { - ClearCacheAll(); + ClearCache(); m_lang = lang; } } - void SetViewportByIndex(m2::RectD const & viewport, size_t idx); - /// Set new viewport for the reserved slot only if it's no a part of the previous one. - void SetReservedViewportIfNeeded(m2::RectD const & viewport); - - /// Check for localities in pre-cached viewports only. - void GetLocalityInViewport(m2::PointD const & pt, string & name) const; - /// Check for localities in all Index and make new cache if needed. - void GetLocalityCreateCache(m2::PointD const & pt, string & name); - - void ClearCacheAll(); - void ClearCache(size_t idx); + void GetLocality(m2::PointD const & pt, string & name); + void ClearCache(); protected: - void CorrectMinimalRect(m2::RectD & rect) const; - void RecreateCache(Cache & cache, m2::RectD rect) const; + void UpdateCache(Cache & cache, m2::PointD const & pt) const; private: friend class DoLoader; Index const * m_pIndex; - enum { MAX_VIEWPORT_COUNT = 3 }; - Cache m_cache[MAX_VIEWPORT_COUNT]; + Cache m_caches[10]; int8_t m_lang; }; diff --git a/search/search_query.cpp b/search/search_query.cpp index ec58199799..5359fec3f9 100644 --- a/search/search_query.cpp +++ b/search/search_query.cpp @@ -251,18 +251,10 @@ void Query::SetViewportByIndex(TMWMVector const & mwmsInfo, m2::RectD const & vi } m_viewport[idx] = viewport; - -#ifdef FIND_LOCALITY_TEST - m_locality.SetViewportByIndex(viewport, idx); -#endif } else { ClearCache(idx); - -#ifdef FIND_LOCALITY_TEST - m_locality.ClearCache(idx); -#endif } } @@ -315,7 +307,7 @@ void Query::ClearCaches() for (size_t i = 0; i < COUNT_V; ++i) ClearCache(i); - m_locality.ClearCacheAll(); + m_locality.ClearCache(); } void Query::ClearCache(size_t ind) @@ -927,16 +919,15 @@ public: Result Query::MakeResult(impl::PreResult2 const & r) const { - Result res = - r.GenerateFinalResult(m_infoGetter, &m_categories, &m_prefferedTypes, m_currentLocaleCode, - m_reverseGeocoder); + Result res = r.GenerateFinalResult(m_infoGetter, &m_categories, &m_prefferedTypes, + m_currentLocaleCode, m_reverseGeocoder); MakeResultHighlight(res); #ifdef FIND_LOCALITY_TEST if (ftypes::IsLocalityChecker::Instance().GetType(r.GetTypes()) == ftypes::NONE) { string city; - m_locality.GetLocalityInViewport(res.GetFeatureCenter(), city); + m_locality.GetLocality(res.GetFeatureCenter(), city); res.AppendCity(city); } #endif diff --git a/search/search_query.hpp b/search/search_query.hpp index 98da2e571b..3fa7036cde 100644 --- a/search/search_query.hpp +++ b/search/search_query.hpp @@ -209,7 +209,7 @@ protected: set m_prefferedTypes; #ifdef FIND_LOCALITY_TEST - LocalityFinder m_locality; + mutable LocalityFinder m_locality; #endif m2::RectD m_viewport[COUNT_V]; diff --git a/search/search_tests/locality_finder_test.cpp b/search/search_tests/locality_finder_test.cpp index ac45ebf6e9..8988324851 100644 --- a/search/search_tests/locality_finder_test.cpp +++ b/search/search_tests/locality_finder_test.cpp @@ -51,42 +51,25 @@ public: platform::CountryIndexes::DeleteFromDisk(m_worldFile); } - void RunTestsViewport(vector const & input, char const * results[]) + void RunTests(vector const & input, char const * results[]) { for (size_t i = 0; i < input.size(); ++i) { string result; - m_finder.GetLocalityInViewport(MercatorBounds::FromLatLon(input[i]), result); - TEST_EQUAL(result, results[i], ()); - } - } - - void RunTestsEverywhere(vector const & input, char const * results[]) - { - for (size_t i = 0; i < input.size(); ++i) - { - string result; - m_finder.GetLocalityCreateCache(MercatorBounds::FromLatLon(input[i]), result); + m_finder.GetLocality(MercatorBounds::FromLatLon(input[i]), result); TEST_EQUAL(result, results[i], ()); } } m2::RectD const & GetWorldRect() const { return m_worldRect; } - void SetViewportByIndex(m2::RectD const & viewport, size_t ind) - { - m_finder.SetViewportByIndex(viewport, ind); - } - void ClearCaches() { m_finder.ClearCacheAll(); } + + void ClearCaches() { m_finder.ClearCache(); } }; } // namespace -/* UNIT_CLASS_TEST(LocalityFinderTest, Smoke) { - m2::RectD const & rect = GetWorldRect(); - SetViewportByIndex(rect, 0); - vector input; input.emplace_back(53.8993094, 27.5433964); // Minsk input.emplace_back(48.856517, 2.3521); // Paris @@ -99,51 +82,20 @@ UNIT_CLASS_TEST(LocalityFinderTest, Smoke) "Berlin" }; - // Tets one viewport based on whole map - RunTestsViewport(input, results); - - // Test two viewport based on quaters of world map - m2::RectD rect1; - rect1.setMinX(rect.minX()); - rect1.setMinY(rect.minY()); - rect1.setMaxX(rect.Center().x); - rect1.setMaxY(rect.Center().y); - - m2::RectD rect2; - rect2.setMinX(rect.Center().x); - rect2.setMinY(rect.Center().y); - rect2.setMaxY(rect.maxY()); - rect2.setMaxX(rect.maxX()); + RunTests(input, results); + ClearCaches(); input.clear(); + input.emplace_back(41.875, -87.624367); // Chicago input.emplace_back(-22.911225, -43.209384); // Rio de Janeiro input.emplace_back(-37.8142, 144.96); // Melbourne (Australia) - input.emplace_back(53.883931, 27.69341); // Parkin Minsk (near MKAD) + input.emplace_back(53.883931, 27.69341); // Parking Minsk (near MKAD) input.emplace_back(53.917306, 27.707875); // Lipki airport (Minsk) input.emplace_back(42.285901, 18.834407); // Budva (Montenegro) input.emplace_back(41.903479, 12.452854); // Vaticano (Rome) input.emplace_back(47.3345002, 8.531262); // Zurich - SetViewportByIndex(rect1, 0); - SetViewportByIndex(rect2, 1); - - char const * results2[] = - { - "", - "Rio de Janeiro", - "", - "Minsk", - "Minsk", - "Budva", - "Rome", - "Zurich" - }; - - RunTestsViewport(input, results2); - - ClearCaches(); - char const * results3[] = { "Chicago", @@ -156,9 +108,8 @@ UNIT_CLASS_TEST(LocalityFinderTest, Smoke) "Zurich" }; - RunTestsEverywhere(input, results3); + RunTests(input, results3); } -*/ UNIT_CLASS_TEST(LocalityFinderTest, Moscow) { @@ -170,5 +121,5 @@ UNIT_CLASS_TEST(LocalityFinderTest, Moscow) "Moscow" }; - RunTestsEverywhere(input, results); + RunTests(input, results); }