const TYPICAL_MM: (f64, f64) = (3.0, 200.0);
const BELIEVABLE_MM: (f64, f64) = (1.0, 2000.0);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum MeshUnit {
#[default]
Millimetre,
Centimetre,
Metre,
Inch,
Micrometre,
}
impl MeshUnit {
pub const ALL: [Self; 5] = [
Self::Millimetre,
Self::Centimetre,
Self::Metre,
Self::Inch,
Self::Micrometre,
];
pub fn from_index(index: i32) -> Self {
usize::try_from(index)
.ok()
.and_then(|i| Self::ALL.get(i).copied())
.unwrap_or_default()
}
pub const fn factor_to_mm(self) -> f64 {
match self {
Self::Millimetre => 1.0,
Self::Centimetre => 10.0,
Self::Metre => 1000.0,
Self::Inch => 25.4,
Self::Micrometre => 0.001,
}
}
pub const fn label(self) -> &'static str {
match self {
Self::Millimetre => "mm",
Self::Centimetre => "cm",
Self::Metre => "m",
Self::Inch => "inch",
Self::Micrometre => "\u{b5}m",
}
}
pub const fn plural(self) -> &'static str {
match self {
Self::Millimetre => "millimetres",
Self::Centimetre => "centimetres",
Self::Metre => "metres",
Self::Inch => "inches",
Self::Micrometre => "micrometres",
}
}
pub fn suggest(raw_largest: f64, current: Self) -> Option<Self> {
if !(raw_largest.is_finite() && raw_largest > 0.0) {
return None;
}
[TYPICAL_MM, BELIEVABLE_MM]
.into_iter()
.find_map(|(lo, hi)| {
Self::ALL.into_iter().find(|&unit| {
unit != current && (lo..=hi).contains(&(raw_largest * unit.factor_to_mm()))
})
})
}
}