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
path: root/search
diff options
context:
space:
mode:
authorYuri Gorshenin <y@maps.me>2016-06-16 17:25:36 +0300
committerYuri Gorshenin <y@maps.me>2016-06-17 14:19:33 +0300
commit683250079ac00a81920ed9cc101239cee4ed2f9c (patch)
treea0fce36270da4e4f4daf1bddd0b6e0b0bf8b7a37 /search
parent01db5017dca8ee1179b157918e47b181062c466c (diff)
[search] Fixed streets matching.
Diffstat (limited to 'search')
-rw-r--r--search/geocoder.cpp89
-rw-r--r--search/geocoder.hpp4
-rw-r--r--search/search_integration_tests/processor_test.cpp17
3 files changed, 75 insertions, 35 deletions
diff --git a/search/geocoder.cpp b/search/geocoder.cpp
index 1f0ac2b8fa..1cafb50e73 100644
--- a/search/geocoder.cpp
+++ b/search/geocoder.cpp
@@ -466,6 +466,8 @@ void Geocoder::SetParams(Params const & params)
}
}
+ LOG(LDEBUG, ("Tokens = ", m_params.m_tokens));
+ LOG(LDEBUG, ("Prefix tokens = ", m_params.m_prefixTokens));
LOG(LDEBUG, ("Languages =", m_params.m_langs));
}
@@ -1075,61 +1077,82 @@ void Geocoder::GreedilyMatchStreets()
continue;
// Here we try to match as many tokens as possible while
- // intersection is a non-empty bit vector of streets. All tokens
- // that are synonyms to streets are ignored. Moreover, each time
- // a token that looks like a beginning of a house number is met,
- // we try to use current intersection of tokens as a street layer
- // and try to match buildings or pois.
- unique_ptr<coding::CompressedBitVector> allFeatures;
+ // intersection is a non-empty bit vector of streets. Single
+ // tokens that are synonyms to streets are ignored. Moreover,
+ // each time a token that looks like a beginning of a house number
+ // is met, we try to use current intersection of tokens as a
+ // street layer and try to match BUILDINGs or POIs.
+ CBVPtr allFeatures(m_streets, false /* isOwner */);
size_t curToken = startToken;
// This variable is used for prevention of duplicate calls to
// CreateStreetsLayerAndMatchLowerLayers() with the same
// arguments.
- size_t lastStopToken = curToken;
+ size_t lastToken = startToken;
- for (; curToken < m_numTokens && !m_usedTokens[curToken]; ++curToken)
- {
- auto const & token = m_params.GetTokens(curToken).front();
- if (IsStreetSynonymPrefix(token))
- continue;
+ bool emptyIntersection = true;
+ bool incomplete = false;
- bool const isPrefix = curToken >= m_params.m_tokens.size();
- if (house_numbers::LooksLikeHouseNumber(token, isPrefix))
+ auto createStreetsLayerAndMatchLowerLayers = [&]()
+ {
+ if (!allFeatures.IsEmpty() && !emptyIntersection && !incomplete && lastToken != curToken)
{
- CreateStreetsLayerAndMatchLowerLayers(startToken, curToken, allFeatures);
- lastStopToken = curToken;
+ CreateStreetsLayerAndMatchLowerLayers(startToken, curToken, *allFeatures);
+ lastToken = curToken;
}
+ };
- unique_ptr<coding::CompressedBitVector> buffer;
- if (startToken == curToken || coding::CompressedBitVector::IsEmpty(allFeatures))
- buffer = coding::CompressedBitVector::Intersect(*m_streets, *m_addressFeatures[curToken]);
- else
- buffer = coding::CompressedBitVector::Intersect(*allFeatures, *m_addressFeatures[curToken]);
+ StreetTokensFilter filter([&](strings::UniString const & /* token */, size_t tag)
+ {
+ auto buffer = coding::CompressedBitVector::Intersect(
+ *allFeatures, *m_addressFeatures[tag]);
+ if (tag < curToken)
+ {
+ allFeatures.Set(move(buffer));
+ emptyIntersection = false;
+ incomplete = true;
+ return;
+ }
+ ASSERT_EQUAL(tag, curToken, ());
+
+ // |allFeatures| will become empty
+ // after the intersection. Therefore
+ // we need to create streets layer
+ // right now.
+ if (coding::CompressedBitVector::IsEmpty(buffer))
+ createStreetsLayerAndMatchLowerLayers();
+
+ allFeatures.Set(move(buffer));
+ emptyIntersection = false;
+ incomplete = false;
+ });
+
+ for (; curToken < m_numTokens && !m_usedTokens[curToken] && !allFeatures.IsEmpty(); ++curToken)
+ {
+ auto const & token = m_params.GetTokens(curToken).front();
+ bool const isPrefix = curToken >= m_params.m_tokens.size();
- if (coding::CompressedBitVector::IsEmpty(buffer))
- break;
+ if (house_numbers::LooksLikeHouseNumber(token, isPrefix))
+ createStreetsLayerAndMatchLowerLayers();
- allFeatures.swap(buffer);
+ filter.Put(token, isPrefix, curToken);
}
-
- if (curToken != lastStopToken)
- CreateStreetsLayerAndMatchLowerLayers(startToken, curToken, allFeatures);
+ createStreetsLayerAndMatchLowerLayers();
}
}
void Geocoder::CreateStreetsLayerAndMatchLowerLayers(
- size_t startToken, size_t endToken, unique_ptr<coding::CompressedBitVector> const & features)
+ size_t startToken, size_t endToken, coding::CompressedBitVector const & features)
{
ASSERT(m_layers.empty(), ());
- if (coding::CompressedBitVector::IsEmpty(features))
+ if (coding::CompressedBitVector::IsEmpty(&features))
return;
- CBVPtr filtered(features.get(), false /* isOwner */);
- if (m_filter->NeedToFilter(*features))
- filtered.Set(m_filter->Filter(*features).release(), true /* isOwner */);
+ CBVPtr filtered(&features, false /* isOwner */);
+ if (m_filter->NeedToFilter(features))
+ filtered.Set(m_filter->Filter(features).release(), true /* isOwner */);
m_layers.emplace_back();
MY_SCOPE_GUARD(cleanupGuard, bind(&vector<FeaturesLayer>::pop_back, &m_layers));
@@ -1138,7 +1161,7 @@ void Geocoder::CreateStreetsLayerAndMatchLowerLayers(
InitLayer(SearchModel::SEARCH_TYPE_STREET, startToken, endToken, layer);
vector<uint32_t> sortedFeatures;
- sortedFeatures.reserve(features->PopCount());
+ sortedFeatures.reserve(features.PopCount());
filtered.ForEach(MakeBackInsertFunctor(sortedFeatures));
layer.m_sortedFeatures = &sortedFeatures;
diff --git a/search/geocoder.hpp b/search/geocoder.hpp
index 439784a742..db8e905b98 100644
--- a/search/geocoder.hpp
+++ b/search/geocoder.hpp
@@ -245,8 +245,8 @@ private:
// then performs geocoding in street vicinities.
void GreedilyMatchStreets();
- void CreateStreetsLayerAndMatchLowerLayers(
- size_t startToken, size_t endToken, unique_ptr<coding::CompressedBitVector> const & features);
+ void CreateStreetsLayerAndMatchLowerLayers(size_t startToken, size_t endToken,
+ coding::CompressedBitVector const & features);
// Tries to find all paths in a search tree, where each edge is
// marked with some substring of the query tokens. These paths are
diff --git a/search/search_integration_tests/processor_test.cpp b/search/search_integration_tests/processor_test.cpp
index 89c9032634..419ed0025b 100644
--- a/search/search_integration_tests/processor_test.cpp
+++ b/search/search_integration_tests/processor_test.cpp
@@ -59,6 +59,8 @@ UNIT_CLASS_TEST(ProcessorTest, Smoke)
TestCity losAlamosCity(m2::PointD(10, 10), "Los Alamos", "en", 100 /* rank */);
TestCity mskCity(m2::PointD(0, 0), "Moscow", "en", 100 /* rank */);
+ TestCity torontoCity(m2::PointD(-10, -10), "Toronto", "en", 100 /* rank */);
+
TestVillage longPondVillage(m2::PointD(15, 15), "Long Pond Village", "en", 10 /* rank */);
TestStreet feynmanStreet(
vector<m2::PointD>{m2::PointD(9.999, 9.999), m2::PointD(10, 10), m2::PointD(10.001, 10.001)},
@@ -94,16 +96,23 @@ UNIT_CLASS_TEST(ProcessorTest, Smoke)
TestPOI lantern1(m2::PointD(10.0005, 10.0005), "lantern 1", "en");
TestPOI lantern2(m2::PointD(10.0006, 10.0005), "lantern 2", "en");
+ TestStreet stradaDrive(vector<m2::PointD>{m2::PointD(-10.001, -10.001), m2::PointD(-10, -10),
+ m2::PointD(-9.999, -9.999)},
+ "Strada drive", "en");
+ TestBuilding terranceHouse(m2::PointD(-10, -10), "", "155", stradaDrive, "en");
+
BuildWorld([&](TestMwmBuilder & builder)
{
builder.Add(wonderlandCountry);
builder.Add(losAlamosCity);
builder.Add(mskCity);
+ builder.Add(torontoCity);
});
auto wonderlandId = BuildCountry(countryName, [&](TestMwmBuilder & builder)
{
builder.Add(losAlamosCity);
builder.Add(mskCity);
+ builder.Add(torontoCity);
builder.Add(longPondVillage);
builder.Add(feynmanStreet);
@@ -125,6 +134,9 @@ UNIT_CLASS_TEST(ProcessorTest, Smoke)
builder.Add(quantumCafe);
builder.Add(lantern1);
builder.Add(lantern2);
+
+ builder.Add(stradaDrive);
+ builder.Add(terranceHouse);
});
SetViewport(m2::RectD(m2::PointD(-1.0, -1.0), m2::PointD(1.0, 1.0)));
@@ -190,6 +202,11 @@ UNIT_CLASS_TEST(ProcessorTest, Smoke)
TRules rules = {ExactMatch(wonderlandId, bornHouse)};
TEST(ResultsMatch("long pond 1st april street 8", rules), ());
}
+
+ {
+ TRules rules = {ExactMatch(wonderlandId, terranceHouse)};
+ TEST(ResultsMatch("Toronto strada drive 155", rules), ());
+ }
}
UNIT_CLASS_TEST(ProcessorTest, SearchInWorld)