Portable floodplain delineation from DEM and stream network.
Delineate unconfined valleys and floodplain extent using the Valley Confinement Algorithm (VCA) — combining slope thresholding, cost-distance analysis, and flood surface modelling. Built on terra for R-native raster processing. Bring your own DEM and streams; works anywhere.
Installation
pak::pak("NewGraphEnvironment/flooded")Example
library(flooded)
dem <- terra::rast("dem.tif")
streams <- sf::st_read("streams.gpkg")
# delineate valleys — one call
valleys <- fl_valley_confine(
dem, streams,
field = "upstream_area_ha",
precip = precip_r # mean annual precipitation (mm) — critical for depth
)
# convert to polygons for GIS
valleys_poly <- fl_valley_poly(valleys)
sf::st_write(valleys_poly, "valleys.gpkg")See the Valley confinement vignette for a full walkthrough with bundled test data, and the function reference for individual components.
Bankfull regression
The flood model uses the VCA bankfull regression to estimate flood depth at stream cells:
bankfull_width = (upstream_area ^ 0.280) * 0.196 * (precip ^ 0.355)
bankfull_depth = bankfull_width ^ 0.607 * 0.145
flood_depth = bankfull_depth * flood_factor
Both upstream_area (hectares) and precip (mean annual precipitation, mm) are important — omitting precipitation underestimates flood depth by ~4x.
Resolution and restoration
flooded is DEM-agnostic — any source works. But resolution changes what you can see. At 25 m (e.g. the provincial TRIM DEM), the floodplain appears as one continuous surface. At 1 m lidar, anthropogenic features emerge: roads, railway grades, dykes, and agricultural fill that sit above the flood surface and block lateral connectivity.
The gap between coarse and fine results is a diagnostic: it shows what is preventing floodplain from functioning and where to act — removing fill, breaching dykes, or installing crossings to reconnect floodplain. See the STAC DEM vignette for a worked example comparing 25 m TRIM with 1 m lidar on the Neexdzii Kwah (Bulkley River).
Performance
Set terra threads before running the pipeline to enable multi-core processing:
terra::terraOptions(threads = 12) # adjust to your machineOn an Apple M4 Max, this cuts a ~2,700 km² watershed (27M cells at 10 m) from ~3.5 min to ~1 min.
Origins
Adapted from:
- BlueGeo by Devin Cairns (MIT) — Valley Confinement Algorithm
- USDA VCA Toolbox — original method
- bcfishpass by Simon Norris (Apache 2.0) — lateral habitat assembly
See LICENSE.note for full attribution.
