Pipeline zum Import der neusten Daten für den Server.
  • JavaScript 100%
Find a file
2026-08-30 17:53:12 +00:00
config Build-Pipes: Geofabrik PBF -> DuckDB (Spatial) + MBTiles Vektor-Tiles 2026-08-30 17:51:33 +00:00
sql Build-Pipes: Geofabrik PBF -> DuckDB (Spatial) + MBTiles Vektor-Tiles 2026-08-30 17:51:33 +00:00
src fix(probe-index): await openDatabase (Promise war nicht awaited) 2026-08-30 17:53:12 +00:00
.gitignore Build-Pipes: Geofabrik PBF -> DuckDB (Spatial) + MBTiles Vektor-Tiles 2026-08-30 17:51:33 +00:00
package-lock.json Build-Pipes: Geofabrik PBF -> DuckDB (Spatial) + MBTiles Vektor-Tiles 2026-08-30 17:51:33 +00:00
package.json Build-Pipes: Geofabrik PBF -> DuckDB (Spatial) + MBTiles Vektor-Tiles 2026-08-30 17:51:33 +00:00
README.md Build-Pipes: Geofabrik PBF -> DuckDB (Spatial) + MBTiles Vektor-Tiles 2026-08-30 17:51:33 +00:00

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-Geodatenbank
  • data/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

  1. PBF herunterladen (Cache in data/raw/, Größen- und OSMHeader-Prüfung)
  2. DuckDB-Arbeitsdatenbank in data/build/ anlegen
  3. ST_ReadOSM('<pbf>') → Element-Staging (nodes/ways); Geometrien werden selbst aufgebaut: Punkte aus lat/lon, Linien und geschlossene Polygone aus refs-Knoten (WKT via ST_GeomFromText; ST_MakePolygon für geschlossene Wege)
  4. Layer-Tabellen erzeugen (sql/*.sql): roads, buildings, places, water, landuse, pois
  5. Indizes: Zonen-B-Trees (zone_x/zone_y, 0,05°-Raster) + räumliche RTREE-Indizes; Metadaten-Tabelle
  6. Validierung (Row-Counts, Geometrien, BBOX-Plausibilität)
  7. Tile-Build (siehe unten)
  8. 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:

  1. COUNT(*) ermitteln.
  2. In Chunks (LIMIT … OFFSET …) lesen, GeoJSON-Features parsen.
  3. Features an geojson-vt() übergeben → Tile-Index.
  4. Alle Tile-Koordinaten über Layer hinweg sammeln.
  5. Pro Koordinate aus jedem Layer einen getTile(z,x,y) ziehen, in einem Objekt { [sourceLayer]: tile } zusammenführen.
  6. Mit vt-pbf.fromGeojsonVt(...) zu MVT-PBF kodieren.
  7. Als XYZ-Koordinate in SQLite-MBTiles schreiben (tile_row wird via (1 << z) - 1 - y ins 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-Konfiguration
  • config/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.