From 097e071f80b967c546d98a48edf14061879f63c9 Mon Sep 17 00:00:00 2001 From: vng Date: Wed, 8 Jan 2014 19:15:08 +0300 Subject: [PATCH] [search] Built-in house search in main engine (initial commit). --- search/house_detector.cpp | 13 +++++- search/house_detector.hpp | 7 ++-- search/intermediate_result.cpp | 44 +++++++++++++++++++++ search/intermediate_result.hpp | 3 ++ search/search_engine.cpp | 2 +- search/search_query.cpp | 72 ++++++++++++++++++++++++++++------ search/search_query.hpp | 13 ++++++ 7 files changed, 137 insertions(+), 17 deletions(-) diff --git a/search/house_detector.cpp b/search/house_detector.cpp index cd825f70c6..b7c2acd56c 100644 --- a/search/house_detector.cpp +++ b/search/house_detector.cpp @@ -183,10 +183,11 @@ void HouseDetector::Bfs(Street * st) } } -void HouseDetector::LoadStreets(vector & ids) +int HouseDetector::LoadStreets(vector & ids) { sort(ids.begin(), ids.end()); + int count = 0; for (size_t i = 0; i < ids.size(); ++i) { if (m_id2st.find(ids[i]) != m_id2st.end()) @@ -201,6 +202,8 @@ void HouseDetector::LoadStreets(vector & ids) if (!f.GetName(0, name) || name.empty()) continue; + ++count; + Street * st = new Street(); st->SetName(name); f.ForEachPoint(StreetCreator(st), FeatureType::BEST_GEOMETRY); @@ -214,6 +217,7 @@ void HouseDetector::LoadStreets(vector & ids) } m_loader.Free(); + return count; } int HouseDetector::MergeStreets() @@ -407,6 +411,10 @@ void HouseDetector::MatchAllHouses(string const & houseNumber, vector & res) +{ + +} namespace @@ -558,7 +566,8 @@ void ProccessHouses(vector & houses, vector range, map & m) +void GetAllHousesForStreet(pair range, + map & m) { for (search::HouseDetector::IterM it = range.first; it != range.second; ++it) { diff --git a/search/house_detector.hpp b/search/house_detector.hpp index 17ca98725a..5511e42a03 100644 --- a/search/house_detector.hpp +++ b/search/house_detector.hpp @@ -150,7 +150,7 @@ public: HouseDetector(Index const * pIndex); - void LoadStreets(vector & ids); + int LoadStreets(vector & ids); /// @return number of different joined streets. int MergeStreets(); @@ -158,7 +158,7 @@ public: void ReadAllHouses(double offsetMeters); void MatchAllHouses(string const & houseNumber, vector & res); - vector GetHouseForName(string const & houseName); + void GetHouseForName(string const & houseNumber, vector & res); pair GetAllStreets(); void SimpleFilter(string const & houseNumber, vector & res); @@ -166,6 +166,7 @@ public: void LongestSubsequence(vector const & houses, vector & result); -void GetAllHousesForStreet(pair range, map & m); +void GetAllHousesForStreet(pair range, + map & m); } diff --git a/search/intermediate_result.cpp b/search/intermediate_result.cpp index 55d06c8b4d..010a42e9ea 100644 --- a/search/intermediate_result.cpp +++ b/search/intermediate_result.cpp @@ -336,6 +336,44 @@ namespace return (find(m_index, e, FirstLevelIndex(type)) != e); } }; + + class IsStreetChecker + { + vector m_types; + + public: + IsStreetChecker() + { + Classificator const & c = classif(); + char const * arr[][2] = { + { "highway", "primary" }, + { "highway", "secondary" }, + { "highway", "residential" }, + { "highway", "pedestrian" }, + { "highway", "residential" }, + { "highway", "tertiary" }, + { "highway", "construction" }, + { "highway", "living_street" }, + { "highway", "trunk" } + }; + + for (size_t i = 0; i < ARRAY_SIZE(arr); ++i) + m_types.push_back(c.GetTypeByPath(vector(arr[i], arr[i] + 2))); + } + + bool IsMy(feature::TypesHolder const & types) const + { + for (size_t i = 0; i < types.Size(); ++i) + { + uint32_t t = types[i]; + ftype::TruncValue(t, 2); + + if (find(m_types.begin(), m_types.end(), t) != m_types.end()) + return true; + } + return false; + } + }; } bool PreResult2::LessLinearTypesF::operator() (PreResult2 const & r1, PreResult2 const & r2) const @@ -375,6 +413,12 @@ bool PreResult2::EqualLinearTypesF::operator() (PreResult2 const & r1, PreResult return false; } +bool PreResult2::IsStreet() const +{ + static IsStreetChecker checker; + return checker.IsMy(m_types); +} + string PreResult2::DebugPrint() const { string res("IntermediateResult: "); diff --git a/search/intermediate_result.hpp b/search/intermediate_result.hpp index fa0d91748e..e1bbe3961c 100644 --- a/search/intermediate_result.hpp +++ b/search/intermediate_result.hpp @@ -119,6 +119,9 @@ public: string DebugPrint() const; + bool IsStreet() const; + inline FeatureID const & GetID() const { return m_id; } + private: template friend bool LessRankT(T const & r1, T const & r2); template friend bool LessViewportDistanceT(T const & r1, T const & r2); diff --git a/search/search_engine.cpp b/search/search_engine.cpp index 048cf416ff..765226e059 100644 --- a/search/search_engine.cpp +++ b/search/search_engine.cpp @@ -85,7 +85,7 @@ Engine::Engine(IndexType const * pIndex, Reader * pCategoriesR, &m_pData->m_categories, &m_pData->m_stringsToSuggest, &m_pData->m_infoGetter, - RESULTS_COUNT)); + 100)); // Temporary for houses test m_pQuery->SetPreferredLanguage(lang); } diff --git a/search/search_query.cpp b/search/search_query.cpp index df61ac4036..c097aaddcb 100644 --- a/search/search_query.cpp +++ b/search/search_query.cpp @@ -75,6 +75,7 @@ Query::Query(Index const * pIndex, m_pCategories(pCategories), m_pStringsToSuggest(pStringsToSuggest), m_pInfoGetter(pInfoGetter), + m_houseDetector(pIndex), m_worldSearch(true), m_position(empty_pos_value, empty_pos_value) { @@ -266,6 +267,11 @@ void Query::ClearQueues() void Query::SetQuery(string const & query) { +#ifdef HOUSE_SEARCH_TEST + m_house.clear(); + m_streetID.clear(); +#endif + // split input query by tokens and prefix search::Delimiters delims; SplitUniString(NormalizeAndSimplifyString(query), MakeBackInsertFunctor(m_tokens), delims); @@ -295,6 +301,31 @@ void Query::SearchCoordinates(string const & query, Results & res) const } } +namespace +{ +bool IsNumber(strings::UniString const & s) +{ + for (size_t i = 0; i < s.size(); ++i) + { + // android production ndk-r8d has bug. "еда" detected as a number. + if (s[i] > 127 || !isdigit(s[i])) + return false; + } + return true; +} + +bool isHouseNumber(strings::UniString const & s) +{ + if (s.size() > 6) + return false; + if (s[0] > 127 || !isdigit(s[0])) + return false; + cout << strings::ToUtf8(s) << " is house number" << endl; + return true; +} + +} + void Query::Search(Results & res, bool searchAddress) { ClearQueues(); @@ -302,6 +333,14 @@ void Query::Search(Results & res, bool searchAddress) if (m_cancel) return; SuggestStrings(res); +#ifdef HOUSE_SEARCH_TEST + if (m_tokens.size() > 1 && isHouseNumber(m_tokens.back())) + { + m_house.swap(m_tokens.back()); + m_tokens.pop_back(); + } +#endif + if (m_cancel) return; if (searchAddress) SearchAddress(); @@ -509,6 +548,28 @@ void Query::FlushResults(Results & res, void (Results::*pAddFn)(Result const &)) if (indV.empty()) return; +#ifdef HOUSE_SEARCH_TEST + if (!m_house.empty()) + { + vector streets; + for (size_t i = 0; i < indV.size(); ++i) + { + impl::PreResult2 const & r = *(indV[i]); + if (r.IsStreet()) + streets.push_back(r.GetID()); + } + + if (m_houseDetector.LoadStreets(streets) > 0) + m_houseDetector.MergeStreets(); + vector houses; + m_houseDetector.GetHouseForName(strings::ToUtf8(m_house), houses); + + for (size_t i = 0; i < houses.size(); ++i) + (res.*pAddFn)(Result(houses[i].GetPosition(), houses[i].GetNumber(), + string(), string(), houses[i].GetPosition().Length(m_position))); + } +#endif + RemoveDuplicatingLinear(indV); for (size_t i = 0; i < m_qCount; ++i) @@ -920,17 +981,6 @@ string DebugPrint(Query::Params const & p) namespace { - bool IsNumber(strings::UniString const & s) - { - for (size_t i = 0; i < s.size(); ++i) - { - // android production ndk-r8d has bug. "еда" detected as a number. - if (s[i] > 127 || !isdigit(s[i])) - return false; - } - return true; - } - class DoStoreNumbers { vector & m_vec; diff --git a/search/search_query.hpp b/search/search_query.hpp index d7ef608529..6a456772dd 100644 --- a/search/search_query.hpp +++ b/search/search_query.hpp @@ -18,6 +18,13 @@ #include "../std/vector.hpp" +#define HOUSE_SEARCH_TEST + +#ifdef HOUSE_SEARCH_TEST +#include "house_detector.hpp" +#endif + + class FeatureType; class CategoriesHolder; @@ -190,6 +197,12 @@ private: buffer_vector m_tokens; strings::UniString m_prefix; +#ifdef HOUSE_SEARCH_TEST + strings::UniString m_house; + vector m_streetID; + search::HouseDetector m_houseDetector; +#endif + /// 0 - current viewport rect /// 1 - near me rect /// 2 - around city rect