Skip to main content

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