diff --git a/search/intermediate_result.cpp b/search/intermediate_result.cpp index 4af140add5..e48dedb208 100644 --- a/search/intermediate_result.cpp +++ b/search/intermediate_result.cpp @@ -89,6 +89,24 @@ bool PreRankerResult::LessDistance(PreRankerResult const & r1, PreRankerResult c return r1.m_info.m_rank > r2.m_info.m_rank; } +bool PreRankerResult::CategoriesComparator::operator()(PreRankerResult const & lhs, + PreRankerResult const & rhs) const +{ + if (m_positionIsInsideViewport) + return lhs.GetDistance() < rhs.GetDistance(); + + if (m_detailedScale) + { + bool const lhsInside = m_viewport.IsPointInside(lhs.GetInfo().m_center); + bool const rhsInside = m_viewport.IsPointInside(rhs.GetInfo().m_center); + if (lhsInside && !rhsInside) + return true; + if (rhsInside && !lhsInside) + return false; + } + return lhs.GetPopularity() > rhs.GetPopularity(); +} + // RankerResult ------------------------------------------------------------------------------------ RankerResult::RankerResult(FeatureType & f, m2::PointD const & center, m2::PointD const & pivot, string const & displayName, string const & fileName) diff --git a/search/intermediate_result.hpp b/search/intermediate_result.hpp index 16368a5f4b..86fcfb78e0 100644 --- a/search/intermediate_result.hpp +++ b/search/intermediate_result.hpp @@ -36,6 +36,15 @@ public: static bool LessRankAndPopularity(PreRankerResult const & r1, PreRankerResult const & r2); static bool LessDistance(PreRankerResult const & r1, PreRankerResult const & r2); + struct CategoriesComparator + { + bool operator()(PreRankerResult const & lhs, PreRankerResult const & rhs) const; + + m2::RectD m_viewport; + bool m_positionIsInsideViewport = false; + bool m_detailedScale = false; + }; + FeatureID const & GetId() const { return m_id; } double GetDistance() const { return m_info.m_distanceToPivot; } uint8_t GetRank() const { return m_info.m_rank; } @@ -76,7 +85,7 @@ public: template inline void SetRankingInfo(TInfo && info) { - m_info = forward(info); + m_info = std::forward(info); } FeatureID const & GetID() const { return m_id; } diff --git a/search/pre_ranker.cpp b/search/pre_ranker.cpp index 4db663baaf..f914574f7b 100644 --- a/search/pre_ranker.cpp +++ b/search/pre_ranker.cpp @@ -9,6 +9,7 @@ #include "indexer/rank_table.hpp" #include "indexer/scales.hpp" +#include "geometry/mercator.hpp" #include "geometry/nearby_points_sweeper.hpp" #include "base/random.hpp" @@ -190,14 +191,29 @@ void PreRanker::Filter(bool viewportSearch) set filtered; - filtered.insert(m_results.begin(), m_results.begin() + min(m_results.size(), BatchSize())); + auto const numResults = min(m_results.size(), BatchSize()); + filtered.insert(m_results.begin(), m_results.begin() + numResults); if (!viewportSearch) { - size_t n = min(m_results.size(), BatchSize()); - nth_element(m_results.begin(), m_results.begin() + n, m_results.end(), - &PreRankerResult::LessRankAndPopularity); - filtered.insert(m_results.begin(), m_results.begin() + n); + if (!m_params.m_categorialRequest) + { + nth_element(m_results.begin(), m_results.begin() + numResults, m_results.end(), + &PreRankerResult::LessRankAndPopularity); + } + else + { + double const kPedestrianRadiusMeters = 2500.0; + PreRankerResult::CategoriesComparator comparator; + comparator.m_positionIsInsideViewport = m_params.m_viewport.IsPointInside(m_params.m_position); + comparator.m_detailedScale = MercatorBounds::DistanceOnEarth( + m_params.m_viewport.LeftTop(), + m_params.m_viewport.RightBottom()) < 2 * kPedestrianRadiusMeters; + comparator.m_viewport = m_params.m_viewport; + nth_element(m_results.begin(), m_results.begin() + numResults, m_results.end(), comparator); + } + + filtered.insert(m_results.begin(), m_results.begin() + numResults); } m_results.assign(filtered.begin(), filtered.end()); diff --git a/search/pre_ranker.hpp b/search/pre_ranker.hpp index 307e433fa0..5648286807 100644 --- a/search/pre_ranker.hpp +++ b/search/pre_ranker.hpp @@ -26,8 +26,6 @@ class PreRanker public: struct Params { - m2::RectD m_viewport; - // Minimal distance between search results in mercators, needed for // filtering of viewport search results. double m_minDistanceOnMapBetweenResults = 0.0; @@ -39,7 +37,11 @@ public: // fast filtering of features outside of the rectangle, while // |m_accuratePivotCenter| should be used when it's needed to // compute the distance from a feature to the pivot. - m2::PointD m_accuratePivotCenter = m2::PointD(0, 0); + m2::PointD m_accuratePivotCenter; + + m2::PointD m_position; + m2::RectD m_viewport; + int m_scale = 0; size_t m_batchSize = 100; @@ -48,6 +50,7 @@ public: size_t m_limit = 0; bool m_viewportSearch = false; + bool m_categorialRequest = false; }; PreRanker(DataSource const & dataSource, Ranker & ranker); diff --git a/search/processor.cpp b/search/processor.cpp index 0529278007..f5ea907089 100644 --- a/search/processor.cpp +++ b/search/processor.cpp @@ -560,15 +560,15 @@ void Processor::InitPreRanker(Geocoder::Params const & geocoderParams, PreRanker::Params params; if (viewportSearch) - { - params.m_viewport = GetViewport(); - params.m_minDistanceOnMapBetweenResults = - searchParams.m_minDistanceOnMapBetweenResults; - } + params.m_minDistanceOnMapBetweenResults = searchParams.m_minDistanceOnMapBetweenResults; + + params.m_viewport = GetViewport(); params.m_accuratePivotCenter = GetPivotPoint(viewportSearch); + params.m_position = GetPosition(); params.m_scale = geocoderParams.GetScale(); params.m_limit = max(kPreResultsCount, searchParams.m_maxNumResults); params.m_viewportSearch = viewportSearch; + params.m_categorialRequest = geocoderParams.IsCategorialRequest(); m_preRanker.Init(params); } diff --git a/search/ranking_info.cpp b/search/ranking_info.cpp index b87cb72616..590a9aaf9d 100644 --- a/search/ranking_info.cpp +++ b/search/ranking_info.cpp @@ -15,7 +15,7 @@ namespace double const kDistanceToPivot = -1.0000000; double const kRank = 1.0000000; // todo: (@t.yan) Adjust. -double const kPopularity = 1.0000000; +double const kPopularity = 0.0500000; double const kFalseCats = -0.0839847; double const kErrorsMade = 0.0066984; double const kAllTokensUsed = 0.0000000;