use crate::foundation::{AlgoError, BBox, Lattice, Result};
pub const FICTIONAL_ORIGIN: [f64; 2] = [431_000.0, 6_521_000.0];
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Georef {
pub east0: f64,
pub north0: f64,
}
impl Georef {
pub fn new(east0: f64, north0: f64) -> Result<Georef> {
if !(east0.is_finite() && north0.is_finite()) {
return Err(AlgoError::InvalidArgument(
"Georef: east0 and north0 must be finite".to_string(),
));
}
Ok(Georef { east0, north0 })
}
pub fn fictional() -> Georef {
Georef {
east0: FICTIONAL_ORIGIN[0],
north0: FICTIONAL_ORIGIN[1],
}
}
pub fn origin(&self) -> [f64; 2] {
[self.east0, self.north0]
}
pub fn lattice(&self, xinc: f64, yinc: f64, ncol: usize, nrow: usize) -> Lattice {
Lattice::regular(self.east0, self.north0, xinc, yinc, ncol, nrow)
}
pub fn place_point(&self, local: [f64; 2]) -> [f64; 2] {
[self.east0 + local[0], self.north0 + local[1]]
}
pub fn place_points(&self, locals: &[[f64; 2]]) -> Vec<[f64; 2]> {
locals.iter().map(|&p| self.place_point(p)).collect()
}
pub fn place_extent(&self, local: &BBox) -> BBox {
BBox {
xmin: self.east0 + local.xmin,
ymin: self.north0 + local.ymin,
xmax: self.east0 + local.xmax,
ymax: self.north0 + local.ymax,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn fictional_origin_places_lattice_in_world() {
let g = Georef::fictional();
assert_eq!(g.origin(), FICTIONAL_ORIGIN);
let lat = g.lattice(100.0, 100.0, 5, 7);
assert_eq!(lat.node_xy(0, 0), (431_000.0, 6_521_000.0));
assert_eq!(lat.ncol, 5);
assert_eq!(lat.nrow, 7);
let (x, y) = lat.node_xy(2, 3);
assert_eq!((x, y), (431_000.0 + 200.0, 6_521_000.0 + 300.0));
}
#[test]
fn point_and_extent_translate_by_origin() {
let g = Georef::new(431_000.0, 6_521_000.0).unwrap();
assert_eq!(g.place_point([12.0, 34.0]), [431_012.0, 6_521_034.0]);
let pts = g.place_points(&[[0.0, 0.0], [10.0, 20.0]]);
assert_eq!(
pts,
vec![[431_000.0, 6_521_000.0], [431_010.0, 6_521_020.0]]
);
let e = g.place_extent(&BBox {
xmin: 0.0,
ymin: 0.0,
xmax: 400.0,
ymax: 600.0,
});
assert_eq!(
e,
BBox {
xmin: 431_000.0,
ymin: 6_521_000.0,
xmax: 431_400.0,
ymax: 6_521_600.0,
}
);
}
#[test]
fn non_finite_origin_errors() {
assert!(Georef::new(f64::NAN, 0.0).is_err());
assert!(Georef::new(0.0, f64::INFINITY).is_err());
}
}