#!/bin/bash # -------------------------------------------------------------------------- # apply-delta.sh # Exports approved candidate_roads from PostGIS as OSM XML, then merges # them into master_map.osm.pbf so GraphHopper routes on them. # # Usage: bash apply-delta.sh [APP_DIR] [MASTER_PBF] [DELTA_OSM] # -------------------------------------------------------------------------- set -e APP_DIR="${1:-/home/hamzadoctor/app}" MASTER_PBF="${2:-${APP_DIR}/infrastructure/osm-data/master_map.osm.pbf}" DELTA_OSM="${3:-${APP_DIR}/infrastructure/osm-data/delta.osm}" MERGED_PBF="${MASTER_PBF%.pbf}_merged.pbf" cd "${APP_DIR}" echo "đŸ›Ŗī¸ Exporting approved roads from PostGIS → ${DELTA_OSM}..." # Build valid OSM XML in pure SQL (nodes declared before ways, matching negative # IDs). No python/psycopg2 is needed in the db container. Source is approved_roads # (snapped-to-network geometry, EPSG:4326); each LineString becomes one . # # Junction connectivity: if a road has start_node/end_node (real OSM node ids the # API resolved at approval time), the first/last points at that REAL node # instead of a fresh one — so after osmium-merge the way shares a node with the # existing highway and GraphHopper routes THROUGH it. Interior vertices (and any # endpoint with no resolved node) get fresh negative-id nodes as before. docker compose exec -T db psql -U mapuser -d mapdb -t -A -X > "${DELTA_OSM}" 2>/dev/null <<'SQL' WITH ways AS ( SELECT id, confidence, "uniqueDriverCount" AS drivers, COALESCE(highway, 'residential') AS highway, COALESCE(oneway, 0) AS oneway, start_node, end_node, ROW_NUMBER() OVER (ORDER BY id) AS way_seq FROM approved_roads ), pts AS ( SELECT w.way_seq, w.confidence, w.drivers, w.highway, w.oneway, w.start_node, w.end_node, dp.path[1] AS pt_order, COUNT(*) OVER (PARTITION BY w.way_seq) AS npts, ST_Y(dp.geom) AS lat, ST_X(dp.geom) AS lon FROM ways w JOIN approved_roads ar ON ar.id = w.id, LATERAL ST_DumpPoints(ar.geometry) AS dp ), pts_numbered AS ( SELECT *, ROW_NUMBER() OVER (ORDER BY way_seq, pt_order) AS gseq FROM pts ), pts_ref AS ( SELECT *, CASE WHEN pt_order = 1 AND start_node IS NOT NULL THEN start_node WHEN pt_order = npts AND end_node IS NOT NULL THEN end_node ELSE -1000000 - gseq END AS node_ref, NOT ( (pt_order = 1 AND start_node IS NOT NULL) OR (pt_order = npts AND end_node IS NOT NULL) ) AS emit_node FROM pts_numbered ), nodes_xml AS ( SELECT string_agg( format(' ', node_ref, lat, lon), E'\n' ORDER BY gseq) AS x FROM pts_ref WHERE emit_node ), ways_xml AS ( SELECT string_agg(w.x, E'\n') AS x FROM ( SELECT format( ' %s%s%s%s%s%s ', -way_seq, string_agg(format(E'\n ', node_ref), '' ORDER BY pt_order), format(E'\n ', min(highway)), E'\n ', format(E'\n ', round(min(confidence)::numeric, 2)), format(E'\n ', min(drivers)), CASE WHEN min(oneway) = 1 THEN E'\n ' WHEN min(oneway) = -1 THEN E'\n ' ELSE '' END ) AS x FROM pts_ref GROUP BY way_seq ) w ) SELECT format( E'\n\n%s\n%s\n', COALESCE((SELECT x FROM nodes_xml), ''), COALESCE((SELECT x FROM ways_xml), '') ); SQL # Bail out cleanly if there are no approved roads yet. if ! grep -q '/dev/null; then echo "â„šī¸ No approved roads to export. Skipping delta merge." rm -f "${DELTA_OSM}" exit 0 fi echo "✅ Exported $(grep -c ' /dev/null; then # osmium merge requires inputs sorted by (type, id). Our SQL emits nodes in # descending-id order, so sort the delta first — otherwise merge is undefined. SORTED_OSM="${DELTA_OSM%.osm}_sorted.osm" echo "🔃 Sorting delta (osmium requires sorted input)..." osmium sort "${DELTA_OSM}" -o "${SORTED_OSM}" --overwrite echo "🔀 Merging delta → ${MASTER_PBF} with osmium..." osmium merge "${MASTER_PBF}" "${SORTED_OSM}" -o "${MERGED_PBF}" --overwrite mv "${MERGED_PBF}" "${MASTER_PBF}" rm -f "${SORTED_OSM}" echo "✅ Master PBF updated with approved roads (endpoints share real OSM nodes where resolved)." else echo "âš ī¸ osmium not found on host." # On Debian/Ubuntu: apt-get install -y osmium-tool # On Mac: brew install osmium-tool echo " Please install osmium-tool: https://osmcode.org/osmium-tool/" echo " Approved roads saved to ${DELTA_OSM} for manual merge." fi echo "🏁 Delta apply complete."