mirror of
https://codeberg.org/comaps/comaps
synced 2025-12-19 04:53:36 +00:00
Borders
This commit is contained in:
committed by
Konstantin Pastbin
parent
3b46dd1dee
commit
128b0f3e2b
@@ -13,7 +13,6 @@
|
||||
#include "coding/varint.hpp"
|
||||
|
||||
#include "geometry/mercator.hpp"
|
||||
#include "geometry/parametrized_segment.hpp"
|
||||
#include "geometry/simplification.hpp"
|
||||
|
||||
#include "base/assert.hpp"
|
||||
@@ -24,20 +23,18 @@
|
||||
|
||||
#include <cmath>
|
||||
#include <fstream>
|
||||
#include <functional>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
#include "base/assert.hpp"
|
||||
#include "base/string_utils.hpp"
|
||||
|
||||
#include "defines.hpp"
|
||||
|
||||
namespace borders
|
||||
{
|
||||
namespace
|
||||
{
|
||||
|
||||
template <class ToDo>
|
||||
void ForEachCountry(std::string const & baseDir, ToDo && toDo)
|
||||
{
|
||||
@@ -49,11 +46,11 @@ void ForEachCountry(std::string const & baseDir, ToDo && toDo)
|
||||
Platform::GetFilesByExt(bordersDir, BORDERS_EXTENSION, files);
|
||||
for (std::string file : files)
|
||||
{
|
||||
std::vector<m2::RegionD> polygons;
|
||||
PolygonsList polygons;
|
||||
if (LoadBorders(bordersDir + file, polygons))
|
||||
{
|
||||
base::GetNameWithoutExt(file);
|
||||
toDo(file, polygons);
|
||||
toDo(std::move(file), std::move(polygons));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -65,7 +62,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(std::string const & name, std::vector<m2::RegionD> const & borders)
|
||||
void operator()(std::string name, PolygonsList && borders)
|
||||
{
|
||||
// use index in vector as tag
|
||||
auto w = m_writer.GetWriter(strings::to_string(m_polys.size()));
|
||||
@@ -105,7 +102,7 @@ private:
|
||||
std::vector<storage::CountryDef> m_polys;
|
||||
};
|
||||
|
||||
bool ReadPolygon(std::istream & stream, m2::RegionD & region, std::string const & filename)
|
||||
bool ReadPolygon(std::istream & stream, Polygon & poly, std::string const & filename)
|
||||
{
|
||||
std::string line, name;
|
||||
double lon, lat;
|
||||
@@ -130,7 +127,7 @@ bool ReadPolygon(std::istream & stream, m2::RegionD & region, std::string const
|
||||
iss >> lon >> lat;
|
||||
CHECK(!iss.fail(), ("Incorrect data in", filename));
|
||||
|
||||
region.AddPoint(mercator::FromLatLon(lat, lon));
|
||||
poly.AddPoint(mercator::FromLatLon(lat, lon));
|
||||
}
|
||||
|
||||
// drop inner rings
|
||||
@@ -146,7 +143,7 @@ bool CountryPolygons::Contains(m2::PointD const & point) const
|
||||
});
|
||||
}
|
||||
|
||||
bool LoadBorders(std::string const & borderFile, std::vector<m2::RegionD> & outBorders)
|
||||
bool LoadBorders(std::string const & borderFile, PolygonsList & outBorders)
|
||||
{
|
||||
std::ifstream stream(borderFile);
|
||||
std::string line;
|
||||
@@ -156,12 +153,12 @@ bool LoadBorders(std::string const & borderFile, std::vector<m2::RegionD> & outB
|
||||
return false;
|
||||
}
|
||||
|
||||
m2::RegionD currentPolygon;
|
||||
Polygon currentPolygon;
|
||||
while (ReadPolygon(stream, currentPolygon, borderFile))
|
||||
{
|
||||
CHECK(currentPolygon.IsValid(), ("Invalid region in", borderFile));
|
||||
outBorders.emplace_back(std::move(currentPolygon));
|
||||
currentPolygon = m2::RegionD();
|
||||
currentPolygon = {};
|
||||
}
|
||||
|
||||
CHECK(!outBorders.empty(), ("No borders were loaded from", borderFile));
|
||||
@@ -178,7 +175,7 @@ bool GetBordersRect(std::string const & baseDir, std::string const & country,
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<m2::RegionD> borders;
|
||||
PolygonsList borders;
|
||||
CHECK(LoadBorders(bordersFile, borders), ());
|
||||
bordersRect.MakeEmpty();
|
||||
for (auto const & border : borders)
|
||||
@@ -192,13 +189,16 @@ CountryPolygonsCollection LoadCountriesList(std::string const & baseDir)
|
||||
LOG(LINFO, ("Loading countries in", BORDERS_DIR, "folder in", baseDir));
|
||||
|
||||
CountryPolygonsCollection countryPolygonsCollection;
|
||||
ForEachCountry(baseDir, [&](auto const & name, auto const & borders)
|
||||
ForEachCountry(baseDir, [&](std::string name, PolygonsList && borders)
|
||||
{
|
||||
PolygonsTree polygons;
|
||||
for (m2::RegionD const & border : borders)
|
||||
polygons.Add(border, border.GetRect());
|
||||
for (Polygon & border : borders)
|
||||
{
|
||||
auto const rect = border.GetRect();
|
||||
polygons.Add(std::move(border), rect);
|
||||
}
|
||||
|
||||
countryPolygonsCollection.Add(CountryPolygons(name, polygons));
|
||||
countryPolygonsCollection.Add(CountryPolygons(std::move(name), std::move(polygons)));
|
||||
});
|
||||
|
||||
LOG(LINFO, ("Countries loaded:", countryPolygonsCollection.GetSize()));
|
||||
@@ -214,7 +214,7 @@ void GeneratePackedBorders(std::string const & baseDir)
|
||||
}
|
||||
|
||||
void DumpBorderToPolyFile(std::string const & targetDir, storage::CountryId const & mwmName,
|
||||
std::vector<m2::RegionD> const & polygons)
|
||||
PolygonsList const & polygons)
|
||||
{
|
||||
CHECK(!polygons.empty(), ());
|
||||
|
||||
@@ -222,7 +222,8 @@ void DumpBorderToPolyFile(std::string const & targetDir, storage::CountryId cons
|
||||
std::ofstream poly(filePath);
|
||||
CHECK(poly.good(), ());
|
||||
|
||||
poly << std::setprecision(20) << std::fixed;
|
||||
// Used to have fixed precicion with 6 digits. And Alaska has 4 digits after comma :) Strange, but as is.
|
||||
poly << std::setprecision(6) << std::fixed;
|
||||
|
||||
poly << mwmName << std::endl;
|
||||
size_t polygonId = 1;
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "generator/feature_builder.hpp"
|
||||
|
||||
#include "storage/storage_defines.hpp"
|
||||
|
||||
#include "coding/geometry_coding.hpp"
|
||||
@@ -11,12 +9,9 @@
|
||||
#include "geometry/region2d.hpp"
|
||||
#include "geometry/tree4d.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#define BORDERS_DIR "borders/"
|
||||
@@ -48,9 +43,8 @@ class CountryPolygons
|
||||
{
|
||||
public:
|
||||
CountryPolygons() = default;
|
||||
explicit CountryPolygons(std::string const & name, PolygonsTree const & regions)
|
||||
: m_name(name)
|
||||
, m_polygons(regions)
|
||||
explicit CountryPolygons(std::string && name, PolygonsTree && regions)
|
||||
: m_name(std::move(name)), m_polygons(std::move(regions))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -97,6 +91,8 @@ public:
|
||||
|
||||
private:
|
||||
std::string m_name;
|
||||
|
||||
/// @todo Is it an overkill to store Tree4D for each country's polygon?
|
||||
PolygonsTree m_polygons;
|
||||
};
|
||||
|
||||
@@ -105,11 +101,15 @@ class CountryPolygonsCollection
|
||||
public:
|
||||
CountryPolygonsCollection() = default;
|
||||
|
||||
void Add(CountryPolygons const & countryPolygons)
|
||||
void Add(CountryPolygons && countryPolygons)
|
||||
{
|
||||
auto const it = m_countryPolygonsMap.emplace(countryPolygons.GetName(), countryPolygons);
|
||||
countryPolygons.ForEachPolygon([&](auto const & polygon) {
|
||||
m_regionsTree.Add(it.first->second, polygon.GetRect());
|
||||
auto const res = m_countryPolygonsMap.emplace(countryPolygons.GetName(), std::move(countryPolygons));
|
||||
CHECK(res.second, ());
|
||||
|
||||
auto const & inserted = res.first->second;
|
||||
inserted.ForEachPolygon([&inserted, this](Polygon const & polygon)
|
||||
{
|
||||
m_regionsTree.Add(inserted, polygon.GetRect());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -119,9 +119,10 @@ public:
|
||||
void ForEachCountryInRect(m2::RectD const & rect, ToDo && toDo) const
|
||||
{
|
||||
std::unordered_set<CountryPolygons const *> uniq;
|
||||
m_regionsTree.ForEachInRect(rect, [&](auto const & countryPolygons) {
|
||||
if (uniq.emplace(&countryPolygons.get()).second)
|
||||
toDo(countryPolygons);
|
||||
m_regionsTree.ForEachInRect(rect, [&](CountryPolygons const & cp)
|
||||
{
|
||||
if (uniq.insert(&cp).second)
|
||||
toDo(cp);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -142,8 +143,10 @@ private:
|
||||
std::unordered_map<std::string, CountryPolygons> m_countryPolygonsMap;
|
||||
};
|
||||
|
||||
using PolygonsList = std::vector<Polygon>;
|
||||
|
||||
/// @return false if borderFile can't be opened
|
||||
bool LoadBorders(std::string const & borderFile, std::vector<m2::RegionD> & outBorders);
|
||||
bool LoadBorders(std::string const & borderFile, PolygonsList & outBorders);
|
||||
|
||||
bool GetBordersRect(std::string const & baseDir, std::string const & country,
|
||||
m2::RectD & bordersRect);
|
||||
@@ -153,10 +156,10 @@ bool LoadCountriesList(std::string const & baseDir, CountryPolygonsCollection &
|
||||
void GeneratePackedBorders(std::string const & baseDir);
|
||||
|
||||
template <typename Source>
|
||||
std::vector<m2::RegionD> ReadPolygonsOfOneBorder(Source & src)
|
||||
PolygonsList ReadPolygonsOfOneBorder(Source & src)
|
||||
{
|
||||
auto const count = ReadVarUint<uint32_t>(src);
|
||||
std::vector<m2::RegionD> result(count);
|
||||
PolygonsList result(count);
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
{
|
||||
std::vector<m2::PointD> points;
|
||||
@@ -168,7 +171,7 @@ std::vector<m2::RegionD> ReadPolygonsOfOneBorder(Source & src)
|
||||
}
|
||||
|
||||
void DumpBorderToPolyFile(std::string const & filePath, storage::CountryId const & mwmName,
|
||||
std::vector<m2::RegionD> const & polygons);
|
||||
PolygonsList const & polygons);
|
||||
void UnpackBorders(std::string const & baseDir, std::string const & targetDir);
|
||||
|
||||
CountryPolygonsCollection const & GetOrCreateCountryPolygonsTree(std::string const & baseDir);
|
||||
|
||||
Reference in New Issue
Block a user