diff --git a/indexer/feature.hpp b/indexer/feature.hpp index a28c7ce15a..c2df0e10eb 100644 --- a/indexer/feature.hpp +++ b/indexer/feature.hpp @@ -101,25 +101,6 @@ public: return m_Center; } - class GetTypesFn - { - public: - uint32_t m_types[m_maxTypesCount]; - size_t m_size; - - GetTypesFn() : m_size(0) {} - - inline void operator() (uint32_t t) { m_types[m_size++] = t; } - - inline bool Has(uint32_t t) const - { - for (size_t i = 0; i < m_size; ++i) - if (m_types[i] == t) - return true; - return false; - } - }; - template void ForEachTypeRef(FunctorT & f) const { diff --git a/indexer/feature_data.cpp b/indexer/feature_data.cpp index ce99bed34a..7759370383 100644 --- a/indexer/feature_data.cpp +++ b/indexer/feature_data.cpp @@ -1,11 +1,18 @@ #include "feature_data.hpp" #include "classificator.hpp" +#include "feature.hpp" #include "../std/algorithm.hpp" using namespace feature; +TypesHolder::TypesHolder(FeatureBase const & f) +{ + m_geoType = f.GetFeatureType(); + f.ForEachTypeRef(*this); +} + void FeatureParamsBase::MakeZero() { layer = 0; diff --git a/indexer/feature_data.hpp b/indexer/feature_data.hpp index 1b57d9b117..2c6032611a 100644 --- a/indexer/feature_data.hpp +++ b/indexer/feature_data.hpp @@ -8,6 +8,8 @@ #include "../std/vector.hpp" +class FeatureBase; + namespace feature { enum EGeomType @@ -46,6 +48,38 @@ namespace feature LAYER_HIGH = 12 }; + + class TypesHolder + { + uint32_t m_types[max_types_count]; + size_t m_size; + + EGeomType m_geoType; + + public: + TypesHolder() : m_size(0), m_geoType(GEOM_UNDEFINED) {} + TypesHolder(FeatureBase const & f); + + /// Accumulation function. + inline void operator() (uint32_t t) { m_types[m_size++] = t; } + + /// @name Selectors. + //@{ + inline EGeomType GetGeoType() const { return m_geoType; } + + inline size_t Size() const { return m_size; } + inline uint32_t operator[] (size_t i) const { return m_types[i]; } + + inline bool Has(uint32_t t) const + { + for (size_t i = 0; i < m_size; ++i) + if (t == m_types[i]) + return true; + + return false; + } + //@} + }; } /// Feature description struct. diff --git a/indexer/feature_utils.cpp b/indexer/feature_utils.cpp index 04f5719b73..6c19a577af 100644 --- a/indexer/feature_utils.cpp +++ b/indexer/feature_utils.cpp @@ -77,13 +77,12 @@ public: return limitR; } - FeatureBase::GetTypesFn types; - f.ForEachTypeRef(types); + feature::TypesHolder types(f); int const upperScale = scales::GetUpperScale(); int scale = upperScale; - for (size_t i = 0; i < types.m_size; ++i) - scale = min(scale, GetScaleForType(types.m_types[i], f)); + for (size_t i = 0; i < types.Size(); ++i) + scale = min(scale, GetScaleForType(types[i], f)); CorrectScaleForVisibility(f, scale); @@ -95,23 +94,23 @@ public: { uint32_t population = feature.GetPopulation(); - FeatureBase::GetTypesFn types; - feature.ForEachTypeRef(types); - for (size_t i = 0; i < types.m_size; ++i) + feature::TypesHolder types(feature); + + for (size_t i = 0; i < types.Size(); ++i) { - if (IsEqual(types.m_types[i], m_TypeSmallVillage)) + if (IsEqual(types[i], m_TypeSmallVillage)) population = max(population, static_cast(100)); - else if (IsEqual(types.m_types[i], m_TypeVillage)) + else if (IsEqual(types[i], m_TypeVillage)) population = max(population, static_cast(1000)); - else if (types.m_types[i] == m_TypeTown || IsEqual(types.m_types[i], m_TypeCounty)) + else if (types[i] == m_TypeTown || IsEqual(types[i], m_TypeCounty)) population = max(population, static_cast(10000)); - else if (types.m_types[i] == m_TypeCity || types.m_types[i] == m_TypeState) + else if (types[i] == m_TypeCity || types[i] == m_TypeState) population = max(population, static_cast(100000)); - else if (types.m_types[i] == m_TypeCityCapital) + else if (types[i] == m_TypeCityCapital) population = max(population, static_cast(1000000)); - else if (types.m_types[i] == m_TypeCountry) + else if (types[i] == m_TypeCountry) population = max(population, static_cast(2000000)); - else if (types.m_types[i] == m_TypeContinent) + else if (types[i] == m_TypeContinent) population = max(population, static_cast(20000000)); } diff --git a/indexer/feature_utils.hpp b/indexer/feature_utils.hpp index ac2bfa14d6..0321f62711 100644 --- a/indexer/feature_utils.hpp +++ b/indexer/feature_utils.hpp @@ -1,6 +1,7 @@ #pragma once #include "../geometry/rect2d.hpp" + #include "../base/base.hpp" class FeatureType; diff --git a/indexer/feature_visibility.cpp b/indexer/feature_visibility.cpp index d5ead6d4bd..1b840595b1 100644 --- a/indexer/feature_visibility.cpp +++ b/indexer/feature_visibility.cpp @@ -130,19 +130,16 @@ namespace pair GetDrawRule(FeatureBase const & f, int level, vector & keys, string & names) { - feature::EGeomType const geoType = f.GetFeatureType(); - - FeatureBase::GetTypesFn types; - f.ForEachTypeRef(types); + feature::TypesHolder types(f); ASSERT ( keys.empty(), () ); Classificator const & c = classif(); - DrawRuleGetter doRules(level, geoType, keys, names); - for (size_t i = 0; i < types.m_size; ++i) - (void)c.ProcessObjects(types.m_types[i], doRules); + DrawRuleGetter doRules(level, types.GetGeoType(), keys, names); + for (size_t i = 0; i < types.Size(); ++i) + (void)c.ProcessObjects(types[i], doRules); - return make_pair(geoType, types.Has(c.GetCoastType())); + return make_pair(types.GetGeoType(), types.Has(c.GetCoastType())); } namespace @@ -243,16 +240,15 @@ bool IsDrawableForIndex(FeatureBase const & f, int level) { Classificator const & c = classif(); - FeatureBase::GetTypesFn types; - f.ForEachTypeRef(types); + feature::TypesHolder types(f); - if (f.GetFeatureType() == feature::GEOM_AREA && !types.Has(c.GetCoastType())) + if (types.GetGeoType() == feature::GEOM_AREA && !types.Has(c.GetCoastType())) if (!scales::IsGoodForLevel(level, f.GetLimitRect())) return false; IsDrawableChecker doCheck(level); - for (size_t i = 0; i < types.m_size; ++i) - if (c.ProcessObjects(types.m_types[i], doCheck)) + for (size_t i = 0; i < types.Size(); ++i) + if (c.ProcessObjects(types[i], doCheck)) return true; return false; @@ -271,13 +267,13 @@ int MinDrawableScaleForFeature(FeatureBase const & f) namespace { - bool IsDrawable(FeatureBase::GetTypesFn const & types, int level, EGeomType geomType) + bool IsDrawable(feature::TypesHolder const & types, int level) { Classificator const & c = classif(); - TextRulesChecker doCheck(level, geomType); - for (size_t i = 0; i < types.m_size; ++i) - if (c.ProcessObjects(types.m_types[i], doCheck)) + TextRulesChecker doCheck(level, types.GetGeoType()); + for (size_t i = 0; i < types.Size(); ++i) + if (c.ProcessObjects(types[i], doCheck)) return true; return false; @@ -286,16 +282,13 @@ namespace pair DrawableScaleRangeForText(FeatureBase const & f) { - FeatureBase::GetTypesFn types; - f.ForEachTypeRef(types); - - feature::EGeomType const geomType = f.GetFeatureType(); + feature::TypesHolder types(f); int const upBound = scales::GetUpperScale(); int lowL = -1; for (int level = 0; level <= upBound; ++level) { - if (IsDrawable(types, level, geomType)) + if (IsDrawable(types, level)) { lowL = level; break; @@ -308,7 +301,7 @@ pair DrawableScaleRangeForText(FeatureBase const & f) int highL = lowL; for (int level = upBound; level > lowL; --level) { - if (IsDrawable(types, level, geomType)) + if (IsDrawable(types, level)) { highL = level; break; diff --git a/indexer/search_index_builder.cpp b/indexer/search_index_builder.cpp index c3800a5ac8..21a37d70ac 100644 --- a/indexer/search_index_builder.cpp +++ b/indexer/search_index_builder.cpp @@ -73,10 +73,9 @@ struct FeatureInserter feature.ForEachNameRef(f); // Add names of categories of the feature. - FeatureType::GetTypesFn getTypesFn; - feature.ForEachTypeRef(getTypesFn); - for (size_t i = 0; i < getTypesFn.m_size; ++i) - f.AddToken(0, search::FeatureTypeToString(getTypesFn.m_types[i])); + feature::TypesHolder types(feature); + for (size_t i = 0; i < types.Size(); ++i) + f.AddToken(0, search::FeatureTypeToString(types[i])); } }; diff --git a/map/map_tests/map_foreach_test.cpp b/map/map_tests/map_foreach_test.cpp index 2434fb2b66..95bec762a0 100644 --- a/map/map_tests/map_foreach_test.cpp +++ b/map/map_tests/map_foreach_test.cpp @@ -264,10 +264,9 @@ namespace cout << "Feature classificator types:\n"; - FeatureType::GetTypesFn getTypes; - f.ForEachTypeRef(getTypes); - for (size_t i = 0; i < getTypes.m_size; ++i) - cout << classif().GetFullObjectName(getTypes.m_types[i]) << endl; + feature::TypesHolder types(f); + for (size_t i = 0; i < types.Size(); ++i) + cout << classif().GetFullObjectName(types[i]) << endl; } } }; diff --git a/search/intermediate_result.cpp b/search/intermediate_result.cpp index 84de0c0f30..9dead7a056 100644 --- a/search/intermediate_result.cpp +++ b/search/intermediate_result.cpp @@ -23,15 +23,12 @@ IntermediateResult::IntermediateResult(m2::RectD const & viewportRect, m2::Point FeatureType const & f, string const & displayName, string const & fileName) - : m_str(displayName), + : m_types(f), + m_str(displayName), m_rect(feature::GetFeatureViewport(f)), m_resultType(RESULT_FEATURE) { - // get feature type - FeatureType::GetTypesFn types; - f.ForEachTypeRef(types); - ASSERT_GREATER(types.m_size, 0, ()); - m_type = types.m_types[0]; + ASSERT_GREATER(m_types.Size(), 0, ()); // get region info if (!fileName.empty()) @@ -54,7 +51,7 @@ IntermediateResult::IntermediateResult(m2::RectD const & viewportRect, m2::Point : m_str("(" + strings::to_string(lat) + ", " + strings::to_string(lon) + ")"), m_rect(MercatorBounds::LonToX(lon - precision), MercatorBounds::LatToY(lat - precision), MercatorBounds::LonToX(lon + precision), MercatorBounds::LatToY(lat + precision)), - m_type(0), m_resultType(RESULT_LATLON), m_searchRank(0) + m_resultType(RESULT_LATLON), m_searchRank(0) { // get common params m_distance = ResultDistance(pos, m_rect.Center()); @@ -133,7 +130,7 @@ Result IntermediateResult::GenerateFinalResult( + ' ' + strings::to_string(static_cast(m_searchRank)) #endif , - m_type, m_rect, m_distance, m_direction); + GetBestType(), m_rect, m_distance, m_direction); case RESULT_LATLON: return Result(m_str, info.m_name, info.m_flag, GetFeatureType(pCat), @@ -178,7 +175,7 @@ bool IntermediateResult::StrictEqualF::operator()(IntermediateResult const & r) { if (m_r.m_resultType == r.m_resultType && m_r.m_resultType == RESULT_FEATURE) { - if (m_r.m_str == r.m_str && m_r.m_type == r.m_type) + if (m_r.m_str == r.m_str && m_r.GetBestType() == r.GetBestType()) { /// @todo Tune this constant. return fabs(m_r.m_distance - r.m_distance) < 500.0; @@ -233,8 +230,8 @@ bool IntermediateResult::LessLinearTypesF::operator() if (r1.m_str != r2.m_str) return (r1.m_str < r2.m_str); - if (r1.m_type != r2.m_type) - return (r1.m_type < r2.m_type); + if (r1.GetBestType() != r2.GetBestType()) + return (r1.GetBestType() < r2.GetBestType()); // Should stay the best feature, after unique, so add this criteria: @@ -250,7 +247,8 @@ bool IntermediateResult::EqualLinearTypesF::operator() { // filter equal linear features static IsLinearChecker checker; - return (r1.m_type == r2.m_type && checker.IsMy(FirstLevelIndex(r1.m_type))); + return (r1.GetBestType() == r2.GetBestType() && + checker.IsMy(FirstLevelIndex(r1.GetBestType()))); } return false; @@ -260,7 +258,7 @@ string IntermediateResult::DebugPrint() const { string res("IntermediateResult: "); res += "Name: " + m_str; - res += "; Type: " + ::DebugPrint(m_type); + res += "; Type: " + ::DebugPrint(GetBestType()); res += "; Rank: " + ::DebugPrint(m_searchRank); res += "; Viewport distance: " + ::DebugPrint(m_viewportDistance); res += "; Distance: " + ::DebugPrint(m_distance); @@ -269,16 +267,18 @@ string IntermediateResult::DebugPrint() const string IntermediateResult::GetFeatureType(CategoriesT const * pCat) const { + uint32_t const type = GetBestType(); + if (pCat) { for (CategoriesT::const_iterator i = pCat->begin(); i != pCat->end(); ++i) { - if (i->second == m_type) + if (i->second == type) return strings::ToUtf8(i->first); } } - string s = classif().GetFullObjectName(m_type); + string s = classif().GetFullObjectName(type); // remove ending dummy symbol ASSERT ( !s.empty(), () ); diff --git a/search/intermediate_result.hpp b/search/intermediate_result.hpp index a51d1b87b3..9159ea65a4 100644 --- a/search/intermediate_result.hpp +++ b/search/intermediate_result.hpp @@ -1,6 +1,8 @@ #pragma once #include "result.hpp" +#include "../indexer/feature_data.hpp" + #include "../base/string_utils.hpp" #include "../std/shared_ptr.hpp" @@ -92,6 +94,13 @@ private: string GetFeatureType(CategoriesT const * pCat) const; + feature::TypesHolder m_types; + inline uint32_t GetBestType() const + { + /// @todo Select best type for search result! + return m_types[0]; + } + string m_str, m_completionString; class RegionInfo @@ -114,7 +123,6 @@ private: } m_region; m2::RectD m_rect; - uint32_t m_type; double m_distance; double m_direction;