diff --git a/task-force-docs/base/infrastructure.sql b/task-force-docs/base/infrastructure.sql new file mode 100644 index 00000000..f5c23641 --- /dev/null +++ b/task-force-docs/base/infrastructure.sql @@ -0,0 +1,289 @@ +SELECT + -- Needed to compute ID and satisfy Overture requirements: + type, + id, + version, + min_lon, + max_lon, + min_lat, + max_lat, + created_at AS update_time, + -- Determine class from subclass or tags + CASE + -- Bus / Ferry / Railway Infrastructure (Transit) + WHEN subclass IN ( + 'bus_route', + 'bus_stop', + 'bus_station', + -- 'ferry_route', + 'ferry_terminal', + 'railway_halt', + 'railway_station' + ) THEN 'transit' + + -- Aerialways + WHEN subclass IN ( + 'aerialway_station', + 'cable_car', + 'gondola', + 'mixed_lift', + 'chair_lift', + 'drag_lift', + 't-bar' + ) THEN 'aerialway' + + WHEN subclass IN ( + 'airport', + 'airstrip', + 'helipad', + 'heliport', + 'international_airport', + 'military_airport', + 'municipal_airport', + 'private_airport', + 'regional_airport', + 'runway', + 'seaplane_airport', + 'taxiway' + ) THEN 'airport' + + -- Bridges + WHEN subclass IN ( + 'bridge', + 'viaduct', + 'boardwalk', + 'aqueduct', + 'movable', + 'covered', + 'cantilever', + 'trestle' + ) THEN 'bridge' + + -- Communication + WHEN subclass IN ( + 'communication_line', + 'communication_pole', + 'communication_tower', + 'mobile_phone_tower' + ) THEN 'communication' + + -- Generic Towers + WHEN subclass IN ( + 'bell_tower', + 'cooling', + 'defensive', + 'diving', + 'hose', + 'lighting', + 'lightning_protection', + 'minaret', + 'monitoring', + 'observation', + 'radar', + 'siren', + 'suspension', + 'watchtower' + ) THEN 'tower' + + -- Power + WHEN subclass IN ( + 'cable_distribution', + 'cable', + 'catenary_mast', + 'connection', + 'generator', + 'heliostat', + 'insulator', + 'minor_line', + 'plant', + 'power_pole', + 'portal', + 'power_line', + 'power_tower', + 'sub_station', + 'substation', + 'switch', + 'terminal', + 'transformer' + ) THEN 'power' + + -- Manholes + WHEN subclass IN ('manhole', 'drain', 'sewer') THEN 'manhole' + + -- Piers & Dams are their own class + WHEN subclass IN ('pier', 'dam') THEN subclass + + END AS subtype, + subclass AS class, + '__OVERTURE_NAMES_QUERY' AS names, + + -- Relevant OSM tags for land type + MAP_FILTER(tags, (k,v) -> k IN ( + 'tower', + 'route', + 'icao', + 'ref' + ) + ) AS source_tags, + + -- Add all OSM Tags for debugging + tags AS osm_tags, + + '__OVERTURE_SOURCES_LIST' AS sources, + + tags['surface'] AS surface, + + tags['level'] AS level, + + -- Wikidata is a top-level property in the OSM Container + tags['wikidata'] as wikidata, + + -- Apparently there are corrupt geometries that are breaking Athena, so write WKT for now: + wkt AS wkt_geometry +FROM ( + SELECT + *, + CASE + -- Transit Infrastructure + -- Air + WHEN tags['aeroway'] IN ('runway', 'taxiway', 'airstrip', 'helipad') THEN tags['aeroway'] + + -- Specific airport classing + WHEN tags['aeroway'] = 'aerodrome' THEN CASE + WHEN tags['aerodrome:type'] = 'military' OR tags['landuse'] = 'military' OR tags['military'] IN ( + 'airfield' + ) THEN 'military_airport' + WHEN tags['access'] IN ('emergency', 'no', 'permissive', 'private') + OR tags['aerodrome:type'] = 'private' THEN 'private_airport' + WHEN tags['name'] LIKE '%international%' OR tags['aerodrome:type'] = 'international' + OR tags['aerodrome'] = 'international' THEN 'international_airport' + WHEN tags['name'] LIKE '%regional%' OR tags['aerodrome:type'] = 'regional' + THEN 'regional_airport' + WHEN tags['name'] LIKE '%municipal%' THEN 'municipal_airport' + WHEN tags['name'] LIKE '%seaplane%' THEN 'seaplane_airport' + WHEN tags['name'] LIKE '%heli%' THEN 'heliport' + ELSE 'airport' + END + + --Aerialways + WHEN tags['aerialway'] IN ( + 'cable_car', + 'gondola', + 'mixed_lift', + 'chair_lift', + 'drag_lift', + 't-bar' + ) THEN tags['aerialway'] + + WHEN tags['aerialway'] = 'station' THEN 'aerialway_station' + + -- Bus + WHEN tags['highway'] = 'bus_stop' THEN 'bus_stop' + WHEN tags['route'] = 'bus' THEN 'bus_route' + WHEN tags['amenity'] = 'bus_station' THEN 'bus_station' + -- Ferry + -- WHEN tags['route'] = 'ferry' THEN 'ferry_route' + WHEN tags['amenity'] = 'ferry_terminal' THEN 'ferry_terminal' + -- Rail + WHEN tags['railway'] = 'station' THEN 'railway_station' + WHEN tags['railway'] = 'halt' THEN 'railway_halt' + + + -- Communication + WHEN tags['communication:mobile_phone'] <> 'no' THEN 'mobile_phone_tower' + WHEN tags['communication'] = 'line' THEN 'communication_line' + WHEN tags['communication'] = 'pole' THEN 'communication_pole' + WHEN tags['tower:type'] = 'communication' THEN 'communication_tower' + + -- Manhole + WHEN tags['manhole'] IN ('drain', 'sewer') THEN tags['manhole'] + WHEN tags['manhole'] IS NOT NULL THEN 'manhole' + + -- Power + WHEN tags['power'] IN ( + 'cable_distribution', + 'cable', + 'catenary_mast', + 'connection', + 'generator', + 'heliostat', + 'insulator', + 'minor_line', + 'plant', + 'portal', + 'sub_station', + 'substation', + 'switch', + 'terminal', + 'transformer' + ) THEN tags['power'] + + WHEN tags['power'] = 'line' THEN 'power_line' + WHEN tags['power'] = 'pole' THEN 'power_pole' + WHEN tags['power'] = 'tower' THEN 'power_tower' + + -- Other towers + WHEN tags['tower:type'] IN ( + 'bell_tower', + 'cooling', + 'defensive', + 'diving', + 'hose', + 'lighting', + 'lightning_protection', + 'minaret', + 'monitoring', + 'observation', + 'radar', + 'siren', + 'watchtower' + ) THEN tags['tower:type'] + + -- TODO: bridges, dams? + WHEN tags['bridge'] = 'yes' THEN 'bridge' + WHEN tags['bridge'] IN ( + 'aqueduct', + 'boardwalk', + 'cantilever', + 'covered', + 'movable', + 'trestle', + 'viaduct' + ) THEN tags['bridge'] + + WHEN tags['man_made'] IN ('bridge', 'pier') THEN tags['man_made'] + + WHEN tags['waterway'] IN ('dam') THEN 'dam' + + END AS subclass + FROM + -- These two lines get injected. + {daylight_table} + WHERE release = '{daylight_version}' + -- + AND ARRAYS_OVERLAP( + MAP_KEYS(tags), + ARRAY[ + 'bridge', + 'communication:mobile_phone', + 'communication', + 'man_made', + 'manhole', + 'power', + 'tower:type', + 'tower', + 'waterway', + -- Transit + 'aerialway', + 'aeroway', + 'amenity', + 'highway', + 'icao', + 'public_transport', + 'railway', + 'route' + ] + ) = TRUE + ) +WHERE + subclass IS NOT NULL diff --git a/task-force-docs/base/land.sql b/task-force-docs/base/land.sql new file mode 100644 index 00000000..23535ca7 --- /dev/null +++ b/task-force-docs/base/land.sql @@ -0,0 +1,142 @@ +SELECT + -- Needed to compute ID and satisfy Overture requirements: + type, + id, + version, + min_lon, + max_lon, + min_lat, + max_lat, + created_at AS update_time, + + -- Determine class from subclass or tags + CASE + WHEN subclass IN ('glacier', 'reef') THEN subclass + WHEN subclass IN ('forest', 'wood') THEN 'forest' + WHEN subclass IN ('fell','grass', 'grassland','meadow','tundra') THEN 'grass' + WHEN subclass IN ('hill', 'peak', 'valley', 'volcano') THEN 'physical' + WHEN subclass IN ('bare_rock','rock','scree','shingle') THEN 'rock' + WHEN subclass IN ('sand', 'beach', 'dune') THEN 'sand' + WHEN subclass IN ('heath','scrub','shrub','shrubbery') THEN 'shrub' + WHEN subclass IN ('tree', 'tree_row') THEN 'tree' + WHEN tags [ 'natural' ] IN ('wetland') THEN 'wetland' + END AS subtype, + subclass AS class, + + '__OVERTURE_NAMES_QUERY' AS names, + + -- Relevant OSM tags for land type + MAP_FILTER(tags, (k,v) -> k IN ( + 'landcover', + 'landuse', + 'natural', + 'surface' + ) + ) AS source_tags, + + -- Add all OSM Tags for debugging + tags AS osm_tags, + + '__OVERTURE_SOURCES_LIST' AS sources, + + -- Wikidata is a top-level property in the OSM Container + tags['wikidata'] as wikidata, + + -- Elevation as integer (meters above sea level) + TRY_CAST(tags['ele'] AS integer) AS elevation, + + -- Apparently there are corrupt geometries that are breaking Athena, so write WKT for now: + wkt_geometry + +FROM ( + SELECT + *, + -- Determine subclass + CASE + -- Natural tags that become subclasses + WHEN tags [ 'natural' ] IN ( + 'bare_rock', + 'beach', + 'dune', + 'fell', + 'forest', + 'glacier', + 'grassland', + 'heath', + 'hill', + 'peak', + 'reef', + 'rock', + 'sand', + 'scree', + 'scrub', + 'shingle', + 'shrub', + 'shrubbery', + 'tree_row', + 'tree', + 'tundra', + 'valley', + 'volcano', + 'wetland', + 'wood' + ) THEN tags [ 'natural' ] + + -- Surface tags that become subclasses + WHEN tags [ 'surface' ] IN ('grass') THEN tags [ 'surface' ] + WHEN tags [ 'landcover' ] = 'trees' THEN 'forest' + WHEN tags [ 'landcover' ] IN ('grass', 'scrub', 'tree') THEN tags [ 'landcover' ] -- These landuse tags become subclasses + + WHEN tags['name'] IS NULL AND tags [ 'meadow' ] IS NULL + AND tags [ 'landuse' ] IN ('forest', 'meadow', 'grass') THEN tags [ 'landuse' ] + ELSE NULL + END AS subclass + FROM ( + SELECT + id, + type, + version, + tags, + created_at, + -- ST_GeometryFromText(wkt) AS geom, + wkt AS wkt_geometry, + min_lon, + max_lon, + min_lat, + max_lat + -- These two lines get injected. + FROM + {daylight_table} + WHERE + release = '{daylight_version}' + -- These features belong in other themes / types + AND tags [ 'highway' ] IS NULL + AND tags [ 'building' ] IS NULL + AND tags [ 'golf' ] IS NULL + AND tags [ 'sport' ] IS NULL + AND tags [ 'leisure' ] IS NULL + AND ( + tags [ 'natural' ] IS NOT NULL + OR tags [ 'surface' ] IS NOT NULL + OR tags [ 'landcover' ] IS NOT NULL + OR tags [ 'landuse' ] IN ('forest', 'meadow', 'grass') + ) + ) +) +WHERE + subclass IS NOT NULL -- The only points/lines allowed are trees and peaks + -- everything else should be a polygon: + AND ( + wkt_geometry LIKE '%POLYGON%' + -- ST_GEOMETRYTYPE(geom) IN ('ST_Polygon', 'ST_MultiPolygon') + OR ( + wkt_geometry LIKE '%POINT%' + -- ST_GEOMETRYTYPE(geom) IN ('ST_Point', 'ST_MultiPoint') + AND subclass IN ('hill', 'peak', 'tree', 'shrub', 'valley', 'volcano') + ) + OR ( + wkt_geometry LIKE '%LINESTRING%' + -- ST_GEOMETRYTYPE(geom) IN ('ST_LineString', 'ST_MultiLineString') + AND subclass = 'tree_row' + ) + ) diff --git a/task-force-docs/base/land_use.sql b/task-force-docs/base/land_use.sql new file mode 100644 index 00000000..3bcbda68 --- /dev/null +++ b/task-force-docs/base/land_use.sql @@ -0,0 +1,479 @@ +SELECT + type, + id, + version, + min_lon, + max_lon, + min_lat, + max_lat, + update_time, + subtype, + class, + names, + source_tags, + osm_tags, + sources, + wikidata, + surface, + elevation, + wkt_geometry +FROM ( + SELECT + -- Needed to compute ID and satisfy Overture requirements. + type, + id, + version, + min_lon, + max_lon, + min_lat, + max_lat, + created_at AS update_time, + + -- Determine class from subclass or tags + CASE + -- Agriculture + WHEN subclass IN ( + 'animal_keeping', + 'farmland', + 'farmyard', + 'meadow' + ) THEN 'agriculture' + + -- Airports + WHEN subclass IN ( + 'aerodrome', + 'helipad', + 'heliport' + ) THEN 'airport' + + -- Aquaculture + WHEN subclass IN ('aquaculture') THEN 'aquaculture' + + -- Campground + WHEN subclass IN ('camp_site') THEN 'campground' + + -- Cemetery + WHEN subclass IN ('cemetery') THEN 'cemetery' + + -- Conservation + WHEN subclass IN ('conservation') THEN 'conservation' + + -- Construction + WHEN subclass IN ( + 'construction', + 'greenfield' + ) THEN 'construction' + + -- Developed + WHEN subclass IN ( + 'commercial', + 'retail', + 'industrial', + 'institutional', + 'brownfield' + ) THEN 'developed' + + -- Education + WHEN subclass IN ( + 'college', + 'education', + 'school', + 'schoolyard', + 'university' + ) THEN 'education' + + -- Entertainment + WHEN subclass IN ( + 'theme_park', + 'water_park', + 'zoo' + ) THEN 'entertainment' + + -- Golf + WHEN subclass IN ( + 'bunker', + 'driving_range', + 'fairway', + 'golf_course', + 'green', + 'lateral_water_hazard', + 'rough', + 'tee', + 'water_hazard' + ) THEN 'golf' + + -- Horticulture + WHEN subclass IN ( + 'allotments', + 'garden', + 'greenhouse_horticulture', + 'flowerbed', + 'plant_nursery', + 'orchard', + 'vineyard' + ) THEN 'horticulture' + + -- Landfill + WHEN subclass IN ('landfill') THEN 'landfill' + + -- Medical + WHEN subclass IN ( + 'clinic', + 'doctors', + 'hospital' + ) THEN 'medical' + + -- Military + WHEN subclass IN ( + 'airfield', + 'barracks', + 'base', + 'danger_area', + 'military', + 'military_other', + 'naval_base', + 'nuclear_explosion_site', + 'obstacle_course', + 'range', + 'training_area', + 'trench' + ) THEN 'military' + + -- Parks / Greenspace + WHEN subclass IN ( + 'common', + 'dog_park', + 'park', + 'village_green' + ) THEN 'park' + + -- Public + WHEN subclass IN ( + 'civic_admin', + 'public' + ) THEN 'public' + + -- Protected + WHEN subclass IN ( + 'aboriginal_land', + 'environmental', + 'forest', + 'state_park', + 'national_park', + 'natural_monument', + 'nature_reserve', + 'protected_landscape_seascape', + 'species_management_area', + 'strict_nature_reserve', + 'wilderness_area', + 'wilderness' + ) THEN 'protected' + + -- Recreation + WHEN subclass IN ( + 'recreation_grass', + 'recreation_paved', + 'pitch', + 'playground', + 'track', + 'recreation_ground', + 'recreation_sand', + + -- Add more leisure= tags here if necessary + 'marina', + 'stadium' + ) THEN 'recreation' + + -- Religious + WHEN subclass IN ('religious', 'churchyard') THEN 'religious' + + -- Residential + WHEN subclass IN ('residential', 'static_caravan', 'garages') + THEN 'residential' + + -- Resource + WHEN subclass IN ( + 'logging', + 'peat_cutting', + 'quarry', + 'salt_pond' + ) THEN 'resource_extraction' + + -- Structure + WHEN subclass IN ('pier', 'dam', 'bridge') THEN 'structure' + + -- Transportation + WHEN subclass IN ('depot', 'traffic_island', 'highway') + THEN 'transportation' + + -- Winter Sports + WHEN subclass IN ('winter_sports') THEN 'winter_sports' + + END AS subtype, + subclass as class, + + '__OVERTURE_NAMES_QUERY' AS names, + + -- Relevant OSM tags for Landuse type + MAP_FILTER(tags, (k,v) -> k IN ( + 'access', + 'aeroway', + 'amenity', + 'area', + 'boundary', + 'golf', + 'highway', + 'layer', + 'leisure', + 'level', + 'man_made', + 'meadow', + 'military', + 'natural', + 'place', + 'protect_class', + 'protection_title', + 'sport', + 'surface', + 'tourism' + ) + ) as source_tags, + + tags as osm_tags, + + '__OVERTURE_SOURCES_LIST' AS sources, + + -- Wikidata is a top-level property in the OSM Container + tags['wikidata'] as wikidata, + + -- Elevation as integer (meters above sea level) + TRY_CAST(tags['ele'] AS integer) AS elevation, + + -- Other type=landuse top-level attributes + surface, + + wkt_geometry + FROM ( + SELECT + *, + IF( + --Polygons + wkt_geometry like '%POLYGON%', + CASE + + --logic for piers / dams + WHEN tags['man_made'] IN ('pier') AND tags['highway'] = NULL THEN tags['man_made'] + WHEN tags['waterway'] = 'dam' THEN 'dam' + + -- Check for Military specific tags + WHEN tags['military'] <> 'no' THEN + IF(tags['military'] IN ( + 'airfield', + 'barracks', + 'base', + 'danger_area', + 'naval_base', + 'nuclear_explosion_site', + 'obstacle_course', + 'range', + 'training_area', + 'trench' + ), tags['military'], + 'military_other') + + -- Priority landuse tags to pass to class logic: + WHEN tags['landuse'] IN ('military') THEN tags['landuse'] + + -- Use these secondary more descriptive tags first: + WHEN tags['tourism'] IN ('zoo','theme_park') THEN tags['tourism'] + + -- Aboriginal Lands & Reservations + WHEN tags['boundary'] IN ('aboriginal_lands') OR ( + tags['boundary'] = 'protected_area' AND tags['protect_class'] = '24' + ) THEN 'aboriginal_land' + + -- Is there is an official Protect Class Designation (wiki.openstreetmap.org/wiki/Key:protect_class)? + WHEN tags['protect_class'] IN ('1a', '1', '2', '3', '4', '5') THEN CASE + WHEN tags['protect_class'] = '1a' THEN 'strict_nature_reserve' + WHEN tags['protect_class'] IN ('1b', '1') THEN 'wilderness_area' + WHEN tags['protect_class'] = '2' THEN 'national_park' + WHEN tags['protect_class'] = '3' THEN 'natural_monument' + WHEN tags['protect_class'] = '4' THEN 'species_management_area' + WHEN tags['protect_class'] = '5' THEN 'protected_landscape_seascape' + END + + -- protect_class >= 6 or null: + WHEN tags['boundary'] = 'protected_area' THEN CASE + WHEN LOWER(tags['protection_title']) IN ('national forest', 'state forest') + THEN 'forest' + WHEN LOWER(tags['protection_title']) IN ('national park') THEN 'national_park' + WHEN LOWER(tags['protection_title']) IN ('state park') THEN 'state_park' + WHEN LOWER(tags['protection_title']) IN ( + 'wilderness area', + 'wilderness study area' + ) THEN 'wilderness_area' + WHEN LOWER(tags['protection_title']) IN ('nature reserve', 'nature refuge') + THEN 'nature_reserve' + WHEN LOWER(tags['protection_title']) IN ('environmental use') + THEN 'environmental' + -- Fall through to landuse if it's protected + WHEN tags['landuse'] IS NOT NULL THEN tags['landuse'] + -- Last resort, a leisure= tag (such as nature_reserve): + WHEN tags['leisure'] IS NOT NULL THEN tags['leisure'] + END + + -- National & State Parks (US) + WHEN STRPOS(LOWER(tags['name']), 'national park') > 0 OR tags['boundary'] + = 'national_park' OR LOWER(tags['protection_title']) = 'national park' + THEN 'national_park' + + WHEN STRPOS(LOWER(tags['name']), 'state park') > 0 OR LOWER(tags['protection_title']) + = 'state park' THEN 'state_park' + + -- Pull out golf before going into sport-specific logic + WHEN tags['golf'] IN ( + 'bunker', + 'driving_range', + 'fairway', + 'golf_course', + 'green', + 'lateral_water_hazard', + 'rough', + 'tee', + 'water_hazard' + ) THEN tags['golf'] + + -- Specific sport surfaces + WHEN tags['leisure'] IN ('pitch', 'playground', 'track', 'stadium') + THEN tags['leisure'] + + -- Meadows are tagged this way + WHEN tags['meadow'] IN ('agricultural', 'agriculture', 'pasture') + THEN 'meadow' + + -- Amenity (Campuses) + WHEN tags['amenity'] IN ( + 'college', + 'university', + 'school', + 'hospital', + 'clinic', + 'doctors' + ) THEN tags['amenity'] + + -- Campgrounds + WHEN tags['tourism'] = 'camp_site' AND tags['refugee'] IS NULL + THEN 'camp_site' + + -- Leisure values that become subclasses: + WHEN tags['leisure'] IN ( + 'common', + 'garden', + 'golf_course', + 'marina', + 'nature_reserve', + 'park', + 'schoolyard', + 'stadium', + 'water_park' + ) THEN tags['leisure'] + + WHEN tags['aeroway'] IN ('aerodrome', 'helipad', 'heliport') THEN tags['aeroway'] + + -- Else use the landuse tag and assign it to a class above + -- (refer aginfo.osm.org/keys/landuse#values for top landuse values) + WHEN tags['landuse'] NOT IN ('meadow','forest') THEN tags['landuse'] + END, + -- Linestrings / Points + CASE + WHEN tags['man_made'] IN ('pier') THEN tags['man_made'] + + -- Some tracks are linestrings and they are not included elsewhere + WHEN tags['leisure'] IN ('track') THEN tags['leisure'] + END + ) AS subclass, + + -- Transform tags to ROW(k,v) for names conversion + TRANSFORM( + MAP_ENTRIES(tags), + r->CAST(r AS ROW(k VARCHAR, v VARCHAR)) + ) AS kv, + + -- Transform the surface tag + IF( + tags['leisure'] IN ('pitch', 'playground', 'track', 'stadium') OR tags['sport'] IS NOT NULL, + CASE + WHEN tags['natural'] = 'sand' OR tags['surface'] IN ( + 'dirt', + 'earth', + 'fine_gravel', + 'gravel', + 'ground', + 'unpaved', + 'sand' + ) OR tags['golf'] IN ('bunker') THEN 'recreation_sand' + WHEN tags['surface'] IN ('artificial_turf', 'grass', 'grass_paver') + THEN 'recreation_grass' + WHEN tags['surface'] IN ( + 'acrylic', + 'asphalt', + 'clay', + 'compacted', + 'concrete', + 'hard', + 'paved' + ) THEN 'recreation_paved' + WHEN tags['surface'] IS NULL AND tags['sport'] IN ('basketball') + THEN 'recreation_paved' + WHEN tags['surface'] IS NULL AND tags['sport'] IN ('soccer', 'football') + THEN 'recreation_grass' + ELSE tags['surface'] + END, + CASE + WHEN tags['golf'] IN ('bunker') THEN 'recreation_sand' + ELSE tags['surface'] + END + ) AS surface + FROM ( + SELECT + id, + type, + version, + created_at, + tags, + -- ST_GeometryFromText(wkt) AS geom, + wkt AS wkt_geometry, + min_lon, max_lon, min_lat, max_lat + FROM + -- These two lines get injected. + {daylight_table} + WHERE release = '{daylight_version}' + -- + AND ARRAYS_OVERLAP( + MAP_KEYS(tags), + ARRAY[ + 'aeroway', + 'amenity', + 'boundary', + 'golf', + 'highway', + 'landuse', + 'leisure', + 'man_made', + 'military', + 'place', + 'tourism', + 'waterway' + ] + ) = TRUE + AND ( + tags['building'] IS NULL + OR tags['building'] = 'no' + ) + ) + ) + WHERE + subclass IS NOT NULL + ) +WHERE + subtype IS NOT NULL diff --git a/task-force-docs/base/water.sql b/task-force-docs/base/water.sql new file mode 100644 index 00000000..d5aa4c03 --- /dev/null +++ b/task-force-docs/base/water.sql @@ -0,0 +1,248 @@ +SELECT + -- Needed to compute ID and satisfy Overture requirements. + type, + id, + version, + min_lon, + max_lon, + min_lat, + max_lat, + created_at AS update_time, + + -- Determine class from subclass or tags + CASE + WHEN subclass IN ('stream') THEN 'stream' + WHEN subclass IN ('river') THEN 'river' + WHEN subclass IN ('pond', 'fishpond') THEN 'pond' + WHEN subclass IN ('lake', 'oxbow', 'lagoon') THEN 'lake' + WHEN subclass IN ('reservoir', 'basin', 'water_storage') THEN 'reservoir' + WHEN subclass IN ('canal', 'ditch', 'moat') THEN 'canal' + WHEN subclass IN ( + 'drain', + 'fish_pass', + 'fish_ladder', + 'reflecting_pool', + 'swimming_pool' + ) THEN 'human_made' + WHEN subclass IN ('cape', 'fairway', 'shoal', 'strait') THEN 'physical' + -- Default to just 'water' + ELSE 'water' + END AS subtype, + subclass as class, + + '__OVERTURE_NAMES_QUERY' AS names, + + -- Relevant OSM tags for water type + MAP_FILTER(tags, (k,v) -> k IN ( + 'basin', + 'intermittent', + 'landuse', + 'leisure', + 'natural', + 'salt', + 'seamark:type', + 'water', + 'waterway' + ) + ) as source_tags, + + -- Temporary for debugging + tags AS osm_tags, + + '__OVERTURE_SOURCES_LIST' AS sources, + + -- Wikidata is a top-level property in the OSM Container + tags['wikidata'] as wikidata, + + TRY_CAST(tags['ele'] AS integer) AS elevation, + + -- Other type=water top-level attributes + (tags['salt'] = 'yes') AS is_salt, + (tags['intermittent'] = 'yes') AS is_intermittent, + + -- Cast geometry as WKB + ST_AsBinary(geom) AS geometry +FROM ( + SELECT + *, + -- Determine subclass + CASE + -- Waterway values that become subclasses + WHEN tags['waterway'] IN ( + 'canal', + 'ditch', + 'dock', + 'drain', + 'fish_pass', + 'river', + 'stream', + 'tidal_channel' + ) THEN tags['waterway'] + + WHEN tags['waterway'] = 'riverbank' THEN 'river' + + -- Water tags that become subclasses, independent of surface area + WHEN tags['water'] IN ( + 'basin', + 'canal', + 'ditch', + 'drain', + 'fishpond', + 'lagoon', + 'lock', + 'moat', + 'oxbow', + 'reflecting_pool', + 'river', + 'salt_pool', + 'stream', + 'wastewater' + ) THEN tags['water'] + + -- Check size of still water to reclassify as pond: + WHEN tags['water'] IN ('lake', 'oxbow', 'reservoir', 'pond') + THEN IF(surface_area_sq_m < 4000, 'pond', tags['water']) + + -- Basins and Reservoirs are classified in landuse + WHEN tags['landuse'] IN ('reservoir', 'basin') THEN CASE + WHEN tags['basin'] IN ( + 'evaporation', + 'detention', + 'retention', + 'infiltration', + 'cooling' + ) THEN 'basin' + WHEN tags['reservoir_type'] IN ('sewage','water_storage') THEN tags['reservoir_type'] + ELSE 'reservoir' + END + + WHEN tags['leisure'] = 'swimming_pool' THEN tags['leisure'] + + WHEN tags['waterway'] = 'dock' AND tags['dock'] <> 'drydock' THEN 'dock' + + WHEN tags['natural'] = 'water' AND tags['man_made'] IN ( + 'basin', + 'pond', + 'reservoir', + 'yes', + 'waterway' + ) THEN IF( + surface_area_sq_m < 4000, + 'pond', + IF( + tags['man_made'] IN ('basin', 'reservoir', 'pond'), + tags['man_made'], + 'water' + ) + ) + + -- Add some new feature/label types for points only + WHEN tags['natural'] IN ('cape', 'shoal', 'strait') THEN IF( + ST_GEOMETRYTYPE(geom) IN ( + 'ST_Point', + 'ST_LineString', + 'ST_MultiLineString' + ), + tags['natural'], + NULL -- null trap to throw out polygons + ) + + WHEN tags['seamark:type'] IN ('fairway') THEN IF( + ST_GEOMETRYTYPE(geom) IN ( + 'ST_Point', + 'ST_LineString', + 'ST_MultiLineString' + ), + tags['seamark:type'], + NULL -- null trap to throw out polygons + ) + -- Default subclass is just 'water' + ELSE 'water' + END AS subclass + FROM ( + SELECT + id, + type, + version, + tags, + geom, + -- Extra attrs for water-specific logic + IF( + ST_GEOMETRYTYPE(geom) IN ('ST_Polygon', 'ST_MultiPolygon'), + ROUND(ST_AREA(TO_SPHERICAL_GEOGRAPHY(geom)), 2), + NULL + ) AS surface_area_sq_m, + created_at, min_lon, max_lon, min_lat, max_lat + FROM ( + SELECT + id, + version, + type, + tags, + IF( + ST_GEOMETRYTYPE(ST_GeometryFromText(wkt)) = 'ST_Polygon' + AND tags['waterway'] IN ('canal', 'drain', 'ditch'), + ST_EXTERIORRING(ST_GeometryFromText(wkt)), + ST_GeometryFromText(wkt) + ) AS geom, + created_at, min_lon, max_lon, min_lat, max_lat + FROM + {daylight_table} + WHERE + release = '{daylight_version}' + AND ( + -- The primary OSM key/value for water features + tags['natural'] = 'water' + + OR ( + -- swimming pools are cool + -- but not if they are a building/indoor + tags['leisure'] = 'swimming_pool' + AND ( + tags['building'] = 'no' + OR tags['building'] IS NULL + ) + + AND ( + tags['location'] IS NULL + OR tags['location'] IN ( + 'roof', + 'outdoor', + 'overground', + 'surface' + ) + ) + ) + -- add some new feature/label types + OR ( + tags['natural'] IN ('cape', 'shoal', 'strait') + OR tags['seamark:type'] = 'fairway' + ) + OR tags['water'] IS NOT NULL + + OR tags['basin'] IS NOT NULL + + OR tags['landuse'] IN ('basin', 'reservoir') + + -- Filter IN for waterway features to avoid dams, locks, etc. + OR ( + tags['waterway'] IN ( + 'canal', + 'ditch', + 'dock', + 'drain', + 'fairway', + 'fish_pass', + 'river', + 'river', + 'riverbank', + 'stream', + 'tidal_channel' + ) + ) + ) + ) + ) + ) +WHERE + subclass IS NOT NULL