From e3ec5ce1f982be64db684bbfe821350467364bae Mon Sep 17 00:00:00 2001 From: Paul Bienkowski Date: Sun, 31 Oct 2021 20:50:09 +0100 Subject: [PATCH] Correct directional road rendering, and include all roads with null data in obs layer --- api/roads_import.lua | 14 +- api/scripts | 2 +- frontend/src/mapstyles/index.js | 179 ++- frontend/src/mapstyles/positron.json | 1047 +++++++++++++++++ tile-generator/layers/obs_roads/layer.sql | 28 +- .../layers/obs_roads/obs_roads.yaml | 28 +- 6 files changed, 1240 insertions(+), 58 deletions(-) create mode 100644 frontend/src/mapstyles/positron.json diff --git a/api/roads_import.lua b/api/roads_import.lua index 8aa9c03..c089d58 100644 --- a/api/roads_import.lua +++ b/api/roads_import.lua @@ -50,8 +50,12 @@ local MOTORWAY_TYPES = { "motorway_link", } +local ONEWAY_YES = {"yes", "true", "1"} +local ONEWAY_REVERSE = {"reverse", "-1"} + local roads = osm2pgsql.define_way_table('road', { { column = 'zone', type = 'text', sql_type="zone_type" }, + { column = 'directionality', type = 'int' }, { column = 'name', type = 'text' }, { column = 'geometry', type = 'linestring' }, { column = 'tags', type = 'hstore' }, @@ -87,10 +91,18 @@ function osm2pgsql.process_way(object) end end + local directionality = 0 + if contains(ONEWAY_YES, tags["oneway"]) then + directionality = 1 + elseif contains(ONEWAY_REVERSE, tags["oneway"]) then + directionality = -1 + end + roads:add_row({ - geometry = { create = 'linear' }, + geom = { create = 'linear' }, name = tags.name, zone = zone, + directionality = directionality, tags = tags, }) end diff --git a/api/scripts b/api/scripts index 767b716..e67a2a9 160000 --- a/api/scripts +++ b/api/scripts @@ -1 +1 @@ -Subproject commit 767b7166105b2446c3b4e0334222052114b0ebae +Subproject commit e67a2a98f7d8d53c687bc44d72774b5429b049c3 diff --git a/frontend/src/mapstyles/index.js b/frontend/src/mapstyles/index.js index 03f650c..101eda8 100644 --- a/frontend/src/mapstyles/index.js +++ b/frontend/src/mapstyles/index.js @@ -1,61 +1,140 @@ import _ from 'lodash' import bright from './bright.json' +import positron from './positron.json' -function getRoadsStyle(sourceUrl = "http://localhost:3002/data/v3.json") { - return { - "version": 8, - "name": "OBS Roads", - "sources": { - "obs": {"type": "vector", "url": sourceUrl} +function addRoadsStyle(style, sourceUrl = "http://localhost:3002/data/v3.json") { + style.sources.obs = {"type": "vector", "url": sourceUrl} + + // insert before "road_oneway" layer + let idx = style.layers.findIndex(l => l.id === 'road_oneway') + if (idx === -1) { + idx = style.layers.length + } + style.layers.splice(idx, 0, { + "id": "obs", + "type": "line", + "source": "obs", + "source-layer": "obs_roads", + "layout": { + "line-cap": "round", + "line-join": "round" }, - "layers": [ - { - "id": "obs", - "type": "line", - "source": "obs", - "source-layer": "obs_roads", - "layout": {"line-cap": "round", "line-join": "round"}, - "paint": { - "line-width": {"stops": [[14, 2], [17, 8]]}, - "line-color": [ - "interpolate-hcl", - ["linear"], - ["get", "distance_overtaker_mean"], - 1, - "rgba(255, 0, 0, 1)", - 1.3, - "rgba(255, 200, 0, 1)", - 1.5, - "rgba(67, 200, 0, 1)", - 1.7, - "rgba(67, 150, 0, 1)" + "paint": { + "line-width": [ + "interpolate", + ["exponential", 1.5], + ["zoom"], + 12, + 1, + 17, + [ + "case", + [ + "!", + [ + "to-boolean", + [ + "get", + "distance_overtaker_mean" + ] + ] ], - "line-opacity": 1, - "line-offset": {"stops": [[14, 1], [17, 7]]} - } - } - ], - "id": "obs-roads" - } -} - -function mergeStyles(baseStyle, ...extensions) { - const style = _.cloneDeep(baseStyle) - for (const extension of extensions) { - for (const key of Object.keys(extension)) { - if (['sources', 'layers', 'id', 'name', 'version'].includes(key)) { - continue - } - - throw new Error(`cannot use style ${extension.id ?? extension.name} as extension style, it defines ${key}`) - } - style.sources = {...style.sources, ...extension.sources} - style.layers = [...style.layers, ...extension.layers] - } + 2, + 6 + ] + ], + "line-color": [ + "case", + [ + "!", + [ + "to-boolean", + [ + "get", + "distance_overtaker_mean" + ] + ] + ], + "#ABC", + [ + "interpolate-hcl", + ["linear"], + [ + "get", + "distance_overtaker_mean" + ], + 1, + "rgba(255, 0, 0, 1)", + 1.3, + "rgba(255, 200, 0, 1)", + 1.5, + "rgba(67, 200, 0, 1)", + 1.7, + "rgba(67, 150, 0, 1)" + ] + ], + "line-opacity": [ + "interpolate", + ["linear"], + ["zoom"], + 12, + 0, + 13, + [ + "case", + [ + "!", + [ + "to-boolean", + [ + "get", + "distance_overtaker_mean" + ] + ] + ], + 0, + 1 + ], + 14, + [ + "case", + [ + "!", + [ + "to-boolean", + [ + "get", + "distance_overtaker_mean" + ] + ] + ], + 0, + 1 + ], + 15, + 1 + ], + "line-offset": [ + "interpolate", + ["exponential", 1.5], + ["zoom"], + 12, + ["get", "offset_direction"], + 19, + [ + "*", + ["get", "offset_direction"], + 8 + ] + ] + }, + "minzoom": 12 + }) return style } + export const basemap = bright -export const obsRoads = (sourceUrl) => mergeStyles(basemap, getRoadsStyle(sourceUrl)) +export const obsRoads = (sourceUrl) => addRoadsStyle(_.cloneDeep(positron), sourceUrl) diff --git a/frontend/src/mapstyles/positron.json b/frontend/src/mapstyles/positron.json new file mode 100644 index 0000000..6d3b9b0 --- /dev/null +++ b/frontend/src/mapstyles/positron.json @@ -0,0 +1,1047 @@ +{ + "version": 8, + "name": "Positron", + "sources": { + "openmaptiles": { + "type": "vector", + "tiles": ["https://portal.openbikesensor.org/tiles/data/basemap/{z}/{x}/{y}.pbf"], + "minzoom": 0, + "maxzoom": 14 + } + }, + "sprite": "https://openmaptiles.github.io/osm-bright-gl-style/sprite", + "glyphs": "https://portal.openbikesensor.org/tiles/fonts/{fontstack}/{range}.pbf?key={key}", + "layers": [ + { + "id": "background", + "type": "background", + "paint": {"background-color": "rgb(242,243,240)"} + }, + { + "id": "park", + "type": "fill", + "source": "openmaptiles", + "source-layer": "park", + "filter": ["==", "$type", "Polygon"], + "layout": {"visibility": "visible"}, + "paint": {"fill-color": "rgb(230, 233, 229)"} + }, + { + "id": "water", + "type": "fill", + "source": "openmaptiles", + "source-layer": "water", + "filter": [ + "all", + ["==", "$type", "Polygon"], + ["!=", "brunnel", "tunnel"] + ], + "layout": {"visibility": "visible"}, + "paint": {"fill-antialias": true, "fill-color": "rgb(194, 200, 202)"} + }, + { + "id": "landcover_ice_shelf", + "type": "fill", + "source": "openmaptiles", + "source-layer": "landcover", + "maxzoom": 8, + "filter": [ + "all", + ["==", "$type", "Polygon"], + ["==", "subclass", "ice_shelf"] + ], + "layout": {"visibility": "visible"}, + "paint": {"fill-color": "hsl(0, 0%, 98%)", "fill-opacity": 0.7} + }, + { + "id": "landcover_glacier", + "type": "fill", + "source": "openmaptiles", + "source-layer": "landcover", + "maxzoom": 8, + "filter": [ + "all", + ["==", "$type", "Polygon"], + ["==", "subclass", "glacier"] + ], + "layout": {"visibility": "visible"}, + "paint": { + "fill-color": "hsl(0, 0%, 98%)", + "fill-opacity": {"base": 1, "stops": [[0, 1], [8, 0.5]]} + } + }, + { + "id": "landuse_residential", + "type": "fill", + "source": "openmaptiles", + "source-layer": "landuse", + "maxzoom": 16, + "filter": [ + "all", + ["==", "$type", "Polygon"], + ["==", "class", "residential"] + ], + "layout": {"visibility": "visible"}, + "paint": { + "fill-color": "rgb(234, 234, 230)", + "fill-opacity": {"base": 0.6, "stops": [[8, 0.8], [9, 0.6]]} + } + }, + { + "id": "landcover_wood", + "type": "fill", + "source": "openmaptiles", + "source-layer": "landcover", + "minzoom": 10, + "filter": ["all", ["==", "$type", "Polygon"], ["==", "class", "wood"]], + "layout": {"visibility": "visible"}, + "paint": { + "fill-color": "rgb(220,224,220)", + "fill-opacity": {"base": 1, "stops": [[8, 0], [12, 1]]} + } + }, + { + "id": "waterway", + "type": "line", + "source": "openmaptiles", + "source-layer": "waterway", + "filter": ["==", "$type", "LineString"], + "layout": {"visibility": "visible"}, + "paint": {"line-color": "hsl(195, 17%, 78%)"} + }, + { + "id": "water_name", + "type": "symbol", + "source": "openmaptiles", + "source-layer": "water_name", + "filter": ["==", "$type", "LineString"], + "layout": { + "symbol-placement": "line", + "symbol-spacing": 500, + "text-field": "{name:latin}\n{name:nonlatin}", + "text-font": ["Metropolis Medium Italic", "Noto Sans Italic"], + "text-rotation-alignment": "map", + "text-size": 12 + }, + "paint": { + "text-color": "rgb(157,169,177)", + "text-halo-blur": 1, + "text-halo-color": "rgb(242,243,240)", + "text-halo-width": 1 + } + }, + { + "id": "building", + "type": "fill", + "source": "openmaptiles", + "source-layer": "building", + "minzoom": 12, + "paint": { + "fill-antialias": true, + "fill-color": "rgb(234, 234, 229)", + "fill-outline-color": "rgb(219, 219, 218)" + } + }, + { + "id": "tunnel_motorway_casing", + "type": "line", + "source": "openmaptiles", + "source-layer": "transportation", + "minzoom": 6, + "filter": [ + "all", + ["==", "$type", "LineString"], + ["all", ["==", "brunnel", "tunnel"], ["==", "class", "motorway"]] + ], + "layout": { + "line-cap": "butt", + "line-join": "miter", + "visibility": "visible" + }, + "paint": { + "line-color": "rgb(213, 213, 213)", + "line-opacity": 1, + "line-width": {"base": 1.4, "stops": [[5.8, 0], [6, 3], [20, 40]]} + } + }, + { + "id": "tunnel_motorway_inner", + "type": "line", + "source": "openmaptiles", + "source-layer": "transportation", + "minzoom": 6, + "filter": [ + "all", + ["==", "$type", "LineString"], + ["all", ["==", "brunnel", "tunnel"], ["==", "class", "motorway"]] + ], + "layout": { + "line-cap": "round", + "line-join": "round", + "visibility": "visible" + }, + "paint": { + "line-color": "rgb(234,234,234)", + "line-width": {"base": 1.4, "stops": [[4, 2], [6, 1.3], [20, 30]]} + } + }, + { + "id": "aeroway-taxiway", + "type": "line", + "source": "openmaptiles", + "source-layer": "aeroway", + "minzoom": 12, + "filter": ["all", ["in", "class", "taxiway"]], + "layout": { + "line-cap": "round", + "line-join": "round", + "visibility": "visible" + }, + "paint": { + "line-color": "hsl(0, 0%, 88%)", + "line-opacity": 1, + "line-width": {"base": 1.55, "stops": [[13, 1.8], [20, 20]]} + } + }, + { + "id": "aeroway-runway-casing", + "type": "line", + "source": "openmaptiles", + "source-layer": "aeroway", + "minzoom": 11, + "filter": ["all", ["in", "class", "runway"]], + "layout": { + "line-cap": "round", + "line-join": "round", + "visibility": "visible" + }, + "paint": { + "line-color": "hsl(0, 0%, 88%)", + "line-opacity": 1, + "line-width": {"base": 1.5, "stops": [[11, 6], [17, 55]]} + } + }, + { + "id": "aeroway-area", + "type": "fill", + "source": "openmaptiles", + "source-layer": "aeroway", + "minzoom": 4, + "filter": [ + "all", + ["==", "$type", "Polygon"], + ["in", "class", "runway", "taxiway"] + ], + "layout": {"visibility": "visible"}, + "paint": { + "fill-color": "rgba(255, 255, 255, 1)", + "fill-opacity": {"base": 1, "stops": [[13, 0], [14, 1]]} + } + }, + { + "id": "aeroway-runway", + "type": "line", + "source": "openmaptiles", + "source-layer": "aeroway", + "minzoom": 11, + "filter": [ + "all", + ["in", "class", "runway"], + ["==", "$type", "LineString"] + ], + "layout": { + "line-cap": "round", + "line-join": "round", + "visibility": "visible" + }, + "paint": { + "line-color": "rgba(255, 255, 255, 1)", + "line-opacity": 1, + "line-width": {"base": 1.5, "stops": [[11, 4], [17, 50]]} + } + }, + { + "id": "road_area_pier", + "type": "fill", + "source": "openmaptiles", + "source-layer": "transportation", + "filter": ["all", ["==", "$type", "Polygon"], ["==", "class", "pier"]], + "layout": {"visibility": "visible"}, + "paint": {"fill-antialias": true, "fill-color": "rgb(242,243,240)"} + }, + { + "id": "road_pier", + "type": "line", + "source": "openmaptiles", + "source-layer": "transportation", + "filter": ["all", ["==", "$type", "LineString"], ["in", "class", "pier"]], + "layout": {"line-cap": "round", "line-join": "round"}, + "paint": { + "line-color": "rgb(242,243,240)", + "line-width": {"base": 1.2, "stops": [[15, 1], [17, 4]]} + } + }, + { + "id": "highway_path", + "type": "line", + "source": "openmaptiles", + "source-layer": "transportation", + "filter": ["all", ["==", "$type", "LineString"], ["==", "class", "path"]], + "layout": { + "line-cap": "round", + "line-join": "round", + "visibility": "visible" + }, + "paint": { + "line-color": "rgb(234, 234, 234)", + "line-opacity": 0.9, + "line-width": {"base": 1.2, "stops": [[13, 1], [20, 10]]} + } + }, + { + "id": "highway_minor", + "type": "line", + "source": "openmaptiles", + "source-layer": "transportation", + "minzoom": 8, + "filter": [ + "all", + ["==", "$type", "LineString"], + ["in", "class", "minor", "service", "track"] + ], + "layout": { + "line-cap": "round", + "line-join": "round", + "visibility": "visible" + }, + "paint": { + "line-color": "hsl(0, 0%, 88%)", + "line-opacity": 0.9, + "line-width": {"base": 1.55, "stops": [[13, 1.8], [20, 20]]} + } + }, + { + "id": "highway_major_casing", + "type": "line", + "source": "openmaptiles", + "source-layer": "transportation", + "minzoom": 11, + "filter": [ + "all", + ["==", "$type", "LineString"], + ["in", "class", "primary", "secondary", "tertiary", "trunk"] + ], + "layout": { + "line-cap": "butt", + "line-join": "miter", + "visibility": "visible" + }, + "paint": { + "line-color": "rgb(213, 213, 213)", + "line-dasharray": [12, 0], + "line-width": {"base": 1.3, "stops": [[10, 3], [20, 23]]} + } + }, + { + "id": "highway_major_inner", + "type": "line", + "source": "openmaptiles", + "source-layer": "transportation", + "minzoom": 11, + "filter": [ + "all", + ["==", "$type", "LineString"], + ["in", "class", "primary", "secondary", "tertiary", "trunk"] + ], + "layout": { + "line-cap": "round", + "line-join": "round", + "visibility": "visible" + }, + "paint": { + "line-color": "#fff", + "line-width": {"base": 1.3, "stops": [[10, 2], [20, 20]]} + } + }, + { + "id": "highway_major_subtle", + "type": "line", + "source": "openmaptiles", + "source-layer": "transportation", + "maxzoom": 11, + "filter": [ + "all", + ["==", "$type", "LineString"], + ["in", "class", "primary", "secondary", "tertiary", "trunk"] + ], + "layout": { + "line-cap": "round", + "line-join": "round", + "visibility": "visible" + }, + "paint": {"line-color": "hsla(0, 0%, 85%, 0.69)", "line-width": 2} + }, + { + "id": "highway_motorway_casing", + "type": "line", + "source": "openmaptiles", + "source-layer": "transportation", + "minzoom": 6, + "filter": [ + "all", + ["==", "$type", "LineString"], + [ + "all", + ["!in", "brunnel", "bridge", "tunnel"], + ["==", "class", "motorway"] + ] + ], + "layout": { + "line-cap": "butt", + "line-join": "miter", + "visibility": "visible" + }, + "paint": { + "line-color": "rgb(213, 213, 213)", + "line-dasharray": [2, 0], + "line-opacity": 1, + "line-width": {"base": 1.4, "stops": [[5.8, 0], [6, 3], [20, 40]]} + } + }, + { + "id": "highway_motorway_inner", + "type": "line", + "source": "openmaptiles", + "source-layer": "transportation", + "minzoom": 6, + "filter": [ + "all", + ["==", "$type", "LineString"], + [ + "all", + ["!in", "brunnel", "bridge", "tunnel"], + ["==", "class", "motorway"] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round", + "visibility": "visible" + }, + "paint": { + "line-color": { + "base": 1, + "stops": [[5.8, "hsla(0, 0%, 85%, 0.53)"], [6, "#fff"]] + }, + "line-width": {"base": 1.4, "stops": [[4, 2], [6, 1.3], [20, 30]]} + } + }, + { + "id": "highway_motorway_subtle", + "type": "line", + "source": "openmaptiles", + "source-layer": "transportation", + "maxzoom": 6, + "filter": [ + "all", + ["==", "$type", "LineString"], + ["==", "class", "motorway"] + ], + "layout": { + "line-cap": "round", + "line-join": "round", + "visibility": "visible" + }, + "paint": { + "line-color": "hsla(0, 0%, 85%, 0.53)", + "line-width": {"base": 1.4, "stops": [[4, 2], [6, 1.3]]} + } + }, + { + "id": "railway_transit", + "type": "line", + "source": "openmaptiles", + "source-layer": "transportation", + "minzoom": 16, + "filter": [ + "all", + ["==", "$type", "LineString"], + ["all", ["==", "class", "transit"], ["!in", "brunnel", "tunnel"]] + ], + "layout": {"line-join": "round", "visibility": "visible"}, + "paint": {"line-color": "#dddddd", "line-width": 3} + }, + { + "id": "railway_transit_dashline", + "type": "line", + "source": "openmaptiles", + "source-layer": "transportation", + "minzoom": 16, + "filter": [ + "all", + ["==", "$type", "LineString"], + ["all", ["==", "class", "transit"], ["!in", "brunnel", "tunnel"]] + ], + "layout": {"line-join": "round", "visibility": "visible"}, + "paint": { + "line-color": "#fafafa", + "line-dasharray": [3, 3], + "line-width": 2 + } + }, + { + "id": "railway_service", + "type": "line", + "source": "openmaptiles", + "source-layer": "transportation", + "minzoom": 16, + "filter": [ + "all", + ["==", "$type", "LineString"], + ["all", ["==", "class", "rail"], ["has", "service"]] + ], + "layout": {"line-join": "round", "visibility": "visible"}, + "paint": {"line-color": "#dddddd", "line-width": 3} + }, + { + "id": "railway_service_dashline", + "type": "line", + "source": "openmaptiles", + "source-layer": "transportation", + "minzoom": 16, + "filter": [ + "all", + ["==", "$type", "LineString"], + ["==", "class", "rail"], + ["has", "service"] + ], + "layout": {"line-join": "round", "visibility": "visible"}, + "paint": { + "line-color": "#fafafa", + "line-dasharray": [3, 3], + "line-width": 2 + } + }, + { + "id": "railway", + "type": "line", + "source": "openmaptiles", + "source-layer": "transportation", + "minzoom": 13, + "filter": [ + "all", + ["==", "$type", "LineString"], + ["all", ["!has", "service"], ["==", "class", "rail"]] + ], + "layout": {"line-join": "round", "visibility": "visible"}, + "paint": { + "line-color": "#dddddd", + "line-width": {"base": 1.3, "stops": [[16, 3], [20, 7]]} + } + }, + { + "id": "railway_dashline", + "type": "line", + "source": "openmaptiles", + "source-layer": "transportation", + "minzoom": 13, + "filter": [ + "all", + ["==", "$type", "LineString"], + ["all", ["!has", "service"], ["==", "class", "rail"]] + ], + "layout": {"line-join": "round", "visibility": "visible"}, + "paint": { + "line-color": "#fafafa", + "line-dasharray": [3, 3], + "line-width": {"base": 1.3, "stops": [[16, 2], [20, 6]]} + } + }, + { + "id": "highway_motorway_bridge_casing", + "type": "line", + "source": "openmaptiles", + "source-layer": "transportation", + "minzoom": 6, + "filter": [ + "all", + ["==", "$type", "LineString"], + ["all", ["==", "brunnel", "bridge"], ["==", "class", "motorway"]] + ], + "layout": { + "line-cap": "butt", + "line-join": "miter", + "visibility": "visible" + }, + "paint": { + "line-color": "rgb(213, 213, 213)", + "line-dasharray": [2, 0], + "line-opacity": 1, + "line-width": {"base": 1.4, "stops": [[5.8, 0], [6, 5], [20, 45]]} + } + }, + { + "id": "highway_motorway_bridge_inner", + "type": "line", + "source": "openmaptiles", + "source-layer": "transportation", + "minzoom": 6, + "filter": [ + "all", + ["==", "$type", "LineString"], + ["all", ["==", "brunnel", "bridge"], ["==", "class", "motorway"]] + ], + "layout": { + "line-cap": "round", + "line-join": "round", + "visibility": "visible" + }, + "paint": { + "line-color": { + "base": 1, + "stops": [[5.8, "hsla(0, 0%, 85%, 0.53)"], [6, "#fff"]] + }, + "line-width": {"base": 1.4, "stops": [[4, 2], [6, 1.3], [20, 30]]} + } + }, + + { + "id": "highway-name-path", + "type": "symbol", + "source": "openmaptiles", + "source-layer": "transportation_name", + "minzoom": 15.5, + "filter": ["==", "class", "path"], + "layout": { + "symbol-placement": "line", + "text-field": "{name:latin} {name:nonlatin}", + "text-font": ["Noto Sans Regular"], + "text-rotation-alignment": "map", + "text-size": {"base": 1, "stops": [[13, 12], [14, 13]]} + }, + "paint": { + "text-color": "hsl(30, 23%, 62%)", + "text-halo-color": "#f8f4f0", + "text-halo-width": 0.5 + } + }, + { + "id": "highway-name-minor", + "type": "symbol", + "source": "openmaptiles", + "source-layer": "transportation_name", + "minzoom": 15, + "filter": [ + "all", + ["==", "$type", "LineString"], + ["in", "class", "minor", "service", "track"] + ], + "layout": { + "symbol-placement": "line", + "text-field": "{name:latin} {name:nonlatin}", + "text-font": ["Noto Sans Regular"], + "text-rotation-alignment": "map", + "text-size": {"base": 1, "stops": [[13, 12], [14, 13]]}, + "text-allow-overlap": false, + "symbol-spacing": 250, + "text-ignore-placement": false + }, + "paint": { + "text-color": "#765", + "text-halo-blur": 0.5, + "text-halo-width": 1 + } + }, + { + "id": "highway-name-major", + "type": "symbol", + "source": "openmaptiles", + "source-layer": "transportation_name", + "minzoom": 12.2, + "filter": ["in", "class", "primary", "secondary", "tertiary", "trunk"], + "layout": { + "symbol-placement": "line", + "text-field": "{name:latin} {name:nonlatin}", + "text-font": ["Noto Sans Regular"], + "text-rotation-alignment": "map", + "text-size": {"base": 1, "stops": [[13, 12], [14, 13]]} + }, + "paint": { + "text-color": "#765", + "text-halo-blur": 0.5, + "text-halo-width": 1 + } + }, + + + + { + "id": "boundary_state", + "type": "line", + "source": "openmaptiles", + "source-layer": "boundary", + "filter": ["==", "admin_level", 4], + "layout": { + "line-cap": "round", + "line-join": "round", + "visibility": "visible" + }, + "paint": { + "line-blur": 0.4, + "line-color": "rgb(230, 204, 207)", + "line-dasharray": [2, 2], + "line-opacity": 1, + "line-width": {"base": 1.3, "stops": [[3, 1], [22, 15]]} + } + }, + { + "id": "boundary_country_z0-4", + "type": "line", + "source": "openmaptiles", + "source-layer": "boundary", + "maxzoom": 5, + "filter": ["all", ["==", "admin_level", 2], ["!has", "claimed_by"]], + "layout": {"line-cap": "round", "line-join": "round"}, + "paint": { + "line-blur": {"base": 1, "stops": [[0, 0.4], [22, 4]]}, + "line-color": "rgb(230, 204, 207)", + "line-opacity": 1, + "line-width": {"base": 1.1, "stops": [[3, 1], [22, 20]]} + } + }, + { + "id": "boundary_country_z5-", + "type": "line", + "source": "openmaptiles", + "source-layer": "boundary", + "minzoom": 5, + "filter": ["==", "admin_level", 2], + "layout": {"line-cap": "round", "line-join": "round"}, + "paint": { + "line-blur": {"base": 1, "stops": [[0, 0.4], [22, 4]]}, + "line-color": "rgb(230, 204, 207)", + "line-opacity": 1, + "line-width": {"base": 1.1, "stops": [[3, 1], [22, 20]]} + } + }, + { + "id": "place_other", + "type": "symbol", + "source": "openmaptiles", + "source-layer": "place", + "maxzoom": 14, + "filter": [ + "all", + [ + "in", + "class", + "continent", + "hamlet", + "neighbourhood", + "isolated_dwelling" + ], + ["==", "$type", "Point"] + ], + "layout": { + "text-anchor": "center", + "text-field": "{name:latin}\n{name:nonlatin}", + "text-font": ["Metropolis Regular", "Noto Sans Regular"], + "text-justify": "center", + "text-offset": [0.5, 0], + "text-size": 10, + "text-transform": "uppercase", + "visibility": "visible" + }, + "paint": { + "text-color": "rgb(117, 129, 145)", + "text-halo-blur": 1, + "text-halo-color": "rgb(242,243,240)", + "text-halo-width": 1 + } + }, + { + "id": "place_suburb", + "type": "symbol", + "source": "openmaptiles", + "source-layer": "place", + "maxzoom": 15, + "filter": ["all", ["==", "$type", "Point"], ["==", "class", "suburb"]], + "layout": { + "text-anchor": "center", + "text-field": "{name:latin}\n{name:nonlatin}", + "text-font": ["Metropolis Regular", "Noto Sans Regular"], + "text-justify": "center", + "text-offset": [0.5, 0], + "text-size": 10, + "text-transform": "uppercase", + "visibility": "visible" + }, + "paint": { + "text-color": "rgb(117, 129, 145)", + "text-halo-blur": 1, + "text-halo-color": "rgb(242,243,240)", + "text-halo-width": 1 + } + }, + { + "id": "place_village", + "type": "symbol", + "source": "openmaptiles", + "source-layer": "place", + "maxzoom": 14, + "filter": ["all", ["==", "$type", "Point"], ["==", "class", "village"]], + "layout": { + "icon-size": 0.4, + "text-anchor": "left", + "text-field": "{name:latin}\n{name:nonlatin}", + "text-font": ["Metropolis Regular", "Noto Sans Regular"], + "text-justify": "left", + "text-offset": [0.5, 0.2], + "text-size": 10, + "text-transform": "uppercase", + "visibility": "visible" + }, + "paint": { + "icon-opacity": 0.7, + "text-color": "rgb(117, 129, 145)", + "text-halo-blur": 1, + "text-halo-color": "rgb(242,243,240)", + "text-halo-width": 1 + } + }, + { + "id": "place_town", + "type": "symbol", + "source": "openmaptiles", + "source-layer": "place", + "maxzoom": 15, + "filter": ["all", ["==", "$type", "Point"], ["==", "class", "town"]], + "layout": { + "icon-image": {"base": 1, "stops": [[0, "circle-11"], [8, ""]]}, + "icon-size": 0.4, + "text-anchor": {"base": 1, "stops": [[0, "left"], [8, "center"]]}, + "text-field": "{name:latin}\n{name:nonlatin}", + "text-font": ["Metropolis Regular", "Noto Sans Regular"], + "text-justify": "left", + "text-offset": [0.5, 0.2], + "text-size": 10, + "text-transform": "uppercase", + "visibility": "visible" + }, + "paint": { + "icon-opacity": 0.7, + "text-color": "rgb(117, 129, 145)", + "text-halo-blur": 1, + "text-halo-color": "rgb(242,243,240)", + "text-halo-width": 1 + } + }, + { + "id": "place_city", + "type": "symbol", + "source": "openmaptiles", + "source-layer": "place", + "maxzoom": 14, + "filter": [ + "all", + ["==", "$type", "Point"], + ["all", ["!=", "capital", 2], ["==", "class", "city"], [">", "rank", 3]] + ], + "layout": { + "icon-image": {"base": 1, "stops": [[0, "circle-11"], [8, ""]]}, + "icon-size": 0.4, + "text-anchor": {"base": 1, "stops": [[0, "left"], [8, "center"]]}, + "text-field": "{name:latin}\n{name:nonlatin}", + "text-font": ["Metropolis Regular", "Noto Sans Regular"], + "text-justify": "left", + "text-offset": [0.5, 0.2], + "text-size": 10, + "text-transform": "uppercase", + "visibility": "visible" + }, + "paint": { + "icon-opacity": 0.7, + "text-color": "rgb(117, 129, 145)", + "text-halo-blur": 1, + "text-halo-color": "rgb(242,243,240)", + "text-halo-width": 1 + } + }, + { + "id": "place_capital", + "type": "symbol", + "source": "openmaptiles", + "source-layer": "place", + "maxzoom": 12, + "filter": [ + "all", + ["==", "$type", "Point"], + ["all", ["==", "capital", 2], ["==", "class", "city"]] + ], + "layout": { + "icon-image": {"base": 1, "stops": [[0, "star-11"], [8, ""]]}, + "icon-size": 1, + "text-anchor": {"base": 1, "stops": [[0, "left"], [8, "center"]]}, + "text-field": "{name:latin}\n{name:nonlatin}", + "text-font": ["Metropolis Regular", "Noto Sans Regular"], + "text-justify": "left", + "text-offset": [0.5, 0.2], + "text-size": 14, + "text-transform": "uppercase", + "visibility": "visible" + }, + "paint": { + "icon-opacity": 0.7, + "text-color": "rgb(117, 129, 145)", + "text-halo-blur": 1, + "text-halo-color": "rgb(242,243,240)", + "text-halo-width": 1 + } + }, + { + "id": "place_city_large", + "type": "symbol", + "source": "openmaptiles", + "source-layer": "place", + "maxzoom": 12, + "filter": [ + "all", + ["==", "$type", "Point"], + [ + "all", + ["!=", "capital", 2], + ["<=", "rank", 3], + ["==", "class", "city"] + ] + ], + "layout": { + "icon-image": {"base": 1, "stops": [[0, "circle-11"], [8, ""]]}, + "icon-size": 0.4, + "text-anchor": {"base": 1, "stops": [[0, "left"], [8, "center"]]}, + "text-field": "{name:latin}\n{name:nonlatin}", + "text-font": ["Metropolis Regular", "Noto Sans Regular"], + "text-justify": "left", + "text-offset": [0.5, 0.2], + "text-size": 14, + "text-transform": "uppercase", + "visibility": "visible" + }, + "paint": { + "icon-opacity": 0.7, + "text-color": "rgb(117, 129, 145)", + "text-halo-blur": 1, + "text-halo-color": "rgb(242,243,240)", + "text-halo-width": 1 + } + }, + { + "id": "place_state", + "type": "symbol", + "source": "openmaptiles", + "source-layer": "place", + "maxzoom": 12, + "filter": ["all", ["==", "$type", "Point"], ["==", "class", "state"]], + "layout": { + "text-field": "{name:latin}\n{name:nonlatin}", + "text-font": ["Metropolis Regular", "Noto Sans Regular"], + "text-size": 10, + "text-transform": "uppercase", + "visibility": "visible" + }, + "paint": { + "text-color": "rgb(113, 129, 144)", + "text-halo-blur": 1, + "text-halo-color": "rgb(242,243,240)", + "text-halo-width": 1 + } + }, + { + "id": "place_country_other", + "type": "symbol", + "source": "openmaptiles", + "source-layer": "place", + "maxzoom": 8, + "filter": [ + "all", + ["==", "$type", "Point"], + ["==", "class", "country"], + ["!has", "iso_a2"] + ], + "layout": { + "text-field": "{name:latin}", + "text-font": ["Metropolis Light Italic", "Noto Sans Italic"], + "text-size": {"base": 1, "stops": [[0, 9], [6, 11]]}, + "text-transform": "uppercase", + "visibility": "visible" + }, + "paint": { + "text-color": { + "base": 1, + "stops": [[3, "rgb(157,169,177)"], [4, "rgb(153, 153, 153)"]] + }, + "text-halo-color": "rgba(236,236,234,0.7)", + "text-halo-width": 1.4 + } + }, + { + "id": "place_country_minor", + "type": "symbol", + "source": "openmaptiles", + "source-layer": "place", + "maxzoom": 8, + "filter": [ + "all", + ["==", "$type", "Point"], + ["==", "class", "country"], + [">=", "rank", 2], + ["has", "iso_a2"] + ], + "layout": { + "text-field": "{name:latin}", + "text-font": ["Metropolis Regular", "Noto Sans Regular"], + "text-size": {"base": 1, "stops": [[0, 10], [6, 12]]}, + "text-transform": "uppercase", + "visibility": "visible" + }, + "paint": { + "text-color": { + "base": 1, + "stops": [[3, "rgb(157,169,177)"], [4, "rgb(153, 153, 153)"]] + }, + "text-halo-color": "rgba(236,236,234,0.7)", + "text-halo-width": 1.4 + } + }, + { + "id": "place_country_major", + "type": "symbol", + "source": "openmaptiles", + "source-layer": "place", + "maxzoom": 6, + "filter": [ + "all", + ["==", "$type", "Point"], + ["<=", "rank", 1], + ["==", "class", "country"], + ["has", "iso_a2"] + ], + "layout": { + "text-anchor": "center", + "text-field": "{name:latin}", + "text-font": ["Metropolis Regular", "Noto Sans Regular"], + "text-size": {"base": 1.4, "stops": [[0, 10], [3, 12], [4, 14]]}, + "text-transform": "uppercase", + "visibility": "visible" + }, + "paint": { + "text-color": { + "base": 1, + "stops": [[3, "rgb(157,169,177)"], [4, "rgb(153, 153, 153)"]] + }, + "text-halo-color": "rgba(236,236,234,0.7)", + "text-halo-width": 1.4 + } + } + ], + "id": "positron" +} diff --git a/tile-generator/layers/obs_roads/layer.sql b/tile-generator/layers/obs_roads/layer.sql index 9a1fd93..7129b85 100644 --- a/tile-generator/layers/obs_roads/layer.sql +++ b/tile-generator/layers/obs_roads/layer.sql @@ -1,15 +1,33 @@ CREATE OR REPLACE FUNCTION layer_obs_roads(bbox geometry, zoom_level int) -RETURNS TABLE(way_id bigint, geometry geometry, distance_overtaker_mean float, direction int) AS $$ +RETURNS TABLE( + way_id bigint, + geometry geometry, + distance_overtaker_mean float, + distance_overtaker_min float, + distance_overtaker_max float, + distance_overtaker_median float, + distance_overtaker_array float[], + overtaking_event_count int, + direction int, + offset_direction int +) AS $$ SELECT road.way_id::bigint as way_id, road.geometry as geometry, avg(distance_overtaker) as distance_overtaker_mean, - r.dir as direction + min(distance_overtaker) as distance_overtaker_min, + max(distance_overtaker) as distance_overtaker_max, + PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY distance_overtaker) as distance_overtaker_median, + array_agg(distance_overtaker) as distance_overtaker_array, + count(overtaking_event.id)::int as distance_overtaker_count, + r.dir as direction, + case when road.directionality = 0 then r.dir else 0 end as offset_direction FROM road - JOIN overtaking_event on road.way_id = overtaking_event.way_id - JOIN (VALUES (1, TRUE), (-1, FALSE)) AS r(dir, rev) ON overtaking_event.direction_reversed = r.rev + FULL OUTER JOIN (VALUES (1, TRUE), (-1, FALSE)) AS r(dir, rev) ON (road.directionality = 0 or road.directionality = r.dir) + FULL OUTER JOIN overtaking_event ON (road.way_id = overtaking_event.way_id and overtaking_event.direction_reversed = r.rev) + -- WHERE road.name = 'Schlierbergstraße' WHERE road.geometry && bbox - GROUP BY road.way_id, road.geometry, direction; + GROUP BY road.way_id, road.geometry, road.directionality, direction; $$ LANGUAGE SQL IMMUTABLE; diff --git a/tile-generator/layers/obs_roads/obs_roads.yaml b/tile-generator/layers/obs_roads/obs_roads.yaml index 6020714..27ecf73 100644 --- a/tile-generator/layers/obs_roads/obs_roads.yaml +++ b/tile-generator/layers/obs_roads/obs_roads.yaml @@ -4,12 +4,24 @@ layer: Road segment statistics for OBS events buffer_size: 4 fields: + distance_overtaker_min: | + Overtaker minimum distance in meters. + distance_overtaker_max: | + Overtaker maximum distance in meters. distance_overtaker_mean: | Overtaker mean distance in meters. + distance_overtaker_median: | + Overtaker median distance in meters. + distance_overtaker_array: | + All overtaker distance values in meters. + overtaking_event_count: | + Number of overtaking events. direction: | Contains -1 for events while going along the way backwards, 1 for forwards. Each road is emitted twice, if it has data for both directions, even if it is oneway. + offset_direction: | + Factor for offset to shift the line to the driving side. One of -1, 0, 1. defaults: srs: EPSG:3785 datasource: @@ -17,7 +29,21 @@ layer: geometry_field: geometry key_field: way_id key_field_as_attribute: no - query: (SELECT way_id, geometry, distance_overtaker_mean, direction FROM layer_obs_roads(!bbox!, z(!scale_denominator!))) AS t + query: | + ( + SELECT + way_id, + geometry, + distance_overtaker_mean, + distance_overtaker_min, + distance_overtaker_max, + distance_overtaker_median, + distance_overtaker_array, + overtaking_event_count, + direction, + offset_direction + FROM layer_obs_roads(!bbox!, z(!scale_denominator!)) + ) AS t schema: - ./layer.sql