From c405cd20ba45f3d2e213b3f80794629fcfffcc86 Mon Sep 17 00:00:00 2001 From: Maxim Pimenov Date: Wed, 11 Jul 2018 11:57:36 +0300 Subject: [PATCH] [geocoder] Forward geocoder stub. --- CMakeLists.txt | 1 + geocoder/CMakeLists.txt | 15 +++++++++ geocoder/geocoder.cpp | 26 +++++++++++++++ geocoder/geocoder.hpp | 38 +++++++++++++++++++++ geocoder/geocoder_tests/CMakeLists.txt | 20 +++++++++++ geocoder/geocoder_tests/geocoder_tests.cpp | 39 ++++++++++++++++++++++ geocoder/hierarchy.cpp | 13 ++++++++ geocoder/hierarchy.hpp | 12 +++++++ geocoder/result.cpp | 15 +++++++++ geocoder/result.hpp | 25 ++++++++++++++ 10 files changed, 204 insertions(+) create mode 100644 geocoder/CMakeLists.txt create mode 100644 geocoder/geocoder.cpp create mode 100644 geocoder/geocoder.hpp create mode 100644 geocoder/geocoder_tests/CMakeLists.txt create mode 100644 geocoder/geocoder_tests/geocoder_tests.cpp create mode 100644 geocoder/hierarchy.cpp create mode 100644 geocoder/hierarchy.hpp create mode 100644 geocoder/result.cpp create mode 100644 geocoder/result.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f27cc568c..351d31f4dc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -272,6 +272,7 @@ add_subdirectory(drape) add_subdirectory(drape_frontend) add_subdirectory(editor) add_subdirectory(generator/mwm_diff) +add_subdirectory(geocoder) add_subdirectory(geometry) add_subdirectory(indexer) add_subdirectory(kml) diff --git a/geocoder/CMakeLists.txt b/geocoder/CMakeLists.txt new file mode 100644 index 0000000000..af3397f95c --- /dev/null +++ b/geocoder/CMakeLists.txt @@ -0,0 +1,15 @@ +project(geocoder) + +set( + SRC + geocoder.cpp + geocoder.hpp + hierarchy.cpp + hierarchy.hpp + result.cpp + result.hpp +) + +omim_add_library(${PROJECT_NAME} ${SRC}) + +omim_add_test_subdirectory(geocoder_tests) diff --git a/geocoder/geocoder.cpp b/geocoder/geocoder.cpp new file mode 100644 index 0000000000..9c931e9005 --- /dev/null +++ b/geocoder/geocoder.cpp @@ -0,0 +1,26 @@ +#include "geocoder/geocoder.hpp" + +#include "base/osm_id.hpp" + +using namespace std; + +namespace geocoder +{ +Geocoder::Geocoder(string pathToJsonHierarchy) : m_hierarchy(pathToJsonHierarchy) {} + +void Geocoder::ProcessQuery(string const & query, vector & results) const +{ + // Only here for demonstration purposes and will be removed shortly. + results.clear(); + if (query == "a") + { + results.emplace_back(osm::Id(10), 0.5 /* certainty */); + results.emplace_back(osm::Id(11), 1.0 /* certainty */); + } + if (query == "b") + { + results.emplace_back(osm::Id(20), 0.8 /* certainty */); + results.emplace_back(osm::Id(21), 0.1 /* certainty */); + } +} +} // namespace geocoder diff --git a/geocoder/geocoder.hpp b/geocoder/geocoder.hpp new file mode 100644 index 0000000000..eb1614900f --- /dev/null +++ b/geocoder/geocoder.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include "geocoder/hierarchy.hpp" +#include "geocoder/result.hpp" + +#include +#include + +namespace geocoder +{ +// This class performs geocoding by using the data that we are currently unable +// to distribute to mobile devices. Therefore, the class is intended to be used +// on the server side. +// On the other hand, the design is largely experimental and when the dust +// settles we may reuse some parts of it in the offline mobile application. +// In this case, a partial merge with search/ and in particular with +// search/geocoder.hpp is possible. +// +// Geocoder receives a search query and returns the osm ids of the features +// that match it. Currently, the only data source for the geocoder is +// the hierarchy of features, that is, for every feature that can be found +// the geocoder expects to have the total information about this feature +// in the region subdivision graph (e.g., country, city, street that contain a +// certain house). This hierarchy is to be obtained elsewhere. +// +// Note that search index, locality index, scale index, and, generally, mwm +// features are currently not used at all. +class Geocoder +{ +public: + explicit Geocoder(std::string pathToJsonHierarchy); + + void ProcessQuery(std::string const & query, std::vector & results) const; + +private: + Hierarchy m_hierarchy; +}; +} // namespace geocoder diff --git a/geocoder/geocoder_tests/CMakeLists.txt b/geocoder/geocoder_tests/CMakeLists.txt new file mode 100644 index 0000000000..7091fd3de6 --- /dev/null +++ b/geocoder/geocoder_tests/CMakeLists.txt @@ -0,0 +1,20 @@ +project(geocoder_tests) + +set( + SRC + geocoder_tests.cpp +) + +omim_add_test(${PROJECT_NAME} ${SRC}) + +omim_link_libraries( + ${PROJECT_NAME} + geocoder + platform + coding + base + stats_client + ${LIBZ} +) + +link_qt5_core(${PROJECT_NAME}) diff --git a/geocoder/geocoder_tests/geocoder_tests.cpp b/geocoder/geocoder_tests/geocoder_tests.cpp new file mode 100644 index 0000000000..90be70115b --- /dev/null +++ b/geocoder/geocoder_tests/geocoder_tests.cpp @@ -0,0 +1,39 @@ +#include "testing/testing.hpp" + +#include "geocoder/geocoder.hpp" + +#include "base/logging.hpp" +#include "base/math.hpp" + +#include +#include + +using namespace std; + +namespace +{ +double const kCertaintyEps = 1e-6; +} // namespace + +namespace geocoder +{ +void TestGeocoder(Geocoder const & geocoder, string const & query, vector const & expected) +{ + vector actual; + geocoder.ProcessQuery(query, actual); + TEST_EQUAL(actual.size(), expected.size(), ()); + for (size_t i = 0; i < actual.size(); ++i) + { + TEST_EQUAL(actual[i].m_osmId, expected[i].m_osmId, ()); + TEST(my::AlmostEqualAbs(actual[i].m_certainty, expected[i].m_certainty, kCertaintyEps), ()); + } +} + +UNIT_TEST(Geocoder_Smoke) +{ + Geocoder geocoder("" /* pathToJsonHierarchy */); + + TestGeocoder(geocoder, "a", {{osm::Id(10), 0.5}, {osm::Id(11), 1.0}}); + TestGeocoder(geocoder, "b", {{osm::Id(20), 0.8}, {osm::Id(21), 0.1}}); +} +} // namespace geocoder diff --git a/geocoder/hierarchy.cpp b/geocoder/hierarchy.cpp new file mode 100644 index 0000000000..8138cfa090 --- /dev/null +++ b/geocoder/hierarchy.cpp @@ -0,0 +1,13 @@ +#include "geocoder/hierarchy.hpp" + +#include "base/macros.hpp" + +using namespace std; + +namespace geocoder +{ +Hierarchy::Hierarchy(string const & pathToJsonHierarchy) +{ + UNUSED_VALUE(pathToJsonHierarchy); +} +} // namespace geocoder diff --git a/geocoder/hierarchy.hpp b/geocoder/hierarchy.hpp new file mode 100644 index 0000000000..836998bead --- /dev/null +++ b/geocoder/hierarchy.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include + +namespace geocoder +{ +class Hierarchy +{ +public: + explicit Hierarchy(std::string const & pathToJsonHierarchy); +}; +} // namespace geocoder diff --git a/geocoder/result.cpp b/geocoder/result.cpp new file mode 100644 index 0000000000..fc649754c3 --- /dev/null +++ b/geocoder/result.cpp @@ -0,0 +1,15 @@ +#include "geocoder/result.hpp" + +#include + +using namespace std; + +namespace geocoder +{ +string DebugPrint(Result const & result) +{ + ostringstream oss; + oss << DebugPrint(result.m_osmId) << " " << result.m_certainty; + return oss.str(); +} +} // namespace geocoder diff --git a/geocoder/result.hpp b/geocoder/result.hpp new file mode 100644 index 0000000000..ae0904b595 --- /dev/null +++ b/geocoder/result.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include "base/osm_id.hpp" + +#include + +namespace geocoder +{ +struct Result +{ + Result(osm::Id const & osmId, double certainty) : m_osmId(osmId), m_certainty(certainty) {} + + // The encoded osm id of a node, way or relation. + osm::Id m_osmId = osm::Id(osm::Id::kInvalid); + + // A floating point number in the range [0.0, 1.0] + // describing the extent to which the result matches + // the query. + // 0.0 corresponds to the least probable results and + // 1.0 to the most probable. + double m_certainty = 0; +}; + +std::string DebugPrint(Result const & result); +} // namespace geocoder