Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYuri Gorshenin <y@maps.me>2015-07-24 15:54:19 +0300
committerAlex Zolotarev <alex@maps.me>2015-09-23 02:58:04 +0300
commitbe7aecb7efa171aa67ac20397794a217f9421dc3 (patch)
tree2e821b4bd637a9af302912697377d00253fb9ffa
parentd7af959ce6c52d949bbdd2161a507b02f5b6684a (diff)
[search] Implemented retrieval.
-rw-r--r--geometry/rect2d.hpp2
-rw-r--r--search/feature_offset_match.hpp8
-rw-r--r--search/integration_tests/integration_tests.pro1
-rw-r--r--search/integration_tests/retrieval_test.cpp230
-rw-r--r--search/integration_tests/test_search_request.hpp7
-rw-r--r--search/retrieval.cpp230
-rw-r--r--search/retrieval.hpp89
-rw-r--r--search/search.pro2
-rw-r--r--search/search_query.cpp4
-rw-r--r--search/search_query_params.cpp4
-rw-r--r--search/search_query_params.hpp3
11 files changed, 571 insertions, 9 deletions
diff --git a/geometry/rect2d.hpp b/geometry/rect2d.hpp
index 39c8a207f9..d49fa049d0 100644
--- a/geometry/rect2d.hpp
+++ b/geometry/rect2d.hpp
@@ -87,6 +87,8 @@ namespace m2
return (m_minX <= m_maxX && m_minY <= m_maxY);
}
+ bool IsEmptyInterior() const { return m_minX >= m_maxX || m_minY >= m_maxY; }
+
void Add(m2::Point<T> const & p)
{
m_minX = min(p.x, m_minX);
diff --git a/search/feature_offset_match.hpp b/search/feature_offset_match.hpp
index 3474d69a23..370c1356ac 100644
--- a/search/feature_offset_match.hpp
+++ b/search/feature_offset_match.hpp
@@ -1,5 +1,6 @@
#pragma once
#include "search/search_common.hpp"
+#include "search/search_query.hpp"
#include "search/search_query_params.hpp"
#include "indexer/search_trie.hpp"
@@ -44,6 +45,7 @@ TrieIterator * MoveTrieIteratorToString(TrieIterator const & trieRoot,
unique_ptr<search::TrieIterator> pIter(trieRoot.Clone());
size_t const szQuery = queryS.size();
+
while (symbolsMatched < szQuery)
{
bool bMatched = false;
@@ -406,8 +408,8 @@ void MatchFeaturesInTrie(SearchQueryParams const & params, TrieIterator const &
impl::OffsetIntersecter<TFilter> intersecter(filter);
for (size_t i = 0; i < params.m_tokens.size(); ++i)
{
- ForEachLangPrefix(params, trieRoot, [&](TrieRootPrefix & langRoot, int8_t /* lang */)
- {
+ ForEachLangPrefix(params, trieRoot, [&](TrieRootPrefix & langRoot, int8_t lang)
+ {
MatchTokenInTrie(params.m_tokens[i], langRoot, intersecter);
});
categoriesHolder.GetValues(i, intersecter);
@@ -417,7 +419,7 @@ void MatchFeaturesInTrie(SearchQueryParams const & params, TrieIterator const &
if (!params.m_prefixTokens.empty())
{
ForEachLangPrefix(params, trieRoot, [&](TrieRootPrefix & langRoot, int8_t /* lang */)
- {
+ {
MatchTokenPrefixInTrie(params.m_prefixTokens, langRoot, intersecter);
});
categoriesHolder.GetValues(params.m_tokens.size(), intersecter);
diff --git a/search/integration_tests/integration_tests.pro b/search/integration_tests/integration_tests.pro
index e3daa7c8b4..c41d9c4a2b 100644
--- a/search/integration_tests/integration_tests.pro
+++ b/search/integration_tests/integration_tests.pro
@@ -21,6 +21,7 @@ macx-*: LIBS *= "-framework Foundation" "-framework IOKit"
SOURCES += \
../../testing/testingmain.cpp \
+ retrieval_test.cpp \
smoke_test.cpp \
test_mwm_builder.cpp \
test_search_engine.cpp \
diff --git a/search/integration_tests/retrieval_test.cpp b/search/integration_tests/retrieval_test.cpp
new file mode 100644
index 0000000000..3cfad01ce5
--- /dev/null
+++ b/search/integration_tests/retrieval_test.cpp
@@ -0,0 +1,230 @@
+#include "testing/testing.hpp"
+
+#include "indexer/classificator_loader.hpp"
+#include "indexer/index.hpp"
+#include "indexer/mwm_set.hpp"
+#include "indexer/scales.hpp"
+#include "indexer/search_delimiters.hpp"
+#include "indexer/search_string_utils.hpp"
+
+#include "search/integration_tests/test_mwm_builder.hpp"
+#include "search/retrieval.hpp"
+#include "search/search_query_params.hpp"
+
+#include "platform/local_country_file.hpp"
+#include "platform/platform.hpp"
+
+#include "base/scope_guard.hpp"
+#include "base/string_utils.hpp"
+
+namespace
+{
+void InitParams(string const & query, search::SearchQueryParams & params)
+{
+ params.Clear();
+ auto insertTokens = [&params](strings::UniString const & token)
+ {
+ params.m_tokens.push_back({token});
+ };
+ search::Delimiters delims;
+ SplitUniString(search::NormalizeAndSimplifyString(query), insertTokens, delims);
+
+ params.m_langs.insert(StringUtf8Multilang::GetLangIndex("en"));
+}
+
+class TestCallback : public search::Retrieval::Callback
+{
+public:
+ TestCallback(MwmSet::MwmId const & id) : m_id(id), m_triggered(false) {}
+
+ // search::Retrieval::Callback overrides:
+ void OnMwmProcessed(MwmSet::MwmId const & id, vector<uint32_t> const & offsets) override
+ {
+ TEST(!m_triggered, ("Callback must be triggered only once."));
+ TEST_EQUAL(m_id, id, ());
+ m_triggered = true;
+ m_offsets = offsets;
+ }
+
+ bool WasTriggered() const { return m_triggered; }
+
+ vector<uint32_t> & Offsets() { return m_offsets; }
+ vector<uint32_t> const & Offsets() const { return m_offsets; }
+
+private:
+ MwmSet::MwmId const m_id;
+ vector<uint32_t> m_offsets;
+ bool m_triggered;
+};
+
+class MultiMwmCallback : public search::Retrieval::Callback
+{
+public:
+ MultiMwmCallback(vector<MwmSet::MwmId> const & ids) : m_ids(ids), m_numFeatures(0) {}
+
+ // search::Retrieval::Callback overrides:
+ void OnMwmProcessed(MwmSet::MwmId const & id, vector<uint32_t> const & offsets) override
+ {
+ auto const it = find(m_ids.cbegin(), m_ids.cend(), id);
+ TEST(it != m_ids.cend(), ("Unknown mwm:", id));
+
+ auto const rt = m_retrieved.find(id);
+ TEST(rt == m_retrieved.cend(), ("For", id, "callback must be triggered only once."));
+
+ m_retrieved.insert(id);
+ m_numFeatures += offsets.size();
+ }
+
+ uint64_t GetNumMwms() const { return m_retrieved.size(); }
+
+ uint64_t GetNumFeatures() const { return m_numFeatures; }
+
+private:
+ vector<MwmSet::MwmId> m_ids;
+ set<MwmSet::MwmId> m_retrieved;
+ uint64_t m_numFeatures;
+};
+} // namespace
+
+UNIT_TEST(Retrieval_Smoke)
+{
+ classificator::Load();
+ Platform & platform = GetPlatform();
+
+ platform::LocalCountryFile file(platform.WritableDir(), platform::CountryFile("WhiskeyTown"), 0);
+ MY_SCOPE_GUARD(deleteFile, [&]()
+ {
+ file.DeleteFromDisk(MapOptions::Map);
+ });
+
+ // Create a test mwm with 100 whiskey bars.
+ {
+ TestMwmBuilder builder(file);
+ for (int x = 0; x < 10; ++x)
+ {
+ for (int y = 0; y < 10; ++y)
+ builder.AddPOI(m2::PointD(x, y), "Whiskey bar", "en");
+ }
+ }
+ TEST_EQUAL(MapOptions::Map, file.GetFiles(), ());
+
+ Index index;
+ auto p = index.RegisterMap(file);
+ auto & handle = p.first;
+ TEST(handle.IsAlive(), ());
+ TEST_EQUAL(p.second, MwmSet::RegResult::Success, ());
+
+ search::SearchQueryParams params;
+ InitParams("whiskey bar", params);
+
+ search::Retrieval retrieval;
+
+ // Retrieve all (100) whiskey bars from the mwm.
+ {
+ TestCallback callback(handle.GetId());
+
+ retrieval.Init(index, m2::RectD(m2::PointD(0, 0), m2::PointD(1, 1)), params,
+ search::Retrieval::Limits());
+ retrieval.Go(callback);
+ TEST(callback.WasTriggered(), ());
+ TEST_EQUAL(100, callback.Offsets().size(), ());
+
+ TestCallback dummyCallback(handle.GetId());
+ retrieval.Go(dummyCallback);
+ TEST(!dummyCallback.WasTriggered(), ());
+ }
+
+ // Retrieve all whiskey bars from the left-bottom 5 x 5 square.
+ {
+ TestCallback callback(handle.GetId());
+ search::Retrieval::Limits limits;
+ limits.SetMaxViewportScale(5.0);
+
+ retrieval.Init(index, m2::RectD(m2::PointD(0, 0), m2::PointD(1, 1)), params, limits);
+ retrieval.Go(callback);
+ TEST(callback.WasTriggered(), ());
+ TEST_EQUAL(36 /* number of whiskey bars in a 5 x 5 square (border is counted) */,
+ callback.Offsets().size(), ());
+ }
+
+ // Retrieve at least than 8 whiskey bars from the center.
+ {
+ TestCallback callback(handle.GetId());
+ search::Retrieval::Limits limits;
+ limits.SetMinNumFeatures(8);
+
+ retrieval.Init(index, m2::RectD(m2::PointD(4.9, 4.9), m2::PointD(5.1, 5.1)), params, limits);
+ retrieval.Go(callback);
+ TEST(callback.WasTriggered(), ());
+ TEST_GREATER_OR_EQUAL(callback.Offsets().size(), 8, ());
+ }
+}
+
+UNIT_TEST(Retrieval_3Mwms)
+{
+ classificator::Load();
+ Platform & platform = GetPlatform();
+
+ platform::LocalCountryFile msk(platform.WritableDir(), platform::CountryFile("msk"), 0);
+ platform::LocalCountryFile mtv(platform.WritableDir(), platform::CountryFile("mtv"), 0);
+ platform::LocalCountryFile zrh(platform.WritableDir(), platform::CountryFile("zrh"), 0);
+ MY_SCOPE_GUARD(deleteFiles, [&]()
+ {
+ msk.DeleteFromDisk(MapOptions::Map);
+ mtv.DeleteFromDisk(MapOptions::Map);
+ zrh.DeleteFromDisk(MapOptions::Map);
+ });
+
+ {
+ TestMwmBuilder builder(msk);
+ builder.AddPOI(m2::PointD(0, 0), "Cafe MTV", "en");
+ }
+ {
+ TestMwmBuilder builder(mtv);
+ builder.AddPOI(m2::PointD(10, 0), "MTV", "en");
+ }
+ {
+ TestMwmBuilder builder(zrh);
+ builder.AddPOI(m2::PointD(0, 10), "Bar MTV", "en");
+ }
+
+ Index index;
+ auto mskP = index.RegisterMap(msk);
+ auto & mskHandle = mskP.first;
+
+ auto mtvP = index.RegisterMap(mtv);
+ auto & mtvHandle = mtvP.first;
+
+ auto zrhP = index.RegisterMap(zrh);
+ auto & zrhHandle = zrhP.first;
+
+ TEST(mskHandle.IsAlive(), ());
+ TEST(mtvHandle.IsAlive(), ());
+ TEST(zrhHandle.IsAlive(), ());
+
+ search::SearchQueryParams params;
+ InitParams("mtv", params);
+
+ search::Retrieval retrieval;
+
+ {
+ TestCallback callback(mskHandle.GetId());
+ search::Retrieval::Limits limits;
+ limits.SetMinNumFeatures(1);
+
+ retrieval.Init(index, m2::RectD(m2::PointD(-1.0, -1.0), m2::PointD(1.0, 1.0)), params, limits);
+ retrieval.Go(callback);
+ TEST(callback.WasTriggered(), ());
+ TEST_EQUAL(callback.Offsets().size(), 1, ());
+ }
+
+ {
+ MultiMwmCallback callback({mskHandle.GetId(), mtvHandle.GetId(), zrhHandle.GetId()});
+ search::Retrieval::Limits limits;
+
+ retrieval.Init(index, m2::RectD(m2::PointD(-1.0, -1.0), m2::PointD(1.0, 1.0)), params, limits);
+ retrieval.Go(callback);
+ TEST_EQUAL(3, callback.GetNumMwms(), ());
+ TEST_EQUAL(3, callback.GetNumFeatures(), ());
+ }
+}
diff --git a/search/integration_tests/test_search_request.hpp b/search/integration_tests/test_search_request.hpp
index fc36b578de..f11bc39a8c 100644
--- a/search/integration_tests/test_search_request.hpp
+++ b/search/integration_tests/test_search_request.hpp
@@ -11,10 +11,9 @@
class TestSearchEngine;
-// This class wraps a search query to a search engine. Note that a
-// full token match will be performed, e.g. the last token will be
-// handled as a complete token (like other tokens), not a token's
-// prefix.
+// This class wraps a search query to a search engine. Note that the
+// last token will be handled as a complete token iff it will be
+// followed by a space in a query.
class TestSearchRequest
{
public:
diff --git a/search/retrieval.cpp b/search/retrieval.cpp
new file mode 100644
index 0000000000..db47039fc1
--- /dev/null
+++ b/search/retrieval.cpp
@@ -0,0 +1,230 @@
+#include "search/retrieval.hpp"
+
+#include "search/feature_offset_match.hpp"
+
+#include "indexer/index.hpp"
+#include "indexer/search_trie.hpp"
+
+#include "coding/reader_wrapper.hpp"
+
+#include "base/stl_add.hpp"
+
+#include "std/cmath.hpp"
+
+namespace search
+{
+namespace
+{
+struct EmptyFilter
+{
+ inline bool operator()(uint32_t /* featureId */) const { return true; }
+};
+
+void RetrieveAddressFeatures(MwmSet::MwmHandle const & handle, SearchQueryParams const & params,
+ vector<uint32_t> & offsets)
+{
+ auto * value = handle.GetValue<MwmValue>();
+ ASSERT(value, ());
+ serial::CodingParams codingParams(GetCPForTrie(value->GetHeader().GetDefCodingParams()));
+ ModelReaderPtr searchReader = value->m_cont.GetReader(SEARCH_INDEX_FILE_TAG);
+ unique_ptr<TrieIterator> const trieRoot(
+ ::trie::reader::ReadTrie(SubReaderWrapper<Reader>(searchReader.GetPtr()),
+ trie::ValueReader(codingParams), trie::EdgeValueReader()));
+
+ offsets.clear();
+ auto collector = [&](trie::ValueReader::ValueType const & value)
+ {
+ offsets.push_back(value.m_featureId);
+ };
+ MatchFeaturesInTrie(params, *trieRoot, EmptyFilter(), collector);
+}
+
+void RetrieveGeometryFeatures(MwmSet::MwmHandle const & handle, m2::RectD const & viewport,
+ SearchQueryParams const & params, vector<uint32_t> & offsets)
+{
+ auto * value = handle.GetValue<MwmValue>();
+ ASSERT(value, ());
+ feature::DataHeader const & header = value->GetHeader();
+ ASSERT(viewport.IsIntersect(header.GetBounds()), ());
+
+ auto const scaleRange = header.GetScaleRange();
+ int const scale = min(max(params.m_scale, scaleRange.first), scaleRange.second);
+
+ covering::CoveringGetter covering(viewport, covering::ViewportWithLowLevels);
+ covering::IntervalsT const & intervals = covering.Get(scale);
+ ScaleIndex<ModelReaderPtr> index(value->m_cont.GetReader(INDEX_FILE_TAG), value->m_factory);
+
+ offsets.clear();
+ auto collector = MakeBackInsertFunctor(offsets);
+ for (auto const & interval : intervals)
+ {
+ index.ForEachInIntervalAndScale(collector, interval.first, interval.second, scale);
+ }
+}
+} // namespace
+
+Retrieval::Limits::Limits()
+ : m_minNumFeatures(0),
+ m_maxViewportScale(0.0),
+ m_minNumFeaturesSet(false),
+ m_maxViewportScaleSet(false)
+{
+}
+
+void Retrieval::Limits::SetMinNumFeatures(uint64_t minNumFeatures)
+{
+ m_minNumFeatures = minNumFeatures;
+ m_minNumFeaturesSet = true;
+}
+
+uint64_t Retrieval::Limits::GetMinNumFeatures() const
+{
+ ASSERT(IsMinNumFeaturesSet(), ());
+ return m_minNumFeatures;
+}
+
+void Retrieval::Limits::SetMaxViewportScale(double maxViewportScale)
+{
+ m_maxViewportScale = maxViewportScale;
+ m_maxViewportScaleSet = true;
+}
+
+double Retrieval::Limits::GetMaxViewportScale() const
+{
+ ASSERT(IsMaxViewportScaleSet(), ());
+ return m_maxViewportScale;
+}
+
+Retrieval::FeatureBucket::FeatureBucket(MwmSet::MwmHandle && handle)
+ : m_handle(move(handle)),
+ m_intersectsWithViewport(false),
+ m_coveredByViewport(false),
+ m_finished(false)
+{
+ auto * value = m_handle.GetValue<MwmValue>();
+ ASSERT(value, ());
+ feature::DataHeader const & header = value->GetHeader();
+ m_bounds = header.GetBounds();
+}
+
+Retrieval::Retrieval() : m_index(nullptr) {}
+
+void Retrieval::Init(Index & index, m2::RectD const & viewport, SearchQueryParams const & params,
+ Limits const & limits)
+{
+ m_index = &index;
+ m_viewport = viewport;
+ m_params = params;
+ m_limits = limits;
+
+ vector<shared_ptr<MwmInfo>> infos;
+ index.GetMwmsInfo(infos);
+
+ m_buckets.clear();
+ for (auto const & info : infos)
+ {
+ MwmSet::MwmHandle handle =
+ index.GetMwmHandleByCountryFile(info->GetLocalFile().GetCountryFile());
+ if (!handle.IsAlive())
+ continue;
+ auto * value = handle.GetValue<MwmValue>();
+ if (value && value->m_cont.IsExist(SEARCH_INDEX_FILE_TAG) &&
+ value->m_cont.IsExist(INDEX_FILE_TAG))
+ {
+ m_buckets.emplace_back(move(handle));
+ }
+ }
+}
+
+void Retrieval::Go(Callback & callback)
+{
+ static double const kViewportScaleMul = sqrt(2.0);
+
+ for (double viewportScale = 1.0;; viewportScale *= kViewportScaleMul)
+ {
+ double scale = viewportScale;
+ if (m_limits.IsMaxViewportScaleSet() && scale >= m_limits.GetMaxViewportScale())
+ scale = m_limits.GetMaxViewportScale();
+
+ m2::RectD viewport = m_viewport;
+ viewport.Scale(scale);
+ RetrieveForViewport(viewport, callback);
+
+ if (ViewportCoversAllMwms())
+ break;
+ if (m_limits.IsMaxViewportScaleSet() && scale >= m_limits.GetMaxViewportScale())
+ break;
+ if (m_limits.IsMinNumFeaturesSet() && CountRetrievedFeatures() >= m_limits.GetMinNumFeatures())
+ break;
+ }
+
+ for (auto & bucket : m_buckets)
+ {
+ if (bucket.m_finished)
+ continue;
+ // The bucket is not covered by viewport, thus all matching
+ // features were not reported.
+ bucket.m_finished = true;
+ if (!bucket.m_intersection.empty())
+ callback.OnMwmProcessed(bucket.m_handle.GetId(), bucket.m_intersection);
+ }
+}
+
+void Retrieval::RetrieveForViewport(m2::RectD const & viewport, Callback & callback)
+{
+ for (auto & bucket : m_buckets)
+ {
+ if (bucket.m_coveredByViewport || bucket.m_finished || !viewport.IsIntersect(bucket.m_bounds))
+ continue;
+
+ if (!bucket.m_intersectsWithViewport)
+ {
+ // This is the first time viewport intersects with mwm. Retrieve
+ // all matching features from search index.
+ RetrieveAddressFeatures(bucket.m_handle, m_params, bucket.m_addressFeatures);
+ sort(bucket.m_addressFeatures.begin(), bucket.m_addressFeatures.end());
+ bucket.m_intersectsWithViewport = true;
+ }
+
+ // Mwm is still not covered by expanding viewport.
+ if (!bucket.m_coveredByViewport)
+ {
+ RetrieveGeometryFeatures(bucket.m_handle, viewport, m_params, bucket.m_geometryFeatures);
+ sort(bucket.m_geometryFeatures.begin(), bucket.m_geometryFeatures.end());
+
+ bucket.m_intersection.clear();
+ set_intersection(bucket.m_addressFeatures.begin(), bucket.m_addressFeatures.end(),
+ bucket.m_geometryFeatures.begin(), bucket.m_geometryFeatures.end(),
+ back_inserter(bucket.m_intersection));
+ }
+
+ if (!bucket.m_coveredByViewport && viewport.IsRectInside(bucket.m_bounds))
+ {
+ // Next time we will skip the bucket, so it's better to report all it's features now.
+ bucket.m_coveredByViewport = true;
+ bucket.m_finished = true;
+ if (!bucket.m_intersection.empty())
+ callback.OnMwmProcessed(bucket.m_handle.GetId(), bucket.m_intersection);
+ }
+ }
+}
+
+bool Retrieval::ViewportCoversAllMwms() const
+{
+ for (auto const & bucket : m_buckets)
+ {
+ if (!bucket.m_coveredByViewport)
+ return false;
+ }
+ return true;
+}
+
+uint64_t Retrieval::CountRetrievedFeatures() const
+{
+ static_assert(sizeof(size_t) <= sizeof(uint64_t), "uint64_t must be not less than size_t");
+ uint64_t count = 0;
+ for (auto const & bucket : m_buckets)
+ count += bucket.m_intersection.size();
+ return count;
+}
+} // namespace search
diff --git a/search/retrieval.hpp b/search/retrieval.hpp
new file mode 100644
index 0000000000..97f94d39a9
--- /dev/null
+++ b/search/retrieval.hpp
@@ -0,0 +1,89 @@
+#pragma once
+
+#include "search/search_query_params.hpp"
+
+#include "indexer/mwm_set.hpp"
+
+#include "geometry/rect2d.hpp"
+
+#include "std/function.hpp"
+#include "std/vector.hpp"
+
+class Index;
+
+namespace search
+{
+class Retrieval
+{
+public:
+ class Callback
+ {
+ public:
+ virtual ~Callback() = default;
+
+ virtual void OnMwmProcessed(MwmSet::MwmId const & id, vector<uint32_t> const & offsets) = 0;
+ };
+
+ // Following class represents a set of retrieval's limits.
+ struct Limits
+ {
+ public:
+ Limits();
+
+ // Sets lower bound on number of features to be retrieved.
+ void SetMinNumFeatures(uint64_t minNumFeatures);
+ uint64_t GetMinNumFeatures() const;
+
+ // Sets upper bound on a maximum viewport's scale.
+ void SetMaxViewportScale(double maxViewportScale);
+ double GetMaxViewportScale() const;
+
+ inline bool IsMinNumFeaturesSet() const { return m_minNumFeaturesSet; }
+ inline bool IsMaxViewportScaleSet() const { return m_maxViewportScaleSet; }
+
+ private:
+ uint64_t m_minNumFeatures;
+ double m_maxViewportScale;
+
+ bool m_minNumFeaturesSet : 1;
+ bool m_maxViewportScaleSet : 1;
+ };
+
+ Retrieval();
+
+ void Init(Index & index, m2::RectD const & viewport, SearchQueryParams const & params,
+ Limits const & limits);
+
+ void Go(Callback & callback);
+
+private:
+ struct FeatureBucket
+ {
+ FeatureBucket(MwmSet::MwmHandle && handle);
+
+ MwmSet::MwmHandle m_handle;
+ vector<uint32_t> m_addressFeatures;
+ vector<uint32_t> m_geometryFeatures;
+ vector<uint32_t> m_intersection;
+ m2::RectD m_bounds;
+ bool m_intersectsWithViewport : 1;
+ bool m_coveredByViewport : 1;
+ bool m_finished : 1;
+ };
+
+ // *NOTE* arguments of successive calls of this method should be
+ // *non-decreasing.
+ void RetrieveForViewport(m2::RectD const & viewport, Callback & callback);
+
+ bool ViewportCoversAllMwms() const;
+
+ uint64_t CountRetrievedFeatures() const;
+
+ Index * m_index;
+ m2::RectD m_viewport;
+ SearchQueryParams m_params;
+ Limits m_limits;
+
+ vector<FeatureBucket> m_buckets;
+};
+} // namespace search
diff --git a/search/search.pro b/search/search.pro
index 697013c988..a0f318a3cc 100644
--- a/search/search.pro
+++ b/search/search.pro
@@ -22,6 +22,7 @@ HEADERS += \
locality_finder.hpp \
params.hpp \
result.hpp \
+ retrieval.hpp \
search_common.hpp \
search_engine.hpp \
search_query.hpp \
@@ -40,6 +41,7 @@ SOURCES += \
locality_finder.cpp \
params.cpp \
result.cpp \
+ retrieval.cpp \
search_engine.cpp \
search_query.cpp \
search_query_params.cpp \
diff --git a/search/search_query.cpp b/search/search_query.cpp
index cbc9732b2f..85eeee4e29 100644
--- a/search/search_query.cpp
+++ b/search/search_query.cpp
@@ -1746,7 +1746,7 @@ void Query::SearchLocality(MwmValue * pMwm, impl::Locality & res1, impl::Region
trie::ValueReader(cp), trie::EdgeValueReader()));
ForEachLangPrefix(params, *trieRoot, [&](TrieRootPrefix & langRoot, int8_t lang)
- {
+ {
impl::DoFindLocality doFind(*this, pMwm, lang);
MatchTokensInTrie(params.m_tokens, langRoot, doFind);
@@ -1859,7 +1859,7 @@ void Query::SearchInMWM(Index::MwmHandle const & mwmHandle, SearchQueryParams co
FeaturesFilter filter(
(viewportId == DEFAULT_V || isWorld) ? 0 : &m_offsetsInViewport[viewportId][mwmId], *this);
MatchFeaturesInTrie(params, *trieRoot, filter, [&](TrieValueT const & value)
- {
+ {
AddResultFromTrie(value, mwmId, viewportId);
});
}
diff --git a/search/search_query_params.cpp b/search/search_query_params.cpp
index de36c8bbc1..916c0393b3 100644
--- a/search/search_query_params.cpp
+++ b/search/search_query_params.cpp
@@ -1,6 +1,7 @@
#include "search/search_query_params.hpp"
#include "indexer/feature_impl.hpp"
+#include "indexer/scales.hpp"
#include "base/assert.hpp"
@@ -56,11 +57,14 @@ private:
};
} // namespace
+SearchQueryParams::SearchQueryParams() : m_scale(scales::GetUpperScale()) {}
+
void SearchQueryParams::Clear()
{
m_tokens.clear();
m_prefixTokens.clear();
m_langs.clear();
+ m_scale = scales::GetUpperScale();
}
void SearchQueryParams::EraseTokens(vector<size_t> & eraseInds)
diff --git a/search/search_query_params.hpp b/search/search_query_params.hpp
index 6bae19b42b..6646e6096c 100644
--- a/search/search_query_params.hpp
+++ b/search/search_query_params.hpp
@@ -17,6 +17,9 @@ struct SearchQueryParams
vector<TSynonymsVector> m_tokens;
TSynonymsVector m_prefixTokens;
TLangsSet m_langs;
+ int m_scale;
+
+ SearchQueryParams();
void Clear();