kopia lustrzana https://gitlab.com/tomaszg/geostat
Initial support for reverse-geocoding for Poland - data about powiaty.
rodzic
0727ad0b17
commit
7d9e978543
|
@ -91,4 +91,6 @@ run `meson build; cd build; ninja`. You might need to set `CXX` variable to poin
|
|||
|
||||
* Maps of Voivodeships of Poland come from https://commons.wikimedia.org/wiki/File:Podlaskie_Voivodeship_location_map.svg, https://commons.wikimedia.org/wiki/File:Pomeranian_Voivodeship_location_map.svg, https://pl.wikipedia.org/wiki/Plik:Kuyavian-Pomeranian_Voivodeship_location_map.svg, https://pl.wikipedia.org/wiki/Plik:Warmian-Masurian_Voivodeship_location_map.svg, https://pl.wikipedia.org/wiki/Plik:Masovian_Voivodeship_location_map.svg, https://pl.wikipedia.org/wiki/Plik:Lesser_Poland_Voivodeship_location_map.svg, https://pl.wikipedia.org/wiki/Plik:Greater_Poland_Voivodeship_location_map.svg, https://pl.wikipedia.org/wiki/Plik:Opole_Voivodeship_location_map.svg, https://pl.wikipedia.org/wiki/Plik:Lower_Silesian_Voivodeship_location_map.svg, https://pl.wikipedia.org/wiki/Plik:Silesian_Voivodeship_location_map.svg, https://pl.wikipedia.org/wiki/Plik:Lublin_Voivodeship_location_map.svg, https://pl.wikipedia.org/wiki/Plik:Subcarpathian_Voivodeship_location_map.svg, https://pl.wikipedia.org/wiki/Plik:West_Pomeranian_Voivodeship_location_map.svg, https://pl.wikipedia.org/wiki/Plik:%C5%9Awi%C4%99tokrzyskie_Voivodeship_location_map.svg, https://pl.wikipedia.org/wiki/Plik:Lubusz_Voivodeship_location_map.svg, https://pl.wikipedia.org/wiki/Plik:%C5%81%C3%B3d%C5%BA_Voivodeship_location_map.svg and are licensed under CC-BY-SA.
|
||||
|
||||
* Data about administrative boundaries of Poland comes from OpenStreetMap via https://wambachers-osm.website/boundaries/.
|
||||
|
||||
* CSS tricks used to render histograms are based on https://css-tricks.com/making-charts-with-css.
|
||||
|
|
1
cache.h
1
cache.h
|
@ -64,6 +64,7 @@ public:
|
|||
bool recommended = 0; // was the cache recommended by that user?
|
||||
std::string type;
|
||||
std::string region;
|
||||
std::string subregion;
|
||||
std::string origin;
|
||||
std::string owner;
|
||||
std::string owner_uuid;
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,32 @@
|
|||
configure_file(input: 'dolnoslaskie.geojson', output: '@PLAINNAME@', copy: true, install: true, install_dir: '.')
|
||||
configure_file(input: 'dolnoslaskie_sub.geojson', output: '@PLAINNAME@', copy: true, install: true, install_dir: '.')
|
||||
configure_file(input: 'gornoslaskie.geojson', output: '@PLAINNAME@', copy: true, install: true, install_dir: '.')
|
||||
configure_file(input: 'gornoslaskie_sub.geojson', output: '@PLAINNAME@', copy: true, install: true, install_dir: '.')
|
||||
configure_file(input: 'kujawsko-pomorskie.geojson', output: '@PLAINNAME@', copy: true, install: true, install_dir: '.')
|
||||
configure_file(input: 'kujawsko-pomorskie_sub.geojson', output: '@PLAINNAME@', copy: true, install: true, install_dir: '.')
|
||||
configure_file(input: 'lodzkie.geojson', output: '@PLAINNAME@', copy: true, install: true, install_dir: '.')
|
||||
configure_file(input: 'lodzkie_sub.geojson', output: '@PLAINNAME@', copy: true, install: true, install_dir: '.')
|
||||
configure_file(input: 'lubelskie.geojson', output: '@PLAINNAME@', copy: true, install: true, install_dir: '.')
|
||||
configure_file(input: 'lubelskie_sub.geojson', output: '@PLAINNAME@', copy: true, install: true, install_dir: '.')
|
||||
configure_file(input: 'lubuskie.geojson', output: '@PLAINNAME@', copy: true, install: true, install_dir: '.')
|
||||
configure_file(input: 'lubuskie_sub.geojson', output: '@PLAINNAME@', copy: true, install: true, install_dir: '.')
|
||||
configure_file(input: 'malopolskie.geojson', output: '@PLAINNAME@', copy: true, install: true, install_dir: '.')
|
||||
configure_file(input: 'malopolskie_sub.geojson', output: '@PLAINNAME@', copy: true, install: true, install_dir: '.')
|
||||
configure_file(input: 'mazowieckie.geojson', output: '@PLAINNAME@', copy: true, install: true, install_dir: '.')
|
||||
configure_file(input: 'mazowieckie_sub.geojson', output: '@PLAINNAME@', copy: true, install: true, install_dir: '.')
|
||||
configure_file(input: 'opolskie.geojson', output: '@PLAINNAME@', copy: true, install: true, install_dir: '.')
|
||||
configure_file(input: 'opolskie_sub.geojson', output: '@PLAINNAME@', copy: true, install: true, install_dir: '.')
|
||||
configure_file(input: 'podkarpackie.geojson', output: '@PLAINNAME@', copy: true, install: true, install_dir: '.')
|
||||
configure_file(input: 'podkarpackie_sub.geojson', output: '@PLAINNAME@', copy: true, install: true, install_dir: '.')
|
||||
configure_file(input: 'podlaskie.geojson', output: '@PLAINNAME@', copy: true, install: true, install_dir: '.')
|
||||
configure_file(input: 'podlaskie_sub.geojson', output: '@PLAINNAME@', copy: true, install: true, install_dir: '.')
|
||||
configure_file(input: 'pomorskie.geojson', output: '@PLAINNAME@', copy: true, install: true, install_dir: '.')
|
||||
configure_file(input: 'pomorskie_sub.geojson', output: '@PLAINNAME@', copy: true, install: true, install_dir: '.')
|
||||
configure_file(input: 'swietokrzyskie.geojson', output: '@PLAINNAME@', copy: true, install: true, install_dir: '.')
|
||||
configure_file(input: 'swietokrzyskie_sub.geojson', output: '@PLAINNAME@', copy: true, install: true, install_dir: '.')
|
||||
configure_file(input: 'warminsko-mazurskie.geojson', output: '@PLAINNAME@', copy: true, install: true, install_dir: '.')
|
||||
configure_file(input: 'warminsko-mazurskie_sub.geojson', output: '@PLAINNAME@', copy: true, install: true, install_dir: '.')
|
||||
configure_file(input: 'wielkopolskie.geojson', output: '@PLAINNAME@', copy: true, install: true, install_dir: '.')
|
||||
configure_file(input: 'wielkopolskie_sub.geojson', output: '@PLAINNAME@', copy: true, install: true, install_dir: '.')
|
||||
configure_file(input: 'zachodniopomorskie.geojson', output: '@PLAINNAME@', copy: true, install: true, install_dir: '.')
|
||||
configure_file(input: 'zachodniopomorskie_sub.geojson', output: '@PLAINNAME@', copy: true, install: true, install_dir: '.')
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
25
geostat.cpp
25
geostat.cpp
|
@ -5,6 +5,7 @@
|
|||
#include "heat.h"
|
||||
#include "ocdb.h"
|
||||
#include "common.h"
|
||||
#include "region.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
@ -243,6 +244,26 @@ int main(int argc, char** argv) {
|
|||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Prepare a set of regions
|
||||
Country poland({
|
||||
"dolnoslaskie",
|
||||
"gornoslaskie",
|
||||
"kujawsko-pomorskie",
|
||||
"lodzkie",
|
||||
"lubelskie",
|
||||
"lubuskie",
|
||||
"malopolskie",
|
||||
"mazowieckie",
|
||||
"opolskie",
|
||||
"podkarpackie",
|
||||
"podlaskie",
|
||||
"pomorskie",
|
||||
"swietokrzyskie",
|
||||
"warminsko-mazurskie",
|
||||
"wielkopolskie",
|
||||
"zachodniopomorskie"
|
||||
});
|
||||
|
||||
// Prepare sorted list of caches, excluding moving caches
|
||||
std::map<std::string, int> dates;
|
||||
Date_Caches sorted_caches;
|
||||
|
@ -259,6 +280,9 @@ int main(int argc, char** argv) {
|
|||
i = cc.erase(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
poland.locate(*i);
|
||||
|
||||
dates[i->date]++;
|
||||
sorted_caches.insert({ i->date_t, &*i });
|
||||
if (i->type != "Moving" && i->type != "Own" && (!get_not_found || !exclude_quiz || i->type != "Quiz")) {
|
||||
|
@ -424,6 +448,7 @@ int main(int argc, char** argv) {
|
|||
show_histogram(cc, &Cache::type, "Cache types", 1);
|
||||
show_histogram(cc, &Cache::size, "Cache sizes", 1);
|
||||
show_histogram(cc, &Cache::region, "Regions", 1);
|
||||
show_histogram(cc, &Cache::subregion, "Subregions", 1);
|
||||
show_histogram(cc, &Cache::day_of_week, "Days of the week", 1, 0);
|
||||
show_histogram(cc, &Cache::mon, "Months", 1, 0);
|
||||
show_histogram(cc, &Cache::year, "Years", 1, 0);
|
||||
|
|
|
@ -14,7 +14,7 @@ if not magick_dep.found()
|
|||
endif
|
||||
|
||||
link = ['-lgpx', '-lheatmap']
|
||||
src = ['geostat.cpp', 'okapi.cpp', 'cache.cpp', 'debug.cpp', 'heat.cpp', 'ocdb.cpp', 'common.cpp']
|
||||
src = ['geostat.cpp', 'okapi.cpp', 'cache.cpp', 'debug.cpp', 'heat.cpp', 'ocdb.cpp', 'common.cpp', 'region.cpp']
|
||||
src_cli = ['geostat_cli.cpp', 'okapi.cpp', 'gpx.cpp', 'cache.cpp', 'debug.cpp', 'heat.cpp', 'ocdb.cpp', 'common.cpp']
|
||||
src_db = ['geodb.cpp', 'debug.cpp', 'ocdb.cpp', 'okapi.cpp', 'cache.cpp', 'common.cpp']
|
||||
|
||||
|
@ -26,3 +26,4 @@ configure_file(input: 'rating-star.png', output: '@PLAINNAME@', copy: true, inst
|
|||
configure_file(input: 'geo.css', output: '@PLAINNAME@', copy: true, install: true, install_dir: '.')
|
||||
|
||||
subdir('maps')
|
||||
subdir('geojson')
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
#include "region.h"
|
||||
#include "debug.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
typedef bg::model::point<double, 2, bg::cs::cartesian> point_t;
|
||||
|
||||
BoundingBox::BoundingBox(Position p1, Position p2) {
|
||||
a.lat = std::min(p1.lat, p2.lat);
|
||||
b.lat = std::max(p1.lat, p2.lat);
|
||||
a.lon = std::min(p1.lon, p2.lon);
|
||||
b.lon = std::max(p1.lon, p2.lon);
|
||||
}
|
||||
|
||||
bool BoundingBox::within(Position p) {
|
||||
return (p.lat >= a.lat && p.lat <= b.lat && p.lon >= a.lon && p.lon <= b.lon);
|
||||
}
|
||||
|
||||
bool ContourData::within(Position p) {
|
||||
return bbox.within(p) && bg::within(point_t{p.lon, p.lat}, contour);
|
||||
}
|
||||
|
||||
ContourData::ContourData(BoundingBox bbox) : bbox(bbox) {}
|
||||
|
||||
void ContourData::add_point(Position p) {
|
||||
bg::append(contour, point_t{p.lon, p.lat});
|
||||
}
|
||||
|
||||
// TODO: Parse inner ring and multi-poligon
|
||||
std::map<std::string, ContourData*> Region::parse_geojson(const std::string& json_file) {
|
||||
if (!std::filesystem::exists(json_file)) {
|
||||
throw std::runtime_error("File " + json_file + " does not exist.");
|
||||
}
|
||||
std::ifstream file(json_file);
|
||||
json j;
|
||||
file >> j;
|
||||
std::string name;
|
||||
|
||||
std::map<std::string, ContourData*> rr;
|
||||
|
||||
for (auto& el : j["features"].items()) {
|
||||
std::cout << "X";
|
||||
|
||||
if (el.value()["properties"]["alltags"].count("short_name") > 0)
|
||||
name = el.value()["properties"]["alltags"]["short_name"];
|
||||
else if (el.value()["properties"].count("name") > 0)
|
||||
name = el.value()["properties"]["name"];
|
||||
else {
|
||||
Debug(1) << "Unknown name for an object, skipping";
|
||||
continue;
|
||||
}
|
||||
ContourData* cont = new ContourData(BoundingBox(Position(el.value()["bbox"][1], el.value()["bbox"][0]), Position(el.value()["bbox"][3], el.value()["bbox"][2])));
|
||||
for (auto& el2 : el.value()["geometry"]["coordinates"][0][0].items()) {
|
||||
cont->add_point(Position(el2.value()[1],el2.value()[0]));
|
||||
}
|
||||
Debug(3) << "Parsed region " << name;
|
||||
rr[name] = cont;
|
||||
}
|
||||
return rr;
|
||||
}
|
||||
|
||||
Region::Region(const std::filesystem::path& geojson, const std::filesystem::path& geojson_sub) {
|
||||
auto reg = *parse_geojson(geojson).begin();
|
||||
name = reg.first;
|
||||
contour = reg.second;
|
||||
|
||||
for (auto& el : parse_geojson(geojson_sub))
|
||||
subregions.emplace_back(new Region(el.second, el.first));
|
||||
}
|
||||
|
||||
Region::~Region() {
|
||||
subregions.clear();
|
||||
delete contour;
|
||||
}
|
||||
|
||||
std::string Region::find_subregion(Position p) {
|
||||
if (!within(p)) throw std::runtime_error("Point not in this region.");
|
||||
|
||||
auto res = std::find_if(subregions.begin(), subregions.end(), [&](auto a) { return a->within(p); });
|
||||
if (res != subregions.end())
|
||||
return (*res)->get_name();
|
||||
return "";
|
||||
// else
|
||||
// throw std::runtime_error("Point " + std::to_string(p.lat) + " " + std::to_string(p.lon) + " not in any of the subregions.");
|
||||
}
|
||||
|
||||
Country::Country(const std::vector<std::filesystem::path>& jsons) {
|
||||
for (auto el : jsons) {
|
||||
std::filesystem::path p1 = "geojson" / el;
|
||||
std::filesystem::path p2 = p1;
|
||||
p1 += ".geojson";
|
||||
p2 += "_sub.geojson";
|
||||
regions.emplace_back(new Region(p1, p2));
|
||||
}
|
||||
}
|
||||
|
||||
void Country::locate(Cache& c) {
|
||||
Position p = c.pos;
|
||||
for (auto& el : regions) {
|
||||
if (el->within(p)) {
|
||||
c.region = el->get_name();
|
||||
c.subregion = el->find_subregion(p);
|
||||
Debug(3) << "Found subregion " << c.subregion;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
#pragma once
|
||||
|
||||
#include "cache.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
|
||||
#include <boost/geometry.hpp>
|
||||
#include <boost/geometry/geometries/point_xy.hpp>
|
||||
#include <boost/geometry/geometries/polygon.hpp>
|
||||
|
||||
namespace bg = boost::geometry;
|
||||
|
||||
class BoundingBox {
|
||||
private:
|
||||
Position a;
|
||||
Position b;
|
||||
public:
|
||||
inline bool within(Position p);
|
||||
|
||||
BoundingBox(Position p1, Position p2);
|
||||
};
|
||||
|
||||
class ContourData {
|
||||
private:
|
||||
bg::model::polygon<boost::geometry::model::d2::point_xy<double>> contour;
|
||||
BoundingBox bbox;
|
||||
public:
|
||||
ContourData(BoundingBox bbox);
|
||||
bool within(Position p);
|
||||
void add_point(Position p);
|
||||
};
|
||||
|
||||
class Region {
|
||||
private:
|
||||
ContourData* contour;
|
||||
std::string name;
|
||||
std::vector<Region*> subregions;
|
||||
|
||||
std::map<std::string, ContourData*> parse_geojson(const std::string& json_file);
|
||||
public:
|
||||
Region(ContourData* contour, std::string name) : contour(contour), name(name) {}
|
||||
Region(const std::filesystem::path& geojson, const std::filesystem::path& geojson_sub);
|
||||
~Region();
|
||||
|
||||
bool within(Position p) { return contour->within(p); }
|
||||
std::string get_name() { return name; }
|
||||
std::string find_subregion(Position p);
|
||||
};
|
||||
|
||||
class Country {
|
||||
private:
|
||||
std::vector<Region*> regions;
|
||||
public:
|
||||
Country(const std::vector<std::filesystem::path>& jsons);
|
||||
void locate(Cache& c);
|
||||
};
|
Ładowanie…
Reference in New Issue