1use anyhow::Result;
4use kcmc::length_unit::LengthUnit;
5use kittycad_modeling_cmds::{self as kcmc};
6use schemars::JsonSchema;
7use serde::{Deserialize, Serialize};
8
9use crate::{errors::KclError, std::fillet::EdgeReference};
10
11#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
13#[ts(export)]
14#[serde(untagged)]
15pub enum Axis2dOrEdgeReference {
16 Axis(AxisAndOrigin2d),
18 Edge(EdgeReference),
20}
21
22#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
24#[ts(export)]
25#[serde(rename_all = "camelCase")]
26pub enum AxisAndOrigin2d {
27 #[serde(rename = "X", alias = "x")]
29 X,
30 #[serde(rename = "Y", alias = "y")]
32 Y,
33 #[serde(rename = "-X", alias = "-x")]
35 NegX,
36 #[serde(rename = "-Y", alias = "-y")]
38 NegY,
39 Custom {
40 axis: [f64; 2],
42 origin: [f64; 2],
44 },
45}
46
47impl AxisAndOrigin2d {
48 pub fn axis_and_origin(&self) -> Result<(kcmc::shared::Point3d<f64>, kcmc::shared::Point3d<LengthUnit>), KclError> {
50 let (axis, origin) = match self {
51 AxisAndOrigin2d::X => ([1.0, 0.0, 0.0], [0.0, 0.0, 0.0]),
52 AxisAndOrigin2d::Y => ([0.0, 1.0, 0.0], [0.0, 0.0, 0.0]),
53 AxisAndOrigin2d::NegX => ([-1.0, 0.0, 0.0], [0.0, 0.0, 0.0]),
54 AxisAndOrigin2d::NegY => ([0.0, -1.0, 0.0], [0.0, 0.0, 0.0]),
55 AxisAndOrigin2d::Custom { axis, origin } => ([axis[0], axis[1], 0.0], [origin[0], origin[1], 0.0]),
56 };
57
58 Ok((
59 kcmc::shared::Point3d {
60 x: axis[0],
61 y: axis[1],
62 z: axis[2],
63 },
64 kcmc::shared::Point3d {
65 x: LengthUnit(origin[0]),
66 y: LengthUnit(origin[1]),
67 z: LengthUnit(origin[2]),
68 },
69 ))
70 }
71}
72
73#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
75#[ts(export)]
76#[serde(untagged)]
77pub enum Axis3dOrEdgeReference {
78 Axis(AxisAndOrigin3d),
80 Edge(EdgeReference),
82}
83
84#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
86#[ts(export)]
87#[serde(rename_all = "camelCase")]
88pub enum AxisAndOrigin3d {
89 #[serde(rename = "X", alias = "x")]
91 X,
92 #[serde(rename = "Y", alias = "y")]
94 Y,
95 #[serde(rename = "Z", alias = "z")]
97 Z,
98 #[serde(rename = "-X", alias = "-x")]
100 NegX,
101 #[serde(rename = "-Y", alias = "-y")]
103 NegY,
104 #[serde(rename = "-Z", alias = "-z")]
106 NegZ,
107 Custom {
108 axis: [f64; 3],
110 origin: [f64; 3],
112 },
113}
114
115impl AxisAndOrigin3d {
116 pub fn axis_and_origin(&self) -> Result<(kcmc::shared::Point3d<f64>, kcmc::shared::Point3d<LengthUnit>), KclError> {
118 let (axis, origin) = match self {
119 AxisAndOrigin3d::X => ([1.0, 0.0, 0.0], [0.0, 0.0, 0.0]),
120 AxisAndOrigin3d::Y => ([0.0, 1.0, 0.0], [0.0, 0.0, 0.0]),
121 AxisAndOrigin3d::Z => ([0.0, 0.0, 1.0], [0.0, 0.0, 0.0]),
122 AxisAndOrigin3d::NegX => ([-1.0, 0.0, 0.0], [0.0, 0.0, 0.0]),
123 AxisAndOrigin3d::NegY => ([0.0, -1.0, 0.0], [0.0, 0.0, 0.0]),
124 AxisAndOrigin3d::NegZ => ([0.0, 0.0, -1.0], [0.0, 0.0, 0.0]),
125 AxisAndOrigin3d::Custom { axis, origin } => {
126 ([axis[0], axis[1], axis[2]], [origin[0], origin[1], origin[2]])
127 }
128 };
129
130 Ok((
131 kcmc::shared::Point3d {
132 x: axis[0],
133 y: axis[1],
134 z: axis[2],
135 },
136 kcmc::shared::Point3d {
137 x: LengthUnit(origin[0]),
138 y: LengthUnit(origin[1]),
139 z: LengthUnit(origin[2]),
140 },
141 ))
142 }
143}
144
145#[cfg(test)]
146mod tests {
147
148 use pretty_assertions::assert_eq;
149
150 use crate::std::axis_or_reference::{
151 Axis2dOrEdgeReference, Axis3dOrEdgeReference, AxisAndOrigin2d, AxisAndOrigin3d,
152 };
153
154 #[test]
155 fn test_deserialize_revolve_axis_2d() {
156 let data = Axis2dOrEdgeReference::Axis(AxisAndOrigin2d::X);
157 let mut str_json = serde_json::to_string(&data).unwrap();
158 assert_eq!(str_json, "\"X\"");
159
160 str_json = "\"Y\"".to_string();
161 let data: Axis2dOrEdgeReference = serde_json::from_str(&str_json).unwrap();
162 assert_eq!(data, Axis2dOrEdgeReference::Axis(AxisAndOrigin2d::Y));
163
164 str_json = "\"-Y\"".to_string();
165 let data: Axis2dOrEdgeReference = serde_json::from_str(&str_json).unwrap();
166 assert_eq!(data, Axis2dOrEdgeReference::Axis(AxisAndOrigin2d::NegY));
167
168 str_json = "\"-x\"".to_string();
169 let data: Axis2dOrEdgeReference = serde_json::from_str(&str_json).unwrap();
170 assert_eq!(data, Axis2dOrEdgeReference::Axis(AxisAndOrigin2d::NegX));
171
172 let data = Axis2dOrEdgeReference::Axis(AxisAndOrigin2d::Custom {
173 axis: [0.0, -1.0],
174 origin: [1.0, 0.0],
175 });
176 str_json = serde_json::to_string(&data).unwrap();
177 assert_eq!(str_json, r#"{"custom":{"axis":[0.0,-1.0],"origin":[1.0,0.0]}}"#);
178
179 str_json = r#"{"custom": {"axis": [0,-1], "origin": [1,2.0]}}"#.to_string();
180 let data: Axis2dOrEdgeReference = serde_json::from_str(&str_json).unwrap();
181 assert_eq!(
182 data,
183 Axis2dOrEdgeReference::Axis(AxisAndOrigin2d::Custom {
184 axis: [0.0, -1.0],
185 origin: [1.0, 2.0]
186 })
187 );
188 }
189
190 #[test]
191 fn test_deserialize_revolve_axis_3d() {
192 let data = Axis3dOrEdgeReference::Axis(AxisAndOrigin3d::X);
193 let mut str_json = serde_json::to_string(&data).unwrap();
194 assert_eq!(str_json, "\"X\"");
195
196 str_json = "\"Y\"".to_string();
197 let data: Axis3dOrEdgeReference = serde_json::from_str(&str_json).unwrap();
198 assert_eq!(data, Axis3dOrEdgeReference::Axis(AxisAndOrigin3d::Y));
199
200 str_json = "\"Z\"".to_string();
201 let data: Axis3dOrEdgeReference = serde_json::from_str(&str_json).unwrap();
202 assert_eq!(data, Axis3dOrEdgeReference::Axis(AxisAndOrigin3d::Z));
203
204 str_json = "\"-Y\"".to_string();
205 let data: Axis3dOrEdgeReference = serde_json::from_str(&str_json).unwrap();
206 assert_eq!(data, Axis3dOrEdgeReference::Axis(AxisAndOrigin3d::NegY));
207
208 str_json = "\"-x\"".to_string();
209 let data: Axis3dOrEdgeReference = serde_json::from_str(&str_json).unwrap();
210 assert_eq!(data, Axis3dOrEdgeReference::Axis(AxisAndOrigin3d::NegX));
211
212 str_json = "\"-z\"".to_string();
213 let data: Axis3dOrEdgeReference = serde_json::from_str(&str_json).unwrap();
214 assert_eq!(data, Axis3dOrEdgeReference::Axis(AxisAndOrigin3d::NegZ));
215
216 let data = Axis3dOrEdgeReference::Axis(AxisAndOrigin3d::Custom {
217 axis: [0.0, -1.0, 0.0],
218 origin: [1.0, 0.0, 0.0],
219 });
220 str_json = serde_json::to_string(&data).unwrap();
221 assert_eq!(str_json, r#"{"custom":{"axis":[0.0,-1.0,0.0],"origin":[1.0,0.0,0.0]}}"#);
222
223 str_json = r#"{"custom": {"axis": [0,-1,0], "origin": [1,2.0,0]}}"#.to_string();
224 let data: Axis3dOrEdgeReference = serde_json::from_str(&str_json).unwrap();
225 assert_eq!(
226 data,
227 Axis3dOrEdgeReference::Axis(AxisAndOrigin3d::Custom {
228 axis: [0.0, -1.0, 0.0],
229 origin: [1.0, 2.0, 0.0]
230 })
231 );
232 }
233}