diff --git a/search/search_engine.cpp b/search/search_engine.cpp index b4dcb59696..803bfd3c84 100644 --- a/search/search_engine.cpp +++ b/search/search_engine.cpp @@ -233,6 +233,12 @@ void Engine::DoSearch(SearchParams const & params, m2::RectD const & viewport, } SetRankPivot(params, viewport, viewportSearch); + + if (params.IsValidPosition()) + m_query->SetPosition(MercatorBounds::FromLatLon(params.m_lat, params.m_lon)); + else + m_query->SetPosition(viewport.Center()); + m_query->SetSearchInWorld(params.HasSearchMode(SearchParams::SEARCH_WORLD)); m_query->SetInputLocale(params.m_inputLocale); diff --git a/search/search_query.cpp b/search/search_query.cpp index 93f2b421af..a745312521 100644 --- a/search/search_query.cpp +++ b/search/search_query.cpp @@ -222,6 +222,7 @@ Query::Query(Index & index, CategoriesHolder const & categories, vector #ifdef FIND_LOCALITY_TEST , m_locality(&index) #endif + , m_position(0, 0) , m_worldSearch(true) , m_keepHouseNumberInQuery(false) { diff --git a/search/search_query.hpp b/search/search_query.hpp index 477a09d9b1..e194a9274d 100644 --- a/search/search_query.hpp +++ b/search/search_query.hpp @@ -84,6 +84,7 @@ public: void SetViewport(m2::RectD const & viewport, bool forceUpdate); 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 void SetSearchInWorld(bool b) { m_worldSearch = b; } @@ -231,6 +232,7 @@ protected: m2::RectD m_viewport[COUNT_V]; m2::PointD m_pivot; + m2::PointD m_position; bool m_worldSearch; Retrieval m_retrieval; diff --git a/search/v2/geocoder.cpp b/search/v2/geocoder.cpp index 8acbae840d..b40ccfb8e0 100644 --- a/search/v2/geocoder.cpp +++ b/search/v2/geocoder.cpp @@ -34,9 +34,6 @@ namespace v2 { namespace { -// 50km maximum viewport radius. -double const kMaxViewportRadiusM = 50.0 * 1000; - void JoinQueryTokens(SearchQueryParams const & params, size_t curToken, size_t endToken, string const & sep, string & res) { @@ -78,7 +75,7 @@ MwmSet::MwmHandle FindWorld(Index & index, vector> & infos) } // namespace // Geocoder::Params -------------------------------------------------------------------------------- -Geocoder::Params::Params() : m_maxNumResults(0) {} +Geocoder::Params::Params() : m_position(0, 0), m_maxNumResults(0) {} // Geocoder::Geocoder ------------------------------------------------------------------------------ Geocoder::Geocoder(Index & index) @@ -301,18 +298,54 @@ void Geocoder::DoGeocodingWithLocalities() void Geocoder::DoGeocodingWithoutLocalities() { - // TODO (@y, @m, @vng): consider to add user position here, to - // inflate viewport if too small number of results is found, etc. - // Limits viewport by kMaxViewportRadiusM. - m2::RectD const viewportLimit = MercatorBounds::RectByCenterXYAndSizeInMeters( - m_params.m_viewport.Center(), kMaxViewportRadiusM); - m2::RectD rect = m_params.m_viewport; - rect.Intersect(viewportLimit); - if (rect.IsEmptyInterior()) - return; + // 50km maximum viewport radius. + double constexpr kMaxViewportRadiusM = 50.0 * 1000; - m_filter.SetFilter(Retrieval::RetrieveGeometryFeatures( - m_context->m_value, static_cast(*this), rect, m_params.m_scale)); + // 50km radius around position. + double constexpr kMaxPositionRadiusM = 50.0 * 1000; + + double constexpr kEps = 1.0e-5; + + m2::RectD const & viewport = m_params.m_viewport; + m2::PointD const & position = m_params.m_position; + + // Extracts features in viewport. + unique_ptr viewportFeatures; + { + // Limits viewport by kMaxViewportRadiusM. + m2::RectD const viewportLimit = + MercatorBounds::RectByCenterXYAndSizeInMeters(viewport.Center(), kMaxViewportRadiusM); + m2::RectD rect = viewport; + rect.Intersect(viewportLimit); + if (!rect.IsEmptyInterior()) + { + viewportFeatures = Retrieval::RetrieveGeometryFeatures( + m_context->m_value, static_cast(*this), rect, m_params.m_scale); + } + } + + // Extracts features around user position. + unique_ptr positionFeatures; + if (!position.EqualDxDy(viewport.Center(), kEps)) + { + m2::RectD const rect = + MercatorBounds::RectByCenterXYAndSizeInMeters(position, kMaxPositionRadiusM); + positionFeatures = Retrieval::RetrieveGeometryFeatures( + m_context->m_value, static_cast(*this), rect, m_params.m_scale); + } + + if (coding::CompressedBitVector::IsEmpty(viewportFeatures) && + coding::CompressedBitVector::IsEmpty(positionFeatures)) + { + return; + } + + if (coding::CompressedBitVector::IsEmpty(viewportFeatures)) + m_filter.SetFilter(move(positionFeatures)); + else if (coding::CompressedBitVector::IsEmpty(positionFeatures)) + m_filter.SetFilter(move(viewportFeatures)); + else + m_filter.SetFilter(coding::CompressedBitVector::Union(*viewportFeatures, *positionFeatures)); // Filter will be applied only for large bit vectors. m_filter.SetThreshold(m_params.m_maxNumResults); @@ -497,8 +530,8 @@ void Geocoder::FindPaths() m_finder.ForEachReachableVertex(*m_matcher, sortedLayers, [this](uint32_t featureId) { - m_results->emplace_back(m_context->m_id, featureId); - }); + m_results->emplace_back(m_context->m_id, featureId); + }); } } // namespace v2 } // namespace search diff --git a/search/v2/geocoder.hpp b/search/v2/geocoder.hpp index 756a8f557b..9ebc07fb21 100644 --- a/search/v2/geocoder.hpp +++ b/search/v2/geocoder.hpp @@ -62,6 +62,7 @@ public: Params(); m2::RectD m_viewport; + m2::PointD m_position; size_t m_maxNumResults; }; diff --git a/search/v2/search_query_v2.cpp b/search/v2/search_query_v2.cpp index 3ff06a8e29..882f1826fe 100644 --- a/search/v2/search_query_v2.cpp +++ b/search/v2/search_query_v2.cpp @@ -40,6 +40,7 @@ void SearchQueryV2::Search(Results & res, size_t resCount) Geocoder::Params params; InitParams(false /* localitySearch */, params); params.m_viewport = m_viewport[CURRENT_V]; + params.m_position = m_position; params.m_maxNumResults = max(resCount, kPreResultsCount); m_geocoder.SetParams(params);