forked from organicmaps/organicmaps
OSRM plugin for mwm identification
This commit is contained in:
parent
f28135dfe8
commit
62000bcace
11 changed files with 368 additions and 154 deletions
3party/osrm/osrm-backend
generator
|
@ -76,6 +76,7 @@ file(GLOB LibOSRMGlob Library/*.cpp)
|
|||
|
||||
file(GLOB MapsMeSources mapsme/*.cpp)
|
||||
file(GLOB MapsMeHeaders mapsme/*.h)
|
||||
file(GLOB MapsMeGenerator ../../../generator/country_loader.cpp)
|
||||
|
||||
set(
|
||||
OSRMSources
|
||||
|
@ -85,6 +86,7 @@ set(
|
|||
${CoordinateGlob}
|
||||
${AlgorithmGlob}
|
||||
${HttpGlob}
|
||||
${MapsMeGenerator}
|
||||
)
|
||||
add_library(COORDINATE OBJECT ${CoordinateGlob})
|
||||
add_library(FINGERPRINT OBJECT Util/FingerPrint.cpp)
|
||||
|
@ -189,7 +191,15 @@ include_directories(${Boost_INCLUDE_DIRS})
|
|||
target_link_libraries(OSRM ${Boost_LIBRARIES})
|
||||
target_link_libraries(osrm-extract ${Boost_LIBRARIES})
|
||||
target_link_libraries(osrm-prepare ${Boost_LIBRARIES})
|
||||
target_link_libraries(osrm-routed ${Boost_LIBRARIES} ${OPTIONAL_SOCKET_LIBS} OSRM)
|
||||
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"
|
||||
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/libbase.a")
|
||||
target_link_libraries(osrm-datastore ${Boost_LIBRARIES})
|
||||
|
||||
target_link_libraries(osrm-mapsme ${Boost_LIBRARIES} OSRM
|
||||
|
|
|
@ -41,6 +41,7 @@ namespace boost { namespace interprocess { class named_mutex; } }
|
|||
#include "../Plugins/NearestPlugin.h"
|
||||
#include "../Plugins/TimestampPlugin.h"
|
||||
#include "../Plugins/ViaRoutePlugin.h"
|
||||
#include "../Plugins/MapsMePlugin.h"
|
||||
#include "../Server/DataStructures/BaseDataFacade.h"
|
||||
#include "../Server/DataStructures/InternalDataFacade.h"
|
||||
#include "../Server/DataStructures/SharedBarriers.h"
|
||||
|
@ -79,6 +80,7 @@ OSRM_impl::OSRM_impl(ServerPaths server_paths, const bool use_shared_memory)
|
|||
RegisterPlugin(new NearestPlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
|
||||
RegisterPlugin(new TimestampPlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
|
||||
RegisterPlugin(new ViaRoutePlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
|
||||
RegisterPlugin(new MapsMePlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade, "../../../data/"));
|
||||
}
|
||||
|
||||
OSRM_impl::~OSRM_impl()
|
||||
|
|
164
3party/osrm/osrm-backend/Plugins/MapsMePlugin.h
Normal file
164
3party/osrm/osrm-backend/Plugins/MapsMePlugin.h
Normal file
|
@ -0,0 +1,164 @@
|
|||
#pragma once
|
||||
|
||||
#include "BasePlugin.h"
|
||||
|
||||
#include "../Algorithms/ObjectToBase64.h"
|
||||
#include "../DataStructures/JSONContainer.h"
|
||||
#include "../DataStructures/QueryEdge.h"
|
||||
#include "../DataStructures/SearchEngine.h"
|
||||
#include "../Descriptors/BaseDescriptor.h"
|
||||
#include "../Util/make_unique.hpp"
|
||||
#include "../Util/StringUtil.h"
|
||||
#include "../Util/TimingUtil.h"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "../../../../generator/country_loader.hpp"
|
||||
#include "../../../../indexer/mercator.hpp"
|
||||
|
||||
class GetMWMNameByPoint
|
||||
{
|
||||
class CheckPointInBorder
|
||||
{
|
||||
m2::PointD const & m_point;
|
||||
bool & m_inside;
|
||||
public:
|
||||
CheckPointInBorder(m2::PointD const & point, bool & inside) : m_point(point), m_inside(inside) {m_inside=false;}
|
||||
void operator()(m2::RegionD const & region)
|
||||
{
|
||||
if (region.Contains(m_point))
|
||||
m_inside=true;
|
||||
}
|
||||
};
|
||||
|
||||
string & m_name;
|
||||
m2::PointD const & m_point;
|
||||
public:
|
||||
GetMWMNameByPoint(string & name, m2::PointD const & point) : m_name(name), m_point(point) {}
|
||||
void operator() (borders::CountryPolygons const & c)
|
||||
{
|
||||
bool inside;
|
||||
CheckPointInBorder getter(m_point, inside);
|
||||
c.m_regions.ForEachInRect(m2::RectD(m_point, m_point), getter);
|
||||
if (inside)
|
||||
m_name = c.m_name;
|
||||
}
|
||||
};
|
||||
|
||||
template <class DataFacadeT> class MapsMePlugin final : public BasePlugin
|
||||
{
|
||||
private:
|
||||
std::unique_ptr<SearchEngine<DataFacadeT>> search_engine_ptr;
|
||||
borders::CountriesContainerT m_countries;
|
||||
|
||||
public:
|
||||
explicit MapsMePlugin(DataFacadeT *facade, std::string const & baseDir) : descriptor_string("mapsme"), facade(facade)
|
||||
{
|
||||
search_engine_ptr = osrm::make_unique<SearchEngine<DataFacadeT>>(facade);
|
||||
CHECK(borders::LoadCountriesList(baseDir, m_countries),
|
||||
("Error loading country polygons files"));
|
||||
}
|
||||
|
||||
virtual ~MapsMePlugin() {}
|
||||
|
||||
const std::string GetDescriptor() const final { return descriptor_string; }
|
||||
|
||||
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply) final
|
||||
{
|
||||
// check number of parameters
|
||||
if (2 > route_parameters.coordinates.size())
|
||||
{
|
||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
RawRouteData raw_route;
|
||||
raw_route.check_sum = facade->GetCheckSum();
|
||||
|
||||
if (std::any_of(begin(route_parameters.coordinates),
|
||||
end(route_parameters.coordinates),
|
||||
[&](FixedPointCoordinate coordinate)
|
||||
{
|
||||
return !coordinate.isValid();
|
||||
}))
|
||||
{
|
||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const FixedPointCoordinate &coordinate : route_parameters.coordinates)
|
||||
{
|
||||
raw_route.raw_via_node_coordinates.emplace_back(coordinate);
|
||||
}
|
||||
|
||||
std::vector<PhantomNode> phantom_node_vector(raw_route.raw_via_node_coordinates.size());
|
||||
const bool checksum_OK = (route_parameters.check_sum == raw_route.check_sum);
|
||||
|
||||
for (unsigned i = 0; i < raw_route.raw_via_node_coordinates.size(); ++i)
|
||||
{
|
||||
if (checksum_OK && i < route_parameters.hints.size() &&
|
||||
!route_parameters.hints[i].empty())
|
||||
{
|
||||
ObjectEncoder::DecodeFromBase64(route_parameters.hints[i], phantom_node_vector[i]);
|
||||
if (phantom_node_vector[i].isValid(facade->GetNumberOfNodes()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
facade->FindPhantomNodeForCoordinate(raw_route.raw_via_node_coordinates[i],
|
||||
phantom_node_vector[i],
|
||||
route_parameters.zoom_level);
|
||||
}
|
||||
|
||||
PhantomNodes current_phantom_node_pair;
|
||||
for (unsigned i = 0; i < phantom_node_vector.size() - 1; ++i)
|
||||
{
|
||||
current_phantom_node_pair.source_phantom = phantom_node_vector[i];
|
||||
current_phantom_node_pair.target_phantom = phantom_node_vector[i + 1];
|
||||
raw_route.segment_end_coordinates.emplace_back(current_phantom_node_pair);
|
||||
}
|
||||
|
||||
search_engine_ptr->shortest_path(
|
||||
raw_route.segment_end_coordinates, route_parameters.uturns, raw_route);
|
||||
|
||||
if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length)
|
||||
{
|
||||
SimpleLogger().Write(logDEBUG) << "Error occurred, single path not found";
|
||||
}
|
||||
reply.status = http::Reply::ok;
|
||||
|
||||
//Get mwm names
|
||||
set<string> usedMwms;
|
||||
|
||||
for (auto i : osrm::irange<std::size_t>(0, raw_route.unpacked_path_segments.size()))
|
||||
{
|
||||
size_t const n = raw_route.unpacked_path_segments[i].size();
|
||||
for (size_t j = 0; j < n; ++j)
|
||||
{
|
||||
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), MercatorBounds::LatToY(coord.lat));
|
||||
GetMWMNameByPoint getter(mwmName, mercatorPoint);
|
||||
m_countries.ForEachInRect(m2::RectD(mercatorPoint, mercatorPoint), getter);
|
||||
usedMwms.insert(mwmName);
|
||||
}
|
||||
}
|
||||
|
||||
JSON::Object json_object;
|
||||
JSON::Array json_array;
|
||||
json_array.values.insert(json_array.values.begin(), usedMwms.begin(), usedMwms.end());
|
||||
json_object.values["used_mwms"] = json_array;
|
||||
JSON::render(reply.content, json_object);
|
||||
}
|
||||
|
||||
private:
|
||||
std::string descriptor_string;
|
||||
DataFacadeT *facade;
|
||||
};
|
|
@ -41,26 +41,4 @@ namespace osm
|
|||
// drop inner rings
|
||||
return name[0] != '!';
|
||||
}
|
||||
|
||||
bool LoadBorders(string const & borderFile, vector<m2::RegionD> & 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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,6 @@
|
|||
|
||||
namespace osm
|
||||
{
|
||||
/// @return false if borderFile can't be opened
|
||||
bool LoadBorders(string const & borderFile, vector<m2::RegionD> & outBorders);
|
||||
void GenerateBordersFromOsm(string const & tagAndOptValue, string const & osmFile,
|
||||
string const & outFile);
|
||||
}
|
||||
|
|
|
@ -22,128 +22,59 @@
|
|||
#include "../std/vector.hpp"
|
||||
#include "../std/bind.hpp"
|
||||
|
||||
#include "../../boost/boost/filesystem.hpp"
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
|
||||
namespace borders
|
||||
{
|
||||
|
||||
class PolygonLoader
|
||||
{
|
||||
CountryPolygons m_polygons;
|
||||
m2::RectD m_rect;
|
||||
|
||||
CountriesContainerT & m_countries;
|
||||
|
||||
public:
|
||||
PolygonLoader(CountriesContainerT & countries)
|
||||
: m_countries(countries) {}
|
||||
|
||||
void operator() (string const & name, vector<m2::RegionD> const & borders)
|
||||
{
|
||||
if (m_polygons.m_name.empty())
|
||||
m_polygons.m_name = name;
|
||||
|
||||
for (m2::RegionD 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();
|
||||
}
|
||||
};
|
||||
|
||||
template <class ToDo>
|
||||
void ForEachCountry(string const & baseDir, ToDo & toDo)
|
||||
{
|
||||
string bordersDir = baseDir + BORDERS_DIR;
|
||||
ASSERT(fs::exists(bordersDir) && fs::is_directory(bordersDir), ("Cannot read borders directory", bordersDir));
|
||||
|
||||
fs::directory_iterator end_iter;
|
||||
for (fs::directory_iterator dir_iter(bordersDir); dir_iter != end_iter; ++dir_iter)
|
||||
{
|
||||
if (fs::is_regular_file(dir_iter->status()) && dir_iter->path().filename().string().find(BORDERS_EXTENSION) != string::npos)
|
||||
{
|
||||
vector<m2::RegionD> borders;
|
||||
if (osm::LoadBorders(dir_iter->path().string(), borders))
|
||||
{
|
||||
toDo(dir_iter->path().stem().string(), borders);
|
||||
toDo.Finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool LoadCountriesList(string const & baseDir, CountriesContainerT & countries)
|
||||
{
|
||||
countries.Clear();
|
||||
|
||||
LOG(LINFO, ("Loading countries."));
|
||||
|
||||
PolygonLoader loader(countries);
|
||||
ForEachCountry(baseDir, loader);
|
||||
|
||||
LOG(LINFO, ("Countries loaded:", countries.GetSize()));
|
||||
|
||||
return !countries.IsEmpty();
|
||||
}
|
||||
|
||||
class PackedBordersGenerator
|
||||
{
|
||||
FilesContainerW m_writer;
|
||||
string const & m_baseDir;
|
||||
|
||||
vector<storage::CountryDef> m_polys;
|
||||
|
||||
public:
|
||||
PackedBordersGenerator(string const & baseDir)
|
||||
: m_writer(baseDir + PACKED_POLYGONS_FILE)
|
||||
: m_writer(baseDir + PACKED_POLYGONS_FILE), m_baseDir(baseDir)
|
||||
{
|
||||
}
|
||||
|
||||
void operator() (string const & name, vector<m2::RegionD> const & borders)
|
||||
void operator() (string const & name)
|
||||
{
|
||||
// use index in vector as tag
|
||||
FileWriter w = m_writer.GetWriter(strings::to_string(m_polys.size()));
|
||||
serial::CodingParams cp;
|
||||
|
||||
// calc rect
|
||||
m2::RectD rect;
|
||||
for (m2::RegionD const & border : borders)
|
||||
rect.Add(border.GetRect());
|
||||
|
||||
// store polygon info
|
||||
m_polys.push_back(storage::CountryDef(name, rect));
|
||||
|
||||
// write polygons as paths
|
||||
WriteVarUint(w, borders.size());
|
||||
for (m2::RegionD const & border : borders)
|
||||
vector<m2::RegionD> borders;
|
||||
if (borders::LoadBorders(m_baseDir + BORDERS_DIR + name + BORDERS_EXTENSION, borders))
|
||||
{
|
||||
typedef vector<m2::PointD> VectorT;
|
||||
typedef m2::DistanceToLineSquare<m2::PointD> DistanceT;
|
||||
// use index in vector as tag
|
||||
FileWriter w = m_writer.GetWriter(strings::to_string(m_polys.size()));
|
||||
serial::CodingParams cp;
|
||||
|
||||
VectorT const & in = border.Data();
|
||||
VectorT out;
|
||||
uint32_t const count = static_cast<uint32_t>(borders.size());
|
||||
|
||||
/// @todo Choose scale level for simplification.
|
||||
double const eps = my::sq(scales::GetEpsilonForSimplify(10));
|
||||
DistanceT dist;
|
||||
SimplifyNearOptimal(20, in.begin(), in.end(), eps, dist,
|
||||
AccumulateSkipSmallTrg<DistanceT, m2::PointD>(dist, out, eps));
|
||||
// calc rect
|
||||
m2::RectD rect;
|
||||
for (uint32_t i = 0; i < count; ++i)
|
||||
rect.Add(borders[i].GetRect());
|
||||
|
||||
serial::SaveOuterPath(out, cp, w);
|
||||
// store polygon info
|
||||
m_polys.push_back(storage::CountryDef(name, rect));
|
||||
|
||||
// write polygons as paths
|
||||
WriteVarUint(w, count);
|
||||
for (uint32_t i = 0; i < count; ++i)
|
||||
{
|
||||
typedef vector<m2::PointD> VectorT;
|
||||
typedef m2::DistanceToLineSquare<m2::PointD> DistanceT;
|
||||
|
||||
VectorT const & in = borders[i].Data();
|
||||
VectorT out;
|
||||
|
||||
/// @todo Choose scale level for simplification.
|
||||
double const eps = my::sq(scales::GetEpsilonForSimplify(10));
|
||||
DistanceT dist;
|
||||
SimplifyNearOptimal(20, in.begin(), in.end(), eps, dist,
|
||||
AccumulateSkipSmallTrg<DistanceT, m2::PointD>(dist, out, eps));
|
||||
|
||||
serial::SaveOuterPath(out, cp, w);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,34 +5,9 @@
|
|||
|
||||
#include "../std/string.hpp"
|
||||
|
||||
#define BORDERS_DIR "borders/"
|
||||
#define BORDERS_EXTENSION ".poly"
|
||||
#include "country_loader.hpp"
|
||||
|
||||
namespace borders
|
||||
{
|
||||
typedef m2::RegionD Region;
|
||||
typedef m4::Tree<Region> 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<CountryPolygons> CountriesContainerT;
|
||||
|
||||
bool LoadCountriesList(string const & baseDir, CountriesContainerT & countries);
|
||||
|
||||
void GeneratePackedBorders(string const & baseDir);
|
||||
}
|
||||
|
|
91
generator/country_loader.cpp
Normal file
91
generator/country_loader.cpp
Normal file
|
@ -0,0 +1,91 @@
|
|||
#include "country_loader.hpp"
|
||||
|
||||
#include "../base/std_serialization.hpp"
|
||||
#include "../base/logging.hpp"
|
||||
|
||||
#include "../coding/file_reader.hpp"
|
||||
#include "../coding/file_writer.hpp"
|
||||
#include "../coding/streams_sink.hpp"
|
||||
|
||||
namespace borders
|
||||
{
|
||||
|
||||
bool LoadBorders(string const & borderFile, vector<m2::RegionD> & 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;
|
||||
}
|
||||
|
||||
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<m2::RegionD> borders;
|
||||
if (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();
|
||||
}
|
||||
};
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
59
generator/country_loader.hpp
Normal file
59
generator/country_loader.hpp
Normal file
|
@ -0,0 +1,59 @@
|
|||
#pragma once
|
||||
|
||||
#include "../geometry/region2d.hpp"
|
||||
#include "../geometry/tree4d.hpp"
|
||||
|
||||
#include "../std/string.hpp"
|
||||
#include "../std/fstream.hpp"
|
||||
|
||||
#define BORDERS_DIR "borders/"
|
||||
#define BORDERS_EXTENSION ".poly"
|
||||
#define POLYGONS_FILE "polygons.lst"
|
||||
|
||||
namespace borders
|
||||
{
|
||||
typedef m2::RegionD Region;
|
||||
typedef m4::Tree<Region> 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<CountryPolygons> CountriesContainerT;
|
||||
|
||||
/// @return false if borderFile can't be opened
|
||||
bool LoadBorders(string const & borderFile, vector<m2::RegionD> & outBorders);
|
||||
|
||||
bool LoadCountriesList(string const & baseDir, CountriesContainerT & countries);
|
||||
|
||||
template <class ToDo>
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -34,6 +34,7 @@ SOURCES += \
|
|||
tesselator.cpp \
|
||||
check_model.cpp \
|
||||
routing_generator.cpp \
|
||||
country_loader.cpp \
|
||||
|
||||
HEADERS += \
|
||||
feature_merger.hpp \
|
||||
|
@ -64,3 +65,4 @@ HEADERS += \
|
|||
ways_merger.hpp \
|
||||
gen_mwm_info.hpp \
|
||||
routing_generator.hpp \
|
||||
country_loader.hpp \
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include "../osm_xml_parser.hpp"
|
||||
#include "../borders_generator.hpp"
|
||||
#include "../country_loader.hpp"
|
||||
|
||||
#include "../../coding/reader.hpp"
|
||||
#include "../../coding/parse_xml.hpp"
|
||||
|
@ -9,6 +10,7 @@
|
|||
#include "../../coding/file_writer.hpp"
|
||||
|
||||
using namespace osm;
|
||||
using namespace borders;
|
||||
|
||||
static char const gOsmXml[] =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||
|
|
Loading…
Add table
Reference in a new issue