use crate::consts::{DEG_TO_RAD, M_PI};
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct UnitDef {
pub id: &'static str,
pub to_meter: &'static str,
pub name: &'static str,
pub factor: f64,
}
pub static LINEAR_UNITS: &[UnitDef] = &[
UnitDef {
id: "km",
to_meter: "1000",
name: "Kilometer",
factor: 1000.0,
},
UnitDef {
id: "m",
to_meter: "1",
name: "Meter",
factor: 1.0,
},
UnitDef {
id: "dm",
to_meter: "1/10",
name: "Decimeter",
factor: 0.1,
},
UnitDef {
id: "cm",
to_meter: "1/100",
name: "Centimeter",
factor: 0.01,
},
UnitDef {
id: "mm",
to_meter: "1/1000",
name: "Millimeter",
factor: 0.001,
},
UnitDef {
id: "kmi",
to_meter: "1852",
name: "International Nautical Mile",
factor: 1852.0,
},
UnitDef {
id: "in",
to_meter: "0.0254",
name: "International Inch",
factor: 0.0254,
},
UnitDef {
id: "ft",
to_meter: "0.3048",
name: "International Foot",
factor: 0.3048,
},
UnitDef {
id: "yd",
to_meter: "0.9144",
name: "International Yard",
factor: 0.9144,
},
UnitDef {
id: "mi",
to_meter: "1609.344",
name: "International Statute Mile",
factor: 1609.344,
},
UnitDef {
id: "fath",
to_meter: "1.8288",
name: "International Fathom",
factor: 1.8288,
},
UnitDef {
id: "ch",
to_meter: "20.1168",
name: "International Chain",
factor: 20.1168,
},
UnitDef {
id: "link",
to_meter: "0.201168",
name: "International Link",
factor: 0.201168,
},
UnitDef {
id: "us-in",
to_meter: "1/39.37",
name: "U.S. Surveyor's Inch",
factor: 100.0 / 3937.0,
},
UnitDef {
id: "us-ft",
to_meter: "0.304800609601219",
name: "U.S. Surveyor's Foot",
factor: 1200.0 / 3937.0,
},
UnitDef {
id: "us-yd",
to_meter: "0.914401828803658",
name: "U.S. Surveyor's Yard",
factor: 3600.0 / 3937.0,
},
UnitDef {
id: "us-ch",
to_meter: "20.11684023368047",
name: "U.S. Surveyor's Chain",
factor: 79200.0 / 3937.0,
},
UnitDef {
id: "us-mi",
to_meter: "1609.347218694437",
name: "U.S. Surveyor's Statute Mile",
factor: 6336000.0 / 3937.0,
},
UnitDef {
id: "ind-yd",
to_meter: "0.91439523",
name: "Indian Yard",
factor: 0.91439523,
},
UnitDef {
id: "ind-ft",
to_meter: "0.30479841",
name: "Indian Foot",
factor: 0.30479841,
},
UnitDef {
id: "ind-ch",
to_meter: "20.11669506",
name: "Indian Chain",
factor: 20.11669506,
},
];
pub static ANGULAR_UNITS: &[UnitDef] = &[
UnitDef {
id: "rad",
to_meter: "1.0",
name: "Radian",
factor: 1.0,
},
UnitDef {
id: "deg",
to_meter: "0.017453292519943296",
name: "Degree",
factor: DEG_TO_RAD,
},
UnitDef {
id: "grad",
to_meter: "0.015707963267948967",
name: "Grad",
factor: M_PI / 200.0,
},
];
pub fn find_linear_unit(id: &str) -> Option<&'static UnitDef> {
LINEAR_UNITS.iter().find(|u| u.id == id)
}
pub fn find_angular_unit(id: &str) -> Option<&'static UnitDef> {
ANGULAR_UNITS.iter().find(|u| u.id == id)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn linear_unit_ft_factor() {
assert_eq!(find_linear_unit("ft").map(|u| u.factor), Some(0.3048));
}
#[test]
fn linear_unit_us_ft_factor() {
assert!((find_linear_unit("us-ft").expect("us-ft").factor - 0.3048006096).abs() < 1e-9);
}
#[test]
fn linear_unit_meter_factor() {
assert_eq!(find_linear_unit("m").map(|u| u.factor), Some(1.0));
}
#[test]
fn angular_unit_deg_factor() {
assert_eq!(find_angular_unit("deg").map(|u| u.factor), Some(DEG_TO_RAD));
}
#[test]
fn angular_unit_rad_factor() {
assert_eq!(find_angular_unit("rad").map(|u| u.factor), Some(1.0));
}
#[test]
fn linear_unit_unknown_is_none() {
assert!(find_linear_unit("nope").is_none());
}
#[test]
fn table_lengths() {
assert_eq!(LINEAR_UNITS.len(), 21);
assert_eq!(ANGULAR_UNITS.len(), 3);
}
#[test]
fn angular_unit_grad_factor() {
assert!(
(find_angular_unit("grad").expect("grad").factor - 0.015707963267948967).abs() < 1e-15
);
}
}