diff --git a/android/jni/com/mapswithme/maps/SearchActivity.cpp b/android/jni/com/mapswithme/maps/SearchActivity.cpp index 73c5d9aa4a..7793fe59e7 100644 --- a/android/jni/com/mapswithme/maps/SearchActivity.cpp +++ b/android/jni/com/mapswithme/maps/SearchActivity.cpp @@ -223,7 +223,7 @@ Java_com_mapswithme_maps_SearchActivity_nativeGetResult( jclass klass = env->FindClass("com/mapswithme/maps/SearchActivity$SearchAdapter$SearchResult"); ASSERT ( klass, () ); - if (res->GetResultType() == search::Result::RESULT_FEATURE) + if (res->GetResultType() != search::Result::RESULT_SUGGESTION) { jmethodID methodID = env->GetMethodID( klass, "", diff --git a/indexer/feature.hpp b/indexer/feature.hpp index eb74291acc..4c65698268 100644 --- a/indexer/feature.hpp +++ b/indexer/feature.hpp @@ -148,21 +148,13 @@ class FeatureType : public FeatureBase { typedef FeatureBase base_type; - /// @name This params define unique id for feature. - //@{ - size_t m_mwmID; - uint32_t m_offset; - //@} + FeatureID m_id; public: void Deserialize(feature::LoaderBase * pLoader, BufferT buffer); - inline void SetID(size_t mwmID, uint32_t offset) - { - m_mwmID = mwmID; - m_offset = offset; - } - inline pair GetID() const { return make_pair(m_mwmID, m_offset); } + inline void SetID(FeatureID const & id) { m_id = id; } + inline FeatureID GetID() const { return m_id; } /// @name Parse functions. Do simple dispatching to m_pLoader. //@{ diff --git a/indexer/feature_data.hpp b/indexer/feature_data.hpp index 37179abee0..27351961ae 100644 --- a/indexer/feature_data.hpp +++ b/indexer/feature_data.hpp @@ -1,4 +1,5 @@ #pragma once +#include "feature_decl.hpp" #include "../coding/multilang_utf8_string.hpp" #include "../coding/value_opt_string.hpp" diff --git a/indexer/feature_decl.hpp b/indexer/feature_decl.hpp new file mode 100644 index 0000000000..82b5a9a6e2 --- /dev/null +++ b/indexer/feature_decl.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include "../std/stdint.hpp" + + +struct FeatureID +{ + size_t m_mwm; + uint32_t m_offset; + + FeatureID() : m_mwm(-1) {} + FeatureID(size_t mwm, uint32_t offset) : m_mwm(mwm), m_offset(offset) {} + + bool IsValid() const { return m_mwm != -1; } + + inline bool operator < (FeatureID const & r) const + { + if (m_mwm == r.m_mwm) + return m_offset < r.m_offset; + else + return m_mwm < r.m_mwm; + } + + inline bool operator == (FeatureID const & r) const + { + return (m_mwm == r.m_mwm && m_offset == r.m_offset); + } +}; diff --git a/indexer/feature_utils.cpp b/indexer/feature_utils.cpp index 8a845cec6d..a117d0ad3b 100644 --- a/indexer/feature_utils.cpp +++ b/indexer/feature_utils.cpp @@ -66,27 +66,18 @@ public: } } - m2::RectD CorrectRectForScales(TypesHolder const & types, m2::RectD const & rect) const + int GetViewportScale(TypesHolder const & types) const { - int const scale = scales::GetScaleLevel(rect); - int scaleNew = scale; - CorrectScaleForVisibility(types, scaleNew); + int scale = GetDefaultScale(); - return ((scale != scaleNew) ? scales::GetRectForLevel(scaleNew, rect.Center()) : rect); - } - - m2::RectD GetViewport(TypesHolder const & types, m2::RectD const & limitRect) const - { - if (types.GetGeoType() != GEOM_POINT) - return CorrectRectForScales(types, limitRect); - - int const upperScale = scales::GetUpperScale(); - int scale = upperScale; - for (size_t i = 0; i < types.Size(); ++i) - scale = min(scale, GetScaleForType(types[i])); + if (types.GetGeoType() == GEOM_POINT) + { + for (size_t i = 0; i < types.Size(); ++i) + scale = min(scale, GetScaleForType(types[i])); + } CorrectScaleForVisibility(types, scale); - return scales::GetRectForLevel(scale, limitRect.Center()); + return scale; } uint8_t GetSearchRank(TypesHolder const & types, m2::PointD const & pt, uint32_t population) const @@ -101,7 +92,8 @@ public: population = max(population, static_cast(10000)); else if (types[i] == m_TypeState) { - m2::RectD usaRects[] = { + m2::RectD usaRects[] = + { // Continental part of USA m2::RectD(-125.73195962769162293, 25.168771674082393019, -66.925073086214325713, 56.956377399113392812), @@ -152,6 +144,7 @@ public: } private: + static int GetDefaultScale() { return scales::GetUpperComfortScale(); } // Returns width and height (lon and lat) for a given type. int GetScaleForType(uint32_t const type) const @@ -181,7 +174,7 @@ private: if (IsEqual(type, m_TypeSmallVillage)) return 14; - return scales::GetUpperScale(); + return GetDefaultScale(); } static uint32_t GetType(string const & s1, @@ -214,9 +207,9 @@ FeatureEstimator const & GetFeatureEstimator() } // namespace feature::impl -m2::RectD GetFeatureViewport(TypesHolder const & types, m2::RectD const & limRect) +int GetFeatureViewportScale(TypesHolder const & types) { - return impl::GetFeatureEstimator().GetViewport(types, limRect); + return impl::GetFeatureEstimator().GetViewportScale(types); } uint8_t GetSearchRank(TypesHolder const & types, m2::PointD const & pt, uint32_t population) diff --git a/indexer/feature_utils.hpp b/indexer/feature_utils.hpp index 0691682e9e..ab4ddc1c58 100644 --- a/indexer/feature_utils.hpp +++ b/indexer/feature_utils.hpp @@ -9,8 +9,8 @@ namespace feature { class TypesHolder; - /// Get viewport to show given feature. Used in search. - m2::RectD GetFeatureViewport(TypesHolder const & types, m2::RectD const & limRect); + /// Get viewport scale to show given feature. Used in search. + int GetFeatureViewportScale(TypesHolder const & types); /// Get search rank for a feature. /// Roughly, rank + 1 means that feature is 1.x times more popular. diff --git a/indexer/index.hpp b/indexer/index.hpp index 40a5423b07..6c43b8ac6c 100644 --- a/indexer/index.hpp +++ b/indexer/index.hpp @@ -119,7 +119,7 @@ private: FeatureType feature; m_V.Get(offset, feature); - feature.SetID(m_mwmID, offset); + feature.SetID(FeatureID(m_mwmID, offset)); m_F(feature); } diff --git a/indexer/indexer.pro b/indexer/indexer.pro index 416015dadd..c12f4be6db 100644 --- a/indexer/indexer.pro +++ b/indexer/indexer.pro @@ -90,6 +90,7 @@ HEADERS += \ feature_algo.hpp \ mwm_version.hpp \ drules_include.hpp \ + feature_decl.hpp \ OTHER_FILES += drules_struct.proto diff --git a/iphone/Maps/Classes/SearchVC.mm b/iphone/Maps/Classes/SearchVC.mm index 17049cc59c..0ff52c72f3 100644 --- a/iphone/Maps/Classes/SearchVC.mm +++ b/iphone/Maps/Classes/SearchVC.mm @@ -410,10 +410,8 @@ static void OnSearchResultCallback(search::Results const & res) } search::Result const & r = [[_searchResults objectAtIndex:scopeSection] getWithPosition:realRowIndex]; - switch (r.GetResultType()) + if (r.GetResultType() != search::Result::RESULT_SUGGESTION) { - case search::Result::RESULT_FEATURE: - { SearchCell * cell = (SearchCell *)[tableView dequeueReusableCellWithIdentifier:@"FeatureCell"]; if (!cell) cell = [[[SearchCell alloc] initWithReuseIdentifier:@"FeatureCell"] autorelease]; @@ -473,22 +471,14 @@ static void OnSearchResultCallback(search::Results const & res) compass.angle = azimut; } return cell; - } - break; - - case search::Result::RESULT_SUGGESTION: - { + } + else + { UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"SuggestionCell"]; if (!cell) cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"SuggestionCell"] autorelease]; cell.textLabel.text = [NSString stringWithUTF8String:r.GetString()]; return cell; - } - break; - - default: - ASSERT(false, ("Unsupported search result type")); - return nil; } } @@ -507,11 +497,8 @@ static void OnSearchResultCallback(search::Results const & res) if (realRowIndex < (NSInteger)[[_searchResults objectAtIndex:scopeSection] getCount]) { search::Result const & res = [[_searchResults objectAtIndex:scopeSection] getWithPosition:realRowIndex]; - switch(res.GetResultType()) + if (res.GetResultType() != search::Result::RESULT_SUGGESTION) { - // Zoom to the feature - case search::Result::RESULT_FEATURE: - { m_framework->ShowSearchResult(res); search::AddressInfo info; @@ -527,14 +514,12 @@ static void OnSearchResultCallback(search::Results const & res) [[MapsAppDelegate theApp].m_mapViewController showSearchResultAsBookmarkAtMercatorPoint:res.GetFeatureCenter() withInfo:info]; [self onCloseButton:nil]; - } - break; - - case search::Result::RESULT_SUGGESTION: + } + else + { [self setSearchBoxText:[NSString stringWithUTF8String:res.GetSuggestionString()]]; // Remove blue selection from the row [tableView deselectRowAtIndexPath: indexPath animated:YES]; - break; } } } @@ -628,7 +613,7 @@ void setSearchType(search::SearchParams & params) UITableViewCell * cell = (UITableViewCell *)[cells objectAtIndex:i]; NSInteger realRowIndex = [m_table indexPathForCell:cell].row; search::Result const & res = [[_searchResults objectAtIndex:scopeSection] getWithPosition:realRowIndex]; - if (res.GetResultType() == search::Result::RESULT_FEATURE) + if (res.GetResultType() != search::Result::RESULT_SUGGESTION) { // Show compass only for cells without flags if ([cell.accessoryView isKindOfClass:[CompassView class]]) diff --git a/map/drawer.cpp b/map/drawer.cpp index 2d7fe61ab6..2950fb96a5 100644 --- a/map/drawer.cpp +++ b/map/drawer.cpp @@ -91,7 +91,7 @@ void Drawer::drawSymbol(m2::PointD const & pt, void Drawer::drawCircle(m2::PointD const & pt, graphics::EPosition pos, di::DrawRule const & rule, - di::FeatureInfo::FeatureID const & id) + FeatureID const & id) { graphics::Circle::Info ci; ConvertStyle(rule.m_rule->GetCircle(), m_visualScale, ci); @@ -102,8 +102,8 @@ void Drawer::drawCircle(m2::PointD const & pt, params.m_position = pos; params.m_pivot = pt; params.m_ci = ci; - params.m_userInfo.m_mwmID = id.first; - params.m_userInfo.m_offset = id.second; + params.m_userInfo.m_mwmID = id.m_mwm; + params.m_userInfo.m_offset = id.m_offset; m_pScreen->drawCircle(params); } @@ -111,7 +111,7 @@ void Drawer::drawCircle(m2::PointD const & pt, void Drawer::drawSymbol(m2::PointD const & pt, graphics::EPosition pos, di::DrawRule const & rule, - di::FeatureInfo::FeatureID const & id) + FeatureID const & id) { graphics::Icon::Info info; ConvertStyle(rule.m_rule->GetSymbol(), info); @@ -122,8 +122,8 @@ void Drawer::drawSymbol(m2::PointD const & pt, params.m_pivot = pt; params.m_info = info; params.m_renderer = m_pScreen.get(); - params.m_userInfo.m_mwmID = id.first; - params.m_userInfo.m_offset = id.second; + params.m_userInfo.m_mwmID = id.m_mwm; + params.m_userInfo.m_offset = id.m_offset; m_pScreen->drawSymbol(params); } @@ -204,7 +204,7 @@ void Drawer::drawText(m2::PointD const & pt, graphics::EPosition pos, di::FeatureStyler const & fs, di::DrawRule const & rule, - di::FeatureInfo::FeatureID const & id) + FeatureID const & id) { graphics::FontDesc primaryFont; m2::PointD primaryOffset; @@ -231,8 +231,8 @@ void Drawer::drawText(m2::PointD const & pt, params.m_auxLogText = strings::MakeUniString(fs.m_secondaryText); params.m_doSplit = true; params.m_useAllParts = false; - params.m_userInfo.m_mwmID = id.first; - params.m_userInfo.m_offset = id.second; + params.m_userInfo.m_mwmID = id.m_mwm; + params.m_userInfo.m_offset = id.m_offset; m_pScreen->drawTextEx(params); } @@ -307,7 +307,7 @@ void Drawer::SetScale(int level) void Drawer::Draw(di::FeatureInfo const & fi) { - di::FeatureInfo::FeatureID const & id = fi.m_id; + FeatureID const & id = fi.m_id; buffer_vector const & rules = fi.m_styler.m_rules; buffer_vector pathRules; diff --git a/map/drawer.hpp b/map/drawer.hpp index e4dabbc6c4..181487ef20 100644 --- a/map/drawer.hpp +++ b/map/drawer.hpp @@ -43,12 +43,12 @@ protected: void drawSymbol(m2::PointD const & pt, graphics::EPosition pos, di::DrawRule const & rule, - di::FeatureInfo::FeatureID const & id); + FeatureID const & id); void drawCircle(m2::PointD const & pt, graphics::EPosition pos, di::DrawRule const & rule, - di::FeatureInfo::FeatureID const & id); + FeatureID const & id); void drawPath(di::PathInfo const & path, di::DrawRule const * rules, @@ -61,7 +61,7 @@ protected: graphics::EPosition pos, di::FeatureStyler const & fs, di::DrawRule const & rule, - di::FeatureInfo::FeatureID const & id); + FeatureID const & id); void drawPathText(di::PathInfo const & info, di::FeatureStyler const & fs, diff --git a/map/feature_info.cpp b/map/feature_info.cpp index e8dc75b3ba..bd5298db2b 100644 --- a/map/feature_info.cpp +++ b/map/feature_info.cpp @@ -1,4 +1,6 @@ #include "feature_info.hpp" +#include "../indexer/feature.hpp" + namespace di { diff --git a/map/feature_info.hpp b/map/feature_info.hpp index 6b52a1a155..e12f0d01d8 100644 --- a/map/feature_info.hpp +++ b/map/feature_info.hpp @@ -4,25 +4,21 @@ #include "path_info.hpp" #include "area_info.hpp" -#include "../indexer/feature.hpp" +#include "../indexer/feature_decl.hpp" #include "../geometry/point2d.hpp" #include "../std/list.hpp" -namespace graphics -{ - class GlyphCache; -} +namespace graphics { class GlyphCache; } +class FeatureType; class ScreenBase; namespace di { struct FeatureInfo { - typedef pair FeatureID; - FeatureStyler m_styler; FeatureID m_id; diff --git a/map/framework.cpp b/map/framework.cpp index 5a0b41a811..7f31006203 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -16,7 +16,12 @@ #include "../indexer/categories_holder.hpp" #include "../indexer/feature.hpp" #include "../indexer/scales.hpp" + +/// @todo Probably it's better to join this functionality. +//@{ #include "../indexer/feature_algo.hpp" +#include "../indexer/feature_utils.hpp" +//@} #include "../anim/controller.hpp" @@ -1224,15 +1229,41 @@ bool Framework::GetCurrentPosition(double & lat, double & lon) const void Framework::ShowSearchResult(search::Result const & res) { + int scale; + m2::PointD center; + + switch (res.GetResultType()) + { + case search::Result::RESULT_FEATURE: + { + FeatureID const id = res.GetFeatureID(); + Index::FeaturesLoaderGuard guard(m_model.GetIndex(), id.m_mwm); + + FeatureType ft; + guard.GetFeature(id.m_offset, ft); + + scale = feature::GetFeatureViewportScale(feature::TypesHolder(ft)); + center = feature::GetCenter(ft, scale); + break; + } + + case search::Result::RESULT_LATLON: + scale = scales::GetUpperComfortScale(); + center = res.GetFeatureCenter(); + break; + + default: + ASSERT(false, ()); + return; + } + StopLocationFollow(); - m2::RectD const rect = res.GetFeatureRect(); - - ShowRectExVisibleScale(rect); + ShowRectExVisibleScale(m_scales.GetRectForDrawScale(scale, center)); search::AddressInfo info; info.MakeFrom(res); - m_balloonManager.ShowAddress(res.GetFeatureCenter(), info); + m_balloonManager.ShowAddress(center, info); } bool Framework::GetDistanceAndAzimut(m2::PointD const & point, diff --git a/qt/search_panel.cpp b/qt/search_panel.cpp index d057de3b6f..484756b41e 100644 --- a/qt/search_panel.cpp +++ b/qt/search_panel.cpp @@ -119,7 +119,7 @@ void SearchPanel::OnSearchResult(ResultsT * res) m_pTable->setItem(rowCount, 1, create_item(QString::fromUtf8(e.GetString()))); m_pTable->setItem(rowCount, 2, create_item(QString::fromUtf8(e.GetRegionString()))); - if (e.GetResultType() == ResultT::RESULT_FEATURE) + if (e.GetResultType() != ResultT::RESULT_SUGGESTION) { // For debug purposes: add bookmarks for search results Bookmark bm(e.GetFeatureCenter(), e.GetString(), "placemark-red"); @@ -163,8 +163,10 @@ void SearchPanel::OnSearchTextChanged(QString const & str) void SearchPanel::OnSearchPanelItemClicked(int row, int) { disconnect(m_pDrawWidget, SIGNAL(ViewportChanged()), this, SLOT(OnViewportChanged())); + ASSERT_EQUAL(m_results.size(), static_cast(m_pTable->rowCount()), ()); - if (m_results[row].GetResultType() == ResultT::RESULT_FEATURE) + + if (m_results[row].GetResultType() != ResultT::RESULT_SUGGESTION) { // center viewport on clicked item m_pDrawWidget->ShowSearchResult(m_results[row]); @@ -175,6 +177,7 @@ void SearchPanel::OnSearchPanelItemClicked(int row, int) string const suggestion = m_results[row].GetSuggestionString(); m_pEditor->setText(QString::fromUtf8(suggestion.c_str())); } + connect(m_pDrawWidget, SIGNAL(ViewportChanged()), this, SLOT(OnViewportChanged())); } diff --git a/search/intermediate_result.cpp b/search/intermediate_result.cpp index ac71ae3a3b..71c3a512cb 100644 --- a/search/intermediate_result.cpp +++ b/search/intermediate_result.cpp @@ -4,7 +4,6 @@ #include "../indexer/classificator.hpp" #include "../indexer/feature.hpp" -#include "../indexer/feature_utils.hpp" #include "../indexer/mercator.hpp" #include "../indexer/scales.hpp" #include "../indexer/categories_holder.hpp" @@ -91,26 +90,42 @@ template bool LessDistanceT(T const & r1, T const & r2) return (r1.m_distanceFromViewportCenter < r2.m_distanceFromViewportCenter); } -PreResult1::PreResult1(uint32_t fID, uint8_t rank, m2::PointD const & center, size_t mwmID, +PreResult1::PreResult1(FeatureID const & fID, uint8_t rank, m2::PointD const & center, m2::PointD const & pos, m2::RectD const & viewport, int8_t viewportID) - : m_center(center), - m_mwmID(mwmID), - m_featureID(fID), + : m_id(fID), m_rank(rank), m_viewportID(viewportID) { - CalcParams(viewport, pos); + ASSERT(m_id.IsValid(), ()); + + CalcParams(center, viewport, pos); } -void PreResult1::CalcParams(m2::RectD const & viewport, m2::PointD const & pos) +PreResult1::PreResult1(m2::PointD const & center, m2::PointD const & pos, m2::RectD const & viewport) { + CalcParams(center, viewport, pos); +} + +namespace +{ + +void AssertValid(m2::PointD const & p) +{ + ASSERT ( my::between_s(-180.0, 180.0, p.x), (p.x) ); + ASSERT ( my::between_s(-180.0, 180.0, p.y), (p.y) ); +} + +} + +void PreResult1::CalcParams(m2::PointD const & fCenter, m2::RectD const & viewport, m2::PointD const & pos) +{ + AssertValid(fCenter); + // Check if point is valid (see Query::empty_pos_value). if (pos.x > -500 && pos.y > -500) { - ASSERT ( my::between_s(-180.0, 180.0, pos.x), (pos.x) ); - ASSERT ( my::between_s(-180.0, 180.0, pos.y), (pos.y) ); - - m_distance = ResultDistance(m_center, pos); + AssertValid(pos); + m_distance = ResultDistance(fCenter, pos); } else { @@ -118,8 +133,8 @@ void PreResult1::CalcParams(m2::RectD const & viewport, m2::PointD const & pos) m_distance = -1.0; } - m_viewportDistance = ViewportDistance(viewport, m_center); - m_distanceFromViewportCenter = ResultDistance(m_center, viewport.Center()); + m_viewportDistance = ViewportDistance(viewport, fCenter); + m_distanceFromViewportCenter = ResultDistance(fCenter, viewport.Center()); } bool PreResult1::LessRank(PreResult1 const & r1, PreResult1 const & r2) @@ -138,10 +153,10 @@ bool PreResult1::LessViewportDistance(PreResult1 const & r1, PreResult1 const & } -void PreResult2::CalcParams(m2::RectD const & viewport, m2::PointD const & pos) +void PreResult2::CalcParams(m2::PointD const & fCenter, m2::RectD const & viewport, m2::PointD const & pos) { // dummy object to avoid copy-paste - PreResult1 res(0, 0, m_center, 0, pos, viewport, -1); + PreResult1 res(fCenter, pos, viewport); m_distance = res.m_distance; m_distanceFromViewportCenter = res.m_distanceFromViewportCenter; @@ -151,24 +166,20 @@ void PreResult2::CalcParams(m2::RectD const & viewport, m2::PointD const & pos) PreResult2::PreResult2(FeatureType const & f, uint8_t rank, m2::RectD const & viewport, m2::PointD const & pos, string const & displayName, string const & fileName) - : m_types(f), + : m_id(f.GetID()), + m_types(f), m_str(displayName), m_resultType(RESULT_FEATURE), m_rank(rank) { - ASSERT ( !m_types.Empty(), () ); + ASSERT(m_id.IsValid(), ()); + ASSERT(!m_types.Empty(), ()); + m_types.SortBySpec(); - m_featureRect = f.GetLimitRect(FeatureType::WORST_GEOMETRY); - m_center = m_featureRect.Center(); - - CalcParams(viewport, pos); - - // get region info - if (!fileName.empty()) - m_region.SetName(fileName); - else - m_region.SetPoint(m_center); + m2::PointD const fCenter = f.GetLimitRect(FeatureType::WORST_GEOMETRY).Center(); + CalcParams(fCenter, viewport, pos); + m_region.SetParams(fileName, fCenter); } PreResult2::PreResult2(m2::RectD const & viewport, m2::PointD const & pos, double lat, double lon) @@ -176,14 +187,9 @@ PreResult2::PreResult2(m2::RectD const & viewport, m2::PointD const & pos, doubl m_resultType(RESULT_LATLON), m_rank(255) { - m_center.x = MercatorBounds::LonToX(lon); - m_center.y = MercatorBounds::LatToY(lat); - m_featureRect.Add(m_center); - - CalcParams(viewport, pos); - - // get region info - m_region.SetPoint(m_center); + m2::PointD const fCenter(MercatorBounds::LonToX(lon), MercatorBounds::LatToY(lat)); + CalcParams(fCenter, viewport, pos); + m_region.SetParams(string(), fCenter); } PreResult2::PreResult2(string const & name, int penalty) @@ -246,15 +252,14 @@ Result PreResult2::GenerateFinalResult( switch (m_resultType) { case RESULT_FEATURE: - return Result(m_str, info.m_name, info.m_flag, GetFeatureType(pCat, pTypes, lang) + return Result(m_id, GetCenter(), m_str, info.m_name, info.m_flag, GetFeatureType(pCat, pTypes, lang) #ifdef DEBUG + ' ' + strings::to_string(static_cast(m_rank)) #endif - , type, GetFinalViewport(), m_distance); + , type, m_distance); case RESULT_LATLON: - return Result(m_str, info.m_name, info.m_flag, string(), 0, - scales::GetRectForLevel(scales::GetUpperScale(), m_center), m_distance); + return Result(GetCenter(), m_str, info.m_name, info.m_flag, m_distance); default: ASSERT_EQUAL ( m_resultType, RESULT_CATEGORY, () ); @@ -282,7 +287,7 @@ bool PreResult2::StrictEqualF::operator() (PreResult2 const & r) const if (m_r.m_resultType == r.m_resultType && m_r.m_resultType == RESULT_FEATURE) { if (m_r.m_str == r.m_str && m_r.GetBestType() == r.GetBestType()) - return (ResultDistance(m_r.m_center, r.m_center) < DIST_EQUAL_RESULTS); + return (ResultDistance(m_r.GetCenter(), r.GetCenter()) < DIST_EQUAL_RESULTS); } return false; @@ -347,7 +352,7 @@ bool PreResult2::EqualLinearTypesF::operator() (PreResult2 const & r1, PreResult // Otherwise we will skip the results for different parts of the map. if (r1.m_resultType == r2.m_resultType && r1.m_str == r2.m_str && //r1.m_viewportDistance == r2.m_viewportDistance && - ResultDistance(r1.m_center, r2.m_center) < DIST_SAME_STREET) + ResultDistance(r1.GetCenter(), r2.GetCenter()) < DIST_SAME_STREET) { // filter equal linear features static IsLinearChecker checker; @@ -415,19 +420,12 @@ string PreResult2::GetFeatureType(CategoriesHolder const * pCat, return classif().GetReadableObjectName(type); } -m2::RectD PreResult2::GetFinalViewport() const -{ - m2::RectD r = feature::GetFeatureViewport(m_types, m_featureRect); - r.SetCenter(m_center); - return r; -} - -void PreResult2::RegionInfo::GetRegion( - storage::CountryInfoGetter const * pInfo, storage::CountryInfo & info) const +void PreResult2::RegionInfo::GetRegion(storage::CountryInfoGetter const * pInfo, + storage::CountryInfo & info) const { if (!m_file.empty()) pInfo->GetRegionInfo(m_file, info); - else if (m_valid) + else pInfo->GetRegionInfo(m_point, info); } diff --git a/search/intermediate_result.hpp b/search/intermediate_result.hpp index 0f35e4ac63..bfac8baab6 100644 --- a/search/intermediate_result.hpp +++ b/search/intermediate_result.hpp @@ -3,11 +3,6 @@ #include "../indexer/feature_data.hpp" -#include "../base/string_utils.hpp" - -#include "../std/shared_ptr.hpp" -#include "../std/map.hpp" - class FeatureType; class CategoriesHolder; @@ -27,7 +22,8 @@ template bool LessRankT(T const & r1, T const & r2); template bool LessViewportDistanceT(T const & r1, T const & r2); template bool LessDistanceT(T const & r1, T const & r2); -/// First results class. Objects are creating during search in trie. +/// First pass results class. Objects are creating during search in trie. +/// Works fast without feature loading and provide ranking. class PreResult1 { friend class PreResult2; @@ -35,34 +31,34 @@ class PreResult1 template friend bool LessViewportDistanceT(T const & r1, T const & r2); template friend bool LessDistanceT(T const & r1, T const & r2); - m2::PointD m_center; + FeatureID m_id; double m_distance, m_distanceFromViewportCenter; - size_t m_mwmID; - uint32_t m_featureID; uint8_t m_viewportDistance; uint8_t m_rank; int8_t m_viewportID; - void CalcParams(m2::RectD const & viewportRect, m2::PointD const & pos); + void CalcParams(m2::PointD const & fCenter, m2::RectD const & viewport, m2::PointD const & pos); public: - PreResult1(uint32_t fID, uint8_t rank, m2::PointD const & center, size_t mwmID, + PreResult1(FeatureID const & fID, uint8_t rank, m2::PointD const & center, m2::PointD const & pos, m2::RectD const & viewport, int8_t viewportID); + PreResult1(m2::PointD const & center, m2::PointD const & pos, m2::RectD const & viewport); static bool LessRank(PreResult1 const & r1, PreResult1 const & r2); static bool LessDistance(PreResult1 const & r1, PreResult1 const & r2); static bool LessViewportDistance(PreResult1 const & r1, PreResult1 const & r2); - inline pair GetID() const { return make_pair(m_mwmID, m_featureID); } - uint8_t GetRank() const { return m_rank; } - int8_t GetViewportID() const { return m_viewportID; } + inline FeatureID GetID() const { return m_id; } + inline uint8_t GetRank() const { return m_rank; } + inline int8_t GetViewportID() const { return m_viewportID; } }; /// Second result class. Objects are creating during reading of features. +/// Read and fill needed info for ranking and getting final results. class PreResult2 { - void CalcParams(m2::RectD const & viewport, m2::PointD const & pos); + void CalcParams(m2::PointD const & fCenter, m2::RectD const & viewport, m2::PointD const & pos); public: enum ResultType @@ -129,34 +125,31 @@ private: string GetFeatureType(CategoriesHolder const * pCat, set const * pTypes, int8_t lang) const; - m2::RectD GetFinalViewport() const; + FeatureID m_id; feature::TypesHolder m_types; + uint32_t GetBestType(set const * pPrefferedTypes = 0) const; string m_str, m_completionString; - class RegionInfo + struct RegionInfo { string m_file; m2::PointD m_point; - bool m_valid; - public: - RegionInfo() : m_valid(false) {} - - void SetName(string const & s) { m_file = s; } - void SetPoint(m2::PointD const & p) + inline void SetParams(string const & file, m2::PointD const & pt) { - m_point = p; - m_valid = true; + m_file = file; + m_point = pt; } - void GetRegion(storage::CountryInfoGetter const * pInfo, storage::CountryInfo & info) const; + void GetRegion(storage::CountryInfoGetter const * pInfo, + storage::CountryInfo & info) const; } m_region; - m2::RectD m_featureRect; - m2::PointD m_center; + m2::PointD GetCenter() const { return m_region.m_point; } + double m_distance, m_distanceFromViewportCenter; ResultType m_resultType; uint8_t m_rank; diff --git a/search/result.cpp b/search/result.cpp index c0f49a8ae0..949dfedd32 100644 --- a/search/result.cpp +++ b/search/result.cpp @@ -4,13 +4,12 @@ namespace search { -Result::Result(string const & str, string const & region, +Result::Result(FeatureID const & id, m2::PointD const & fCenter, + string const & str, string const & region, string const & flag, string const & type, - uint32_t featureType, m2::RectD const & featureRect, - double distanceFromCenter) - : m_str(str), m_region(region), m_flag(flag), m_type(type), - m_featureRect(featureRect), m_featureType(featureType), - m_distanceFromCenter(distanceFromCenter) + uint32_t featureType, double distance) + : m_id(id), m_center(fCenter), m_str(str), m_region(region), + m_flag(flag), m_type(type), m_featureType(featureType), m_distance(distance) { // Features with empty names can be found after suggestion. if (m_str.empty()) @@ -20,6 +19,14 @@ Result::Result(string const & str, string const & region, } } +Result::Result(m2::PointD const & fCenter, + string const & str, string const & region, + string const & flag, double distance) + : m_center(fCenter), m_str(str), m_region(region), + m_flag(flag), m_distance(distance) +{ +} + Result::Result(string const & str, string const & suggestionStr) : m_str(str), m_suggestionStr(suggestionStr) { @@ -29,25 +36,28 @@ Result::ResultType Result::GetResultType() const { if (!m_suggestionStr.empty()) return RESULT_SUGGESTION; - return RESULT_FEATURE; + if (m_id.IsValid()) + return RESULT_FEATURE; + else + return RESULT_LATLON; } -m2::RectD Result::GetFeatureRect() const +FeatureID Result::GetFeatureID() const { ASSERT_EQUAL(GetResultType(), RESULT_FEATURE, ()); - return m_featureRect; + return m_id; +} + +double Result::GetDistance() const +{ + ASSERT_NOT_EQUAL(GetResultType(), RESULT_SUGGESTION, ()); + return m_distance; } m2::PointD Result::GetFeatureCenter() const { - ASSERT_EQUAL(GetResultType(), RESULT_FEATURE, ()); - return m_featureRect.Center(); -} - -double Result::GetDistanceFromCenter() const -{ - ASSERT_EQUAL(GetResultType(), RESULT_FEATURE, ()); - return m_distanceFromCenter; + ASSERT_NOT_EQUAL(GetResultType(), RESULT_SUGGESTION, ()); + return m_center; } char const * Result::GetSuggestionString() const @@ -60,7 +70,7 @@ bool Result::operator== (Result const & r) const { return (m_str == r.m_str && m_region == r.m_region && m_featureType == r.m_featureType && GetResultType() == r.GetResultType() && - my::AlmostEqual(m_distanceFromCenter, r.m_distanceFromCenter)); + my::AlmostEqual(m_distance, r.m_distance)); } void Results::AddResultCheckExisting(Result const & r) @@ -75,7 +85,7 @@ void Results::AddResultCheckExisting(Result const & r) void AddressInfo::MakeFrom(Result const & res) { - ASSERT_EQUAL ( res.GetResultType(), Result::RESULT_FEATURE, () ); + ASSERT_NOT_EQUAL(res.GetResultType(), Result::RESULT_SUGGESTION, ()); // push the feature type (may be empty for coordinates result) string const type = res.GetFeatureType(); diff --git a/search/result.hpp b/search/result.hpp index 27f1399854..db19031a4b 100644 --- a/search/result.hpp +++ b/search/result.hpp @@ -1,8 +1,12 @@ #pragma once +#include "../indexer/feature_decl.hpp" + #include "../geometry/point2d.hpp" #include "../geometry/rect2d.hpp" + #include "../std/string.hpp" + namespace search { @@ -13,43 +17,59 @@ public: enum ResultType { RESULT_FEATURE, + RESULT_LATLON, RESULT_SUGGESTION }; - Result(string const & str, string const & region, + /// For RESULT_FEATURE. + Result(FeatureID const & id, m2::PointD const & fCenter, + string const & str, string const & region, string const & flag, string const & type, - uint32_t featureType, m2::RectD const & featureRect, - double distanceFromCenter); + uint32_t featureType, double distance); + + /// For RESULT_LATLON. + Result(m2::PointD const & fCenter, + string const & str, string const & region, + string const & flag, double distance); + + /// For RESULT_SUGGESTION. Result(string const & str, string const & suggestionStr); - // String that is displayed in the GUI. + /// Strings that is displayed in the GUI. + //@{ char const * GetString() const { return m_str.c_str(); } char const * GetRegionString() const { return m_region.c_str(); } char const * GetRegionFlag() const { return m_flag.empty() ? 0 : m_flag.c_str(); } char const * GetFeatureType() const { return m_type.c_str(); } + //@} - // Type of the result. + /// Type of the result. ResultType GetResultType() const; - // Rect of a feature, if GetResultType() == RESULT_FEATURE. - m2::RectD GetFeatureRect() const; + /// Feature id in mwm. + /// @precondition GetResultType() == RESULT_FEATURE + FeatureID GetFeatureID() const; - // Center point of a feature, if GetResultType() == RESULT_FEATURE. + /// Center point of a feature. + /// @precondition GetResultType() != RESULT_SUGGESTION m2::PointD GetFeatureCenter() const; - // Distance from the center of the screen, if GetResultType() == RESULT_FEATURE. - double GetDistanceFromCenter() const; + /// Distance from the current position or -1 if location is not detected. + /// @precondition GetResultType() != RESULT_SUGGESTION + double GetDistance() const; - // String to write in the search box. + /// String to write in the search box. + /// @precondition GetResultType() == RESULT_SUGGESTION char const * GetSuggestionString() const; bool operator== (Result const & r) const; private: + FeatureID m_id; + m2::PointD m_center; string m_str, m_region, m_flag, m_type; - m2::RectD m_featureRect; uint32_t m_featureType; - double m_distanceFromCenter; + double m_distance; string m_suggestionStr; }; diff --git a/search/search_engine.cpp b/search/search_engine.cpp index 5dfe0f4562..60a4e8815f 100644 --- a/search/search_engine.cpp +++ b/search/search_engine.cpp @@ -193,12 +193,19 @@ namespace { bool LessByDistance(Result const & r1, Result const & r2) { - Result::ResultType const t1 = r1.GetResultType(); + bool const isSuggest1 = r1.GetResultType() == Result::RESULT_SUGGESTION; + bool const isNotSuggest2 = r2.GetResultType() != Result::RESULT_SUGGESTION; - if (t1 == r2.GetResultType() && t1 == Result::RESULT_FEATURE) - return (r1.GetDistanceFromCenter() < r2.GetDistanceFromCenter()); - else if (t1 == Result::RESULT_SUGGESTION) - return true; + if (isSuggest1) + { + // suggestions should always be on top + return isNotSuggest2; + } + else if (isNotSuggest2) + { + // we can't call GetDistance for suggestions + return (r1.GetDistance() < r2.GetDistance()); + } else return false; } diff --git a/search/search_query.cpp b/search/search_query.cpp index 0dcd3ea53e..4929b264f1 100644 --- a/search/search_query.cpp +++ b/search/search_query.cpp @@ -432,13 +432,13 @@ namespace impl scoped_ptr m_pFV; // For the best performance, incoming id's should be sorted by id.first (mwm file id). - void LoadFeature(pair const & id, - FeatureType & f, string & name, string & country) + void LoadFeature(FeatureID const & id, FeatureType & f, string & name, string & country) { - if (m_pFV.get() == 0 || m_pFV->GetID() != id.first) - m_pFV.reset(new Index::FeaturesLoaderGuard(*m_query.m_pIndex, id.first)); + if (m_pFV.get() == 0 || m_pFV->GetID() != id.m_mwm) + m_pFV.reset(new Index::FeaturesLoaderGuard(*m_query.m_pIndex, id.m_mwm)); - m_pFV->GetFeature(id.second, f); + m_pFV->GetFeature(id.m_offset, f); + f.SetID(id); m_query.GetBestMatchName(f, name); @@ -466,7 +466,7 @@ namespace impl name, country); } - impl::PreResult2 * operator() (pair const & id) + impl::PreResult2 * operator() (FeatureID const & id) { FeatureType feature; string name, country; @@ -575,7 +575,7 @@ namespace void Query::AddResultFromTrie(TrieValueT const & val, size_t mwmID, int8_t viewportID) { - impl::PreResult1 res(val.m_featureId, val.m_rank, val.m_pt, mwmID, + impl::PreResult1 res(FeatureID(mwmID, val.m_featureId), val.m_rank, val.m_pt, GetPosition(viewportID), GetViewport(viewportID), viewportID); for (size_t i = 0; i < m_qCount; ++i) @@ -1834,7 +1834,7 @@ void Query::SearchAllInViewport(m2::RectD const & viewport, Results & res, unsig { if (m_cancel) break; - AddPreResult2(maker(make_pair(i, offsets[i][j])), indV); + AddPreResult2(maker(FeatureID(i, offsets[i][j])), indV); } }