diff --git a/3party/osrm/osrm-backend/CMakeLists.txt b/3party/osrm/osrm-backend/CMakeLists.txt index 0e7b04a733..a626911bc9 100644 --- a/3party/osrm/osrm-backend/CMakeLists.txt +++ b/3party/osrm/osrm-backend/CMakeLists.txt @@ -33,6 +33,7 @@ OPTION(WITH_TOOLS "Build OSRM tools" OFF) OPTION(BUILD_TOOLS "Build OSRM tools" OFF) include_directories(${CMAKE_SOURCE_DIR}/Include/) +include_directories(${CMAKE_SOURCE_DIR}/../../jansson/src/) add_custom_target(FingerPrintConfigure ALL ${CMAKE_COMMAND} -DSOURCE_DIR=${CMAKE_SOURCE_DIR} @@ -72,7 +73,7 @@ file(GLOB LibOSRMGlob Library/*.cpp) file(GLOB MapsMeSources mapsme/*.cpp) file(GLOB MapsMeHeaders mapsme/*.h) -file(GLOB MapsMeGenerator ../../../generator/country_loader.cpp) +file(GLOB MapsMeGenerator ../../../storage/country.cpp ../../../storage/country_decl.cpp ../../../storage/country_info.cpp) set( OSRMSources @@ -190,11 +191,13 @@ target_link_libraries(osrm-prepare ${Boost_LIBRARIES}) target_link_libraries(osrm-routed ${Boost_LIBRARIES} ${OPTIONAL_SOCKET_LIBS} OSRM debug "${CMAKE_SOURCE_DIR}/../../../../omim-build-debug/out/debug/libcoding.a" "${CMAKE_SOURCE_DIR}/../../../../omim-build-debug/out/debug/libbase.a" - "${CMAKE_SOURCE_DIR}/../../../../omim-build-debug/out/debug/libindexer.a" "${CMAKE_SOURCE_DIR}/../../../../omim-build-debug/out/debug/libgeometry.a" + "${CMAKE_SOURCE_DIR}/../../../../omim-build-debug/out/debug/libindexer.a" + "${CMAKE_SOURCE_DIR}/../../../../omim-build-debug/out/debug/libjansson.a" general "${CMAKE_SOURCE_DIR}/../../../../omim-build-release/out/release/libcoding.a" - "${CMAKE_SOURCE_DIR}/../../../../omim-build-release/out/release/libindexer.a" "${CMAKE_SOURCE_DIR}/../../../../omim-build-release/out/release/libgeometry.a" + "${CMAKE_SOURCE_DIR}/../../../../omim-build-release/out/release/libindexer.a" + "${CMAKE_SOURCE_DIR}/../../../../omim-build-release/out/release/libjansson.a" "${CMAKE_SOURCE_DIR}/../../../../omim-build-release/out/release/libbase.a") target_link_libraries(osrm-datastore ${Boost_LIBRARIES}) diff --git a/3party/osrm/osrm-backend/Plugins/MapsMePlugin.h b/3party/osrm/osrm-backend/Plugins/MapsMePlugin.h index 5a9eea6cfd..187be39e25 100644 --- a/3party/osrm/osrm-backend/Plugins/MapsMePlugin.h +++ b/3party/osrm/osrm-backend/Plugins/MapsMePlugin.h @@ -19,17 +19,84 @@ #include #include -#include "../../../../generator/country_loader.hpp" +#include "../../../../base/string_utils.hpp" +#include "../../../../coding/file_container.hpp" +#include "../../../../coding/read_write_utils.hpp" +#include "../../../../defines.hpp" +#include "../../../../geometry/region2d.hpp" +#include "../../../../indexer/geometry_serialization.hpp" #include "../../../../indexer/mercator.hpp" +#include "../../../../storage/country_decl.hpp" +#include "../../../../storage/country_polygon.hpp" template class MapsMePlugin final : public BasePlugin { - public: - explicit MapsMePlugin(DataFacadeT *facade, std::string const & baseDir) : descriptor_string("mapsme"), facade(facade) + class GetByPoint { + m2::PointD const & m_pt; + std::vector > const & m_regions; + + public: + size_t m_res; + + GetByPoint(std::vector > const & regions, m2::PointD const & pt) + : m_pt(pt), m_regions(regions), m_res(-1) + { + } + + /// @param[in] id Index in m_countries. + /// @return false If point is in country. + bool operator() (size_t id) + { + + std::vector const & rgnV = m_regions[id]; + for (size_t i = 0; i < rgnV.size(); ++i) + { + if (rgnV[i].Contains(m_pt)) + { + m_res = id; + return false; + } + } + return true; + } + }; + +public: + explicit MapsMePlugin(DataFacadeT *facade, std::string const & baseDir) : descriptor_string("mapsme"), facade(facade), + m_reader(baseDir + '/' + PACKED_POLYGONS_FILE) + { + ReaderSource src(m_reader.GetReader(PACKED_POLYGONS_INFO_TAG)); + rw::Read(src, m_countries); + m_regions.resize(m_countries.size()); + for (size_t i = 0; i < m_countries.size(); ++i) + { + std::vector & rgnV = m_regions[i]; + + // load regions from file + ReaderSource src(m_reader.GetReader(strings::to_string(i))); + + uint32_t const count = ReadVarUint(src); + for (size_t j = 0; j < count; ++j) + { + vector points; + serial::LoadOuterPath(src, serial::CodingParams(), points); + + rgnV.push_back(m2::RegionD()); + rgnV.back().Assign(points.begin(), points.end()); + } + + } search_engine_ptr = osrm::make_unique>(facade); - CHECK(borders::LoadCountriesList(baseDir, m_countries), - ("Error loading country polygons files")); + } + + template + void ForEachCountry(m2::PointD const & pt, ToDo & toDo) const + { + for (size_t i = 0; i < m_countries.size(); ++i) + if (m_countries[i].m_rect.IsPointInside(pt)) + if (!toDo(i)) + return; } virtual ~MapsMePlugin() {} @@ -109,20 +176,13 @@ template class MapsMePlugin final : public BasePlugin { PathData const & path_data = raw_route.unpacked_path_segments[i][j]; FixedPointCoordinate const coord = facade->GetCoordinateOfNode(path_data.node); - string mwmName; - m2::PointD mercatorPoint(MercatorBounds::LonToX(coord.lon/1000000.0), MercatorBounds::LatToY(coord.lat/1000000.0)); - m_countries.ForEachInRect(m2::RectD(mercatorPoint, mercatorPoint), [&](borders::CountryPolygons const & c) - { - bool inside = false; - c.m_regions.ForEachInRect(m2::RectD(mercatorPoint, mercatorPoint), [&](m2::RegionD const & region) - { - if (region.Contains(mercatorPoint)) - inside = true; - }); - if (inside) - mwmName = c.m_name; - }); - usedMwms.insert(mwmName); + storage::CountryInfo info; + m2::PointD pt = MercatorBounds::FromLatLon(coord.lat/1000000.0, coord.lon/1000000.0); + GetByPoint doGet(m_regions, pt); + ForEachCountry(pt, doGet); + + if (doGet.m_res != -1) + usedMwms.insert(m_countries[doGet.m_res].m_name); } } @@ -135,7 +195,9 @@ template class MapsMePlugin final : public BasePlugin private: std::unique_ptr> search_engine_ptr; - borders::CountriesContainerT m_countries; + std::vector m_countries; + std::vector> m_regions; std::string descriptor_string; DataFacadeT *facade; + FilesContainerR m_reader; }; diff --git a/generator/borders_generator.cpp b/generator/borders_generator.cpp index 706c9cbd44..05d14e07bb 100644 --- a/generator/borders_generator.cpp +++ b/generator/borders_generator.cpp @@ -10,4 +10,57 @@ namespace osm { + bool ReadPolygon(istream & stream, m2::RegionD & region, string const & filename) + { + string line, name; + double lon, lat; + + // read ring id, fail if it's empty + getline(stream, name); + if (name.empty() || name == "END") + return false; + + while (stream.good()) + { + getline(stream, line); + strings::Trim(line); + + if (line.empty()) + continue; + + if (line == "END") + break; + + istringstream iss(line); + iss >> lon >> lat; + CHECK(!iss.fail(), ("Incorrect data in", filename)); + + region.AddPoint(MercatorBounds::FromLatLon(lat, lon)); + } + + // drop inner rings + return name[0] != '!'; } + + bool LoadBorders(string const & borderFile, vector & outBorders) + { + ifstream stream(borderFile); + string line; + if (!getline(stream, line).good()) // skip title + { + LOG(LERROR, ("Polygon file is empty:", borderFile)); + return false; + } + + m2::RegionD currentRegion; + while (ReadPolygon(stream, currentRegion, borderFile)) + { + CHECK(currentRegion.IsValid(), ("Invalid region in", borderFile)); + outBorders.push_back(currentRegion); + currentRegion = m2::RegionD(); + } + + CHECK(!outBorders.empty(), ("No borders were loaded from", borderFile)); + return true; + } +} diff --git a/generator/borders_generator.hpp b/generator/borders_generator.hpp index 2dda47ccc2..297973dcb3 100644 --- a/generator/borders_generator.hpp +++ b/generator/borders_generator.hpp @@ -8,6 +8,6 @@ namespace osm { - void GenerateBordersFromOsm(string const & tagAndOptValue, string const & osmFile, - string const & outFile); + /// @return false if borderFile can't be opened + bool LoadBorders(string const & borderFile, vector & outBorders); } diff --git a/generator/borders_loader.cpp b/generator/borders_loader.cpp index 767fff56d2..4d4c213024 100644 --- a/generator/borders_loader.cpp +++ b/generator/borders_loader.cpp @@ -22,9 +22,87 @@ #include "../std/vector.hpp" #include "../std/bind.hpp" + +#define POLYGONS_FILE "polygons.lst" + + namespace borders { +class PolygonLoader +{ + CountryPolygons m_polygons; + m2::RectD m_rect; + + string const & m_baseDir; + CountriesContainerT & m_countries; + +public: + PolygonLoader(string const & baseDir, CountriesContainerT & countries) + : m_baseDir(baseDir), m_countries(countries) {} + + void operator() (string const & name) + { + if (m_polygons.m_name.empty()) + m_polygons.m_name = name; + + vector borders; + if (osm::LoadBorders(m_baseDir + BORDERS_DIR + name + BORDERS_EXTENSION, borders)) + { + for (size_t i = 0; i < borders.size(); ++i) + { + m2::RectD const rect(borders[i].GetRect()); + m_rect.Add(rect); + m_polygons.m_regions.Add(borders[i], rect); + } + } + } + + void Finish() + { + if (!m_polygons.IsEmpty()) + { + ASSERT_NOT_EQUAL ( m_rect, m2::RectD::GetEmptyRect(), () ); + m_countries.Add(m_polygons, m_rect); + } + + m_polygons.Clear(); + m_rect.MakeEmpty(); + } +}; + +template +void ForEachCountry(string const & baseDir, ToDo & toDo) +{ + ifstream stream((baseDir + POLYGONS_FILE).c_str()); + string line; + + while (stream.good()) + { + std::getline(stream, line); + if (line.empty()) + continue; + + // in polygons file every country is a separate string + toDo(line); + toDo.Finish(); + } +} + +bool LoadCountriesList(string const & baseDir, CountriesContainerT & countries) +{ + countries.Clear(); + + LOG(LINFO, ("Loading countries.")); + + PolygonLoader loader(baseDir, countries); + ForEachCountry(baseDir, loader); + + LOG(LINFO, ("Countries loaded:", countries.GetSize())); + + return !countries.IsEmpty(); +} + class PackedBordersGenerator { FilesContainerW m_writer; @@ -41,7 +119,7 @@ public: void operator() (string const & name) { vector borders; - if (borders::LoadBorders(m_baseDir + BORDERS_DIR + name + BORDERS_EXTENSION, borders)) + if (osm::LoadBorders(m_baseDir + BORDERS_DIR + name + BORDERS_EXTENSION, borders)) { // use index in vector as tag FileWriter w = m_writer.GetWriter(strings::to_string(m_polys.size())); diff --git a/generator/borders_loader.hpp b/generator/borders_loader.hpp index 4b049b814d..bd94520d5d 100644 --- a/generator/borders_loader.hpp +++ b/generator/borders_loader.hpp @@ -5,9 +5,34 @@ #include "../std/string.hpp" -#include "country_loader.hpp" +#define BORDERS_DIR "borders/" +#define BORDERS_EXTENSION ".poly" namespace borders { + typedef m2::RegionD Region; + typedef m4::Tree RegionsContainerT; + + struct CountryPolygons + { + CountryPolygons(string const & name = "") : m_name(name), m_index(-1) {} + + bool IsEmpty() const { return m_regions.IsEmpty(); } + void Clear() + { + m_regions.Clear(); + m_name.clear(); + m_index = -1; + } + + RegionsContainerT m_regions; + string m_name; + mutable int m_index; + }; + + typedef m4::Tree CountriesContainerT; + + bool LoadCountriesList(string const & baseDir, CountriesContainerT & countries); + void GeneratePackedBorders(string const & baseDir); } diff --git a/generator/country_loader.cpp b/generator/country_loader.cpp deleted file mode 100644 index 9ec1810380..0000000000 --- a/generator/country_loader.cpp +++ /dev/null @@ -1,126 +0,0 @@ -#include "country_loader.hpp" - -#include "../base/std_serialization.hpp" -#include "../base/logging.hpp" - -#include "../coding/file_reader.hpp" -#include "../coding/streams_sink.hpp" - -namespace borders -{ -bool ReadPolygon(istream & stream, m2::RegionD & region, string const & filename) -{ - string line, name; - double lon, lat; - - // read ring id, fail if it's empty - getline(stream, name); - if (name.empty() || name == "END") - return false; - - while (stream.good()) - { - getline(stream, line); - strings::Trim(line); - - if (line.empty()) - continue; - - if (line == "END") - break; - - istringstream iss(line); - iss >> lon >> lat; - CHECK(!iss.fail(), ("Incorrect data in", filename)); - - region.AddPoint(MercatorBounds::FromLatLon(lat, lon)); - } - - // drop inner rings - return name[0] != '!'; -} - -bool LoadBorders(string const & borderFile, vector & outBorders) -{ - ifstream stream(borderFile); - string line; - if (!getline(stream, line).good()) // skip title - { - FileReader file(borderFile); - ReaderSource source(file); - stream::SinkReaderStream > stream(source); - - stream >> outBorders; - CHECK(!outBorders.empty(), ("Borders weren't loaded from", borderFile)); - } - - m2::RegionD currentRegion; - while (ReadPolygon(stream, currentRegion, borderFile)) - { - CHECK(currentRegion.IsValid(), ("Invalid region in", borderFile)); - outBorders.push_back(currentRegion); - currentRegion = m2::RegionD(); - } - - CHECK(!outBorders.empty(), ("No borders were loaded from", borderFile)); - return true; -} - -class PolygonLoader -{ -public: - PolygonLoader(string const & baseDir, CountriesContainerT & countries) - : m_baseDir(baseDir), m_countries(countries) {} - - void operator() (string const & name) - { - if (m_polygons.m_name.empty()) - m_polygons.m_name = name; - - vector borders; - if (LoadBorders(m_baseDir + BORDERS_DIR + name + BORDERS_EXTENSION, borders)) - { - for (auto const & border : borders) - { - m2::RectD const rect(border.GetRect()); - m_rect.Add(rect); - m_polygons.m_regions.Add(border, rect); - } - } - } - - void Finish() - { - if (!m_polygons.IsEmpty()) - { - ASSERT_NOT_EQUAL ( m_rect, m2::RectD::GetEmptyRect(), () ); - m_countries.Add(m_polygons, m_rect); - } - - m_polygons.Clear(); - m_rect.MakeEmpty(); - } - -private: - CountryPolygons m_polygons; - m2::RectD m_rect; - - string const & m_baseDir; - CountriesContainerT & m_countries; -}; - -bool LoadCountriesList(string const & baseDir, CountriesContainerT & countries) -{ - countries.Clear(); - - LOG(LINFO, ("Loading countries...")); - - PolygonLoader loader(baseDir, countries); - ForEachCountry(baseDir, loader); - - LOG(LINFO, ("Countries loaded:", countries.GetSize())); - - return !countries.IsEmpty(); -} - -} diff --git a/generator/country_loader.hpp b/generator/country_loader.hpp deleted file mode 100644 index 1e56528021..0000000000 --- a/generator/country_loader.hpp +++ /dev/null @@ -1,59 +0,0 @@ -#pragma once - -#include "../geometry/region2d.hpp" -#include "../geometry/tree4d.hpp" - -#include "../std/fstream.hpp" -#include "../std/string.hpp" - -#define BORDERS_DIR "borders/" -#define BORDERS_EXTENSION ".poly" -#define POLYGONS_FILE "polygons.lst" - -namespace borders -{ - typedef m2::RegionD Region; - typedef m4::Tree RegionsContainerT; - - struct CountryPolygons - { - CountryPolygons(string const & name = "") : m_name(name), m_index(-1) {} - - bool IsEmpty() const { return m_regions.IsEmpty(); } - void Clear() - { - m_regions.Clear(); - m_name.clear(); - m_index = -1; - } - - RegionsContainerT m_regions; - string m_name; - mutable int m_index; - }; - - typedef m4::Tree CountriesContainerT; - - /// @return false if borderFile can't be opened - bool LoadBorders(string const & borderFile, vector & outBorders); - - bool LoadCountriesList(string const & baseDir, CountriesContainerT & countries); - - template - void ForEachCountry(string const & baseDir, ToDo & toDo) - { - ifstream stream((baseDir + POLYGONS_FILE).c_str()); - string line; - - while (stream.good()) - { - std::getline(stream, line); - if (line.empty()) - continue; - - // in polygons file every country is a separate string - toDo(line); - toDo.Finish(); - } - } -} diff --git a/generator/generator.pro b/generator/generator.pro index 1a48c3a705..88fce5be2f 100644 --- a/generator/generator.pro +++ b/generator/generator.pro @@ -34,7 +34,6 @@ SOURCES += \ tesselator.cpp \ check_model.cpp \ routing_generator.cpp \ - country_loader.cpp \ HEADERS += \ feature_merger.hpp \ @@ -65,4 +64,3 @@ HEADERS += \ ways_merger.hpp \ gen_mwm_info.hpp \ routing_generator.hpp \ - country_loader.hpp \ diff --git a/generator/generator_tests/osm_parser_test.cpp b/generator/generator_tests/osm_parser_test.cpp index c39b9f9852..0bd29e072b 100644 --- a/generator/generator_tests/osm_parser_test.cpp +++ b/generator/generator_tests/osm_parser_test.cpp @@ -2,7 +2,6 @@ #include "../osm_xml_parser.hpp" #include "../borders_generator.hpp" -#include "../country_loader.hpp" #include "../../coding/reader.hpp" #include "../../coding/parse_xml.hpp" @@ -10,7 +9,6 @@ #include "../../coding/file_writer.hpp" using namespace osm; -using namespace borders; static char const gOsmXml[] = ""