1use crate::{instruction::InstructionKind, Destination, Instruction};
3use kittycad_execution_plan_macros::ExecutionPlanValue;
4use kittycad_execution_plan_traits::{Address, Value};
5use kittycad_modeling_cmds::shared::{Point2d, Point3d, Point4d};
6use serde::{Deserialize, Serialize};
7use uuid::Uuid;
8
9#[derive(Clone, ExecutionPlanValue, PartialEq, Debug, Deserialize, Serialize)]
11pub struct SketchGroup {
12 pub id: Uuid,
16 pub on: SketchSurface,
18 pub position: Point3d,
20 pub rotation: Point4d,
22 pub axes: Axes,
24 pub entity_id: Option<Uuid>,
26 pub path_first: BasePath,
28 pub path_rest: Vec<PathSegment>,
30}
31
32impl SketchGroup {
33 pub fn last_point(&self) -> Point2d<f64> {
36 self.get_last_path_segment().to
37 }
38
39 fn get_last_path_segment(&self) -> &BasePath {
41 match self.path_rest.last() {
42 Some(segment) => segment.get_base(),
43 None => &self.path_first,
44 }
45 }
46
47 pub fn path_id_offset() -> usize {
49 0
50 }
51 pub fn set_base_path(&self, sketch_group: Address, start_point: Address, tag: Option<Address>) -> Vec<Instruction> {
56 let base_path_addr = sketch_group
57 + self.id.into_parts().len()
58 + self.on.into_parts().len()
59 + self.position.into_parts().len()
60 + self.rotation.into_parts().len()
61 + self.axes.into_parts().len()
62 + self.entity_id.into_parts().len()
63 + self.entity_id.into_parts().len();
64 let mut out = vec![
65 Instruction::from(InstructionKind::Copy {
67 source: start_point,
68 destination: Destination::Address(base_path_addr),
69 length: 1,
70 }),
71 Instruction::from(InstructionKind::Copy {
73 source: start_point,
74 destination: Destination::Address(base_path_addr + self.path_first.from.into_parts().len()),
75 length: 1,
76 }),
77 ];
78 if let Some(tag) = tag {
79 out.push(Instruction::from(InstructionKind::Copy {
81 source: tag,
82 destination: Destination::Address(
83 base_path_addr + self.path_first.from.into_parts().len() + self.path_first.to.into_parts().len(),
84 ),
85 length: 1,
86 }));
87 }
88 out
89 }
90}
91
92#[derive(Debug, Clone, Copy, ExecutionPlanValue, PartialEq, Deserialize, Serialize)]
94pub struct Axes {
95 #[allow(missing_docs)]
96 pub x: Point3d,
97 #[allow(missing_docs)]
98 pub y: Point3d,
99 #[allow(missing_docs)]
100 pub z: Point3d,
101}
102
103#[derive(Debug, Clone, ExecutionPlanValue, PartialEq, Deserialize, Serialize)]
105pub struct BasePath {
106 pub from: Point2d<f64>,
108 pub to: Point2d<f64>,
110 pub name: String,
112}
113
114#[derive(Debug, Clone, ExecutionPlanValue, PartialEq, Deserialize, Serialize)]
117#[serde(rename_all = "snake_case", tag = "type")]
118pub enum PathSegment {
119 ToPoint {
121 base: BasePath,
123 },
124 TangentialArcTo {
126 base: BasePath,
128 center: Point2d,
130 ccw: bool,
132 },
133 Horizontal {
135 base: BasePath,
137 x: f64,
139 },
140 AngledLineTo {
142 base: BasePath,
144 x: Option<f64>,
146 y: Option<f64>,
148 },
149 Base {
151 base: BasePath,
153 },
154}
155
156impl PathSegment {
157 pub fn segment_kind(&self) -> &'static str {
159 match self {
160 PathSegment::ToPoint { .. } => "ToPoint",
161 PathSegment::TangentialArcTo { .. } => "TangentialArcTo",
162 PathSegment::Horizontal { .. } => "Horizontal",
163 PathSegment::AngledLineTo { .. } => "AngledLineTo",
164 PathSegment::Base { .. } => "Base",
165 }
166 }
167
168 fn get_base(&self) -> &BasePath {
170 match self {
171 PathSegment::ToPoint { base } => base,
172 PathSegment::TangentialArcTo { base, .. } => base,
173 PathSegment::Horizontal { base, .. } => base,
174 PathSegment::AngledLineTo { base, .. } => base,
175 PathSegment::Base { base } => base,
176 }
177 }
178}
179
180#[derive(Debug, Clone, Copy, ExecutionPlanValue, PartialEq, Deserialize, Serialize)]
182#[serde(rename_all = "snake_case", tag = "type")]
183pub enum SketchSurface {
184 Plane(Plane),
186}
187
188#[derive(Debug, Clone, Copy, ExecutionPlanValue, PartialEq, Deserialize, Serialize)]
190pub struct Plane {
191 pub id: Uuid,
193 pub value: PlaneType,
195 pub origin: Point3d,
197 pub axes: Axes,
199}
200
201#[derive(Debug, Clone, Copy, ExecutionPlanValue, PartialEq, Deserialize, Serialize)]
203#[serde(rename_all = "snake_case", tag = "type")]
204pub enum PlaneType {
205 #[allow(missing_docs)]
206 XY,
207 #[allow(missing_docs)]
208 XZ,
209 #[allow(missing_docs)]
210 YZ,
211 Custom,
213}