From ee406ece0c354c0650690d8c76a5bb1aa4198099 Mon Sep 17 00:00:00 2001 From: vng Date: Fri, 11 Mar 2011 00:54:50 +0200 Subject: [PATCH] Code for feature uniting is more generic now. Define any types for unite processing in WorldMapGenerator. --- indexer/feature.cpp | 16 ++++ indexer/feature.hpp | 6 +- indexer/feature_merger.cpp | 2 +- indexer/feature_merger.hpp | 7 +- indexer/indexer_tool/feature_bucketer.hpp | 2 +- indexer/indexer_tool/polygonizer.hpp | 2 +- indexer/indexer_tool/world_map_generator.hpp | 93 +++++++++++++------- 7 files changed, 87 insertions(+), 41 deletions(-) diff --git a/indexer/feature.cpp b/indexer/feature.cpp index 106515e78b..64cd18bf74 100644 --- a/indexer/feature.cpp +++ b/indexer/feature.cpp @@ -68,6 +68,22 @@ void FeatureBuilder1::AddName(string const & name) m_Name = name; } +bool FeatureBuilder1::IsTypeExist(uint32_t t) const +{ + return (find(m_Types.begin(), m_Types.end(), t) != m_Types.end()); +} + +bool FeatureBuilder1::AssignType_SetDifference(vector const & diffTypes) +{ + vector src; + src.swap(m_Types); + + sort(src.begin(), src.end()); + set_difference(src.begin(), src.end(), diffTypes.begin(), diffTypes.end(), back_inserter(m_Types)); + + return !m_Types.empty(); +} + void FeatureBuilder1::AddLayer(int32_t layer) { int const bound = 10; diff --git a/indexer/feature.hpp b/indexer/feature.hpp index e2ff75771e..d41aa92133 100644 --- a/indexer/feature.hpp +++ b/indexer/feature.hpp @@ -20,9 +20,6 @@ class FeatureBase; /// Used for serialization\deserialization of features during --generate_features. class FeatureBuilder1 { - // needed for hacky coastlines merging - friend class FeatureBuilder1Merger; - public: FeatureBuilder1(); @@ -57,6 +54,9 @@ public: m_Types.clear(); m_Types.push_back(type); } + + bool IsTypeExist(uint32_t t) const; + bool AssignType_SetDifference(vector const & diffTypes); void AddLayer(int32_t layer); diff --git a/indexer/feature_merger.cpp b/indexer/feature_merger.cpp index 98532936d2..b4ecbf82fc 100644 --- a/indexer/feature_merger.cpp +++ b/indexer/feature_merger.cpp @@ -11,7 +11,7 @@ FeatureBuilder1Merger::FeatureBuilder1Merger(FeatureBuilder1 const & fb) bool FeatureBuilder1Merger::ReachedMaxPointsCount() const { - return m_Geometry.size() > MAX_MERGED_POINTS_COUNT; + return (m_Geometry.size() > MAX_MERGED_POINTS_COUNT); } void FeatureBuilder1Merger::AppendFeature(FeatureBuilder1Merger const & fb) diff --git a/indexer/feature_merger.hpp b/indexer/feature_merger.hpp index 3e851de7a1..32a50ff16a 100644 --- a/indexer/feature_merger.hpp +++ b/indexer/feature_merger.hpp @@ -11,7 +11,12 @@ public: /// but only if they have common point void AppendFeature(FeatureBuilder1Merger const & fb); - vector const & Type() const { return m_Types; } + uint32_t KeyType() const + { + ASSERT_EQUAL ( m_Types.size(), 1, () ); + return m_Types.front(); + } + bool ReachedMaxPointsCount() const; m2::PointD FirstPoint() const { return m_Geometry.front(); } diff --git a/indexer/indexer_tool/feature_bucketer.hpp b/indexer/indexer_tool/feature_bucketer.hpp index b0a5926e6b..8c1d5cce42 100644 --- a/indexer/indexer_tool/feature_bucketer.hpp +++ b/indexer/indexer_tool/feature_bucketer.hpp @@ -50,7 +50,7 @@ public: Init(); } - void operator () (feature_builder_t const & fb) + void operator () (feature_builder_t & fb) { if (m_worldMap(fb)) return; // we do not duplicate features in world and bucket files diff --git a/indexer/indexer_tool/polygonizer.hpp b/indexer/indexer_tool/polygonizer.hpp index 6ad86ecbbf..f8fe3832b3 100644 --- a/indexer/indexer_tool/polygonizer.hpp +++ b/indexer/indexer_tool/polygonizer.hpp @@ -87,7 +87,7 @@ namespace feature } }; - void operator () (FeatureBuilder1 const & fb) + void operator () (FeatureBuilder1 & fb) { if (m_worldMap(fb)) return; // do not duplicate feature in any country if it's stored in world map diff --git a/indexer/indexer_tool/world_map_generator.hpp b/indexer/indexer_tool/world_map_generator.hpp index fd92c29cc0..7775e7874a 100644 --- a/indexer/indexer_tool/world_map_generator.hpp +++ b/indexer/indexer_tool/world_map_generator.hpp @@ -37,7 +37,7 @@ class WorldMapGenerator size_t m_areasCounter; typedef unordered_map FeaturesContainerT; - typedef map, FeaturesContainerT> TypesContainerT; + typedef map TypesContainerT; TypesContainerT m_features; private: @@ -54,8 +54,9 @@ private: base->second.AppendFeature(found->second); features.erase(found); ++m_mergedCounter; + if (base->second.FirstPoint() == base->second.LastPoint()) - { // @TODO create area feature + { (*m_worldBucket)(base->second); features.erase(base); ++m_areasCounter; @@ -66,10 +67,9 @@ private: return false; } - void TryToMerge(FeatureBuilder1 const & fb) + void TryToMerge(FeatureBuilder1Merger & fbm) { - FeatureBuilder1Merger fbm(fb); - FeaturesContainerT & container = m_features[fbm.Type()]; + FeaturesContainerT & container = m_features[fbm.KeyType()]; FeaturesContainerT::iterator found = container.find(fbm.LastPoint()); if (found != container.end()) { @@ -80,28 +80,31 @@ private: if (fbm.FirstPoint() == fbm.LastPoint()) { - // @TODO create area feature (*m_worldBucket)(fbm); ++m_areasCounter; - return; } - pair result = container.insert(make_pair(fbm.FirstPoint(), fbm)); - // if we found feature with the same starting point, emit it directly - if (!result.second) + else { - LOG(LWARNING, ("Found features with common first point, points counts are:", - result.first->second.GetPointsCount(), fb.GetPointsCount())); - (*m_worldBucket)(fbm); + pair result = container.insert(make_pair(fbm.FirstPoint(), fbm)); + // if we found feature with the same starting point, emit it directly + if (!result.second) + { + LOG(LWARNING, ("Found features with common first point, points counts are:", + result.first->second.GetPointsCount(), fbm.GetPointsCount())); + (*m_worldBucket)(fbm); + } } } - struct FeatureTypePrinter - { - void operator()(uint32_t type) const - { - cout << classif().GetFullObjectName(type) << "."; - } - }; + //struct FeatureTypePrinter + //{ + // void operator()(uint32_t type) const + // { + // cout << classif().GetFullObjectName(type) << "."; + // } + //}; + + vector m_MergeTypes; public: WorldMapGenerator(int maxWorldScale, bool mergeCoastlines, @@ -111,6 +114,21 @@ public: { if (maxWorldScale >= 0) m_worldBucket.reset(new FeatureOutT(WORLD_FILE_NAME, featureOutInitData)); + + // fill vector with types that need to be merged + char const * arrMerge[][2] = { {"natural", "coastline"} }; + + for (size_t i = 0; i < ARRAY_SIZE(arrMerge); ++i) + { + vector path(2); + path[0] = arrMerge[i][0]; + path[1] = arrMerge[i][1]; + m_MergeTypes.push_back(classif().GetTypeByPath(path)); + + ASSERT_NOT_EQUAL ( m_MergeTypes.back(), ftype::GetEmptyValue(), () ); + } + + sort(m_MergeTypes.begin(), m_MergeTypes.end()); } ~WorldMapGenerator() @@ -119,6 +137,7 @@ public: { LOG(LINFO, ("Final merging of coastlines started")); } + // try to merge all merged features with each other for (TypesContainerT::iterator it = m_features.begin(); it != m_features.end(); ++it) { @@ -137,29 +156,35 @@ public: } } - bool operator()(FeatureBuilder1 const & fb) + bool operator()(FeatureBuilder1 & fb) { if (m_worldBucket) { FeatureBase fBase = fb.GetFeatureBase(); - int minScale = feature::MinDrawableScaleForFeature(fBase); + int const minScale = feature::MinDrawableScaleForFeature(fBase); CHECK_GREATER(minScale, -1, ("Non-drawable feature found!?")); if (m_maxWorldScale >= minScale) { - FeatureTypePrinter typePrinter; - fBase.ForEachTypeRef(typePrinter); - cout << endl; - if (m_mergeCoastlines) + //FeatureTypePrinter typePrinter; + //fBase.ForEachTypeRef(typePrinter); + //cout << endl; + + if (m_mergeCoastlines && fBase.GetFeatureType() == FeatureBase::FEATURE_TYPE_LINE) { - // we're merging only linear features, - // areas and points are written immediately - if (fBase.GetFeatureType() != FeatureBase::FEATURE_TYPE_LINE) - (*m_worldBucket)(fb); - else - TryToMerge(fb); + for (size_t i = 0; i < m_MergeTypes.size(); ++i) + { + if (fb.IsTypeExist(m_MergeTypes[i])) + { + FeatureBuilder1Merger fbm(fb); + fbm.SetType(m_MergeTypes[i]); + TryToMerge(fbm); + } + } + + if (!fb.AssignType_SetDifference(m_MergeTypes)) + return true; } - else - (*m_worldBucket)(fb); + (*m_worldBucket)(fb); return true; } }