From 66dd84982c314b69e31b7022038355d5486056da Mon Sep 17 00:00:00 2001 From: gluap Date: Mon, 2 May 2022 22:00:17 +0200 Subject: [PATCH 1/8] Implement difference between urban and rural for events and road segments. --- .../versions/b22108ab2ffb_add_event_zone.py | 25 ++++++++++ api/obs/api/db.py | 1 + api/obs/api/process.py | 3 +- api/obs/api/routes/exports.py | 3 ++ api/obs/api/routes/mapdetails.py | 1 + frontend/src/mapstyles/index.js | 50 +++++++++++++++++-- frontend/src/pages/MapPage/LayerSidebar.tsx | 10 +++- frontend/src/pages/MapPage/RoadInfo.tsx | 7 +-- frontend/src/pages/MapPage/index.tsx | 4 +- frontend/webpack.config.js | 1 + tile-generator/layers/obs_events/layer.sql | 3 +- .../layers/obs_events/obs_events.yaml | 4 +- tile-generator/layers/obs_roads/layer.sql | 4 +- .../layers/obs_roads/obs_roads.yaml | 3 ++ 14 files changed, 104 insertions(+), 15 deletions(-) create mode 100644 api/migrations/versions/b22108ab2ffb_add_event_zone.py diff --git a/api/migrations/versions/b22108ab2ffb_add_event_zone.py b/api/migrations/versions/b22108ab2ffb_add_event_zone.py new file mode 100644 index 0000000..1fd53e9 --- /dev/null +++ b/api/migrations/versions/b22108ab2ffb_add_event_zone.py @@ -0,0 +1,25 @@ +"""add event zone + +Revision ID: b22108ab2ffb +Revises: a9627f63fbed +Create Date: 2022-04-30 19:06:11.472579 + +""" +from alembic import op +import sqlalchemy as sa + +from migrations.utils import dbtype + +# revision identifiers, used by Alembic. +revision = 'b22108ab2ffb' +down_revision = 'a9627f63fbed' +branch_labels = None +depends_on = None + + +def upgrade(): + op.add_column("overtaking_event", sa.Column("zone", dbtype("zone_type")), ) + + +def downgrade(): + op.drop_column("overtaking_event", "zone") diff --git a/api/obs/api/db.py b/api/obs/api/db.py index 00f849d..40b4045 100644 --- a/api/obs/api/db.py +++ b/api/obs/api/db.py @@ -124,6 +124,7 @@ class OvertakingEvent(Base): distance_stationary = Column(Float) course = Column(Float) speed = Column(Float) + zone = Column(ZoneType) def __repr__(self): return f"" diff --git a/api/obs/api/process.py b/api/obs/api/process.py index 6fc2c5e..90266e2 100644 --- a/api/obs/api/process.py +++ b/api/obs/api/process.py @@ -27,7 +27,7 @@ from obs.face.filter import ( from obs.face.osm import DataSource, DatabaseTileSource, OverpassTileSource -from obs.api.db import OvertakingEvent, RoadUsage, Track, make_session +from obs.api.db import OvertakingEvent, RoadUsage, Track, make_session, ZoneType from obs.api.app import app log = logging.getLogger(__name__) @@ -293,6 +293,7 @@ async def import_overtaking_events(session, track, overtaking_events): distance_stationary=m["distance_stationary"], course=m["course"], speed=m["speed"], + zone=m["OSM_zone"] if ('OSM_zone' in m and m['OSM_zone'] is not None) else "urban" ) session.add_all(event_models.values()) diff --git a/api/obs/api/routes/exports.py b/api/obs/api/routes/exports.py index 90218fd..a7bf668 100644 --- a/api/obs/api/routes/exports.py +++ b/api/obs/api/routes/exports.py @@ -77,6 +77,7 @@ async def export_events(req): writer.field("direction", "N", decimal=0) writer.field("course", "N", decimal=4) writer.field("speed", "N", decimal=4) + writer.field("zone", "N", decimal=4) async for event in events: writer.point(event.longitude, event.latitude) @@ -87,6 +88,7 @@ async def export_events(req): way_id=event.way_id, course=event.course, speed=event.speed, + zone=event.zone # "time"=event.time, ) @@ -107,6 +109,7 @@ async def export_events(req): "course": event.course, "speed": event.speed, "time": event.time, + "zone": event.zone }, } ) diff --git a/api/obs/api/routes/mapdetails.py b/api/obs/api/routes/mapdetails.py index 51aa7df..5b0eba3 100644 --- a/api/obs/api/routes/mapdetails.py +++ b/api/obs/api/routes/mapdetails.py @@ -112,6 +112,7 @@ async def mapdetails_road(req): "histogram": { "bins": [None if math.isinf(b) else b for b in bins.tolist()], "counts": hist.tolist(), + "zone": road.zone }, "values": list(map(rounder, arr.tolist())), } diff --git a/frontend/src/mapstyles/index.js b/frontend/src/mapstyles/index.js index 56a8449..5d90dc0 100644 --- a/frontend/src/mapstyles/index.js +++ b/frontend/src/mapstyles/index.js @@ -47,24 +47,64 @@ export function colorByCount(attribute = 'event_count', maxCount, colormap = vir return colormapToScale(colormap, ['case', ['to-boolean', ['get', attribute]], ['get', attribute], 0], 0, maxCount) } -export function colorByDistance(attribute = 'distance_overtaker_mean', fallback = '#ABC') { +var steps = {'rural': [1.6,1.8,2.0,2.2], + 'urban': [1.1,1.3,1.5,1.7]} + +export function borderByZone() { + return ["match", ['get', 'zone'], + "rural", "brown", + "urban", "olive", + "purple" + ] +} + +export function colorByDistance(attribute = 'distance_overtaker_mean', fallback = '#ABC', zone='urban') { + return [ 'case', ['!', ['to-boolean', ['get', attribute]]], fallback, + ["match", ['get', 'zone'], "rural", [ 'step', ['get', attribute], 'rgba(150, 0, 0, 1)', - 1.1, + steps['rural'][0], 'rgba(255, 0, 0, 1)', - 1.3, + steps['rural'][1], 'rgba(255, 220, 0, 1)', - 1.5, + steps['rural'][2], 'rgba(67, 200, 0, 1)', - 1.7, + steps['rural'][3], + 'rgba(67, 150, 0, 1)', + ], "urban", + [ + 'step', + ['get', attribute], + 'rgba(150, 0, 0, 1)', + steps['urban'][0], + 'rgba(255, 0, 0, 1)', + steps['urban'][1], + 'rgba(255, 220, 0, 1)', + steps['urban'][2], + 'rgba(67, 200, 0, 1)', + steps['urban'][3], 'rgba(67, 150, 0, 1)', ], + [ + 'step', + ['get', attribute], + 'rgba(150, 0, 0, 1)', + steps['urban'][0], + 'rgba(255, 0, 0, 1)', + steps['urban'][1], + 'rgba(255, 220, 0, 1)', + steps['urban'][2], + 'rgba(67, 200, 0, 1)', + steps['urban'][3], + 'rgba(67, 150, 0, 1)', + ] + ] ] } diff --git a/frontend/src/pages/MapPage/LayerSidebar.tsx b/frontend/src/pages/MapPage/LayerSidebar.tsx index 9e38026..d0f7a4d 100644 --- a/frontend/src/pages/MapPage/LayerSidebar.tsx +++ b/frontend/src/pages/MapPage/LayerSidebar.tsx @@ -98,7 +98,10 @@ function LayerSidebar({ ) : ( - + Urban + + Rural + )} @@ -120,7 +123,10 @@ function LayerSidebar({ {showEvents && ( <> - + Urban + + Rural + )} diff --git a/frontend/src/pages/MapPage/RoadInfo.tsx b/frontend/src/pages/MapPage/RoadInfo.tsx index 5d2758e..35fdc0e 100644 --- a/frontend/src/pages/MapPage/RoadInfo.tsx +++ b/frontend/src/pages/MapPage/RoadInfo.tsx @@ -9,7 +9,7 @@ import {Chart} from 'components' import {pairwise} from 'utils' import api from 'api' -import {colorByDistance} from 'mapstyles' +import {colorByDistance, borderByZone} from 'mapstyles' import styles from './styles.module.less' @@ -75,14 +75,15 @@ function RoadStatsTable({data}) { ) } -function HistogramChart({bins, counts}) { +function HistogramChart({bins, counts, zone}) { const diff = bins[1] - bins[0] + const colortype = zone=="rural" ? 3:5; const data = _.zip( bins.slice(0, bins.length - 1).map((v) => v + diff / 2), counts ).map((value) => ({ value, - itemStyle: {color: selectFromColorMap(colorByDistance()[3].slice(2), value[0])}, + itemStyle: {color: selectFromColorMap(colorByDistance()[3][colortype].slice(2), value[0]),}, })) return ( diff --git a/frontend/src/pages/MapPage/index.tsx b/frontend/src/pages/MapPage/index.tsx index 9d30847..3579afa 100644 --- a/frontend/src/pages/MapPage/index.tsx +++ b/frontend/src/pages/MapPage/index.tsx @@ -6,7 +6,7 @@ import produce from 'immer' import {Page, Map} from 'components' import {useConfig} from 'config' -import {colorByDistance, colorByCount, reds} from 'mapstyles' +import {colorByDistance, colorByCount, borderByZone, reds} from 'mapstyles' import {useMapConfig} from 'reducers/mapConfig' import RoadInfo from './RoadInfo' @@ -67,6 +67,8 @@ const getEventsLayer = () => ({ paint: { 'circle-radius': ['interpolate', ['linear'], ['zoom'], 14, 3, 17, 8], 'circle-color': colorByDistance('distance_overtaker'), + 'circle-stroke-color': borderByZone(), + 'circle-stroke-width':['interpolate', ['linear'], ['zoom'], 14, 1, 17, 4], }, minzoom: 11, }) diff --git a/frontend/webpack.config.js b/frontend/webpack.config.js index 0930c34..3206622 100644 --- a/frontend/webpack.config.js +++ b/frontend/webpack.config.js @@ -163,6 +163,7 @@ module.exports = function (webpackEnv) { '/config.json': apiUrl, '/api': apiUrl, '/login': apiUrl, + '/tiles': apiUrl }, }, module: { diff --git a/tile-generator/layers/obs_events/layer.sql b/tile-generator/layers/obs_events/layer.sql index c57874a..94a9792 100644 --- a/tile-generator/layers/obs_events/layer.sql +++ b/tile-generator/layers/obs_events/layer.sql @@ -1,5 +1,5 @@ CREATE OR REPLACE FUNCTION layer_obs_events(bbox geometry, zoom_level int) -RETURNS TABLE(event_id bigint, geometry geometry, distance_overtaker float, distance_stationary float, direction int, course float, speed float, way_id bigint) AS $$ +RETURNS TABLE(event_id bigint, geometry geometry, distance_overtaker float, distance_stationary float, direction int, course float, speed float, zone zone_type, way_id bigint) AS $$ SELECT id::bigint as event_id, @@ -9,6 +9,7 @@ RETURNS TABLE(event_id bigint, geometry geometry, distance_overtaker float, dist (case when direction_reversed then -1 else 1 end)::int as direction, course, speed, + zone, way_id::bigint as way_id FROM overtaking_event WHERE ST_Transform(overtaking_event.geometry, 3857) && bbox; diff --git a/tile-generator/layers/obs_events/obs_events.yaml b/tile-generator/layers/obs_events/obs_events.yaml index 4eb82d2..be11e7c 100644 --- a/tile-generator/layers/obs_events/obs_events.yaml +++ b/tile-generator/layers/obs_events/obs_events.yaml @@ -16,6 +16,8 @@ layer: Direction of travel, as reported by GPS, in degree from North. speed: | Speed of travel, as reported by GPS, in meters per second (?). + zone: | + rural or urban defaults: srs: EPSG:3785 datasource: @@ -23,7 +25,7 @@ layer: geometry_field: geometry key_field: event_id key_field_as_attribute: no - query: (SELECT event_id, geometry, distance_overtaker, distance_stationary, direction, course, speed, way_id FROM layer_obs_events(!bbox!, z(!scale_denominator!))) AS t + query: (SELECT event_id, geometry, distance_overtaker, distance_stationary, direction, course, speed, zone, way_id FROM layer_obs_events(!bbox!, z(!scale_denominator!))) AS t schema: - ./layer.sql diff --git a/tile-generator/layers/obs_roads/layer.sql b/tile-generator/layers/obs_roads/layer.sql index 92c4f2f..53d8dd3 100644 --- a/tile-generator/layers/obs_roads/layer.sql +++ b/tile-generator/layers/obs_roads/layer.sql @@ -12,6 +12,7 @@ RETURNS TABLE( overtaking_event_count int, usage_count bigint, direction int, + zone zone_type, offset_direction int ) AS $$ @@ -27,12 +28,13 @@ RETURNS TABLE( (select count(id) from road_usage where road_usage.way_id = road.way_id and (road.directionality != 0 or road_usage.direction_reversed = r.rev)) as usage_count, r.dir as direction, + road.zone::zone_type as zone, case when road.directionality = 0 then r.dir else 0 end as offset_direction FROM road LEFT JOIN (VALUES (-1, TRUE), (1, FALSE), (0, FALSE)) AS r(dir, rev) ON (abs(r.dir) != road.directionality) FULL OUTER JOIN overtaking_event ON (road.way_id = overtaking_event.way_id and (road.directionality != 0 or overtaking_event.direction_reversed = r.rev)) -- WHERE road.name = 'Merzhauser Straße' WHERE road.geometry && bbox - GROUP BY road.name, road.way_id, road.geometry, road.directionality, r.dir, r.rev; + GROUP BY road.name, road.way_id, road.geometry, road.directionality, r.dir, r.rev, road.zone; $$ LANGUAGE SQL IMMUTABLE; diff --git a/tile-generator/layers/obs_roads/obs_roads.yaml b/tile-generator/layers/obs_roads/obs_roads.yaml index b246eb4..3b0e918 100644 --- a/tile-generator/layers/obs_roads/obs_roads.yaml +++ b/tile-generator/layers/obs_roads/obs_roads.yaml @@ -22,6 +22,8 @@ layer: 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. + zone: | + ural or urban offset_direction: | Factor for offset to shift the line to the driving side. One of -1, 0, 1. defaults: @@ -44,6 +46,7 @@ layer: overtaking_event_count, usage_count, direction, + zone, offset_direction FROM layer_obs_roads(!bbox!, z(!scale_denominator!)) ) AS t From 8ba5d8e3adaf9704d8c818b5ffdfc36758292500 Mon Sep 17 00:00:00 2001 From: gluap Date: Thu, 5 May 2022 23:16:38 +0200 Subject: [PATCH 2/8] Take the zone from road, not event as suggested by opatut. --- .../versions/b22108ab2ffb_add_event_zone.py | 25 ------------------- api/obs/api/db.py | 1 - api/obs/api/process.py | 3 +-- api/obs/api/routes/exports.py | 3 --- tile-generator/layers/obs_events/layer.sql | 5 ++-- 5 files changed, 4 insertions(+), 33 deletions(-) delete mode 100644 api/migrations/versions/b22108ab2ffb_add_event_zone.py diff --git a/api/migrations/versions/b22108ab2ffb_add_event_zone.py b/api/migrations/versions/b22108ab2ffb_add_event_zone.py deleted file mode 100644 index 1fd53e9..0000000 --- a/api/migrations/versions/b22108ab2ffb_add_event_zone.py +++ /dev/null @@ -1,25 +0,0 @@ -"""add event zone - -Revision ID: b22108ab2ffb -Revises: a9627f63fbed -Create Date: 2022-04-30 19:06:11.472579 - -""" -from alembic import op -import sqlalchemy as sa - -from migrations.utils import dbtype - -# revision identifiers, used by Alembic. -revision = 'b22108ab2ffb' -down_revision = 'a9627f63fbed' -branch_labels = None -depends_on = None - - -def upgrade(): - op.add_column("overtaking_event", sa.Column("zone", dbtype("zone_type")), ) - - -def downgrade(): - op.drop_column("overtaking_event", "zone") diff --git a/api/obs/api/db.py b/api/obs/api/db.py index 40b4045..00f849d 100644 --- a/api/obs/api/db.py +++ b/api/obs/api/db.py @@ -124,7 +124,6 @@ class OvertakingEvent(Base): distance_stationary = Column(Float) course = Column(Float) speed = Column(Float) - zone = Column(ZoneType) def __repr__(self): return f"" diff --git a/api/obs/api/process.py b/api/obs/api/process.py index 90266e2..6fc2c5e 100644 --- a/api/obs/api/process.py +++ b/api/obs/api/process.py @@ -27,7 +27,7 @@ from obs.face.filter import ( from obs.face.osm import DataSource, DatabaseTileSource, OverpassTileSource -from obs.api.db import OvertakingEvent, RoadUsage, Track, make_session, ZoneType +from obs.api.db import OvertakingEvent, RoadUsage, Track, make_session from obs.api.app import app log = logging.getLogger(__name__) @@ -293,7 +293,6 @@ async def import_overtaking_events(session, track, overtaking_events): distance_stationary=m["distance_stationary"], course=m["course"], speed=m["speed"], - zone=m["OSM_zone"] if ('OSM_zone' in m and m['OSM_zone'] is not None) else "urban" ) session.add_all(event_models.values()) diff --git a/api/obs/api/routes/exports.py b/api/obs/api/routes/exports.py index a7bf668..90218fd 100644 --- a/api/obs/api/routes/exports.py +++ b/api/obs/api/routes/exports.py @@ -77,7 +77,6 @@ async def export_events(req): writer.field("direction", "N", decimal=0) writer.field("course", "N", decimal=4) writer.field("speed", "N", decimal=4) - writer.field("zone", "N", decimal=4) async for event in events: writer.point(event.longitude, event.latitude) @@ -88,7 +87,6 @@ async def export_events(req): way_id=event.way_id, course=event.course, speed=event.speed, - zone=event.zone # "time"=event.time, ) @@ -109,7 +107,6 @@ async def export_events(req): "course": event.course, "speed": event.speed, "time": event.time, - "zone": event.zone }, } ) diff --git a/tile-generator/layers/obs_events/layer.sql b/tile-generator/layers/obs_events/layer.sql index 94a9792..7ae714f 100644 --- a/tile-generator/layers/obs_events/layer.sql +++ b/tile-generator/layers/obs_events/layer.sql @@ -9,9 +9,10 @@ RETURNS TABLE(event_id bigint, geometry geometry, distance_overtaker float, dist (case when direction_reversed then -1 else 1 end)::int as direction, course, speed, - zone, - way_id::bigint as way_id + CASE WHEN road.zone IS NULL THEN 'urban' else road.zone END as zone, + overtaking_event.way_id::bigint as way_id FROM overtaking_event + FULL OUTER JOIN road ON (road.way_id = overtaking_event.way_id) WHERE ST_Transform(overtaking_event.geometry, 3857) && bbox; $$ LANGUAGE SQL IMMUTABLE; From f36e38b10bcf96a844650dadc531f3e4a97778cf Mon Sep 17 00:00:00 2001 From: gluap Date: Sat, 21 May 2022 21:09:54 +0200 Subject: [PATCH 3/8] some more lua logic to guess rurality. --- roads_import.lua | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/roads_import.lua b/roads_import.lua index c314d50..4d7ab92 100644 --- a/roads_import.lua +++ b/roads_import.lua @@ -81,13 +81,26 @@ function osm2pgsql.process_way(object) zone = "urban" elseif string.match(zone, "motorway") then zone = "motorway" - elseif contains(URBAN_TYPES, tags.highway) then + elseif string.match(zone, "30") then + zone = "urban" + else + zone = "urban" + end + end + if not tags["zone:traffic"] then + if contains(URBAN_TYPES, tags.highway) then zone = "urban" elseif contains(MOTORWAY_TYPES, tags.highway) then zone = "motorway" + elseif (tags.maxspeed) and (tonumber(string.match(tags.maxspeed, '[%d]*'))) and tonumber(string.match(tags.maxspeed, '[%d]*')) > 60 then + zone = "rural" + elseif tags['source:maxspeed'] and string.match(tags['source:maxspeed'], "rural") then + zone = "rural" + elseif tags['source:maxspeed'] and string.match(tags['source:maxspeed'], "urban") then + zone = "urban" else -- we can't figure it out - zone = nil + zone = "urban" end end From 225a238e771c275ed442e4e76065886be9efd086 Mon Sep 17 00:00:00 2001 From: gluap Date: Fri, 24 Jun 2022 18:51:52 +0200 Subject: [PATCH 4/8] more lua ifery to detect rural streets --- roads_import.lua | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/roads_import.lua b/roads_import.lua index 4d7ab92..2c1c45b 100644 --- a/roads_import.lua +++ b/roads_import.lua @@ -61,6 +61,8 @@ local roads = osm2pgsql.define_way_table('road', { { column = 'oneway', type = 'bool' }, }) +local minspeed_rural = 60 + function osm2pgsql.process_way(object) if object.tags.highway and contains(HIGHWAY_TYPES, object.tags.highway) then local tags = object.tags @@ -92,7 +94,11 @@ function osm2pgsql.process_way(object) zone = "urban" elseif contains(MOTORWAY_TYPES, tags.highway) then zone = "motorway" - elseif (tags.maxspeed) and (tonumber(string.match(tags.maxspeed, '[%d]*'))) and tonumber(string.match(tags.maxspeed, '[%d]*')) > 60 then + elseif (tags.maxspeed) and (tonumber(string.match(tags.maxspeed, '[%d]*'))) and tonumber(string.match(tags.maxspeed, '[%d]*')) > minspeed_rural then + zone = "rural" + elseif (tags["maxspeed:forward"]) and (tonumber(string.match(tags["maxspeed:forward"], '[%d]*'))) and tonumber(string.match(tags["maxspeed:forward"], '[%d]*')) > minspeed_rural then + zone = "rural" + elseif (tags["maxspeed:backward"]) and (tonumber(string.match(tags["maxspeed:backward"], '[%d]*'))) and tonumber(string.match(tags["maxspeed:backward"], '[%d]*')) > minspeed_rural then zone = "rural" elseif tags['source:maxspeed'] and string.match(tags['source:maxspeed'], "rural") then zone = "rural" From afc801aefc0e936ae5a6b4f9dcc1a5bd4fa9b9e8 Mon Sep 17 00:00:00 2001 From: gluap Date: Fri, 24 Jun 2022 18:52:59 +0200 Subject: [PATCH 5/8] save current state. --- frontend/src/mapstyles/index.js | 4 ++-- frontend/src/pages/MapPage/LayerSidebar.tsx | 14 +++++++++++--- frontend/src/pages/MapPage/RoadInfo.tsx | 2 +- frontend/src/pages/MapPage/index.tsx | 4 ++-- frontend/src/reducers/mapConfig.ts | 3 ++- 5 files changed, 18 insertions(+), 9 deletions(-) diff --git a/frontend/src/mapstyles/index.js b/frontend/src/mapstyles/index.js index 5d90dc0..e82106b 100644 --- a/frontend/src/mapstyles/index.js +++ b/frontend/src/mapstyles/index.js @@ -52,8 +52,8 @@ var steps = {'rural': [1.6,1.8,2.0,2.2], export function borderByZone() { return ["match", ['get', 'zone'], - "rural", "brown", - "urban", "olive", + "rural", "cyan", + "urban", "blue", "purple" ] } diff --git a/frontend/src/pages/MapPage/LayerSidebar.tsx b/frontend/src/pages/MapPage/LayerSidebar.tsx index d0f7a4d..b3ccc91 100644 --- a/frontend/src/pages/MapPage/LayerSidebar.tsx +++ b/frontend/src/pages/MapPage/LayerSidebar.tsx @@ -1,7 +1,7 @@ import React from 'react' import _ from 'lodash' import {connect} from 'react-redux' -import {List, Select, Input, Divider, Checkbox, Header} from 'semantic-ui-react' +import {List, Select, Input, Divider, Label, Checkbox, Header} from 'semantic-ui-react' import { MapConfig, @@ -23,6 +23,7 @@ const ROAD_ATTRIBUTE_OPTIONS = [ {value: 'distance_overtaker_median', key: 'distance_overtaker_median', text: 'Overtaker distance median'}, {value: 'overtaking_event_count', key: 'overtaking_event_count', text: 'Event count'}, {value: 'usage_count', key: 'usage_count', text: 'Usage count'}, + {value: 'zone', key: 'zone', text: 'Overtaking distance zone'} ] function LayerSidebar({ @@ -96,6 +97,13 @@ function LayerSidebar({ ) : + attribute.endsWith('zone') ? ( + <> + + + + + ) : ( Urban @@ -123,9 +131,9 @@ function LayerSidebar({ {showEvents && ( <> - Urban + Urban - Rural + Rural diff --git a/frontend/src/pages/MapPage/RoadInfo.tsx b/frontend/src/pages/MapPage/RoadInfo.tsx index 35fdc0e..871279a 100644 --- a/frontend/src/pages/MapPage/RoadInfo.tsx +++ b/frontend/src/pages/MapPage/RoadInfo.tsx @@ -34,7 +34,7 @@ const LABELS = { max: 'Maximum', mean: 'Average', } -const ZONE_COLORS = {urban: 'olive', rural: 'brown', motorway: 'purple'} +const ZONE_COLORS = {urban: 'blue', rural: 'cyan', motorway: 'purple'} const CARDINAL_DIRECTIONS = ['north', 'north-east', 'east', 'south-east', 'south', 'south-west', 'west', 'north-west'] const getCardinalDirection = (bearing) => bearing == null diff --git a/frontend/src/pages/MapPage/index.tsx b/frontend/src/pages/MapPage/index.tsx index 3579afa..bf597e0 100644 --- a/frontend/src/pages/MapPage/index.tsx +++ b/frontend/src/pages/MapPage/index.tsx @@ -54,6 +54,8 @@ const getRoadsLayer = (colorAttribute, maxCount) => ? colorByDistance(colorAttribute) : colorAttribute.endsWith('_count') ? colorByCount(colorAttribute, maxCount) + : colorAttribute.endsWith('zone') + ? borderByZone() : '#DDD' draft.paint['line-opacity'][3] = 12 draft.paint['line-opacity'][5] = 13 @@ -67,8 +69,6 @@ const getEventsLayer = () => ({ paint: { 'circle-radius': ['interpolate', ['linear'], ['zoom'], 14, 3, 17, 8], 'circle-color': colorByDistance('distance_overtaker'), - 'circle-stroke-color': borderByZone(), - 'circle-stroke-width':['interpolate', ['linear'], ['zoom'], 14, 1, 17, 4], }, minzoom: 11, }) diff --git a/frontend/src/reducers/mapConfig.ts b/frontend/src/reducers/mapConfig.ts index f0140cb..e7c14cf 100644 --- a/frontend/src/reducers/mapConfig.ts +++ b/frontend/src/reducers/mapConfig.ts @@ -11,7 +11,8 @@ type RoadAttribute = | "distance_overtaker_max" | "distance_overtaker_median" | "overtaking_event_count" - | "usage_count"; + | "usage_count" + | "zone"; export type MapConfig = { baseMap: { From a11a3c4b8ce899c398408ee469d16ac1ad762ed2 Mon Sep 17 00:00:00 2001 From: gluap Date: Mon, 25 Jul 2022 18:02:09 +0200 Subject: [PATCH 6/8] make color change active --- frontend/src/mapstyles/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/mapstyles/index.js b/frontend/src/mapstyles/index.js index 5d90dc0..e82106b 100644 --- a/frontend/src/mapstyles/index.js +++ b/frontend/src/mapstyles/index.js @@ -52,8 +52,8 @@ var steps = {'rural': [1.6,1.8,2.0,2.2], export function borderByZone() { return ["match", ['get', 'zone'], - "rural", "brown", - "urban", "olive", + "rural", "cyan", + "urban", "blue", "purple" ] } From 76b1b41b4b13d252484457f6241577d32cf3b188 Mon Sep 17 00:00:00 2001 From: Paul Bienkowski Date: Mon, 25 Jul 2022 22:24:31 +0200 Subject: [PATCH 7/8] derive logic for "include roads without data" from selected attribute --- frontend/src/mapstyles/index.js | 11 +++++++++-- frontend/src/pages/MapPage/index.tsx | 18 ++++++++++-------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/frontend/src/mapstyles/index.js b/frontend/src/mapstyles/index.js index e82106b..7dcfa1f 100644 --- a/frontend/src/mapstyles/index.js +++ b/frontend/src/mapstyles/index.js @@ -44,12 +44,19 @@ export const reds = [ ] export function colorByCount(attribute = 'event_count', maxCount, colormap = viridis) { - return colormapToScale(colormap, ['case', ['to-boolean', ['get', attribute]], ['get', attribute], 0], 0, maxCount) + return colormapToScale(colormap, ['case', isValidAttribute(attribute), ['get', attribute], 0], 0, maxCount) } var steps = {'rural': [1.6,1.8,2.0,2.2], 'urban': [1.1,1.3,1.5,1.7]} +export function isValidAttribute(attribute) { + if (attribute.endsWith('zone')) { + return ['in', ['get', attribute], ['literal', ['rural', 'urban']]] + } + return ['to-boolean', ['get', attribute]] +} + export function borderByZone() { return ["match", ['get', 'zone'], "rural", "cyan", @@ -62,7 +69,7 @@ export function colorByDistance(attribute = 'distance_overtaker_mean', fallback return [ 'case', - ['!', ['to-boolean', ['get', attribute]]], + ['!', isValidAttribute(attribute)], fallback, ["match", ['get', 'zone'], "rural", [ diff --git a/frontend/src/pages/MapPage/index.tsx b/frontend/src/pages/MapPage/index.tsx index bf597e0..a3196dd 100644 --- a/frontend/src/pages/MapPage/index.tsx +++ b/frontend/src/pages/MapPage/index.tsx @@ -6,7 +6,7 @@ import produce from 'immer' import {Page, Map} from 'components' import {useConfig} from 'config' -import {colorByDistance, colorByCount, borderByZone, reds} from 'mapstyles' +import {colorByDistance, colorByCount, borderByZone, reds, isValidAttribute} from 'mapstyles' import {useMapConfig} from 'reducers/mapConfig' import RoadInfo from './RoadInfo' @@ -40,15 +40,16 @@ const untaggedRoadsLayer = { minzoom: 12, } +const getUntaggedRoadsLayer = (colorAttribute, maxCount) => + produce(untaggedRoadsLayer, (draft) => { + draft.filter = ['!', isValidAttribute(colorAttribute)] + }) + + const getRoadsLayer = (colorAttribute, maxCount) => produce(untaggedRoadsLayer, (draft) => { draft.id = 'obs_roads_normal' - if (colorAttribute.endsWith('_count')) { - // delete draft.filter - draft.filter = ['to-boolean', ['get', colorAttribute]] - } else { - draft.filter = draft.filter[1] // remove '!' - } + draft.filter = isValidAttribute(colorAttribute) draft.paint['line-width'][6] = 6 // scale bigger on zoom draft.paint['line-color'] = colorAttribute.startsWith('distance_') ? colorByDistance(colorAttribute) @@ -130,8 +131,9 @@ export default function MapPage() { const layers = [] + const untaggedRoadsLayerCustom = useMemo(() => getUntaggedRoadsLayer(attribute), [attribute]) if (mapConfig.obsRoads.show && mapConfig.obsRoads.showUntagged) { - layers.push(untaggedRoadsLayer) + layers.push(untaggedRoadsLayerCustom) } const roadsLayer = useMemo(() => getRoadsLayer(attribute, maxCount), [attribute, maxCount]) From 617011c528e15082fea29946bbfec350255a49a9 Mon Sep 17 00:00:00 2001 From: Paul Bienkowski Date: Mon, 25 Jul 2022 22:24:41 +0200 Subject: [PATCH 8/8] make headers in sidebar pretty, and remove colors --- frontend/src/pages/MapPage/LayerSidebar.tsx | 22 +++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/frontend/src/pages/MapPage/LayerSidebar.tsx b/frontend/src/pages/MapPage/LayerSidebar.tsx index b3ccc91..46167b2 100644 --- a/frontend/src/pages/MapPage/LayerSidebar.tsx +++ b/frontend/src/pages/MapPage/LayerSidebar.tsx @@ -105,12 +105,16 @@ function LayerSidebar({ ) : ( - - Urban - - Rural - - + <> + + Urban + + + + Rural + + + )} )} @@ -131,9 +135,11 @@ function LayerSidebar({ {showEvents && ( <> - Urban + Urban - Rural + + + Rural