Skip to content

Commit

Permalink
Start a layer for OS road widths and speeds (#348)
Browse files Browse the repository at this point in the history
* Start a layer for OS road widths and speeds

* Document private_layers/ in GCS bucket
  • Loading branch information
dabreegster authored Sep 20, 2023
1 parent 88cad1a commit 62d7064
Show file tree
Hide file tree
Showing 5 changed files with 190 additions and 0 deletions.
1 change: 1 addition & 0 deletions backend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ Names and regions should match above.
1. `gcloud storage --project=$PROJECT buckets create gs://$PROJECT --location=EUROPE-WEST2 --uniform-bucket-level-access`
2. Generate fake scheme data and upload it: `npm run generate-random-schemes && gsutil cp random_schemes.geojson gs://$PROJECT/`
3. Sync current public layers to GCS. This only works if you have S3 access (aka Dustin). Skip these otherwise, or download another way. This might take a few minutes, depending on your connection: `aws s3 sync s3://atip.uk/layers layers; gsutil -m cp -r ./layers gs://$PROJECT/`
4. Also copy private files (currently [only from Ordnance Survey](https://github.com/acteng/atip-data-prep/tree/main/ordnance_survey_layers)) into `gs://$PROJECT/private_layers/v1/`. These have to be generated by a developer; they can't be mirrored from S3, because our S3 bucket is only appropriate for public data.

### Deploy

Expand Down
7 changes: 7 additions & 0 deletions src/lib/browse/LayerControls.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<script lang="ts">
import {
appVersion,
BaselayerSwitcher,
CollapsibleCard,
StreetViewController,
Expand All @@ -21,6 +22,8 @@
import ParliamentaryConstituenciesLayerControl from "./layers/ParliamentaryConstituenciesLayerControl.svelte";
import PctLayerControl from "./layers/PctLayerControl.svelte";
import RailwayStationsLayerControl from "./layers/RailwayStationsLayerControl.svelte";
import RoadSpeedsLayerControl from "./layers/RoadSpeedsLayerControl.svelte";
import RoadWidthsLayerControl from "./layers/RoadWidthsLayerControl.svelte";
import SchoolsLayerControl from "./layers/SchoolsLayerControl.svelte";
import SportsSpacesLayerControl from "./layers/SportsSpacesLayerControl.svelte";
import VehicleCountsLayerControl from "./layers/VehicleCountsLayerControl.svelte";
Expand Down Expand Up @@ -73,6 +76,10 @@
<CollapsibleCard label="Other">
<VehicleCountsLayerControl />
<PctLayerControl />
{#if appVersion() == "Private (development)"}
<RoadWidthsLayerControl />
<RoadSpeedsLayerControl />
{/if}
</CollapsibleCard>
<StreetViewController
bind:this={streetViewController}
Expand Down
110 changes: 110 additions & 0 deletions src/lib/browse/layers/RoadSpeedsLayerControl.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
<script lang="ts">
import { ExternalLink, HelpButton, InteractiveLayer } from "lib/common";
import { Checkbox, Radio } from "lib/govuk";
import {
hoveredToggle,
makeColorRamp,
overwriteLineLayer,
overwritePmtilesSource,
} from "lib/maplibre";
import type { MapGeoJSONFeature } from "maplibre-gl";
import { map } from "stores";
import { colors, denseLineWidth } from "../colors";
import SequentialLegend from "./SequentialLegend.svelte";
let name = "road_speeds";
let colorScale = colors.sequential_low_to_high;
let limits = [0, 20, 30, 40, 50, 90];
let showSpeed = "indicative_mph";
overwritePmtilesSource(
$map,
name,
`${import.meta.env.VITE_RESOURCE_BASE}/private_layers/v1/${name}.pmtiles`
);
overwriteLineLayer($map, {
id: name,
source: name,
sourceLayer: name,
color: makeColorRamp(["get", showSpeed], limits, colorScale),
width: denseLineWidth,
opacity: hoveredToggle(0.5, 1.0),
});
let show = false;
function tooltip(feature: MapGeoJSONFeature): string {
// @ts-ignore Trusting the input data has the correct form
let time = {
mf4to7: "Monday-Friday 4-7am",
mf7to9: "Monday-Friday 7-9am",
mf9to12: "Monday-Friday 9am-12pm",
mf12to14: "Monday-Friday 12-2pm",
mf14to16: "Monday-Friday 2-4pm",
mf16to19: "Monday-Friday 4-7pm",
mf19to22: "Monday-Friday 7-10pm",
mf22to4: "Monday-Friday 10pm-4am",
ss4to7: "Saturday-Sunday 4-7am",
ss7to10: "Saturday-Sunday 7-10am",
ss10to14: "Saturday-Sunday 10am-2pm",
ss14to19: "Saturday-Sunday 2-7pm",
ss19to22: "Saturday-Sunday 7-10pm",
ss22to4: "Saturday-Sunday 10pm-4am",
}[feature.properties.highest_description];
let x = `<p>Posted speed limit: ${feature.properties.indicative_mph} mph</p>`;
x += `<p>Highest average speed: ${feature.properties.highest_mph} mph (during ${time})</p>`;
return x;
}
function changeStyle() {
$map.setPaintProperty(
name,
"line-color",
makeColorRamp(["get", showSpeed], limits, colorScale)
);
}
</script>

<Checkbox id={name} bind:checked={show}>
OS Speeds
<span slot="right">
<HelpButton>
<p>
The average speed data is collected over a six-month period by <ExternalLink
href="https://basemap.co.uk/speed-data"
>
Basemap
</ExternalLink> from 135,000 vehicle telematic systems and provided through
Ordnance Survey. The averages are grouped by different time periods for weekdays
and weekends. This map shows the highest average.
</p>
<p>Data valid as of 1 September, 2023</p>
<p>
License: Contains OS data &copy; Crown copyright and database right
2023. Made available under the <ExternalLink
href="https://www.ordnancesurvey.co.uk/documents/licensing/psga-member-licence.pdf"
>
Public Sector Geospatial Agreement
</ExternalLink>.
</p>
</HelpButton>
</span>
</Checkbox>
{#if show}
<SequentialLegend {colorScale} {limits} />
<Radio
legend="Show speed types"
id="showSpeed"
choices={[
["indicative_mph", "Posted speed limit"],
["highest_mph", "Highest measured average speed"],
]}
bind:value={showSpeed}
on:change={changeStyle}
inlineSmall
/>
{/if}

<InteractiveLayer layer={name} {tooltip} {show} clickable={false} />
70 changes: 70 additions & 0 deletions src/lib/browse/layers/RoadWidthsLayerControl.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<script lang="ts">
import { ExternalLink, HelpButton, InteractiveLayer } from "lib/common";
import { Checkbox } from "lib/govuk";
import {
hoveredToggle,
makeColorRamp,
overwriteLineLayer,
overwritePmtilesSource,
} from "lib/maplibre";
import type { MapGeoJSONFeature } from "maplibre-gl";
import { map } from "stores";
import { colors, denseLineWidth } from "../colors";
import SequentialLegend from "./SequentialLegend.svelte";
let name = "road_widths";
let colorScale = colors.sequential_low_to_high;
let limits = [0, 5, 10, 15, 20, 100];
overwritePmtilesSource(
$map,
name,
`${import.meta.env.VITE_RESOURCE_BASE}/private_layers/v1/${name}.pmtiles`
);
overwriteLineLayer($map, {
id: name,
source: name,
sourceLayer: name,
color: makeColorRamp(["get", "average"], limits, colorScale),
// TODO Try showing the actual width, in meters and not pixels
width: denseLineWidth,
opacity: hoveredToggle(0.5, 1.0),
});
let show = false;
function tooltip(feature: MapGeoJSONFeature): string {
let x = `<p>Average width: ${feature.properties.average} meters</p>`;
x += `<p>Minimum width: ${feature.properties.minimum} meters</p>`;
return x;
}
</script>

<Checkbox id={name} bind:checked={show}>
OS Road widths
<span slot="right">
<HelpButton>
<p>
This is average and minimum road carriageway width (in meters) from
Ordnance Survey. The coloring shows the average width, and the line
thickness has no meaning. Be careful interpreting the data near dual
carriageways and crossing islands.
</p>
<p>Data valid as of 1 September, 2023</p>
<p>
License: Contains OS data &copy; Crown copyright and database right
2023. Made available under the <ExternalLink
href="https://www.ordnancesurvey.co.uk/documents/licensing/psga-member-licence.pdf"
>
Public Sector Geospatial Agreement
</ExternalLink>.
</p>
</HelpButton>
</span>
</Checkbox>
{#if show}
<SequentialLegend {colorScale} {limits} />
{/if}

<InteractiveLayer layer={name} {tooltip} {show} clickable={false} />
2 changes: 2 additions & 0 deletions src/lib/maplibre/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,8 @@ const layerZorder = [
"vehicle_counts",
"pct_commute",
"pct_school",
"road_widths",
"road_speeds",

// Polygons are bigger than lines, which're bigger than points. When geometry
// overlaps, put the smaller thing on top
Expand Down

0 comments on commit 62d7064

Please sign in to comment.