From f3f8b9804e22cf2dfc39ee962983823e698fb80f Mon Sep 17 00:00:00 2001 From: Jiri Kozel Date: Wed, 14 Nov 2018 15:26:24 +0100 Subject: [PATCH] Improve 3D buildings (#533) Add `hide_3d` building attribute to hide some building parts in 3D. Fix #128 --- layers/building/building.sql | 41 ++++++++++++++++++++++------------- layers/building/building.yaml | 4 +++- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/layers/building/building.sql b/layers/building/building.sql index 53902b11..372142d6 100644 --- a/layers/building/building.sql +++ b/layers/building/building.sql @@ -14,6 +14,7 @@ $$ STRICT LANGUAGE plpgsql IMMUTABLE; CREATE INDEX IF NOT EXISTS osm_building_relation_building_idx ON osm_building_relation(building); +CREATE INDEX IF NOT EXISTS osm_building_relation_member_idx ON osm_building_relation(member); --CREATE INDEX IF NOT EXISTS osm_building_associatedstreet_role_idx ON osm_building_associatedstreet(role); --CREATE INDEX IF NOT EXISTS osm_building_street_role_idx ON osm_building_street(role); @@ -24,7 +25,8 @@ CREATE OR REPLACE VIEW osm_all_buildings AS ( COALESCE(nullif(as_numeric(height),-1),nullif(as_numeric(buildingheight),-1)) as height, COALESCE(nullif(as_numeric(min_height),-1),nullif(as_numeric(buildingmin_height),-1)) as min_height, COALESCE(nullif(as_numeric(levels),-1),nullif(as_numeric(buildinglevels),-1)) as levels, - COALESCE(nullif(as_numeric(min_level),-1),nullif(as_numeric(buildingmin_level),-1)) as min_level + COALESCE(nullif(as_numeric(min_level),-1),nullif(as_numeric(buildingmin_level),-1)) as min_level, + FALSE as hide_3d FROM osm_building_relation WHERE building = '' UNION ALL @@ -35,7 +37,8 @@ CREATE OR REPLACE VIEW osm_all_buildings AS ( COALESCE(nullif(as_numeric(height),-1),nullif(as_numeric(buildingheight),-1)) as height, COALESCE(nullif(as_numeric(min_height),-1),nullif(as_numeric(buildingmin_height),-1)) as min_height, COALESCE(nullif(as_numeric(levels),-1),nullif(as_numeric(buildinglevels),-1)) as levels, - COALESCE(nullif(as_numeric(min_level),-1),nullif(as_numeric(buildingmin_level),-1)) as min_level + COALESCE(nullif(as_numeric(min_level),-1),nullif(as_numeric(buildingmin_level),-1)) as min_level, + FALSE as hide_3d FROM osm_building_associatedstreet WHERE role = 'house' UNION ALL @@ -45,7 +48,8 @@ CREATE OR REPLACE VIEW osm_all_buildings AS ( COALESCE(nullif(as_numeric(height),-1),nullif(as_numeric(buildingheight),-1)) as height, COALESCE(nullif(as_numeric(min_height),-1),nullif(as_numeric(buildingmin_height),-1)) as min_height, COALESCE(nullif(as_numeric(levels),-1),nullif(as_numeric(buildinglevels),-1)) as levels, - COALESCE(nullif(as_numeric(min_level),-1),nullif(as_numeric(buildingmin_level),-1)) as min_level + COALESCE(nullif(as_numeric(min_level),-1),nullif(as_numeric(buildingmin_level),-1)) as min_level, + FALSE as hide_3d FROM osm_building_street WHERE role = 'house' UNION ALL @@ -56,29 +60,35 @@ CREATE OR REPLACE VIEW osm_all_buildings AS ( COALESCE(nullif(as_numeric(height),-1),nullif(as_numeric(buildingheight),-1)) as height, COALESCE(nullif(as_numeric(min_height),-1),nullif(as_numeric(buildingmin_height),-1)) as min_height, COALESCE(nullif(as_numeric(levels),-1),nullif(as_numeric(buildinglevels),-1)) as levels, - COALESCE(nullif(as_numeric(min_level),-1),nullif(as_numeric(buildingmin_level),-1)) as min_level + COALESCE(nullif(as_numeric(min_level),-1),nullif(as_numeric(buildingmin_level),-1)) as min_level, + FALSE as hide_3d FROM osm_building_polygon obp WHERE EXISTS (SELECT 1 FROM osm_building_multipolygon obm WHERE obp.osm_id = obm.osm_id) UNION ALL -- etldoc: osm_building_polygon -> layer_building:z14_ -- Standalone buildings - SELECT osm_id,geometry, - COALESCE(nullif(as_numeric(height),-1),nullif(as_numeric(buildingheight),-1)) as height, - COALESCE(nullif(as_numeric(min_height),-1),nullif(as_numeric(buildingmin_height),-1)) as min_height, - COALESCE(nullif(as_numeric(levels),-1),nullif(as_numeric(buildinglevels),-1)) as levels, - COALESCE(nullif(as_numeric(min_level),-1),nullif(as_numeric(buildingmin_level),-1)) as min_level + SELECT obp.osm_id,obp.geometry, + COALESCE(nullif(as_numeric(obp.height),-1),nullif(as_numeric(obp.buildingheight),-1)) as height, + COALESCE(nullif(as_numeric(obp.min_height),-1),nullif(as_numeric(obp.buildingmin_height),-1)) as min_height, + COALESCE(nullif(as_numeric(obp.levels),-1),nullif(as_numeric(obp.buildinglevels),-1)) as levels, + COALESCE(nullif(as_numeric(obp.min_level),-1),nullif(as_numeric(obp.buildingmin_level),-1)) as min_level, + CASE WHEN obr.role='outline' THEN TRUE ELSE FALSE END as hide_3d FROM - osm_building_polygon WHERE osm_id >= 0 + osm_building_polygon obp + LEFT JOIN osm_building_relation obr ON (obr.member = obp.osm_id) + WHERE obp.osm_id >= 0 ); CREATE OR REPLACE FUNCTION layer_building(bbox geometry, zoom_level int) -RETURNS TABLE(geometry geometry, osm_id bigint, render_height int, render_min_height int) AS $$ - SELECT geometry, osm_id, render_height, render_min_height +RETURNS TABLE(geometry geometry, osm_id bigint, render_height int, render_min_height int, hide_3d boolean) AS $$ + SELECT geometry, osm_id, render_height, render_min_height, + CASE WHEN hide_3d THEN TRUE ELSE NULL::boolean END AS hide_3d FROM ( -- etldoc: osm_building_polygon_gen1 -> layer_building:z13 SELECT osm_id, geometry, - NULL::int AS render_height, NULL::int AS render_min_height + NULL::int AS render_height, NULL::int AS render_min_height, + FALSE AS hide_3d FROM osm_building_polygon_gen1 WHERE zoom_level = 13 AND geometry && bbox UNION ALL @@ -86,8 +96,9 @@ RETURNS TABLE(geometry geometry, osm_id bigint, render_height int, render_min_he SELECT DISTINCT ON (osm_id) osm_id, geometry, ceil( COALESCE(height, levels*3.66,5))::int AS render_height, - floor(COALESCE(min_height, min_level*3.66,0))::int AS render_min_height FROM - osm_all_buildings + floor(COALESCE(min_height, min_level*3.66,0))::int AS render_min_height, + hide_3d + FROM osm_all_buildings WHERE (levels IS NULL OR levels < 1000) AND (min_level IS NULL OR min_level < 1000) AND diff --git a/layers/building/building.yaml b/layers/building/building.yaml index 7e391b59..51652000 100644 --- a/layers/building/building.yaml +++ b/layers/building/building.yaml @@ -5,12 +5,14 @@ layer: this is welcomed. buffer_size: 4 datasource: - query: (SELECT geometry, render_height, render_min_height FROM layer_building(!bbox!, z(!scale_denominator!))) AS t + query: (SELECT geometry, render_height, render_min_height, hide_3d FROM layer_building(!bbox!, z(!scale_denominator!))) AS t fields: render_height: | An approximated height from levels and height of the building or building:part after the method of Paul Norman in [OSM Clear](https://github.com/ClearTables/osm-clear). For future 3D rendering of buildings. render_min_height: | An approximated height from levels and height of the bottom of the building or building:part after the method of Paul Norman in [OSM Clear](https://github.com/ClearTables/osm-clear). For future 3D rendering of buildings. + hide_3d: | + If True, building (part) should not be rendered in 3D. Currently, [building outlines](https://wiki.openstreetmap.org/wiki/Simple_3D_buildings) are marked as hide_3d. schema: - ./building.sql datasources: