const VPU_TO_MM: f32 = (25.4 * 1.0625) / 50.0;
const VPU_TO_CM: f32 = VPU_TO_MM / 10.0;
const VPU_TO_M: f32 = VPU_TO_MM / 1000.0;
#[inline]
pub fn vpu_to_mm(vpu: f32) -> f32 {
vpu * VPU_TO_MM
}
#[inline]
pub fn vpu_to_cm(vpu: f32) -> f32 {
vpu * VPU_TO_CM
}
#[inline]
pub fn vpu_to_m(vpu: f32) -> f32 {
vpu * VPU_TO_M
}
#[inline]
pub fn mm_to_vpu(mm: f32) -> f32 {
mm / VPU_TO_MM
}
#[inline]
pub fn cm_to_vpu(cm: f32) -> f32 {
cm / VPU_TO_CM
}
#[inline]
pub fn m_to_vpu(m: f32) -> f32 {
m / VPU_TO_M
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub enum ExportUnits {
#[default]
Vpu,
Mm,
Cm,
M,
}
impl ExportUnits {
#[inline]
pub fn scale(self) -> f32 {
match self {
ExportUnits::Vpu => 1.0,
ExportUnits::Mm => VPU_TO_MM,
ExportUnits::Cm => VPU_TO_CM,
ExportUnits::M => VPU_TO_M,
}
}
}
#[inline]
pub fn vpu_to_units(vpu: f32, units: ExportUnits) -> f32 {
vpu * units.scale()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_vpu_to_mm() {
let mm = vpu_to_mm(50.0);
assert!(
(mm - 26.9875).abs() < 0.001,
"50 VPU should be ~26.99 mm, got {}",
mm
);
}
#[test]
fn test_vpu_to_m() {
let m = vpu_to_m(1000.0);
assert!(
(m - 0.53975).abs() < 0.001,
"1000 VPU should be ~0.54 m, got {}",
m
);
}
#[test]
fn test_round_trip_mm() {
let original = 100.0;
let converted = mm_to_vpu(vpu_to_mm(original));
assert!(
(converted - original).abs() < 0.001,
"Round trip failed: {} -> {}",
original,
converted
);
}
#[test]
fn test_round_trip_cm() {
let original = 100.0;
let converted = cm_to_vpu(vpu_to_cm(original));
assert!(
(converted - original).abs() < 0.001,
"Round trip failed: {} -> {}",
original,
converted
);
}
#[test]
fn test_round_trip_m() {
let original = 100.0;
let converted = m_to_vpu(vpu_to_m(original));
assert!(
(converted - original).abs() < 0.001,
"Round trip failed: {} -> {}",
original,
converted
);
}
}