From d7fc1508d3be050439f65bd59c70f21cc3694849 Mon Sep 17 00:00:00 2001 From: Jennings Anderson Date: Thu, 30 May 2024 16:51:39 -0700 Subject: [PATCH] Reverting changes to dev --- docs/schema/reference/base/land_use.mdx | 1 + schema/base/land.yaml | 1 + schema/base/land_use.yaml | 1 - task-force-docs/base/infrastructure.sql | 632 ++++++++++-------- task-force-docs/base/land.sql | 365 +++++----- .../places/overture_categories.csv | 2 +- 6 files changed, 572 insertions(+), 430 deletions(-) diff --git a/docs/schema/reference/base/land_use.mdx b/docs/schema/reference/base/land_use.mdx index 7b9830ce..bf3e6f14 100644 --- a/docs/schema/reference/base/land_use.mdx +++ b/docs/schema/reference/base/land_use.mdx @@ -55,4 +55,5 @@ Features in the land use theme come primarily from OpenStreetMap features contai { JSON.stringify(yamlLoad(LandUseExample), null, 2) } + diff --git a/schema/base/land.yaml b/schema/base/land.yaml index 7b39d083..982dff6a 100644 --- a/schema/base/land.yaml +++ b/schema/base/land.yaml @@ -85,5 +85,6 @@ properties: - volcano - wetland - wood + elevation: { "$ref": ./defs.yaml#/$defs/propertyDefinitions/elevation } surface: { "$ref": ./defs.yaml#/$defs/propertyDefinitions/surface } diff --git a/schema/base/land_use.yaml b/schema/base/land_use.yaml index 6b5720fa..a3532124 100644 --- a/schema/base/land_use.yaml +++ b/schema/base/land_use.yaml @@ -38,7 +38,6 @@ properties: - education - entertainment - golf - - grass - horticulture - landfill - managed diff --git a/task-force-docs/base/infrastructure.sql b/task-force-docs/base/infrastructure.sql index 23a47575..14dda106 100644 --- a/task-force-docs/base/infrastructure.sql +++ b/task-force-docs/base/infrastructure.sql @@ -1,27 +1,270 @@ --- This file contains the logic for transforming OpenStreetMap features into Overture features --- for the `infrastructure` type within the `base` theme. +SELECT + -- Needed to compute ID and satisfy Overture requirements: + type, + id, + version, + min_lon, + max_lon, + min_lat, + max_lat, + TO_ISO8601(created_at AT TIME ZONE 'UTC') AS update_time, + -- Determine class from subclass or tags + CASE + -- Bus / Ferry / Railway Infrastructure (Transit) + WHEN class IN ( + 'bus_route', + 'bus_stop', + 'bus_station', + -- 'ferry_route', + 'ferry_terminal', + 'railway_halt', + 'railway_station', + -- Parking + 'parking', + 'parking_space', + + -- Public transport / cycle + 'stop_position', + 'platform', + + -- cycle + 'bicycle_parking' + + ) THEN 'transit' + + -- Aerialways + WHEN class IN ( + 'aerialway_station', + 'cable_car', + 'chair_lift', + 'drag_lift', + 'gondola', + 'mixed_lift', + 'pylon', + 't-bar' + ) THEN 'aerialway' + + -- Airports + WHEN class IN ( + 'airport', + 'airstrip', + 'helipad', + 'heliport', + 'international_airport', + 'military_airport', + 'municipal_airport', + 'private_airport', + 'regional_airport', + 'runway', + 'seaplane_airport', + 'taxiway' + ) THEN 'airport' + + -- Barriers / Fences + WHEN class IN ( + 'barrier', + 'block', + 'bollard', + 'cattle_grid', + 'chain', + 'city_wall', + 'cycle_barrier', + 'ditch', + 'entrance', + 'guard_rail', + 'hedge', + 'height_restrictor', + 'jersey_barrier', + 'kerb', + 'kissing_gate', + 'lift_gate', + 'retaining_wall', + 'stile', + 'swing_gate', + 'toll_booth', + 'wall', + 'cutline' + ) THEN 'barrier' + + -- Bridges + WHEN class IN ( + 'bridge', + 'viaduct', + 'boardwalk', + 'aqueduct', + 'movable', + 'covered', + 'cantilever', + 'trestle' + ) THEN 'bridge' + + -- Communication + WHEN class IN ( + 'communication_line', + 'communication_pole', + 'communication_tower', + 'mobile_phone_tower' + ) THEN 'communication' + + -- Generic Towers + WHEN class IN ( + 'bell_tower', + 'cooling', + 'defensive', + 'diving', + 'hose', + 'lighting', + 'lightning_protection', + 'minaret', + 'monitoring', + 'observation', + 'radar', + 'siren', + 'suspension', + 'watchtower' + ) THEN 'tower' + + -- Power + WHEN class 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' + + -- Pedestrian + WHEN class IN ( + 'atm', + 'bench', + 'information', + 'picnic_table', + 'post_box', + 'toilets', + 'vending_machine', + 'viewpoint' + ) THEN 'pedestrian' + + -- Manholes + WHEN class IN ('manhole', 'drain', 'sewer') THEN 'manhole' + + -- Generic Utility + WHEN class IN ( + 'silo', + 'storage_tank', + 'utility_pole', + 'water_tower' + ) THEN 'utility' + + WHEN class IN ('camp_site') THEN 'recreation' + + -- Utility + WHEN class IN ('pipeline','storage_tank') THEN 'utility' + + -- Waste Management + WHEN class IN ( + 'recycling', + 'waste_basket', + 'waste_disposal' + ) THEN 'waste_management' + + -- Piers & Dams are their own subtypes + WHEN class IN ('pier') THEN class + + WHEN class IN ('dam','weir') THEN 'water' + + END AS subtype, + class, + '__OVERTURE_NAMES_QUERY' AS names, --- The order of the WHEN clauses in the following CASE statement is very specific. It is the same --- as saying "WHEN this tag is present AND ignore any of the other tags below this line" + -- Relevant OSM tags for land type + MAP_FILTER(tags, (k,v) -> k IN ( + 'access', + 'aerodrome:type', + 'aerodrome', + 'amenity', + 'barrier', + 'icao', + 'landuse', + 'military', + 'parking', + 'ref', + 'route', + 'surface', + 'tower', + 'tourism' + ) + ) AS source_tags, -WITH classified_osm AS ( - SELECT CAST( - CASE - -- Transit - WHEN element_at(tags,'railway') IN ('station','halt') THEN ROW('transit', 'railway_' || element_at(tags,'railway')) + -- Add all OSM Tags for debugging + tags AS osm_tags, - WHEN element_at(tags,'highway') = 'bus_stop' THEN ROW('transit', 'bus_stop') - WHEN element_at(tags,'route') = 'bus' THEN ROW('transit', 'bus_route') - WHEN element_at(tags,'amenity') = 'bus_station' THEN ROW('transit', 'bus_station') + -- Sources are an array of structs. + ARRAY [ CAST( + ROW( + '', + 'OpenStreetMap', + SUBSTR(type, 1, 1) || CAST(id AS varchar) || '@' || CAST(version AS varchar), + NULL + ) + AS ROW( + property varchar, + dataset varchar, + record_id varchar, + confidence double + ) + ) ] AS sources, - WHEN element_at(tags,'amenity') = 'ferry_terminal' THEN ROW('transit','ferry_terminal') + tags['surface'] AS surface, - WHEN element_at(tags,'amenity') IN ('parking','parking_space','bicycle_parking') THEN ROW('transit', element_at(tags,'amenity')) + -- Overture's concept of `layer` is called level + TRY_CAST(tags['layer'] AS int) AS level, - WHEN element_at(tags,'public_transport') IN ('stop_position', 'platform') THEN ROW('transit', element_at(tags,'public_transport')) + -- Wikidata is a top-level property in the OSM Container + tags['wikidata'] as wikidata, - -- Aerialways - WHEN element_at(tags,'aerialway') IN ( + -- 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', @@ -29,67 +272,84 @@ WITH classified_osm AS ( 'drag_lift', 't-bar', 'pylon' - ) THEN ROW('aerialway', element_at(tags,'aerialway')) - - WHEN element_at(tags,'aerialway') = 'station' THEN ROW('aerialway', 'aerialway_station') - - -- Airports - WHEN element_at(tags,'aeroway') IN ('runway', 'taxiway', 'airstrip', 'helipad') THEN ROW('airport', element_at(tags,'aeroway')) - - WHEN element_at(tags,'aeroway') = 'gate' THEN ROW('airport', 'airport_gate') - - WHEN element_at(tags,'aeroway') = 'aerodrome' THEN CASE - WHEN element_at(tags,'aerodrome:type') = 'military' OR element_at(tags,'landuse') = 'military' OR element_at(tags,'military') IN ( - 'airfield' - ) THEN ROW('airport','military_airport') - WHEN element_at(tags,'access') IN ('emergency', 'no', 'permissive', 'private') - OR element_at(tags,'aerodrome:type') = 'private' THEN ROW('airport','private_airport') - WHEN lower(element_at(tags,'name')) LIKE '%international%' OR element_at(tags,'aerodrome:type') = 'international' - OR element_at(tags,'aerodrome') = 'international' THEN ROW('airport','international_airport') - WHEN lower(element_at(tags,'name')) LIKE '%regional%' OR element_at(tags,'aerodrome:type') = 'regional' - THEN ROW('airport','regional_airport') - WHEN lower(element_at(tags,'name')) LIKE '%municipal%' THEN ROW('airport','municipal_airport') - WHEN lower(element_at(tags,'name')) LIKE '%seaplane%' THEN ROW('airport','seaplane_airport') - WHEN lower(element_at(tags,'name')) LIKE '%heli%' THEN ROW('airport','heliport') - ELSE ROW('airport','airport') - END - - -- Bridges - WHEN element_at(tags,'bridge') IN ( - 'aqueduct', - 'boardwalk', - 'cantilever', - 'covered', - 'movable', - 'trestle', - 'viaduct' - ) THEN ROW('bridge', element_at(tags,'bridge')) - WHEN element_at(tags,'bridge:support') IS NOT NULL THEN - ROW('bridge', 'bridge_support') - - -- Communication - WHEN element_at(tags,'communication:mobile_phone') <> 'no' THEN ROW('communication','mobile_phone_tower') - WHEN element_at(tags,'communication') IN ('line','pole') THEN ROW('communication','communication_' || element_at(tags,'communication')) - WHEN element_at(tags,'tower:type') = 'communication' THEN ROW('communication','communication_tower') - - -- Pedestrian - WHEN element_at(tags,'highway') IS NULL AND element_at(tags,'footway') IN ('crossing') AND (wkt LIKE 'MULTIPOLYGON%' OR wkt LIKE 'POLYGON%') THEN ROW('pedestrian','pedestrian_crossing') - WHEN element_at(tags,'tourism') IN ('information', 'viewpoint') THEN ROW('pedestrian', element_at(tags,'tourism')) - WHEN element_at(tags,'amenity') IN ( + ) THEN tags['aerialway'] + + WHEN tags['aerialway'] = 'station' THEN 'aerialway_station' + + --Barriers + WHEN tags['barrier'] IS NOT NULL AND tags['barrier'] <> 'no' THEN + IF(tags['barrier'] IN ( + 'block', + 'bollard', + 'cattle_grid', + 'chain', + 'city_wall', + 'cycle_barrier', + 'ditch', + 'entrance', + 'guard_rail', + 'hedge', + 'height_restrictor', + 'jersey_barrier', + 'kerb', + 'kissing_gate', + 'lift_gate', + 'retaining_wall', + 'stile', + 'swing_gate', + 'toll_booth', + 'wall' + ), tags['barrier'], + 'barrier' + ) + + -- Bus + WHEN tags['highway'] = 'bus_stop' THEN 'bus_stop' + WHEN tags['route'] = 'bus' THEN 'bus_route' + WHEN tags['amenity'] = 'bus_station' THEN 'bus_station' + + -- Public Transport + WHEN tags['public_transport'] IN ('stop_position','platform') THEN tags['public_transport'] + + -- Ferry + -- WHEN tags['route'] = 'ferry' THEN 'ferry_route' + WHEN tags['amenity'] = 'ferry_terminal' THEN 'ferry_terminal' + + -- Parking + WHEN tags['amenity'] IN ('parking','parking_space','bicycle_parking') THEN tags['amenity'] + + -- Amenity Tags (pedestrian, waste_management, etc) + WHEN tags['amenity'] IN ( 'atm', 'bench', 'picnic_table', 'post_box', + 'recycling', 'toilets', - 'vending_machine' - ) THEN ROW('pedestrian', element_at(tags,'amenity')) + 'vending_machine', + 'waste_basket', + 'waste_disposal' + ) THEN tags['amenity'] + + WHEN tags['tourism'] IN ('information','viewpoint') THEN tags['tourism'] + + -- Rail + WHEN tags['railway'] = 'station' THEN 'railway_station' + WHEN tags['railway'] = 'halt' THEN 'railway_halt' - -- Manholes - WHEN element_at(tags,'manhole') IN ('drain', 'sewer') THEN ROW('manhole', element_at(tags,'manhole')) - WHEN element_at(tags,'manhole') IS NOT NULL THEN ROW('manhole','manhole') + + -- 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 element_at(tags,'power') IN ( + WHEN tags['power'] IN ( 'cable_distribution', 'cable', 'catenary_mast', @@ -105,15 +365,14 @@ WITH classified_osm AS ( 'switch', 'terminal', 'transformer' - ) THEN ROW('power', element_at(tags,'power')) + ) THEN tags['power'] - WHEN element_at(tags,'power') IN ('line', 'pole', 'tower') THEN ROW('power','power_' || element_at(tags,'power')) + WHEN tags['power'] = 'line' THEN 'power_line' + WHEN tags['power'] = 'pole' THEN 'power_pole' + WHEN tags['power'] = 'tower' THEN 'power_tower' - -- Recreation - WHEN element_at(tags,'tourism') = ('camp_site') AND wkt LIKE 'POINT%' THEN ROW('recreation','camp_site') - - -- Towers - WHEN element_at(tags,'tower:type') IN ( + -- Other towers + WHEN tags['tower:type'] IN ( 'bell_tower', 'cooling', 'defensive', @@ -127,84 +386,35 @@ WITH classified_osm AS ( 'radar', 'siren', 'watchtower' - ) THEN ROW('tower', element_at(tags,'tower:type')) + ) THEN tags['tower:type'] - -- Utility - WHEN element_at(tags,'man_made') IN ('silo','utility_pole','storage_tank', 'pipeline', 'water_tower') THEN ROW('utility',element_at(tags,'man_made')) + WHEN tags['bridge'] = 'yes' THEN 'bridge' + WHEN tags['bridge'] IN ( + 'aqueduct', + 'boardwalk', + 'cantilever', + 'covered', + 'movable', + 'trestle', + 'viaduct' + ) THEN tags['bridge'] - -- Waste Management - WHEN element_at(tags,'amenity') IN( - 'recycling', - 'waste_basket', - 'waste_disposal' - ) THEN ROW('waste_management',element_at(tags,'amenity')) - - --Water - WHEN element_at(tags,'man_made') IN ('dam') THEN ROW('water',element_at(tags,'man_made')) - WHEN element_at(tags,'waterway') IN ('dam','weir') THEN ROW('water', element_at(tags,'waterway')) - WHEN element_at(tags,'amenity') = ('drinking_water') AND - (element_at(tags,'drinking_water') IS NULL OR element_at(tags,'drinking_water') <> 'no') AND - (element_at(tags,'access') IS NULL OR element_at(tags,'access') <> 'private') - THEN ROW('water', 'drinking_water') - - - -- Standalone piers - WHEN element_at(tags,'man_made') IN ('pier') THEN ROW('pier','pier') - - - -- Barrier tags are often secondary on other features, so put them last. - -- Barrier tags that are not allowed on points: - WHEN wkt NOT LIKE 'POINT%' AND element_at(tags,'barrier') IN ( - 'cable_barrier', - 'city_wall', - 'chain', - 'ditch', - 'fence', - 'guard_rail', - 'handrail', - 'hedge', - 'jersey_barrier', - 'kerb', - 'retaining_wall', - 'wall' - ) THEN ROW('barrier', element_at(tags,'barrier')) - - -- Points allowed on these types of barriers: - WHEN element_at(tags,'barrier') IN ( - 'block', - 'bollard', - 'border_control', - 'bump_gate', - 'bus_trap', - 'cattle_grid', - 'cycle_barrier', - 'chain', - 'entrance', - 'full-height_turnstile', - 'gate', - 'hampshire_gate', - 'height_restrictor', - 'jersey_barrier', - 'kerb', - 'kissing_gate', - 'lift_gate', - 'planter', - 'sally_port', - 'stile', - 'swing_gate', - 'toll_booth' - ) THEN ROW('barrier', element_at(tags,'barrier')) - WHEN element_at(tags,'man_made') IN ('cutline') THEN ROW('barrier','cutline') - - -- If there remains a barrier tag but it's not in the above list: - WHEN element_at(tags,'barrier') IS NOT NULL THEN ROW('barrier','barrier') - - -- Lower priority generic `bridge` tags - WHEN element_at(tags,'man_made') = 'bridge' THEN ROW('bridge','bridge') - WHEN element_at(tags,'bridge') = 'yes' THEN ROW('bridge','bridge') - - END AS ROW(subtype varchar, class varchar)) AS overture, - * + WHEN tags['man_made'] IN ( + 'bridge', + 'cutline', + 'pier', + 'pipeline', + 'storage_tank', + 'silo', + 'utility_pole', + 'water_tower' + ) THEN tags['man_made'] + + WHEN tags['waterway'] IN ('dam','weir') THEN tags['waterway'] + + WHEN tags['tourism'] = 'camp_site' AND wkt LIKE 'POINT%' THEN 'camp_site' + + END AS class FROM -- These two lines get injected. {daylight_table} @@ -215,8 +425,6 @@ WITH classified_osm AS ( ARRAY[ 'barrier', 'bridge', - 'bridge:support', - 'bridge:structure', 'communication:mobile_phone', 'communication', 'man_made', @@ -230,121 +438,13 @@ WITH classified_osm AS ( 'aerialway', 'aeroway', 'amenity', - 'footway', 'highway', 'icao', 'public_transport', 'railway', 'route' ] - ) -) - -SELECT - -- Needed to compute pseudo-stable ID: - type, - id, - version, - min_lon, - max_lon, - min_lat, - max_lat, - - -- Names query gets injected - '__OVERTURE_NAMES_QUERY' AS names, - - -- The overture struct is defined below - overture.subtype as subtype, - overture.class AS class, - - -- Relevant OSM tags for infrastructure - MAP_FILTER(tags, - (k,v) -> k IN ( - 'access', - 'aerodrome:type', - 'aerodrome', - 'amenity', - 'barrier', - 'bridge:structure', - 'bridge:support', - 'frequency', - 'icao', - 'landuse', - 'location', - 'military', - 'parking', - 'ref', - 'route', - 'substation', - 'surface', - 'tourism', - 'tower', - 'voltage' - ) - ) AS source_tags, - - -- Add all OSM Tags for debugging - tags AS osm_tags, - - -- Sources are an array of structs. - ARRAY [ CAST( - ROW( - '', - 'OpenStreetMap', - SUBSTR(type, 1, 1) || CAST(id AS varchar) || '@' || CAST(version AS varchar), - TO_ISO8601(created_at AT TIME ZONE 'UTC'), - NULL - ) - AS ROW( - property varchar, - dataset varchar, - record_id varchar, - update_time varchar, - confidence double - ) - ) ] AS sources, - - -- Values of surface are restricted - CASE - WHEN element_at(tags,'surface') IN ( - 'asphalt', - 'cobblestone', - 'compacted', - 'concrete', - 'dirt', - 'earth', - 'fine_gravel', - 'grass', - 'gravel', - 'ground', - 'paved', - 'paving_stones', - 'pebblestone', - 'recreation_grass', - 'recreation_paved', - 'recreation_sand', - 'rubber', - 'sand', - 'sett', - 'tartan', - 'unpaved', - 'wood', - 'woodchips' - ) THEN element_at(tags,'surface') - WHEN element_at(tags,'surface') = 'concrete:plates' - THEN 'concrete_plates' - ELSE NULL - END AS surface, - - -- Overture's concept of `layer` is called level - TRY_CAST(element_at(tags,'layer') AS int) AS level, - - -- Wikidata is a top-level property in the OSM Container - element_at(tags,'wikidata') as wikidata, - - -- Store geometries as WKT - wkt AS wkt_geometry -FROM - classified_osm + ) = TRUE + ) WHERE - overture.subtype IS NOT NULL + class IS NOT NULL diff --git a/task-force-docs/base/land.sql b/task-force-docs/base/land.sql index 5985e85e..04da4e58 100644 --- a/task-force-docs/base/land.sql +++ b/task-force-docs/base/land.sql @@ -1,165 +1,84 @@ --- This file contains the logic for transforming OpenStreetMap features into Overture features --- for the `land` type within the `base` theme. - --- The order of the WHEN clauses in the following CASE statement is very specific. It is the same --- as saying "WHEN this tag is present AND ignore any of the other tags below this line" -WITH classified_osm AS ( - SELECT CAST( - CASE - -- Desert - WHEN tags['natural'] IN ('desert') THEN ROW('desert', tags['natural']) - - -- Wetland - WHEN tags['natural'] IN ('wetland') THEN ROW('wetland', 'wetland') - - -- Glacier - WHEN tags['natural'] IN ('glacier') THEN ROW('glacier', tags['natural']) - - -- Rock - WHEN tags['natural'] IN ( - 'bare_rock', - 'rock', - 'scree', - 'shingle', - 'stone' - ) THEN ROW('rock', tags['natural']) +SELECT + -- Needed to compute ID and satisfy Overture requirements: + type, + id, + version, + min_lon, + max_lon, + min_lat, + max_lat, + TO_ISO8601(created_at AT TIME ZONE 'UTC') AS update_time, - -- Sand - WHEN tags['natural'] IN ('beach', 'dune', 'sand') THEN ROW('sand', tags['natural']) + -- Determine subtype from class: + CASE + -- Desert + WHEN class IN ('desert') THEN 'desert' - -- Grass - WHEN tags['natural'] IN ( - 'fell', - 'grass', - 'grassland', - 'meadow', - 'tundra' - ) THEN ROW('grass', tags['natural']) - WHEN tags['landcover'] IN ('grass') THEN ROW ('grass', tags['landcover']) + -- Forest + WHEN class IN ('forest', 'wood') THEN 'forest' - -- Shrub / Scrub - WHEN tags['natural'] IN ( - 'heath', - 'shrub', - 'shrubbery', - 'scrub' - ) THEN ROW('shrub',tags['natural']) - WHEN tags['landcover'] IN ('scrub') THEN ROW('shrub', tags['landcover']) + -- Glacier + WHEN class IN ('glacier') THEN 'glacier' - -- Reefs - WHEN tags['natural'] IN ('reef') THEN ROW('reef', tags['natural']) + -- Grass + WHEN class IN ('fell', 'grass', 'grassland', 'meadow', 'tundra') THEN 'grass' - -- Forest - WHEN tags['natural'] IN ('forest', 'wood') THEN ROW('forest', tags['natural']) - WHEN tags['landcover'] IN ('trees') THEN ROW('forest', 'forest') - WHEN tags['landuse'] IN ('forest') THEN ROW('forest','forest') + -- General land (including islands) + WHEN class IN ('archipelago','islet','island') THEN 'land' - -- Single trees tree rows - WHEN tags['natural'] IN ('tree') THEN ROW('tree','tree') - WHEN tags['natural'] IN ('tree_row') THEN ROW('tree','tree_row') + -- Physical + WHEN class IN ( + 'cave_entrance', + 'cliff', + 'hill', + 'mountain_range', + 'peak', + 'peninsula', + 'plateau', + 'ridge', + 'saddle', + 'valley', + 'volcano' + ) THEN 'physical' - -- Physical Subtype - WHEN tags['natural'] IN( - 'cave_entrance', - 'cliff', - 'hill', - 'mountain_range', - 'peak', - 'peninsula', - 'ridge', - 'saddle', - 'valley' - ) THEN ROW('physical', tags['natural']) + -- Reef + WHEN class IN ('reef') THEN 'reef' - -- Volcanoes - WHEN tags['natural'] = 'volcano' THEN IF( - tags['type'] = 'extinct' OR tags['volcano:status'] = 'extinct', - ROW ('physical','peak'), - ROW('physical','volcano') - ) + -- Rock + WHEN class IN ( + 'bare_rock', + 'rock', + 'scree', + 'shingle', + 'stone' + ) THEN 'rock' - -- Archipelagos, Islands & Islets - WHEN tags['place'] IN ( - 'archipelago', - 'island', - 'islet' - ) THEN ROW('land',tags['place']) + --Sand + WHEN class IN ( + 'sand', + 'beach', + 'dune' + ) THEN 'sand' - -- Look at surface tag now - WHEN tags['surface'] IN ('grass') THEN ROW('grass','grass') + --Shrub + WHEN class IN ( + 'heath', + 'scrub', + 'shrub', + 'shrubbery' + ) THEN 'shrub' - ELSE ROW(NULL, NULL) - END AS ROW(subtype varchar, class varchar) - ) AS overture, + -- Tree + WHEN class IN ('tree', 'tree_row') THEN 'tree' - -- Allowed surface tags - CASE - WHEN tags['surface'] IN ( - 'asphalt', - 'cobblestone', - 'compacted', - 'concrete', - 'dirt', - 'earth', - 'fine_gravel', - 'grass', - 'gravel', - 'ground', - 'paved', - 'paving_stones', - 'pebblestone', - 'recreation_grass', - 'recreation_paved', - 'recreation_sand', - 'rubber', - 'sand', - 'sett', - 'tartan', - 'unpaved', - 'wood', - 'woodchips' - ) THEN tags['surface'] - WHEN tags['surface'] = 'concrete:plates' - THEN 'concrete_plates' - ELSE NULL - END AS surface, - TRY_CAST(tags['ele'] AS integer) AS elevation, - * - FROM - {daylight_table} - WHERE - release = '{daylight_version}' - -- These tags are considered for the land type: - AND - ( - tags [ 'natural' ] IS NOT NULL - OR tags [ 'surface' ] IS NOT NULL - OR tags [ 'landcover' ] IS NOT NULL - OR tags [ 'landuse' ] IN ('forest', 'meadow') - OR tags [ 'place' ] IN ('archipelago','island','islet') - ) - -- None of the below tags can be present; they go in other theme/types - AND tags [ 'highway' ] IS NULL - AND tags [ 'building' ] IS NULL - AND tags [ 'golf' ] IS NULL - AND tags [ 'leisure' ] IS NULL -) -SELECT - -- Needed to compute ID and satisfy Overture requirements: - type, - id, - version, - min_lon, - max_lon, - min_lat, - max_lat, + -- Wetland + WHEN tags [ 'natural' ] IN ('wetland') THEN 'wetland' + END AS subtype, + class, -- Complex name logic gets injected here '__OVERTURE_NAMES_QUERY' AS names, - overture.subtype AS subtype, - overture.class AS class, - -- Relevant OSM tags for land type MAP_FILTER(tags, (k,v) -> k IN ( 'building', @@ -179,7 +98,6 @@ SELECT 'min_height', 'natural', 'place', - 'reef', 'species', 'sport', 'surface', @@ -201,14 +119,12 @@ SELECT '', 'OpenStreetMap', SUBSTR(type, 1, 1) || CAST(id AS varchar) || '@' || CAST(version AS varchar), - TO_ISO8601(created_at AT TIME ZONE 'UTC'), NULL ) AS ROW( property varchar, dataset varchar, record_id varchar, - update_time varchar, confidence double ) ) ] AS sources, @@ -219,18 +135,144 @@ SELECT -- Overture's concept of `layer` is called level TRY_CAST(tags['layer'] AS int) AS level, - -- Elevation as meters above sea level - IF(elevation < 9000, elevation, NULL) as elevation, + -- Elevation as integer (meters above sea level) + TRY_CAST(tags['ele'] AS integer) AS elevation, - -- Surface - surface, + wkt_geometry - wkt AS wkt_geometry +FROM ( + SELECT + *, + -- Determine classes from OSM tags + CASE -FROM - classified_osm + -- Natural tags that map to specific classes: + WHEN tags [ 'natural' ] IN ( + 'bare_rock', + 'beach', + 'cave_entrance', + 'cliff', + 'desert', + 'dune', + 'fell', + 'forest', + 'glacier', + 'grassland', + 'heath', + 'hill', + 'mountain_range', + 'peak', + 'peninsula', + 'plateau', + 'reef', + 'ridge', + 'rock', + 'sand', + 'saddle', + 'scree', + 'scrub', + 'shingle', + 'shrub', + 'shrubbery', + 'stone', + 'tree_row', + 'tree', + 'tundra', + 'valley', + 'wetland', + 'wood' + ) THEN tags ['natural'] + + -- More complicated logic for turning volcanoes into peaks. + WHEN tags['natural'] = 'volcano' THEN CASE + WHEN tags['type'] = 'extinct' OR tags['volcano:status'] = 'extinct' THEN 'peak' + WHEN (tags['type'] <> 'extinct' OR tags['type'] IS NULL) AND (tags['volcano:status'] <> 'extinct' OR tags['volcano:status'] IS NULL) THEN 'volcano' + END + + -- Surface tags that become classes + WHEN tags [ 'surface' ] IN ('grass') THEN tags [ 'surface' ] + WHEN tags [ 'landcover' ] = 'trees' THEN 'forest' + WHEN tags [ 'landcover' ] IN ('grass', 'scrub', 'tree') THEN tags [ 'landcover' ] + + WHEN tags [ 'meadow' ] IS NULL AND tags [ 'landuse' ] = 'forest' THEN 'forest' + + -- If there was no other land tag, we can send these up to `land` + WHEN tags ['place'] IN ('archipelago','island','islet') THEN tags['place'] + + ELSE NULL + END AS class + 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 tags are considered for the land type: + AND + ( + tags [ 'natural' ] IS NOT NULL + OR tags [ 'surface' ] IS NOT NULL + OR tags [ 'landcover' ] IS NOT NULL + OR tags [ 'landuse' ] IN ('forest', 'meadow') + OR tags [ 'place' ] IN ('archipelago','island','islet') + ) + -- None of the below tags can be present; they go in other theme/types + AND tags [ 'highway' ] IS NULL + AND tags [ 'building' ] IS NULL + AND tags [ 'golf' ] IS NULL + AND tags [ 'leisure' ] IS NULL + ) +) WHERE - overture.subtype IS NOT NULL + class IS NOT NULL -- Ignore anything that didn't get assigned a class + AND ( + -- Polygons are always allowed + wkt_geometry LIKE '%POLYGON%' + + -- Valid Point classes: + OR ( + wkt_geometry LIKE '%POINT%' + AND class IN ( + 'cave_entrance', + 'cliff', + 'hill', + 'mountain_range', + 'peak', + 'peninsula', + 'plateau', + 'saddle', + 'shrub', + 'tree', + 'valley', + 'volcano', + 'stone' + ) + ) + -- Valid LineStrings + OR ( + wkt_geometry LIKE '%LINESTRING%' + AND class IN ( + 'cliff', + 'mountain_range', + 'tree_row', + 'ridge', + 'valley' + ) + ) + ) UNION ALL -- Land derived from the OSM Coastline tool @@ -243,9 +285,11 @@ SELECT ST_XMAX(ST_GeometryFromText(wkt)) as max_lon, ST_YMIN(ST_GeometryFromText(wkt)) AS min_lat, ST_YMAX(ST_GeometryFromText(wkt)) AS max_lat, - NULL AS names, - class as subtype, + -- Stub with today's date for now + TO_ISO8601(cast(now() as timestamp) AT TIME ZONE 'UTC') AS update_time, + class as subType, subclass as class, + NULL AS names, MAP() AS source_tags, MAP() AS osm_tags, -- Source is OSM @@ -254,20 +298,17 @@ SELECT '', 'OpenStreetMap', NULL, - NULL, NULL ) AS ROW( property varchar, dataset varchar, record_id varchar, - update_time varchar, confidence double ) ) ] as sources, NULL AS wikidata, NULL AS level, NULL AS elevation, - NULL AS surface, wkt AS wkt_geometry FROM {daylight_earth_table} WHERE release = '{daylight_version}' diff --git a/task-force-docs/places/overture_categories.csv b/task-force-docs/places/overture_categories.csv index 6fa1f944..2c1c22b9 100644 --- a/task-force-docs/places/overture_categories.csv +++ b/task-force-docs/places/overture_categories.csv @@ -645,7 +645,7 @@ massage;[beauty_and_spa,massage] nail_salon;[beauty_and_spa,nail_salon] onsen;[beauty_and_spa,onsen] permanent_makeup;[beauty_and_spa,permanent_makeup] -tattoo_and_piercing;[beauty_and_spa,tattoo_and_piercing] +tattoo_and_piercing;[beauty_and_spa,tattoo_and_piercing piercing;[beauty_and_spa,tattoo_and_piercing,piercing] tattoo;[beauty_and_spa,tattoo_and_piercing,tattoo] public_bath_houses;[beauty_and_spa,public_bath_houses]