Merge pull request #242 from openbikesensor/rural_urban
Implement difference between urban and rural for events and roads
This commit is contained in:
commit
2755d6b2b5
|
@ -112,6 +112,7 @@ async def mapdetails_road(req):
|
||||||
"histogram": {
|
"histogram": {
|
||||||
"bins": [None if math.isinf(b) else b for b in bins.tolist()],
|
"bins": [None if math.isinf(b) else b for b in bins.tolist()],
|
||||||
"counts": hist.tolist(),
|
"counts": hist.tolist(),
|
||||||
|
"zone": road.zone
|
||||||
},
|
},
|
||||||
"values": list(map(rounder, arr.tolist())),
|
"values": list(map(rounder, arr.tolist())),
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,27 +44,74 @@ export const reds = [
|
||||||
]
|
]
|
||||||
|
|
||||||
export function colorByCount(attribute = 'event_count', maxCount, colormap = viridis) {
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
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 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",
|
||||||
|
"urban", "blue",
|
||||||
|
"purple"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
export function colorByDistance(attribute = 'distance_overtaker_mean', fallback = '#ABC', zone='urban') {
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'case',
|
'case',
|
||||||
['!', ['to-boolean', ['get', attribute]]],
|
['!', isValidAttribute(attribute)],
|
||||||
fallback,
|
fallback,
|
||||||
|
["match", ['get', 'zone'], "rural",
|
||||||
[
|
[
|
||||||
'step',
|
'step',
|
||||||
['get', attribute],
|
['get', attribute],
|
||||||
'rgba(150, 0, 0, 1)',
|
'rgba(150, 0, 0, 1)',
|
||||||
1.1,
|
steps['rural'][0],
|
||||||
'rgba(255, 0, 0, 1)',
|
'rgba(255, 0, 0, 1)',
|
||||||
1.3,
|
steps['rural'][1],
|
||||||
'rgba(255, 220, 0, 1)',
|
'rgba(255, 220, 0, 1)',
|
||||||
1.5,
|
steps['rural'][2],
|
||||||
'rgba(67, 200, 0, 1)',
|
'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)',
|
'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)',
|
||||||
|
]
|
||||||
|
]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
import {connect} from 'react-redux'
|
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 {
|
import {
|
||||||
MapConfig,
|
MapConfig,
|
||||||
|
@ -23,6 +23,7 @@ const ROAD_ATTRIBUTE_OPTIONS = [
|
||||||
{value: 'distance_overtaker_median', key: 'distance_overtaker_median', text: 'Overtaker distance median'},
|
{value: 'distance_overtaker_median', key: 'distance_overtaker_median', text: 'Overtaker distance median'},
|
||||||
{value: 'overtaking_event_count', key: 'overtaking_event_count', text: 'Event count'},
|
{value: 'overtaking_event_count', key: 'overtaking_event_count', text: 'Event count'},
|
||||||
{value: 'usage_count', key: 'usage_count', text: 'Usage count'},
|
{value: 'usage_count', key: 'usage_count', text: 'Usage count'},
|
||||||
|
{value: 'zone', key: 'zone', text: 'Overtaking distance zone'}
|
||||||
]
|
]
|
||||||
|
|
||||||
function LayerSidebar({
|
function LayerSidebar({
|
||||||
|
@ -96,10 +97,24 @@ function LayerSidebar({
|
||||||
<ColorMapLegend map={_.chunk(colorByCount('obsRoads.maxCount', mapConfig.obsRoads.maxCount, viridisSimpleHtml ).slice(3), 2)} twoTicks />
|
<ColorMapLegend map={_.chunk(colorByCount('obsRoads.maxCount', mapConfig.obsRoads.maxCount, viridisSimpleHtml ).slice(3), 2)} twoTicks />
|
||||||
</List.Item></>
|
</List.Item></>
|
||||||
) :
|
) :
|
||||||
(
|
attribute.endsWith('zone') ? (
|
||||||
|
<>
|
||||||
<List.Item>
|
<List.Item>
|
||||||
<DiscreteColorMapLegend map={colorByDistance('distance_overtaker')[3].slice(2)} />
|
<Label size="small" style={{background: "blue",color:"white"}}>urban (1.5 m)</Label>
|
||||||
|
<Label size="small" style={{background: "cyan", color:"black"}}>rural (2 m)</Label>
|
||||||
|
</List.Item></>
|
||||||
|
) :
|
||||||
|
(
|
||||||
|
<>
|
||||||
|
<List.Item>
|
||||||
|
<List.Header>Urban</List.Header>
|
||||||
|
<DiscreteColorMapLegend map={colorByDistance('distance_overtaker')[3][5].slice(2)} />
|
||||||
</List.Item>
|
</List.Item>
|
||||||
|
<List.Item>
|
||||||
|
<List.Header>Rural</List.Header>
|
||||||
|
<DiscreteColorMapLegend map={colorByDistance('distance_overtaker')[3][3].slice(2)} />
|
||||||
|
</List.Item>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
@ -120,7 +135,12 @@ function LayerSidebar({
|
||||||
{showEvents && (
|
{showEvents && (
|
||||||
<>
|
<>
|
||||||
<List.Item>
|
<List.Item>
|
||||||
<DiscreteColorMapLegend map={colorByDistance('distance_overtaker')[3].slice(2)} />
|
<List.Header>Urban</List.Header>
|
||||||
|
<DiscreteColorMapLegend map={colorByDistance('distance_overtaker')[3][5].slice(2)} />
|
||||||
|
</List.Item>
|
||||||
|
<List.Item>
|
||||||
|
<List.Header>Rural</List.Header>
|
||||||
|
<DiscreteColorMapLegend map={colorByDistance('distance_overtaker')[3][3].slice(2)} />
|
||||||
</List.Item>
|
</List.Item>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import {Chart} from 'components'
|
||||||
import {pairwise} from 'utils'
|
import {pairwise} from 'utils'
|
||||||
|
|
||||||
import api from 'api'
|
import api from 'api'
|
||||||
import {colorByDistance} from 'mapstyles'
|
import {colorByDistance, borderByZone} from 'mapstyles'
|
||||||
|
|
||||||
import styles from './styles.module.less'
|
import styles from './styles.module.less'
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ const LABELS = {
|
||||||
max: 'Maximum',
|
max: 'Maximum',
|
||||||
mean: 'Average',
|
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 CARDINAL_DIRECTIONS = ['north', 'north-east', 'east', 'south-east', 'south', 'south-west', 'west', 'north-west']
|
||||||
const getCardinalDirection = (bearing) =>
|
const getCardinalDirection = (bearing) =>
|
||||||
bearing == null
|
bearing == null
|
||||||
|
@ -75,14 +75,15 @@ function RoadStatsTable({data}) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function HistogramChart({bins, counts}) {
|
function HistogramChart({bins, counts, zone}) {
|
||||||
const diff = bins[1] - bins[0]
|
const diff = bins[1] - bins[0]
|
||||||
|
const colortype = zone=="rural" ? 3:5;
|
||||||
const data = _.zip(
|
const data = _.zip(
|
||||||
bins.slice(0, bins.length - 1).map((v) => v + diff / 2),
|
bins.slice(0, bins.length - 1).map((v) => v + diff / 2),
|
||||||
counts
|
counts
|
||||||
).map((value) => ({
|
).map((value) => ({
|
||||||
value,
|
value,
|
||||||
itemStyle: {color: selectFromColorMap(colorByDistance()[3].slice(2), value[0])},
|
itemStyle: {color: selectFromColorMap(colorByDistance()[3][colortype].slice(2), value[0]),},
|
||||||
}))
|
}))
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -6,7 +6,7 @@ import produce from 'immer'
|
||||||
|
|
||||||
import {Page, Map} from 'components'
|
import {Page, Map} from 'components'
|
||||||
import {useConfig} from 'config'
|
import {useConfig} from 'config'
|
||||||
import {colorByDistance, colorByCount, reds} from 'mapstyles'
|
import {colorByDistance, colorByCount, borderByZone, reds, isValidAttribute} from 'mapstyles'
|
||||||
import {useMapConfig} from 'reducers/mapConfig'
|
import {useMapConfig} from 'reducers/mapConfig'
|
||||||
|
|
||||||
import RoadInfo from './RoadInfo'
|
import RoadInfo from './RoadInfo'
|
||||||
|
@ -40,20 +40,23 @@ const untaggedRoadsLayer = {
|
||||||
minzoom: 12,
|
minzoom: 12,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getUntaggedRoadsLayer = (colorAttribute, maxCount) =>
|
||||||
|
produce(untaggedRoadsLayer, (draft) => {
|
||||||
|
draft.filter = ['!', isValidAttribute(colorAttribute)]
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
const getRoadsLayer = (colorAttribute, maxCount) =>
|
const getRoadsLayer = (colorAttribute, maxCount) =>
|
||||||
produce(untaggedRoadsLayer, (draft) => {
|
produce(untaggedRoadsLayer, (draft) => {
|
||||||
draft.id = 'obs_roads_normal'
|
draft.id = 'obs_roads_normal'
|
||||||
if (colorAttribute.endsWith('_count')) {
|
draft.filter = isValidAttribute(colorAttribute)
|
||||||
// delete draft.filter
|
|
||||||
draft.filter = ['to-boolean', ['get', colorAttribute]]
|
|
||||||
} else {
|
|
||||||
draft.filter = draft.filter[1] // remove '!'
|
|
||||||
}
|
|
||||||
draft.paint['line-width'][6] = 6 // scale bigger on zoom
|
draft.paint['line-width'][6] = 6 // scale bigger on zoom
|
||||||
draft.paint['line-color'] = colorAttribute.startsWith('distance_')
|
draft.paint['line-color'] = colorAttribute.startsWith('distance_')
|
||||||
? colorByDistance(colorAttribute)
|
? colorByDistance(colorAttribute)
|
||||||
: colorAttribute.endsWith('_count')
|
: colorAttribute.endsWith('_count')
|
||||||
? colorByCount(colorAttribute, maxCount)
|
? colorByCount(colorAttribute, maxCount)
|
||||||
|
: colorAttribute.endsWith('zone')
|
||||||
|
? borderByZone()
|
||||||
: '#DDD'
|
: '#DDD'
|
||||||
draft.paint['line-opacity'][3] = 12
|
draft.paint['line-opacity'][3] = 12
|
||||||
draft.paint['line-opacity'][5] = 13
|
draft.paint['line-opacity'][5] = 13
|
||||||
|
@ -128,8 +131,9 @@ export default function MapPage() {
|
||||||
|
|
||||||
const layers = []
|
const layers = []
|
||||||
|
|
||||||
|
const untaggedRoadsLayerCustom = useMemo(() => getUntaggedRoadsLayer(attribute), [attribute])
|
||||||
if (mapConfig.obsRoads.show && mapConfig.obsRoads.showUntagged) {
|
if (mapConfig.obsRoads.show && mapConfig.obsRoads.showUntagged) {
|
||||||
layers.push(untaggedRoadsLayer)
|
layers.push(untaggedRoadsLayerCustom)
|
||||||
}
|
}
|
||||||
|
|
||||||
const roadsLayer = useMemo(() => getRoadsLayer(attribute, maxCount), [attribute, maxCount])
|
const roadsLayer = useMemo(() => getRoadsLayer(attribute, maxCount), [attribute, maxCount])
|
||||||
|
|
|
@ -11,7 +11,8 @@ type RoadAttribute =
|
||||||
| "distance_overtaker_max"
|
| "distance_overtaker_max"
|
||||||
| "distance_overtaker_median"
|
| "distance_overtaker_median"
|
||||||
| "overtaking_event_count"
|
| "overtaking_event_count"
|
||||||
| "usage_count";
|
| "usage_count"
|
||||||
|
| "zone";
|
||||||
|
|
||||||
export type MapConfig = {
|
export type MapConfig = {
|
||||||
baseMap: {
|
baseMap: {
|
||||||
|
|
|
@ -163,6 +163,7 @@ module.exports = function (webpackEnv) {
|
||||||
'/config.json': apiUrl,
|
'/config.json': apiUrl,
|
||||||
'/api': apiUrl,
|
'/api': apiUrl,
|
||||||
'/login': apiUrl,
|
'/login': apiUrl,
|
||||||
|
'/tiles': apiUrl
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
module: {
|
module: {
|
||||||
|
|
|
@ -61,6 +61,8 @@ local roads = osm2pgsql.define_way_table('road', {
|
||||||
{ column = 'oneway', type = 'bool' },
|
{ column = 'oneway', type = 'bool' },
|
||||||
})
|
})
|
||||||
|
|
||||||
|
local minspeed_rural = 60
|
||||||
|
|
||||||
function osm2pgsql.process_way(object)
|
function osm2pgsql.process_way(object)
|
||||||
if object.tags.highway and contains(HIGHWAY_TYPES, object.tags.highway) then
|
if object.tags.highway and contains(HIGHWAY_TYPES, object.tags.highway) then
|
||||||
local tags = object.tags
|
local tags = object.tags
|
||||||
|
@ -81,13 +83,30 @@ function osm2pgsql.process_way(object)
|
||||||
zone = "urban"
|
zone = "urban"
|
||||||
elseif string.match(zone, "motorway") then
|
elseif string.match(zone, "motorway") then
|
||||||
zone = "motorway"
|
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"
|
zone = "urban"
|
||||||
elseif contains(MOTORWAY_TYPES, tags.highway) then
|
elseif contains(MOTORWAY_TYPES, tags.highway) then
|
||||||
zone = "motorway"
|
zone = "motorway"
|
||||||
|
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"
|
||||||
|
elseif tags['source:maxspeed'] and string.match(tags['source:maxspeed'], "urban") then
|
||||||
|
zone = "urban"
|
||||||
else
|
else
|
||||||
-- we can't figure it out
|
-- we can't figure it out
|
||||||
zone = nil
|
zone = "urban"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
CREATE OR REPLACE FUNCTION layer_obs_events(bbox geometry, zoom_level int)
|
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
|
SELECT
|
||||||
id::bigint as event_id,
|
id::bigint as event_id,
|
||||||
|
@ -9,8 +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,
|
(case when direction_reversed then -1 else 1 end)::int as direction,
|
||||||
course,
|
course,
|
||||||
speed,
|
speed,
|
||||||
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
|
FROM overtaking_event
|
||||||
|
FULL OUTER JOIN road ON (road.way_id = overtaking_event.way_id)
|
||||||
WHERE ST_Transform(overtaking_event.geometry, 3857) && bbox;
|
WHERE ST_Transform(overtaking_event.geometry, 3857) && bbox;
|
||||||
|
|
||||||
$$ LANGUAGE SQL IMMUTABLE;
|
$$ LANGUAGE SQL IMMUTABLE;
|
||||||
|
|
|
@ -16,6 +16,8 @@ layer:
|
||||||
Direction of travel, as reported by GPS, in degree from North.
|
Direction of travel, as reported by GPS, in degree from North.
|
||||||
speed: |
|
speed: |
|
||||||
Speed of travel, as reported by GPS, in meters per second (?).
|
Speed of travel, as reported by GPS, in meters per second (?).
|
||||||
|
zone: |
|
||||||
|
rural or urban
|
||||||
defaults:
|
defaults:
|
||||||
srs: EPSG:3785
|
srs: EPSG:3785
|
||||||
datasource:
|
datasource:
|
||||||
|
@ -23,7 +25,7 @@ layer:
|
||||||
geometry_field: geometry
|
geometry_field: geometry
|
||||||
key_field: event_id
|
key_field: event_id
|
||||||
key_field_as_attribute: no
|
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:
|
schema:
|
||||||
- ./layer.sql
|
- ./layer.sql
|
||||||
|
|
|
@ -12,6 +12,7 @@ RETURNS TABLE(
|
||||||
overtaking_event_count int,
|
overtaking_event_count int,
|
||||||
usage_count bigint,
|
usage_count bigint,
|
||||||
direction int,
|
direction int,
|
||||||
|
zone zone_type,
|
||||||
offset_direction int
|
offset_direction int
|
||||||
) AS $$
|
) AS $$
|
||||||
|
|
||||||
|
@ -27,12 +28,13 @@ RETURNS TABLE(
|
||||||
(select count(id) from road_usage where road_usage.way_id = road.way_id and
|
(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,
|
(road.directionality != 0 or road_usage.direction_reversed = r.rev)) as usage_count,
|
||||||
r.dir as direction,
|
r.dir as direction,
|
||||||
|
road.zone::zone_type as zone,
|
||||||
case when road.directionality = 0 then r.dir else 0 end as offset_direction
|
case when road.directionality = 0 then r.dir else 0 end as offset_direction
|
||||||
FROM road
|
FROM road
|
||||||
LEFT JOIN (VALUES (-1, TRUE), (1, FALSE), (0, FALSE)) AS r(dir, rev) ON (abs(r.dir) != road.directionality)
|
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))
|
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.name = 'Merzhauser Straße'
|
||||||
WHERE road.geometry && bbox
|
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;
|
$$ LANGUAGE SQL IMMUTABLE;
|
||||||
|
|
|
@ -22,6 +22,8 @@ layer:
|
||||||
Contains -1 for events while going along the way backwards, 1 for
|
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,
|
forwards. Each road is emitted twice, if it has data for both directions,
|
||||||
even if it is oneway.
|
even if it is oneway.
|
||||||
|
zone: |
|
||||||
|
ural or urban
|
||||||
offset_direction: |
|
offset_direction: |
|
||||||
Factor for offset to shift the line to the driving side. One of -1, 0, 1.
|
Factor for offset to shift the line to the driving side. One of -1, 0, 1.
|
||||||
defaults:
|
defaults:
|
||||||
|
@ -44,6 +46,7 @@ layer:
|
||||||
overtaking_event_count,
|
overtaking_event_count,
|
||||||
usage_count,
|
usage_count,
|
||||||
direction,
|
direction,
|
||||||
|
zone,
|
||||||
offset_direction
|
offset_direction
|
||||||
FROM layer_obs_roads(!bbox!, z(!scale_denominator!))
|
FROM layer_obs_roads(!bbox!, z(!scale_denominator!))
|
||||||
) AS t
|
) AS t
|
||||||
|
|
Loading…
Reference in a new issue