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:
authorvng <viktor.govako@gmail.com>2012-08-23 11:25:26 +0400
committerAlex Zolotarev <alex@maps.me>2015-09-23 01:42:27 +0300
commitf8679434b8f1e2668d447dc8eb11ca0c7c168fb6 (patch)
tree1a05cf0ae12e3190dc306d93c7fcdf5dbdf59045 /search
parent7cf9981c61381384b9668c592e5072382f70f24d (diff)
[search] Process country or state in address search.
Diffstat (limited to 'search')
-rw-r--r--search/search_query.cpp152
1 files changed, 138 insertions, 14 deletions
diff --git a/search/search_query.cpp b/search/search_query.cpp
index cb69e71c4c..7e583e0e34 100644
--- a/search/search_query.cpp
+++ b/search/search_query.cpp
@@ -807,6 +807,18 @@ namespace impl
res += "; Matched: " + ::DebugPrint(l.m_matchedTokens.size());
return res;
}
+
+ struct Region
+ {
+ vector<size_t> m_ids;
+ vector<size_t> m_matchedTokens;
+ string m_enName;
+ };
+
+ string DebugPrint(Region const & r)
+ {
+ return string("Name: " + r.m_enName);
+ }
}
void Query::SearchAddress()
@@ -826,7 +838,7 @@ void Query::SearchAddress()
impl::Locality loc;
if (SearchLocality(pMwm, loc))
{
- LOG(LDEBUG, ("Locality = ", loc.m_enName));
+ LOG(LDEBUG, ("Final locality = ", loc));
Params params(*this);
params.EraseTokens(loc.m_matchedTokens);
@@ -859,7 +871,7 @@ namespace impl
bool operator() (Locality const & l) const { return (l.m_value.m_featureId == m_id); }
};
- vector<Locality> m_localities;
+ vector<Locality> m_localities, m_countries, m_states;
FeaturesVector m_vector;
size_t m_index; ///< index of processing token
@@ -873,6 +885,7 @@ namespace impl
{
char const * arr[][2] = {
{ "place", "country" },
+ { "place", "state" },
{ "place", "city" },
{ "place", "town" }
};
@@ -896,9 +909,22 @@ namespace impl
return 0;
}
- bool IsCountry(uint32_t t) const
+ Locality & PushLocalityByType(DoFindLocality & parent, Locality const & l) const
{
- return (t == m_vec[0]);
+ if (l.m_type == m_vec[0])
+ {
+ parent.m_countries.push_back(l);
+ return parent.m_countries.back();
+ }
+
+ if (l.m_type == m_vec[1])
+ {
+ parent.m_states.push_back(l);
+ return parent.m_states.back();
+ }
+
+ parent.m_localities.push_back(l);
+ return parent.m_localities.back();
}
};
@@ -907,16 +933,76 @@ namespace impl
void AssignEnglishName(FeatureType const & f, Locality & l)
{
+ // search for name in next order: "en", "int_name", "default"
for (int i = 0; i < 3; ++i)
if (f.GetName(m_arrEn[i], l.m_enName))
- break;
+ {
+ // make name lower-case
+ strings::AsciiToLower(l.m_enName);
+
+ // do special correction for USA
+ // (needed for CountryInfoGetter::GetMatchedRegions matching)
+ char const * arrUSA[] = { "united", "states", "america" };
+ for (size_t i = 0; i < ARRAY_SIZE(arrUSA); ++i)
+ if (l.m_enName.find(arrUSA[i]) == string::npos)
+ return;
+
+ l.m_enName = "usa";
+ return;
+ }
+ }
+
+ storage::CountryInfoGetter const * m_pInfoGetter;
+
+ void AddRegions(vector<Locality> & localities, vector<Region> & regions) const
+ {
+ // fill regions vector in priority order
+ sort(localities.begin(), localities.end());
+
+ for (vector<Locality>::reverse_iterator i = localities.rbegin();
+ i != localities.rend(); ++i)
+ {
+ // no need to check region with empty english name (can't match for polygon)
+ if (!i->m_enName.empty())
+ {
+ vector<size_t> vec;
+ m_pInfoGetter->GetMatchedRegions(i->m_enName, vec);
+ if (!vec.empty())
+ {
+ regions.push_back(Region());
+ Region & r = regions.back();
+
+ r.m_ids.swap(vec);
+ r.m_matchedTokens.swap(i->m_matchedTokens);
+ r.m_enName.swap(i->m_enName);
+ }
+ }
+ }
+ }
+
+ bool IsBelong(Locality const & loc, Region const & r) const
+ {
+ // check that locality and region are produced from different tokens
+ vector<size_t> dummy;
+ set_intersection(loc.m_matchedTokens.begin(), loc.m_matchedTokens.end(),
+ r.m_matchedTokens.begin(), r.m_matchedTokens.end(),
+ back_inserter(dummy));
+
+ if (dummy.empty())
+ {
+ // check that locality belong to region
+ return m_pInfoGetter->IsBelongToRegion(loc.m_value.m_pt, r.m_ids);
+ }
+
+ return false;
}
volatile bool & m_isCancelled;
public:
DoFindLocality(Query & q, MwmValue * pMwm, int8_t lang, volatile bool & isCancelled)
- : m_vector(pMwm->m_cont, pMwm->GetHeader()), m_lang(lang), m_isCancelled(isCancelled)
+ : m_vector(pMwm->m_cont, pMwm->GetHeader()), m_lang(lang),
+ m_pInfoGetter(q.m_pInfoGetter), m_isCancelled(isCancelled)
{
m_arrEn[0] = q.GetLanguage(LANG_ENGLISH);
m_arrEn[1] = q.GetLanguage(LANG_INTERNATIONAL);
@@ -947,27 +1033,65 @@ namespace impl
// check, if feature is locality
static TypeChecker checker;
uint32_t const t = checker.GetType(f);
- /// @todo Process countries too.
- if (t > 0 && !checker.IsCountry(t))
+ if (t > 0)
{
- m_localities.push_back(Locality(v, t));
+ Locality & loc = checker.PushLocalityByType(*this, Locality(v, t));
- f.GetName(m_lang, m_localities.back().m_name);
+ f.GetName(m_lang, loc.m_name);
- m_localities.back().m_matchedTokens.push_back(m_index);
+ loc.m_matchedTokens.push_back(m_index);
- AssignEnglishName(f, m_localities.back());
+ AssignEnglishName(f, loc);
}
}
bool GetBestLocality(Locality & res)
{
+ LOG(LDEBUG, ("Countries before processing = ", m_countries));
+ LOG(LDEBUG, ("States before processing = ", m_states));
+
+ // First, prepare countries info for checking locality.
+ vector<Region> regions;
+ AddRegions(m_states, regions);
+ AddRegions(m_countries, regions);
+
+ LOG(LDEBUG, ("Regions after processing = ", regions));
+
+ // Get suitable locality.
sort(m_localities.begin(), m_localities.end());
- for (vector<Locality>::const_reverse_iterator i = m_localities.rbegin(); i != m_localities.rend(); ++i)
+ for (vector<Locality>::reverse_iterator i = m_localities.rbegin(); i != m_localities.rend(); ++i)
{
if (i->IsFullNameMatched())
{
+ if (!regions.empty())
+ {
+ // additional check for locality belongs to region
+ Region const * p = 0;
+ for (size_t j = 0; j < regions.size(); ++j)
+ {
+ if (IsBelong(*i, regions[j]))
+ {
+ p = &regions[j];
+ break;
+ }
+ }
+
+ if (p == 0)
+ {
+ // locality doesn't belong to region - goto next
+ continue;
+ }
+ else
+ {
+ // splice locality info with region info
+ i->m_matchedTokens.insert(i->m_matchedTokens.end(),
+ p->m_matchedTokens.begin(), p->m_matchedTokens.end());
+ i->m_enName = i->m_enName + ", " + p->m_enName;
+ }
+ }
+
+ // get best locality and exit
res = *i;
return true;
}
@@ -1006,7 +1130,7 @@ bool Query::SearchLocality(MwmValue * pMwm, impl::Locality & res)
impl::Locality loc;
if (doFind.GetBestLocality(loc) && (res < loc))
{
- LOG(LDEBUG, ("Better location ", loc, " for lang ", lang));
+ LOG(LDEBUG, ("Better location ", loc, " for language ", lang));
res = loc;
}
}