diff options
author | Maksim Andrianov <maksimandrianov1@gmail.com> | 2019-05-19 02:46:08 +0300 |
---|---|---|
committer | mpimenov <mpimenov@users.noreply.github.com> | 2019-05-21 12:56:48 +0300 |
commit | 91dda74d7ec612c7ae78be491ee2f44c0dc2d73b (patch) | |
tree | 351d4a05df3ba425e7aca787b325e578ec4f133d /generator | |
parent | 066e3de6aa90638fffb05fed1cacc58bfb748d22 (diff) |
[generator] Refactored Polygonizer.
Diffstat (limited to 'generator')
-rw-r--r-- | generator/emitter_coastline.cpp | 2 | ||||
-rw-r--r-- | generator/emitter_simple.cpp | 2 | ||||
-rw-r--r-- | generator/feature_builder.hpp | 39 | ||||
-rw-r--r-- | generator/feature_generator.cpp | 6 | ||||
-rw-r--r-- | generator/feature_generator.hpp | 8 | ||||
-rw-r--r-- | generator/feature_processing_layers.cpp | 6 | ||||
-rw-r--r-- | generator/generator_tests/coasts_test.cpp | 2 | ||||
-rw-r--r-- | generator/generator_tests/popularity_builder_tests.cpp | 2 | ||||
-rw-r--r-- | generator/generator_tests_support/test_mwm_builder.cpp | 2 | ||||
-rw-r--r-- | generator/geo_objects/geo_objects.cpp | 4 | ||||
-rw-r--r-- | generator/locality_sorter.cpp | 6 | ||||
-rw-r--r-- | generator/polygonizer.hpp | 264 | ||||
-rw-r--r-- | generator/regions/regions.cpp | 2 | ||||
-rw-r--r-- | generator/world_map_generator.hpp | 2 |
14 files changed, 126 insertions, 221 deletions
diff --git a/generator/emitter_coastline.cpp b/generator/emitter_coastline.cpp index e81c2d06a1..6cc745b48d 100644 --- a/generator/emitter_coastline.cpp +++ b/generator/emitter_coastline.cpp @@ -47,7 +47,7 @@ bool EmitterCoastline::Finish() m_generator->GetFeatures(features); for (auto & feature : features) { - collector(feature); + collector.Collect(feature); ++totalFeatures; totalPoints += feature.GetPointsCount(); diff --git a/generator/emitter_simple.cpp b/generator/emitter_simple.cpp index 9d7a5eac43..0eb14d6bc5 100644 --- a/generator/emitter_simple.cpp +++ b/generator/emitter_simple.cpp @@ -11,7 +11,7 @@ EmitterSimple::EmitterSimple(feature::GenerateInfo const & info) : void EmitterSimple::GetNames(std::vector<std::string> & names) const { - names = m_regionGenerator->Parent().Names(); + names = m_regionGenerator->Parent().GetNames(); } void EmitterSimple::Process(FeatureBuilder1 & fb) diff --git a/generator/feature_builder.hpp b/generator/feature_builder.hpp index 4299c3f432..e9dfcdd331 100644 --- a/generator/feature_builder.hpp +++ b/generator/feature_builder.hpp @@ -127,16 +127,18 @@ public: private: template <class ToDo> class ToDoWrapper { - ToDo & m_toDo; public: - ToDoWrapper(ToDo & toDo) : m_toDo(toDo) {} + ToDoWrapper(ToDo && toDo) : m_toDo(std::forward<ToDo>(toDo)) {} bool operator() (m2::PointD const & p) { return m_toDo(p); } void EndRegion() {} + + private: + ToDo && m_toDo; }; public: template <class ToDo> - void ForEachGeometryPointEx(ToDo & toDo) const + void ForEachGeometryPointEx(ToDo && toDo) const { if (m_params.GetGeomType() == feature::GeomType::Point) toDo(m_center); @@ -153,13 +155,38 @@ public: } template <class ToDo> - void ForEachGeometryPoint(ToDo & toDo) const + void ForEachGeometryPoint(ToDo && toDo) const { - ToDoWrapper<ToDo> wrapper(toDo); - ForEachGeometryPointEx(wrapper); + ToDoWrapper<ToDo> wrapper(std::forward<ToDo>(toDo)); + ForEachGeometryPointEx(std::move(wrapper)); } //@} + template <class ToDo> + bool AnyOfGeometryPointEx(ToDo && toDo) const + { + if (m_params.GetGeomType() == feature::GeomType::Point) + return toDo(m_center); + else + { + for (PointSeq const & points : m_polygons) + { + for (auto const & pt : points) + if (toDo(pt)) + return true; + toDo.EndRegion(); + } + return false; + } + } + + template <class ToDo> + bool AnyOfGeometryPoint(ToDo && toDo) const + { + ToDoWrapper<ToDo> wrapper(std::forward<ToDo>(toDo)); + return AnyOfGeometryPointEx(std::move(wrapper)); + } + bool PreSerialize(); bool PreSerializeAndRemoveUselessNames(); diff --git a/generator/feature_generator.cpp b/generator/feature_generator.cpp index 82f54fe406..deba8d226a 100644 --- a/generator/feature_generator.cpp +++ b/generator/feature_generator.cpp @@ -92,7 +92,7 @@ uint32_t FeaturesCollector::WriteFeatureBase(std::vector<char> const & bytes, Fe return m_featureID++; } -uint32_t FeaturesCollector::operator()(FeatureBuilder1 const & fb) +uint32_t FeaturesCollector::Collect(FeatureBuilder1 const & fb) { FeatureBuilder1::Buffer bytes; fb.Serialize(bytes); @@ -112,9 +112,9 @@ FeaturesAndRawGeometryCollector::~FeaturesAndRawGeometryCollector() LOG(LINFO, ("Write", m_rawGeometryCounter, "geometries into", m_rawGeometryFileStream.GetName())); } -uint32_t FeaturesAndRawGeometryCollector::operator()(FeatureBuilder1 const & fb) +uint32_t FeaturesAndRawGeometryCollector::Collect(FeatureBuilder1 const & fb) { - uint32_t const featureId = FeaturesCollector::operator()(fb); + uint32_t const featureId = FeaturesCollector::Collect(fb); FeatureBuilder1::Geometry const & geom = fb.GetGeometry(); if (geom.empty()) return featureId; diff --git a/generator/feature_generator.hpp b/generator/feature_generator.hpp index d0e874c06d..358eef32db 100644 --- a/generator/feature_generator.hpp +++ b/generator/feature_generator.hpp @@ -29,10 +29,10 @@ public: /// and |kInvalidFeatureId| if not. /// \note See implementation operator() in derived class for cases when |f| cannot be /// serialized. - virtual uint32_t operator()(FeatureBuilder1 const & f); - virtual uint32_t operator()(FeatureBuilder1 & f) + virtual uint32_t Collect(FeatureBuilder1 const & f); + virtual uint32_t Collect(FeatureBuilder1 & f) { - return (*this)(const_cast<FeatureBuilder1 const &>(f)); + return Collect(const_cast<FeatureBuilder1 const &>(f)); } virtual void Finish() {} @@ -65,7 +65,7 @@ public: std::string const & rawGeometryFileName); ~FeaturesAndRawGeometryCollector() override; - uint32_t operator()(FeatureBuilder1 const & f) override; + uint32_t Collect(FeatureBuilder1 const & f) override; }; uint32_t CheckedFilePosCast(FileWriter const & f); diff --git a/generator/feature_processing_layers.cpp b/generator/feature_processing_layers.cpp index ac215171fc..388225239e 100644 --- a/generator/feature_processing_layers.cpp +++ b/generator/feature_processing_layers.cpp @@ -336,8 +336,8 @@ EmitCoastsLayer::~EmitCoastsLayer() m_countryMapper->Map(fb); emitter.Finish(); - fb.AddName("default", emitter.m_currentNames); - (*m_collector)(fb); + fb.AddName("default", emitter.GetCurrentNames()); + m_collector->Collect(fb); }); } @@ -369,7 +369,7 @@ CountryMapper::Polygonizer & CountryMapper::Parent() std::vector<std::string> const & CountryMapper::GetNames() const { - return m_countries->Parent().Names(); + return m_countries->Parent().GetNames(); } WorldMapper::WorldMapper(std::string const & worldFilename, std::string const & rawGeometryFilename, diff --git a/generator/generator_tests/coasts_test.cpp b/generator/generator_tests/coasts_test.cpp index 3dfa742e78..30b7513c61 100644 --- a/generator/generator_tests/coasts_test.cpp +++ b/generator/generator_tests/coasts_test.cpp @@ -99,7 +99,7 @@ public: void operator()(FeatureBuilder1 const & fb1, uint64_t) { if (HasID(fb1)) - m_collector(fb1); + m_collector.Collect(fb1); } private: diff --git a/generator/generator_tests/popularity_builder_tests.cpp b/generator/generator_tests/popularity_builder_tests.cpp index e69d9e73a2..26a025ca0b 100644 --- a/generator/generator_tests/popularity_builder_tests.cpp +++ b/generator/generator_tests/popularity_builder_tests.cpp @@ -242,7 +242,7 @@ public: { feature::FeaturesCollector collector(filename); for (auto const & feature : m_testSet) - collector(feature); + collector.Collect(feature); } PopularityBuilder builder(filename); diff --git a/generator/generator_tests_support/test_mwm_builder.cpp b/generator/generator_tests_support/test_mwm_builder.cpp index 924347026e..1f8c806e82 100644 --- a/generator/generator_tests_support/test_mwm_builder.cpp +++ b/generator/generator_tests_support/test_mwm_builder.cpp @@ -104,7 +104,7 @@ bool TestMwmBuilder::Add(FeatureBuilder1 & fb) return false; } - (*m_collector)(fb); + m_collector->Collect(fb); return true; } diff --git a/generator/geo_objects/geo_objects.cpp b/generator/geo_objects/geo_objects.cpp index e315400d1a..c6083eb894 100644 --- a/generator/geo_objects/geo_objects.cpp +++ b/generator/geo_objects/geo_objects.cpp @@ -144,7 +144,7 @@ void FilterAddresslessByCountryAndRepackMwm(std::string const & pathInGeoObjects { if (GeoObjectsFilter::HasHouse(fb)) { - collector(fb); + collector.Collect(fb); return; } @@ -158,7 +158,7 @@ void FilterAddresslessByCountryAndRepackMwm(std::string const & pathInGeoObjects auto countryName = FromJSON<std::string>(country); auto pos = includeCountries.find(countryName); if (pos != std::string::npos) - collector(fb); + collector.Collect(fb); }; feature::ForEachFromDatRawFormat(pathInGeoObjectsTmpMwm, filteringCollector); diff --git a/generator/locality_sorter.cpp b/generator/locality_sorter.cpp index 533be70db0..1709466c1c 100644 --- a/generator/locality_sorter.cpp +++ b/generator/locality_sorter.cpp @@ -44,7 +44,7 @@ public: } // FeaturesCollector overrides: - uint32_t operator()(FeatureBuilder1 & fb) override + uint32_t Collect(FeatureBuilder1 & fb) override { if (fb.IsArea()) { @@ -101,7 +101,7 @@ public: m_writer.Finish(); } - uint32_t operator()(FeatureBuilder1 & fb1) override + uint32_t Collect(FeatureBuilder1 & fb1) override { auto & fb2 = static_cast<FeatureBuilder2 &>(fb1); @@ -217,7 +217,7 @@ bool GenerateLocalityDataImpl(FeaturesCollector & collector, NeedSerialize const ReadFromSourceRawFormat(src, f); // Emit object. if (needSerialize(f)) - collector(f); + collector.Collect(f); } collector.Finish(); diff --git a/generator/polygonizer.hpp b/generator/polygonizer.hpp index c6e84f8719..15cc53700b 100644 --- a/generator/polygonizer.hpp +++ b/generator/polygonizer.hpp @@ -3,220 +3,98 @@ #include "generator/borders_loader.hpp" #include "generator/feature_builder.hpp" #include "generator/generate_info.hpp" -#include "generator/osm_source.hpp" - -#include "indexer/feature_visibility.hpp" -#include "indexer/cell_id.hpp" #include "geometry/rect2d.hpp" +#include "geometry/mercator.hpp" -#include "coding/file_writer.hpp" - -#include "base/base.hpp" -#include "base/buffer_vector.hpp" -#include "base/macros.hpp" - +#include <memory> #include <string> - -#ifndef PARALLEL_POLYGONIZER -#define PARALLEL_POLYGONIZER 1 -#endif - -#if PARALLEL_POLYGONIZER -#include <QtCore/QSemaphore> -#include <QtCore/QThreadPool> -#include <QtCore/QMutex> -#include <QtCore/QMutexLocker> -#endif +#include <vector> namespace feature { - // Groups features according to country polygons - template <class FeatureOutT> - class Polygonizer +// Groups features according to country polygons +template <class FeatureOut> +class Polygonizer +{ +public: + Polygonizer(feature::GenerateInfo const & info) + : m_info(info) { - feature::GenerateInfo const & m_info; - - vector<FeatureOutT*> m_Buckets; - vector<std::string> m_Names; - borders::CountriesContainer m_countries; - -#if PARALLEL_POLYGONIZER - QThreadPool m_ThreadPool; - QSemaphore m_ThreadPoolSemaphore; - QMutex m_EmitFeatureMutex; -#endif - - public: - Polygonizer(feature::GenerateInfo const & info) - : m_info(info) -#if PARALLEL_POLYGONIZER - , m_ThreadPoolSemaphore(m_ThreadPool.maxThreadCount() * 8) -#endif + if (info.m_splitByPolygons) { -#if PARALLEL_POLYGONIZER - LOG(LINFO, ("Polygonizer thread pool threads:", m_ThreadPool.maxThreadCount())); -#endif - - if (info.m_splitByPolygons) - { - CHECK(borders::LoadCountriesList(info.m_targetDir, m_countries), + CHECK(borders::LoadCountriesList(info.m_targetDir, m_countries), ("Error loading country polygons files")); - } - else - { - // Insert fake country polygon equal to whole world to - // create only one output file which contains all features - m_countries.Add(borders::CountryPolygons(info.m_fileName), MercatorBounds::FullRect()); - } - } - ~Polygonizer() - { - Finish(); - for_each(m_Buckets.begin(), m_Buckets.end(), base::DeleteFunctor()); - } - - struct PointChecker - { - borders::RegionsContainer const & m_regions; - bool m_belongs; - - PointChecker(borders::RegionsContainer const & regions) - : m_regions(regions), m_belongs(false) {} - - bool operator()(m2::PointD const & pt) - { - m_regions.ForEachInRect(m2::RectD(pt, pt), - std::bind<void>(std::ref(*this), std::placeholders::_1, std::cref(pt))); - return !m_belongs; - } - - void operator() (borders::Region const & rgn, borders::Region::Value const & point) - { - if (!m_belongs) - m_belongs = rgn.Contains(point); - } - }; - - class InsertCountriesPtr - { - typedef buffer_vector<borders::CountryPolygons const *, 32> vec_type; - vec_type & m_vec; - - public: - InsertCountriesPtr(vec_type & vec) : m_vec(vec) {} - void operator() (borders::CountryPolygons const & c) - { - m_vec.push_back(&c); - } - }; - - void operator()(FeatureBuilder1 & fb) - { - buffer_vector<borders::CountryPolygons const *, 32> vec; - m_countries.ForEachInRect(fb.GetLimitRect(), InsertCountriesPtr(vec)); - - switch (vec.size()) - { - case 0: - break; - case 1: - EmitFeature(vec[0], fb); - break; - default: - { -#if PARALLEL_POLYGONIZER - m_ThreadPoolSemaphore.acquire(); - m_ThreadPool.start(new PolygonizerTask(this, vec, fb)); -#else - PolygonizerTask task(this, vec, fb); - task.RunBase(); -#endif - } - } } - - std::string m_currentNames; - - void Start() + else { - m_currentNames.clear(); + // Insert fake country polygon equal to whole world to + // create only one output file which contains all features + m_countries.Add(borders::CountryPolygons(info.m_fileName), MercatorBounds::FullRect()); } + } - void Finish() - { -#if PARALLEL_POLYGONIZER - m_ThreadPool.waitForDone(); -#endif - } - - void EmitFeature(borders::CountryPolygons const * country, FeatureBuilder1 const & fb) - { -#if PARALLEL_POLYGONIZER - QMutexLocker mutexLocker(&m_EmitFeatureMutex); - UNUSED_VALUE(mutexLocker); -#endif - if (country->m_index == -1) - { - m_Names.push_back(country->m_name); - m_Buckets.push_back(new FeatureOutT(m_info.GetTmpFileName(country->m_name))); - country->m_index = static_cast<int>(m_Buckets.size())-1; - } + ~Polygonizer() + { + Finish(); + } - if (!m_currentNames.empty()) - m_currentNames += ';'; - m_currentNames += country->m_name; + void operator()(FeatureBuilder1 & fb) + { + m_countries.ForEachInRect(fb.GetLimitRect(), [&](auto const & countryPolygons) { + auto const need = fb.AnyOfGeometryPoint([&](auto const & point) { + auto const & regions = countryPolygons.m_regions; + return regions.AnyOfInRect(m2::RectD(point, point), [&](auto const & rgn) { + return rgn.Contains(point); + }); + return true; + }); + + if (need) + EmitFeature(countryPolygons, fb); + }); + } + + void Start() + { + m_currentNames.clear(); + } - auto & bucket = *(m_Buckets[country->m_index]); - bucket(fb); - } + void Finish() + { + } - vector<std::string> const & Names() const + void EmitFeature(borders::CountryPolygons const & countryPolygons, FeatureBuilder1 const & fb) + { + if (countryPolygons.m_index == -1) { - return m_Names; + m_Names.push_back(countryPolygons.m_name); + m_Buckets.emplace_back(new FeatureOut(m_info.GetTmpFileName(countryPolygons.m_name))); + countryPolygons.m_index = static_cast<int>(m_Buckets.size())-1; } - private: - friend class PolygonizerTask; - - class PolygonizerTask -#if PARALLEL_POLYGONIZER - : public QRunnable -#endif - { - public: - PolygonizerTask(Polygonizer * pPolygonizer, - buffer_vector<borders::CountryPolygons const *, 32> const & countries, - FeatureBuilder1 const & fb) - : m_pPolygonizer(pPolygonizer), m_Countries(countries), m_fb(fb) - { - } - - void RunBase() - { - for (size_t i = 0; i < m_Countries.size(); ++i) - { - PointChecker doCheck(m_Countries[i]->m_regions); - m_fb.ForEachGeometryPoint(doCheck); - - if (doCheck.m_belongs) - m_pPolygonizer->EmitFeature(m_Countries[i], m_fb); - } - } + if (!m_currentNames.empty()) + m_currentNames += ';'; -#if PARALLEL_POLYGONIZER - void run() - { - RunBase(); + m_currentNames += countryPolygons.m_name; + m_Buckets[countryPolygons.m_index]->Collect(fb); + } - m_pPolygonizer->m_ThreadPoolSemaphore.release(); - } -#endif + std::vector<std::string> const & GetNames() const + { + return m_Names; + } - private: - Polygonizer * m_pPolygonizer; - buffer_vector<borders::CountryPolygons const *, 32> m_Countries; - FeatureBuilder1 m_fb; - }; - }; + std::string const & GetCurrentNames() const + { + return m_currentNames; + } + +private: + feature::GenerateInfo const & m_info; + std::vector<std::unique_ptr<FeatureOut>> m_Buckets; + std::vector<std::string> m_Names; + borders::CountriesContainer m_countries; + std::string m_currentNames; +}; } // namespace feature diff --git a/generator/regions/regions.cpp b/generator/regions/regions.cpp index 74866524fe..1e93a97c55 100644 --- a/generator/regions/regions.cpp +++ b/generator/regions/regions.cpp @@ -158,7 +158,7 @@ private: } CHECK(fb.IsArea(), ()); - collector(fb); + collector.Collect(fb); }; feature::ForEachFromDatRawFormat(m_pathInRegionsTmpMwm, toDo); diff --git a/generator/world_map_generator.hpp b/generator/world_map_generator.hpp index 149c78464e..1d6b29c4a0 100644 --- a/generator/world_map_generator.hpp +++ b/generator/world_map_generator.hpp @@ -243,7 +243,7 @@ class WorldMapGenerator return (scales::GetUpperWorldScale() >= fb.GetMinFeatureDrawScale()); } - void PushSure(FeatureBuilder1 const & fb) { m_output(fb); } + void PushSure(FeatureBuilder1 const & fb) { m_output.Collect(fb); } }; EmitterImpl m_worldBucket; |