From c3fb65a6537bd251ca67a363f1b437b6afd84913 Mon Sep 17 00:00:00 2001 From: Viktor Govako Date: Sun, 13 Feb 2022 19:21:22 +0300 Subject: [PATCH] [indexer] Several FeatureType enhancements. Signed-off-by: Viktor Govako --- generator/feature_builder.cpp | 22 ++++++------ generator/feature_builder.hpp | 23 ++++++++----- indexer/editable_map_object.cpp | 11 +++--- indexer/feature.cpp | 3 +- indexer/feature_data.cpp | 61 +++++++++------------------------ indexer/feature_data.hpp | 35 +++++++++---------- indexer/feature_meta.cpp | 21 +++++------- indexer/feature_meta.hpp | 15 +++----- map/framework.cpp | 25 +++++++++----- 9 files changed, 94 insertions(+), 122 deletions(-) diff --git a/generator/feature_builder.cpp b/generator/feature_builder.cpp index 6579e47d4f..71e0f0b076 100644 --- a/generator/feature_builder.cpp +++ b/generator/feature_builder.cpp @@ -286,14 +286,8 @@ void FeatureBuilder::RemoveUselessNames() { if (!m_params.name.IsEmpty() && !IsCoastCell()) { - // Use lambda syntax to correctly compile according to standard: - // http://en.cppreference.com/w/cpp/algorithm/remove - // The signature of the predicate function should be equivalent to the following: - // bool pred(const Type &a); - // Without it on clang-libc++ on Linux we get: - // candidate template ignored: substitution failure - // [with _Tp = bool (unsigned int) const]: reference to function type 'bool (unsigned int) const' cannot have 'const' - // qualifier + // Remove names for boundary-administrative-* features. + // AFAIR, they were very messy in search because they contain places' names. auto const typeRemover = [](uint32_t type) { static TypeSetChecker const checkBoundary({ "boundary", "administrative" }); @@ -303,6 +297,7 @@ void FeatureBuilder::RemoveUselessNames() auto types = GetTypesHolder(); if (types.RemoveIf(typeRemover)) { + // Remove only if there are no other text-style types in feature (e.g. highway). pair const range = GetDrawableScaleRangeForRules(types, RULE_ANY_TEXT); if (range.first == -1) m_params.name.Clear(); @@ -623,20 +618,25 @@ bool FeatureBuilder::IsDrawableInRange(int lowScale, int highScale) const bool FeatureBuilder::PreSerializeAndRemoveUselessNamesForMwm(SupportingData const & data) { - // make flags actual before header serialization + // We don't need empty features without geometry. GeomType const geomType = m_params.GetGeomType(); if (geomType == GeomType::Line) { if (data.m_ptsMask == 0 && data.m_innerPts.empty()) + { + LOG(LWARNING, ("Skip feature with empty geometry", GetMostGenericOsmId())); return false; + } } else if (geomType == GeomType::Area) { if (data.m_trgMask == 0 && data.m_innerTrg.empty()) + { + LOG(LWARNING, ("Skip feature with empty geometry", GetMostGenericOsmId())); return false; + } } - // we don't need empty features without geometry return PreSerializeAndRemoveUselessNamesForIntermediate(); } @@ -784,7 +784,7 @@ string DebugPrint(FeatureBuilder const & fb) out << " " << DebugPrint(fb.GetLimitRect()) << " " << DebugPrint(fb.GetParams()) - << " " << ::DebugPrint(fb.GetOsmIds()); + << " " << ::DebugPrint(fb.m_osmIds); return out.str(); } diff --git a/generator/feature_builder.hpp b/generator/feature_builder.hpp index 58d31d3a94..cc8e758b16 100644 --- a/generator/feature_builder.hpp +++ b/generator/feature_builder.hpp @@ -54,7 +54,8 @@ public: bool IsValid() const; - // To work with geometry. + /// @name To work with geometry. + ///@{ void AddPoint(m2::PointD const & p); void SetHoles(Geometry const & holes); void AddPolygon(std::vector & poly); @@ -68,7 +69,7 @@ public: m2::PointD GetKeyPoint() const; size_t GetPointsCount() const; size_t GetPolygonsCount() const { return m_polygons.size(); } - size_t GetTypesCount() const { return m_params.m_types.size(); } + ///@} template void ForEachPoint(ToDo && toDo) const @@ -117,7 +118,8 @@ public: bool IsLine() const { return GetGeomType() == GeomType::Line; } bool IsArea() const { return GetGeomType() == GeomType::Area; } - // To work with types. + /// @name To work with types. + ///@{ void SetType(uint32_t type) { m_params.SetType(type); } void AddType(uint32_t type) { m_params.AddType(type); } bool PopExactType(uint32_t type) { return m_params.PopExactType(type); } @@ -133,6 +135,8 @@ public: bool HasType(uint32_t t, uint8_t level) const { return m_params.IsTypeExist(t, level); } uint32_t FindType(uint32_t comp, uint8_t level) const { return m_params.FindType(comp, level); } FeatureParams::Types const & GetTypes() const { return m_params.m_types; } + size_t GetTypesCount() const { return m_params.m_types.size(); } + ///@} // To work with additional information. void SetRank(uint8_t rank); @@ -160,7 +164,8 @@ public: int GetMinFeatureDrawScale() const; bool IsDrawableInRange(int lowScale, int highScale) const; - // Serialization. + /// @name Serialization. + ///@{ bool PreSerialize(); bool PreSerializeAndRemoveUselessNamesForIntermediate(); void SerializeForIntermediate(Buffer & data) const; @@ -176,11 +181,13 @@ public: void SerializeLocalityObject(serial::GeometryCodingParams const & params, SupportingData & data) const; void SerializeForMwm(SupportingData & data, serial::GeometryCodingParams const & params) const; + ///@} // Get common parameters of feature. TypesHolder GetTypesHolder() const; - // To work with osm ids. + /// @name To work with osm ids. + ///@{ void AddOsmId(base::GeoObjectId id); void SetOsmId(base::GeoObjectId id); base::GeoObjectId GetFirstOsmId() const; @@ -190,12 +197,14 @@ public: base::GeoObjectId GetMostGenericOsmId() const; bool HasOsmId(base::GeoObjectId const & id) const; bool HasOsmIds() const { return !m_osmIds.empty(); } - std::vector const & GetOsmIds() const { return m_osmIds; } + ///@} // To work with coasts. void SetCoastCell(int64_t iCell) { m_coastCell = iCell; } bool IsCoastCell() const { return (m_coastCell != -1); } + friend std::string DebugPrint(FeatureBuilder const & fb); + protected: // Can be one of the following: // - point in point-feature @@ -211,8 +220,6 @@ protected: int64_t m_coastCell; }; -std::string DebugPrint(FeatureBuilder const & fb); - // SerializationPolicy serialization and deserialization. namespace serialization_policy { diff --git a/indexer/editable_map_object.cpp b/indexer/editable_map_object.cpp index be80eb9875..7bc86fc3fe 100644 --- a/indexer/editable_map_object.cpp +++ b/indexer/editable_map_object.cpp @@ -577,18 +577,15 @@ LocalizedStreet const & EditableMapObject::GetStreet() const { return m_street; void EditableMapObject::SetCuisines(vector const & cuisines) { FeatureParams params; - params.m_types.insert(params.m_types.begin(), m_types.begin(), m_types.end()); + params.m_types.assign(m_types.begin(), m_types.end()); + Classificator const & cl = classif(); for (auto const & cuisine : cuisines) - params.m_types.push_back(classif().GetTypeByPath({"cuisine", cuisine})); + params.m_types.push_back(cl.GetTypeByPath({"cuisine", cuisine})); // Move useless types to the end and resize to fit TypesHolder. params.FinishAddingTypes(); - feature::TypesHolder types; - for (auto const t : params.m_types) - types.Add(t); - - m_types = types; + m_types.Assign(params.m_types.begin(), params.m_types.end()); } void EditableMapObject::SetOpeningHours(string const & openingHours) diff --git a/indexer/feature.cpp b/indexer/feature.cpp index 70a6c050e1..32dca8fc80 100644 --- a/indexer/feature.cpp +++ b/indexer/feature.cpp @@ -585,7 +585,8 @@ string FeatureType::DebugString(int scale) Classificator const & c = classif(); string res = "Types"; - for (size_t i = 0; i < GetTypesCount(); ++i) + uint32_t const count = GetTypesCount(); + for (size_t i = 0; i < count; ++i) res += (" : " + c.GetReadableObjectName(m_types[i])); res += "\n"; diff --git a/indexer/feature_data.cpp b/indexer/feature_data.cpp index 56040c86dd..d1ac8f7598 100644 --- a/indexer/feature_data.cpp +++ b/indexer/feature_data.cpp @@ -26,7 +26,7 @@ using namespace std::placeholders; namespace feature { -string DebugPrint(TypesHolder const & holder) +template string TypesToString(ContT const & holder) { Classificator const & c = classif(); string s; @@ -37,6 +37,11 @@ string DebugPrint(TypesHolder const & holder) return s; } +std::string DebugPrint(TypesHolder const & holder) +{ + return TypesToString(holder); +} + TypesHolder::TypesHolder(FeatureType & f) : m_size(0), m_geomType(f.GetGeomType()) { f.ForEachType([this](uint32_t type) @@ -45,18 +50,6 @@ TypesHolder::TypesHolder(FeatureType & f) : m_size(0), m_geomType(f.GetGeomType( }); } -// static -TypesHolder TypesHolder::FromTypesIndexes(std::vector const & indexes) -{ - TypesHolder result; - for (auto index : indexes) - { - result.Add(classif().GetTypeForIndex(index)); - } - - return result; -} - void TypesHolder::Remove(uint32_t type) { UNUSED_VALUE(RemoveIf(base::EqualFunctor(type))); @@ -67,13 +60,16 @@ bool TypesHolder::Equals(TypesHolder const & other) const if (m_size != other.m_size) return false; - vector my(this->begin(), this->end()); - vector his(other.begin(), other.end()); + // Dynamic vector + sort for kMaxTypesCount array is a huge overhead. - sort(::begin(my), ::end(my)); - sort(::begin(his), ::end(his)); - - return my == his; + auto const b = begin(); + auto const e = end(); + for (auto t : other) + { + if (std::find(b, e, t) == e) + return false; + } + return true; } } // namespace feature @@ -402,24 +398,6 @@ void FeatureParams::SetRwSubwayType(char const * cityName) } } -void FeatureParams::AddTypes(FeatureParams const & rhs, uint32_t skipType2) -{ - if (skipType2 == 0) - { - m_types.insert(m_types.end(), rhs.m_types.begin(), rhs.m_types.end()); - } - else - { - for (size_t i = 0; i < rhs.m_types.size(); ++i) - { - uint32_t t = rhs.m_types[i]; - ftype::TruncValue(t, 2); - if (t != skipType2) - m_types.push_back(rhs.m_types[i]); - } - } -} - bool FeatureParams::FinishAddingTypes() { base::SortUnique(m_types); @@ -524,12 +502,7 @@ void FeatureBuilderParams::AddPostcode(string const & s) string DebugPrint(FeatureParams const & p) { - Classificator const & c = classif(); - - string res = "Types: "; - for (size_t i = 0; i < p.m_types.size(); ++i) - res = res + c.GetReadableObjectName(p.m_types[i]) + "; "; - + string res = "Types: " + TypesToString(p.m_types) + "; "; return (res + p.DebugString()); } @@ -539,6 +512,6 @@ string DebugPrint(FeatureBuilderParams const & p) oss << "ReversedGeometry: " << (p.GetReversedGeometry() ? "true" : "false") << "; "; oss << DebugPrint(p.GetMetadata()) << "; "; oss << DebugPrint(p.GetAddressData()) << "; "; - oss << DebugPrint(FeatureParams(p)); + oss << DebugPrint(static_cast(p)); return oss.str(); } diff --git a/indexer/feature_data.hpp b/indexer/feature_data.hpp index 79c750f372..9b526856de 100644 --- a/indexer/feature_data.hpp +++ b/indexer/feature_data.hpp @@ -62,32 +62,36 @@ namespace feature explicit TypesHolder(GeomType geomType) : m_geomType(geomType) {} explicit TypesHolder(FeatureType & f); - static TypesHolder FromTypesIndexes(std::vector const & indexes); - void Assign(uint32_t type) { m_types[0] = type; m_size = 1; } - /// Accumulation function. + template void Assign(IterT beg, IterT end) + { + m_size = std::distance(beg, end); + CHECK_LESS_OR_EQUAL(m_size, kMaxTypesCount, ()); + std::copy(beg, end, m_types.begin()); + } + void Add(uint32_t type) { - ASSERT_LESS(m_size, kMaxTypesCount, ()); - if (m_size < kMaxTypesCount) - m_types[m_size++] = type; + CHECK_LESS(m_size, kMaxTypesCount, ()); + m_types[m_size++] = type; } GeomType GetGeomType() const { return m_geomType; } size_t Size() const { return m_size; } bool Empty() const { return (m_size == 0); } - Types::const_iterator cbegin() const { return m_types.cbegin(); } - Types::const_iterator cend() const { return m_types.cbegin() + m_size; } - Types::const_iterator begin() const { return m_types.cbegin(); } - Types::const_iterator end() const { return m_types.cbegin() + m_size; } - Types::iterator begin() { return m_types.begin(); } - Types::iterator end() { return m_types.begin() + m_size; } + + auto cbegin() const { return m_types.cbegin(); } + auto cend() const { return m_types.cbegin() + m_size; } + auto begin() const { return m_types.cbegin(); } + auto end() const { return m_types.cbegin() + m_size; } + auto begin() { return m_types.begin(); } + auto end() { return m_types.begin() + m_size; } /// Assume that m_types is already sorted by SortBySpec function. uint32_t GetBestType() const @@ -114,8 +118,6 @@ namespace feature /// Sort types by it's specification (more detailed type goes first). void SortBySpec(); - /// Returns true if this->m_types and other.m_types contain same values - /// in any order. Works in O(n log n). bool Equals(TypesHolder const & other) const; std::vector ToObjectNames() const; @@ -133,7 +135,6 @@ namespace feature FeatureParamsBase const & params); } // namespace feature -/// Feature description struct. struct FeatureParamsBase { StringUtf8Multilang name; @@ -236,10 +237,6 @@ public: /// the special subway type for the correspondent city. void SetRwSubwayType(char const * cityName); - /// @param skipType2 Do not accumulate this type if skipType2 != 0. - /// '2' means 2-level type in classificator tree (also skip child types). - void AddTypes(FeatureParams const & rhs, uint32_t skipType2); - bool FinishAddingTypes(); void SetType(uint32_t t); diff --git a/indexer/feature_meta.cpp b/indexer/feature_meta.cpp index 5d70958a04..5b98a31ed4 100644 --- a/indexer/feature_meta.cpp +++ b/indexer/feature_meta.cpp @@ -2,8 +2,6 @@ #include "std/target_os.hpp" -#include - using namespace std; namespace feature @@ -207,9 +205,8 @@ string ToString(Metadata::EType type) string DebugPrint(Metadata const & metadata) { - ostringstream oss; bool first = true; - oss << "Metadata ["; + std::string res = "Metadata ["; for (uint8_t i = 0; i < static_cast(Metadata::FMD_COUNT); ++i) { auto const t = static_cast(i); @@ -219,21 +216,19 @@ string DebugPrint(Metadata const & metadata) if (first) first = false; else - oss << "; "; + res += "; "; - oss << DebugPrint(t) << "=" << s; + res = res + DebugPrint(t) + "=" + s; } } - oss << "]"; - return oss.str(); + res += "]"; + return res; } string DebugPrint(feature::AddressData const & addressData) { - ostringstream oss; - oss << "AddressData ["; - oss << "Street = \"" << addressData.Get(AddressData::Type::Street) << "\"; "; - oss << "Postcode = \"" << addressData.Get(AddressData::Type::Postcode) << "\"]"; - return oss.str(); + return std::string("AddressData [") + + "Street = \"" + addressData.Get(AddressData::Type::Street) + "\"; " + + "Postcode = \"" + addressData.Get(AddressData::Type::Postcode) + "\"]"; } } // namespace feature diff --git a/indexer/feature_meta.hpp b/indexer/feature_meta.hpp index ada955f0f2..30c092dd2b 100644 --- a/indexer/feature_meta.hpp +++ b/indexer/feature_meta.hpp @@ -83,18 +83,13 @@ protected: // TODO: Change uint8_t to appropriate type when FMD_COUNT reaches 256. void Set(uint8_t type, std::string const & value) { - auto found = m_metadata.find(type); - if (found == m_metadata.end()) - { - if (!value.empty()) - m_metadata[type] = value; - } + if (value.empty()) + m_metadata.erase(type); else { - if (value.empty()) - m_metadata.erase(found); - else - found->second = value; + auto res = m_metadata.try_emplace(type, value); + if (!res.second) + res.first->second = value; } } diff --git a/map/framework.cpp b/map/framework.cpp index 15cdf0cbd4..4d901ee258 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -578,9 +578,22 @@ kml::MarkGroupId Framework::AddCategory(string const & categoryName) void Framework::FillPointInfoForBookmark(Bookmark const & bmk, place_page::Info & info) const { - auto types = feature::TypesHolder::FromTypesIndexes(bmk.GetData().m_featureTypes); - FillPointInfo(info, bmk.GetPivot(), {} /* customTitle */, [&types](FeatureType & ft) { - return !types.Empty() && feature::TypesHolder(ft).Equals(types); + // Convert indices to sorted classifier types. + Classificator const & cl = classif(); + buffer_vector types; + for (uint32_t i : bmk.GetData().m_featureTypes) + types.push_back(cl.GetTypeForIndex(i)); + std::sort(types.begin(), types.end()); + + FillPointInfo(info, bmk.GetPivot(), {} /* customTitle */, [&types](FeatureType & ft) + { + if (types.empty() || ft.GetTypesCount() != types.size()) + return false; + + // Strict equal types. + feature::TypesHolder fTypes(ft); + std::sort(fTypes.begin(), fTypes.end()); + return std::equal(types.begin(), types.end(), fTypes.begin(), fTypes.end()); }); } @@ -2575,12 +2588,6 @@ void Framework::BlockTapEvents(bool block) m_drapeEngine->BlockTapEvents(block); } -namespace feature -{ -string GetPrintableTypes(FeatureType & ft) { return DebugPrint(feature::TypesHolder(ft)); } -uint32_t GetBestType(FeatureType & ft) { return feature::TypesHolder(ft).GetBestType(); } -} - bool Framework::ParseDrapeDebugCommand(string const & query) { MapStyle desiredStyle = MapStyleCount;