Fix units bug with involuteCircular (#6711)

Signed-off-by: Nick Cameron <nrc@ncameron.org>
This commit is contained in:
Nick Cameron
2025-05-06 14:58:53 +12:00
committed by GitHub
parent 9c52f5b19a
commit 9c246d6621
12 changed files with 9158 additions and 25 deletions

View File

@ -91945,7 +91945,7 @@
"type": "number", "type": "number",
"schema": { "schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema", "$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "double", "title": "TyF64",
"type": "number", "type": "number",
"format": "double", "format": "double",
"definitions": { "definitions": {
@ -93550,7 +93550,7 @@
"type": "number", "type": "number",
"schema": { "schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema", "$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "double", "title": "TyF64",
"type": "number", "type": "number",
"format": "double", "format": "double",
"definitions": { "definitions": {
@ -95155,7 +95155,7 @@
"type": "number", "type": "number",
"schema": { "schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema", "$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "double", "title": "TyF64",
"type": "number", "type": "number",
"format": "double", "format": "double",
"definitions": { "definitions": {

View File

@ -2708,3 +2708,24 @@ mod clone_w_shell {
super::execute(TEST_NAME, true).await super::execute(TEST_NAME, true).await
} }
} }
mod involute_circular_units {
const TEST_NAME: &str = "involute_circular_units";
/// 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
}
}

View File

@ -107,17 +107,8 @@ 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 angle: TyF64 = args.get_kw_arg_typed("angle", &RuntimeType::angle(), exec_state)?;
let reverse = args.get_kw_arg_opt("reverse")?; let reverse = args.get_kw_arg_opt("reverse")?;
let tag = args.get_kw_arg_opt(NEW_TAG_KW)?; let tag = args.get_kw_arg_opt(NEW_TAG_KW)?;
let new_sketch = inner_involute_circular( let new_sketch =
sketch, inner_involute_circular(sketch, start_radius, end_radius, angle, reverse, tag, exec_state, args).await?;
start_radius.n,
end_radius.n,
angle.n,
reverse,
tag,
exec_state,
args,
)
.await?;
Ok(KclValue::Sketch { Ok(KclValue::Sketch {
value: Box::new(new_sketch), value: Box::new(new_sketch),
}) })
@ -157,33 +148,35 @@ fn involute_curve(radius: f64, angle: f64) -> (f64, f64) {
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
async fn inner_involute_circular( async fn inner_involute_circular(
sketch: Sketch, sketch: Sketch,
start_radius: f64, start_radius: TyF64,
end_radius: f64, end_radius: TyF64,
angle: f64, angle: TyF64,
reverse: Option<bool>, reverse: Option<bool>,
tag: Option<TagNode>, tag: Option<TagNode>,
exec_state: &mut ExecState, exec_state: &mut ExecState,
args: Args, args: Args,
) -> Result<Sketch, KclError> { ) -> Result<Sketch, KclError> {
let id = exec_state.next_uuid(); let id = exec_state.next_uuid();
let angle = Angle::from_degrees(angle);
let segment = PathSegment::CircularInvolute {
start_radius: LengthUnit(start_radius),
end_radius: LengthUnit(end_radius),
angle,
reverse: reverse.unwrap_or_default(),
};
args.batch_modeling_cmd( args.batch_modeling_cmd(
id, id,
ModelingCmd::from(mcmd::ExtendPath { ModelingCmd::from(mcmd::ExtendPath {
path: sketch.id.into(), path: sketch.id.into(),
segment, segment: PathSegment::CircularInvolute {
start_radius: LengthUnit(start_radius.to_mm()),
end_radius: LengthUnit(end_radius.to_mm()),
angle: Angle::from_degrees(angle.to_degrees()),
reverse: reverse.unwrap_or_default(),
},
}), }),
) )
.await?; .await?;
let from = sketch.current_pen_position()?; let from = sketch.current_pen_position()?;
let start_radius = start_radius.to_length_units(from.units);
let end_radius = end_radius.to_length_units(from.units);
let mut end: KPoint3d<f64> = Default::default(); // ADAM: TODO impl this below. let mut end: KPoint3d<f64> = Default::default(); // ADAM: TODO impl this below.
let theta = f64::sqrt(end_radius * end_radius - start_radius * start_radius) / start_radius; let theta = f64::sqrt(end_radius * end_radius - start_radius * start_radius) / start_radius;
let (x, y) = involute_curve(start_radius, theta); let (x, y) = involute_curve(start_radius, theta);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,6 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Artifact graph flowchart involute_circular_units.kcl
extension: md
snapshot_kind: binary
---

View File

@ -0,0 +1,121 @@
```mermaid
flowchart LR
subgraph path2 [Path]
2["Path<br>[335, 375, 0]"]
4["Segment<br>[381, 519, 0]"]
5["Segment<br>[525, 571, 0]"]
6["Segment<br>[577, 722, 0]"]
7["Segment<br>[728, 870, 0]"]
8["Segment<br>[876, 922, 0]"]
9["Segment<br>[928, 1002, 0]"]
10["Segment<br>[1157, 1164, 0]"]
13[Solid2d]
end
subgraph path3 [Path]
3["Path<br>[1188, 1223, 0]"]
11["Segment<br>[1188, 1223, 0]"]
12[Solid2d]
end
1["Plane<br>[312, 329, 0]"]
14["Sweep Extrusion<br>[1230, 1258, 0]"]
15[Wall]
16[Wall]
17[Wall]
18[Wall]
19[Wall]
20[Wall]
21["Cap Start"]
22["Cap End"]
23["SweepEdge Opposite"]
24["SweepEdge Opposite"]
25["SweepEdge Opposite"]
26["SweepEdge Opposite"]
27["SweepEdge Opposite"]
28["SweepEdge Opposite"]
29["SweepEdge Adjacent"]
30["SweepEdge Adjacent"]
31["SweepEdge Adjacent"]
32["SweepEdge Adjacent"]
33["SweepEdge Adjacent"]
34["SweepEdge Adjacent"]
1 --- 2
1 --- 3
2 --- 4
2 --- 5
2 --- 6
2 --- 7
2 --- 8
2 --- 9
2 --- 10
2 --- 13
2 ---- 14
3 --- 11
3 --- 12
4 --- 20
4 x--> 21
4 --- 25
4 --- 32
5 --- 18
5 x--> 21
5 --- 23
5 --- 29
6 --- 17
6 x--> 21
6 --- 24
6 --- 31
7 --- 19
7 x--> 21
7 --- 26
7 --- 33
8 --- 16
8 x--> 21
8 --- 28
8 --- 30
9 --- 15
9 x--> 21
9 --- 27
9 --- 34
14 --- 15
14 --- 16
14 --- 17
14 --- 18
14 --- 19
14 --- 20
14 --- 21
14 --- 22
14 --- 23
14 --- 24
14 --- 25
14 --- 26
14 --- 27
14 --- 28
14 --- 29
14 --- 30
14 --- 31
14 --- 32
14 --- 33
14 --- 34
27 <--x 15
30 <--x 15
34 <--x 15
28 <--x 16
30 <--x 16
33 <--x 16
24 <--x 17
29 <--x 17
31 <--x 17
23 <--x 18
29 <--x 18
32 <--x 18
26 <--x 19
31 <--x 19
33 <--x 19
25 <--x 20
32 <--x 20
23 <--x 22
24 <--x 22
25 <--x 22
26 <--x 22
27 <--x 22
28 <--x 22
```

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,47 @@
@settings(defaultLengthUnit = cm)
// Define parameters
nTeeth = 21
module = 0.5
pitchDiameter = module * nTeeth
pressureAngle = 20deg
addendum = module
deddendum = 1.25 * module
baseDiameter = pitchDiameter * cos(pressureAngle)
tipDiameter = pitchDiameter + 2 * module
gearHeight = .3
angle001 = 6
sketch001 = startSketchOn(XY)
|> startProfile(at = [baseDiameter / 2, 0])
|> involuteCircular(
startRadius = baseDiameter / 2,
endRadius = tipDiameter / 2,
angle = 0,
tag = $seg01,
)
|> line(endAbsolute = [lastSegX(%), lastSegY(%)])
|> arc(
angleStart = asin(segEndY(seg01) / segEndX(seg01)),
angleEnd = 9,
radius = tipDiameter / 2,
tag = $seg02,
)
|> involuteCircular(
startRadius = baseDiameter / 2,
endRadius = tipDiameter / 2,
angle = -12,
reverse = true,
)
|> line(endAbsolute = [lastSegX(%), lastSegY(%)])
|> line(endAbsolute = polar(angle = 360 / nTeeth, length = baseDiameter / 2))
|> patternCircular2d(
%,
instances = nTeeth,
center = [0, 0],
arcDegrees = 360,
rotateDuplicates = true,
)
|> close()
|> subtract2d(tool = circle(center = [0, 0], radius = 1))
|> extrude(length = gearHeight)

View File

@ -0,0 +1,124 @@
---
source: kcl-lib/src/simulation_tests.rs
assertion_line: 282
description: Operations executed involute_circular_units.kcl
---
[
{
"labeledArgs": {},
"name": "startSketchOn",
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": {
"value": {
"type": "Plane",
"artifact_id": "[uuid]"
},
"sourceRange": []
}
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "polar",
"functionSourceRange": [],
"unlabeledArg": null,
"labeledArgs": {
"angle": {
"value": {
"type": "Number",
"value": 17.142857142857142,
"ty": {
"type": "Default",
"len": {
"type": "Cm"
},
"angle": {
"type": "Degrees"
}
}
},
"sourceRange": []
},
"length": {
"value": {
"type": "Number",
"value": 4.933386259126019,
"ty": {
"type": "Default",
"len": {
"type": "Cm"
},
"angle": {
"type": "Degrees"
}
}
},
"sourceRange": []
}
}
},
"sourceRange": []
},
{
"labeledArgs": {
"tool": {
"value": {
"type": "Sketch",
"value": {
"artifactId": "[uuid]"
}
},
"sourceRange": []
}
},
"name": "subtract2d",
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": {
"value": {
"type": "Sketch",
"value": {
"artifactId": "[uuid]"
}
},
"sourceRange": []
}
},
{
"labeledArgs": {
"length": {
"value": {
"type": "Number",
"value": 0.3,
"ty": {
"type": "Default",
"len": {
"type": "Cm"
},
"angle": {
"type": "Degrees"
}
}
},
"sourceRange": []
}
},
"name": "extrude",
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": {
"value": {
"type": "Sketch",
"value": {
"artifactId": "[uuid]"
}
},
"sourceRange": []
}
},
{
"type": "GroupEnd"
}
]

View File

@ -0,0 +1,434 @@
---
source: kcl-lib/src/simulation_tests.rs
assertion_line: 187
description: Variables in memory after executing involute_circular_units.kcl
---
{
"addendum": {
"type": "Number",
"value": 0.5,
"ty": {
"type": "Default",
"len": {
"type": "Cm"
},
"angle": {
"type": "Degrees"
}
}
},
"angle001": {
"type": "Number",
"value": 6.0,
"ty": {
"type": "Default",
"len": {
"type": "Cm"
},
"angle": {
"type": "Degrees"
}
}
},
"baseDiameter": {
"type": "Number",
"value": 9.8668,
"ty": {
"type": "Default",
"len": {
"type": "Cm"
},
"angle": {
"type": "Degrees"
}
}
},
"deddendum": {
"type": "Number",
"value": 0.625,
"ty": {
"type": "Default",
"len": {
"type": "Cm"
},
"angle": {
"type": "Degrees"
}
}
},
"gearHeight": {
"type": "Number",
"value": 0.3,
"ty": {
"type": "Default",
"len": {
"type": "Cm"
},
"angle": {
"type": "Degrees"
}
}
},
"module": {
"type": "Number",
"value": 0.5,
"ty": {
"type": "Default",
"len": {
"type": "Cm"
},
"angle": {
"type": "Degrees"
}
}
},
"nTeeth": {
"type": "Number",
"value": 21.0,
"ty": {
"type": "Default",
"len": {
"type": "Cm"
},
"angle": {
"type": "Degrees"
}
}
},
"pitchDiameter": {
"type": "Number",
"value": 10.5,
"ty": {
"type": "Default",
"len": {
"type": "Cm"
},
"angle": {
"type": "Degrees"
}
}
},
"pressureAngle": {
"type": "Number",
"value": 20.0,
"ty": {
"type": "Known",
"type": "Angle",
"type": "Degrees"
}
},
"seg01": {
"type": "TagIdentifier",
"type": "TagIdentifier",
"value": "seg01"
},
"seg02": {
"type": "TagIdentifier",
"type": "TagIdentifier",
"value": "seg02"
},
"sketch001": {
"type": "Solid",
"value": {
"type": "Solid",
"id": "[uuid]",
"artifactId": "[uuid]",
"value": [
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": {
"commentStart": 505,
"end": 511,
"start": 505,
"type": "TagDeclarator",
"value": "seg01"
},
"type": "extrudePlane"
},
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": null,
"type": "extrudePlane"
},
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": {
"commentStart": 708,
"end": 714,
"start": 708,
"type": "TagDeclarator",
"value": "seg02"
},
"type": "extrudeArc"
},
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": null,
"type": "extrudePlane"
},
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": null,
"type": "extrudePlane"
},
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": null,
"type": "extrudePlane"
}
],
"sketch": {
"type": "Sketch",
"id": "[uuid]",
"paths": [
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
4.9334,
0.0
],
"tag": {
"commentStart": 505,
"end": 511,
"start": 505,
"type": "TagDeclarator",
"value": "seg01"
},
"to": [
5.7399,
0.3404
],
"type": "ToPoint",
"units": {
"type": "Cm"
}
},
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
5.7399,
0.3404
],
"tag": null,
"to": [
5.7399,
0.3404
],
"type": "ToPoint",
"units": {
"type": "Cm"
}
},
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"ccw": true,
"center": [
0.0,
-0.0006
],
"from": [
5.7399,
0.3404
],
"radius": 5.75,
"tag": {
"commentStart": 708,
"end": 714,
"start": 708,
"type": "TagDeclarator",
"value": "seg02"
},
"to": [
5.6792,
0.8989
],
"type": "Arc",
"units": {
"type": "Cm"
}
},
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
5.6792,
0.8989
],
"tag": null,
"to": [
4.8196,
1.0642
],
"type": "ToPoint",
"units": {
"type": "Cm"
}
},
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
4.8196,
1.0642
],
"tag": null,
"to": [
4.8196,
1.0642
],
"type": "ToPoint",
"units": {
"type": "Cm"
}
},
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
4.8196,
1.0642
],
"tag": null,
"to": [
4.7142,
1.4541
],
"type": "ToPoint",
"units": {
"type": "Cm"
}
},
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
4.7142,
1.4541
],
"tag": null,
"to": [
4.9334,
0.0
],
"type": "ToPoint",
"units": {
"type": "Cm"
}
}
],
"on": {
"artifactId": "[uuid]",
"id": "[uuid]",
"origin": {
"x": 0.0,
"y": 0.0,
"z": 0.0,
"units": {
"type": "Mm"
}
},
"type": "plane",
"value": "XY",
"xAxis": {
"x": 1.0,
"y": 0.0,
"z": 0.0,
"units": {
"type": "Unknown"
}
},
"yAxis": {
"x": 0.0,
"y": 1.0,
"z": 0.0,
"units": {
"type": "Unknown"
}
}
},
"start": {
"from": [
4.9334,
0.0
],
"to": [
4.9334,
0.0
],
"units": {
"type": "Cm"
},
"tag": null,
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
}
},
"tags": {
"seg01": {
"type": "TagIdentifier",
"value": "seg01"
},
"seg02": {
"type": "TagIdentifier",
"value": "seg02"
}
},
"artifactId": "[uuid]",
"originalId": "[uuid]",
"units": {
"type": "Cm"
}
},
"height": 0.3,
"startCapId": "[uuid]",
"endCapId": "[uuid]",
"units": {
"type": "Cm"
},
"sectional": false
}
},
"tipDiameter": {
"type": "Number",
"value": 11.5,
"ty": {
"type": "Default",
"len": {
"type": "Cm"
},
"angle": {
"type": "Degrees"
}
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

View File

@ -0,0 +1,52 @@
---
source: kcl-lib/src/simulation_tests.rs
assertion_line: 109
description: Result of unparsing involute_circular_units.kcl
---
@settings(defaultLengthUnit = cm)
// Define parameters
nTeeth = 21
module = 0.5
pitchDiameter = module * nTeeth
pressureAngle = 20deg
addendum = module
deddendum = 1.25 * module
baseDiameter = pitchDiameter * cos(pressureAngle)
tipDiameter = pitchDiameter + 2 * module
gearHeight = .3
angle001 = 6
sketch001 = startSketchOn(XY)
|> startProfile(at = [baseDiameter / 2, 0])
|> involuteCircular(
startRadius = baseDiameter / 2,
endRadius = tipDiameter / 2,
angle = 0,
tag = $seg01,
)
|> line(endAbsolute = [lastSegX(%), lastSegY(%)])
|> arc(
angleStart = asin(segEndY(seg01) / segEndX(seg01)),
angleEnd = 9,
radius = tipDiameter / 2,
tag = $seg02,
)
|> involuteCircular(
startRadius = baseDiameter / 2,
endRadius = tipDiameter / 2,
angle = -12,
reverse = true,
)
|> line(endAbsolute = [lastSegX(%), lastSegY(%)])
|> line(endAbsolute = polar(angle = 360 / nTeeth, length = baseDiameter / 2))
|> patternCircular2d(
%,
instances = nTeeth,
center = [0, 0],
arcDegrees = 360,
rotateDuplicates = true,
)
|> close()
|> subtract2d(tool = circle(center = [0, 0], radius = 1))
|> extrude(length = gearHeight)