#!/usr/bin/env bash # Second half of tools/geodata/backcountry-osm/build (runs in the geotools image; no database): the `routes` layer, then # one tileset (docs/backcountry/PLAN.md B2.2a). Planetiler's YAML schemas can't read route relations, so route=canoe, # hiking and foot relations (GDAL's `multilinestrings`) are read with GDAL's OSM driver, tiled with tippecanoe (z8-14) # (the relation id as the feature id, for snapping) and joined with Planetiler's portages, water and camp layers (tile-join). The result stays one ODbL tileset, stamped # with the licence, the 4.6 offer and the extract date (pmtiles_meta.py), and never holds non-OSM data. # # HG_OSM_PBF=/data/downloads/osm/.osm.pbf HG_FEATURES=/data/build/backcountry-osm-features.pmtiles \ # tools/geodata/run backcountry-osm/routes set -euo pipefail HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" log() { printf '\033[1;32m==>\033[0m %s\n' "$*"; } die() { printf '\033[1;31merror:\033[0m %s\n' "$*" >&2; exit 1; } PBF="${HG_OSM_PBF:?HG_OSM_PBF is required}" FEATURES="${HG_FEATURES:?HG_FEATURES is required}" [[ -f "$PBF" ]] || die "no OSM file at $PBF" [[ -f "$FEATURES" ]] || die "no features tileset at $FEATURES" BUILD_DIR="${HG_BUILD_DIR:-/tmp/hg-build}/backcountry-osm" rm -rf "$BUILD_DIR" && mkdir -p "$BUILD_DIR" # The extract's date: its replication timestamp as Planetiler read it, else the file's date (curl -R keeps the server's). extract_day="$(python3 -I -c 'import sys; sys.path.insert(0, sys.argv[2]); import pmtiles_meta print(pmtiles_meta.read_metadata(sys.argv[1]).get("planetiler:osm:osmosisreplicationtime", "")[:10])' "$FEATURES" "$HERE/../lib")" VERSION="OpenStreetMap ${extract_day:-$(date -u -r "$PBF" +%Y-%m-%d)}" ROUTES="'canoe','hiking','foot'" # Backcountry's source register (B0.2): refuses the run if OpenStreetMap's entry were ever blocked or unregistered. python3 -I "$HERE/../republishing/republishing.py" backcountry-require dataset:backcountry-osm log "Canoe and hiking route relations from $(basename "$PBF")" ogr2ogr -f GeoJSONSeq "$BUILD_DIR/routes.geojsonl" "$PBF" -oo CONFIG_FILE="$HERE/osmconf-backcountry.ini" \ -dialect SQLite -sql "select cast(osm_id as integer) as id, route, name, ref, network, operator, geometry from multilinestrings where route in ($ROUTES)" \ --config CPL_TMPDIR "$BUILD_DIR" --config OSM_MAX_TMPFILE_SIZE 4096 --config OSM_COMPRESS_NODES YES \ 2> "$BUILD_DIR/routes.err" || { cat "$BUILD_DIR/routes.err" >&2; die "ogr2ogr (routes) failed"; } if grep -q '^ERROR' "$BUILD_DIR/routes.err"; then cat "$BUILD_DIR/routes.err" >&2; die "GDAL reported errors (routes)"; fi features="$(wc -l <"$BUILD_DIR/routes.geojsonl")" log "$features route relations" cp "$FEATURES" "$BUILD_DIR/features.pmtiles" inputs=("$BUILD_DIR/features.pmtiles") # tippecanoe refuses an empty input: a region without canoe or hiking routes gets no routes layer. if (( features > 0 )); then tippecanoe -o "$BUILD_DIR/routes.pmtiles" -t "$BUILD_DIR" --force --quiet -l routes -Z8 -z14 \ --use-attribute-for-id=id --drop-densest-as-needed "$BUILD_DIR/routes.geojsonl" inputs+=("$BUILD_DIR/routes.pmtiles") fi tile-join -o "$BUILD_DIR/backcountry-osm.pmtiles" -f -q -pk -n "HuntGrid Backcountry OSM" \ -A '© OpenStreetMap contributors' \ "${inputs[@]}" # The ODbL notice, licence URI, 4.6 offer and extract date in the file's own metadata (F20.15). python3 "$HERE/../lib/pmtiles_meta.py" odbl "$BUILD_DIR/backcountry-osm.pmtiles" backcountry-osm "$VERSION" mkdir -p /data/tiles cp "$BUILD_DIR/backcountry-osm.pmtiles" /data/tiles/.backcountry-osm.pmtiles.part mv -f /data/tiles/.backcountry-osm.pmtiles.part /data/tiles/backcountry-osm.pmtiles rm -rf "$BUILD_DIR" log "Done: data/tiles/backcountry-osm.pmtiles ($VERSION)"