use nalgebra::Vector3;
use winds_engine::{geotiff_grid, ConstantField, Monitor, TerrainFlowField, WindField};
const FIRING_LAT: f64 = 47.403947;
const FIRING_LON: f64 = -92.995347;
const TARGET_LAT: f64 = 47.407748;
const TARGET_LON: f64 = -92.990340;
fn lane_geometry() -> ((f64, f64), (f64, f64), f64) {
const R: f64 = 6_371_000.0;
let latm = ((FIRING_LAT + TARGET_LAT) / 2.0).to_radians();
let east = (TARGET_LON - FIRING_LON).to_radians() * R * latm.cos();
let north = (TARGET_LAT - FIRING_LAT).to_radians() * R;
let length = (east * east + north * north).sqrt();
let (ex, nx) = (east / length, north / length);
((FIRING_LON, FIRING_LAT), (ex, nx), length)
}
fn web_mercator(lat: f64, lon: f64) -> (f64, f64) {
let x = lon * 20_037_508.34 / 180.0;
let y = (lat.to_radians() / 2.0 + std::f64::consts::FRAC_PI_4)
.tan()
.ln()
* 20_037_508.34
/ std::f64::consts::PI;
(x, y)
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let dem = std::fs::read(concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/data/hibbing_lane.tif"
))?;
let grid = geotiff_grid(&dem)?.downsample(30.0)?;
println!(
"down-sampled grid {}x{} @ {:.1} m",
grid.ncols, grid.nrows, grid.dx
);
let ((f_lon, f_lat), (_ex, _nx), length) = lane_geometry();
let (x0, y0) = web_mercator(f_lat, f_lon);
let (x1, y1) = web_mercator(TARGET_LAT, TARGET_LON);
println!("lane length {:.1} m", length);
let readings: [(f64, f64, f64); 4] = [
(0.25, 3.1, 240.0),
(0.40, 3.8, 225.0),
(0.60, 2.9, 250.0),
(0.75, 3.5, 220.0),
];
let mut monitors = Vec::new();
for &(t, speed, from_north_deg) in &readings {
let x = x0 + (x1 - x0) * t;
let z = y0 + (y1 - y0) * t;
let toward = (from_north_deg + 180.0_f64).to_radians();
let east_mps = speed * toward.sin();
let north_mps = speed * toward.cos();
let d = (north_mps.atan2(east_mps).to_degrees() - 180.0).rem_euclid(360.0);
monitors.push(Monitor::at(x, z, speed, d));
}
let base = ConstantField(Vector3::new(6.0, 0.0, 0.0));
let field = TerrainFlowField::adjust(
grid.clone(),
&base,
&monitors,
&[10.0, 50.0, 150.0, 400.0],
800.0,
200.0,
300.0,
)?;
let mut digest = String::new();
for (label, t) in [
("firing", 0.00),
("25%", 0.25),
("mid", 0.50),
("75%", 0.75),
("target", 1.00),
] {
let x = x0 + (x1 - x0) * t;
let z = y0 + (y1 - y0) * t;
let h = grid.height_at(x, z) + 10.0;
let w = field.wind(0.0, Vector3::new(x, h, z));
let (wx, wz) = (w.x, w.z);
let speed = (wx * wx + wz * wz).sqrt();
println!("{label:>6} {wx:+.3} {wz:+.3} {speed:.2} m/s");
digest.push_str(&format!("{t:.2}:{wx:.6}:{wz:.6};"));
}
println!("\nDIGEST {digest}");
Ok(())
}