ENG: Tool that prepares packages for JOSM (OpenStreetMap data editor) for easy imports of data from Polish government registries.
Narzędzie do porównywania i przygotowywania importów uwolnionych danych państwowych do OpenStreetMap (OSM).
Pełny opis w dziale FAQ/Pomocy. Zachęcamy do korzystania i zgłaszania uwag oraz pomysłów.
Mamy nadzieję uczynić z tego pomocne narzędzie dla edytorów, które ułatwi import danych z otwartych danych urzędowych do OSM.
https://budynki.openstreetmap.org.pl
Przy okazji tworzenia tej aplikacji napisałem kilka skryptów pomocniczych do importu danych z plików XML (GML) z adresami z PRG czy łączenia się z do API GUS w celu pobrania plików z nazwami gmin, miejscowości, ulic (TERYT).
Poniżej krótki opis, może komuś przydadzą się te skrypty w innym celu.
Pobiera spakowane pliki XML (GML) z danymi adresowymi (PRG) z geoportalu.
Użycie (windows):
python prg_dl.py --output_dir "D:/temp/"
Dostępny parametry:
- --output_dir - ścieżka gdzie chcesz zapisać pliki.
- --only - pobierz tylko plik dla wybranego województwa. Podaj dwucyfrowy kod TERYT.
Parsuje pliki XML (GML) z danymi adresowymi (PRG). Może zapisać dane wynikowe do bazy PostgreSQL, SQLite, plików CSV lub wydrukuje w konsoli (stdout). Parsowanie metodą SAX dzięki czemu zużycie pamięci RAM jest bardzo niewielkie (50-100mb).
Użycie (windows):
python prg.py --input "D:/ścieżka/do/pliku/02_PunktyAdresowe.zip --writer stdout --limit 5
Dostępne parametry:
- --input - ścieżka do pliku do przetworzenia
- --writer - której metody zapisu danych wyjściowych chcemy użyć (postgresql, sqlite, csv, stdout)
- --csv_directory - w przypadku wybrania writer csv ten parametr ustawia ścieżkę (folder) gdzie pliki wyjściowe będą zapisane
- --sqlite_file - w przypadku wybrania writer sqlite ten parametr ustawia ścieżkę do bazy sqlite gdzie będą zapisywane dane
- --dsn - w przypadku wybrania writer postgresql
- --prep_tables - jeżeli zapisujemy do bazy danych (postgresql lub sqlite) to ten parametr (wystarczy że sam jest obecny nie trzeba mu nic dodatkowo podawać typu true, 1 etc.) powoduje że najpierw tabele w bazie będą usunięte i odtworzone, przydatne przy ładowaniu pierwszego z serii plików
- --limit - przetwórz tylko tyle wierszy. Przydatne do testowania.
Pobiera spakowane pliki z nazwami gmin, miejscowości, ulic z API rejestru TERYT prowadzonego przez GUS i ładuje je do bazy PostgreSQL.
API GUS dla rejestru TERYT: https://api.stat.gov.pl/Home/TerytApi
Użycie (windows):
python teryt_dl.py --api_env test --api_user UzytkownikTestowy --api_password demo1234 --dsn "host=localhost port=5432 dbname=test user=test password=test"
Dostępne parametry:
- --api_env - środowisko API (prod, test)
- --api_user - użytkownik do API, którego zakłada nam GUS
- --api_password - hasło do użytkownika API
- --dsn - dane do połączenia się z bazą PostgreSQL (parametr przekazywany do metody connect biblioteki psycopg2, szczegóły: https://www.psycopg.org/docs/module.html#psycopg2.connect )
Jedną z funkcji strony jest pobieranie danych z Overpass API, konwersja ich do formatu GeoJSON i prezentacja na stronie w okienku wyboru warstw.
Warstwy odświeżane są raz na dzień.
Dodawanie nowych warstw wymaga dodania kwerendy w języku Overpassa do folderu: processing/overpass/ oraz wpisu w pliku konfiguracyjnym: web/overpass-layers.json
Wpis wymaga podania stylu warstwy w formacie Mapbox. Opis w dokumentacji: https://docs.mapbox.com/mapbox-gl-js/style-spec/layers/#type
Kwerendy Overpass nie mogą zawierać elementów obsługiwanych tylko przez stronę overpass-turbo.eu, czyli tych zawartych w znakach "{{ }}".
Przykład kwerendy:
[out:json][timeout:250];
// area(3600049715) = Polska
area(3600336075)->.searchArea;
(
way["addr:interpolation"](area.searchArea);
);
out body;
>;
out skel qt;
Przykład konfiguracji:
{
"sources": [
{
"id": "test-olayer",
"name": "Testowa warstwa Overpass",
"url": "https://budynki.openstreetmap.org.pl/overpass-layers/test.geojson",
"layers": [
{
"id": "test-olayer-lines",
"type": "line",
"source": "test-olayer",
"paint": {
"line-color": "orange",
"line-opacity": 0.8,
"line-width": 5
},
"filter": ["==", "$type", "LineString"]
}
]
}
]
}
Nazwa pliku geojson będzie taka sama jak nazwa pliku z kwerendą Overpass. ID warstw i źródeł mogą być dowolne (poza już istniejącymi w pliku map.js), ale lepiej, żeby nawiązywały do tego, co się w nich znajduje.
Jedno źródło może mieć wiele warstw (np. punkty i poligony albo punkty prezentowane jako kropka plus punkty prezentowane jako napis).
Lokalne środowisko deweloperskie można uruchomić w kontenerach Docker. Kontener nie jest w pełni funkcjonalny w porównaniu do środowiska produkcyjnego, ale podstawowe rzeczy poza aktualizacją danych powinny działać.
Bazę danych można odtworzyć z backupu. Można użyć PostgreSQL+PostGIS zainstalowanego bezpośrednio na maszynie lub utworzyć kontener Docker z bazą (co pewnie jest rozwiązaniem prostszym skoro i tak mamy zainstalowanego Dockera, żeby odpalić aplikację).
docker run --name "postgis" --shm-size=4g -e MAINTAINANCE_WORK_MEM=512MB -p 25432:5432 -e POSTGRES_USER=postgres -e POSTGRES_PASS=1234 -e POSTGRES_DBNAME=gis -d -t kartoza/postgis
--name - nadaje nazwę dla kontenera, można wybrać dowolną
--shm-size=4g - dodatkowy parametr zwiększający ilość miejsca tymczasowego, raczej nie jest niezbędny, ale nie zaszkodzi
-e MAINTAINANCE_WORK_MEM=512MB - zwiększamy dostępną pamięć dla procesów budujących indeksy itp, nie jest niezbędne, ale może się przydać
-p 25432:5432 - mapujemy porty, numer po lewej to ten którym się będziemy mogli połączyć do bazy z naszego systemu
-e POSTGRES_USER=postgres - nazwa domyślnego użytkownika dla bazy PostgreSQL
-e POSTGRES_PASS=1234 - hasło dla powyższego
-e POSTGRES_DBNAME=gis - tworzy od razu nową bazę (z odblokowanym rozszerzenim PostGIS)
-d - uruchamia kontener w tle dzięki czemu będzie można zamknąć okno konsoli bez zatrzymywania bazy
-t kartoza/postgis - nazwa obrazu do uruchomienia, korzystamy z obrazu od razu skonfigurowanego z bazą PostgreSQL i dodatkiem PostGIS
Najpierw tworzymy schematy „prg” i „teryt”:
psql -d gis -h localhost -p 25432 -U postgres -c "create schema prg;"
psql -d gis -h localhost -p 25432 -U postgres -c "create schema teryt;"
Następnie przywracamy kilka wybranych tabel i indeksów do schematów public i prg:
pg_restore --jobs 2 --no-owner -n public -d gis -h localhost -p 25432 -U postgres db.bak
pg_restore --jobs 2 --no-owner -n prg -t delta -I delta_gis -I delta_lokalnyid -I delta_simc -d gis -h localhost -p 25432 -U postgres db.bak
pg_restore --jobs 2 --no-owner -n teryt -d gis -h localhost -p 25432 -U postgres db.bak
Na końcu trzeba podać ścieżkę do pliku, jeżeli nie znajduje się w tym folderze, w którym mamy otworzoną konsole.
Najpierw przygotowujemy plik .env w folderze conf/ na podstawie .env_example gdzie podajemy IP bazy PostgreSQL, użytkownika, hasło oraz nazwę bazy danych.
IP podajemy dla kontenera od bazy danych (jeżeli baza była uruchamiana instrukcjami powyżej). Można to sprawdzić komendą:
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' postgis
(gdzie postgis to nazwa kontenera z bazą danych).
Zwróć uwagę, że podajemy port, pod którym postgres jest uruchomiony w kontenerze, ponieważ kontenery rozmawiają ze sobą w jednej sieci wirtualnej, trochę inaczej niż kontener z hostem.
Przechodzimy w konsoli do folderu gdzie mamy sklonowane repozytorium (do folderu gdzie jest Dockerfile) i uruchamiamy:
docker build -t gugik2osm .
-t gugik2osm - oznacza nazwę dla naszego obrazu, można zmienić
. - oznacza obecną lokalizację
Następnie uruchamiamy kontener (windows):
docker run --rm -p 45000:80 `
--mount type=bind,source=C:/Users/Tomasz/PycharmProjects/gugik2osm/app,target=/opt/gugik2osm/app `
--mount type=bind,source=C:/Users/Tomasz/PycharmProjects/gugik2osm/web,target=/opt/gugik2osm/web `
--mount type=bind,source=C:/Users/Tomasz/PycharmProjects/gugik2osm/processing,target=/opt/gugik2osm/git/processing `
-it gugik2osm
--rm - powoduje że po wyłączeniu kontenera jest on automatycznie usuwany
-p 45000:80 - mapowanie portów, numer po lewej oznacza pod jakim portem będziemy mogli się połączyć do kontenera z "zewnątrz" czyli naszej maszyny
--mount type=bind,source=C:/Users/Tomasz/PycharmProjects/gugik2osm/app,target=/opt/gugik2osm/app - montuje katalog z naszej maszyny w określonym miejscu w kontenerze, trzeba podawać ścieżki absolutne, zmień lewą część na swoją ścieżkę, tak by prowadziła do folderów app, web i processing w sklonowanym repozytorium
-it - przeciwieństwo -d, uruchamia kontener "na pierwszym planie", dzięki czemu będziemy mogli wykonywać w nim komendy w razie potrzeby
gugik2osm - nazwa obrazu, który zbudowaliśmy w poprzednim kroku
Po uruchomieniu kontenera odpali się terminal bash.
Ostatnią rzeczą, jaką powinniśmy zmienić, jest url dla serwera z kafelkami MVT. W pliku web/map.js znajdujemy fragment:
var updatesLayerURL = "https://budynki.openstreetmap.org.pl/updates.geojson";
var vectorTilesURL = "https://budynki.openstreetmap.org.pl/tiles/{z}/{x}/{y}.pbf";
var overpass_layers_url = "https://budynki.openstreetmap.org.pl/overpass-layers.json";
var downloadable_layers_url = "https://budynki.openstreetmap.org.pl/layers/";
i zamieniamy url na:
var updatesLayerURL = "http://localhost:45000/updates.geojson";
var vectorTilesURL = "http://localhost:45000/tiles/{z}/{x}/{y}.pbf";
var overpass_layers_url = "http://localhost:45000/overpass-layers.json";
var downloadable_layers_url = "http://localhost:45000/layers/";
(port podajemy taki jaki ustawiliśmy w parametrze -p dla kontenera aplikacji).
Wszystkie zmiany dla plików HTML/JS i Python powinny być automatycznie widoczne po odświeżeniu strony (rzeczy typu pliki js mogą wymagać odświeżenia wraz z usunięciem cache: ctrl+f5).
W przeglądarce przejdź do http://localhost:45000 (lub pod innym portem zależnie od tego, co zostało ustawione w komendzie docker run).
Jeżeli pracujemy w systemie Windows, to możemy użyć pomocniczego skryptu PowerShell: run_local_tests_windows.ps1.