diff options
author | Vladimir Byko-Ianko <bykoianko@gmail.com> | 2016-11-17 14:30:16 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-11-17 14:30:16 +0300 |
commit | 915d8130a778955455e899b973a1b93479c8ba36 (patch) | |
tree | 1eea309b5d8d78e2d8a374fe41b86b8848496110 /storage | |
parent | 05f4288f2c753f07279925ec0ba0f3fcbc34fac1 (diff) | |
parent | 647bc20a338d26108726e40770b8d6779a636e51 (diff) |
Merge pull request #4738 from rokuz/intersection-mwm-rect
Added getting mwms by rect
Diffstat (limited to 'storage')
-rw-r--r-- | storage/country_info_getter.cpp | 52 | ||||
-rw-r--r-- | storage/country_info_getter.hpp | 9 | ||||
-rw-r--r-- | storage/storage_tests/country_info_getter_test.cpp | 26 |
3 files changed, 87 insertions, 0 deletions
diff --git a/storage/country_info_getter.cpp b/storage/country_info_getter.cpp index 3994e618e5..7d07f860cf 100644 --- a/storage/country_info_getter.cpp +++ b/storage/country_info_getter.cpp @@ -59,6 +59,23 @@ TCountryId CountryInfoGetter::GetRegionCountryId(m2::PointD const & pt) const return id != kInvalidId ? m_countries[id].m_countryId : kInvalidCountryId; } +vector<TCountryId> CountryInfoGetter::GetRegionsCountryIdByRect(m2::RectD const & rect) const +{ + size_t constexpr kAverageSize = 10; + + vector<TCountryId> result; + result.reserve(kAverageSize); + for (size_t id = 0; id < m_countries.size(); ++id) + { + if (rect.IsRectInside(m_countries[id].m_rect) || + (rect.IsIntersect(m_countries[id].m_rect) && IsIntersectedByRegionImpl(id, rect))) + { + result.push_back(m_countries[id].m_countryId); + } + } + return result; +} + void CountryInfoGetter::GetRegionsCountryId(m2::PointD const & pt, TCountriesVec & closestCoutryIds) { double const kLookupRadiusM = 30 /* km */ * 1000; @@ -297,6 +314,35 @@ bool CountryInfoReader::IsBelongToRegionImpl(size_t id, m2::PointD const & pt) c return WithRegion(id, contains); } +bool CountryInfoReader::IsIntersectedByRegionImpl(size_t id, m2::RectD const & rect) const +{ + vector<pair<m2::PointD, m2::PointD>> edges = + { + {rect.LeftTop(), rect.RightTop()}, + {rect.RightTop(), rect.RightBottom()}, + {rect.RightBottom(), rect.LeftBottom()}, + {rect.LeftBottom(), rect.LeftTop()} + }; + auto contains = [&edges](vector<m2::RegionD> const & regions) + { + for (auto const & region : regions) + { + for (auto const & edge : edges) + { + m2::PointD result; + if (region.FindIntersection(edge.first, edge.second, result)) + return true; + } + } + return false; + }; + + if (WithRegion(id, contains)) + return true; + + return IsBelongToRegionImpl(id, rect.Center()); +} + bool CountryInfoReader::IsCloseEnough(size_t id, m2::PointD const & pt, double distance) { m2::RectD const lookupRect = MercatorBounds::RectByCenterXYAndSizeInMeters(pt, distance); @@ -347,6 +393,12 @@ bool CountryInfoGetterForTesting::IsBelongToRegionImpl(size_t id, return m_countries[id].m_rect.IsPointInside(pt); } +bool CountryInfoGetterForTesting::IsIntersectedByRegionImpl(size_t id, m2::RectD const & rect) const +{ + CHECK_LESS(id, m_countries.size(), ()); + return rect.IsIntersect(m_countries[id].m_rect); +} + bool CountryInfoGetterForTesting::IsCloseEnough(size_t id, m2::PointD const & pt, double distance) { CHECK_LESS(id, m_countries.size(), ()); diff --git a/storage/country_info_getter.hpp b/storage/country_info_getter.hpp index 3acda1a2d8..a4a42818c2 100644 --- a/storage/country_info_getter.hpp +++ b/storage/country_info_getter.hpp @@ -36,6 +36,10 @@ public: // string. TCountryId GetRegionCountryId(m2::PointD const & pt) const; + // Returns vector of countries file names without an extension for + // countries belong to |rect|. + vector<TCountryId> GetRegionsCountryIdByRect(m2::RectD const & rect) const; + // Returns a list of country ids by a |pt| in mercator. // |closestCoutryIds| is filled with country ids of mwm which covers |pt| or close to it. // |closestCoutryIds| is not filled with country world.mwm country id and with custom mwm. @@ -96,6 +100,9 @@ protected: // Returns true when |pt| belongs to a country identified by |id|. virtual bool IsBelongToRegionImpl(size_t id, m2::PointD const & pt) const = 0; + // Returns true when |rect| intersects a country identified by |id|. + virtual bool IsIntersectedByRegionImpl(size_t id, m2::RectD const & rect) const = 0; + // Returns true when the distance from |pt| to country identified by |id| less then |distance|. virtual bool IsCloseEnough(size_t id, m2::PointD const & pt, double distance) = 0; @@ -144,6 +151,7 @@ protected: // CountryInfoGetter overrides: void ClearCachesImpl() const override; bool IsBelongToRegionImpl(size_t id, m2::PointD const & pt) const override; + bool IsIntersectedByRegionImpl(size_t id, m2::RectD const & rect) const override; bool IsCloseEnough(size_t id, m2::PointD const & pt, double distance) override; template <typename TFn> @@ -172,6 +180,7 @@ protected: // CountryInfoGetter overrides: void ClearCachesImpl() const override; bool IsBelongToRegionImpl(size_t id, m2::PointD const & pt) const override; + bool IsIntersectedByRegionImpl(size_t id, m2::RectD const & rect) const override; bool IsCloseEnough(size_t id, m2::PointD const & pt, double distance) override; }; } // namespace storage diff --git a/storage/storage_tests/country_info_getter_test.cpp b/storage/storage_tests/country_info_getter_test.cpp index b093123980..46398cc2d6 100644 --- a/storage/storage_tests/country_info_getter_test.cpp +++ b/storage/storage_tests/country_info_getter_test.cpp @@ -7,6 +7,8 @@ #include "storage/storage.hpp" #include "geometry/mercator.hpp" +#include "geometry/point2d.hpp" +#include "geometry/rect2d.hpp" #include "platform/mwm_version.hpp" #include "platform/platform.hpp" @@ -14,6 +16,7 @@ #include "base/logging.hpp" #include "std/unique_ptr.hpp" +#include "std/vector.hpp" using namespace storage; @@ -45,6 +48,29 @@ UNIT_TEST(CountryInfoGetter_GetByPoint_Smoke) TEST_EQUAL(info.m_name, "Japan, Kinki", ()); } +UNIT_TEST(CountryInfoGetter_GetRegionsCountryIdByRect_Smoke) +{ + auto const getter = CreateCountryInfoGetter(); + + m2::PointD const p = MercatorBounds::FromLatLon(53.9022651, 27.5618818); + + // Inside mwm. + m2::PointD const halfSize = m2::PointD(0.1, 0.1); + auto countries = getter->GetRegionsCountryIdByRect(m2::RectD(p - halfSize, p + halfSize)); + TEST_EQUAL(countries, vector<storage::TCountryId> { "Belarus" }, ()); + + // Several countries. + m2::PointD const halfSize2 = m2::PointD(5.0, 5.0); + auto countries2 = getter->GetRegionsCountryIdByRect(m2::RectD(p - halfSize2, p + halfSize2)); + auto expected = vector<storage::TCountryId> { "Belarus", "Latvia", "Lithuania", "Poland", + "Russia_Central", "Russia_Northwestern", "Ukraine" }; + TEST_EQUAL(countries2, expected, ()); + + // No one found. + auto countries3 = getter->GetRegionsCountryIdByRect(m2::RectD(-halfSize, halfSize)); + TEST_EQUAL(countries3, vector<storage::TCountryId>{}, ()); +} + UNIT_TEST(CountryInfoGetter_ValidName_Smoke) { string buffer; |