diff options
author | Sergey Yershov <yershov@corp.mail.ru> | 2015-07-28 15:15:06 +0300 |
---|---|---|
committer | Alex Zolotarev <alex@maps.me> | 2015-09-23 02:58:23 +0300 |
commit | 3cef8ffe6ab5b0860a2ff599321ddfb5f525a45d (patch) | |
tree | f69390091e2416da1e9c9a2c01f5c14b3c739f08 /generator/world_map_generator.hpp | |
parent | 1dc564769c8a6f7a0f0a2f620fed77f47c9dc8a1 (diff) |
Review fixes
Diffstat (limited to 'generator/world_map_generator.hpp')
-rw-r--r-- | generator/world_map_generator.hpp | 246 |
1 files changed, 130 insertions, 116 deletions
diff --git a/generator/world_map_generator.hpp b/generator/world_map_generator.hpp index 8a4e5bd515..45dce6171c 100644 --- a/generator/world_map_generator.hpp +++ b/generator/world_map_generator.hpp @@ -13,6 +13,113 @@ #include "defines.hpp" +namespace +{ +class WaterBoundaryChecker +{ + uint32_t m_boundaryType; + deque<m2::RegionD> m_waterRegions; + + m4::Tree<size_t> m_tree; + size_t m_totalFeatures = 0; + size_t m_totalBorders = 0; + size_t m_skippedBorders = 0; + size_t m_selectedPolygons = 0; + +public: + WaterBoundaryChecker(feature::GenerateInfo const & info) + { + m_boundaryType = classif().GetTypeByPath({"boundary", "administrative"}); + LoadWaterGeometry( + info.GetIntermediateFileName(WORLD_COASTS_FILE_NAME, RAW_GEOM_FILE_EXTENSION)); + } + + ~WaterBoundaryChecker() + { + LOG(LINFO, ("Features checked:", m_totalFeatures, "borders checked:", m_totalBorders, + "borders skipped:", m_skippedBorders, "selected polygons:", m_selectedPolygons)); + } + + void LoadWaterGeometry(string const & rawGeometryFileName) + { + LOG(LINFO, ("Loading water geometry:", rawGeometryFileName)); + FileReader reader(rawGeometryFileName); + ReaderSource<FileReader> file(reader); + + size_t total = 0; + while (true) + { + uint64_t numGeometries = 0; + file.Read(&numGeometries, sizeof(numGeometries)); + + if (numGeometries == 0) + break; + + ++total; + + vector<m2::PointD> points; + for (size_t i = 0; i < numGeometries; ++i) + { + uint64_t numPoints = 0; + file.Read(&numPoints, sizeof(numPoints)); + points.resize(numPoints); + file.Read(points.data(), sizeof(m2::PointD) * numPoints); + m_waterRegions.push_back(m2::RegionD()); + m_waterRegions.back().Assign(points.begin(), points.end()); + m_tree.Add(m_waterRegions.size() - 1, m_waterRegions.back().GetRect()); + } + } + LOG(LINFO, ("Load", total, "water geometries")); + } + + bool IsWaterBoundaries(FeatureBuilder1 const & fb) + { + ++m_totalFeatures; + + if (fb.FindType(m_boundaryType, 2) == ftype::GetEmptyValue()) + return false; + + ++m_totalBorders; + + array<m2::PointD, 3> pts = {{{0, 0}, {0, 0}, {0, 0}}}; + array<size_t, 3> hits = {{0, 0, 0}}; + + // For check we select first, last and middle point in line. + auto const & line = fb.GetGeometry().front(); + pts[0] = line.front(); + pts[1] = *(line.cbegin() + line.size() / 2); + pts[2] = line.back(); + + double constexpr kExtension = 0.01; + + for (size_t i = 0; i < pts.size(); ++i) + { + m2::PointD const & p = pts[i]; + m2::RectD r(p.x - kExtension, p.y - kExtension, p.x + kExtension, p.y + kExtension); + m_tree.ForEachInRect(r, [&](size_t index) + { + ++m_selectedPolygons; + hits[i] += m_waterRegions[index].Contains(pts[i]) ? 1 : 0; + }); + } + + size_t const state = (hits[0] & 0x01) + (hits[1] & 0x01) + (hits[2] & 0x01); + + // whole border on water + if (state == 3) + { + LOG(LINFO, ("Boundary", (state == 3 ? "deleted" : "kept"), "hits:", hits, + DebugPrint(fb.GetParams()), fb.GetOsmIdsString())); + ++m_skippedBorders; + return true; + } + + // state == 0 whole border on land, else partial intersection + return false; + } +}; +} + /// Process FeatureBuilder1 for world map. Main functions: /// - check for visibility in world map /// - merge linear features @@ -22,69 +129,25 @@ class WorldMapGenerator class EmitterImpl : public FeatureEmitterIFace { FeatureOutT m_output; - uint32_t m_boundaryType; - deque<m2::RegionD> m_waterRegions; - - m4::Tree<size_t> m_tree; map<uint32_t, size_t> m_mapTypes; - size_t m_totalFeatures = 0; - size_t m_totalBorders = 0; - size_t m_skippedBorders = 0; - size_t m_selectedPolygons = 0; public: explicit EmitterImpl(feature::GenerateInfo const & info) : m_output(info.GetTmpFileName(WORLD_FILE_NAME)) { - m_boundaryType = classif().GetTypeByPath({"boundary", "administrative"}); - LoadWaterGeometry(info.GetIntermediateFileName(WORLD_COASTS_FILE_NAME, RAW_GEOM_FILE_EXTENSION)); LOG(LINFO, ("Output World file:", info.GetTmpFileName(WORLD_FILE_NAME))); } ~EmitterImpl() override { Classificator const & c = classif(); - - LOG(LINFO, ("Features checked:", m_totalFeatures, "borders checked:", m_totalBorders, "borders skipped:", m_skippedBorders, "selected polygons:", m_selectedPolygons)); + stringstream ss; for (auto const & p : m_mapTypes) ss << c.GetReadableObjectName(p.first) << " : " << p.second << endl; LOG(LINFO, ("World types:\n", ss.str())); } - void LoadWaterGeometry(string const & rawGeometryFileName) - { - LOG(LINFO, ("Loading water geometry:", rawGeometryFileName)); - FileReader reader(rawGeometryFileName); - ReaderSource<FileReader> file(reader); - - size_t total = 0; - while (true) - { - uint64_t numGeometries = 0; - file.Read(&numGeometries, sizeof(numGeometries)); - - if (numGeometries == 0) - break; - - ++total; - - vector<m2::PointD> points; - for (size_t i = 0; i < numGeometries; ++i) - { - uint64_t numPoints = 0; - file.Read(&numPoints, sizeof(numPoints)); - points.resize(numPoints); - file.Read(points.data(), sizeof(m2::PointD) * numPoints); - m_waterRegions.push_back(m2::RegionD()); - m_waterRegions.back().Assign(points.begin(), points.end()); - m_tree.Add(m_waterRegions.size() - 1, m_waterRegions.back().GetRect()); - } - } - - LOG(LINFO, ("Load", total, "water geometries")); - } - /// This function is called after merging linear features. void operator()(FeatureBuilder1 const & fb) override { @@ -100,51 +163,6 @@ class WorldMapGenerator ++m_mapTypes[type]; } - bool IsWaterBoundaries(FeatureBuilder1 const & fb) - { - ++m_totalFeatures; - - if (fb.FindType(m_boundaryType, 2) == ftype::GetEmptyValue()) - return false; - - ++m_totalBorders; - - array<m2::PointD, 3> pts = {m2::PointD{0, 0}, {0, 0}, {0, 0}}; - array<size_t, 3> hits = {0, 0, 0}; - - // For check we select first, last and middle point in line. - auto const & line = fb.GetGeometry().front(); - pts[0] = line.front(); - pts[1] = *(line.cbegin() + line.size() / 2); - pts[2] = line.back(); - - double constexpr kExtension = 0.01; - - for (size_t i = 0; i < pts.size(); ++i) - { - m2::RectD r(pts[i].x - kExtension, pts[i].y - kExtension, pts[i].x + kExtension, pts[i].y + kExtension); - m_tree.ForEachInRect(r, [&](size_t index) - { - ++m_selectedPolygons; - hits[i] += m_waterRegions[index].Contains(pts[i]) ? 1 : 0; - }); - } - - size_t const state = (hits[0] & 0x01) + (hits[1] & 0x01) + (hits[2] & 0x01); - - // whole border on water - if (state == 3) - { - LOG(LINFO, ("Boundary", (state == 3 ? "deleted" : "kept"), "hits:", hits, - DebugPrint(fb.GetParams()), fb.GetOsmIdsString())); - ++m_skippedBorders; - return true; - } - - // state == 0 whole border on land, else partial intersection - return false; - } - bool NeedPushToWorld(FeatureBuilder1 const & fb) const { // GetMinFeatureDrawScale also checks suitable size for AREA features @@ -157,12 +175,13 @@ class WorldMapGenerator EmitterImpl m_worldBucket; FeatureTypesProcessor m_typesCorrector; FeatureMergeProcessor m_merger; + WaterBoundaryChecker m_boundaryChecker; public: - template <class TInfo> - explicit WorldMapGenerator(TInfo const & info) + explicit WorldMapGenerator(feature::GenerateInfo const & info) : m_worldBucket(info), - m_merger(POINT_COORD_BITS - (scales::GetUpperScale() - scales::GetUpperWorldScale()) / 2) + m_merger(POINT_COORD_BITS - (scales::GetUpperScale() - scales::GetUpperWorldScale()) / 2), + m_boundaryChecker(info) { // Do not strip last types for given tags, // for example, do not cut 'admin_level' in 'boundary-administrative-XXX'. @@ -200,25 +219,24 @@ public: void operator()(FeatureBuilder1 fb) { - if (m_worldBucket.NeedPushToWorld(fb)) - { - m_worldBucket.CalcStatistics(fb); - // skip visible water boundary - if (m_worldBucket.IsWaterBoundaries(fb)) - return; + if (!m_worldBucket.NeedPushToWorld(fb)) + return; - if (fb.GetGeomType() == feature::GEOM_LINE) - { - MergedFeatureBuilder1 * p = m_typesCorrector(fb); - if (p) - m_merger(p); - } - else - { - if (feature::PreprocessForWorldMap(fb)) - m_worldBucket.PushSure(fb); - } + m_worldBucket.CalcStatistics(fb); + // skip visible water boundary + if (m_boundaryChecker.IsWaterBoundaries(fb)) + return; + + if (fb.GetGeomType() == feature::GEOM_LINE) + { + MergedFeatureBuilder1 * p = m_typesCorrector(fb); + if (p) + m_merger(p); + return; } + + if (feature::PreprocessForWorldMap(fb)) + m_worldBucket.PushSure(fb); } void DoMerge() { m_merger.DoMerge(m_worldBucket); } @@ -230,11 +248,7 @@ class CountryMapGenerator FeatureOutT m_bucket; public: - template <class TInfo> - explicit CountryMapGenerator(TInfo const & info) - : m_bucket(info) - { - } + explicit CountryMapGenerator(feature::GenerateInfo const & info) : m_bucket(info) {} void operator()(FeatureBuilder1 fb) { @@ -242,5 +256,5 @@ public: m_bucket(fb); } - FeatureOutT const & Parent() const { return m_bucket; } + inline FeatureOutT const & Parent() const { return m_bucket; } }; |