1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
//! **eikonal** — Fast Marching Method and grid routing utilities.
//!
//! The crate-level [`solve`] APIs solve the eikonal equation
//! `|∇T(x)| = C(x) = 1/F(x)` on 2D regular grids using a first-order upwind
//! Fast Marching Method. The [`graph`] module provides 8-neighbor Dijkstra
//! shortest paths for applications that need exact discrete graph paths, and
//! [`terrain`] builds on graph routing for DEM-aware path costs.
//!
//! # Core concepts
//!
//! | Type | Purpose |
//! |------|---------|
//! | [`CostField`] | Per-cell cost/slowness (`1 / speed`) |
//! | [`SolveResult`] | FMM arrival-time field + upwind backtrace |
//! | [`graph::SolveResult`] | 8-neighbor Dijkstra graph distances + shortest paths |
//! | [`TerrainResult`](terrain::TerrainResult) | Terrain-routing result with elevation profiles |
//! | [`TerrainConfig`](terrain::TerrainConfig) | Slope penalty configuration |
//!
//! # Quick start — eikonal / FMM
//!
//! ```
//! use ndarray::Array2;
//! use eikonal::{CostField, solve};
//!
//! let cost = CostField::uniform(50, 50);
//! let result = solve(&cost, (0, 0)).unwrap();
//!
//! // FMM arrival time to far corner
//! let d = result.distance()[[49, 49]];
//! assert!(d > 0.0);
//!
//! // Extract an upwind backtrace through the arrival-time field
//! let path = result.path_to(49, 49).unwrap();
//! assert_eq!(path.cells[0], (0, 0));
//! ```
//!
//! # Quick start — weighted grid shortest paths
//!
//! ```
//! use eikonal::{graph, CostField};
//!
//! let cost = CostField::uniform(50, 50);
//! let result = graph::solve(&cost, (0, 0)).unwrap();
//! let path = result.path_to(49, 49).unwrap();
//! assert_eq!(path.cells[0], (0, 0));
//! ```
//!
//! # Quick start — terrain routing
//!
//! ```
//! use ndarray::Array2;
//! use eikonal::terrain::{self, TerrainConfig};
//!
//! // A DEM with a hill in the center
//! let dem = Array2::from_shape_fn((50, 50), |(r, c)| {
//! let dr = r as f64 - 25.0;
//! let dc = c as f64 - 25.0;
//! 100.0 * (-(dr * dr + dc * dc) / 200.0).exp()
//! });
//!
//! let config = TerrainConfig::hiking(30.0).unwrap(); // 30m cells
//! let result = terrain::solve(&dem, config, None, (0, 0)).unwrap();
//! let path = result.path_to(49, 49).unwrap();
//!
//! assert!(path.surface_distance > path.projected_distance);
//! assert!(path.total_ascent > 0.0);
//! ```
//!
//! # Isochrones
//!
//! ```
//! use eikonal::{CostField, solve, isochrone};
//!
//! let cost = CostField::uniform(30, 30);
//! let result = solve(&cost, (15, 15)).unwrap();
//! let reachable = isochrone(result.distance(), 10.0);
//! ```
//!
//! # Parallelism
//!
//! Enable the `parallel` feature for Rayon-accelerated cost field construction:
//!
//! ```toml
//! [dependencies]
//! eikonal = { version = "0.1", features = ["parallel"] }
//! ```
//!
//! The FMM and graph solvers are inherently sequential priority-queue
//! algorithms. The `parallel` feature currently accelerates cost field
//! construction; isochrone extraction remains sequential.
pub use CostField;
pub use ;
pub use ;
pub use ;
pub use ;