From 4dda2e079c494dcb6524ddbf96135f0cadd75e16 Mon Sep 17 00:00:00 2001 From: vng Date: Thu, 24 Jul 2014 20:15:16 +0300 Subject: [PATCH] [search] Refactored emitting final search results. --- .../com/mapswithme/maps/SearchActivity.cpp | 17 ++-- .../com/mapswithme/maps/SearchActivity.java | 3 +- indexer/feature_data.hpp | 6 ++ indexer/ftypes_matcher.hpp | 2 + iphone/Maps/Classes/SearchView.mm | 7 +- map/framework.cpp | 34 +++++--- qt/search_panel.cpp | 12 +-- search/house_detector.cpp | 10 ++- search/house_detector.hpp | 5 ++ search/intermediate_result.cpp | 29 ++++--- search/intermediate_result.hpp | 13 +-- search/result.cpp | 83 ++++++++++--------- search/result.hpp | 35 ++++---- search/search_query.cpp | 28 ++----- 14 files changed, 149 insertions(+), 135 deletions(-) diff --git a/android/jni/com/mapswithme/maps/SearchActivity.cpp b/android/jni/com/mapswithme/maps/SearchActivity.cpp index 0f3c560baa..dd5162e57e 100644 --- a/android/jni/com/mapswithme/maps/SearchActivity.cpp +++ b/android/jni/com/mapswithme/maps/SearchActivity.cpp @@ -251,34 +251,27 @@ Java_com_mapswithme_maps_SearchActivity_nativeGetResult( env->ReleaseIntArrayElements(ranges, narr, 0); jclass klass = env->FindClass("com/mapswithme/maps/SearchActivity$SearchAdapter$SearchResult"); - ASSERT ( klass, () ); + ASSERT(klass, ()); - if (res->GetResultType() != search::Result::RESULT_SUGGESTION) + if (!res->IsSuggest()) { jmethodID methodID = env->GetMethodID( klass, "", - "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;D[I)V"); + "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[I)V"); ASSERT ( methodID, () ); string distance; - double azimut = -1.0; if (hasPosition) { - if (!g_framework->NativeFramework()->GetDistanceAndAzimut( - res->GetFeatureCenter(), lat, lon, north, distance, azimut)) - { - // do not show the arrow for far away features - azimut = -1.0; - } + double dummy; + (void) g_framework->NativeFramework()->GetDistanceAndAzimut(res->GetFeatureCenter(), lat, lon, north, distance, dummy); } return env->NewObject(klass, methodID, jni::ToJavaString(env, res->GetString()), jni::ToJavaString(env, res->GetRegionString()), jni::ToJavaString(env, res->GetFeatureType()), - jni::ToJavaString(env, res->GetRegionFlag()), jni::ToJavaString(env, distance.c_str()), - static_cast(azimut), static_cast(ranges)); } else diff --git a/android/src/com/mapswithme/maps/SearchActivity.java b/android/src/com/mapswithme/maps/SearchActivity.java index 60eb2dbc8d..df5d22fb8f 100644 --- a/android/src/com/mapswithme/maps/SearchActivity.java +++ b/android/src/com/mapswithme/maps/SearchActivity.java @@ -496,8 +496,7 @@ public class SearchActivity extends MapsWithMeBaseListActivity implements Locati // Called from native code @SuppressWarnings("unused") public SearchResult(String name, String country, String amenity, - String flag, String distance, double azimut, - int[] highlightRanges) + String distance, int[] highlightRanges) { mName = name; mCountry = country; diff --git a/indexer/feature_data.hpp b/indexer/feature_data.hpp index af9230fec6..2d1d0f09a3 100644 --- a/indexer/feature_data.hpp +++ b/indexer/feature_data.hpp @@ -66,6 +66,12 @@ namespace feature TypesHolder(EGeomType geoType = GEOM_UNDEFINED) : m_size(0), m_geoType(geoType) {} TypesHolder(FeatureBase const & f); + void Assign(uint32_t type) + { + m_types[0] = type; + m_size = 1; + } + /// Accumulation function. inline void operator() (uint32_t t) { m_types[m_size++] = t; } diff --git a/indexer/ftypes_matcher.hpp b/indexer/ftypes_matcher.hpp index 84dd84eff0..5b0844ae23 100644 --- a/indexer/ftypes_matcher.hpp +++ b/indexer/ftypes_matcher.hpp @@ -42,6 +42,8 @@ class IsBuildingChecker : public BaseChecker { public: IsBuildingChecker(); + + uint32_t GetMainType() const { return m_types[0]; } }; /// Type of locality (do not change values and order - they have detalization order) diff --git a/iphone/Maps/Classes/SearchView.mm b/iphone/Maps/Classes/SearchView.mm index 1c7e256a8d..3711038d1d 100644 --- a/iphone/Maps/Classes/SearchView.mm +++ b/iphone/Maps/Classes/SearchView.mm @@ -274,8 +274,8 @@ __weak SearchView * selfPointer; - (void)recalculateDistances { LocationManager * locationManager = [MapsAppDelegate theApp].m_locationManager; + double north = -1.0; - double azimut = -1.0; [locationManager getNorthRad:north]; double lat, lon; if ([locationManager getLat:lat Lon:lon]) @@ -284,9 +284,10 @@ __weak SearchView * selfPointer; for (NSInteger position = 0; position < [wrapper count]; position++) { search::Result const & result = [wrapper resultWithPosition:position]; - string distance; - if (result.GetResultType() != search::Result::RESULT_SUGGESTION) + if (result.HasPoint()) { + string distance; + double azimut = -1.0; GetFramework().GetDistanceAndAzimut(result.GetFeatureCenter(), lat, lon, north, distance, azimut); wrapper.distances[@(position)] = [NSString stringWithUTF8String:distance.c_str()]; } diff --git a/map/framework.cpp b/map/framework.cpp index b5c7082a30..b51574ad95 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -1430,26 +1430,36 @@ size_t Framework::ShowAllSearchResults() m2::PointD const center = viewport.Center(); double minDistance = numeric_limits::max(); - size_t minInd; + int minInd = -1; for (size_t i = 0; i < count; ++i) { - double const dist = center.SquareLength(results.GetResult(i).GetFeatureCenter()); - if (dist < minDistance) + Result const & r = results.GetResult(i); + if (r.HasPoint()) { - minDistance = dist; - minInd = i; + double const dist = center.SquareLength(r.GetFeatureCenter()); + if (dist < minDistance) + { + minDistance = dist; + minInd = static_cast(i); + } } } - m2::PointD const pt = results.GetResult(minInd).GetFeatureCenter(); - if (!viewport.IsPointInside(pt)) + if (minInd != -1) { - viewport.SetSizesToIncludePoint(pt); + m2::PointD const pt = results.GetResult(minInd).GetFeatureCenter(); + if (!viewport.IsPointInside(pt)) + { + viewport.SetSizesToIncludePoint(pt); - ShowRectFixedAR(viewport); - StopLocationFollow(); + ShowRectFixedAR(viewport); + StopLocationFollow(); + } + else + minInd = -1; } - else + + if (minInd == -1) Invalidate(); return count; @@ -1468,7 +1478,7 @@ void Framework::FillSearchResultsMarks(search::Results const & results) using namespace search; Result const & r = results.GetResult(i); - if (!r.IsSuggest()) + if (r.HasPoint()) { AddressInfo info; info.MakeFrom(r); diff --git a/qt/search_panel.cpp b/qt/search_panel.cpp index 0abdc96e8d..78cc1c181e 100644 --- a/qt/search_panel.cpp +++ b/qt/search_panel.cpp @@ -183,17 +183,17 @@ void SearchPanel::OnSearchPanelItemClicked(int row, int) { ASSERT_EQUAL(m_results.size(), static_cast(m_pTable->rowCount()), ()); - if (m_results[row].GetResultType() != ResultT::RESULT_SUGGESTION) - { - // center viewport on clicked item - m_pDrawWidget->ShowSearchResult(m_results[row]); - } - else + if (m_results[row].IsSuggest()) { // insert suggestion into the search bar string const suggestion = m_results[row].GetSuggestionString(); m_pEditor->setText(QString::fromUtf8(suggestion.c_str())); } + else + { + // center viewport on clicked item + m_pDrawWidget->ShowSearchResult(m_results[row]); + } } void SearchPanel::hideEvent(QHideEvent *) diff --git a/search/house_detector.cpp b/search/house_detector.cpp index d64777bbc7..9cd872e75b 100644 --- a/search/house_detector.cpp +++ b/search/house_detector.cpp @@ -2,7 +2,6 @@ #include "search_common.hpp" #include "algos.hpp" -#include "../indexer/ftypes_matcher.hpp" #include "../indexer/feature_impl.hpp" #include "../indexer/classificator.hpp" @@ -803,15 +802,18 @@ HouseProjection const * MergedStreet::GetHousePivot(bool isOdd, bool & sign) con return 0; } +uint32_t HouseDetector::GetBuildingType() const +{ + return m_buildingChecker.GetMainType(); +} + template void HouseDetector::ReadHouse(FeatureType const & f, Street * st, ProjectionCalcT & calc) { - static ftypes::IsBuildingChecker const checker; - string const houseNumber = f.GetHouseNumber(); /// @todo After new data generation we can skip IsHouseNumber check here. - if (checker(f) && feature::IsHouseNumber(houseNumber)) + if (m_buildingChecker(f) && feature::IsHouseNumber(houseNumber)) { HouseMapT::iterator const it = m_id2house.find(f.GetID()); bool const isNew = it == m_id2house.end(); diff --git a/search/house_detector.hpp b/search/house_detector.hpp index 38a5939c91..16f0e84c4c 100644 --- a/search/house_detector.hpp +++ b/search/house_detector.hpp @@ -3,6 +3,7 @@ #include "../indexer/feature_decl.hpp" #include "../indexer/index.hpp" +#include "../indexer/ftypes_matcher.hpp" #include "../geometry/point2d.hpp" @@ -237,6 +238,8 @@ class HouseDetector int m_streetNum; double m_houseOffsetM; + ftypes::IsBuildingChecker m_buildingChecker; + typedef pair StreetPtr; StreetPtr FindConnection(Street const * st, bool beg) const; void MergeStreets(Street * st); @@ -252,6 +255,8 @@ class HouseDetector public: HouseDetector(Index const * pIndex); + uint32_t GetBuildingType() const; + int LoadStreets(vector const & ids); /// @return number of different joined streets. int MergeStreets(); diff --git a/search/intermediate_result.cpp b/search/intermediate_result.cpp index c3fb46d3eb..03afe967fe 100644 --- a/search/intermediate_result.cpp +++ b/search/intermediate_result.cpp @@ -171,15 +171,19 @@ PreResult2::PreResult2(FeatureType const & f, PreResult1 const * p, CalcParams(viewport, pos); } -PreResult2::PreResult2(m2::RectD const & viewport, m2::PointD const & pos, double lat, double lon) +PreResult2::PreResult2(double lat, double lon) : m_str("(" + MeasurementUtils::FormatLatLon(lat, lon) + ")"), - m_resultType(RESULT_LATLON), - m_rank(255), - m_geomType(feature::GEOM_UNDEFINED) + m_resultType(RESULT_LATLON) { - m2::PointD const fCenter(MercatorBounds::FromLatLon(lat, lon)); - m_region.SetParams(string(), fCenter); - CalcParams(viewport, pos); + m_region.SetParams(string(), MercatorBounds::FromLatLon(lat, lon)); +} + +PreResult2::PreResult2(m2::PointD const & pt, string const & str, uint32_t type) + : m_str(str), m_resultType(RESULT_BUILDING) +{ + m_region.SetParams(string(), pt); + + m_types.Assign(type); } namespace @@ -218,7 +222,7 @@ Result PreResult2::GenerateFinalResult( uint32_t const type = GetBestType(); - static SkipRegionInfo checker; + static SkipRegionInfo const checker; if (!checker.IsContinent(type)) { m_region.GetRegion(pInfo, info); @@ -230,15 +234,18 @@ Result PreResult2::GenerateFinalResult( switch (m_resultType) { case RESULT_FEATURE: - return Result(m_id, GetCenter(), m_str, info.m_name, info.m_flag, GetFeatureType(pCat, pTypes, lang) + return Result(m_id, GetCenter(), m_str, info.m_name, GetFeatureType(pCat, pTypes, lang) #ifdef DEBUG + ' ' + strings::to_string(static_cast(m_rank)) #endif - , type, m_distance); + , type); + + case RESULT_BUILDING: + return Result(GetCenter(), m_str, info.m_name, GetFeatureType(pCat, pTypes, lang)); default: ASSERT_EQUAL(m_resultType, RESULT_LATLON, ()); - return Result(GetCenter(), m_str, info.m_name, info.m_flag, m_distance); + return Result(GetCenter(), m_str, info.m_name, string()); } } diff --git a/search/intermediate_result.hpp b/search/intermediate_result.hpp index 7aa843047b..6334ff68c3 100644 --- a/search/intermediate_result.hpp +++ b/search/intermediate_result.hpp @@ -69,17 +69,20 @@ public: enum ResultType { RESULT_LATLON, - RESULT_FEATURE + RESULT_FEATURE, + RESULT_BUILDING }; - // For RESULT_FEATURE. + /// For RESULT_FEATURE. PreResult2(FeatureType const & f, PreResult1 const * p, m2::RectD const & viewport, m2::PointD const & pos, string const & displayName, string const & fileName); - // For RESULT_LATLON. - PreResult2(m2::RectD const & viewport, m2::PointD const & pos, - double lat, double lon); + /// For RESULT_LATLON. + PreResult2(double lat, double lon); + + /// For RESULT_BUILDING. + PreResult2(m2::PointD const & pt, string const & str, uint32_t type); /// @param[in] pInfo Need to get region for result. /// @param[in] pCat Categories need to display readable type string. diff --git a/search/result.cpp b/search/result.cpp index c3e61424c9..e50ebf65d6 100644 --- a/search/result.cpp +++ b/search/result.cpp @@ -5,19 +5,15 @@ namespace search { -Result::Result(FeatureID const & id, m2::PointD const & fCenter, +Result::Result(FeatureID const & id, m2::PointD const & pt, string const & str, string const & region, - string const & flag, string const & type, - 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) + string const & type, uint32_t featureType) + : m_id(id), m_center(pt), m_str(str), m_region(region), + m_type(type), m_featureType(featureType) { // Features with empty names can be found after suggestion. if (m_str.empty()) - { - //m_str = "-"; m_str = type; - } } Result::Result(m2::PointD const & pt, string const & str, string const & type) @@ -25,11 +21,9 @@ Result::Result(m2::PointD const & pt, string const & str, string const & type) { } -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_featureType(0), m_distance(distance) +Result::Result(m2::PointD const & pt, string const & str, + string const & region, string const & type) + : m_center(pt), m_str(str), m_region(region), m_type(type) { } @@ -38,14 +32,21 @@ Result::Result(string const & str, string const & suggest) { } +Result::Result(Result const & res, string const & suggest) + : m_center(res.m_center), m_str(res.m_str), m_region(res.m_region), + m_featureType(res.m_featureType), m_suggestionStr(suggest), + m_hightlightRanges(res.m_hightlightRanges) +{ +} + Result::ResultType Result::GetResultType() const { + bool const idValid = m_id.IsValid(); + if (!m_suggestionStr.empty()) - return RESULT_SUGGESTION; - if (m_id.IsValid()) - return RESULT_FEATURE; - else - return RESULT_LATLON; + return (idValid ? RESULT_SUGGEST_FROM_FEATURE : RESULT_SUGGEST_PURE); + + return (idValid ? RESULT_FEATURE : RESULT_LATLON); } bool Result::IsSuggest() const @@ -53,21 +54,20 @@ bool Result::IsSuggest() const return !m_suggestionStr.empty(); } +bool Result::HasPoint() const +{ + return (GetResultType() != RESULT_SUGGEST_PURE); +} + FeatureID Result::GetFeatureID() const { ASSERT_EQUAL(GetResultType(), RESULT_FEATURE, ()); return m_id; } -double Result::GetDistance() const -{ - ASSERT(!IsSuggest(), ()); - return m_distance; -} - m2::PointD Result::GetFeatureCenter() const { - ASSERT(!IsSuggest(), ()); + ASSERT(HasPoint(), ()); return m_center; } @@ -82,8 +82,11 @@ bool Result::operator== (Result const & r) const ResultType const type = GetResultType(); if (type == r.GetResultType()) { - if (type == RESULT_SUGGESTION) - return m_suggestionStr == r.m_suggestionStr; + if (IsSuggest()) + { + ASSERT(r.IsSuggest(), ()); + return (m_suggestionStr == r.m_suggestionStr); + } else { // This function is used to filter duplicate results in cases: @@ -133,15 +136,18 @@ bool Results::AddResultCheckExisting(Result const & r) size_t Results::GetSuggestsCount() const { - size_t suggestsCount = 0; + size_t res = 0; for (size_t i = 0; i < GetCount(); i++) { - if (m_vec[i].GetResultType() == search::Result::RESULT_SUGGESTION) - suggestsCount++; + if (m_vec[i].IsSuggest()) + ++res; else + { + // Suggests always go first, so we can exit here. break; + } } - return suggestsCount; + return res; } //////////////////////////////////////////////////////////////////////////////////// @@ -150,26 +156,23 @@ size_t Results::GetSuggestsCount() const void AddressInfo::MakeFrom(Result const & res) { - ASSERT_NOT_EQUAL(res.GetResultType(), Result::RESULT_SUGGESTION, ()); + ASSERT_NOT_EQUAL(res.GetResultType(), Result::RESULT_SUGGEST_PURE, ()); - // push the feature type (may be empty for coordinates result) - string const type = res.GetFeatureType(); + string const & type = res.GetFeatureType(); if (!type.empty()) m_types.push_back(type); // assign name if it's not equal with type - string name = res.GetString(); + string const & name = res.GetString(); if (name != type) - m_name.swap(name); + m_name = name; } -void AddressInfo::SetPinName(string const & name) +bool AddressInfo::IsEmptyName() const { - m_name = name; + return m_name.empty() && m_house.empty(); } -bool AddressInfo::IsEmptyName() const { return m_name.empty() && m_house.empty(); } - string AddressInfo::GetPinName() const { if (IsEmptyName() && !m_types.empty()) diff --git a/search/result.hpp b/search/result.hpp index 36eb443b5d..e5cf84a202 100644 --- a/search/result.hpp +++ b/search/result.hpp @@ -20,36 +20,37 @@ public: { RESULT_FEATURE, RESULT_LATLON, - RESULT_SUGGESTION, - RESULT_POI_SUGGEST + RESULT_SUGGEST_PURE, + RESULT_SUGGEST_FROM_FEATURE }; /// For RESULT_FEATURE. - Result(FeatureID const & id, m2::PointD const & fCenter, + Result(FeatureID const & id, m2::PointD const & pt, string const & str, string const & region, - string const & flag, string const & type, - uint32_t featureType, double distance); + string const & type, uint32_t featureType); /// Used for point-like results on the map. Result(m2::PointD const & pt, string const & str, string const & type); - /// For RESULT_LATLON. - Result(m2::PointD const & fCenter, - string const & str, string const & region, - string const & flag, double distance); + /// @param[in] type Pass 0 - for RESULT_LATLON or building type for building address. + Result(m2::PointD const & pt, string const & str, + string const & region, string const & type); - /// For RESULT_SUGGESTION. + /// For RESULT_SUGGESTION_PURE. Result(string const & str, string const & suggest); + /// For RESULT_SUGGESTION_FROM_FEATURE. + Result(Result const & res, string const & suggest); + /// 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(); } //@} bool IsSuggest() const; + bool HasPoint() const; /// Type of the result. ResultType GetResultType() const; @@ -59,15 +60,11 @@ public: FeatureID GetFeatureID() const; /// Center point of a feature. - /// @precondition GetResultType() != RESULT_SUGGESTION + /// @precondition HasPoint() == true m2::PointD GetFeatureCenter() 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. - /// @precondition GetResultType() == RESULT_SUGGESTION + /// @precondition IsSuggest() == true char const * GetSuggestionString() const; bool operator== (Result const & r) const; @@ -81,9 +78,8 @@ public: private: FeatureID m_id; m2::PointD m_center; - string m_str, m_region, m_flag, m_type; + string m_str, m_region, m_type; uint32_t m_featureType; - double m_distance; string m_suggestionStr; buffer_vector, 4> m_hightlightRanges; }; @@ -154,7 +150,6 @@ struct AddressInfo void MakeFrom(search::Result const & res); - void SetPinName(string const & name); string GetPinName() const; // Caroline string GetPinType() const; // shop diff --git a/search/search_query.cpp b/search/search_query.cpp index c0af4213ef..048795bebd 100644 --- a/search/search_query.cpp +++ b/search/search_query.cpp @@ -389,7 +389,7 @@ void Query::SearchCoordinates(string const & query, Results & res) const if (MatchLatLonDegree(query, lat, lon)) { //double const precision = 5.0 * max(0.0001, min(latPrec, lonPrec)); // Min 55 meters - res.AddResult(MakeResult(impl::PreResult2(GetViewport(), m_position, lat, lon))); + res.AddResult(MakeResult(impl::PreResult2(lat, lon))); } } @@ -711,19 +711,9 @@ void Query::FlushHouses(Results & res, bool allMWMs, vector const & s for (size_t i = 0; i < count; ++i) { House const * h = houses[i].m_house; - storage::CountryInfo ci; - m_pInfoGetter->GetRegionInfo(h->GetPosition(), ci); - - Result r(h->GetPosition(), h->GetNumber() + ", " + houses[i].m_street->GetName(), - ci.m_name, string(), IsValidPosition() ? h->GetPosition().Length(m_position) : -1.0); - - MakeResultHighlight(r); -#ifdef FIND_LOCALITY_TEST - string city; - m_locality.GetLocalityCreateCache(r.GetFeatureCenter(), city); - r.AppendCity(city); -#endif - (res.*addFn)(r); + (res.*addFn)(MakeResult(impl::PreResult2(h->GetPosition(), + h->GetNumber() + ", " + houses[i].m_street->GetName(), + m_houseDetector.GetBuildingType()))); } } } @@ -889,14 +879,12 @@ template void Query::ProcessSuggestions(vector & vec, Results & res GetSuggestion(r.GetName(), suggest); if (!suggest.empty() && added < MAX_SUGGESTS_COUNT) { - Result rr(r.GetName(), suggest); - MakeResultHighlight(rr); + Result rr(MakeResult(r), suggest); if (res.AddResultCheckExisting(rr)) - { ++added; - i = vec.erase(i); - continue; - } + + i = vec.erase(i); + continue; } } ++i;