10.4 Distance and Cost Surfaces
From straight-line proximity rasters to cost-weighted least-cost paths.
Key takeaways
- A distance surface gives every cell its distance to the nearest feature.
- A cost surface encodes how expensive movement through each cell is.
- Least-cost paths combine both to find the "easiest" route through a landscape.
Introduction
Continuous-surface questions often need continuous-surface answers. How far from the nearest road is every point in the park? What route minimises elevation gain, vegetation density, and water crossings? Distance and cost surfaces answer these at raster scale.
Euclidean distance surface
Every cell gets the distance (in metres or CRS units) to the nearest source feature.
GDAL
gdal_proximity.py roads.tif dist.tif -values 1 -distunits GEOPython
from scipy.ndimage import distance_transform_edtEarth Engine
var dist = roads.distance(50000, 'meters');Uses: buffers-as-continuous-values, service-area gradient maps, habitat proximity metrics.
Cost surface
A cost surface assigns each cell a cost per unit distance reflecting how hard movement through it is:
- Steep slope → high cost.
- Dense vegetation → high cost.
- Open road → low cost.
- Water → impassable (infinite) or very high.
Combine inputs linearly or through a weighted sum:
cost = 1.0 + 2.0 * slope_normalised + 5.0 * water_maskScale each input to a comparable range (0–1 or class scores) before summing; otherwise a raw variable dominates.
Cost-distance / accumulated-cost surface
Accumulated cost from a source to every cell — i.e., the least-cost distance on a cost-weighted raster. Uses an algorithm similar to Dijkstra's but on a grid.
1from skimage.graph import route_through_array
2[object Object]
3[object Object]
4Tools:
- GRASS
r.cost,r.walk. - ArcGIS Spatial Analyst
Cost Distance. - QGIS
Least-cost path. - Python:
scikit-image route_through_array,pyrouting(network-based).
Least-cost path
From the accumulated-cost surface, back-trace from a destination to a source along the gradient — the path of minimum accumulated cost.
Applications:
- Wildlife corridor design.
- Utility line routing.
- Logistics through unstructured terrain.
- Pedestrian routing where no network data exists.
Anisotropic cost
Some costs depend on direction of travel. Classic example: climbing uphill vs going downhill has different energy costs per metre. Tobler's hiking function:
$$v = 6 e^{-3.5 |s + 0.05|}$$
(where s is slope, returns km/h). GRASS's r.walk implements this.
Euclidean vs network vs cost surface
| Method | Pros | Cons |
|---|---|---|
| Euclidean | Simple, fast | Ignores obstacles |
| Network | Realistic for roads | Requires network data |
| Cost surface | Works off-road | More input data needed |
Choose based on data availability and realism required.
Multi-source / multi-destination
"Distance to the nearest of many sources":
1all_sources = roads_mask | schools_mask | hospitals_mask
2distance = distance_transform_edt(~all_sources) * cell_sizeTime surfaces
Convert cost surface (per-cell minutes) into an accumulated time surface. Gives you walking-time isochrones ("everywhere within 30 min"), useful where no road network exists or you want to include terrain.
Pitfalls
- Diagonal vs straight connectivity — allowing diagonal movement vs only cardinal (4 vs 8 neighbours) subtly changes distances. Use
fully_connected=Truefor 8-way. - Resolution — coarse cells underestimate distance (diagonals are discretised).
- Cost weighting — arbitrary weights yield arbitrary paths; calibrate with real observations if possible.
- Barriers — model impassable features with very high cost rather than nodata to allow paths to route around.
Self-check exercises
1. You need "distance to the nearest road" as a raster across a 100 × 100 km area. Which tool / approach?
gdal_proximity.py on a rasterised road mask, at the same resolution and CRS as your analysis raster. For a metric CRS at 30 m resolution, this takes seconds. In Earth Engine, roads.distance(50000) is the equivalent. Always use a projected CRS to get metre distances.
2. Why use a cost surface instead of straight-line distance for wildlife corridor analysis?
Wildlife movement depends on habitat quality, not geometric distance. A river, a highway, or dense human development may be effectively impassable despite being geographically short. A cost surface encoding these constraints produces corridors that real animals can use — Euclidean paths might cross a highway that no animal would.
3. A least-cost path in your analysis clings unrealistically to one cell column. What's likely wrong?
(1) Diagonal movement isn't enabled (fully_connected=True). (2) Cost weights are too extreme (one variable dominates, forcing paths along a narrow ridge). (3) Resolution is too coarse — real paths "see" obstacles differently at different scales. (4) Source / destination points may have been snapped into a no-data or infinite-cost cell.
Summary
- Distance surfaces are proximity-as-raster.
- Cost surfaces encode variable movement difficulty per cell.
- Accumulated-cost + back-trace yields least-cost paths.
- Tobler's hiking function and anisotropic costs model realistic movement.
Further reading
- Tobler, W. (1993) — Three presentations on geographical analysis and modeling.
- GRASS
r.cost,r.walkdocumentation. - Quantitative Methods in Landscape Ecology — Turner & Gardner.
- scikit-image route_through_array documentation.