Skip to main content

kcl_lib/std/
axis_or_reference.rs

1//! Types for referencing an axis or edge.
2
3use super::args::TyF64;
4use crate::KclError;
5use crate::errors::KclErrorDetails;
6use crate::execution::Plane;
7use crate::execution::Segment;
8use crate::execution::SegmentKind;
9use crate::execution::Sketch;
10use crate::execution::Solid;
11use crate::execution::TagIdentifier;
12use crate::std::fillet::EdgeReference;
13use crate::std::sketch::FaceTag;
14
15/// A 2D axis or tagged edge.
16#[derive(Debug, Clone, PartialEq)]
17pub enum Axis2dOrEdgeReference {
18    /// 2D axis and origin.
19    Axis { direction: [TyF64; 2], origin: [TyF64; 2] },
20    /// Tagged edge.
21    Edge(EdgeReference),
22}
23
24/// A 3D mirror target.
25#[derive(Debug, Clone, PartialEq)]
26pub enum MirrorAcross3d {
27    /// 3D axis and origin.
28    Axis {
29        direction: Box<[TyF64; 3]>,
30        origin: Box<[TyF64; 3]>,
31    },
32    /// Tagged edge.
33    Edge(Box<EdgeReference>),
34    /// A plane.
35    Plane(Box<Plane>),
36}
37
38impl Axis2dOrEdgeReference {
39    /// Use a sketch-solve segment by finding its engine ID.
40    pub fn from_segment(segment: &Segment) -> Result<Self, KclError> {
41        match &segment.kind {
42            SegmentKind::Line { .. } => Ok(Self::Edge(EdgeReference::Uuid(segment.id))),
43            SegmentKind::Point { .. } => Err(KclError::new_type(KclErrorDetails {
44                source_ranges: segment.meta.iter().map(|meta| meta.source_range).collect(),
45                backtrace: Default::default(),
46                message: "Cannot use a point as an axis".to_owned(),
47            })),
48            SegmentKind::Arc { .. } => Err(KclError::new_type(KclErrorDetails {
49                source_ranges: segment.meta.iter().map(|meta| meta.source_range).collect(),
50                backtrace: Default::default(),
51                message: "Cannot use an arc as an axis".to_owned(),
52            })),
53            SegmentKind::Circle { .. } => Err(KclError::new_type(KclErrorDetails {
54                source_ranges: segment.meta.iter().map(|meta| meta.source_range).collect(),
55                backtrace: Default::default(),
56                message: "Cannot use a circle as an axis".to_owned(),
57            })),
58            SegmentKind::ControlPointSpline { .. } => Err(KclError::new_type(KclErrorDetails {
59                source_ranges: segment.meta.iter().map(|meta| meta.source_range).collect(),
60                backtrace: Default::default(),
61                message: "Cannot use a control point spline as an axis".to_owned(),
62            })),
63        }
64    }
65}
66
67impl MirrorAcross3d {
68    /// Use a sketch-solve segment by finding its engine ID.
69    pub fn from_segment(segment: &Segment) -> Result<Self, KclError> {
70        match &segment.kind {
71            SegmentKind::Line { .. } => Ok(Self::Edge(Box::new(EdgeReference::Uuid(segment.id)))),
72            SegmentKind::Point { .. } => Err(KclError::new_type(KclErrorDetails {
73                source_ranges: segment.meta.iter().map(|meta| meta.source_range).collect(),
74                backtrace: Default::default(),
75                message: "Cannot use a point as an axis".to_owned(),
76            })),
77            SegmentKind::Arc { .. } => Err(KclError::new_type(KclErrorDetails {
78                source_ranges: segment.meta.iter().map(|meta| meta.source_range).collect(),
79                backtrace: Default::default(),
80                message: "Cannot use an arc as an axis".to_owned(),
81            })),
82            SegmentKind::Circle { .. } => Err(KclError::new_type(KclErrorDetails {
83                source_ranges: segment.meta.iter().map(|meta| meta.source_range).collect(),
84                backtrace: Default::default(),
85                message: "Cannot use a circle as an axis".to_owned(),
86            })),
87            SegmentKind::ControlPointSpline { .. } => Err(KclError::new_type(KclErrorDetails {
88                source_ranges: segment.meta.iter().map(|meta| meta.source_range).collect(),
89                backtrace: Default::default(),
90                message: "Cannot use a control point spline as an axis".to_owned(),
91            })),
92        }
93    }
94}
95
96/// A 3D axis or tagged edge.
97#[allow(clippy::large_enum_variant)]
98#[derive(Debug, Clone, PartialEq)]
99pub enum Axis3dOrEdgeReference {
100    /// 3D axis and origin.
101    Axis { direction: [TyF64; 3], origin: [TyF64; 3] },
102    /// Tagged edge.
103    Edge(EdgeReference),
104}
105
106impl Axis3dOrEdgeReference {
107    /// Use a sketch-solve segment by finding its engine ID.
108    pub fn from_segment(segment: &Segment) -> Result<Self, KclError> {
109        match &segment.kind {
110            SegmentKind::Line { .. } => Ok(Self::Edge(EdgeReference::Uuid(segment.id))),
111            SegmentKind::Point { .. } => Err(KclError::new_type(KclErrorDetails {
112                source_ranges: segment.meta.iter().map(|meta| meta.source_range).collect(),
113                backtrace: Default::default(),
114                message: "Cannot use a point as an axis".to_owned(),
115            })),
116            SegmentKind::Arc { .. } => Err(KclError::new_type(KclErrorDetails {
117                source_ranges: segment.meta.iter().map(|meta| meta.source_range).collect(),
118                backtrace: Default::default(),
119                message: "Cannot use an arc as an axis".to_owned(),
120            })),
121            SegmentKind::Circle { .. } => Err(KclError::new_type(KclErrorDetails {
122                source_ranges: segment.meta.iter().map(|meta| meta.source_range).collect(),
123                backtrace: Default::default(),
124                message: "Cannot use a circle as an axis".to_owned(),
125            })),
126            SegmentKind::ControlPointSpline { .. } => Err(KclError::new_type(KclErrorDetails {
127                source_ranges: segment.meta.iter().map(|meta| meta.source_range).collect(),
128                backtrace: Default::default(),
129                message: "Cannot use a control point spline as an axis".to_owned(),
130            })),
131        }
132    }
133}
134
135/// A 3D point or tagged edge.
136#[allow(clippy::large_enum_variant)]
137#[derive(Debug, Clone, PartialEq)]
138pub enum Point3dOrEdgeReference {
139    /// 3D point and origin.
140    Point([TyF64; 3]),
141    /// Tagged edge.
142    Edge(EdgeReference),
143}
144
145impl Point3dOrEdgeReference {
146    /// Use a sketch-solve segment by finding its engine ID.
147    pub fn from_segment(segment: &Segment) -> Result<Self, KclError> {
148        match &segment.kind {
149            SegmentKind::Line { .. } => Ok(Self::Edge(EdgeReference::Uuid(segment.id))),
150            SegmentKind::Point { position, .. } => Ok(Self::Point([
151                position[0].clone(),
152                position[1].clone(),
153                TyF64::count(0.0),
154            ])),
155            SegmentKind::Arc { .. } => Err(KclError::new_type(KclErrorDetails {
156                source_ranges: segment.meta.iter().map(|meta| meta.source_range).collect(),
157                backtrace: Default::default(),
158                message: "Cannot use an arc as a 3D point or edge reference".to_owned(),
159            })),
160            SegmentKind::Circle { .. } => Err(KclError::new_type(KclErrorDetails {
161                source_ranges: segment.meta.iter().map(|meta| meta.source_range).collect(),
162                backtrace: Default::default(),
163                message: "Cannot use a circle as a 3D point or edge reference".to_owned(),
164            })),
165            SegmentKind::ControlPointSpline { .. } => Err(KclError::new_type(KclErrorDetails {
166                source_ranges: segment.meta.iter().map(|meta| meta.source_range).collect(),
167                backtrace: Default::default(),
168                message: "Cannot use a control point spline as a 3D point or edge reference".to_owned(),
169            })),
170        }
171    }
172}
173
174/// A 2D axis or a raw point2d.
175#[derive(Debug, Clone, PartialEq)]
176pub enum Axis2dOrPoint2d {
177    /// 2D axis and origin.
178    Axis { direction: [TyF64; 2], origin: [TyF64; 2] },
179    /// Raw point2d.
180    Point([TyF64; 2]),
181}
182
183impl Axis2dOrPoint2d {
184    /// Convert to a 2D axis.
185    pub fn to_point2d(&self) -> [TyF64; 2] {
186        match self {
187            Axis2dOrPoint2d::Axis { direction, origin: _ } => direction.clone(),
188            Axis2dOrPoint2d::Point(point) => point.clone(),
189        }
190    }
191}
192
193/// A 3D axis or a raw point3d.
194#[derive(Debug, Clone, PartialEq)]
195pub enum Axis3dOrPoint3d {
196    /// 3D axis and origin.
197    Axis { direction: [TyF64; 3], origin: [TyF64; 3] },
198    /// Raw point3d.
199    Point([TyF64; 3]),
200}
201
202impl Axis3dOrPoint3d {
203    /// Convert to a 3D axis.
204    pub fn to_point3d(&self) -> [TyF64; 3] {
205        match self {
206            Axis3dOrPoint3d::Axis { direction, origin: _ } => direction.clone(),
207            Axis3dOrPoint3d::Point(point) => point.clone(),
208        }
209    }
210
211    pub fn axis_origin(&self) -> Option<[TyF64; 3]> {
212        match self {
213            Axis3dOrPoint3d::Axis { origin, .. } => Some(origin.clone()),
214            Axis3dOrPoint3d::Point(..) => None,
215        }
216    }
217}
218
219/// A raw point3d, 3D axis, Edge, Face, Solid or Tag.
220#[allow(clippy::large_enum_variant)]
221#[derive(Debug, Clone, PartialEq)]
222pub enum Point3dAxis3dOrGeometryReference {
223    /// Raw point3d.
224    Point([TyF64; 3]),
225    /// 3D axis and origin.
226    Axis { direction: [TyF64; 3], origin: [TyF64; 3] },
227    /// Plane.
228    Plane(Box<Plane>),
229    /// Edge Reference.
230    Edge(EdgeReference),
231    /// Face.
232    Face(FaceTag),
233    /// Sketch.
234    Sketch(Box<Sketch>),
235    /// Solid.
236    Solid(Box<Solid>),
237    /// Tagged edge or face.
238    TaggedEdgeOrFace(TagIdentifier),
239}