Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'generator/polygonizer.hpp')
-rw-r--r--generator/polygonizer.hpp203
1 files changed, 203 insertions, 0 deletions
diff --git a/generator/polygonizer.hpp b/generator/polygonizer.hpp
new file mode 100644
index 0000000000..8ce1963780
--- /dev/null
+++ b/generator/polygonizer.hpp
@@ -0,0 +1,203 @@
+#pragma once
+#include "kml_parser.hpp"
+#include "world_map_generator.hpp"
+
+#include "../indexer/feature.hpp"
+#include "../indexer/feature_visibility.hpp"
+#include "../indexer/cell_id.hpp"
+#include "../geometry/rect2d.hpp"
+#include "../coding/file_writer.hpp"
+#include "../base/base.hpp"
+#include "../base/buffer_vector.hpp"
+#include "../base/macros.hpp"
+#include "../std/scoped_ptr.hpp"
+#include "../std/string.hpp"
+
+#ifndef PARALLEL_POLYGONIZER
+#define PARALLEL_POLYGONIZER 1
+#endif
+
+#if PARALLEL_POLYGONIZER
+#include <QSemaphore>
+#include <QThreadPool>
+#include <QMutex>
+#include <QMutexLocker>
+#endif
+
+namespace feature
+{
+ // Groups features according to country polygons
+ template <class FeatureOutT, class BoundsT, typename CellIdT>
+ class Polygonizer
+ {
+ public:
+ template <class TInfo>
+ Polygonizer(TInfo & info) : m_FeatureOutInitData(info.datFilePrefix, info.datFileSuffix),
+ m_worldMap(info.maxScaleForWorldFeatures, info.mergeCoastlines, m_FeatureOutInitData)
+#if PARALLEL_POLYGONIZER
+ , m_ThreadPoolSemaphore(m_ThreadPool.maxThreadCount() * 8)
+#endif
+ {
+#if PARALLEL_POLYGONIZER
+ LOG(LINFO, ("Polygonizer thread pool threads:", m_ThreadPool.maxThreadCount()));
+#endif
+
+ CHECK(kml::LoadCountriesList(info.datFilePrefix, m_countries, info.simplifyCountriesLevel),
+ ("Error loading country polygons files"));
+
+ //LOG_SHORT(LINFO, ("Loaded polygons count for regions:"));
+ //for (size_t i = 0; i < m_countries.size(); ++i)
+ //{
+ // LOG_SHORT(LINFO, (m_countries[i].m_name, m_countries[i].m_regions.size()));
+ //}
+ }
+ ~Polygonizer()
+ {
+ Finish();
+ for_each(m_Buckets.begin(), m_Buckets.end(), DeleteFunctor());
+ }
+
+ struct PointChecker
+ {
+ kml::RegionsContainerT const & m_regions;
+ bool m_belongs;
+
+ PointChecker(kml::RegionsContainerT const & regions)
+ : m_regions(regions), m_belongs(false) {}
+
+ bool operator()(m2::PointD const & pt)
+ {
+ m_regions.ForEachInRect(m2::RectD(pt, pt), bind<void>(ref(*this), _1, cref(pt)));
+ return !m_belongs;
+ }
+
+ void operator() (kml::Region const & rgn, kml::Region::value_type const & point)
+ {
+ if (!m_belongs)
+ m_belongs = rgn.Contains(point);
+ }
+ };
+
+ class InsertCountriesPtr
+ {
+ typedef buffer_vector<kml::CountryPolygons const *, 32> vec_type;
+ vec_type & m_vec;
+
+ public:
+ InsertCountriesPtr(vec_type & vec) : m_vec(vec) {}
+ void operator() (kml::CountryPolygons const & c)
+ {
+ m_vec.push_back(&c);
+ }
+ };
+
+ void operator () (FeatureBuilder1 const & fb)
+ {
+ m_worldMap(fb);
+
+ buffer_vector<kml::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
+ }
+ }
+ }
+
+ void Finish()
+ {
+#if PARALLEL_POLYGONIZER
+ m_ThreadPool.waitForDone();
+#endif
+ }
+
+ void EmitFeature(kml::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(country->m_name, m_FeatureOutInitData));
+ country->m_index = m_Buckets.size()-1;
+ }
+
+ (*(m_Buckets[country->m_index]))(fb);
+ }
+
+ vector<string> const & Names()
+ {
+ return m_Names;
+ }
+
+ private:
+ typename FeatureOutT::InitDataType m_FeatureOutInitData;
+
+ vector<FeatureOutT*> m_Buckets;
+ vector<string> m_Names;
+ kml::CountriesContainerT m_countries;
+ WorldMapGenerator<FeatureOutT> m_worldMap;
+
+#if PARALLEL_POLYGONIZER
+ QThreadPool m_ThreadPool;
+ QSemaphore m_ThreadPoolSemaphore;
+ QMutex m_EmitFeatureMutex;
+#endif
+
+ friend class PolygonizerTask;
+
+ class PolygonizerTask
+#if PARALLEL_POLYGONIZER
+ : public QRunnable
+#endif
+ {
+ public:
+ PolygonizerTask(Polygonizer * pPolygonizer,
+ buffer_vector<kml::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.ForEachTruePointRef(doCheck);
+
+ if (doCheck.m_belongs)
+ m_pPolygonizer->EmitFeature(m_Countries[i], m_FB);
+ }
+ }
+
+#if PARALLEL_POLYGONIZER
+ void run()
+ {
+ RunBase();
+
+ m_pPolygonizer->m_ThreadPoolSemaphore.release();
+ }
+#endif
+
+ private:
+ Polygonizer * m_pPolygonizer;
+ buffer_vector<kml::CountryPolygons const *, 32> m_Countries;
+ FeatureBuilder1 m_FB;
+ };
+ };
+}