Skip to content

Add involute to Path info #6448

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58,677 changes: 42,864 additions & 15,813 deletions docs/kcl/std.json

Large diffs are not rendered by default.

20 changes: 20 additions & 0 deletions docs/kcl/types/ExtrudeSurface.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,26 @@ An extruded arc.
| `sourceRange` |`[integer, integer, integer]`| The source range. | No |


----
An extruded involute.

**Type:** `object`





## Properties

| Property | Type | Description | Required |
|----------|------|-------------|----------|
| `type` |enum: `extrudeInvolute`| | No |
| `faceId` |[`string`](/docs/kcl/types/string)| The face id for the extrude surface. | No |
| [`tag`](/docs/kcl/types/tag) |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag. | No |
| `id` |[`string`](/docs/kcl/types/string)| The id of the geometry. | No |
| `sourceRange` |`[integer, integer, integer]`| The source range. | No |


----
Geometry metadata.

Expand Down
25 changes: 25 additions & 0 deletions docs/kcl/types/Path.md
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,31 @@ A circular arc, not necessarily tangential to the current point.


----
An involute of a circle of start_radius ending at end_radius

**Type:** `object`





## Properties

| Property | Type | Description | Required |
|----------|------|-------------|----------|
| `type` |enum: `CircularInvolute`| | No |
| `start_radius` |[`number`](/docs/kcl/types/number)| The radius of the base circle of the involute | No |
| `end_radius` |[`number`](/docs/kcl/types/number)| The radius that the involute ends at | No |
| `angle` |[`number`](/docs/kcl/types/number)| Angle about which the whole involute is rotated | No |
| `reverse` |`boolean`| If true, the path segment starts at the end radius and goes towards the start radius | No |
| `from` |`[number, number]`| The from point. | No |
| `to` |`[number, number]`| The to point. | No |
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A unit of length. | No |
| [`tag`](/docs/kcl/types/tag) |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag of the path. | No |
| `__geoMeta` |[`GeoMeta`](/docs/kcl/types/GeoMeta)| Metadata. | No |


----



Expand Down
52 changes: 51 additions & 1 deletion rust/kcl-lib/src/execution/geometry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1132,6 +1132,19 @@ pub enum Path {
/// True if the arc is counterclockwise.
ccw: bool,
},
/// An involute of a circle of start_radius ending at end_radius
CircularInvolute {
#[serde(flatten)]
base: BasePath,
/// The radius of the base circle of the involute
start_radius: f64,
/// The radius that the involute ends at
end_radius: f64,
/// Angle about which the whole involute is rotated
angle: f64,
/// If true, the path segment starts at the end radius and goes towards the start radius
reverse: bool,
},
}

/// What kind of path is this?
Expand All @@ -1146,6 +1159,7 @@ enum PathType {
Horizontal,
AngledLineTo,
Arc,
CircularInvolute,
}

impl From<&Path> for PathType {
Expand All @@ -1161,6 +1175,7 @@ impl From<&Path> for PathType {
Path::Base { .. } => Self::Base,
Path::Arc { .. } => Self::Arc,
Path::ArcThreePoint { .. } => Self::Arc,
Path::CircularInvolute { .. } => Self::CircularInvolute,
}
}
}
Expand All @@ -1178,6 +1193,7 @@ impl Path {
Path::CircleThreePoint { base, .. } => base.geo_meta.id,
Path::Arc { base, .. } => base.geo_meta.id,
Path::ArcThreePoint { base, .. } => base.geo_meta.id,
Path::CircularInvolute { base, .. } => base.geo_meta.id,
}
}

Expand All @@ -1193,6 +1209,7 @@ impl Path {
Path::CircleThreePoint { base, .. } => base.geo_meta.id = id,
Path::Arc { base, .. } => base.geo_meta.id = id,
Path::ArcThreePoint { base, .. } => base.geo_meta.id = id,
Path::CircularInvolute { base, .. } => base.geo_meta.id = id,
}
}

Expand All @@ -1208,6 +1225,7 @@ impl Path {
Path::CircleThreePoint { base, .. } => base.tag.clone(),
Path::Arc { base, .. } => base.tag.clone(),
Path::ArcThreePoint { base, .. } => base.tag.clone(),
Path::CircularInvolute { base, .. } => base.tag.clone(),
}
}

Expand All @@ -1223,6 +1241,7 @@ impl Path {
Path::CircleThreePoint { base, .. } => base,
Path::Arc { base, .. } => base,
Path::ArcThreePoint { base, .. } => base,
Path::CircularInvolute { base, .. } => base,
}
}

Expand Down Expand Up @@ -1284,6 +1303,15 @@ impl Path {
// TODO: Call engine utils to figure this out.
linear_distance(&self.get_base().from, &self.get_base().to)
}
Self::CircularInvolute {
base: _,
start_radius,
end_radius,
..
} => {
let angle = (end_radius * end_radius - start_radius * start_radius).sqrt() / start_radius;
0.5 * start_radius * angle * angle
Comment on lines +1312 to +1313
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The calculation (end_radius * end_radius - start_radius * start_radius).sqrt() / start_radius will produce a runtime error if end_radius < start_radius, as it would attempt to take the square root of a negative number. This is particularly problematic when the reverse flag is set to true, which suggests the path should go from end_radius to start_radius. Consider adding a validation check or using abs() to ensure the calculation is always performed on a positive value.

Suggested change
let angle = (end_radius * end_radius - start_radius * start_radius).sqrt() / start_radius;
0.5 * start_radius * angle * angle
let angle = ((end_radius * end_radius - start_radius * start_radius).abs()).sqrt() / start_radius;
0.5 * start_radius * angle * angle

Spotted by Diamond

Is this helpful? React 👍 or 👎 to let us know.

}
};
TyF64::new(n, self.get_base().units.into())
}
Expand All @@ -1300,6 +1328,7 @@ impl Path {
Path::CircleThreePoint { base, .. } => Some(base),
Path::Arc { base, .. } => Some(base),
Path::ArcThreePoint { base, .. } => Some(base),
Path::CircularInvolute { base, .. } => Some(base),
}
}

Expand Down Expand Up @@ -1335,7 +1364,11 @@ impl Path {
radius: circle.radius,
}
}
Path::ToPoint { .. } | Path::Horizontal { .. } | Path::AngledLineTo { .. } | Path::Base { .. } => {
Path::CircularInvolute { .. }
| Path::ToPoint { .. }
| Path::Horizontal { .. }
| Path::AngledLineTo { .. }
| Path::Base { .. } => {
let base = self.get_base();
GetTangentialInfoFromPathsResult::PreviousPoint(base.from)
}
Expand All @@ -1362,6 +1395,7 @@ pub enum ExtrudeSurface {
/// An extrude plane.
ExtrudePlane(ExtrudePlane),
ExtrudeArc(ExtrudeArc),
ExtrudeInvolute(ExtrudeInvolute),
Chamfer(ChamferSurface),
Fillet(FilletSurface),
}
Expand Down Expand Up @@ -1422,11 +1456,26 @@ pub struct ExtrudeArc {
pub geo_meta: GeoMeta,
}

/// An extruded involute.
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
pub struct ExtrudeInvolute {
/// The face id for the extrude surface.
pub face_id: uuid::Uuid,
/// The tag.
pub tag: Option<Node<TagDeclarator>>,
/// Metadata.
#[serde(flatten)]
pub geo_meta: GeoMeta,
}

impl ExtrudeSurface {
pub fn get_id(&self) -> uuid::Uuid {
match self {
ExtrudeSurface::ExtrudePlane(ep) => ep.geo_meta.id,
ExtrudeSurface::ExtrudeArc(ea) => ea.geo_meta.id,
ExtrudeSurface::ExtrudeInvolute(ea) => ea.geo_meta.id,
ExtrudeSurface::Fillet(f) => f.geo_meta.id,
ExtrudeSurface::Chamfer(c) => c.geo_meta.id,
}
Expand All @@ -1436,6 +1485,7 @@ impl ExtrudeSurface {
match self {
ExtrudeSurface::ExtrudePlane(ep) => ep.tag.clone(),
ExtrudeSurface::ExtrudeArc(ea) => ea.tag.clone(),
ExtrudeSurface::ExtrudeInvolute(ea) => ea.tag.clone(),
ExtrudeSurface::Fillet(f) => f.tag.clone(),
ExtrudeSurface::Chamfer(c) => c.tag.clone(),
}
Expand Down
22 changes: 22 additions & 0 deletions rust/kcl-lib/src/simulation_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2600,3 +2600,25 @@ mod multiple_foreign_imports_all_render {
super::execute(TEST_NAME, true).await
}
}

mod involute_fail {
const TEST_NAME: &str = "involute_fail";

/// Test parsing KCL.
#[test]
fn parse() {
super::parse(TEST_NAME)
}

/// Test that parsing and unparsing KCL produces the original KCL input.
#[tokio::test(flavor = "multi_thread")]
async fn unparse() {
super::unparse(TEST_NAME).await
}

/// Test that KCL is executed correctly.
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_execute() {
super::execute(TEST_NAME, true).await
}
}
11 changes: 11 additions & 0 deletions rust/kcl-lib/src/std/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -713,6 +713,17 @@ impl Args {
None
}
}
ExtrudeSurface::ExtrudeInvolute(extrude_involute) => {
if let Some(involute_tag) = &extrude_involute.tag {
if involute_tag.name == tag.value {
Some(Ok(extrude_involute.face_id))
} else {
None
}
} else {
None
}
}
ExtrudeSurface::Chamfer(chamfer) => {
if let Some(chamfer_tag) = &chamfer.tag {
if chamfer_tag.name == tag.value {
Expand Down
11 changes: 11 additions & 0 deletions rust/kcl-lib/src/std/extrude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,17 @@ pub(crate) async fn do_post_extrude<'a>(
});
Some(extrude_surface)
}
Path::CircularInvolute { .. } => {
let extrude_surface = ExtrudeSurface::ExtrudeInvolute(crate::execution::ExtrudeInvolute {
face_id: *actual_face_id,
tag: path.get_base().tag.clone(),
geo_meta: GeoMeta {
id: path.get_base().geo_meta.id,
metadata: path.get_base().geo_meta.metadata,
},
});
Some(extrude_surface)
}
}
} else if no_engine_commands {
// Only pre-populate the extrude surface if we are in mock mode.
Expand Down
18 changes: 17 additions & 1 deletion rust/kcl-lib/src/std/sketch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,18 @@ pub async fn involute_circular(exec_state: &mut ExecState, args: Args) -> Result
let angle: TyF64 = args.get_kw_arg_typed("angle", &RuntimeType::angle(), exec_state)?;
let reverse = args.get_kw_arg_opt("reverse")?;
let tag = args.get_kw_arg_opt(NEW_TAG_KW)?;

if end_radius.n < start_radius.n {
return Err(KclError::Semantic(KclErrorDetails {
source_ranges: vec![args.source_range],
message: format!(
"endRadius: {0} cannot be less than startRadius: {1}",
end_radius.n, start_radius.n
)
.to_owned(),
}));
}

let new_sketch = inner_involute_circular(
sketch,
start_radius.n,
Expand Down Expand Up @@ -198,7 +210,7 @@ async fn inner_involute_circular(
end.x += from.x;
end.y += from.y;

let current_path = Path::ToPoint {
let current_path = Path::CircularInvolute {
base: BasePath {
from: from.ignore_units(),
to: [end.x, end.y],
Expand All @@ -209,6 +221,10 @@ async fn inner_involute_circular(
metadata: args.source_range.into(),
},
},
start_radius,
end_radius,
angle: angle.to_degrees(),
reverse: reverse.unwrap_or_default(),
};

let mut new_sketch = sketch.clone();
Expand Down
32 changes: 32 additions & 0 deletions rust/kcl-lib/tests/involute_fail/artifact_commands.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Artifact commands involute_fail.kcl
---
[
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "edge_lines_visible",
"hidden": false
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "object_visible",
"object_id": "[uuid]",
"hidden": true
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "object_visible",
"object_id": "[uuid]",
"hidden": true
}
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Artifact graph flowchart involute_fail.kcl
extension: md
snapshot_kind: binary
---
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```mermaid
flowchart LR
```
Loading
Loading