Skip to content

Add runout avoidance #5

@justmytwospence

Description

@justmytwospence

Plan: Add Avalanche Runout Zone Avoidance

Compute runout zones eagerly when aspects are calculated, using the 10° beta point (gradient ≈ 0.176 rise/run) from avalanche literature. Runout zones will be avoided during pathfinding and visualized with a distinct amber hue.

Algorithm Overview

Runout Zone Computation (in Rust):

  1. For each pixel where gradient >= 0.176 AND aspect ∈ excluded_aspects: mark as source zone
  2. For each source zone pixel, perform steepest-descent flow to propagate danger downhill:
    • Look at all 8 neighbors, find the one with lowest elevation
    • If that neighbor's gradient is still ≥ 0.176 (10°), mark it as runout and continue flowing from there
    • Stop when slope drops below 10° (the beta point where debris typically stops)
  3. Output: binary raster where 1 = runout zone, 0 = safe

Steps

  1. Add compute_runout_zones function in azimuth.rs: Accept excluded_aspects: Vec<String>, elevations: &Vec<Vec<f64>>, azimuths: &Vec<Vec<f64>>, gradients: &Vec<Vec<f64>>. Iterate all pixels; for each source cell (steep + excluded aspect), do BFS/flood-fill following steepest descent until gradient < 0.176. Return Vec<Vec<u8>> runout mask.

  2. Extend AzimuthResult and compute_azimuths in azimuth.rs: Add excluded_aspects: &[String] parameter to compute_azimuths. Call compute_runout_zones after computing azimuths/gradients. Add runout_zones: Vec<u8> field to AzimuthResult (serialized as GeoTIFF).

  3. Update TypeScript WASM wrapper in pathfinder-wasm.ts: Pass excludedAspects array to compute_azimuths, receive and return runout_zones buffer.

  4. Thread runout through find-path-button.tsx: Pass excludedAspects when calling aspect computation, forward runout_zones to handleSetAspectRaster callback.

  5. Add runout exclusion in find_path.rs: Accept runout_zones buffer, parse as raster, add check in successors closure: if runout_zones[ny][nx] > 0 { break 'neighbors; } alongside existing aspect check.

  6. Update handleSetAspectRaster in page.tsx: Accept third runout_zones: Uint8Array parameter, parse with parseGeoraster, merge as third band into aspectRaster state.

  7. Add runout visualization in leaflet-raster-layer.tsx: Read third band (values[2]) from aspectRaster. For pixels where runout > 0, render with amber/orange color (rgba(245, 158, 11, 0.5)) distinct from the red excluded-aspect shading.

Further Considerations

  1. Caching invalidation: Runout depends on excludedAspects, so changing aspects requires recomputing runout. Should we cache multiple runout configurations, or always recompute? Recommend: always recompute—it's fast and aspects rarely change mid-session

  2. Steep terrain without excluded aspects: Currently runout only flows from excluded-aspect slopes. Should all steep terrain generate runout regardless of aspect selection? Recommend: only excluded aspects, since user explicitly chose what to avoid

  3. Flow algorithm choice: BFS flood-fill vs. following single steepest-descent path. BFS captures wider runout fans but is slower. Recommend: start with single steepest-descent path per source cell for performance, can expand later

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions