From 07ec07b7b3900db277157498ee33d294714910cc Mon Sep 17 00:00:00 2001 From: grigo Date: Tue, 23 Jun 2026 10:39:05 +0300 Subject: [PATCH] added bootstrap buildings --- README.md | 4 ++- db/init/01_postgis.sql | 1 + db/sql/normalize_buildings.sql | 56 ++++++++++++++++++++++++++++++++++ scripts/load_buildings.sh | 23 +++++++------- 4 files changed, 72 insertions(+), 12 deletions(-) create mode 100644 db/sql/normalize_buildings.sql diff --git a/README.md b/README.md index d6934c1..6becba8 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,9 @@ docker compose restart api worker ``` The script builds a local `radio-osm2pgsql:latest` image from -`scripts/Dockerfile.osm2pgsql` on first run. +`scripts/Dockerfile.osm2pgsql` on first run. It imports the PBF through standard +`osm2pgsql` tables, then normalizes `planet_osm_polygon` into the API `buildings` +table with `db/sql/normalize_buildings.sql`. The import writes a `buildings` table with `geom`, `height_m`, `levels`, `building_type`, and `source`. Heights come from `height`, then diff --git a/db/init/01_postgis.sql b/db/init/01_postgis.sql index 576e542..67a0700 100644 --- a/db/init/01_postgis.sql +++ b/db/init/01_postgis.sql @@ -1 +1,2 @@ CREATE EXTENSION IF NOT EXISTS postgis; +CREATE EXTENSION IF NOT EXISTS hstore; diff --git a/db/sql/normalize_buildings.sql b/db/sql/normalize_buildings.sql new file mode 100644 index 0000000..84e4919 --- /dev/null +++ b/db/sql/normalize_buildings.sql @@ -0,0 +1,56 @@ +DROP TABLE IF EXISTS buildings CASCADE; + +CREATE TABLE buildings AS +WITH raw AS ( + SELECT + osm_id, + way, + NULLIF(building, '') AS building_type, + substring(replace(COALESCE(tags -> 'height', ''), ',', '.') FROM '[-+]?[0-9]+(\.[0-9]+)?')::real + AS height_value, + substring(replace(COALESCE(tags -> 'building:levels', ''), ',', '.') FROM '[-+]?[0-9]+(\.[0-9]+)?')::real + AS levels_value + FROM planet_osm_polygon + WHERE building IS NOT NULL + AND building <> '' + AND building <> 'no' +), +normalized AS ( + SELECT + osm_id, + ST_Multi(ST_CollectionExtract(ST_MakeValid(way), 3)) AS geom, + building_type, + height_value, + levels_value + FROM raw +) +SELECT + osm_id, + geom, + CASE + WHEN height_value IS NOT NULL AND height_value > 0 THEN height_value + WHEN levels_value IS NOT NULL AND levels_value > 0 THEN levels_value * 3.0 + WHEN building_type IN ('garage', 'garages', 'shed') THEN 3.0 + WHEN building_type IN ('industrial', 'warehouse') THEN 8.0 + WHEN building_type IN ('church', 'cathedral') THEN 12.0 + ELSE 9.0 + END::real AS height_m, + CASE + WHEN levels_value IS NOT NULL AND levels_value > 0 THEN levels_value::integer + ELSE NULL + END AS levels, + building_type, + CASE + WHEN height_value IS NOT NULL AND height_value > 0 THEN 'measured' + ELSE 'estimated' + END AS source +FROM normalized +WHERE NOT ST_IsEmpty(geom); + +ALTER TABLE buildings ALTER COLUMN geom TYPE geometry(MultiPolygon, 4326) + USING ST_SetSRID(geom, 4326); + +CREATE INDEX IF NOT EXISTS buildings_geom_gix ON buildings USING GIST (geom); +CREATE INDEX IF NOT EXISTS buildings_height_idx ON buildings (height_m); +CREATE INDEX IF NOT EXISTS buildings_type_idx ON buildings (building_type); +ANALYZE buildings; diff --git a/scripts/load_buildings.sh b/scripts/load_buildings.sh index df538d4..263cda9 100644 --- a/scripts/load_buildings.sh +++ b/scripts/load_buildings.sh @@ -54,14 +54,20 @@ docker compose exec -T "$POSTGIS_SERVICE" psql -U "$DB_USER" -d "$DB_NAME" \ echo "Drop previous buildings table" docker compose exec -T "$POSTGIS_SERVICE" psql -U "$DB_USER" -d "$DB_NAME" \ - -c "DROP TABLE IF EXISTS buildings CASCADE;" + -c "DROP TABLE IF EXISTS buildings CASCADE; + DROP TABLE IF EXISTS planet_osm_point CASCADE; + DROP TABLE IF EXISTS planet_osm_line CASCADE; + DROP TABLE IF EXISTS planet_osm_polygon CASCADE; + DROP TABLE IF EXISTS planet_osm_roads CASCADE; + DROP TABLE IF EXISTS planet_osm_nodes CASCADE; + DROP TABLE IF EXISTS planet_osm_ways CASCADE; + DROP TABLE IF EXISTS planet_osm_rels CASCADE;" echo "Import buildings from $PBF_PATH" docker run --rm \ --network "$NETWORK" \ -e PGPASSWORD="$DB_PASSWORD" \ -v "$PBF_DIR:/osm:ro" \ - -v "$SCRIPT_DIR:/scripts:ro" \ "$OSM2PGSQL_IMAGE" \ -H "$POSTGIS_SERVICE" \ -P 5432 \ @@ -71,16 +77,11 @@ docker run --rm \ --slim \ --drop \ --latlong \ - --output flex \ - --style /scripts/osm2pgsql_buildings.lua \ + --hstore \ "/osm/$PBF_FILE" -echo "Create buildings indexes" -docker compose exec -T "$POSTGIS_SERVICE" psql -U "$DB_USER" -d "$DB_NAME" <<'SQL' -CREATE INDEX IF NOT EXISTS buildings_geom_gix ON buildings USING GIST (geom); -CREATE INDEX IF NOT EXISTS buildings_height_idx ON buildings (height_m); -CREATE INDEX IF NOT EXISTS buildings_type_idx ON buildings (building_type); -ANALYZE buildings; -SQL +echo "Normalize buildings table" +docker compose exec -T "$POSTGIS_SERVICE" psql -U "$DB_USER" -d "$DB_NAME" \ + < "$REPO_DIR/db/sql/normalize_buildings.sql" echo "Buildings import complete"