Skip to main content

kcl_lib/std/
axis_or_reference.rs

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