What this is: a modelled estimate of how much shade you would find on a walking, dog walking or cycling route through a corridor of northern Brisbane, at five times of day on a single representative summer day.
What it is not: live data, a weather service, or safety advice. Nothing here is measured on the day you are reading it. The most important limitations are collected under What this model gets wrong and are worth reading before trusting a route for a hot afternoon.
A corridor of roughly 30–40 km² running from the Kedron Brook Bikeway through Nundah and Nudgee to Boondall Wetlands and Nudgee Beach. The corridor is built by buffering the bikeway spine by 1 km and adding the park and reserve polygons along it.
The area is deliberately small. Modelling shade properly at 1 m resolution is expensive, and a corridor that can be validated on foot is worth more than a city that cannot.
Full licence and attribution detail is in attribution.md.
| What | Source | Vintage |
|---|---|---|
| Ground and canopy heights | ELVIS LiDAR point cloud, Brisbane_2019_Prj |
captured 2019 |
| Paths, footways and roads | OpenStreetMap | retrieved 2026-08-01 |
| Dog off-leash areas, drinking fountains | Brisbane City Council open data | retrieved 2026-08-01 |
The elevation capture is 1.91 billion points at 51.7 points/m², classified by return type, so vegetation can be separated from ground and structures directly rather than inferred.
Two 1 m rasters are derived from the point cloud: a terrain model from ground-classified returns, and a surface model from the highest return in each cell. Where the surface stands more than 2 m above the terrain and the returns are vegetation-classified, that cell is canopy.
Solar azimuth and elevation come from pvlib for the design day (15 January 2026, a
representative midsummer date) in Australia/Brisbane time (no daylight saving). Shade is
computed hourly from 06:00 to 18:00. Outside those hours the sun is below the horizon and
there is nothing to model.
The site shows five of those times: 06:00, 09:00, 12:00, 15:00 and 18:00.
For each cell, a ray is marched toward the sun. If any surface along it rises above the sightline, the cell is shaded.
The sightline starts at the ground, not at the surface. This sounds like a detail and is not. A footpath under a fig canopy has its surface model at the top of the canopy; measuring from there finds nothing above it and scores the most shaded ground in the corridor as fully exposed. Early versions of this model did exactly that.
Where the blocker is vegetation, a transmissivity of 0.25 is applied: a quarter of the light gets through. That figure is measured from the gap fraction in the LiDAR returns for this corridor, not taken from literature: published values around 0.03 describe dense northern-hemisphere canopy, and Brisbane's eucalypts are roughly eight times more porous than that. Using the literature value would have made every tree a solid roof.
Transmissivity applies once per crown, not once per cell crossed. Compounding it per cell would turn 0.25 into effectively zero across a wide crown and make porous canopy indistinguishable from opaque.
At this latitude the sun reaches about 84° above the horizon at summer solar noon. A 10 m tree casts roughly 1 m of shadow. Buildings and walls contribute almost nothing at midday.
This is a canopy-overhead product, not a street-canyon one, and the midday collapse in the numbers below is real rather than a modelling failure:
| Time | Share of the path network in shade |
|---|---|
| 06:00 | 71% |
| 09:00 | 31% |
| 12:00 | 7% |
| 15:00 | 31% |
| 18:00 | 76% |
Modelled for the design day with canopy transmissivity 0.25. Verified 2026-08-05.
Instantaneous shade is not pavement temperature. Asphalt shaded at 3pm but baking since 10am is still hot enough to hurt a dog's paws, and a model that only looks at the current hour scores it as perfectly safe.
So every segment also carries a cumulative exposure value: the fraction of the preceding daylight hours it spent in sun. This is why shade is computed hourly even though only five times are shown: five three-hourly snapshots cannot express it.
The fastest-to-coolest slider sets how much detour is worth accepting for shade. At the fastest setting the route ignores shade entirely and is the shortest path. At the coolest it will take a meaningfully longer way round to stay under trees.
All weights are configuration values, and they will be tuned against what is observed on the ground.
The canopy is 2019 canopy. Seven years old at the time of modelling. Trees have grown, been removed, been planted, and been through storms since. This is the single largest source of error, and there is no free dataset that would refresh it: the only alternative captures are older, sparser, or do not cover the corridor.
One day of the year. Everything is computed for a representative midsummer date (15 January). Winter shade coverage is substantially higher — shadow lengths differ by up to 9x — so using this model in winter will understate the shade actually available. The model does not tell you how much shade there is in June; it tells you how much there is at the worst time of year.
The scan was flown in winter; the model is of a summer day. The LiDAR was acquired between 11 June and 16 August 2019. Brisbane's canopy is dominated by evergreen species (eucalypt, fig, melaleuca), so crown structure is broadly comparable across seasons, and this matters far less here than it would somewhere with deciduous street trees. But it is an assumption, not something we measured, and any species that thins in winter will be under-represented in the modelled shade.
No weather, no cloud, no heat. A fully shaded route on a 42°C day is still dangerous. The model knows about geometry and nothing about temperature. The temperature shown alongside a route is not part of the shade model: it defaults to the typical air temperature at the selected time of day on the design day (from a weather archive for this location), so the paw-burn warning reflects a walk taken at that hour rather than the moment you happen to be looking. You can type your own temperature to override it. When a season rotation is added, each season will carry its own daily temperature curve.
Shade is only modelled inside the corridor. Routes may leave the modelled area where the path network genuinely runs outside it: clipping the routing graph to the corridor severed real connections and made most destinations unreachable. Segments outside carry no shade claim, and each route reports how much of it is actually modelled. A route that is mostly outside is not making a shade promise.
Surface data is partial. About 74% of path length carries a surface tag in OpenStreetMap; the rest is inferred from the path type. Informal desire lines across grass are largely unmapped, so "off pavement" is inferred from a combination of soft surface tags and park containment rather than claimed precisely.
Off-leash areas are sparse. Fourteen polygons across the corridor, about 0.2% of path length, so dog loops are geometrically constrained by where those areas actually are.
Modelled, not measured. No part of this has been checked against a thermometer or a light meter. Planned field validation is walking routes in person and comparing what the map claims to what is actually there.
Validation is layered. Computational correctness, browser operation, route geometry and field inputs can each be validated independently. Summer shade claims require seasonally comparable field evidence and are assessed separately.
What has been checked, and to what tolerance:
| Check | Result |
|---|---|
| Shadow direction vs computed sun azimuth | within 0.02° |
Shadow length vs height / tan(elevation) |
within 7.6% |
| Derived terrain vs Queensland's official 1 m DEM | median 4 cm difference, 98.9% within 25 cm |
| Canopy present in the surface model | 63.5% of corridor cells carry vegetation returns |
| Canopy transparency | 25% light transmission, measured from LiDAR gap fraction |
| Unfilled gaps inside the modelled area | none |
| Golden-route regression (7 loops) | exact match on identity, metrics, shade and profile |
The terrain comparison is the most reassuring: two independently derived surfaces from different processing chains agreeing to 4 cm is strong evidence the gridding is right.
The numeric checks were originally passed with canopy modelled as fully opaque and have been re-run (2026-08-05) against the current partly-transparent canopy model (transmissivity 0.25). All measurements remain within tolerance. Geometry is unaffected (the direction and length of a shadow do not depend on how much light passes through a crown); the shaded-percentage figures above reflect the current model.
A synthetic test suite checks the shadow caster against cases with analytically known answers, including deliberately oblique sun angles, because a mirrored or axis-swapped implementation still passes at 90° and 45° and looks entirely plausible on a map. Two real defects were caught this way: shadows cast toward the sun with correct lengths, and shade evaluated at canopy top instead of ground level.
Core application flows (routing, loops, explore, search, POI, mode switching) have been
verified in browser and on a physical device. See docs/RELEASE_BASELINE.md for the
current verification record.
Selected locations have been field checked for path existence, canopy currency, and POI accuracy. A winter observation at Boondall (August 2026) confirmed canopy, paths and most POIs in that precinct. This level does not validate summer shade claims.
No summer shade claim has been field checked. The model's design day is 15 January; winter shadow lengths differ by up to 9x, so winter observations cannot validate summer shade percentages or continuous-sun-run predictions. The summer field exercise will be a representative sampled validation with pre-registered criteria, planned for December 2026 to February 2027.
The pipeline is a sequence of stages driven by a single config.yaml, and every parameter
quoted on this page is a configuration value rather than a constant buried in code. Source,
including the test suite: see the project repository.