Compare commits

...

1 Commits

Author SHA1 Message Date
2fafe547c8 Path enum no longer includes BasePath
BasePath is a pair of points and geometry metadata.

Previously BasePath was used for:

 - The start of a sketch
 - The data which all path types have in common

It wasn't a good fit for the start of a sketch, because there was a lot
of duplicated information, and a sketch starts at a point, not a line
(two points).

This adds a separate SketchStart struct which replaces the first use
of BasePath. This means BasePath no longer needs to be a variant of
Path, simplifying it.

Solves problem 4 of
 https://github.com/KittyCAD/modeling-app/issues/4297
2024-10-28 11:30:47 -05:00
9 changed files with 3374 additions and 9216 deletions

File diff suppressed because it is too large Load Diff

View File

@ -141,26 +141,6 @@ An angled line to.
| `__geoMeta` |[`GeoMeta`](/docs/kcl/types/GeoMeta)| Metadata. | No | | `__geoMeta` |[`GeoMeta`](/docs/kcl/types/GeoMeta)| Metadata. | No |
----
A base path.
**Type:** `object`
## Properties
| Property | Type | Description | Required |
|----------|------|-------------|----------|
| `type` |enum: `Base`| | No |
| `from` |`[number, number]`| The from point. | No |
| `to` |`[number, number]`| The to point. | No |
| `tag` |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag of the path. | No |
| `__geoMeta` |[`GeoMeta`](/docs/kcl/types/GeoMeta)| Metadata. | No |
---- ----
A circular arc, not necessarily tangential to the current point. A circular arc, not necessarily tangential to the current point.

View File

@ -19,7 +19,7 @@ A sketch is a collection of paths.
| `id` |`string`| The id of the sketch (this will change when the engine's reference to it changes). | No | | `id` |`string`| The id of the sketch (this will change when the engine's reference to it changes). | No |
| `paths` |`[` [`Path`](/docs/kcl/types/Path) `]`| The paths in the sketch. | No | | `paths` |`[` [`Path`](/docs/kcl/types/Path) `]`| The paths in the sketch. | No |
| `on` |[`SketchSurface`](/docs/kcl/types/SketchSurface)| What the sketch is on (can be a plane or a face). | No | | `on` |[`SketchSurface`](/docs/kcl/types/SketchSurface)| What the sketch is on (can be a plane or a face). | No |
| `start` |[`BasePath`](/docs/kcl/types/BasePath)| The starting path. | No | | `start` |[`SketchStart`](/docs/kcl/types/SketchStart)| The starting path. | No |
| `tags` |`object`| Tag identifiers that have been declared in this sketch. | No | | `tags` |`object`| Tag identifiers that have been declared in this sketch. | No |
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| Metadata. | No | | `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| Metadata. | No |

View File

@ -28,7 +28,7 @@ A sketch is a collection of paths.
| `id` |`string`| The id of the sketch (this will change when the engine's reference to it changes). | No | | `id` |`string`| The id of the sketch (this will change when the engine's reference to it changes). | No |
| `paths` |`[` [`Path`](/docs/kcl/types/Path) `]`| The paths in the sketch. | No | | `paths` |`[` [`Path`](/docs/kcl/types/Path) `]`| The paths in the sketch. | No |
| `on` |[`SketchSurface`](/docs/kcl/types/SketchSurface)| What the sketch is on (can be a plane or a face). | No | | `on` |[`SketchSurface`](/docs/kcl/types/SketchSurface)| What the sketch is on (can be a plane or a face). | No |
| `start` |[`BasePath`](/docs/kcl/types/BasePath)| The starting path. | No | | `start` |[`SketchStart`](/docs/kcl/types/SketchStart)| The starting path. | No |
| `tags` |`object`| Tag identifiers that have been declared in this sketch. | No | | `tags` |`object`| Tag identifiers that have been declared in this sketch. | No |
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| Metadata. | No | | `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| Metadata. | No |

View File

@ -0,0 +1,23 @@
---
title: "SketchStart"
excerpt: "Where the sketch starts."
layout: manual
---
Where the sketch starts.
**Type:** `object`
## Properties
| Property | Type | Description | Required |
|----------|------|-------------|----------|
| `at` |`[number, number]`| Start point. | No |
| `tag` |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| Tag of the start point. | No |
| `__geoMeta` |[`GeoMeta`](/docs/kcl/types/GeoMeta)| Metadata. | No |

View File

@ -43,6 +43,22 @@ The surface information for the tag.
| `surface` |[`ExtrudeSurface`](/docs/kcl/types/ExtrudeSurface)| Engine information for a tag. | No | | `surface` |[`ExtrudeSurface`](/docs/kcl/types/ExtrudeSurface)| Engine information for a tag. | No |
----
The point being tagged.
**Type:** `object`
## Properties
| Property | Type | Description | Required |
|----------|------|-------------|----------|
| `point` |`[number, number]`| | No |
---- ----

View File

@ -1141,6 +1141,11 @@ impl TagEngineInfo {
pub fn surface(&self) -> Option<&ExtrudeSurface> { pub fn surface(&self) -> Option<&ExtrudeSurface> {
self.tagged.surface() self.tagged.surface()
} }
/// If this is tagging a point, get it.
pub fn point(&self) -> Option<&[f64; 2]> {
self.tagged.point()
}
} }
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
@ -1151,6 +1156,8 @@ pub enum Tagged {
Path(Path), Path(Path),
/// The surface information for the tag. /// The surface information for the tag.
Surface(ExtrudeSurface), Surface(ExtrudeSurface),
/// The point being tagged.
Point([f64; 2]),
} }
impl Tagged { impl Tagged {
@ -1169,6 +1176,13 @@ impl Tagged {
}; };
Some(x) Some(x)
} }
/// If this is a path, get it.
fn point(&self) -> Option<&[f64; 2]> {
let Self::Point(x) = &self else {
return None;
};
Some(x)
}
} }
/// A sketch is a collection of paths. /// A sketch is a collection of paths.
@ -1183,7 +1197,7 @@ pub struct Sketch {
/// What the sketch is on (can be a plane or a face). /// What the sketch is on (can be a plane or a face).
pub on: SketchSurface, pub on: SketchSurface,
/// The starting path. /// The starting path.
pub start: BasePath, pub start: SketchStart,
/// Tag identifiers that have been declared in this sketch. /// Tag identifiers that have been declared in this sketch.
#[serde(default, skip_serializing_if = "HashMap::is_empty")] #[serde(default, skip_serializing_if = "HashMap::is_empty")]
pub tags: HashMap<String, TagIdentifier>, pub tags: HashMap<String, TagIdentifier>,
@ -1261,7 +1275,7 @@ impl Sketch {
/// where the last path segment ends, and the next path segment will begin. /// where the last path segment ends, and the next path segment will begin.
pub(crate) fn current_pen_position(&self) -> Result<Point2d, KclError> { pub(crate) fn current_pen_position(&self) -> Result<Point2d, KclError> {
let Some(path) = self.latest_path() else { let Some(path) = self.latest_path() else {
return Ok(self.start.to.into()); return Ok(self.start.at.into());
}; };
let base = path.get_base(); let base = path.get_base();
@ -1271,7 +1285,7 @@ impl Sketch {
pub(crate) fn get_tangential_info_from_paths(&self) -> GetTangentialInfoFromPathsResult { pub(crate) fn get_tangential_info_from_paths(&self) -> GetTangentialInfoFromPathsResult {
let Some(path) = self.latest_path() else { let Some(path) = self.latest_path() else {
return GetTangentialInfoFromPathsResult { return GetTangentialInfoFromPathsResult {
center_or_tangent_point: self.start.to, center_or_tangent_point: self.start.at,
is_center: false, is_center: false,
ccw: false, ccw: false,
}; };
@ -1617,6 +1631,21 @@ pub struct BasePath {
pub geo_meta: GeoMeta, pub geo_meta: GeoMeta,
} }
/// Where the sketch starts.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
pub struct SketchStart {
/// Start point.
#[ts(type = "[number, number]")]
pub at: [f64; 2],
/// Tag of the start point.
pub tag: Option<TagDeclarator>,
/// Metadata.
#[serde(rename = "__geoMeta")]
pub geo_meta: GeoMeta,
}
/// Geometry metadata. /// Geometry metadata.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)] #[ts(export)]
@ -1689,11 +1718,6 @@ pub enum Path {
/// The y coordinate. /// The y coordinate.
y: Option<f64>, y: Option<f64>,
}, },
/// A base path.
Base {
#[serde(flatten)]
base: BasePath,
},
/// A circular arc, not necessarily tangential to the current point. /// A circular arc, not necessarily tangential to the current point.
Arc { Arc {
#[serde(flatten)] #[serde(flatten)]
@ -1709,7 +1733,6 @@ pub enum Path {
#[derive(Display)] #[derive(Display)]
enum PathType { enum PathType {
ToPoint, ToPoint,
Base,
TangentialArc, TangentialArc,
TangentialArcTo, TangentialArcTo,
Circle, Circle,
@ -1727,7 +1750,6 @@ impl From<&Path> for PathType {
Path::Circle { .. } => Self::Circle, Path::Circle { .. } => Self::Circle,
Path::Horizontal { .. } => Self::Horizontal, Path::Horizontal { .. } => Self::Horizontal,
Path::AngledLineTo { .. } => Self::AngledLineTo, Path::AngledLineTo { .. } => Self::AngledLineTo,
Path::Base { .. } => Self::Base,
Path::Arc { .. } => Self::Arc, Path::Arc { .. } => Self::Arc,
} }
} }
@ -1739,7 +1761,6 @@ impl Path {
Path::ToPoint { base } => base.geo_meta.id, Path::ToPoint { base } => base.geo_meta.id,
Path::Horizontal { base, .. } => base.geo_meta.id, Path::Horizontal { base, .. } => base.geo_meta.id,
Path::AngledLineTo { base, .. } => base.geo_meta.id, Path::AngledLineTo { base, .. } => base.geo_meta.id,
Path::Base { base } => base.geo_meta.id,
Path::TangentialArcTo { base, .. } => base.geo_meta.id, Path::TangentialArcTo { base, .. } => base.geo_meta.id,
Path::TangentialArc { base, .. } => base.geo_meta.id, Path::TangentialArc { base, .. } => base.geo_meta.id,
Path::Circle { base, .. } => base.geo_meta.id, Path::Circle { base, .. } => base.geo_meta.id,
@ -1752,7 +1773,6 @@ impl Path {
Path::ToPoint { base } => base.tag.clone(), Path::ToPoint { base } => base.tag.clone(),
Path::Horizontal { base, .. } => base.tag.clone(), Path::Horizontal { base, .. } => base.tag.clone(),
Path::AngledLineTo { base, .. } => base.tag.clone(), Path::AngledLineTo { base, .. } => base.tag.clone(),
Path::Base { base } => base.tag.clone(),
Path::TangentialArcTo { base, .. } => base.tag.clone(), Path::TangentialArcTo { base, .. } => base.tag.clone(),
Path::TangentialArc { base, .. } => base.tag.clone(), Path::TangentialArc { base, .. } => base.tag.clone(),
Path::Circle { base, .. } => base.tag.clone(), Path::Circle { base, .. } => base.tag.clone(),
@ -1765,7 +1785,6 @@ impl Path {
Path::ToPoint { base } => base, Path::ToPoint { base } => base,
Path::Horizontal { base, .. } => base, Path::Horizontal { base, .. } => base,
Path::AngledLineTo { base, .. } => base, Path::AngledLineTo { base, .. } => base,
Path::Base { base } => base,
Path::TangentialArcTo { base, .. } => base, Path::TangentialArcTo { base, .. } => base,
Path::TangentialArc { base, .. } => base, Path::TangentialArc { base, .. } => base,
Path::Circle { base, .. } => base, Path::Circle { base, .. } => base,
@ -1785,7 +1804,7 @@ impl Path {
/// Length of this path segment, in cartesian plane. /// Length of this path segment, in cartesian plane.
pub fn length(&self) -> f64 { pub fn length(&self) -> f64 {
match self { match self {
Self::ToPoint { .. } | Self::Base { .. } | Self::Horizontal { .. } | Self::AngledLineTo { .. } => { Self::ToPoint { .. } | Self::Horizontal { .. } | Self::AngledLineTo { .. } => {
linear_distance(self.get_from(), self.get_to()) linear_distance(self.get_from(), self.get_to())
} }
Self::TangentialArc { Self::TangentialArc {
@ -1818,7 +1837,6 @@ impl Path {
Path::ToPoint { base } => Some(base), Path::ToPoint { base } => Some(base),
Path::Horizontal { base, .. } => Some(base), Path::Horizontal { base, .. } => Some(base),
Path::AngledLineTo { base, .. } => Some(base), Path::AngledLineTo { base, .. } => Some(base),
Path::Base { base } => Some(base),
Path::TangentialArcTo { base, .. } => Some(base), Path::TangentialArcTo { base, .. } => Some(base),
Path::TangentialArc { base, .. } => Some(base), Path::TangentialArc { base, .. } => Some(base),
Path::Circle { base, .. } => Some(base), Path::Circle { base, .. } => Some(base),

View File

@ -238,7 +238,7 @@ pub(crate) async fn do_post_extrude(
}); });
Some(extrude_surface) Some(extrude_surface)
} }
Path::Base { .. } | Path::ToPoint { .. } | Path::Horizontal { .. } | Path::AngledLineTo { .. } => { Path::ToPoint { .. } | Path::Horizontal { .. } | Path::AngledLineTo { .. } => {
let extrude_surface = ExtrudeSurface::ExtrudePlane(crate::executor::ExtrudePlane { let extrude_surface = ExtrudeSurface::ExtrudePlane(crate::executor::ExtrudePlane {
face_id: *actual_face_id, face_id: *actual_face_id,
tag: path.get_base().tag.clone(), tag: path.get_base().tag.clone(),

View File

@ -12,7 +12,7 @@ use parse_display::{Display, FromStr};
use schemars::JsonSchema; use schemars::JsonSchema;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::executor::Tagged; use crate::executor::{SketchStart, Tagged};
use crate::{ use crate::{
ast::types::TagDeclarator, ast::types::TagDeclarator,
errors::{KclError, KclErrorDetails}, errors::{KclError, KclErrorDetails},
@ -1224,9 +1224,8 @@ pub(crate) async fn inner_start_profile_at(
) )
.await?; .await?;
let current_path = BasePath { let start = SketchStart {
from: to, at: to,
to,
tag: tag.clone(), tag: tag.clone(),
geo_meta: GeoMeta { geo_meta: GeoMeta {
id, id,
@ -1243,17 +1242,15 @@ pub(crate) async fn inner_start_profile_at(
tags: if let Some(tag) = &tag { tags: if let Some(tag) = &tag {
let mut tag_identifier: TagIdentifier = tag.into(); let mut tag_identifier: TagIdentifier = tag.into();
tag_identifier.info = Some(TagEngineInfo { tag_identifier.info = Some(TagEngineInfo {
id: current_path.geo_meta.id, id,
sketch: path_id, sketch: path_id,
tagged: Tagged::Path(Path::Base { tagged: Tagged::Point(to),
base: current_path.clone(),
}),
}); });
HashMap::from([(tag.name.to_string(), tag_identifier)]) HashMap::from([(tag.name.to_string(), tag_identifier)])
} else { } else {
Default::default() Default::default()
}, },
start: current_path, start,
}; };
Ok(sketch) Ok(sketch)
} }
@ -1279,7 +1276,7 @@ pub async fn profile_start_x(_exec_state: &mut ExecState, args: Args) -> Result<
name = "profileStartX" name = "profileStartX"
}] }]
pub(crate) fn inner_profile_start_x(sketch: Sketch) -> Result<f64, KclError> { pub(crate) fn inner_profile_start_x(sketch: Sketch) -> Result<f64, KclError> {
Ok(sketch.start.to[0]) Ok(sketch.start.at[0])
} }
/// Returns the Y component of the sketch profile start point. /// Returns the Y component of the sketch profile start point.
@ -1302,7 +1299,7 @@ pub async fn profile_start_y(_exec_state: &mut ExecState, args: Args) -> Result<
name = "profileStartY" name = "profileStartY"
}] }]
pub(crate) fn inner_profile_start_y(sketch: Sketch) -> Result<f64, KclError> { pub(crate) fn inner_profile_start_y(sketch: Sketch) -> Result<f64, KclError> {
Ok(sketch.start.to[1]) Ok(sketch.start.at[1])
} }
/// Returns the sketch profile start point. /// Returns the sketch profile start point.
@ -1336,7 +1333,7 @@ pub async fn profile_start(_exec_state: &mut ExecState, args: Args) -> Result<Kc
name = "profileStart" name = "profileStart"
}] }]
pub(crate) fn inner_profile_start(sketch: Sketch) -> Result<[f64; 2], KclError> { pub(crate) fn inner_profile_start(sketch: Sketch) -> Result<[f64; 2], KclError> {
Ok(sketch.start.to) Ok(sketch.start.at)
} }
/// Close the current sketch. /// Close the current sketch.
@ -1379,7 +1376,7 @@ pub(crate) async fn inner_close(
args: Args, args: Args,
) -> Result<Sketch, KclError> { ) -> Result<Sketch, KclError> {
let from = sketch.current_pen_position()?; let from = sketch.current_pen_position()?;
let to: Point2d = sketch.start.from.into(); let to: Point2d = sketch.start.at.into();
let id = exec_state.id_generator.next_uuid(); let id = exec_state.id_generator.next_uuid();