From b68ac4e65606e633ef5a364fce43f04abe6a89d1 Mon Sep 17 00:00:00 2001 From: Denis Koronchik Date: Mon, 30 Jun 2014 18:28:13 +0300 Subject: [PATCH] Added country and city into address search results --- search/locality_finder.cpp | 72 ++++++++++++++++---- search/locality_finder.hpp | 37 ++++++---- search/search_query.cpp | 15 +++- search/search_tests/locality_finder_test.cpp | 38 +++++++++-- 4 files changed, 125 insertions(+), 37 deletions(-) diff --git a/search/locality_finder.cpp b/search/locality_finder.cpp index c3aa157fc7..4c42858e6a 100644 --- a/search/locality_finder.cpp +++ b/search/locality_finder.cpp @@ -9,12 +9,12 @@ namespace search { -double const MAX_RADIUS_M = 30000.0; +double const MAX_RADIUS_CITY = 30000.0; class DoLoader { public: - DoLoader(LocalityFinder & finder, FeaturesVector const & loader, LocalityFinder::Cache & cache, m2::RectD const & rect) + DoLoader(LocalityFinder const & finder, FeaturesVector const & loader, LocalityFinder::Cache & cache, m2::RectD const & rect) : m_finder(finder), m_loader(loader), m_cache(cache), m_rect(rect) { } @@ -61,7 +61,7 @@ public: } private: - LocalityFinder & m_finder; + LocalityFinder const & m_finder; FeaturesVector const & m_loader; LocalityFinder::Cache & m_cache; m2::RectD m_rect; @@ -111,21 +111,22 @@ LocalityFinder::LocalityFinder(Index const * pIndex) { } -void LocalityFinder::CorrectMinimalRect(m2::RectD & rect) +void LocalityFinder::CorrectMinimalRect(m2::RectD & rect) const { - m2::RectD const rlt = MercatorBounds::RectByCenterXYAndSizeInMeters(rect.LeftTop(), MAX_RADIUS_M); - m2::RectD const rrb = MercatorBounds::RectByCenterXYAndSizeInMeters(rect.RightBottom(), MAX_RADIUS_M); + 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())); } -void LocalityFinder::SetViewportByIndex(MWMVectorT const & mwmInfo, m2::RectD rect, size_t idx) +void LocalityFinder::RecreateCache(Cache & cache, m2::RectD rect) const { - ASSERT_LESS(idx, (size_t)MAX_VIEWPORT_COUNT, ()); + vector mwmInfo; + m_pIndex->GetMwmInfo(mwmInfo); - ClearCache(idx); + cache.Clear(); CorrectMinimalRect(rect); covering::CoveringGetter cov(rect, covering::ViewportWithLowLevels); @@ -133,7 +134,6 @@ void LocalityFinder::SetViewportByIndex(MWMVectorT const & mwmInfo, m2::RectD re for (MwmSet::MwmId mwmId = 0; mwmId < mwmInfo.size(); ++mwmId) { typedef feature::DataHeader HeaderT; - Index::MwmLock mwmLock(*m_pIndex, mwmId); MwmValue * pMwm = mwmLock.GetValue(); if (pMwm && pMwm->GetHeader().GetType() == HeaderT::world) @@ -147,9 +147,10 @@ void LocalityFinder::SetViewportByIndex(MWMVectorT const & mwmInfo, m2::RectD re FeaturesVector loader(pMwm->m_cont, header); + cache.m_rect = rect; for (size_t i = 0; i < interval.size(); ++i) { - index.ForEachInIntervalAndScale(DoLoader(*this, loader, m_cache[idx], rect), + index.ForEachInIntervalAndScale(DoLoader(*this, loader, cache, rect), interval[i].first, interval[i].second, scale); } @@ -157,16 +158,49 @@ void LocalityFinder::SetViewportByIndex(MWMVectorT const & mwmInfo, m2::RectD re } } -void LocalityFinder::GetLocality(const m2::PointD & pt, string & name) const +void LocalityFinder::SetViewportByIndex(m2::RectD const & rect, size_t idx) +{ + ASSERT_LESS(idx, (size_t)MAX_VIEWPORT_COUNT, ()); + RecreateCache(m_cache[idx], rect); +} + +void LocalityFinder::GetLocalityInViewport(const m2::PointD & pt, string & name) const { for (size_t i = 0; i < MAX_VIEWPORT_COUNT; ++i) - m_cache[i].m_tree.ForEachInRect(m2::RectD(pt, pt), DoSelectLocality(name, pt)); + m_cache[i].GetLocality(pt, name); +} + +void LocalityFinder::GetLocalityCreateCache(const m2::PointD & pt, string & name) const +{ + // 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_CACHE_TMP_COUNT; ++idx) + { + Cache const & cache = m_cache_tmp[idx]; + cache.GetLocality(pt, name); + if (!name.empty()) + return; + + if (cache.m_usage < minUsage) + { + minUsage = cache.m_usage; + minUsageIdx = idx; + } + } + + Cache & cache = m_cache_tmp[minUsageIdx]; + RecreateCache(cache, MercatorBounds::RectByCenterXYAndSizeInMeters(pt, MAX_RADIUS_CITY)); + cache.GetLocality(pt, name); } void LocalityFinder::ClearCacheAll() { for (size_t i = 0; i < MAX_VIEWPORT_COUNT; ++i) ClearCache(i); + + for (size_t i = 0; i < MAX_CACHE_TMP_COUNT; ++i) + m_cache_tmp[i].Clear(); } void LocalityFinder::ClearCache(size_t idx) @@ -175,10 +209,22 @@ void LocalityFinder::ClearCache(size_t idx) m_cache[idx].Clear(); } + + void LocalityFinder::Cache::Clear() { + m_usage = 0; m_tree.Clear(); m_loaded.clear(); } +void LocalityFinder::Cache::GetLocality(m2::PointD const & pt, string & name) const +{ + if (!m_rect.IsPointInside(pt)) + return; + + ++m_usage; + m_tree.ForEachInRect(m2::RectD(pt, pt), DoSelectLocality(name, pt)); +} + } diff --git a/search/locality_finder.hpp b/search/locality_finder.hpp index ebcdc102e2..b061f629d5 100644 --- a/search/locality_finder.hpp +++ b/search/locality_finder.hpp @@ -30,9 +30,21 @@ struct LocalityItem class LocalityFinder { -public: - typedef vector MWMVectorT; + struct Cache + { + m4::Tree m_tree; + set m_loaded; + mutable uint32_t m_usage; + m2::RectD m_rect; + + Cache() : m_usage(0) {} + + void Clear(); + void GetLocality(m2::PointD const & pt, string & name) const; + }; + +public: LocalityFinder(Index const * pIndex); void SetLanguage(int8_t lang) @@ -44,31 +56,28 @@ public: } } - void SetViewportByIndex(MWMVectorT const & mwmInfo, m2::RectD rect, size_t idx); + void SetViewportByIndex(m2::RectD const & rect, size_t idx); - void GetLocality(m2::PointD const & pt, string & name) const; + /// Check for localities in pre-cached viewports only. + void GetLocalityInViewport(m2::PointD const & pt, string & name) const; + /// Checl for localities in all Index and make new cache if needed. + void GetLocalityCreateCache(m2::PointD const & pt, string & name) const; void ClearCacheAll(); void ClearCache(size_t idx); protected: - void CorrectMinimalRect(m2::RectD & rect); + void CorrectMinimalRect(m2::RectD & rect) const; + void RecreateCache(Cache & cache, m2::RectD rect) const; private: friend class DoLoader; Index const * m_pIndex; - struct Cache - { - m4::Tree m_tree; - set m_loaded; - - void Clear(); - }; - - enum { MAX_VIEWPORT_COUNT = 3 }; + enum { MAX_VIEWPORT_COUNT = 3, MAX_CACHE_TMP_COUNT = 4}; Cache m_cache[MAX_VIEWPORT_COUNT]; + mutable Cache m_cache_tmp[MAX_CACHE_TMP_COUNT]; int8_t m_lang; }; diff --git a/search/search_query.cpp b/search/search_query.cpp index bf121e6b30..39d9dff75b 100644 --- a/search/search_query.cpp +++ b/search/search_query.cpp @@ -164,7 +164,7 @@ void Query::SetViewportByIndex(MWMVectorT const & mwmInfo, m2::RectD const & vie UpdateViewportOffsets(mwmInfo, viewport, m_offsetsInViewport[idx]); #ifdef FIND_LOCALITY_TEST - m_locality.SetViewportByIndex(mwmInfo, viewport, idx); + m_locality.SetViewportByIndex(viewport, idx); #endif } } @@ -664,9 +664,18 @@ void Query::FlushHouses(Results & res, bool allMWMs, vector const & s for (size_t i = 0; i < count; ++i) { House const * h = houses[i].m_house; + storage::CountryInfo countryInfo; + m_pInfoGetter->GetRegionInfo(h->GetPosition(), countryInfo); + Result r(h->GetPosition(), h->GetNumber() + ", " + houses[i].m_street->GetName(), - string(), string(), IsValidPosition() ? h->GetPosition().Length(m_position) : -1.0); + countryInfo.m_name, string(), IsValidPosition() ? h->GetPosition().Length(m_position) : -1.0); + MakeResultHighlight(r); +#ifdef FIND_LOCALITY_TEST + string city; + m_locality.GetLocalityCreateCache(r.GetFeatureCenter(), city); + r.AppendCity(city); +#endif (res.*addFn)(r); } } @@ -961,7 +970,7 @@ Result Query::MakeResult(impl::PreResult2 const & r) const if (ftypes::IsLocalityChecker::Instance().GetType(r.GetTypes()) == ftypes::NONE) { string city; - m_locality.GetLocality(res.GetFeatureCenter(), city); + m_locality.GetLocalityInViewport(res.GetFeatureCenter(), city); res.AppendCity(city); } #endif diff --git a/search/search_tests/locality_finder_test.cpp b/search/search_tests/locality_finder_test.cpp index 7b4a4a8898..3efc9d0a2f 100644 --- a/search/search_tests/locality_finder_test.cpp +++ b/search/search_tests/locality_finder_test.cpp @@ -11,7 +11,18 @@ void doTests(search::LocalityFinder & finder, vector const & input, for (size_t i = 0; i < input.size(); ++i) { string result; - finder.GetLocality(m2::PointD(MercatorBounds::LonToX(input[i].x), MercatorBounds::LatToY(input[i].y)), result); + finder.GetLocalityInViewport(m2::PointD(MercatorBounds::LonToX(input[i].x), MercatorBounds::LatToY(input[i].y)), result); + TEST_EQUAL(result, results[i], ()); + } +} + + +void doTests2(search::LocalityFinder & finder, vector const & input, char const * results[]) +{ + for (size_t i = 0; i < input.size(); ++i) + { + string result; + finder.GetLocalityCreateCache(m2::PointD(MercatorBounds::LonToX(input[i].x), MercatorBounds::LatToY(input[i].y)), result); TEST_EQUAL(result, results[i], ()); } } @@ -30,10 +41,7 @@ UNIT_TEST(LocalityFinder) search::LocalityFinder finder(&index); finder.SetLanguage(StringUtf8Multilang::GetLangIndex("en")); - - search::LocalityFinder::MWMVectorT mwm; - index.GetMwmInfo(mwm); - finder.SetViewportByIndex(mwm, MercatorBounds::FullRect(), 0); + finder.SetViewportByIndex(MercatorBounds::FullRect(), 0); vector input; input.push_back(m2::PointD(27.5433964, 53.8993094)); // Minsk @@ -73,8 +81,8 @@ UNIT_TEST(LocalityFinder) input.push_back(m2::PointD(12.452854, 41.903479)); // Vaticano (Rome) input.push_back(m2::PointD(8.531262, 47.3345002)); // Zurich - finder.SetViewportByIndex(mwm, rect1, 0); - finder.SetViewportByIndex(mwm, rect2, 1); + finder.SetViewportByIndex(rect1, 0); + finder.SetViewportByIndex(rect2, 1); char const * results2[] = { @@ -89,4 +97,20 @@ UNIT_TEST(LocalityFinder) }; doTests(finder, input, results2); + + finder.ClearCacheAll(); + + char const * results3[] = + { + "Chicago", + "Rio de Janeiro", + "Melbourne", + "Minsk", + "Minsk", + "Budva", + "Rome", + "Zurich" + }; + + doTests2(finder, input, results3); }