- JavaScript 100%
| config | ||
| sql | ||
| src | ||
| .gitignore | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
Build Pipes (Geofabrik → DuckDB + MBTiles)
Erzeugt aus einem Geofabrik-OSM-Extrakt zwei kompakte Artefakte für das Leitstellenspiel:
gis.duckdb– DuckDB mit Spatial-Extension für Einsatzort-Generierung, Platzierungsprüfungen, Adress-Kontext.gis.mbtiles– Vektor-Tiles (MBTiles/SQLite) für MapLibre GL JS.
Build-Prozess, kein Bestandteil des Spiel-Servers. Der Ordner ist selbstständig und kann in ein eigenes Repository verschoben werden.
Voraussetzungen
- Node.js ≥ 20
- Internetzugang (Geofabrik-Download, DuckDB-Spatial-Extension)
Technik
Die Pipeline nutzt @duckdb/node-api (offizieller DuckDB-Nachfolger des
alten duckdb-Pakets, Core ≥ 1.5). Die Spatial-Extension wird über
SET extension_directory in das eigene data/extensions/ installiert und
per LOAD spatial geladen. Der Spiel-Server verwendet eine getrennte Kopie
unter <repo>/data/extensions/ und öffnet die Artefakt-Datei read-only.
Tile-Generierung ist Node-only und ohne externe C++-Tools:
| Schritt | Bibliothek |
|---|---|
| Features in Chunks aus DuckDB lesen | @duckdb/node-api |
| GeoJSON in Tile-Index schneiden | geojson-vt v3 |
| Tile-Geometrie zu MVT (PBF) serialisieren | vt-pbf v3 |
| MVT in SQLite-MBTiles schreiben | better-sqlite3 |
Die Chunk-Größe ist konfigurierbar (tiles.chunkSize); die Strategie ist
unabhängig von der Quell-Region-Größe immer dieselbe.
Nutzung
npm install
npm run build -- --region bremen # oder: npm run build -- bremen
npm run build -- --region niedersachsen # groß: ~1,2 GB Download
npm run build -- --region bremen --refresh # Download + Build erzwingen
npm run clean # raw/build-Dateien entfernen
Artefakte nach erfolgreichem Build:
data/dist/gis.duckdb– DuckDB-Geodatenbankdata/tiles/gis.mbtiles– MapLibre-Vector-Tiles
Spiel-Server: Zeigt mit GEODATA_FILE=osm-pipeline/data/dist/gis.duckdb
(relativ zum Repo) auf das DuckDB-Artefakt; die Region des Servers wird über
REGION_BBOX=minLng,minLat,maxLng,maxLat eingestellt (z. B. für Niedersachsen
REGION_BBOX=6.6,51.3,11.6,53.9).
Ablauf
- PBF herunterladen (Cache in
data/raw/, Größen- und OSMHeader-Prüfung) - DuckDB-Arbeitsdatenbank in
data/build/anlegen ST_ReadOSM('<pbf>')→ Element-Staging (nodes/ways); Geometrien werden selbst aufgebaut: Punkte auslat/lon, Linien und geschlossene Polygone ausrefs-Knoten (WKT viaST_GeomFromText;ST_MakePolygonfür geschlossene Wege)- Layer-Tabellen erzeugen (
sql/*.sql):roads,buildings,places,water,landuse,pois - Indizes: Zonen-B-Trees (
zone_x/zone_y, 0,05°-Raster) + räumliche RTREE-Indizes; Metadaten-Tabelle - Validierung (Row-Counts, Geometrien, BBOX-Plausibilität)
- Tile-Build (siehe unten)
- Atomare Veröffentlichung (Kopie + Rename) nach
data/dist/gis.duckdb
Tile-Build
Pro Layer-Tabelle wird ein Tile-Layer erzeugt. Die Trennung
Polygon/LineString erfolgt im SQL per ST_GeometryType(...):
| Tile-Layer | Quell-Tabelle | Geometrie-Typ | Property-Mapping |
|---|---|---|---|
roads |
roads |
LINESTRING | class = highway |
water |
water |
POLYGON | class = water|natural |
waterway |
water (waterway != null) |
LINESTRING | class = waterway|water|natural |
landuse |
landuse |
POLYGON | class = landuse|natural |
buildings |
buildings |
POLYGON | class = building |
places |
places |
POINT | class = place, population |
pois |
pois |
POINT | class = amenity|shop|tourism |
Ablauf pro Layer:
COUNT(*)ermitteln.- In Chunks (
LIMIT … OFFSET …) lesen, GeoJSON-Features parsen. - Features an
geojson-vt()übergeben → Tile-Index. - Alle Tile-Koordinaten über Layer hinweg sammeln.
- Pro Koordinate aus jedem Layer einen
getTile(z,x,y)ziehen, in einem Objekt{ [sourceLayer]: tile }zusammenführen. - Mit
vt-pbf.fromGeojsonVt(...)zu MVT-PBF kodieren. - Als XYZ-Koordinate in SQLite-MBTiles schreiben
(
tile_rowwird via(1 << z) - 1 - yins TMS-Schema konvertiert).
Die Tile-Konfiguration liegt unter config/pipeline.json → tiles:
{
"tiles": {
"output": "data/tiles/gis.mbtiles",
"minZoom": 0,
"maxZoom": 16,
"buffer": 64,
"tolerance": 3,
"chunkSize": 50000,
"extent": 4096
}
}
Zum Abschalten der Tile-Erzeugung: "tiles": false.
Datenmodell
Alle Geometrien in EPSG:4326 (OSM lat/lon). Jede Geometrietabelle:
| Tabelle | Spalten |
|---|---|
roads |
id, geometry, highway, name |
buildings |
id, geometry, building, name, addr_street, addr_housenumber |
places |
id, geometry, place, name, population |
water |
id, geometry, water, natural, waterway, name |
landuse |
id, geometry, landuse, natural, name |
pois |
id, geometry, amenity, shop, tourism, name |
metadata |
key, value (Region, Quelle, Datum, Version, CRS) |
Konfiguration
config/pipeline.json– Pfade (raw/build/extensions/output/tiles), DuckDB-Ressourcen, Tile-Konfigurationconfig/regions.json– Regionen: Geofabrik-URL, Größen-Hinweis, optionale BBOX (BBOX filtert die Layer-Tabellen auf das Spielgebiet)
Fehlerbehandlung
Jeder Schritt bricht bei Fehlern mit einer aussagekräftigen Meldung ab
(non-zero Exit-Code). Ein fehlerhafter Build veröffentlicht kein Artefakt;
vorhandene gis.duckdb/gis.mbtiles bleiben unangetastet.