eikonal
Fast Marching Method and grid-routing utilities for regular 2D grids.
Top-level solve computes first-order upwind FMM arrival times for:
|grad T(x)| = C(x) = 1 / F(x)
Use eikonal::graph for exact weighted shortest paths on an 8-neighbor grid,
and eikonal::terrain for DEM-aware graph routing with 3D surface distances,
elevation profiles, and uphill/downhill cost factors.
Raster I/O, CRS handling, reprojection, resampling, and vertical datum handling
are outside the crate. Use geotiff-rust for GeoTIFF I/O and terrand for
DEM-derived rasters such as slope.
Installation
Or add the dependency directly:
[]
= "0.1"
Enable Rayon-accelerated cost-field construction with:
= { = "0.1", = ["parallel"] }
Quick Start
use ;
let cost = uniform;
let fmm = solve.unwrap;
let arrival = fmm.distance;
assert!;
let routed = solve.unwrap;
let path = routed.path_to.unwrap;
assert_eq!;
use Array2;
use ;
let dem = from_shape_fn;
let config = hiking.unwrap;
let result = solve.unwrap;
let path = result.path_to.unwrap;
assert!;
Choosing an API
Use top-level solve / solve_to when you want a continuous-style
arrival-time field, isochrones, or front propagation. FMM reduces grid
direction bias, but path_to is an upwind backtrace through the field, not an
exact discrete shortest path.
Use graph::solve / graph::solve_to when the route itself is primary. It is
exact for the crate's 8-neighbor graph model with endpoint-averaged edge costs.
Use terrain::solve / terrain::solve_to for graph routing over a DEM. It
uses 3D surface edge distances, optional scalar cost multipliers, and validated
TerrainConfig slope factors.
Assumptions
All APIs use (row, col) grid coordinates. Top-level FMM and graph use unit
grid spacing. Terrain routing uses TerrainConfig::cell_size() for horizontal
map units; DEM elevations should use compatible vertical units if surface
distance and slope penalties should be physically meaningful.
CostField values must be finite and non-negative. Zero marks an impassable
cell. Large finite costs are accepted, but solvers reject non-finite accumulated
distances.
solve_to stops once the target is finalized. The returned distance field may
be incomplete; unfinished cells are reported as f64::INFINITY.
Graph and terrain routing allow diagonal moves. Diagonal edges only require the two endpoint cells to be traversable, so they may pass between blocked orthogonal neighbors; no extra corner-cutting rule is applied.
Terrain DEM nodata policy: non-finite elevations (NaN, +inf, -inf) are
barriers. Routes never enter them, and source/early-target cells must have
finite elevation.
GeoTIFF Workflow
The intended geospatial pipeline is:
geotiff-rust -> ndarray DEM/cost rasters -> terrand -> eikonal -> geotiff-rust
Read a projected, regular-grid DEM with geotiff-reader, preserving transform,
cell size, CRS, and nodata metadata outside eikonal. Convert nodata cells to
non-finite DEM elevations or zero-valued CostField cells. Use terrand to
derive slope or other terrain rasters, then build costs with
CostField::from_slope or pass the DEM directly to terrain. Write distance,
isochrone, or route outputs with geotiff-writer using the original raster
metadata.