diff --git a/generator/affiliation.cpp b/generator/affiliation.cpp index 6780265f3e..4d26d3c9de 100644 --- a/generator/affiliation.cpp +++ b/generator/affiliation.cpp @@ -20,50 +20,53 @@ namespace { using namespace feature; -template +template struct RemoveCvref { typedef std::remove_cv_t> type; }; -template +template using RemoveCvrefT = typename RemoveCvref::type; -template +template m2::RectD GetLimitRect(T && t) { using Type = RemoveCvrefT; if constexpr(std::is_same_v) return t.GetLimitRect(); - else if constexpr(std::is_same_v) + if constexpr(std::is_same_v) return m2::RectD(t, t); - else - UNREACHABLE(); + + UNREACHABLE(); } -template -bool ForAnyGeometryPoint(T && t, F && f) +template +bool ForAnyPoint(T && t, F && f) { using Type = RemoveCvrefT; if constexpr(std::is_same_v) - return t.ForAnyGeometryPoint(f); + return t.ForAnyPoint(std::forward(f)); + if constexpr(std::is_same_v) + return f(std::forward(t)); + + UNREACHABLE(); +} + +template +void ForEachPoint(T && t, F && f) +{ + using Type = RemoveCvrefT; + if constexpr(std::is_same_v) + t.ForEachPoint(std::forward(f)); else if constexpr(std::is_same_v) - return f(t); + f(std::forward(t)); else UNREACHABLE(); } -template -void ForEachGeometryPoint(T && t, F && f) -{ - ForAnyGeometryPoint(std::forward(t), [&](auto const & p) { - f(p); - return false; - }); -} - // An implementation for CountriesFilesAffiliation class. -template +template std::vector GetAffiliations(T && t, borders::CountryPolygonsCollection const & countryPolygonsTree, bool haveBordersForWholeWorld) @@ -85,7 +88,7 @@ std::vector GetAffiliations(T && t, for (borders::CountryPolygons const & countryPolygons : countriesContainer) { - auto const need = ForAnyGeometryPoint(t, [&](auto const & point) { + auto const need = ForAnyPoint(t, [&](auto const & point) { return countryPolygons.Contains(point); }); @@ -125,12 +128,12 @@ std::optional IsOneCountryForLimitRect(m2::RectD const & limitRect, return country ? country->GetName() : std::optional{}; } -template +template std::vector GetHonestAffiliations(T && t, IndexSharedPtr const & index) { std::vector affiliations; std::unordered_set countires; - ForEachGeometryPoint(t, [&](auto const & point) { + ForEachPoint(t, [&](auto const & point) { std::vector values; boost::geometry::index::query(*index, boost::geometry::index::covers(point), std::back_inserter(values)); @@ -156,7 +159,7 @@ std::vector GetHonestAffiliations(T && t, IndexSharedPtr const & in return affiliations; } -template +template std::vector GetAffiliations(T && t, IndexSharedPtr const & index) { auto const oneCountry = IsOneCountryForLimitRect(GetLimitRect(t), index); @@ -195,21 +198,21 @@ CountriesFilesIndexAffiliation::CountriesFilesIndexAffiliation(std::string const static std::mutex cacheMutex; static std::unordered_map> cache; auto const key = borderPath + std::to_string(haveBordersForWholeWorld); + + std::lock_guard lock(cacheMutex); + + auto const it = cache.find(key); + if (it != std::cend(cache)) { - std::lock_guard lock(cacheMutex); - auto const it = cache.find(key); - if (it != std::cend(cache)) - { - m_index = it->second; - return; - } + m_index = it->second; + return; } + auto const net = generator::cells_merger::MakeNet(0.2 /* step */, mercator::Bounds::kMinX, mercator::Bounds::kMinY, mercator::Bounds::kMaxX, mercator::Bounds::kMaxY); auto const index = BuildIndex(net); m_index = index; - std::lock_guard lock(cacheMutex); cache.emplace(key, index); } diff --git a/generator/coastlines_generator.cpp b/generator/coastlines_generator.cpp index 21a3db13a7..a50ea583ae 100644 --- a/generator/coastlines_generator.cpp +++ b/generator/coastlines_generator.cpp @@ -28,63 +28,34 @@ CoastlineFeaturesGenerator::CoastlineFeaturesGenerator() namespace { - m2::RectD GetLimitRect(RegionT const & rgn) - { - RectT r = rgn.GetRect(); - return m2::RectD(r.minX(), r.minY(), r.maxX(), r.maxY()); - } +m2::RectD GetLimitRect(RegionT const & rgn) +{ + RectT r = rgn.GetRect(); + return m2::RectD(r.minX(), r.minY(), r.maxX(), r.maxY()); +} - inline PointT D2I(m2::PointD const & p) - { - m2::PointU const pu = PointDToPointU(p, kPointCoordBits); - return PointT(static_cast(pu.x), static_cast(pu.y)); - } - - template class DoCreateRegion - { - Tree & m_tree; - - RegionT m_rgn; - m2::PointD m_pt; - bool m_exist; - - public: - template - DoCreateRegion(T && tree) : m_tree(std::forward(tree)), m_exist(false) {} - - bool operator()(m2::PointD const & p) - { - // This logic is to skip last polygon point (that is equal to first). - - if (m_exist) - { - // add previous point to region - m_rgn.AddPoint(D2I(m_pt)); - } - else - m_exist = true; - - // save current point - m_pt = p; - return true; - } - - void EndRegion() - { - m_tree.Add(m_rgn, GetLimitRect(m_rgn)); - - m_rgn = RegionT(); - m_exist = false; - } - }; +inline PointT D2I(m2::PointD const & p) +{ + m2::PointU const pu = PointDToPointU(p, kPointCoordBits); + return PointT(static_cast(pu.x), static_cast(pu.y)); +} } // namespace void CoastlineFeaturesGenerator::AddRegionToTree(FeatureBuilder const & fb) { - ASSERT ( fb.IsGeometryClosed(), () ); + ASSERT(fb.IsGeometryClosed(), ()); - DoCreateRegion createRgn(m_tree); - fb.ForEachGeometryPointEx(createRgn); + fb.ForEachPolygon([&](auto const & polygon) { + if (polygon.empty()) + return; + + RegionT rgn; + for (auto it = std::next(std::cbegin(polygon)); it != std::cend(polygon); ++it) + rgn.AddPoint(D2I(*it)); + + auto const limitRect = GetLimitRect(rgn); + m_tree.Add(std::move(rgn), limitRect); + }); } void CoastlineFeaturesGenerator::Process(FeatureBuilder const & fb) diff --git a/generator/feature_builder.hpp b/generator/feature_builder.hpp index ee364089bf..74cc7549f4 100644 --- a/generator/feature_builder.hpp +++ b/generator/feature_builder.hpp @@ -70,7 +70,7 @@ public: size_t GetTypesCount() const { return m_params.m_types.size(); } template - void ForEachGeometryPointEx(ToDo && toDo) const + void ForEachPoint(ToDo && toDo) const { if (IsPoint()) { @@ -78,48 +78,34 @@ public: } else { - for (PointSeq const & points : m_polygons) + for (auto const & points : m_polygons) { for (auto const & pt : points) - { - if (!toDo(pt)) - return; - } - toDo.EndRegion(); + toDo(pt); } } } template - void ForEachGeometryPoint(ToDo && toDo) const - { - ToDoWrapper wrapper(std::forward(toDo)); - ForEachGeometryPointEx(std::move(wrapper)); - } - - template - bool ForAnyGeometryPointEx(ToDo && toDo) const + bool ForAnyPoint(ToDo && toDo) const { if (IsPoint()) return toDo(m_center); - for (PointSeq const & points : m_polygons) + for (auto const & points : m_polygons) { - for (auto const & pt : points) - { - if (toDo(pt)) - return true; - } - toDo.EndRegion(); + if (base::AnyOf(points, std::forward(toDo))) + return true; } + return false; } template - bool ForAnyGeometryPoint(ToDo && toDo) const + void ForEachPolygon(ToDo && toDo) const { - ToDoWrapper wrapper(std::forward(toDo)); - return ForAnyGeometryPointEx(std::move(wrapper)); + for (auto const & points : m_polygons) + toDo(points); } // To work with geometry type. @@ -210,18 +196,6 @@ public: bool IsCoastCell() const { return (m_coastCell != -1); } protected: - template - class ToDoWrapper - { - public: - ToDoWrapper(ToDo && toDo) : m_toDo(std::forward(toDo)) {} - bool operator()(m2::PointD const & p) { return m_toDo(p); } - void EndRegion() {} - - private: - ToDo && m_toDo; - }; - // Can be one of the following: // - point in point-feature // - origin point of text [future] in line-feature diff --git a/generator/feature_helpers.cpp b/generator/feature_helpers.cpp index db4e668038..c70cb998d2 100644 --- a/generator/feature_helpers.cpp +++ b/generator/feature_helpers.cpp @@ -26,7 +26,7 @@ void CalculateMidPoints::operator()(FeatureBuilder const & ft, uint64_t pos) m_midLoc = m2::PointD::Zero();; m_locCount = 0; - ft.ForEachGeometryPoint(*this); + ft.ForEachPoint(*this); ASSERT_NOT_EQUAL(m_locCount, 0, ()); m_midLoc = m_midLoc / m_locCount; diff --git a/generator/generator_tests/affiliation_tests.cpp b/generator/generator_tests/affiliation_tests.cpp index ad6fd13fa8..21eadb894a 100644 --- a/generator/generator_tests/affiliation_tests.cpp +++ b/generator/generator_tests/affiliation_tests.cpp @@ -25,14 +25,16 @@ public: static const std::string kOne; static const std::string kTwo; - static constexpr m2::PointD kPointOne1{3.0, 3.0}; - static constexpr m2::PointD kPointOne2{4.0, 4.0}; - static constexpr m2::PointD kPointTwo1{10.0, 3.0}; - static constexpr m2::PointD kPointTwo2{11.0, 4.0}; - static constexpr m2::PointD kPointOneTwo1{7.0, 4.0}; - static constexpr m2::PointD kPointOneTwo2{9.0, 5.0}; - static constexpr m2::PointD kPointOneBb{1.0, 9.0}; - static constexpr m2::PointD kPointTwoBb{14.0, 9.0}; + static constexpr m2::PointD kPointInsideOne1{3.0, 3.0}; + static constexpr m2::PointD kPointInsideOne2{4.0, 4.0}; + static constexpr m2::PointD kPointInsideTwo1{10.0, 3.0}; + static constexpr m2::PointD kPointInsideTwo2{11.0, 4.0}; + static constexpr m2::PointD kPointInsideOneAndTwo1{7.0, 4.0}; + static constexpr m2::PointD kPointInsideOneAndTwo2{9.0, 5.0}; + static constexpr m2::PointD kPointOnBorderOne{1.0, 6.0}; + static constexpr m2::PointD kPointOnBorderTwo{14.0, 6.0}; + static constexpr m2::PointD kPointInsideOneBoundingBox{1.0, 9.0}; + static constexpr m2::PointD kPointInsideTwoBoundingBox{14.0, 9.0}; AffiliationTests() { @@ -102,31 +104,41 @@ bool Test(std::vector && res, std::set const & answ) void TestCountriesAffiliationInsideBorders(feature::AffiliationInterface const & affiliation) { - TEST(Test(affiliation.GetAffiliations(AffiliationTests::kPointOne1), {AffiliationTests::kOne}), + TEST(Test(affiliation.GetAffiliations(AffiliationTests::kPointInsideOne1), + {AffiliationTests::kOne}), ()); - TEST(Test(affiliation.GetAffiliations(AffiliationTests::kPointOne2), {AffiliationTests::kOne}), + TEST(Test(affiliation.GetAffiliations(AffiliationTests::kPointInsideOne2), + {AffiliationTests::kOne}), ()); - TEST(Test(affiliation.GetAffiliations(AffiliationTests::kPointTwo1), {AffiliationTests::kTwo}), + TEST(Test(affiliation.GetAffiliations(AffiliationTests::kPointOnBorderOne), + {AffiliationTests::kOne}), ()); - TEST(Test(affiliation.GetAffiliations(AffiliationTests::kPointTwo2), {AffiliationTests::kTwo}), + TEST(Test(affiliation.GetAffiliations(AffiliationTests::kPointInsideTwo1), + {AffiliationTests::kTwo}), ()); - TEST(Test(affiliation.GetAffiliations(AffiliationTests::kPointOneTwo1), + TEST(Test(affiliation.GetAffiliations(AffiliationTests::kPointInsideTwo2), + {AffiliationTests::kTwo}), + ()); + TEST(Test(affiliation.GetAffiliations(AffiliationTests::kPointInsideOneAndTwo1), {AffiliationTests::kOne, AffiliationTests::kTwo}), ()); - TEST(Test(affiliation.GetAffiliations(AffiliationTests::kPointOneTwo2), + TEST(Test(affiliation.GetAffiliations(AffiliationTests::kPointInsideOneAndTwo2), {AffiliationTests::kOne, AffiliationTests::kTwo}), ()); + TEST(Test(affiliation.GetAffiliations(AffiliationTests::kPointOnBorderTwo), + {AffiliationTests::kTwo}), + ()); TEST(Test(affiliation.GetAffiliations(AffiliationTests::MakeLineFb( - {AffiliationTests::kPointOne1, AffiliationTests::kPointOne2})), + {AffiliationTests::kPointInsideOne1, AffiliationTests::kPointInsideOne2})), {AffiliationTests::kOne}), ()); TEST(Test(affiliation.GetAffiliations(AffiliationTests::MakeLineFb( - {AffiliationTests::kPointTwo1, AffiliationTests::kPointTwo2})), + {AffiliationTests::kPointInsideTwo1, AffiliationTests::kPointInsideTwo2})), {AffiliationTests::kTwo}), ()); TEST(Test(affiliation.GetAffiliations(AffiliationTests::MakeLineFb( - {AffiliationTests::kPointOne1, AffiliationTests::kPointTwo1})), + {AffiliationTests::kPointInsideOne1, AffiliationTests::kPointInsideTwo1})), {AffiliationTests::kOne, AffiliationTests::kTwo}), ()); } @@ -139,17 +151,19 @@ void TestCountriesFilesAffiliation(std::string const & borderPath) TestCountriesAffiliationInsideBorders(affiliation); - TEST(Test(affiliation.GetAffiliations(AffiliationTests::kPointOneBb), {}), ()); - TEST(Test(affiliation.GetAffiliations(AffiliationTests::kPointTwoBb), {}), ()); + TEST(Test(affiliation.GetAffiliations(AffiliationTests::kPointInsideOneBoundingBox), {}), ()); + TEST(Test(affiliation.GetAffiliations(AffiliationTests::kPointInsideTwoBoundingBox), {}), ()); } { T affiliation(borderPath, true /* haveBordersForWholeWorld */); TestCountriesAffiliationInsideBorders(affiliation); - TEST(Test(affiliation.GetAffiliations(AffiliationTests::kPointOneBb), {AffiliationTests::kOne}), + TEST(Test(affiliation.GetAffiliations(AffiliationTests::kPointInsideOneBoundingBox), + {AffiliationTests::kOne}), ()); - TEST(Test(affiliation.GetAffiliations(AffiliationTests::kPointTwoBb), {AffiliationTests::kTwo}), + TEST(Test(affiliation.GetAffiliations(AffiliationTests::kPointInsideTwoBoundingBox), + {AffiliationTests::kTwo}), ()); } } @@ -159,12 +173,12 @@ UNIT_CLASS_TEST(AffiliationTests, SingleAffiliationTests) std::string const kName = "Name"; feature::SingleAffiliation affiliation(kName); - TEST(Test(affiliation.GetAffiliations(AffiliationTests::kPointOne1), {kName}), ()); + TEST(Test(affiliation.GetAffiliations(AffiliationTests::kPointInsideOne1), {kName}), ()); - TEST(Test(affiliation.GetAffiliations(AffiliationTests::kPointOneTwo1), {kName}), ()); + TEST(Test(affiliation.GetAffiliations(AffiliationTests::kPointInsideOneAndTwo1), {kName}), ()); TEST(Test(affiliation.GetAffiliations(AffiliationTests::MakeLineFb( - {AffiliationTests::kPointOne1, AffiliationTests::kPointTwo1})), + {AffiliationTests::kPointInsideOne1, AffiliationTests::kPointInsideTwo1})), {kName}), ());