From 78694f08ea9bb948413414309721b4ccd6198718 Mon Sep 17 00:00:00 2001 From: Yuri Gorshenin Date: Tue, 22 Mar 2016 16:53:46 +0300 Subject: [PATCH] Review fixes. --- search/search_query.cpp | 11 ++--- search/search_query.hpp | 3 ++ search/v2/geocoder.cpp | 4 +- search/v2/geocoder.hpp | 4 +- search/v2/geometry_cache.cpp | 87 +++++++++++++++++++++--------------- search/v2/geometry_cache.hpp | 77 ++++++++++++++++++++++++------- 6 files changed, 125 insertions(+), 61 deletions(-) diff --git a/search/search_query.cpp b/search/search_query.cpp index c14fb066f7..682419c431 100644 --- a/search/search_query.cpp +++ b/search/search_query.cpp @@ -166,15 +166,12 @@ void RemoveDuplicatingLinear(vector & indV) m2::RectD NormalizeViewport(m2::RectD viewport) { - double constexpr kMinViewportRadiusM = 5.0 * 1000; - double constexpr kMaxViewportRadiusM = 50.0 * 1000; - m2::RectD minViewport = - MercatorBounds::RectByCenterXYAndSizeInMeters(viewport.Center(), kMinViewportRadiusM); + MercatorBounds::RectByCenterXYAndSizeInMeters(viewport.Center(), Query::kMinViewportRadiusM); viewport.Add(minViewport); m2::RectD maxViewport = - MercatorBounds::RectByCenterXYAndSizeInMeters(viewport.Center(), kMaxViewportRadiusM); + MercatorBounds::RectByCenterXYAndSizeInMeters(viewport.Center(), Query::kMaxViewportRadiusM); VERIFY(viewport.Intersect(maxViewport), ()); return viewport; } @@ -189,6 +186,10 @@ m2::RectD GetRectAroundPosition(m2::PointD const & position) // static size_t const Query::kPreResultsCount; +// static +double const Query::kMinViewportRadiusM = 5.0 * 1000; +double const Query::kMaxViewportRadiusM = 50.0 * 1000; + Query::Query(Index & index, CategoriesHolder const & categories, vector const & suggests, storage::CountryInfoGetter const & infoGetter) : m_index(index) diff --git a/search/search_query.hpp b/search/search_query.hpp index 3dc5b8efc9..c0233bbb34 100644 --- a/search/search_query.hpp +++ b/search/search_query.hpp @@ -70,6 +70,9 @@ public: // Maximum result candidates count for each viewport/criteria. static size_t const kPreResultsCount = 200; + static double const kMinViewportRadiusM; + static double const kMaxViewportRadiusM; + Query(Index & index, CategoriesHolder const & categories, vector const & suggests, storage::CountryInfoGetter const & infoGetter); diff --git a/search/v2/geocoder.cpp b/search/v2/geocoder.cpp index 9b9c18cf44..a28b86dcd2 100644 --- a/search/v2/geocoder.cpp +++ b/search/v2/geocoder.cpp @@ -2,6 +2,7 @@ #include "search/dummy_rank_table.hpp" #include "search/retrieval.hpp" +#include "search/search_query.hpp" #include "search/v2/cbv_ptr.hpp" #include "search/v2/features_filter.hpp" #include "search/v2/features_layer_matcher.hpp" @@ -420,7 +421,8 @@ Geocoder::Geocoder(Index & index, storage::CountryInfoGetter const & infoGetter) , m_infoGetter(infoGetter) , m_numTokens(0) , m_model(SearchModel::Instance()) - , m_pivotRectsCache(kPivotRectsCacheSize, static_cast(*this)) + , m_pivotRectsCache(kPivotRectsCacheSize, static_cast(*this), + Query::kMaxViewportRadiusM) , m_localityRectsCache(kLocalityRectsCacheSize, static_cast(*this)) , m_pivotFeatures(index) , m_streets(nullptr) diff --git a/search/v2/geocoder.hpp b/search/v2/geocoder.hpp index 0c14d6acc1..3cdefc2a22 100644 --- a/search/v2/geocoder.hpp +++ b/search/v2/geocoder.hpp @@ -309,8 +309,8 @@ private: // Caches of features in rects. These caches are separated from // TLocalitiesCache because the latter are quite lightweight and not // all of them are needed. - GeometryCache m_pivotRectsCache; - GeometryCache m_localityRectsCache; + PivotRectsCache m_pivotRectsCache; + LocalityRectsCache m_localityRectsCache; // Cache of nested rects used to estimate distance from a feature to the pivot. NestedRectsCache m_pivotFeatures; diff --git a/search/v2/geometry_cache.cpp b/search/v2/geometry_cache.cpp index 0779771c0e..2884e76aa1 100644 --- a/search/v2/geometry_cache.cpp +++ b/search/v2/geometry_cache.cpp @@ -1,66 +1,79 @@ #include "search/v2/geometry_cache.hpp" +#include "search/geometry_utils.hpp" #include "search/retrieval.hpp" #include "search/v2/mwm_context.hpp" #include "geometry/mercator.hpp" -#include "base/assert.hpp" - -#include "std/algorithm.hpp" -#include "std/utility.hpp" - namespace search { namespace v2 { namespace { -double constexpr kComparePoints = MercatorBounds::GetCellID2PointAbsEpsilon(); +double constexpr kCellEps = MercatorBounds::GetCellID2PointAbsEpsilon(); } // namespace -GeometryCache::Entry::Entry() : m_scale(0) {} - -GeometryCache::Entry::Entry(m2::RectD const & lowerBound, m2::RectD const & upperBound, - unique_ptr cbv, int scale) - : m_lowerBound(lowerBound), m_upperBound(upperBound), m_cbv(move(cbv)), m_scale(scale) -{ -} - -bool GeometryCache::Entry::Matches(m2::RectD const & rect, int scale) const -{ - return m_scale == scale && rect.IsRectInside(m_lowerBound) && m_upperBound.IsRectInside(rect); -} - +// GeometryCache ----------------------------------------------------------------------------------- GeometryCache::GeometryCache(size_t maxNumEntries, my::Cancellable const & cancellable) : m_maxNumEntries(maxNumEntries), m_cancellable(cancellable) { CHECK_GREATER(m_maxNumEntries, 0, ()); } -coding::CompressedBitVector const * GeometryCache::Get(MwmContext const & context, - m2::RectD const & rect, int scale) +void GeometryCache::InitEntry(MwmContext const & context, m2::RectD const & rect, int scale, + Entry & entry) { - auto & entries = m_entries[context.GetId()]; - auto it = entries.begin(); - for (; it != entries.end() && !it->Matches(rect, scale); ++it) - ; - if (it != entries.end()) + entry.m_rect = rect; + entry.m_cbv = v2::RetrieveGeometryFeatures(context, m_cancellable, rect, scale); + entry.m_scale = scale; +} + +// PivotRectsCache --------------------------------------------------------------------------------- +PivotRectsCache::PivotRectsCache(size_t maxNumEntries, my::Cancellable const & cancellable, + double maxRadiusMeters) + : GeometryCache(maxNumEntries, cancellable), m_maxRadiusMeters(maxRadiusMeters) +{ +} + +coding::CompressedBitVector const * PivotRectsCache::Get(MwmContext const & context, + m2::RectD const & rect, int scale) +{ + auto p = FindOrCreateEntry(context.GetId(), [&rect, &scale](Entry const & entry) { - if (it != entries.begin()) - iter_swap(entries.begin(), it); - return entries.front().m_cbv.get(); + return scale == entry.m_scale && + (entry.m_rect.IsRectInside(rect) || IsEqualMercator(rect, entry.m_rect, kCellEps)); + }); + auto & entry = p.first; + if (p.second) + { + m2::RectD normRect = + MercatorBounds::RectByCenterXYAndSizeInMeters(rect.Center(), m_maxRadiusMeters); + if (!normRect.IsRectInside(rect)) + normRect = rect; + InitEntry(context, normRect, scale, entry); } + return entry.m_cbv.get(); +} - auto cbv = v2::RetrieveGeometryFeatures(context, m_cancellable, rect, scale); - entries.emplace_front(rect, m2::Inflate(rect, kComparePoints, kComparePoints), move(cbv), scale); - if (entries.size() == m_maxNumEntries + 1) - entries.pop_back(); +// LocalityRectsCache ------------------------------------------------------------------------------ +LocalityRectsCache::LocalityRectsCache(size_t maxNumEntries, my::Cancellable const & cancellable) + : GeometryCache(maxNumEntries, cancellable) +{ +} - ASSERT_LESS_OR_EQUAL(entries.size(), m_maxNumEntries, ()); - ASSERT(!entries.empty(), ()); - - return entries.front().m_cbv.get(); +coding::CompressedBitVector const * LocalityRectsCache::Get(MwmContext const & context, + m2::RectD const & rect, int scale) +{ + auto p = FindOrCreateEntry(context.GetId(), [&rect, &scale](Entry const & entry) + { + return scale == entry.m_scale && IsEqualMercator(rect, entry.m_rect, kCellEps); + }); + auto & entry = p.first; + if (p.second) + InitEntry(context, rect, scale, entry); + return entry.m_cbv.get(); } } // namespace v2 } // namespace search diff --git a/search/v2/geometry_cache.hpp b/search/v2/geometry_cache.hpp index 9b9b399bf5..62805918a5 100644 --- a/search/v2/geometry_cache.hpp +++ b/search/v2/geometry_cache.hpp @@ -6,10 +6,14 @@ #include "geometry/rect2d.hpp" +#include "base/assert.hpp" + +#include "std/algorithm.hpp" #include "std/cstdint.hpp" #include "std/deque.hpp" #include "std/map.hpp" #include "std/unique_ptr.hpp" +#include "std/utility.hpp" namespace my { @@ -28,37 +32,78 @@ class MwmContext; class GeometryCache { public: - // |maxNumEntries| denotes the maximum number of rectangles that - // will be cached for each mwm individually. - GeometryCache(size_t maxNumEntries, my::Cancellable const & cancellable); + virtual ~GeometryCache() = default; // Returns (hopefully, cached) list of features in a given // rect. Note that return value may be invalidated on next calls to // this method. - coding::CompressedBitVector const * Get(MwmContext const & context, m2::RectD const & rect, - int scale); + virtual coding::CompressedBitVector const * Get(MwmContext const & context, + m2::RectD const & rect, int scale) = 0; inline void Clear() { m_entries.clear(); } -private: +protected: struct Entry { - Entry(); - - Entry(m2::RectD const & lowerBound, m2::RectD const & upperBound, - unique_ptr cbv, int scale); - - bool Matches(m2::RectD const & rect, int scale) const; - - m2::RectD m_lowerBound; - m2::RectD m_upperBound; + m2::RectD m_rect; unique_ptr m_cbv; - int m_scale; + int m_scale = 0; }; + // |maxNumEntries| denotes the maximum number of rectangles that + // will be cached for each mwm individually. + GeometryCache(size_t maxNumEntries, my::Cancellable const & cancellable); + + template + pair FindOrCreateEntry(MwmSet::MwmId const & id, TPred && pred) + { + auto & entries = m_entries[id]; + auto it = find_if(entries.begin(), entries.end(), forward(pred)); + if (it != entries.end()) + { + if (it != entries.begin()) + iter_swap(entries.begin(), it); + return pair(entries.front(), false); + } + + entries.emplace_front(); + if (entries.size() == m_maxNumEntries + 1) + entries.pop_back(); + + ASSERT_LESS_OR_EQUAL(entries.size(), m_maxNumEntries, ()); + ASSERT(!entries.empty(), ()); + return pair(entries.front(), true); + } + + void InitEntry(MwmContext const & context, m2::RectD const & rect, int scale, Entry & entry); + map> m_entries; size_t const m_maxNumEntries; my::Cancellable const & m_cancellable; }; + +class PivotRectsCache : public GeometryCache +{ +public: + PivotRectsCache(size_t maxNumEntries, my::Cancellable const & cancellable, + double maxRadiusMeters); + + // GeometryCache overrides: + coding::CompressedBitVector const * Get(MwmContext const & context, m2::RectD const & rect, + int scale) override; + +private: + double const m_maxRadiusMeters; +}; + +class LocalityRectsCache : public GeometryCache +{ +public: + LocalityRectsCache(size_t maxNumEntries, my::Cancellable const & cancellable); + + // GeometryCache overrides: + coding::CompressedBitVector const * Get(MwmContext const & context, m2::RectD const & rect, + int scale) override; +}; } // namespace v2 } // namespace search