schema_name: Shortbread schema_description: A basic, lean, general-purpose vector tile schema for OpenStreetMap data. See https://shortbread.geofabrik.de/ attribution: © OpenStreetMap contributors examples: shortbread.spec.yml args: area: description: Geofabrik area to download default: massachusetts osm_url: description: OSM URL to download default: '${ args.area == "planet" ? "aws:latest" : ("geofabrik:" + args.area) }' sources: ocean: type: shapefile url: https://osmdata.openstreetmap.de/download/water-polygons-split-3857.zip admin_points: type: shapefile url: https://shortbread.geofabrik.de/shapefiles/admin-points-4326.zip osm: type: osm url: '${ args.osm_url }' definitions: # TODO let attribute definitions set multiple keys so you can just use `- *names` attributes: - &name key: name - &name_en key: name_en tag_value: name:en - &name_de key: name_de tag_value: name:de layers: # Water - id: ocean features: - source: ocean geometry: polygon - id: water_polygons features: - source: osm geometry: polygon min_zoom: default_value: 4 overrides: &water_zoom_overrides 10: waterway: [ dock, canal ] include_when: &water_filter natural: - glacier - water waterway: - riverbank - dock - canal landuse: - reservoir - basin attributes: - key: kind type: match_value - id: water_polygons_labels features: - source: osm geometry: polygon_centroid min_zoom: default_value: 14 overrides: *water_zoom_overrides include_when: *water_filter exclude_when: name: '' attributes: - key: kind type: match_value - *name - *name_en - *name_de - id: water_lines features: - source: osm geometry: line min_zoom: default_value: 9 overrides: 14: waterway: [ stream, ditch ] # TODO rivers and canals min length=0.25px include_when: waterway: - canal - river - stream - ditch attributes: - key: kind type: match_value - id: water_line_labels features: - source: osm geometry: line min_zoom: default_value: 12 overrides: 14: waterway: [ stream, ditch ] # TODO rivers and canals min length=0.25px include_when: waterway: - canal - river - stream - ditch exclude_when: name: '' attributes: - key: kind type: match_value - *name - *name_en - *name_de ## Countries, States, Cities - id: boundaries features: - source: osm geometry: line # TODO get min admin level from relations min_size: 0 min_zoom: default_value: 7 overrides: 0: admin_level: 2 include_when: __all__: - boundary: administrative - admin_level: [ 2, 4 ] attributes: - key: maritime type: boolean - key: admin_level type: integer - id: boundary_labels features: - source: admin_points geometry: point min_zoom: default_value: 5 overrides: 2: '${ feature.tags.has("ADMIN_LEVEL", "2") && double(feature.tags.WAY_AREA) >= 2e8 }' 3: '${ double(feature.tags.WAY_AREA) >= 7e7 }' 4: '${ double(feature.tags.WAY_AREA) >= 1e7 }' # TODO sort by WAY_AREA descending attributes: - key: way_area tag_value: WAY_AREA type: double - key: admin_level tag_value: ADMIN_LEVEL type: integer - key: name tag_value: NAME - key: name_en tag_value: NAME_EN - key: name_de tag_value: NAME_DE - id: place_labels features: - source: osm geometry: point include_when: place: - city - town - village - hamlet - suburb - neighbourhood - isolated_dwelling - farm - island - locality exclude_when: name: '' min_zoom: default_value: 10 overrides: 4: __all__: place: [ city, town, village, hamlet ] capital: [ yes, '4' ] 6: __all__: place: city __not__: capital: [ yes, '4' ] 7: __all__: place: town __not__: capital: [ yes, '4' ] # TODO z-order attributes: - key: kind value: default_value: '${ match_value }' overrides: capital: __all__: place: [ city, town, village, hamlet ] capital: yes state_capital: __all__: place: [ city, town, village, hamlet ] capital: '4' - *name - *name_en - *name_de - key: population type: integer value: match: - value: '${ feature.tags.get("population") }' if: { population: __any__ } - value: 100000 if: { place: city } - value: 5000 if: { place: town } - value: 1000 if: { place: suburb } - value: 100 if: { place: [ village, neighborhood ] } - value: 50 if: { place: hamlet } - value: 5 if: { place: [ isolated_dwelling, farm ] } - else: 0 # Land Use, Land Cover, Buildings - id: land features: - source: osm geometry: polygon include_when: amenity: - grave_yard landuse: - allotments - brownfield - cemetery - commercial - farmland - farmyard - forest - grass - greenfield - greenhouse_horticulture - industrial - landfill - meadow - orchard - plant_nursery - quarry - railway - recreation_ground - residential - retail - village_green - vineyard leisure: - garden - golf_course - miniature_golf - park - playground natural: - bare_rock - beach - grassland - heath - sand - scree - scrub - shingle - wood wetland: - bog - marsh - string_bog - swamp - wet_meadow min_zoom: default_value: 11 overrides: 7: natural: wood landuse: forest 10: landuse: - brownfield - commercial - farmland - farmyard - greenfield - industrial - landfill - railway - residential - retail natural: - beach - sand 13: amenity: grave_yard natural: wood landuse: cemetery attributes: - key: kind value: '${match_value == "forest" ? "wood": match_value}' - id: sites features: - source: osm geometry: polygon min_zoom: 14 include_when: military: danger_area leisure: sports_center landuse: construction amenity: - university - hospital - prison - parking - bicycle_parking attributes: - key: kind type: match_value - id: buildings features: - source: osm geometry: polygon min_zoom: 14 include_when: building: __any__ exclude_when: building: no - id: addresses features: - source: osm geometry: polygon_centroid_if_convex min_zoom: 14 include_when: &address_filter addr:housenumber: __any__ addr:housename: __any__ attributes: &address_attributes - key: name tag_value: addr:housename - key: number tag_value: addr:housenumber - source: osm geometry: point min_zoom: 14 include_when: *address_filter attributes: *address_attributes ## Streets and Transport - id: streets features: - source: osm geometry: line min_size: 0 min_zoom: default_value: 13 overrides: 5: highway: motorway% 6: highway: trunk% 8: highway: primary% __all__: railway: [ rail, narrow_gauge ] service: __any__ 9: highway: secondary% 10: __all__: railway: [ rail, narrow_gauge ] service: '' railway: - funicular - light_rail - monorail - subway - tram highway: tertiary 11: aeroway: runway 12: highway: [ residential, unclassified ] # TODO min_tile_cover_size: 0 # TODO z-order include_when: highway: - motorway - motorway_link - trunk - trunk_link - primary - primary_link - secondary - secondary_link - tertiary - tertiary_link - unclassified - residential - living_street - service - pedestrian - track - footway - steps - path - cycleway aeroway: # TODO update shortbread spec - runway - taxiway railway: - rail - narrow_gauge - tram - light_rail - funicular - subway - monorail attributes: - key: kind value: '${ match_value.replace("_link", "") }' - key: link min_zoom: 11 value: true include_when: highway: '%_link' else: false - key: rail min_zoom: 11 value: true include_when: railway: __any__ else: false - &tunnel_attr key: tunnel min_zoom: 11 value: true include_when: tunnel: [ yes, building_passage ] covered: yes else: false - &bridge_attr key: bridge min_zoom: 11 value: true include_when: bridge: yes else: false - key: tracktype min_zoom: 11 - key: surface # TODO canonicalize? min_zoom: 11 - key: service min_zoom: 11 - key: bicycle min_zoom: 14 - key: horse min_zoom: 14 - id: street_labels features: - source: osm geometry: line min_zoom: default_value: 14 overrides: 10: highway: motorway 12: highway: [ trunk, primary ] 13: highway: - motorway_link - trunk_link - primary_link - secondary - secondary_link - tertiary include_when: highway: - motorway - motorway_link - trunk - trunk_link - primary - primary_link - secondary - secondary_link - tertiary - tertiary_link - unclassified - residential - living_street - service - pedestrian - track - footway - steps - path - cycleway exclude_when: __all__: name: '' ref: '' attributes: - key: kind value: '${ match_value.replace("_link", "") }' - *name - *name_en - *name_de # TODO use ref var to avoid duplicating logic - key: ref exclude_when: &missing_ref ref: '' value: '${ feature.tags["ref"].replace(";", "\n") }' - key: ref_cols value: '${ max(feature.tags["ref"].split(";").map(r, size(r))) }' exclude_when: *missing_ref - key: ref_rows value: '${ size(feature.tags["ref"].split(";")) }' exclude_when: *missing_ref - id: street_polygons features: - source: osm geometry: polygon min_zoom: 14 include_when: __all__: - highway: [ pedestrian, service ] - area: yes attributes: - key: kind type: match_value - *bridge_attr - *tunnel_attr - key: surface - key: rail value: false # TODO omit? - id: street_polygons_labels features: - source: osm geometry: polygon_point_on_surface min_zoom: 14 include_when: __all__: highway: [ pedestrian, service ] area: yes name: __any__ attributes: - key: kind type: match_value - *name - *name_en - *name_de - id: street_labels_points # TODO update documentation (streetS_labels_points) features: - source: osm geometry: point min_zoom: 12 include_when: highway: motorway_junction attributes: - key: kind type: match_value - key: ref - *name - *name_en - *name_de - id: aerialways features: - source: osm geometry: line min_zoom: 12 include_when: aerialway: __any__ attributes: - key: kind type: match_value - id: public_transport features: - source: osm geometry: point min_zoom: &public_transport_zoom default_value: 14 overrides: 11: aeroway: aerodrome 13: railway: [ station, halt ] aerialway: station include_when: &public_transport_filter railway: [ station, halt, tram_stop ] aeroway: aerodrome aerialway: station attributes: &public_transport_attrs - key: kind type: match_value - *name - *name_en - *name_de - key: iata - source: osm geometry: polygon_point_on_surface min_zoom: *public_transport_zoom include_when: *public_transport_filter attributes: *public_transport_attrs