mod band_lu;
mod convergent;
mod gridder;
mod idw;
pub mod kriging;
mod min_curvature;
mod mincurv_operator;
mod nearest;
mod resample;
pub use convergent::ConvergentGridder;
pub use gridder::Gridder;
pub use mincurv_operator::MinCurvatureOperator;
pub use kriging::{
AnisotropicVariogram, OrdinaryKriging, SpatialVariogram, Variogram, VariogramModel,
};
pub use resample::{resample, ResampleMethod};
use crate::foundation::{AlgoError, Lattice, Result};
use ndarray::Array2;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum Conditioning {
#[default]
NearestNode,
Bilinear,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum GridMethod {
Nearest,
InverseDistance,
MinimumCurvature,
}
pub fn grid(coords: &[[f64; 3]], lattice: &Lattice, method: GridMethod) -> Result<Array2<f64>> {
if coords.is_empty() {
return Err(AlgoError::EmptyInput("grid: no points to grid"));
}
Ok(match method {
GridMethod::Nearest => nearest::grid_nearest(coords, lattice),
GridMethod::InverseDistance => idw::grid_idw(coords, lattice),
GridMethod::MinimumCurvature => {
min_curvature::grid_min_curvature(coords, lattice, None, Conditioning::NearestNode)
}
})
}
pub fn grid_min_curvature_seeded(
coords: &[[f64; 3]],
lattice: &Lattice,
seed: Option<&Array2<f64>>,
) -> Result<Array2<f64>> {
if coords.is_empty() {
return Err(AlgoError::EmptyInput(
"grid_min_curvature_seeded: no points to grid",
));
}
Ok(min_curvature::grid_min_curvature(
coords,
lattice,
seed,
Conditioning::NearestNode,
))
}
pub fn grid_min_curvature_conditioned(
coords: &[[f64; 3]],
lattice: &Lattice,
seed: Option<&Array2<f64>>,
conditioning: Conditioning,
) -> Result<Array2<f64>> {
if coords.is_empty() {
return Err(AlgoError::EmptyInput(
"grid_min_curvature_conditioned: no points to grid",
));
}
Ok(min_curvature::grid_min_curvature(
coords,
lattice,
seed,
conditioning,
))
}
#[cfg(test)]
mod tests {
use super::*;
use crate::foundation::Lattice;
#[test]
fn empty_input_errors() {
let g = Lattice::regular(0.0, 0.0, 1.0, 1.0, 4, 4);
assert!(matches!(
grid(&[], &g, GridMethod::Nearest),
Err(AlgoError::EmptyInput(_))
));
}
#[test]
fn seeded_empty_input_errors() {
let g = Lattice::regular(0.0, 0.0, 1.0, 1.0, 4, 4);
assert!(matches!(
grid_min_curvature_seeded(&[], &g, None),
Err(AlgoError::EmptyInput(_))
));
}
#[test]
fn seeded_none_equals_cold_grid() {
let g = Lattice::regular(0.0, 0.0, 1.0, 1.0, 8, 7);
let coords = [[1.0, 1.0, 3.0], [6.0, 5.0, 12.0], [3.0, 4.0, 7.0]];
let cold = grid(&coords, &g, GridMethod::MinimumCurvature).unwrap();
let seeded_none = grid_min_curvature_seeded(&coords, &g, None).unwrap();
assert_eq!(cold, seeded_none);
let warm = grid_min_curvature_seeded(&coords, &g, Some(&cold)).unwrap();
let maxd = warm
.iter()
.zip(cold.iter())
.map(|(w, c)| (w - c).abs())
.fold(0.0_f64, f64::max);
assert!(maxd < 1e-3, "warm vs cold max diff = {maxd}");
}
}