From f640dd75a462f0668fb8f07ea80a80214db6db35 Mon Sep 17 00:00:00 2001 From: vng Date: Tue, 7 Jul 2015 14:41:42 +0300 Subject: [PATCH] [generator] Better classificatory types filtering using 2-arity level type comparison for finding duplicates. --- generator/generator_tests/osm_type_test.cpp | 1 + indexer/feature_data.cpp | 38 +++++++++++++++++++-- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/generator/generator_tests/osm_type_test.cpp b/generator/generator_tests/osm_type_test.cpp index c41586a603..2e84e4480f 100644 --- a/generator/generator_tests/osm_type_test.cpp +++ b/generator/generator_tests/osm_type_test.cpp @@ -340,6 +340,7 @@ UNIT_TEST(OsmType_Capital) { char const * arr[][2] = { + { "place", "city" }, { "admin_level", "6" }, { "boundary", "administrative" }, { "capital", "2" }, diff --git a/indexer/feature_data.cpp b/indexer/feature_data.cpp index c5b3204f8c..f7e642eaa6 100644 --- a/indexer/feature_data.cpp +++ b/indexer/feature_data.cpp @@ -299,8 +299,42 @@ void FeatureParams::AddTypes(FeatureParams const & rhs, uint32_t skipType2) bool FeatureParams::FinishAddingTypes() { - sort(m_Types.begin(), m_Types.end()); - m_Types.erase(unique(m_Types.begin(), m_Types.end()), m_Types.end()); + static uint32_t const boundary = classif().GetTypeByPath({ "boundary", "administrative" }); + + vector newTypes; + + for (size_t i = 0; i < m_Types.size(); ++i) + { + uint32_t candidate = m_Types[i]; + + // Assume that classificator types are equal if they are equal for 2-arity dimension + // (e.g. "place-city-capital" is equal to "place-city" and we leave the longest one "place-city-capital"). + // The only exception is "boundary-administrative" type. + + uint32_t type = m_Types[i]; + ftype::TruncValue(type, 2); + if (type != boundary) + { + // Find all equal types (2-arity). + auto j = RemoveIfKeepValid(m_Types.begin() + i + 1, m_Types.end(), [type] (uint32_t t) + { + ftype::TruncValue(t, 2); + return (type == t); + }); + + // Choose the best type from equals by arity level. + for (auto k = j; k != m_Types.end(); ++k) + if (ftype::GetLevel(*k) > ftype::GetLevel(candidate)) + candidate = *k; + + // Delete equal types. + m_Types.erase(j, m_Types.end()); + } + + newTypes.push_back(candidate); + } + + m_Types.swap(newTypes); if (m_Types.size() > max_types_count) m_Types.resize(max_types_count);