diff --git a/search/intermediate_result.cpp b/search/intermediate_result.cpp index d76016d4b0..0cdedb1ff1 100644 --- a/search/intermediate_result.cpp +++ b/search/intermediate_result.cpp @@ -7,6 +7,7 @@ #include "indexer/categories_holder.hpp" #include "indexer/classificator.hpp" #include "indexer/feature.hpp" +#include "indexer/feature_algo.hpp" #include "indexer/ftypes_matcher.hpp" #include "indexer/scales.hpp" @@ -81,12 +82,6 @@ bool PreResult1::LessPriority(PreResult1 const & r1, PreResult1 const & r2) return r1.m_info.m_rank > r2.m_info.m_rank; } -// static -bool PreResult1::LessPointsForViewport(PreResult1 const & r1, PreResult1 const & r2) -{ - return r1.m_id < r2.m_id; -} - PreResult2::PreResult2(FeatureType const & f, PreResult1 const * p, m2::PointD const & pivot, string const & displayName, string const & fileName) : m_id(f.GetID()), @@ -100,10 +95,9 @@ PreResult2::PreResult2(FeatureType const & f, PreResult1 const * p, m2::PointD c m_types.SortBySpec(); - m2::PointD fCenter; - fCenter = f.GetLimitRect(FeatureType::WORST_GEOMETRY).Center(); + auto const center = feature::GetCenter(f); - m_region.SetParams(fileName, fCenter); + m_region.SetParams(fileName, center); m_distance = PointDistance(GetCenter(), pivot); ProcessMetadata(f, m_metadata); @@ -215,22 +209,6 @@ Result PreResult2::GenerateFinalResult(storage::CountryInfoGetter const & infoGe } } -// static -bool PreResult2::LessRank(PreResult2 const & r1, PreResult2 const & r2) -{ - if (r1.m_info.m_rank != r2.m_info.m_rank) - return r1.m_info.m_rank > r2.m_info.m_rank; - return r1.m_distance < r2.m_distance; -} - -// static -bool PreResult2::LessDistance(PreResult2 const & r1, PreResult2 const & r2) -{ - if (r1.m_distance != r2.m_distance) - return r1.m_distance < r2.m_distance; - return r1.m_info.m_rank > r2.m_info.m_rank; -} - bool PreResult2::StrictEqualF::operator() (PreResult2 const & r) const { if (m_r.m_resultType == r.m_resultType && m_r.m_resultType == RESULT_FEATURE) diff --git a/search/intermediate_result.hpp b/search/intermediate_result.hpp index 5fe416505b..6a213acb1f 100644 --- a/search/intermediate_result.hpp +++ b/search/intermediate_result.hpp @@ -40,7 +40,6 @@ public: static bool LessRank(PreResult1 const & r1, PreResult1 const & r2); static bool LessPriority(PreResult1 const & r1, PreResult1 const & r2); - static bool LessPointsForViewport(PreResult1 const & r1, PreResult1 const & r2); inline FeatureID GetID() const { return m_id; } inline double GetPriority() const { return m_priority; } @@ -87,9 +86,6 @@ public: CategoriesHolder const * pCat, set const * pTypes, int8_t locale, ReverseGeocoder const & coder) const; - static bool LessRank(PreResult2 const & r1, PreResult2 const & r2); - static bool LessDistance(PreResult2 const & r1, PreResult2 const & r2); - /// Filter equal features for different mwm's. class StrictEqualF { diff --git a/search/search_query.cpp b/search/search_query.cpp index 5359fec3f9..8ac47833d1 100644 --- a/search/search_query.cpp +++ b/search/search_query.cpp @@ -51,6 +51,7 @@ #include "std/function.hpp" #include "std/iterator.hpp" #include "std/limits.hpp" +#include "std/random.hpp" #define LONG_OP(op) \ { \ @@ -162,6 +163,27 @@ void RemoveDuplicatingLinear(vector & indV) }), indV.end()); } + +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); + viewport.Add(minViewport); + + m2::RectD maxViewport = + MercatorBounds::RectByCenterXYAndSizeInMeters(viewport.Center(), kMaxViewportRadiusM); + VERIFY(viewport.Intersect(maxViewport), ()); + return viewport; +} + +m2::RectD GetRectAroundPosition(m2::PointD const & position) +{ + double constexpr kMaxPositionRadiusM = 50.0 * 1000; + return MercatorBounds::RectByCenterXYAndSizeInMeters(position, kMaxPositionRadiusM); +} } // namespace // static @@ -207,6 +229,22 @@ int8_t Query::GetLanguage(int id) const return m_keywordsScorer.GetLanguage(GetLangIndex(id)); } +m2::PointD Query::GetPivotPoint() const +{ + m2::RectD const & viewport = m_viewport[CURRENT_V]; + if (viewport.IsPointInside(GetPosition())) + return GetPosition(); + return viewport.Center(); +} + +m2::RectD Query::GetPivotRect() const +{ + m2::RectD const & viewport = m_viewport[CURRENT_V]; + if (viewport.IsPointInside(GetPosition())) + return GetRectAroundPosition(GetPosition()); + return NormalizeViewport(viewport); +} + void Query::SetViewport(m2::RectD const & viewport, bool forceUpdate) { Reset(); @@ -541,9 +579,10 @@ class PreResult2Maker search::v2::RankingInfo & info) { auto const & preInfo = res.GetInfo(); - m2::PointD pivot = m_params.m_pivot.Center(); - info.m_distanceToPivot = feature::GetMinDistanceMeters(ft, pivot); + auto const & pivot = m_params.m_pivotCenter; + + info.m_distanceToPivot = MercatorBounds::DistanceOnEarth(feature::GetCenter(ft), pivot); info.m_rank = preInfo.m_rank; info.m_searchType = preInfo.m_searchType; @@ -592,8 +631,7 @@ public: string name, country; LoadFeature(res1.GetID(), ft, name, country); - Query::ViewportID const viewportID = static_cast(res1.GetViewportID()); - auto res2 = make_unique(ft, &res1, m_query.GetPosition(viewportID), name, country); + auto res2 = make_unique(ft, &res1, m_query.GetPosition(), name, country); search::v2::RankingInfo info; InitRankingInfo(ft, res1, info); res2->SetRankingInfo(move(info)); @@ -660,9 +698,17 @@ void Query::MakePreResult2(v2::Geocoder::Params const & params, vector & cont for (; e != m_results.end() && e->GetPriority() == lastPriority; ++e) ; - // TODO (@y, @m, @vng): this method is deprecated, need to rewrite - // it. - random_shuffle(b, e); + // The main reason of shuffling here is to select a random subset + // from the low-priority results. We're using a linear congruental + // method with default seed because it is fast, simple and doesn't + // need an external entropy source. + // + // TODO (@y, @m, @vng): consider to take some kind of hash from + // features and then select a subset with smallest values of this + // hash. In this case this subset of results will be persistent + // to small changes in the original set. + minstd_rand engine; + shuffle(b, e, engine); } theSet.insert(m_results.begin(), m_results.begin() + min(m_results.size(), kPreResultsCount)); @@ -1633,17 +1679,6 @@ m2::RectD const & Query::GetViewport(ViewportID vID /*= DEFAULT_V*/) const return m_viewport[CURRENT_V]; } -m2::PointD Query::GetPosition(ViewportID vID /*= DEFAULT_V*/) const -{ - switch (vID) - { - case LOCALITY_V: // center of the founded locality - return m_viewport[vID].Center(); - default: - return m_pivot; - } -} - string DebugPrint(Query::ViewportID viewportId) { switch (viewportId) diff --git a/search/search_query.hpp b/search/search_query.hpp index 3fa7036cde..3dc5b8efc9 100644 --- a/search/search_query.hpp +++ b/search/search_query.hpp @@ -80,9 +80,12 @@ public: /// @param[in] forceUpdate Pass true (default) to recache feature's ids even /// if viewport is a part of the old cached rect. void SetViewport(m2::RectD const & viewport, bool forceUpdate); + + // TODO (@y): this function must be removed. void SetRankPivot(m2::PointD const & pivot); inline string const & GetPivotRegion() const { return m_region; } inline void SetPosition(m2::PointD const & position) { m_position = position; } + inline m2::PointD const & GetPosition() const { return m_position; } inline void SetMode(Mode mode) { m_mode = mode; } inline void SetSearchInWorld(bool b) { m_worldSearch = b; } @@ -147,6 +150,9 @@ protected: using TOffsetsVector = map>; using TFHeader = feature::DataHeader; + m2::PointD GetPivotPoint() const; + m2::RectD GetPivotRect() const; + void SetViewportByIndex(TMWMVector const & mwmsInfo, m2::RectD const & viewport, size_t idx, bool forceUpdate); void ClearCache(size_t ind); @@ -223,8 +229,6 @@ protected: //@{ /// @return Rect for viewport-distance calculation. m2::RectD const & GetViewport(ViewportID vID = DEFAULT_V) const; - /// @return Control point for distance-to calculation. - m2::PointD GetPosition(ViewportID vID = DEFAULT_V) const; //@} void SetLanguage(int id, int8_t lang); diff --git a/search/v2/geocoder.cpp b/search/v2/geocoder.cpp index 76b8ea8518..b96beace65 100644 --- a/search/v2/geocoder.cpp +++ b/search/v2/geocoder.cpp @@ -399,7 +399,7 @@ bool SameMwm(Geocoder::TResult const & lhs, Geocoder::TResult const & rhs) } // namespace // Geocoder::Params -------------------------------------------------------------------------------- -Geocoder::Params::Params() : m_mode(Mode::Everywhere), m_maxNumResults(0) {} +Geocoder::Params::Params() : m_mode(Mode::Everywhere), m_pivotCenter(0, 0), m_maxNumResults(0) {} // Geocoder::Geocoder ------------------------------------------------------------------------------ Geocoder::Geocoder(Index & index, storage::CountryInfoGetter const & infoGetter) @@ -1312,7 +1312,7 @@ void Geocoder::FillMissingFieldsInResults() if (m_results->size() > m_params.m_maxNumResults) { - m_pivotFeatures.SetPosition(m_params.m_pivot.Center(), m_params.m_scale); + m_pivotFeatures.SetPosition(m_params.m_pivotCenter, m_params.m_scale); for (auto & result : *m_results) { auto const & id = result.first; diff --git a/search/v2/geocoder.hpp b/search/v2/geocoder.hpp index c463def0a4..78b074c272 100644 --- a/search/v2/geocoder.hpp +++ b/search/v2/geocoder.hpp @@ -76,7 +76,13 @@ public: Params(); Mode m_mode; + + // We need to pass both pivot and pivot center because pivot is + // usually a rectangle created by radius and center, and due to + // precision loss, |m_pivot|.Center() may differ from + // |m_pivotCenter|. m2::RectD m_pivot; + m2::PointD m_pivotCenter; size_t m_maxNumResults; }; diff --git a/search/v2/search_query_v2.cpp b/search/v2/search_query_v2.cpp index 63246c302c..33b4fa0549 100644 --- a/search/v2/search_query_v2.cpp +++ b/search/v2/search_query_v2.cpp @@ -13,30 +13,6 @@ namespace search { namespace v2 { -namespace -{ -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); - viewport.Add(minViewport); - - m2::RectD maxViewport = - MercatorBounds::RectByCenterXYAndSizeInMeters(viewport.Center(), kMaxViewportRadiusM); - VERIFY(viewport.Intersect(maxViewport), ()); - return viewport; -} - -m2::RectD GetRectAroundPosition(m2::PointD const & position) -{ - double constexpr kMaxPositionRadiusM = 50.0 * 1000; - return MercatorBounds::RectByCenterXYAndSizeInMeters(position, kMaxPositionRadiusM); -} -} // namespace - SearchQueryV2::SearchQueryV2(Index & index, CategoriesHolder const & categories, vector const & suggests, storage::CountryInfoGetter const & infoGetter) @@ -66,12 +42,8 @@ void SearchQueryV2::Search(Results & res, size_t resCount) InitParams(false /* localitySearch */, params); params.m_mode = m_mode; - m2::RectD const & viewport = m_viewport[CURRENT_V]; - if (viewport.IsPointInside(m_position)) - params.m_pivot = GetRectAroundPosition(m_position); - else - params.m_pivot = NormalizeViewport(viewport); - + params.m_pivot = GetPivotRect(); + params.m_pivotCenter = GetPivotPoint(); params.m_maxNumResults = max(resCount, kPreResultsCount); m_geocoder.SetParams(params); diff --git a/std/random.hpp b/std/random.hpp index e90db2357c..04ac1483a9 100644 --- a/std/random.hpp +++ b/std/random.hpp @@ -7,6 +7,7 @@ #include using std::default_random_engine; +using std::minstd_rand; using std::mt19937; using std::uniform_int_distribution;