kittycad_modeling_cmds/
length_unit.rs

1//! A length unit is a type that converts a length value from one unit to another.
2//! In the case of the engine we will always convert to millimeters, since that is what the engine uses.
3
4use serde::{Deserialize, Serialize};
5
6use crate::shared::{Point2d, Point3d, Point4d};
7
8/// A length unit is wrapper around an f64 that represents a length in some unit.
9#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Serialize, Deserialize, Default)]
10#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
11#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
12pub struct LengthUnit(pub f64);
13
14impl LengthUnit {
15    /// Get the value of the length unit in millimeters.
16    /// This is how we convert for the engine.
17    pub fn to_millimeters(&self, from: crate::units::UnitLength) -> f64 {
18        from.convert_to(crate::units::UnitLength::Millimeters, self.0)
19    }
20
21    /// Get the value from millimeters to the length unit.
22    pub fn from_millimeters(&self, to: crate::units::UnitLength) -> LengthUnit {
23        LengthUnit(crate::units::UnitLength::Millimeters.convert_to(to, self.0))
24    }
25}
26
27impl Point3d<LengthUnit> {
28    /// Convert the point to millimeters.
29    pub fn to_millimeters(&self, from: crate::units::UnitLength) -> Point3d<f64> {
30        Point3d {
31            x: self.x.to_millimeters(from),
32            y: self.y.to_millimeters(from),
33            z: self.z.to_millimeters(from),
34        }
35    }
36}
37
38impl Point3d<f64> {
39    /// Convert the point from millimeters.
40    pub fn from_millimeters(&self, to: crate::units::UnitLength) -> Point3d<LengthUnit> {
41        Point3d {
42            x: crate::units::UnitLength::Millimeters.convert_to(to, self.x).into(),
43            y: crate::units::UnitLength::Millimeters.convert_to(to, self.y).into(),
44            z: crate::units::UnitLength::Millimeters.convert_to(to, self.z).into(),
45        }
46    }
47}
48
49impl Point2d<LengthUnit> {
50    /// Convert the point to millimeters.
51    pub fn to_millimeters(&self, from: crate::units::UnitLength) -> Point2d<f64> {
52        Point2d {
53            x: self.x.to_millimeters(from),
54            y: self.y.to_millimeters(from),
55        }
56    }
57}
58
59impl Point2d<f64> {
60    /// Convert the point from millimeters.
61    pub fn from_millimeters(&self, to: crate::units::UnitLength) -> Point2d<LengthUnit> {
62        Point2d {
63            x: crate::units::UnitLength::Millimeters.convert_to(to, self.x).into(),
64            y: crate::units::UnitLength::Millimeters.convert_to(to, self.y).into(),
65        }
66    }
67}
68
69impl Point4d<LengthUnit> {
70    /// Convert the point to millimeters.
71    pub fn to_millimeters(&self, from: crate::units::UnitLength) -> Point4d<f64> {
72        Point4d {
73            x: self.x.to_millimeters(from),
74            y: self.y.to_millimeters(from),
75            z: self.z.to_millimeters(from),
76            w: self.w.0,
77        }
78    }
79}
80
81impl Point4d<f64> {
82    /// Convert the point from millimeters.
83    pub fn from_millimeters(&self, to: crate::units::UnitLength) -> Point4d<LengthUnit> {
84        Point4d {
85            x: crate::units::UnitLength::Millimeters.convert_to(to, self.x).into(),
86            y: crate::units::UnitLength::Millimeters.convert_to(to, self.y).into(),
87            z: crate::units::UnitLength::Millimeters.convert_to(to, self.z).into(),
88            w: LengthUnit(self.w),
89        }
90    }
91}
92
93impl schemars::JsonSchema for LengthUnit {
94    fn schema_name() -> String {
95        "LengthUnit".to_string()
96    }
97
98    fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
99        <f64>::json_schema(gen)
100    }
101}
102
103impl From<f64> for LengthUnit {
104    fn from(value: f64) -> Self {
105        LengthUnit(value)
106    }
107}
108
109impl std::ops::Neg for LengthUnit {
110    type Output = Self;
111
112    fn neg(self) -> Self::Output {
113        LengthUnit(-self.0)
114    }
115}
116
117impl std::ops::Add for LengthUnit {
118    type Output = Self;
119
120    fn add(self, rhs: Self) -> Self::Output {
121        LengthUnit(self.0 + rhs.0)
122    }
123}
124
125impl std::ops::Sub for LengthUnit {
126    type Output = Self;
127
128    fn sub(self, rhs: Self) -> Self::Output {
129        LengthUnit(self.0 - rhs.0)
130    }
131}
132
133impl std::ops::Mul<f64> for LengthUnit {
134    type Output = Self;
135
136    fn mul(self, rhs: f64) -> Self::Output {
137        LengthUnit(self.0 * rhs)
138    }
139}
140
141impl std::ops::Div<f64> for LengthUnit {
142    type Output = Self;
143
144    fn div(self, rhs: f64) -> Self::Output {
145        LengthUnit(self.0 / rhs)
146    }
147}