diff --git a/indexer/feature_merger.cpp b/indexer/feature_merger.cpp index 04e62df4df..6dfe0e21d0 100644 --- a/indexer/feature_merger.cpp +++ b/indexer/feature_merger.cpp @@ -1,8 +1,8 @@ #include "feature_merger.hpp" -//#include "../base/logging.hpp" +#include "../base/logging.hpp" -#define MAX_MERGED_POINTS_COUNT 1000 +#define MAX_MERGED_POINTS_COUNT 10000 FeatureBuilder1Merger::FeatureBuilder1Merger(FeatureBuilder1 const & fb) : FeatureBuilder1(fb) @@ -14,50 +14,22 @@ bool FeatureBuilder1Merger::ReachedMaxPointsCount() const return m_Geometry.size() > MAX_MERGED_POINTS_COUNT; } -bool FeatureBuilder1Merger::MergeWith(FeatureBuilder1 const & fb) +void FeatureBuilder1Merger::AppendFeature(FeatureBuilder1Merger const & fb) { // check that both features are of linear type - if (!fb.m_bLinear || !m_bLinear) - return false; + CHECK(fb.m_bLinear && m_bLinear, ("Not linear feature")); // check that classificator types are the same - if (fb.m_Types != m_Types) - return false; - - // do not create too long features - if (m_Geometry.size() > MAX_MERGED_POINTS_COUNT) - return false; - if (fb.m_Geometry.size() > MAX_MERGED_POINTS_COUNT) - return false; + CHECK_EQUAL(fb.m_Types, m_Types, ("Not equal types")); // check last-first points equality - //if (m2::AlmostEqual(m_Geometry.back(), fb.m_Geometry.front())) - if (m_Geometry.back() == fb.m_Geometry.front()) + CHECK_EQUAL(m_Geometry.back(), fb.m_Geometry.front(), ("End and Start point are no equal")); + // merge fb at the end + size_t const size = fb.m_Geometry.size(); + for (size_t i = 1; i < size; ++i) { - // merge fb at the end - for (size_t i = 1; i < fb.m_Geometry.size(); ++i) - { - m_Geometry.push_back(fb.m_Geometry[i]); - m_LimitRect.Add(m_Geometry.back()); - } + m_Geometry.push_back(fb.m_Geometry[i]); + m_LimitRect.Add(fb.m_Geometry[i]); } - // check first-last points equality - //else if (m2::AlmostEqual(m_Geometry.front(), fb.m_Geometry.back())) - else if (m_Geometry.front() == fb.m_Geometry.back()) - { - // merge fb in the beginning - m_Geometry.insert(m_Geometry.begin(), fb.m_Geometry.begin(), fb.m_Geometry.end()); - for (size_t i = 0; i < fb.m_Geometry.size() - 1; ++i) - m_LimitRect.Add(fb.m_Geometry[i]); - } - else - return false; // no common points were found... - - - //static int counter = 0; - // @TODO check if we got AREA feature after merging, this can be useful for coastlines - //LOG(LINFO, (++counter, "features were merged!")); - - return true; + //LOG(LINFO, ("Appended feature", m_Geometry.size())); } - diff --git a/indexer/feature_merger.hpp b/indexer/feature_merger.hpp index 3e625e437a..3e851de7a1 100644 --- a/indexer/feature_merger.hpp +++ b/indexer/feature_merger.hpp @@ -6,8 +6,14 @@ class FeatureBuilder1Merger : public FeatureBuilder1 { public: FeatureBuilder1Merger(FeatureBuilder1 const & fb); - bool MergeWith(FeatureBuilder1 const & fb); + + /// adds fb's geometry at the end of own geometry, + /// but only if they have common point + void AppendFeature(FeatureBuilder1Merger const & fb); vector const & Type() const { return m_Types; } bool ReachedMaxPointsCount() const; + + m2::PointD FirstPoint() const { return m_Geometry.front(); } + m2::PointD LastPoint() const { return m_Geometry.back(); } }; diff --git a/indexer/indexer_tool/world_map_generator.hpp b/indexer/indexer_tool/world_map_generator.hpp index eb3a3eb01c..6b29af6389 100644 --- a/indexer/indexer_tool/world_map_generator.hpp +++ b/indexer/indexer_tool/world_map_generator.hpp @@ -7,12 +7,23 @@ #include "../../indexer/feature.hpp" #include "../../indexer/feature_merger.hpp" #include "../../indexer/feature_visibility.hpp" +#include "../../indexer/point_to_int64.hpp" #include "../../std/map.hpp" #include "../../std/list.hpp" #include "../../std/vector.hpp" +#include "../../std/functional.hpp" #include +#include + +namespace m2 +{ + inline size_t hash_value(m2::PointD const & pt) + { + return PointToInt64(pt.x, pt.y); + } +} template class WorldMapGenerator @@ -23,7 +34,7 @@ class WorldMapGenerator int m_maxWorldScale; bool m_mergeCoastlines; - typedef list FeaturesContainerT; + typedef boost::unordered_map FeaturesContainerT; typedef map, FeaturesContainerT> TypesContainerT; TypesContainerT m_features; @@ -32,39 +43,41 @@ private: /// @return true if one feature was merged bool ReMergeFeatures(FeaturesContainerT & features) { - bool merged = false; - for (FeaturesContainerT::iterator base = features.begin(); base != features.end();) + //bool merged = false; + for (FeaturesContainerT::iterator base = features.begin(); base != features.end(); ++base) { - FeaturesContainerT::iterator ft = base; - for (++ft; ft != features.end();) + FeaturesContainerT::iterator found = features.find(base->second.LastPoint()); + if (found != features.end()) { - if (base->MergeWith(*ft)) - { - features.erase(ft++); - merged = true; - } - else if (base->ReachedMaxPointsCount()) - break; - else - ++ft; + base->second.AppendFeature(found->second); + features.erase(found); + return true; + //merged = true; } - - if (base->ReachedMaxPointsCount()) - { - // emit "overflowed" features - (*m_worldBucket)(*base); - features.erase(base++); - } - else - ++base; } - return merged; + //return merged; + return false; } void TryToMerge(FeatureBuilder1 const & fb) { - FeatureBuilder1Merger const fbm(fb); - m_features[fbm.Type()].push_back(fbm); + FeatureBuilder1Merger fbm(fb); + FeaturesContainerT & container = m_features[fbm.Type()]; + FeaturesContainerT::iterator found = container.find(fbm.LastPoint()); + if (found != container.end()) + { + fbm.AppendFeature(found->second); + container.erase(found); + } + + 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(), fb.GetPointsCount())); + (*m_worldBucket)(fb); + } } public: @@ -89,7 +102,7 @@ public: {} // emit all merged features for (FeaturesContainerT::iterator itF = it->second.begin(); itF != it->second.end(); ++itF) - (*m_worldBucket)(*itF); + (*m_worldBucket)(itF->second); } if (m_mergeCoastlines) diff --git a/platform/download_manager.hpp b/platform/download_manager.hpp index ce89f7e810..d117b1941f 100644 --- a/platform/download_manager.hpp +++ b/platform/download_manager.hpp @@ -10,7 +10,14 @@ typedef std::pair TDownloadProgress; typedef boost::function TDownloadProgressFunction; -typedef boost::function TDownloadFinishedFunction; +enum DownloadResult +{ + EHttpDownloadOk, + EHttpDownloadFileNotFound, // HTTP 404 + EHttpDownloadFailed, + EHttpDownloadFileIsLocked // downloaded file can't replace existing locked file +}; +typedef boost::function TDownloadFinishedFunction; /// Platform-dependent implementations should derive it /// and implement pure virtual methods diff --git a/platform/qt_download.cpp b/platform/qt_download.cpp index 8cdf37cd18..3afbd0fcb0 100644 --- a/platform/qt_download.cpp +++ b/platform/qt_download.cpp @@ -94,7 +94,7 @@ QtDownload::QtDownload(QtDownloadManager & manager, char const * url, m_file = 0; if (m_finish) - m_finish(url, false); + m_finish(url, EHttpDownloadFailed); // mark itself to delete deleteLater(); return; @@ -186,7 +186,8 @@ void QtDownload::OnHttpFinished() m_reply = 0; if (m_finish) - m_finish(objectName().toUtf8().data(), false); + m_finish(objectName().toUtf8().data(), netError == QNetworkReply::ContentNotFoundError + ? EHttpDownloadFileNotFound : EHttpDownloadFailed); // selfdestruct deleteLater(); } @@ -212,7 +213,7 @@ void QtDownload::OnHttpFinished() { // sh*t... file is locked and can't be removed m_file->remove(); // report error to GUI - LOG(LERROR, ("File exists and can't be replaced by downloaded one:", qPrintable(originalFileName))); + LOG(LWARNING, ("File exists and can't be replaced by downloaded one:", qPrintable(originalFileName))); resultForGui = false; } @@ -222,7 +223,7 @@ void QtDownload::OnHttpFinished() m_reply = 0; if (m_finish) - m_finish(qPrintable(objectName()), resultForGui); + m_finish(qPrintable(objectName()), resultForGui ? EHttpDownloadOk : EHttpDownloadFileIsLocked); // selfdestruct deleteLater(); } diff --git a/std/functional.hpp b/std/functional.hpp index c8c5478abf..aa6f8cba10 100644 --- a/std/functional.hpp +++ b/std/functional.hpp @@ -8,6 +8,7 @@ #include using std::greater; using std::less; +using std::equal_to; #ifdef DEBUG_NEW #define new DEBUG_NEW