From cc9ed5436bece8e3b0531c9ccf7f92d18668dbcc Mon Sep 17 00:00:00 2001 From: Maksim Andrianov Date: Fri, 27 Dec 2019 19:16:36 +0300 Subject: [PATCH] [generator] Fixed optimization with countries borders. --- generator/affiliation.cpp | 14 ++++---- generator/affiliation.hpp | 2 +- generator/borders.cpp | 71 +++++++++++++-------------------------- generator/borders.hpp | 61 ++++++++++++++------------------- 4 files changed, 58 insertions(+), 90 deletions(-) diff --git a/generator/affiliation.cpp b/generator/affiliation.cpp index c3c3387424..6bab02f1d9 100644 --- a/generator/affiliation.cpp +++ b/generator/affiliation.cpp @@ -19,7 +19,7 @@ BOOST_GEOMETRY_REGISTER_RING(std::vector); namespace feature { CountriesFilesAffiliation::CountriesFilesAffiliation(std::string const & borderPath, bool haveBordersForWholeWorld) - : m_countries(borders::PackedBorders::GetOrCreate(borderPath)) + : m_countryPolygonsTree(borders::GetOrCreateCountryPolygonsTree(borderPath)) , m_haveBordersForWholeWorld(haveBordersForWholeWorld) { } @@ -28,7 +28,7 @@ std::vector CountriesFilesAffiliation::GetAffiliations(FeatureBuild { std::vector countries; std::vector> countriesContainer; - m_countries.ForEachInRect(fb.GetLimitRect(), [&](auto const & countryPolygons) { + m_countryPolygonsTree.ForEachPolygonInRect(fb.GetLimitRect(), [&](auto const & countryPolygons) { countriesContainer.emplace_back(countryPolygons); }); @@ -59,7 +59,7 @@ CountriesFilesAffiliation::GetAffiliations(m2::PointD const & point) const { std::vector countries; std::vector> countriesContainer; - m_countries.ForEachInRect(m2::RectD(point, point), [&](auto const & countryPolygons) { + m_countryPolygonsTree.ForEachPolygonInRect(m2::RectD(point, point), [&](auto const & countryPolygons) { countriesContainer.emplace_back(countryPolygons); }); @@ -83,7 +83,7 @@ CountriesFilesAffiliation::GetAffiliations(m2::PointD const & point) const bool CountriesFilesAffiliation::HasRegionByName(std::string const & name) const { - return m_countries.HasRegionByName(name); + return m_countryPolygonsTree.HasRegionByName(name); } CountriesFilesIndexAffiliation::CountriesFilesIndexAffiliation(std::string const & borderPath, @@ -188,7 +188,7 @@ CountriesFilesIndexAffiliation::BuildIndex(const std::vector & net) { pool.SubmitWork([&, rect]() { std::vector> countries; - m_countries.ForEachInRect(rect, [&](auto const & country) { + m_countryPolygonsTree.ForEachPolygonInRect(rect, [&](auto const & country) { countries.emplace_back(country); }); if (m_haveBordersForWholeWorld && countries.size() == 1) @@ -203,8 +203,8 @@ CountriesFilesIndexAffiliation::BuildIndex(const std::vector & net) std::vector> interCountries; for (borders::CountryPolygons const & cp : countries) { - cp.ForAnyRegionGeometry([&](auto const & geometry) { - if (!boost::geometry::intersects(geometry, box)) + cp.ForAnyRegion([&](auto const & region) { + if (!boost::geometry::intersects(region.Data(), box)) return false; interCountries.emplace_back(cp); return true; diff --git a/generator/affiliation.hpp b/generator/affiliation.hpp index 894f415fb1..f33c85f089 100644 --- a/generator/affiliation.hpp +++ b/generator/affiliation.hpp @@ -36,7 +36,7 @@ public: bool HasRegionByName(std::string const & name) const override; protected: - borders::CountriesContainer const & m_countries; + borders::CountryPolygonsCollection const & m_countryPolygonsTree; bool m_haveBordersForWholeWorld; }; diff --git a/generator/borders.cpp b/generator/borders.cpp index be10bba38e..959036b7f4 100644 --- a/generator/borders.cpp +++ b/generator/borders.cpp @@ -47,35 +47,20 @@ public: { RegionsContainer regions; for (m2::RegionD const & border : borders) - { - m2::RectD const rect(border.GetRect()); - m_rect.Add(rect); - regions.Add(border, rect); - } + regions.Add(border, border.GetRect()); - m_polygons = CountryPolygons(name, regions); - } + CountryPolygons countryPolygons(name, regions); - void Finish() - { - if (!m_polygons.IsEmpty()) - { - ASSERT_NOT_EQUAL(m_rect, m2::RectD::GetEmptyRect(), ()); - m_countries.Add(std::move(m_polygons), std::move(m_rect)); - } - - m_polygons.Clear(); - m_rect.MakeEmpty(); + for (m2::RegionD const & border : borders) + m_countries.Add(countryPolygons, border.GetRect()); } private: m4::Tree & m_countries; - CountryPolygons m_polygons; - m2::RectD m_rect; }; template -void ForEachCountry(std::string const & baseDir, ToDo & toDo) +void ForEachCountry(std::string const & baseDir, ToDo && toDo) { std::string const bordersDir = base::JoinPath(baseDir, BORDERS_DIR); CHECK(Platform::IsFileExistsByFullPath(bordersDir), @@ -90,7 +75,6 @@ void ForEachCountry(std::string const & baseDir, ToDo & toDo) { base::GetNameWithoutExt(file); toDo(file, borders); - toDo.Finish(); } } } @@ -133,8 +117,6 @@ public: } } - void Finish() {} - void WritePolygonsInfo() { auto w = m_writer.GetWriter(PACKED_POLYGONS_INFO_TAG); @@ -221,23 +203,22 @@ bool GetBordersRect(std::string const & baseDir, std::string const & country, return true; } -bool LoadCountriesList(std::string const & baseDir, CountriesContainer & countries) +CountryPolygonsCollection LoadCountriesList(std::string const & baseDir) { - m4::Tree regionsTree; LOG(LINFO, ("Loading countries.")); - PolygonLoader loader(regionsTree); - ForEachCountry(baseDir, loader); + CountryPolygonsCollection countryPolygonsCollection; + ForEachCountry(baseDir, [&](auto const & name, auto const & borders) { + RegionsContainer regions; + for (m2::RegionD const & border : borders) + regions.Add(border, border.GetRect()); - LOG(LINFO, ("Countries loaded:", regionsTree.GetSize())); + countryPolygonsCollection.Add(CountryPolygons(name, regions)); + }); - if (!regionsTree.IsEmpty()) - { - countries = CountriesContainer(regionsTree); - return true; - } - - return false; + LOG(LINFO, ("Countries loaded:", countryPolygonsCollection.GetSize())); + CHECK_NOT_EQUAL(countryPolygonsCollection.GetSize(), 0, (baseDir)); + return countryPolygonsCollection; } void GeneratePackedBorders(std::string const & baseDir) @@ -295,22 +276,18 @@ void UnpackBorders(std::string const & baseDir, std::string const & targetDir) } } -// static -std::mutex PackedBorders::m_mutex; -// static -std::unordered_map PackedBorders::m_countries; -// static -CountriesContainer const & PackedBorders::GetOrCreate(std::string const & name) +CountryPolygonsCollection const & GetOrCreateCountryPolygonsTree(std::string const & baseDir) { - std::lock_guard lock(m_mutex); - auto const it = m_countries.find(name); - if (it != m_countries.cend()) + static std::mutex mutex; + static std::unordered_map countriesMap; + + std::lock_guard lock(mutex); + auto const it = countriesMap.find(baseDir); + if (it != countriesMap.cend()) return it->second; - CountriesContainer countries; - CHECK(LoadCountriesList(name, countries), ("Error loading country polygons files.")); - auto const eIt = m_countries.emplace(name, countries); + auto const eIt = countriesMap.emplace(baseDir, LoadCountriesList(baseDir)); return eIt.first->second; } } // namespace borders diff --git a/generator/borders.hpp b/generator/borders.hpp index cc9869ee49..730aa6d1ed 100644 --- a/generator/borders.hpp +++ b/generator/borders.hpp @@ -74,11 +74,15 @@ public: } template - bool ForAnyRegionGeometry(Do && fn) const + void ForEachRegion(Do && fn) const { - return m_regions.ForAny([&](auto const & region) { - return fn(region.Data()); - }); + m_regions.ForEach(std::forward(fn)); + } + + template + bool ForAnyRegion(Do && fn) const + { + return m_regions.ForAny(std::forward(fn)); } private: @@ -86,48 +90,43 @@ private: RegionsContainer m_regions; }; -class CountriesContainer +class CountryPolygonsCollection { public: - CountriesContainer() = default; - explicit CountriesContainer(m4::Tree const & tree) - : m_regionsTree(tree) + CountryPolygonsCollection() = default; + + void Add(CountryPolygons const & countryPolygons) { + auto const it = m_countryPolygonsMap.emplace(countryPolygons.GetName(), countryPolygons); + countryPolygons.ForEachRegion([&](auto const & region){ + m_regionsTree.Add(it.first->second, region.GetRect()); + return true; + }); } + size_t GetSize() const { return m_countryPolygonsMap.size(); } + template - void ForEachInRect(m2::RectD const & rect, ToDo && toDo) const + void ForEachPolygonInRect(m2::RectD const & rect, ToDo && toDo) const { m_regionsTree.ForEachInRect(rect, std::forward(toDo)); } bool HasRegionByName(std::string const & name) const { - return m_regionsTree.FindNode([&](auto const & countryPolygons) { - return countryPolygons.GetName() == name; - }); + return m_countryPolygonsMap.count(name) != 0; } CountryPolygons const & GetRegionByName(std::string const & name) const { ASSERT(HasRegionByName(name), ()); - CountryPolygons const * country = nullptr; - m_regionsTree.FindNode([&](auto const & countryPolygons) { - if (countryPolygons.GetName() == name) - { - country = &countryPolygons; - return true; - } - - return false; - }); - - return *country; + return m_countryPolygonsMap.at(name); } private: - m4::Tree m_regionsTree; + m4::Tree> m_regionsTree; + std::unordered_map m_countryPolygonsMap; }; /// @return false if borderFile can't be opened @@ -136,7 +135,7 @@ bool LoadBorders(std::string const & borderFile, std::vector & outB bool GetBordersRect(std::string const & baseDir, std::string const & country, m2::RectD & bordersRect); -bool LoadCountriesList(std::string const & baseDir, CountriesContainer & countries); +bool LoadCountriesList(std::string const & baseDir, CountryPolygonsCollection & countries); void GeneratePackedBorders(std::string const & baseDir); @@ -159,13 +158,5 @@ void DumpBorderToPolyFile(std::string const & filePath, storage::CountryId const std::vector const & polygons); void UnpackBorders(std::string const & baseDir, std::string const & targetDir); -class PackedBorders -{ -public: - static CountriesContainer const & GetOrCreate(std::string const & name); - -private: - static std::mutex m_mutex; - static std::unordered_map m_countries; -}; +CountryPolygonsCollection const & GetOrCreateCountryPolygonsTree(std::string const & baseDir); } // namespace borders