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:
authorArsentiy Milchakov <milcars@mapswithme.com>2018-06-19 14:16:22 +0300
committerVlad Mihaylenko <vxmihaylenko@gmail.com>2018-06-19 19:27:18 +0300
commitc701d2d7be6e0890d5cd2518942ba45b9aaae3f6 (patch)
treedc1801ac95460808d2e63578a619ed8825572109 /storage
parent360fdd2db0e107450029fbca6957019c95c57c52 (diff)
[storage][lightweight] added lightweight country info reader.
Diffstat (limited to 'storage')
-rw-r--r--storage/CMakeLists.txt2
-rw-r--r--storage/country_info_getter.cpp90
-rw-r--r--storage/country_info_getter.hpp75
-rw-r--r--storage/country_info_reader_light.cpp78
-rw-r--r--storage/country_info_reader_light.hpp36
-rw-r--r--storage/storage_integration_tests/CMakeLists.txt1
-rw-r--r--storage/storage_integration_tests/lightweight_matching_tests.cpp58
7 files changed, 263 insertions, 77 deletions
diff --git a/storage/CMakeLists.txt b/storage/CMakeLists.txt
index 6f0c13478f..43249852a5 100644
--- a/storage/CMakeLists.txt
+++ b/storage/CMakeLists.txt
@@ -13,6 +13,8 @@ set(
country_info_getter.hpp
country_name_getter.cpp
country_name_getter.hpp
+ country_info_reader_light.cpp
+ country_info_reader_light.hpp
country_parent_getter.cpp
country_parent_getter.hpp
country_polygon.hpp
diff --git a/storage/country_info_getter.cpp b/storage/country_info_getter.cpp
index 2dadcf3149..4da112944d 100644
--- a/storage/country_info_getter.cpp
+++ b/storage/country_info_getter.cpp
@@ -50,13 +50,59 @@ private:
};
} // namespace
-// CountryInfoGetter -------------------------------------------------------------------------------
-TCountryId CountryInfoGetter::GetRegionCountryId(m2::PointD const & pt) const
+// CountryInfoGetterBase ---------------------------------------------------------------------------------
+TCountryId CountryInfoGetterBase::GetRegionCountryId(m2::PointD const & pt) const
{
TRegionId const id = FindFirstCountry(pt);
return id != kInvalidId ? m_countries[id].m_countryId : kInvalidCountryId;
}
+bool CountryInfoGetterBase::IsBelongToRegions(m2::PointD const & pt,
+ TRegionIdSet const & regions) const
+{
+ for (auto const & id : regions)
+ {
+ if (m_countries[id].m_rect.IsPointInside(pt) && IsBelongToRegionImpl(id, pt))
+ return true;
+ }
+ return false;
+}
+
+bool CountryInfoGetterBase::IsBelongToRegions(TCountryId const & countryId,
+ TRegionIdSet const & regions) const
+{
+ for (auto const & id : regions)
+ {
+ if (m_countries[id].m_countryId == countryId)
+ return true;
+ }
+ return false;
+}
+
+void CountryInfoGetterBase::RegionIdsToCountryIds(TRegionIdSet const & regions,
+ TCountriesVec & countries) const
+{
+ for (auto const & id : regions)
+ countries.push_back(m_countries[id].m_countryId);
+}
+
+CountryInfoGetterBase::TRegionId CountryInfoGetterBase::FindFirstCountry(m2::PointD const & pt) const
+{
+ for (size_t id = 0; id < m_countries.size(); ++id)
+ {
+ if (m_countries[id].m_rect.IsPointInside(pt) && IsBelongToRegionImpl(id, pt))
+ return id;
+ }
+
+ ms::LatLon const latLon = MercatorBounds::ToLatLon(pt);
+ alohalytics::LogEvent(m_isSingleMwm
+ ? "Small mwm case. CountryInfoGetter could not find any mwm by point."
+ : "Big mwm case. CountryInfoGetter could not find any mwm by point.",
+ alohalytics::Location::FromLatLon(latLon.lat, latLon.lon));
+ return kInvalidId;
+}
+
+// CountryInfoGetter -------------------------------------------------------------------------------
vector<TCountryId> CountryInfoGetter::GetRegionsCountryIdByRect(m2::RectD const & rect, bool rough) const
{
size_t constexpr kAverageSize = 10;
@@ -149,52 +195,12 @@ void CountryInfoGetter::GetMatchedRegions(string const & affiliation, TRegionIdS
regions.push_back(i);
}
}
-
-bool CountryInfoGetter::IsBelongToRegions(m2::PointD const & pt, TRegionIdSet const & regions) const
-{
- for (auto const & id : regions)
- {
- if (m_countries[id].m_rect.IsPointInside(pt) && IsBelongToRegionImpl(id, pt))
- return true;
- }
- return false;
-}
-
-bool CountryInfoGetter::IsBelongToRegions(TCountryId const & countryId, TRegionIdSet const & regions) const
-{
- for (auto const & id : regions)
- {
- if (m_countries[id].m_countryId == countryId)
- return true;
- }
- return false;
-}
-
-void CountryInfoGetter::RegionIdsToCountryIds(TRegionIdSet const & regions, TCountriesVec & countries) const
-{
- for (auto const & id : regions)
- countries.push_back(m_countries[id].m_countryId);
-}
void CountryInfoGetter::InitAffiliationsInfo(TMappingAffiliations const * affiliations)
{
m_affiliations = affiliations;
}
-CountryInfoGetter::TRegionId CountryInfoGetter::FindFirstCountry(m2::PointD const & pt) const
-{
- for (size_t id = 0; id < m_countries.size(); ++id)
- {
- if (m_countries[id].m_rect.IsPointInside(pt) && IsBelongToRegionImpl(id, pt))
- return id;
- }
-
- ms::LatLon const latLon = MercatorBounds::ToLatLon(pt);
- alohalytics::LogEvent(m_isSingleMwm ? "Small mwm case. CountryInfoGetter could not find any mwm by point."
- : "Big mwm case. CountryInfoGetter could not find any mwm by point.",
- alohalytics::Location::FromLatLon(latLon.lat, latLon.lon));
- return kInvalidId;
-}
template <typename ToDo>
void CountryInfoGetter::ForEachCountry(string const & prefix, ToDo && toDo) const
diff --git a/storage/country_info_getter.hpp b/storage/country_info_getter.hpp
index a53af3fed1..c3b1069d91 100644
--- a/storage/country_info_getter.hpp
+++ b/storage/country_info_getter.hpp
@@ -20,25 +20,57 @@
namespace storage
{
-// This class allows users to get information about country by point
-// or by name.
-//
-// *NOTE* This class is thread-safe.
-class CountryInfoGetter
+class CountryInfoGetterBase
{
public:
// Identifier of a region (index in m_countries array).
using TRegionId = size_t;
using TRegionIdSet = std::vector<TRegionId>;
- CountryInfoGetter(bool isSingleMwm) : m_isSingleMwm(isSingleMwm) {}
- virtual ~CountryInfoGetter() = default;
+ CountryInfoGetterBase(bool isSingleMwm) : m_isSingleMwm(isSingleMwm) {}
+ virtual ~CountryInfoGetterBase() = default;
// Returns country file name without an extension for a country |pt|
// belongs to. If there is no such country, returns an empty
// string.
TCountryId GetRegionCountryId(m2::PointD const & pt) const;
+ // Returns true when |pt| belongs to at least one of the specified
+ // |regions|.
+ bool IsBelongToRegions(m2::PointD const & pt, TRegionIdSet const & regions) const;
+
+ // Returns true if there're at least one region with id equals to
+ // |countryId|.
+ bool IsBelongToRegions(TCountryId const & countryId, TRegionIdSet const & regions) const;
+
+ void RegionIdsToCountryIds(TRegionIdSet const & regions, TCountriesVec & countries) const;
+
+protected:
+ // Returns identifier of a first country containing |pt|.
+ TRegionId FindFirstCountry(m2::PointD const & pt) const;
+
+ // Returns true when |pt| belongs to a country identified by |id|.
+ virtual bool IsBelongToRegionImpl(size_t id, m2::PointD const & pt) const = 0;
+
+ // @TODO(bykoianko): consider to get rid of m_countryIndex.
+ // The possibility should be considered.
+ // List of all known countries.
+ std::vector<CountryDef> m_countries;
+ // m_isSingleMwm == true if the system is currently working with single (small) mwms
+ // and false otherwise.
+ // @TODO(bykoianko) Init m_isSingleMwm correctly.
+ bool m_isSingleMwm;
+};
+
+// This class allows users to get information about country by point
+// or by name.
+//
+// *NOTE* This class is thread-safe.
+class CountryInfoGetter : public CountryInfoGetterBase
+{
+public:
+ CountryInfoGetter(bool isSingleMwm) : CountryInfoGetterBase(isSingleMwm) {}
+
// Returns vector of countries file names without an extension for
// countries belong to |rect|. |rough| provides fast rough result
// or a slower but more precise one.
@@ -73,27 +105,13 @@ public:
// Returns identifiers for all regions matching to correspondent |affiliation|.
virtual void GetMatchedRegions(string const & affiliation, TRegionIdSet & regions) const;
- // Returns true when |pt| belongs to at least one of the specified
- // |regions|.
- bool IsBelongToRegions(m2::PointD const & pt, TRegionIdSet const & regions) const;
-
- // Returns true if there're at least one region with id equals to
- // |countryId|.
- bool IsBelongToRegions(TCountryId const & countryId, TRegionIdSet const & regions) const;
-
- void RegionIdsToCountryIds(TRegionIdSet const & regions, TCountriesVec & countries) const;
-
// Clears regions cache.
inline void ClearCaches() const { ClearCachesImpl(); }
void InitAffiliationsInfo(TMappingAffiliations const * affiliations);
protected:
- CountryInfoGetter() = default;
-
- // Returns identifier of a first country containing |pt|.
- TRegionId FindFirstCountry(m2::PointD const & pt) const;
-
+ CountryInfoGetter() : CountryInfoGetterBase(true) {};
// Invokes |toDo| on each country whose name starts with |prefix|.
template <typename ToDo>
void ForEachCountry(string const & prefix, ToDo && toDo) const;
@@ -101,19 +119,11 @@ protected:
// Clears regions cache.
virtual void ClearCachesImpl() const = 0;
- // 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;
-
- // @TODO(bykoianko): consider to get rid of m_countryIndex.
- // The possibility should be considered.
- // List of all known countries.
- std::vector<CountryDef> m_countries;
// Maps all leaf country id (file names) to their indices in m_countries.
std::unordered_map<TCountryId, TRegionId> m_countryIndex;
@@ -121,11 +131,6 @@ protected:
// Maps country file name without an extension to a country info.
std::map<std::string, CountryInfo> m_id2info;
-
- // m_isSingleMwm == true if the system is currently working with single (small) mwms
- // and false otherwise.
- // @TODO(bykoianko) Init m_isSingleMwm correctly.
- bool m_isSingleMwm;
};
// This class reads info about countries from polygons file and
diff --git a/storage/country_info_reader_light.cpp b/storage/country_info_reader_light.cpp
new file mode 100644
index 0000000000..eb395d1369
--- /dev/null
+++ b/storage/country_info_reader_light.cpp
@@ -0,0 +1,78 @@
+#include "storage/country_info_reader_light.hpp"
+
+#include "storage/country_decl.hpp"
+#include "storage/country_polygon.hpp"
+
+#include "platform/platform.hpp"
+#include "platform/preferred_languages.hpp"
+
+#include "coding/file_name_utils.hpp"
+#include "coding/file_reader.hpp"
+#include "coding/geometry_coding.hpp"
+#include "coding/read_write_utils.hpp"
+
+#include "geometry/region2d.hpp"
+
+#include "base/logging.hpp"
+#include "base/string_utils.hpp"
+
+#include <chrono>
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace lightweight
+{
+CountryInfoReader::CountryInfoReader()
+ : CountryInfoGetterBase(true)
+{
+ try
+ {
+ m_reader = std::make_unique<FilesContainerR>(GetPlatform().GetReader(PACKED_POLYGONS_FILE));
+ ReaderSource<ModelReaderPtr> src(m_reader->GetReader(PACKED_POLYGONS_INFO_TAG));
+ rw::Read(src, m_countries);
+ }
+ catch (FileReader::Exception const & exception)
+ {
+ LOG(LERROR,
+ ("Exception while reading file:", PACKED_POLYGONS_FILE, "reason:", exception.what()));
+
+ m_reader.reset();
+ m_countries.clear();
+ }
+
+ m_nameGetter.SetLocale(languages::GetCurrentTwine());
+}
+
+bool CountryInfoReader::IsBelongToRegionImpl(size_t id, m2::PointD const & pt) const
+{
+ // Load regions from file.
+ ReaderSource<ModelReaderPtr> src(m_reader->GetReader(strings::to_string(id)));
+
+ uint32_t const count = ReadVarUint<uint32_t>(src);
+ std::vector<m2::RegionD> regions;
+
+ for (size_t i = 0; i < count; ++i)
+ {
+ std::vector<m2::PointD> points;
+ serial::LoadOuterPath(src, serial::GeometryCodingParams(), points);
+ regions.emplace_back(move(points));
+ }
+
+ for (auto const & region : regions)
+ {
+ if (region.Contains(pt))
+ return true;
+ }
+
+ return false;
+}
+
+CountryInfoReader::Info CountryInfoReader::GetMwmInfo(m2::PointD const & pt) const
+{
+ Info info;
+ info.m_id = GetRegionCountryId(pt);
+ info.m_name = m_nameGetter(info.m_id);
+ return info;
+}
+} // namespace lightweight
diff --git a/storage/country_info_reader_light.hpp b/storage/country_info_reader_light.hpp
new file mode 100644
index 0000000000..a171b26be8
--- /dev/null
+++ b/storage/country_info_reader_light.hpp
@@ -0,0 +1,36 @@
+#pragma once
+
+#include "storage/index.hpp"
+#include "storage/country_info_getter.hpp"
+#include "storage/country_name_getter.hpp"
+
+#include "coding/file_container.hpp"
+
+#include "geometry/point2d.hpp"
+
+#include <cstdint>
+#include <memory>
+
+namespace lightweight
+{
+// Protected inheritance for test purposes only.
+class CountryInfoReader : protected storage::CountryInfoGetterBase
+{
+public:
+ struct Info
+ {
+ storage::TCountryId m_id;
+ std::string m_name;
+ };
+
+ CountryInfoReader();
+ Info GetMwmInfo(m2::PointD const & pt) const;
+
+protected:
+ bool IsBelongToRegionImpl(size_t id, m2::PointD const & pt) const override;
+
+private:
+ std::unique_ptr<FilesContainerR> m_reader;
+ storage::CountryNameGetter m_nameGetter;
+};
+} // namespace lightweight
diff --git a/storage/storage_integration_tests/CMakeLists.txt b/storage/storage_integration_tests/CMakeLists.txt
index 59eb9320fc..6d0ccda436 100644
--- a/storage/storage_integration_tests/CMakeLists.txt
+++ b/storage/storage_integration_tests/CMakeLists.txt
@@ -5,6 +5,7 @@ add_definitions("-DOMIM_UNIT_TEST_WITH_QT_EVENT_LOOP")
set(
SRC
+ lightweight_matching_tests.cpp
migrate_tests.cpp
storage_3levels_tests.cpp
storage_downloading_tests.cpp
diff --git a/storage/storage_integration_tests/lightweight_matching_tests.cpp b/storage/storage_integration_tests/lightweight_matching_tests.cpp
new file mode 100644
index 0000000000..3ed2aa0135
--- /dev/null
+++ b/storage/storage_integration_tests/lightweight_matching_tests.cpp
@@ -0,0 +1,58 @@
+#include "testing/testing.hpp"
+
+#include "storage/country_info_reader_light.hpp"
+#include "storage/index.hpp"
+
+#include "geometry/mercator.hpp"
+#include "geometry/point2d.hpp"
+
+#include <utility>
+#include <vector>
+
+using namespace lightweight;
+
+namespace
+{
+double constexpr kStepInMercator = 1; // 1 mercator ~= 9602.84 meters
+
+struct PointAndCountry
+{
+ PointAndCountry(m2::PointD && pt, storage::TCountryId && country)
+ : m_pt(std::move(pt))
+ , m_country(std::move(country))
+ {
+ }
+
+ m2::PointD m_pt;
+ storage::TCountryId m_country;
+};
+
+UNIT_CLASS_TEST(CountryInfoReader, LightweightMatching)
+{
+ auto const reader = storage::CountryInfoReader::CreateCountryInfoReader(GetPlatform());
+
+ LOG(LINFO, ("Generating dataset..."));
+ std::vector<PointAndCountry> dataset;
+ for (auto x = MercatorBounds::minX; x <= MercatorBounds::maxX; x += kStepInMercator)
+ {
+ for (auto y = MercatorBounds::minY; y <= MercatorBounds::maxY; y += kStepInMercator)
+ {
+ m2::PointD pt(x, y);
+ dataset.emplace_back(std::move(pt), reader->GetRegionCountryId(pt));
+ }
+ }
+
+ {
+ m2::PointD ptFrom = {MercatorBounds::minX, MercatorBounds::minY};
+ m2::PointD ptTo = {MercatorBounds::minX + kStepInMercator, MercatorBounds::minY};
+ auto const stepSizeInMeters = MercatorBounds::DistanceOnEarth(ptFrom, ptTo);
+ LOG(LINFO, ("The dataset is generated. Dataset size:", dataset.size(),
+ ". The step is:", stepSizeInMeters, "meters"));
+ }
+
+ for (auto const & sample : dataset)
+ {
+ TEST_EQUAL(GetRegionCountryId(sample.m_pt), sample.m_country, (sample.m_pt));
+ }
+}
+} // namespace