Skip to content

Commit

Permalink
Add a PCT layer. #337 (#339)
Browse files Browse the repository at this point in the history
* Add a PCT layer. #337

* Adjust wording

* Update src/lib/browse/layers/PctLayerControl.svelte

Co-authored-by: Robin Lovelace <Robinlovelace@users.noreply.github.com>

---------

Co-authored-by: Robin Lovelace <Robinlovelace@users.noreply.github.com>
  • Loading branch information
dabreegster and Robinlovelace authored Sep 18, 2023
1 parent f8a1c2a commit 4fe6695
Show file tree
Hide file tree
Showing 5 changed files with 157 additions and 12 deletions.
2 changes: 2 additions & 0 deletions src/lib/browse/LayerControls.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import LocalPlanningAuthoritiesLayerControl from "./layers/LocalPlanningAuthoritiesLayerControl.svelte";
import MrnLayerControl from "./layers/MrnLayerControl.svelte";
import ParliamentaryConstituenciesLayerControl from "./layers/ParliamentaryConstituenciesLayerControl.svelte";
import PctLayerControl from "./layers/PctLayerControl.svelte";
import RailwayStationsLayerControl from "./layers/RailwayStationsLayerControl.svelte";
import SchoolsLayerControl from "./layers/SchoolsLayerControl.svelte";
import SportsSpacesLayerControl from "./layers/SportsSpacesLayerControl.svelte";
Expand Down Expand Up @@ -71,6 +72,7 @@
</CollapsibleCard>
<CollapsibleCard label="Other">
<VehicleCountsLayerControl />
<PctLayerControl />
</CollapsibleCard>
<StreetViewController
bind:this={streetViewController}
Expand Down
16 changes: 16 additions & 0 deletions src/lib/browse/colors.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { type DataDrivenPropertyValueSpecification } from "maplibre-gl";

// These are specific to the browse page
export const colors = {
schools: "#007DBB",
Expand Down Expand Up @@ -36,3 +38,17 @@ export const colors = {
atf3: "#FF62DC",
atf4: "#FFD833",
};

// For dense line layers, make individual lines easily distinguished when
// zoomed in, but not too thick when zoomed out.
export const denseLineWidth: DataDrivenPropertyValueSpecification<number> = [
"interpolate",
["exponential", 1.6],
["zoom"],
3,
1.0,
7,
2.0,
18,
20.0,
];
14 changes: 2 additions & 12 deletions src/lib/browse/layers/CyclePathsLayerControl.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
} from "lib/maplibre";
import type { MapGeoJSONFeature } from "maplibre-gl";
import { map } from "stores";
import { colors } from "../colors";
import { colors, denseLineWidth } from "../colors";
let name = "cycle_paths";
Expand Down Expand Up @@ -45,17 +45,7 @@
},
"red"
),
width: [
"interpolate",
["exponential", 1.6],
["zoom"],
3,
1.0,
7,
2.0,
18,
20.0,
],
width: denseLineWidth,
opacity: hoveredToggle(0.5, 1.0),
});
Expand Down
135 changes: 135 additions & 0 deletions src/lib/browse/layers/PctLayerControl.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
<script lang="ts">
import { ExternalLink, HelpButton, InteractiveLayer } from "lib/common";
import { Checkbox, Radio, Select } 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";
// TODO It'd be much simpler to have one source with both attributes
let nameCommute = "pct_commute";
let nameSchool = "pct_school";
let colorScale = colors.sequential_low_to_high;
let limits = [0, 50, 100, 500, 1000, 2000];
let tripPurpose = nameCommute;
let scenario = "baseline";
for (let name of [nameCommute, nameSchool]) {
overwritePmtilesSource(
$map,
name,
`${import.meta.env.VITE_RESOURCE_BASE}/layers/v1/${name}.pmtiles`
);
overwriteLineLayer($map, {
id: name,
source: name,
sourceLayer: name,
color: makeColorRamp(["get", scenario], limits, colorScale),
width: denseLineWidth,
opacity: hoveredToggle(0.5, 1.0),
});
}
let show = false;
function tooltip(feature: MapGeoJSONFeature): string {
let baseline = feature.properties.baseline;
let gov_target = feature.properties.gov_target;
let go_dutch = feature.properties.go_dutch;
let x = `<h2>Trip purpose: ${
tripPurpose == nameCommute ? "commuting" : "school"
}</h2>`;
x += `<p>Baseline (2011): <b>${baseline.toLocaleString()}</b></p>`;
if (baseline == 0) {
x += `<p>Government target (2025): <b>${gov_target.toLocaleString()}</b></p>`;
x += `<p>Go Dutch: <b>${go_dutch.toLocaleString()}</b></p>`;
} else {
let multiplier_gov_target = (gov_target / baseline).toFixed(1);
let multiplier_go_dutch = (go_dutch / baseline).toFixed(1);
x += `<p>Government target (2025): ${gov_target.toLocaleString()} (<b>${multiplier_gov_target}x</b> of baseline)</p>`;
x += `<p>Go Dutch: ${go_dutch.toLocaleString()} (<b>${multiplier_go_dutch}x</b> of baseline)</p>`;
}
return x;
}
function changeStyle() {
$map.setPaintProperty(
tripPurpose,
"line-color",
makeColorRamp(["get", scenario], limits, colorScale)
);
}
</script>

<Checkbox id={nameCommute} bind:checked={show}>
Propensity to Cycle Tool
<span slot="right">
<HelpButton>
<p>
The PCT shows major links on the transport network on which there is
high latent demand for cycling under scenarios of change, based on the
"fastest" routes from CycleStreets. Counts approximate daily rush hour
traffic levels.
</p>
<p>
Note this layer uses 2011 census data and outdated OpenStreetMap data.
Please use this layer with caution.
</p>
<p>
See <ExternalLink href="https://www.pct.bike">
the PCT website
</ExternalLink> and <ExternalLink
href="https://www.jtlu.org/index.php/jtlu/article/view/862"
>
2017 journal article
</ExternalLink> for details on methodology and data sources.
</p>
</HelpButton>
</span>
</Checkbox>
{#if show}
<SequentialLegend {colorScale} {limits} />
<Radio
legend="Trip purpose"
id="tripPurpose"
choices={[
["pct_commute", "Commuting"],
["pct_school", "School"],
]}
bind:value={tripPurpose}
on:change={changeStyle}
inlineSmall
/>
<Select
label="Scenario"
id="scenario"
choices={[
["baseline", "Baseline (2011)"],
["gov_target", "Government target (2025)"],
["go_dutch", "Go Dutch"],
]}
bind:value={scenario}
on:change={changeStyle}
/>
{/if}

<InteractiveLayer
layer={nameCommute}
{tooltip}
show={show && tripPurpose == nameCommute}
clickable={false}
/>
<InteractiveLayer
layer={nameSchool}
{tooltip}
show={show && tripPurpose == nameSchool}
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 @@ -322,6 +322,8 @@ const layerZorder = [
"crossings",
"cycle_paths",
"vehicle_counts",
"pct_commute",
"pct_school",

// 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 4fe6695

Please sign in to comment.