Compare commits

...

8 Commits

Author SHA1 Message Date
b63b0e538a Fix to not have infinite console errors editing tangentialArc (#7296) 2025-05-30 12:58:47 -04:00
5118198cec Add variable name to operations display in Feature Tree (#7274)
* Add variable name to operations in Feature Tree

* small design tweak

---------

Co-authored-by: Kurt Hutten Irev-Dev <k.hutten@protonmail.ch>
2025-05-30 11:09:01 -04:00
1611244b94 Revert "Fix the black screen of death" (#7292)
Revert "Fix the black screen of death (#7238)"

This reverts commit 46b6707e3a.
2025-05-30 10:36:33 -04:00
227ad31fc2 #4376 UI should generate relative tangentialArc (#7189)
* first step of UI using trelative angentialArc

* use tangentialArcTo when snapping to one of the axes

* remove duplications via tangentialArcHelpers

* update test: snapToProfile start only works for current profile

* add test: Can add multiple profiles to a sketch (all tool types)

* update test: Straight line snapping to previous tangent

* fixes for removing individual constraints (should keep endAbsolute for lines, tangentialArcs)

* fix fnNameToToolTipFromSegment arcTo

* update snapshot test to use relative tangentialArc

* stabilize some snapshot tests

* stabilize and update Inch snapshot test on ubuntu

* fix tsc

* stabilize and update Millimeter scale snapshot test on ubuntu

* update snapshot for Inch scale test

* Update snapshots

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-05-30 14:44:31 +02:00
80e3dc9095 Move more functions to KCL decls (#7266)
* Move some sketch functions to KCL

Signed-off-by: Nick Cameron <nrc@ncameron.org>

* Move asserts to KCL

Signed-off-by: Nick Cameron <nrc@ncameron.org>

* sweep, loft -> KCL

Signed-off-by: Nick Cameron <nrc@ncameron.org>

* Move pattern transforms to KCL

Signed-off-by: Nick Cameron <nrc@ncameron.org>

---------

Signed-off-by: Nick Cameron <nrc@ncameron.org>
2025-05-29 19:00:16 -04:00
46b6707e3a Fix the black screen of death (#7238)
* Fix the black screen of death

* fmt

* make check

* Clean up

* Fix up zoom to fit

* Change how emulateNetworkConditions work

* Do NOT use browser's offline/online mechanisms

* Fix test
2025-05-29 15:02:12 -04:00
0eebb76bfd Update Bone Plate (#7260)
* Add clock

* update bone plate

* header check

* adding nick b's comments

* Update kcl-samples simulation test output

* Update kcl-samples simulation test output

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-05-29 09:59:27 -07:00
464372e7ed Use the same OS images for web and desktop e2e (#7275) 2025-05-29 12:51:11 -04:00
82 changed files with 5804 additions and 86382 deletions

View File

@ -217,7 +217,10 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
include:
- os: "runs-on=${{ github.run_id }}/family=i7ie.2xlarge/image=ubuntu22-full-x64"
- os: namespace-profile-macos-8-cores
- os: windows-latest-8-cores
runs-on: ${{ matrix.os }}
name: e2e:web (${{ contains(matrix.os, 'ubuntu') && 'ubuntu' || (contains(matrix.os, 'windows') && 'windows' || 'macos') }})
env:

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,50 @@
---
title: "assert"
subtitle: "Function in std"
excerpt: ""
layout: manual
---
```kcl
assert(
@actual: number,
isGreaterThan?: number,
isLessThan?: number,
isGreaterThanOrEqual?: number,
isLessThanOrEqual?: number,
isEqualTo?: number,
tolerance?: number,
error?: string,
)
```
Check a value meets some expected conditions at runtime. Program terminates with an error if conditions aren't met.
If you provide multiple conditions, they will all be checked and all must be met.
### Arguments
| Name | Type | Description | Required |
|----------|------|-------------|----------|
| `actual` | [`number`](/docs/kcl-std/types/std-types-number) | Value to check. If this is the boolean value true, assert passes. Otherwise it fails.. | Yes |
| `isGreaterThan` | [`number`](/docs/kcl-std/types/std-types-number) | Comparison argument. If given, checks the `actual` value is greater than this. | No |
| `isLessThan` | [`number`](/docs/kcl-std/types/std-types-number) | Comparison argument. If given, checks the `actual` value is less than this. | No |
| `isGreaterThanOrEqual` | [`number`](/docs/kcl-std/types/std-types-number) | Comparison argument. If given, checks the `actual` value is greater than or equal to this. | No |
| `isLessThanOrEqual` | [`number`](/docs/kcl-std/types/std-types-number) | Comparison argument. If given, checks the `actual` value is less than or equal to this. | No |
| `isEqualTo` | [`number`](/docs/kcl-std/types/std-types-number) | Comparison argument. If given, checks the `actual` value is less than or equal to this. | No |
| `tolerance` | [`number`](/docs/kcl-std/types/std-types-number) | If `isEqualTo` is used, this is the tolerance to allow for the comparison. This tolerance is used because KCL's number system has some floating-point imprecision when used with very large decimal places. | No |
| `error` | [`string`](/docs/kcl-std/types/std-types-string) | If the value was false, the program will terminate with this error message | No |
### Examples
```kcl
n = 10
assert(n, isEqualTo = 10)
assert(n, isGreaterThanOrEqual = 0, isLessThan = 100, error = "number should be between 0 and 100")
assert(1.0000000000012, isEqualTo = 1, tolerance = 0.0001, error = "number should be almost exactly 1")
```

View File

@ -0,0 +1,35 @@
---
title: "assertIs"
subtitle: "Function in std"
excerpt: "Asserts that a value is the boolean value true."
layout: manual
---
Asserts that a value is the boolean value true.
```kcl
assertIs(
@actual: bool,
error?: string,
)
```
### Arguments
| Name | Type | Description | Required |
|----------|------|-------------|----------|
| `actual` | [`bool`](/docs/kcl-std/types/std-types-bool) | Value to check. If this is the boolean value true, assert passes. Otherwise it fails.. | Yes |
| `error` | [`string`](/docs/kcl-std/types/std-types-string) | If the value was false, the program will terminate with this error message | No |
### Examples
```kcl
kclIsFun = true
assertIs(kclIsFun)
```

View File

@ -9,7 +9,7 @@ layout: manual
```kcl
circle(
@sketch_or_surface: Sketch | Plane | Face,
@sketchOrSurface: Sketch | Plane | Face,
center: Point2d,
radius?: number(Length),
diameter?: number(Length),
@ -24,7 +24,7 @@ the provided (x, y) origin point.
| Name | Type | Description | Required |
|----------|------|-------------|----------|
| `sketch_or_surface` | [`Sketch`](/docs/kcl-std/types/std-types-Sketch) or [`Plane`](/docs/kcl-std/types/std-types-Plane) or [`Face`](/docs/kcl-std/types/std-types-Face) | Sketch to extend, or plane or surface to sketch on. | Yes |
| `sketchOrSurface` | [`Sketch`](/docs/kcl-std/types/std-types-Sketch) or [`Plane`](/docs/kcl-std/types/std-types-Plane) or [`Face`](/docs/kcl-std/types/std-types-Face) | Sketch to extend, or plane or surface to sketch on. | Yes |
| `center` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | The center of the circle. | Yes |
| `radius` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The radius of the circle. Incompatible with `diameter`. | No |
| `diameter` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The diameter of the circle. Incompatible with `radius`. | No |

View File

@ -9,11 +9,11 @@ Construct a circle derived from 3 points.
```kcl
circleThreePoint(
@sketchSurfaceOrGroup: Sketch | Plane | Face,
@sketchOrSurface: Sketch | Plane | Face,
p1: Point2d,
p2: Point2d,
p3: Point2d,
tag?: TagDeclarator,
tag?: tag,
): Sketch
```
@ -23,11 +23,11 @@ circleThreePoint(
| Name | Type | Description | Required |
|----------|------|-------------|----------|
| `sketchSurfaceOrGroup` | [`Sketch`](/docs/kcl-std/types/std-types-Sketch) or [`Plane`](/docs/kcl-std/types/std-types-Plane) or [`Face`](/docs/kcl-std/types/std-types-Face) | Plane or surface to sketch on. | Yes |
| `sketchOrSurface` | [`Sketch`](/docs/kcl-std/types/std-types-Sketch) or [`Plane`](/docs/kcl-std/types/std-types-Plane) or [`Face`](/docs/kcl-std/types/std-types-Face) | Plane or surface to sketch on. | Yes |
| `p1` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | 1st point to derive the circle. | Yes |
| `p2` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | 2nd point to derive the circle. | Yes |
| `p3` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | 3rd point to derive the circle. | Yes |
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`TagDeclarator`](/docs/kcl-lang/types#TagDeclarator) | Identifier for the circle to reference elsewhere. | No |
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`tag`](/docs/kcl-std/types/std-types-tag) | Identifier for the circle to reference elsewhere. | No |
### Returns
@ -38,7 +38,7 @@ circleThreePoint(
```kcl
exampleSketch = startSketchOn(XY)
|> circleThreePoint(p1 = [10, 10], p2 = [20, 8], p3 = [15, 5])
|> circleThreePoint(p1 = [10,10], p2 = [20,8], p3 = [15,5])
|> extrude(length = 5)
```

View File

@ -1,39 +1,43 @@
---
title: "extrude"
subtitle: "Function in std::sketch"
excerpt: "Extend a 2-dimensional sketch through a third dimension in order to create new 3-dimensional volume, or if extruded into an existing volume, cut into an existing solid."
excerpt: ""
layout: manual
---
Extend a 2-dimensional sketch through a third dimension in order to create new 3-dimensional volume, or if extruded into an existing volume, cut into an existing solid.
```kcl
extrude(
@sketches: [Sketch],
length: number,
@sketches: [Sketch; 1+],
length: number(Length),
symmetric?: bool,
bidirectionalLength?: number,
tagStart?: TagDeclarator,
tagEnd?: TagDeclarator,
): [Solid]
bidirectionalLength?: number(Length),
tagStart?: tag,
tagEnd?: tag,
): [Solid; 1+]
```
You can provide more than one sketch to extrude, and they will all be extruded in the same direction.
Extend a 2-dimensional sketch through a third dimension in order to
create new 3-dimensional volume, or if extruded into an existing volume,cut into an existing solid.
You can provide more than one sketch to extrude, and they will all be
extruded in the same direction.
### Arguments
| Name | Type | Description | Required |
|----------|------|-------------|----------|
| `sketches` | [`[Sketch]`](/docs/kcl-std/types/std-types-Sketch) | Which sketch or sketches should be extruded | Yes |
| `length` | [`number`](/docs/kcl-std/types/std-types-number) | How far to extrude the given sketches | Yes |
| `sketches` | [`[Sketch; 1+]`](/docs/kcl-std/types/std-types-Sketch) | Which sketch or sketches should be extruded. | Yes |
| `length` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | How far to extrude the given sketches. | Yes |
| `symmetric` | [`bool`](/docs/kcl-std/types/std-types-bool) | If true, the extrusion will happen symmetrically around the sketch. Otherwise, the extrusion will happen on only one side of the sketch. | No |
| `bidirectionalLength` | [`number`](/docs/kcl-std/types/std-types-number) | If specified, will also extrude in the opposite direction to 'distance' to the specified distance. If 'symmetric' is true, this value is ignored. | No |
| `tagStart` | [`TagDeclarator`](/docs/kcl-lang/types#TagDeclarator) | A named tag for the face at the start of the extrusion, i.e. the original sketch | No |
| `tagEnd` | [`TagDeclarator`](/docs/kcl-lang/types#TagDeclarator) | A named tag for the face at the end of the extrusion, i.e. the new face created by extruding the original sketch | No |
| `bidirectionalLength` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | If specified, will also extrude in the opposite direction to 'distance' to the specified distance. If 'symmetric' is true, this value is ignored. | No |
| `tagStart` | [`tag`](/docs/kcl-std/types/std-types-tag) | A named tag for the face at the start of the extrusion, i.e. the original sketch. | No |
| `tagEnd` | [`tag`](/docs/kcl-std/types/std-types-tag) | A named tag for the face at the end of the extrusion, i.e. the new face created by extruding the original sketch. | No |
### Returns
[`[Solid]`](/docs/kcl-std/types/std-types-Solid)
[`[Solid; 1+]`](/docs/kcl-std/types/std-types-Solid)
### Examples
@ -42,10 +46,18 @@ You can provide more than one sketch to extrude, and they will all be extruded i
example = startSketchOn(XZ)
|> startProfile(at = [0, 0])
|> line(end = [10, 0])
|> arc(angleStart = 120, angleEnd = 0, radius = 5)
|> arc(
angleStart = 120,
angleEnd = 0,
radius = 5,
)
|> line(end = [5, 0])
|> line(end = [0, 10])
|> bezierCurve(control1 = [-10, 0], control2 = [2, 10], end = [-5, 10])
|> bezierCurve(
control1 = [-10, 0],
control2 = [2, 10],
end = [-5, 10],
)
|> line(end = [-5, -2])
|> close()
|> extrude(length = 10)
@ -56,10 +68,18 @@ example = startSketchOn(XZ)
```kcl
exampleSketch = startSketchOn(XZ)
|> startProfile(at = [-10, 0])
|> arc(angleStart = 120, angleEnd = -60, radius = 5)
|> arc(
angleStart = 120,
angleEnd = -60,
radius = 5,
)
|> line(end = [10, 0])
|> line(end = [5, 0])
|> bezierCurve(control1 = [-3, 0], control2 = [2, 10], end = [-5, 10])
|> bezierCurve(
control1 = [-3, 0],
control2 = [2, 10],
end = [-5, 10],
)
|> line(end = [-4, 10])
|> line(end = [-5, -2])
|> close()
@ -72,10 +92,18 @@ example = extrude(exampleSketch, length = 10)
```kcl
exampleSketch = startSketchOn(XZ)
|> startProfile(at = [-10, 0])
|> arc(angleStart = 120, angleEnd = -60, radius = 5)
|> arc(
angleStart = 120,
angleEnd = -60,
radius = 5,
)
|> line(end = [10, 0])
|> line(end = [5, 0])
|> bezierCurve(control1 = [-3, 0], control2 = [2, 10], end = [-5, 10])
|> bezierCurve(
control1 = [-3, 0],
control2 = [2, 10],
end = [-5, 10],
)
|> line(end = [-4, 10])
|> line(end = [-5, -2])
|> close()
@ -88,10 +116,18 @@ example = extrude(exampleSketch, length = 20, symmetric = true)
```kcl
exampleSketch = startSketchOn(XZ)
|> startProfile(at = [-10, 0])
|> arc(angleStart = 120, angleEnd = -60, radius = 5)
|> arc(
angleStart = 120,
angleEnd = -60,
radius = 5,
)
|> line(end = [10, 0])
|> line(end = [5, 0])
|> bezierCurve(control1 = [-3, 0], control2 = [2, 10], end = [-5, 10])
|> bezierCurve(
control1 = [-3, 0],
control2 = [2, 10],
end = [-5, 10],
)
|> line(end = [-4, 10])
|> line(end = [-5, -2])
|> close()

File diff suppressed because one or more lines are too long

View File

@ -1,39 +1,41 @@
---
title: "patternCircular2d"
subtitle: "Function in std::sketch"
excerpt: "Repeat a 2-dimensional sketch some number of times along a partial or complete circle some specified number of times. Each object may additionally be rotated along the circle, ensuring orientation of the solid with respect to the center of the circle is maintained."
excerpt: ""
layout: manual
---
Repeat a 2-dimensional sketch some number of times along a partial or complete circle some specified number of times. Each object may additionally be rotated along the circle, ensuring orientation of the solid with respect to the center of the circle is maintained.
```kcl
patternCircular2d(
@sketchSet: [Sketch],
instances: number,
@sketches: [Sketch; 1+],
instances: number(_),
center: Point2d,
arcDegrees?: number,
arcDegrees?: number(Angle),
rotateDuplicates?: bool,
useOriginal?: bool,
): [Sketch]
): [Sketch; 1+]
```
Repeat a 2-dimensional sketch some number of times along a partial or
complete circle some specified number of times. Each object mayadditionally be rotated along the circle, ensuring orientation of the
solid with respect to the center of the circle is maintained.
### Arguments
| Name | Type | Description | Required |
|----------|------|-------------|----------|
| `sketchSet` | [`[Sketch]`](/docs/kcl-std/types/std-types-Sketch) | Which sketch(es) to pattern | Yes |
| `instances` | [`number`](/docs/kcl-std/types/std-types-number) | The number of total instances. Must be greater than or equal to 1. This includes the original entity. For example, if instances is 2, there will be two copies -- the original, and one new copy. If instances is 1, this has no effect. | Yes |
| `sketches` | [`[Sketch; 1+]`](/docs/kcl-std/types/std-types-Sketch) | The sketch(es) to duplicate. | Yes |
| `instances` | [`number(_)`](/docs/kcl-std/types/std-types-number) | The number of total instances. Must be greater than or equal to 1. This includes the original entity. For example, if instances is 2, there will be two copies -- the original, and one new copy. If instances is 1, this has no effect. | Yes |
| `center` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | The center about which to make the pattern. This is a 2D vector. | Yes |
| `arcDegrees` | [`number`](/docs/kcl-std/types/std-types-number) | The arc angle (in degrees) to place the repetitions. Must be greater than 0. Defaults to 360. | No |
| `rotateDuplicates` | [`bool`](/docs/kcl-std/types/std-types-bool) | Whether or not to rotate the duplicates as they are copied. Defaults to true. | No |
| `useOriginal` | [`bool`](/docs/kcl-std/types/std-types-bool) | If the target was sketched on an extrusion, setting this will use the original sketch as the target, not the entire joined solid. Defaults to false. | No |
| `arcDegrees` | [`number(Angle)`](/docs/kcl-std/types/std-types-number) | The arc angle (in degrees) to place the repetitions. Must be greater than 0. | No |
| `rotateDuplicates` | [`bool`](/docs/kcl-std/types/std-types-bool) | Whether or not to rotate the duplicates as they are copied. | No |
| `useOriginal` | [`bool`](/docs/kcl-std/types/std-types-bool) | If the target was sketched on an extrusion, setting this will use the original sketch as the target, not the entire joined solid. | No |
### Returns
[`[Sketch]`](/docs/kcl-std/types/std-types-Sketch)
[`[Sketch; 1+]`](/docs/kcl-std/types/std-types-Sketch)
### Examples
@ -49,7 +51,7 @@ exampleSketch = startSketchOn(XZ)
center = [0, 0],
instances = 13,
arcDegrees = 360,
rotateDuplicates = true,
rotateDuplicates = true
)
example = extrude(exampleSketch, length = 1)

File diff suppressed because one or more lines are too long

View File

@ -9,9 +9,9 @@ Create a regular polygon with the specified number of sides that is either inscr
```kcl
polygon(
@sketchSurfaceOrGroup: Sketch | Plane | Face,
radius: number,
numSides: u64,
@sketchOrSurface: Sketch | Plane | Face,
radius: number(Length),
numSides: number(_),
center: Point2d,
inscribed?: bool,
): Sketch
@ -23,11 +23,11 @@ polygon(
| Name | Type | Description | Required |
|----------|------|-------------|----------|
| `sketchSurfaceOrGroup` | [`Sketch`](/docs/kcl-std/types/std-types-Sketch) or [`Plane`](/docs/kcl-std/types/std-types-Plane) or [`Face`](/docs/kcl-std/types/std-types-Face) | Plane or surface to sketch on | Yes |
| `radius` | [`number`](/docs/kcl-std/types/std-types-number) | The radius of the polygon | Yes |
| `numSides` | `u64` | The number of sides in the polygon | Yes |
| `center` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | The center point of the polygon | Yes |
| `inscribed` | [`bool`](/docs/kcl-std/types/std-types-bool) | Whether the polygon is inscribed (true, the default) or circumscribed (false) about a circle with the specified radius | No |
| `sketchOrSurface` | [`Sketch`](/docs/kcl-std/types/std-types-Sketch) or [`Plane`](/docs/kcl-std/types/std-types-Plane) or [`Face`](/docs/kcl-std/types/std-types-Face) | Plane or surface to sketch on. | Yes |
| `radius` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The radius of the polygon. | Yes |
| `numSides` | [`number(_)`](/docs/kcl-std/types/std-types-number) | The number of sides in the polygon. | Yes |
| `center` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | The center point of the polygon. | Yes |
| `inscribed` | [`bool`](/docs/kcl-std/types/std-types-bool) | Whether the polygon is inscribed (true, the default) or circumscribed (false) about a circle with the specified radius. | No |
### Returns
@ -40,11 +40,11 @@ polygon(
// Create a regular hexagon inscribed in a circle of radius 10
hex = startSketchOn(XY)
|> polygon(
radius = 10,
numSides = 6,
center = [0, 0],
inscribed = true,
)
radius = 10,
numSides = 6,
center = [0, 0],
inscribed = true,
)
example = extrude(hex, length = 5)
```
@ -55,11 +55,11 @@ example = extrude(hex, length = 5)
// Create a square circumscribed around a circle of radius 5
square = startSketchOn(XY)
|> polygon(
radius = 5.0,
numSides = 4,
center = [10, 10],
inscribed = false,
)
radius = 5.0,
numSides = 4,
center = [10, 10],
inscribed = false,
)
example = extrude(square, length = 5)
```

File diff suppressed because one or more lines are too long

View File

@ -9,12 +9,11 @@ layout: manual
### Functions
* [**std**](/docs/kcl-std/modules/std)
* [`assert`](/docs/kcl-std/assert)
* [`assertIs`](/docs/kcl-std/assertIs)
* [`assert`](/docs/kcl-std/functions/std-assert)
* [`assertIs`](/docs/kcl-std/functions/std-assertIs)
* [`clone`](/docs/kcl-std/functions/std-clone)
* [`helix`](/docs/kcl-std/functions/std-helix)
* [`offsetPlane`](/docs/kcl-std/functions/std-offsetPlane)
* [`patternLinear2d`](/docs/kcl-std/patternLinear2d)
* [**std::appearance**](/docs/kcl-std/modules/std-appearance)
* [`appearance::hexString`](/docs/kcl-std/functions/std-appearance-hexString)
* [**std::array**](/docs/kcl-std/modules/std-array)
@ -53,9 +52,9 @@ layout: manual
* [`arc`](/docs/kcl-std/arc)
* [`bezierCurve`](/docs/kcl-std/bezierCurve)
* [`circle`](/docs/kcl-std/functions/std-sketch-circle)
* [`circleThreePoint`](/docs/kcl-std/circleThreePoint)
* [`circleThreePoint`](/docs/kcl-std/functions/std-sketch-circleThreePoint)
* [`close`](/docs/kcl-std/close)
* [`extrude`](/docs/kcl-std/extrude)
* [`extrude`](/docs/kcl-std/functions/std-sketch-extrude)
* [`getCommonEdge`](/docs/kcl-std/functions/std-sketch-getCommonEdge)
* [`getNextAdjacentEdge`](/docs/kcl-std/functions/std-sketch-getNextAdjacentEdge)
* [`getOppositeEdge`](/docs/kcl-std/functions/std-sketch-getOppositeEdge)
@ -64,10 +63,11 @@ layout: manual
* [`lastSegX`](/docs/kcl-std/lastSegX)
* [`lastSegY`](/docs/kcl-std/lastSegY)
* [`line`](/docs/kcl-std/line)
* [`loft`](/docs/kcl-std/loft)
* [`patternCircular2d`](/docs/kcl-std/patternCircular2d)
* [`loft`](/docs/kcl-std/functions/std-sketch-loft)
* [`patternCircular2d`](/docs/kcl-std/functions/std-sketch-patternCircular2d)
* [`patternLinear2d`](/docs/kcl-std/functions/std-sketch-patternLinear2d)
* [`patternTransform2d`](/docs/kcl-std/functions/std-sketch-patternTransform2d)
* [`polygon`](/docs/kcl-std/polygon)
* [`polygon`](/docs/kcl-std/functions/std-sketch-polygon)
* [`profileStart`](/docs/kcl-std/profileStart)
* [`profileStartX`](/docs/kcl-std/profileStartX)
* [`profileStartY`](/docs/kcl-std/profileStartY)
@ -83,7 +83,7 @@ layout: manual
* [`startProfile`](/docs/kcl-std/startProfile)
* [`startSketchOn`](/docs/kcl-std/startSketchOn)
* [`subtract2d`](/docs/kcl-std/subtract2d)
* [`sweep`](/docs/kcl-std/sweep)
* [`sweep`](/docs/kcl-std/functions/std-sketch-sweep)
* [`tangentToEnd`](/docs/kcl-std/tangentToEnd)
* [`tangentialArc`](/docs/kcl-std/tangentialArc)
* [`xLine`](/docs/kcl-std/xLine)

View File

@ -17,9 +17,9 @@ This module contains functions for creating and manipulating sketches, and makin
* [`arc`](/docs/kcl-std/arc)
* [`bezierCurve`](/docs/kcl-std/bezierCurve)
* [`circle`](/docs/kcl-std/functions/std-sketch-circle)
* [`circleThreePoint`](/docs/kcl-std/circleThreePoint)
* [`circleThreePoint`](/docs/kcl-std/functions/std-sketch-circleThreePoint)
* [`close`](/docs/kcl-std/close)
* [`extrude`](/docs/kcl-std/extrude)
* [`extrude`](/docs/kcl-std/functions/std-sketch-extrude)
* [`getCommonEdge`](/docs/kcl-std/functions/std-sketch-getCommonEdge)
* [`getNextAdjacentEdge`](/docs/kcl-std/functions/std-sketch-getNextAdjacentEdge)
* [`getOppositeEdge`](/docs/kcl-std/functions/std-sketch-getOppositeEdge)
@ -28,10 +28,11 @@ This module contains functions for creating and manipulating sketches, and makin
* [`lastSegX`](/docs/kcl-std/lastSegX)
* [`lastSegY`](/docs/kcl-std/lastSegY)
* [`line`](/docs/kcl-std/line)
* [`loft`](/docs/kcl-std/loft)
* [`patternCircular2d`](/docs/kcl-std/patternCircular2d)
* [`loft`](/docs/kcl-std/functions/std-sketch-loft)
* [`patternCircular2d`](/docs/kcl-std/functions/std-sketch-patternCircular2d)
* [`patternLinear2d`](/docs/kcl-std/functions/std-sketch-patternLinear2d)
* [`patternTransform2d`](/docs/kcl-std/functions/std-sketch-patternTransform2d)
* [`polygon`](/docs/kcl-std/polygon)
* [`polygon`](/docs/kcl-std/functions/std-sketch-polygon)
* [`profileStart`](/docs/kcl-std/profileStart)
* [`profileStartX`](/docs/kcl-std/profileStartX)
* [`profileStartY`](/docs/kcl-std/profileStartY)
@ -47,7 +48,7 @@ This module contains functions for creating and manipulating sketches, and makin
* [`startProfile`](/docs/kcl-std/startProfile)
* [`startSketchOn`](/docs/kcl-std/startSketchOn)
* [`subtract2d`](/docs/kcl-std/subtract2d)
* [`sweep`](/docs/kcl-std/sweep)
* [`sweep`](/docs/kcl-std/functions/std-sketch-sweep)
* [`tangentToEnd`](/docs/kcl-std/tangentToEnd)
* [`tangentialArc`](/docs/kcl-std/tangentialArc)
* [`xLine`](/docs/kcl-std/xLine)

View File

@ -36,10 +36,9 @@ You might also want the [KCL language reference](/docs/kcl-lang) or the [KCL gui
* [`Y`](/docs/kcl-std/consts/std-Y)
* [`YZ`](/docs/kcl-std/consts/std-YZ)
* [`Z`](/docs/kcl-std/consts/std-Z)
* [`assert`](/docs/kcl-std/assert)
* [`assertIs`](/docs/kcl-std/assertIs)
* [`assert`](/docs/kcl-std/functions/std-assert)
* [`assertIs`](/docs/kcl-std/functions/std-assertIs)
* [`clone`](/docs/kcl-std/functions/std-clone)
* [`helix`](/docs/kcl-std/functions/std-helix)
* [`offsetPlane`](/docs/kcl-std/functions/std-offsetPlane)
* [`patternLinear2d`](/docs/kcl-std/patternLinear2d)

File diff suppressed because it is too large Load Diff

View File

@ -265,6 +265,7 @@ middle(0)
})
await expect(
page.getByText(`assert failed: Expected 0 to be greater than 0 but it wasn't
assert()
check()
middle()`)
).toBeVisible()

View File

@ -1733,7 +1733,7 @@ profile003 = startProfile(sketch001, at = [206.63, -56.73])
await page.waitForTimeout(600)
})
const codeFromTangentialArc = ` |> tangentialArc(endAbsolute = [39.49, 88.22])`
const codeFromTangentialArc = ` |> tangentialArc(end = [-10.82, 144.95])`
await test.step('check that tangential tool does not snap to other profile starts', async () => {
await toolbar.selectTangentialArc()
await page.waitForTimeout(1000)
@ -1755,7 +1755,7 @@ profile003 = startProfile(sketch001, at = [206.63, -56.73])
// check pixel is now gray at tanArcLocation to verify code has executed
await scene.expectPixelColor([26, 26, 26], tanArcLocation, 15)
await editor.expectEditor.not.toContain(
`tangentialArc(endAbsolute = [39.49, 88.22])`
`tangentialArc(end = [-10.82, 144.95])`
)
})
@ -1955,7 +1955,7 @@ profile003 = startProfile(sketch001, at = [206.63, -56.73])
await endArcStartLine()
await editor.expectEditor.toContain(
`|> tangentialArc(endAbsolute = [16.61, 4.14])`
`|> tangentialArc(end = [2.98, -7.52])`
)
// Add a three-point arc segment
@ -3181,7 +3181,7 @@ test.describe('Redirecting to home page and back to the original file should cle
sketch001 = startSketchOn(XZ)
profile001 = startProfile(sketch001, at = [0, 0])
|> line(end = [191.39, 191.39])
|> tangentialArc(endAbsolute = [287.08, 95.69], tag = $seg01)
|> tangentialArc(end = [95.69, -95.7], tag = $seg01)
|> angledLine(angle = tangentToEnd(seg01), length = 135.34)
|> arc(interiorAbsolute = [191.39, -95.69], endAbsolute = [287.08, -95.69], tag = $seg02)
|> angledLine(angle = tangentToEnd(seg02) + turns::HALF_TURN, length = 270.67)

View File

@ -375,22 +375,22 @@ test.describe(
await expect(u.codeLocator).toHaveText(code)
await toolbar.selectTangentialArc()
await page.waitForTimeout(100)
await page.waitForTimeout(200)
// click to continue profile
await page.mouse.click(813, 392)
await page.waitForTimeout(100)
await page.waitForTimeout(300)
await page.mouse.click(startXPx + PUR * 30, 500 - PUR * 20)
code += `
|> tangentialArc(endAbsolute = [551.2, -62.01])`
|> tangentialArc(end = [184.31, 184.31])`
await expect(u.codeLocator).toHaveText(code)
// click tangential arc tool again to unequip it
// it will be available directly in the toolbar since it was last equipped
await toolbar.tangentialArcBtn.click()
await page.waitForTimeout(100)
await page.waitForTimeout(1000)
// screen shot should show the sketch
await expect(page).toHaveScreenshot({
@ -472,20 +472,20 @@ test.describe(
await expect(u.codeLocator).toHaveText(code)
await toolbar.selectTangentialArc()
await page.waitForTimeout(100)
await page.waitForTimeout(200)
// click to continue profile
await page.mouse.click(813, 392)
await page.waitForTimeout(100)
await page.waitForTimeout(300)
await page.mouse.click(startXPx + PUR * 30, 500 - PUR * 20)
code += `
|> tangentialArc(endAbsolute = [551.2, -62.01])`
|> tangentialArc(end = [184.31, 184.31])`
await expect(u.codeLocator).toHaveText(code)
await toolbar.tangentialArcBtn.click()
await page.waitForTimeout(100)
await page.waitForTimeout(1000)
// screen shot should show the sketch
await expect(page).toHaveScreenshot({

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

View File

@ -29,27 +29,27 @@ plateRevolve = startSketchOn(YZ)
|> close()
|> revolve(axis = Y, angle = 65, symmetric = true)
// Create a hole sketch with the size and location of each bolt hole
holeSketch = startSketchOn(XZ)
hole01 = circle(holeSketch, center = [0, 12.25], radius = boltSize / 2)
|> extrude(length = -100)
hole02 = circle(holeSketch, center = [0, 29.5], radius = boltSize / 2)
|> extrude(length = -100)
hole03 = circle(holeSketch, center = [0, 46.25], radius = boltSize / 2)
|> extrude(length = -100)
hole04 = circle(holeSketch, center = [0, 77], radius = boltSize / 2)
|> extrude(length = -100)
hole05 = circle(holeSketch, center = [0, 100], radius = boltSize / 2)
|> extrude(length = -100)
hole06 = circle(holeSketch, center = [0, 130], radius = boltSize / 2)
|> extrude(length = -100)
hole07 = circle(holeSketch, center = [-20, 130], radius = boltSize / 2)
|> extrude(length = -100)
hole08 = circle(holeSketch, center = [20, 130], radius = boltSize / 2)
|> extrude(length = -100)
// Define a function to create and extrude holes
fn holeFn(@center) {
return startSketchOn(XZ)
|> circle(center = center, diameter = boltSize)
|> extrude(length = -100)
}
// Cut each guiding clearance hole from the bone plate
solid001 = subtract([plateRevolve], tools = union([hole01, hole02]))
solid002 = subtract([solid001], tools = union([hole03, hole04]))
solid003 = subtract([solid002], tools = union([hole05, hole06]))
solid004 = subtract([solid003], tools = union([hole07, hole08]))
// Create a hole sketch with the size and location of each bolt hole
holeCenters = [
[0, 12.25],
[0, 29.5],
[0, 46.25],
[0, 77],
[0, 100],
[0, 130],
[-20, 130],
[20, 130]
]
// Use map to apply the hole creation function to the list of center coordinates
holes = map(holeCenters, f = holeFn)
// Cut each guiding clearance hole from the bone plate using a single subtract operation
solid = subtract([plateRevolve], tools = holes)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 83 KiB

After

Width:  |  Height:  |  Size: 83 KiB

View File

@ -117,6 +117,23 @@ pub const TEST_NAMES: &[&str] = &[
"std-sketch-getOppositeEdge-0",
"std-sketch-getPreviousAdjacentEdge-0",
"std-sketch-getNextAdjacentEdge-0",
"std-sketch-extrude-0",
"std-sketch-extrude-1",
"std-sketch-extrude-2",
"std-sketch-extrude-3",
"std-sketch-polygon-0",
"std-sketch-polygon-1",
"std-sketch-sweep-0",
"std-sketch-sweep-1",
"std-sketch-sweep-2",
"std-sketch-sweep-3",
"std-sketch-loft-0",
"std-sketch-loft-1",
"std-sketch-loft-2",
"std-sketch-patternLinear2d-0",
"std-sketch-patternLinear2d-1",
"std-sketch-patternCircular2d-0",
"std-sketch-circleThreePoint-0",
"std-solid-appearance-0",
"std-solid-appearance-1",
"std-solid-appearance-2",

View File

@ -644,13 +644,13 @@ impl FnData {
format!("{}({})", self.preferred_name, args.join(", "))
}
fn to_signature_help(&self) -> SignatureHelp {
pub(crate) fn to_signature_help(&self) -> SignatureHelp {
// TODO Fill this in based on the current position of the cursor.
let active_parameter = None;
SignatureHelp {
signatures: vec![SignatureInformation {
label: self.preferred_name.clone(),
label: self.preferred_name.clone() + &self.fn_signature(),
documentation: self.short_docs().map(|s| {
Documentation::MarkupContent(MarkupContent {
kind: MarkupKind::Markdown,
@ -824,6 +824,7 @@ impl ArgData {
),
)),
Some("Axis2d | Edge") | Some("Axis3d | Edge") => Some((index, format!(r#"{label}${{{index}:X}}"#))),
Some("Sketch") | Some("Sketch | Helix") => Some((index, format!(r#"{label}${{{index}:sketch000}}"#))),
Some("Edge") => Some((index, format!(r#"{label}${{{index}:tag_or_edge_fn}}"#))),
Some("[Edge; 1+]") => Some((index, format!(r#"{label}[${{{index}:tag_or_edge_fn}}]"#))),
Some("Plane") => Some((index, format!(r#"{label}${{{}:XY}}"#, index))),
@ -1280,7 +1281,10 @@ mod test {
continue;
};
for i in 0..f.examples.len() {
for (i, (_, props)) in f.examples.iter().enumerate() {
if props.norun {
continue;
}
let name = format!("{}-{i}", f.qual_name.replace("::", "-"));
assert!(TEST_NAMES.contains(&&*name), "Missing test for example \"{name}\", maybe need to update kcl-derive-docs/src/example_tests.rs?")
}

View File

@ -976,9 +976,12 @@ mod tests {
#[test]
fn get_autocomplete_snippet_extrude() {
let extrude_fn: Box<dyn StdLibFn> = Box::new(crate::std::extrude::Extrude);
let snippet = extrude_fn.to_autocomplete_snippet().unwrap();
assert_eq!(snippet, r#"extrude(${0:%}, length = ${1:3.14})"#);
let data = kcl_doc::walk_prelude();
let DocData::Fn(data) = data.find_by_name("extrude").unwrap() else {
panic!();
};
let snippet = data.to_autocomplete_snippet();
assert_eq!(snippet, r#"extrude(length = ${0:10})"#);
}
#[test]
@ -1064,11 +1067,14 @@ mod tests {
#[test]
fn get_autocomplete_snippet_pattern_linear_2d() {
let pattern_fn: Box<dyn StdLibFn> = Box::new(crate::std::patterns::PatternLinear2D);
let snippet = pattern_fn.to_autocomplete_snippet().unwrap();
let data = kcl_doc::walk_prelude();
let DocData::Fn(data) = data.find_by_name("patternLinear2d").unwrap() else {
panic!();
};
let snippet = data.to_autocomplete_snippet();
assert_eq!(
snippet,
r#"patternLinear2d(${0:%}, instances = ${1:10}, distance = ${2:3.14}, axis = [${3:1}, ${4:0}])"#
r#"patternLinear2d(instances = ${0:10}, distance = ${1:10}, axis = [${2:1}, ${3:0}])"#
);
}
@ -1084,16 +1090,22 @@ mod tests {
#[test]
fn get_autocomplete_snippet_loft() {
let loft_fn: Box<dyn StdLibFn> = Box::new(crate::std::loft::Loft);
let snippet = loft_fn.to_autocomplete_snippet().unwrap();
let data = kcl_doc::walk_prelude();
let DocData::Fn(data) = data.find_by_name("loft").unwrap() else {
panic!();
};
let snippet = data.to_autocomplete_snippet();
assert_eq!(snippet, r#"loft([${0:sketch000}, ${1:sketch001}])"#);
}
#[test]
fn get_autocomplete_snippet_sweep() {
let sweep_fn: Box<dyn StdLibFn> = Box::new(crate::std::sweep::Sweep);
let snippet = sweep_fn.to_autocomplete_snippet().unwrap();
assert_eq!(snippet, r#"sweep(${0:%}, path = ${1:sketch000})"#);
let data = kcl_doc::walk_prelude();
let DocData::Fn(data) = data.find_by_name("sweep").unwrap() else {
panic!();
};
let snippet = data.to_autocomplete_snippet();
assert_eq!(snippet, r#"sweep(path = ${0:sketch000})"#);
}
#[test]
@ -1225,18 +1237,21 @@ mod tests {
#[test]
fn get_extrude_signature_help() {
let extrude_fn: Box<dyn StdLibFn> = Box::new(crate::std::extrude::Extrude);
let sh = extrude_fn.to_signature_help();
let data = kcl_doc::walk_prelude();
let DocData::Fn(data) = data.find_by_name("extrude").unwrap() else {
panic!();
};
let sh = data.to_signature_help();
assert_eq!(
sh.signatures[0].label,
r#"extrude(
@sketches: [Sketch],
length: number,
@sketches: [Sketch; 1+],
length: number(Length),
symmetric?: bool,
bidirectionalLength?: number,
tagStart?: TagNode,
tagEnd?: TagNode,
): [Solid]"#
bidirectionalLength?: number(Length),
tagStart?: tag,
tagEnd?: tag,
): [Solid; 1+]"#
);
}
}

View File

@ -1202,17 +1202,7 @@ a1 = startSketchOn(offsetPlane(XY, offset = 10))
"Expected one signature, got {:?}",
signature_help.signatures
);
assert_eq!(
signature_help.signatures[0].label,
r#"extrude(
@sketches: [Sketch],
length: number,
symmetric?: bool,
bidirectionalLength?: number,
tagStart?: TagNode,
tagEnd?: TagNode,
): [Solid]"#
);
assert!(signature_help.signatures[0].label.starts_with("extrude"));
} else {
panic!("Expected signature help");
}
@ -1300,17 +1290,7 @@ a1 = startSketchOn(offsetPlane(XY, offset = 10))
"Expected one signature, got {:?}",
signature_help.signatures
);
assert_eq!(
signature_help.signatures[0].label,
r#"extrude(
@sketches: [Sketch],
length: number,
symmetric?: bool,
bidirectionalLength?: number,
tagStart?: TagNode,
tagEnd?: TagNode,
): [Solid]"#
);
assert!(signature_help.signatures[0].label.starts_with("extrude"));
} else {
panic!("Expected signature help");
}
@ -1393,17 +1373,7 @@ a1 = startSketchOn(offsetPlane(XY, offset = 10))
"Expected one signature, got {:?}",
signature_help.signatures
);
assert_eq!(
signature_help.signatures[0].label,
r#"extrude(
@sketches: [Sketch],
length: number,
symmetric?: bool,
bidirectionalLength?: number,
tagStart?: TagNode,
tagEnd?: TagNode,
): [Solid]"#
);
assert!(signature_help.signatures[0].label.starts_with("extrude"));
} else {
panic!("Expected signature help");
}
@ -1491,17 +1461,7 @@ a1 = startSketchOn(offsetPlane(XY, offset = 10))
"Expected one signature, got {:?}",
signature_help.signatures
);
assert_eq!(
signature_help.signatures[0].label,
r#"extrude(
@sketches: [Sketch],
length: number,
symmetric?: bool,
bidirectionalLength?: number,
tagStart?: TagNode,
tagEnd?: TagNode,
): [Solid]"#
);
assert!(signature_help.signatures[0].label.starts_with("extrude"));
} else {
panic!("Expected signature help");
}

View File

@ -1,7 +1,6 @@
//! Standard library assert functions.
use anyhow::Result;
use kcl_derive_docs::stdlib;
use super::args::TyF64;
use crate::{
@ -42,19 +41,6 @@ pub async fn assert(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
Ok(KclValue::none())
}
/// Asserts that a value is the boolean value true.
/// ```no_run
/// kclIsFun = true
/// assertIs(kclIsFun)
/// ```
#[stdlib{
name = "assertIs",
unlabeled_first = true,
args = {
actual = { docs = "Value to check. If this is the boolean value true, assert passes. Otherwise it fails." },
error = { docs = "If the value was false, the program will terminate with this error message" },
}
}]
async fn inner_assert_is(actual: bool, error: Option<String>, args: &Args) -> Result<(), KclError> {
let error_msg = match &error {
Some(x) => x,
@ -63,29 +49,6 @@ async fn inner_assert_is(actual: bool, error: Option<String>, args: &Args) -> Re
_assert(actual, error_msg, args).await
}
/// Check a value meets some expected conditions at runtime. Program terminates with an error if conditions aren't met.
/// If you provide multiple conditions, they will all be checked and all must be met.
///
/// ```no_run
/// n = 10
/// assert(n, isEqualTo = 10)
/// assert(n, isGreaterThanOrEqual = 0, isLessThan = 100, error = "number should be between 0 and 100")
/// assert(1.0000000000012, isEqualTo = 1, tolerance = 0.0001, error = "number should be almost exactly 1")
/// ```
#[stdlib {
name = "assert",
unlabeled_first = true,
args = {
actual = { docs = "Value to check. It will be compared with one of the comparison arguments." },
is_greater_than = { docs = "Comparison argument. If given, checks the `actual` value is greater than this." },
is_less_than = { docs = "Comparison argument. If given, checks the `actual` value is less than this." },
is_greater_than_or_equal = { docs = "Comparison argument. If given, checks the `actual` value is greater than or equal to this." },
is_less_than_or_equal = { docs = "Comparison argument. If given, checks the `actual` value is less than or equal to this." },
is_equal_to = { docs = "Comparison argument. If given, checks the `actual` value is less than or equal to this.", include_in_snippet = true },
tolerance = { docs = "If `isEqualTo` is used, this is the tolerance to allow for the comparison. This tolerance is used because KCL's number system has some floating-point imprecision when used with very large decimal places." },
error = { docs = "If the value was false, the program will terminate with this error message" },
}
}]
#[allow(clippy::too_many_arguments)]
async fn inner_assert(
actual: TyF64,

View File

@ -3,7 +3,6 @@
use std::collections::HashMap;
use anyhow::Result;
use kcl_derive_docs::stdlib;
use kcmc::{
each_cmd as mcmd,
length_unit::LengthUnit,
@ -52,113 +51,6 @@ pub async fn extrude(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
Ok(result.into())
}
/// Extend a 2-dimensional sketch through a third dimension in order to
/// create new 3-dimensional volume, or if extruded into an existing volume,
/// cut into an existing solid.
///
/// You can provide more than one sketch to extrude, and they will all be
/// extruded in the same direction.
///
/// ```no_run
/// example = startSketchOn(XZ)
/// |> startProfile(at = [0, 0])
/// |> line(end = [10, 0])
/// |> arc(
/// angleStart = 120,
/// angleEnd = 0,
/// radius = 5,
/// )
/// |> line(end = [5, 0])
/// |> line(end = [0, 10])
/// |> bezierCurve(
/// control1 = [-10, 0],
/// control2 = [2, 10],
/// end = [-5, 10],
/// )
/// |> line(end = [-5, -2])
/// |> close()
/// |> extrude(length = 10)
/// ```
///
/// ```no_run
/// exampleSketch = startSketchOn(XZ)
/// |> startProfile(at = [-10, 0])
/// |> arc(
/// angleStart = 120,
/// angleEnd = -60,
/// radius = 5,
/// )
/// |> line(end = [10, 0])
/// |> line(end = [5, 0])
/// |> bezierCurve(
/// control1 = [-3, 0],
/// control2 = [2, 10],
/// end = [-5, 10],
/// )
/// |> line(end = [-4, 10])
/// |> line(end = [-5, -2])
/// |> close()
///
/// example = extrude(exampleSketch, length = 10)
/// ```
///
/// ```no_run
/// exampleSketch = startSketchOn(XZ)
/// |> startProfile(at = [-10, 0])
/// |> arc(
/// angleStart = 120,
/// angleEnd = -60,
/// radius = 5,
/// )
/// |> line(end = [10, 0])
/// |> line(end = [5, 0])
/// |> bezierCurve(
/// control1 = [-3, 0],
/// control2 = [2, 10],
/// end = [-5, 10],
/// )
/// |> line(end = [-4, 10])
/// |> line(end = [-5, -2])
/// |> close()
///
/// example = extrude(exampleSketch, length = 20, symmetric = true)
/// ```
///
/// ```no_run
/// exampleSketch = startSketchOn(XZ)
/// |> startProfile(at = [-10, 0])
/// |> arc(
/// angleStart = 120,
/// angleEnd = -60,
/// radius = 5,
/// )
/// |> line(end = [10, 0])
/// |> line(end = [5, 0])
/// |> bezierCurve(
/// control1 = [-3, 0],
/// control2 = [2, 10],
/// end = [-5, 10],
/// )
/// |> line(end = [-4, 10])
/// |> line(end = [-5, -2])
/// |> close()
///
/// example = extrude(exampleSketch, length = 10, bidirectionalLength = 50)
/// ```
#[stdlib {
name = "extrude",
feature_tree_operation = true,
unlabeled_first = true,
args = {
sketches = { docs = "Which sketch or sketches should be extruded"},
length = { docs = "How far to extrude the given sketches"},
symmetric = { docs = "If true, the extrusion will happen symmetrically around the sketch. Otherwise, the extrusion will happen on only one side of the sketch." },
bidirectional_length = { docs = "If specified, will also extrude in the opposite direction to 'distance' to the specified distance. If 'symmetric' is true, this value is ignored."},
tag_start = { docs = "A named tag for the face at the start of the extrusion, i.e. the original sketch" },
tag_end = { docs = "A named tag for the face at the end of the extrusion, i.e. the new face created by extruding the original sketch" },
},
tags = ["sketch"]
}]
#[allow(clippy::too_many_arguments)]
async fn inner_extrude(
sketches: Vec<Sketch>,

View File

@ -3,7 +3,6 @@
use std::num::NonZeroU32;
use anyhow::Result;
use kcl_derive_docs::stdlib;
use kcmc::{each_cmd as mcmd, length_unit::LengthUnit, ModelingCmd};
use kittycad_modeling_cmds as kcmc;
@ -55,87 +54,6 @@ pub async fn loft(exec_state: &mut ExecState, args: Args) -> Result<KclValue, Kc
Ok(KclValue::Solid { value })
}
/// Create a 3D surface or solid by interpolating between two or more sketches.
///
/// The sketches need to closed and on the same plane.
///
/// ```no_run
/// // Loft a square and a triangle.
/// squareSketch = startSketchOn(XY)
/// |> startProfile(at = [-100, 200])
/// |> line(end = [200, 0])
/// |> line(end = [0, -200])
/// |> line(end = [-200, 0])
/// |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
/// |> close()
///
/// triangleSketch = startSketchOn(offsetPlane(XY, offset = 75))
/// |> startProfile(at = [0, 125])
/// |> line(end = [-15, -30])
/// |> line(end = [30, 0])
/// |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
/// |> close()
///
/// loft([triangleSketch, squareSketch])
/// ```
///
/// ```no_run
/// // Loft a square, a circle, and another circle.
/// squareSketch = startSketchOn(XY)
/// |> startProfile(at = [-100, 200])
/// |> line(end = [200, 0])
/// |> line(end = [0, -200])
/// |> line(end = [-200, 0])
/// |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
/// |> close()
///
/// circleSketch0 = startSketchOn(offsetPlane(XY, offset = 75))
/// |> circle( center = [0, 100], radius = 50 )
///
/// circleSketch1 = startSketchOn(offsetPlane(XY, offset = 150))
/// |> circle( center = [0, 100], radius = 20 )
///
/// loft([squareSketch, circleSketch0, circleSketch1])
/// ```
///
/// ```no_run
/// // Loft a square, a circle, and another circle with options.
/// squareSketch = startSketchOn(XY)
/// |> startProfile(at = [-100, 200])
/// |> line(end = [200, 0])
/// |> line(end = [0, -200])
/// |> line(end = [-200, 0])
/// |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
/// |> close()
///
/// circleSketch0 = startSketchOn(offsetPlane(XY, offset = 75))
/// |> circle( center = [0, 100], radius = 50 )
///
/// circleSketch1 = startSketchOn(offsetPlane(XY, offset = 150))
/// |> circle( center = [0, 100], radius = 20 )
///
/// loft([squareSketch, circleSketch0, circleSketch1],
/// baseCurveIndex = 0,
/// bezApproximateRational = false,
/// tolerance = 0.000001,
/// vDegree = 2,
/// )
/// ```
#[stdlib {
name = "loft",
feature_tree_operation = true,
unlabeled_first = true,
args = {
sketches = {docs = "Which sketches to loft. Must include at least 2 sketches."},
v_degree = {docs = "Degree of the interpolation. Must be greater than zero. For example, use 2 for quadratic, or 3 for cubic interpolation in the V direction. This defaults to 2, if not specified."},
bez_approximate_rational = {docs = "Attempt to approximate rational curves (such as arcs) using a bezier. This will remove banding around interpolations between arcs and non-arcs. It may produce errors in other scenarios Over time, this field won't be necessary."},
base_curve_index = {docs = "This can be set to override the automatically determined topological base curve, which is usually the first section encountered."},
tolerance = {docs = "Tolerance for the loft operation."},
tag_start = { docs = "A named tag for the face at the start of the loft, i.e. the original sketch" },
tag_end = { docs = "A named tag for the face at the end of the loft, i.e. the last sketch" },
},
tags = ["sketch"]
}]
#[allow(clippy::too_many_arguments)]
async fn inner_loft(
sketches: Vec<Sketch>,

View File

@ -45,7 +45,6 @@ pub type StdFn = fn(
lazy_static! {
static ref CORE_FNS: Vec<Box<dyn StdLibFn>> = vec![
Box::new(crate::std::extrude::Extrude),
Box::new(crate::std::segment::SegEnd),
Box::new(crate::std::segment::SegEndX),
Box::new(crate::std::segment::SegEndY),
@ -57,8 +56,6 @@ lazy_static! {
Box::new(crate::std::segment::SegLen),
Box::new(crate::std::segment::SegAng),
Box::new(crate::std::segment::TangentToEnd),
Box::new(crate::std::shapes::CircleThreePoint),
Box::new(crate::std::shapes::Polygon),
Box::new(crate::std::sketch::InvoluteCircular),
Box::new(crate::std::sketch::Line),
Box::new(crate::std::sketch::XLine),
@ -75,12 +72,6 @@ lazy_static! {
Box::new(crate::std::sketch::TangentialArc),
Box::new(crate::std::sketch::BezierCurve),
Box::new(crate::std::sketch::Subtract2D),
Box::new(crate::std::patterns::PatternLinear2D),
Box::new(crate::std::patterns::PatternCircular2D),
Box::new(crate::std::sweep::Sweep),
Box::new(crate::std::loft::Loft),
Box::new(crate::std::assert::Assert),
Box::new(crate::std::assert::AssertIs)
];
}
@ -233,6 +224,14 @@ pub(crate) fn std_fn(path: &str, fn_name: &str) -> (crate::std::StdFn, StdFnProp
|e, a| Box::pin(crate::std::planes::offset_plane(e, a)),
StdFnProps::default("std::offsetPlane").include_in_feature_tree(),
),
("prelude", "assert") => (
|e, a| Box::pin(crate::std::assert::assert(e, a)),
StdFnProps::default("std::assert"),
),
("prelude", "assertIs") => (
|e, a| Box::pin(crate::std::assert::assert_is(e, a)),
StdFnProps::default("std::assertIs"),
),
("solid", "fillet") => (
|e, a| Box::pin(crate::std::fillet::fillet(e, a)),
StdFnProps::default("std::solid::fillet").include_in_feature_tree(),
@ -301,6 +300,10 @@ pub(crate) fn std_fn(path: &str, fn_name: &str) -> (crate::std::StdFn, StdFnProp
|e, a| Box::pin(crate::std::shapes::circle(e, a)),
StdFnProps::default("std::sketch::circle"),
),
("sketch", "extrude") => (
|e, a| Box::pin(crate::std::extrude::extrude(e, a)),
StdFnProps::default("std::sketch::extrude").include_in_feature_tree(),
),
("sketch", "patternTransform2d") => (
|e, a| Box::pin(crate::std::patterns::pattern_transform_2d(e, a)),
StdFnProps::default("std::sketch::patternTransform2d"),
@ -309,6 +312,22 @@ pub(crate) fn std_fn(path: &str, fn_name: &str) -> (crate::std::StdFn, StdFnProp
|e, a| Box::pin(crate::std::revolve::revolve(e, a)),
StdFnProps::default("std::sketch::revolve").include_in_feature_tree(),
),
("sketch", "sweep") => (
|e, a| Box::pin(crate::std::sweep::sweep(e, a)),
StdFnProps::default("std::sketch::sweep").include_in_feature_tree(),
),
("sketch", "loft") => (
|e, a| Box::pin(crate::std::loft::loft(e, a)),
StdFnProps::default("std::sketch::loft").include_in_feature_tree(),
),
("sketch", "polygon") => (
|e, a| Box::pin(crate::std::shapes::polygon(e, a)),
StdFnProps::default("std::sketch::polygon"),
),
("sketch", "circleThreePoint") => (
|e, a| Box::pin(crate::std::shapes::circle_three_point(e, a)),
StdFnProps::default("std::sketch::circleThreePoint"),
),
("sketch", "getCommonEdge") => (
|e, a| Box::pin(crate::std::edge::get_common_edge(e, a)),
StdFnProps::default("std::sketch::getCommonEdge"),
@ -325,6 +344,14 @@ pub(crate) fn std_fn(path: &str, fn_name: &str) -> (crate::std::StdFn, StdFnProp
|e, a| Box::pin(crate::std::edge::get_previous_adjacent_edge(e, a)),
StdFnProps::default("std::sketch::getPreviousAdjacentEdge"),
),
("sketch", "patternLinear2d") => (
|e, a| Box::pin(crate::std::patterns::pattern_linear_2d(e, a)),
StdFnProps::default("std::sketch::patternLinear2d"),
),
("sketch", "patternCircular2d") => (
|e, a| Box::pin(crate::std::patterns::pattern_circular_2d(e, a)),
StdFnProps::default("std::sketch::patternCircular2d"),
),
("appearance", "hexString") => (
|e, a| Box::pin(crate::std::appearance::hex_string(e, a)),
StdFnProps::default("std::appearance::hexString"),

View File

@ -3,7 +3,6 @@
use std::cmp::Ordering;
use anyhow::Result;
use kcl_derive_docs::stdlib;
use kcmc::{
each_cmd as mcmd, length_unit::LengthUnit, ok_response::OkModelingCmdResponse, shared::Transform,
websocket::OkWebSocketResponseData, ModelingCmd,
@ -546,47 +545,6 @@ pub async fn pattern_linear_2d(exec_state: &mut ExecState, args: Args) -> Result
Ok(sketches.into())
}
/// Repeat a 2-dimensional sketch along some dimension, with a dynamic amount
/// of distance between each repetition, some specified number of times.
///
/// ```no_run
/// /// Pattern using a named axis.
///
/// exampleSketch = startSketchOn(XZ)
/// |> circle(center = [0, 0], radius = 1)
/// |> patternLinear2d(
/// axis = X,
/// instances = 7,
/// distance = 4
/// )
///
/// example = extrude(exampleSketch, length = 1)
/// ```
///
/// ```no_run
/// /// Pattern using a raw axis.
///
/// exampleSketch = startSketchOn(XZ)
/// |> circle(center = [0, 0], radius = 1)
/// |> patternLinear2d(
/// axis = [1, 0],
/// instances = 7,
/// distance = 4
/// )
///
/// example = extrude(exampleSketch, length = 1)
/// ```
#[stdlib {
name = "patternLinear2d",
unlabeled_first = true,
args = {
sketches = { docs = "The sketch(es) to duplicate" },
instances = { docs = "The number of total instances. Must be greater than or equal to 1. This includes the original entity. For example, if instances is 2, there will be two copies -- the original, and one new copy. If instances is 1, this has no effect." },
distance = { docs = "Distance between each repetition. Also known as 'spacing'."},
axis = { docs = "The axis of the pattern. A 2D vector.", snippet_value_array = ["1", "0"] },
use_original = { docs = "If the target was sketched on an extrusion, setting this will use the original sketch as the target, not the entire joined solid. Defaults to false." },
}
}]
async fn inner_pattern_linear_2d(
sketches: Vec<Sketch>,
instances: u32,
@ -810,40 +768,6 @@ pub async fn pattern_circular_2d(exec_state: &mut ExecState, args: Args) -> Resu
Ok(sketches.into())
}
/// Repeat a 2-dimensional sketch some number of times along a partial or
/// complete circle some specified number of times. Each object may
/// additionally be rotated along the circle, ensuring orientation of the
/// solid with respect to the center of the circle is maintained.
///
/// ```no_run
/// exampleSketch = startSketchOn(XZ)
/// |> startProfile(at = [.5, 25])
/// |> line(end = [0, 5])
/// |> line(end = [-1, 0])
/// |> line(end = [0, -5])
/// |> close()
/// |> patternCircular2d(
/// center = [0, 0],
/// instances = 13,
/// arcDegrees = 360,
/// rotateDuplicates = true
/// )
///
/// example = extrude(exampleSketch, length = 1)
/// ```
#[stdlib {
name = "patternCircular2d",
unlabeled_first = true,
args = {
sketch_set = { docs = "Which sketch(es) to pattern" },
instances = { docs = "The number of total instances. Must be greater than or equal to 1. This includes the original entity. For example, if instances is 2, there will be two copies -- the original, and one new copy. If instances is 1, this has no effect."},
center = { docs = "The center about which to make the pattern. This is a 2D vector.", snippet_value_array = ["0", "0"]},
arc_degrees = { docs = "The arc angle (in degrees) to place the repetitions. Must be greater than 0. Defaults to 360."},
rotate_duplicates= { docs = "Whether or not to rotate the duplicates as they are copied. Defaults to true."},
use_original= { docs = "If the target was sketched on an extrusion, setting this will use the original sketch as the target, not the entire joined solid. Defaults to false."},
},
tags = ["sketch"]
}]
#[allow(clippy::too_many_arguments)]
async fn inner_pattern_circular_2d(
sketch_set: Vec<Sketch>,

View File

@ -1,7 +1,6 @@
//! Standard library shapes.
use anyhow::Result;
use kcl_derive_docs::stdlib;
use kcmc::{
each_cmd as mcmd,
length_unit::LengthUnit,
@ -143,26 +142,6 @@ pub async fn circle_three_point(exec_state: &mut ExecState, args: Args) -> Resul
})
}
/// Construct a circle derived from 3 points.
///
/// ```no_run
/// exampleSketch = startSketchOn(XY)
/// |> circleThreePoint(p1 = [10,10], p2 = [20,8], p3 = [15,5])
/// |> extrude(length = 5)
/// ```
#[stdlib {
name = "circleThreePoint",
unlabeled_first = true,
args = {
sketch_surface_or_group = {docs = "Plane or surface to sketch on."},
p1 = {docs = "1st point to derive the circle."},
p2 = {docs = "2nd point to derive the circle."},
p3 = {docs = "3rd point to derive the circle."},
tag = {docs = "Identifier for the circle to reference elsewhere."},
},
tags = ["sketch"]
}]
// Similar to inner_circle, but needs to retain 3-point information in the
// path so it can be used for other features, otherwise it's lost.
async fn inner_circle_three_point(
@ -281,44 +260,6 @@ pub async fn polygon(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
})
}
/// Create a regular polygon with the specified number of sides that is either inscribed or circumscribed around a circle of the specified radius.
///
/// ```no_run
/// // Create a regular hexagon inscribed in a circle of radius 10
/// hex = startSketchOn(XY)
/// |> polygon(
/// radius = 10,
/// numSides = 6,
/// center = [0, 0],
/// inscribed = true,
/// )
///
/// example = extrude(hex, length = 5)
/// ```
///
/// ```no_run
/// // Create a square circumscribed around a circle of radius 5
/// square = startSketchOn(XY)
/// |> polygon(
/// radius = 5.0,
/// numSides = 4,
/// center = [10, 10],
/// inscribed = false,
/// )
/// example = extrude(square, length = 5)
/// ```
#[stdlib {
name = "polygon",
unlabeled_first = true,
args = {
sketch_surface_or_group = { docs = "Plane or surface to sketch on" },
radius = { docs = "The radius of the polygon", include_in_snippet = true },
num_sides = { docs = "The number of sides in the polygon", include_in_snippet = true },
center = { docs = "The center point of the polygon", snippet_value_array = ["0", "0"] },
inscribed = { docs = "Whether the polygon is inscribed (true, the default) or circumscribed (false) about a circle with the specified radius" },
},
tags = ["sketch"]
}]
#[allow(clippy::too_many_arguments)]
async fn inner_polygon(
sketch_surface_or_group: SketchOrSurface,

View File

@ -1,7 +1,6 @@
//! Standard library sweep.
use anyhow::Result;
use kcl_derive_docs::stdlib;
use kcmc::{each_cmd as mcmd, length_unit::LengthUnit, ModelingCmd};
use kittycad_modeling_cmds::{self as kcmc, shared::RelativeTo};
use schemars::JsonSchema;
@ -56,122 +55,6 @@ pub async fn sweep(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
Ok(value.into())
}
/// Extrude a sketch along a path.
///
/// This, like extrude, is able to create a 3-dimensional solid from a
/// 2-dimensional sketch. However, unlike extrude, this creates a solid
/// by using the extent of the sketch as its path. This is useful for
/// creating more complex shapes that can't be created with a simple
/// extrusion.
///
/// You can provide more than one sketch to sweep, and they will all be
/// swept along the same path.
///
/// ```no_run
/// // Create a pipe using a sweep.
///
/// // Create a path for the sweep.
/// sweepPath = startSketchOn(XZ)
/// |> startProfile(at = [0.05, 0.05])
/// |> line(end = [0, 7])
/// |> tangentialArc(angle = 90, radius = 5)
/// |> line(end = [-3, 0])
/// |> tangentialArc(angle = -90, radius = 5)
/// |> line(end = [0, 7])
///
/// // Create a hole for the pipe.
/// pipeHole = startSketchOn(XY)
/// |> circle(
/// center = [0, 0],
/// radius = 1.5,
/// )
///
/// sweepSketch = startSketchOn(XY)
/// |> circle(
/// center = [0, 0],
/// radius = 2,
/// )
/// |> subtract2d(tool = pipeHole)
/// |> sweep(path = sweepPath)
/// ```
///
/// ```no_run
/// // Create a spring by sweeping around a helix path.
///
/// // Create a helix around the Z axis.
/// helixPath = helix(
/// angleStart = 0,
/// ccw = true,
/// revolutions = 4,
/// length = 10,
/// radius = 5,
/// axis = Z,
/// )
///
///
/// // Create a spring by sweeping around the helix path.
/// springSketch = startSketchOn(XZ)
/// |> circle( center = [5, 0], radius = 1)
/// |> sweep(path = helixPath)
/// ```
///
/// ```no_run
/// // Sweep two sketches along the same path.
///
/// sketch001 = startSketchOn(XY)
/// rectangleSketch = startProfile(sketch001, at = [-200, 23.86])
/// |> angledLine(angle = 0, length = 73.47, tag = $rectangleSegmentA001)
/// |> angledLine(
/// angle = segAng(rectangleSegmentA001) - 90,
/// length = 50.61,
/// )
/// |> angledLine(
/// angle = segAng(rectangleSegmentA001),
/// length = -segLen(rectangleSegmentA001),
/// )
/// |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
/// |> close()
///
/// circleSketch = circle(sketch001, center = [200, -30.29], radius = 32.63)
///
/// sketch002 = startSketchOn(YZ)
/// sweepPath = startProfile(sketch002, at = [0, 0])
/// |> yLine(length = 231.81)
/// |> tangentialArc(radius = 80, angle = -90)
/// |> xLine(length = 384.93)
///
/// sweep([rectangleSketch, circleSketch], path = sweepPath)
/// ```
/// ```
/// // Sectionally sweep one sketch along the path
///
/// sketch001 = startSketchOn(XY)
/// circleSketch = circle(sketch001, center = [200, -30.29], radius = 32.63)
///
/// sketch002 = startSketchOn(YZ)
/// sweepPath = startProfile(sketch002, at = [0, 0])
/// |> yLine(length = 231.81)
/// |> tangentialArc(radius = 80, angle = -90)
/// |> xLine(length = 384.93)
///
/// sweep(circleSketch, path = sweepPath, sectional = true)
/// ```
#[stdlib {
name = "sweep",
feature_tree_operation = true,
unlabeled_first = true,
args = {
sketches = { docs = "The sketch or set of sketches that should be swept in space" },
path = { docs = "The path to sweep the sketch along" },
sectional = { docs = "If true, the sweep will be broken up into sub-sweeps (extrusions, revolves, sweeps) based on the trajectory path components." },
tolerance = { docs = "Tolerance for this operation" },
relative_to = { docs = "What is the sweep relative to? Can be either 'sketchPlane' or 'trajectoryCurve'. Defaults to trajectoryCurve."},
tag_start = { docs = "A named tag for the face at the start of the sweep, i.e. the original sketch" },
tag_end = { docs = "A named tag for the face at the end of the sweep" },
},
tags = ["sketch"]
}]
#[allow(clippy::too_many_arguments)]
async fn inner_sweep(
sketches: Vec<Sketch>,

View File

@ -484,3 +484,47 @@ export fn clone(
/// The sketch, solid, or imported geometry to be cloned.
@geometry: Sketch | Solid | ImportedGeometry,
): Sketch | Solid | ImportedGeometry {}
/// Asserts that a value is the boolean value true.
///
/// ```kcl,norun
/// kclIsFun = true
/// assertIs(kclIsFun)
/// ```
@(impl = std_rust)
export fn assertIs(
/// Value to check. If this is the boolean value true, assert passes. Otherwise it fails..
@actual: bool,
/// If the value was false, the program will terminate with this error message
error?: string,
) {}
/// Check a value meets some expected conditions at runtime. Program terminates with an error if conditions aren't met.
/// If you provide multiple conditions, they will all be checked and all must be met.
///
/// ```kcl,norun
/// n = 10
/// assert(n, isEqualTo = 10)
/// assert(n, isGreaterThanOrEqual = 0, isLessThan = 100, error = "number should be between 0 and 100")
/// assert(1.0000000000012, isEqualTo = 1, tolerance = 0.0001, error = "number should be almost exactly 1")
/// ```
@(impl = std_rust)
export fn assert(
/// Value to check. If this is the boolean value true, assert passes. Otherwise it fails..
@actual: number,
/// Comparison argument. If given, checks the `actual` value is greater than this.
isGreaterThan?: number,
/// Comparison argument. If given, checks the `actual` value is less than this.
isLessThan?: number,
/// Comparison argument. If given, checks the `actual` value is greater than or equal to this.
isGreaterThanOrEqual?: number,
/// Comparison argument. If given, checks the `actual` value is less than or equal to this.
isLessThanOrEqual?: number,
/// Comparison argument. If given, checks the `actual` value is less than or equal to this.
@(includeInSnippet = true)
isEqualTo?: number,
/// If `isEqualTo` is used, this is the tolerance to allow for the comparison. This tolerance is used because KCL's number system has some floating-point imprecision when used with very large decimal places.
tolerance?: number,
/// If the value was false, the program will terminate with this error message
error?: string,
) {}

View File

@ -31,7 +31,7 @@
@(impl = std_rust)
export fn circle(
/// Sketch to extend, or plane or surface to sketch on.
@sketch_or_surface: Sketch | Plane | Face,
@sketchOrSurface: Sketch | Plane | Face,
/// The center of the circle.
@(snippetArray = ["0", "0"])
center: Point2d,
@ -44,6 +44,115 @@ export fn circle(
tag?: tag,
): Sketch {}
/// Extend a 2-dimensional sketch through a third dimension in order to
/// create new 3-dimensional volume, or if extruded into an existing volume,
/// cut into an existing solid.
///
/// You can provide more than one sketch to extrude, and they will all be
/// extruded in the same direction.
///
/// ```kcl
/// example = startSketchOn(XZ)
/// |> startProfile(at = [0, 0])
/// |> line(end = [10, 0])
/// |> arc(
/// angleStart = 120,
/// angleEnd = 0,
/// radius = 5,
/// )
/// |> line(end = [5, 0])
/// |> line(end = [0, 10])
/// |> bezierCurve(
/// control1 = [-10, 0],
/// control2 = [2, 10],
/// end = [-5, 10],
/// )
/// |> line(end = [-5, -2])
/// |> close()
/// |> extrude(length = 10)
/// ```
///
/// ```kcl
/// exampleSketch = startSketchOn(XZ)
/// |> startProfile(at = [-10, 0])
/// |> arc(
/// angleStart = 120,
/// angleEnd = -60,
/// radius = 5,
/// )
/// |> line(end = [10, 0])
/// |> line(end = [5, 0])
/// |> bezierCurve(
/// control1 = [-3, 0],
/// control2 = [2, 10],
/// end = [-5, 10],
/// )
/// |> line(end = [-4, 10])
/// |> line(end = [-5, -2])
/// |> close()
///
/// example = extrude(exampleSketch, length = 10)
/// ```
///
/// ```kcl
/// exampleSketch = startSketchOn(XZ)
/// |> startProfile(at = [-10, 0])
/// |> arc(
/// angleStart = 120,
/// angleEnd = -60,
/// radius = 5,
/// )
/// |> line(end = [10, 0])
/// |> line(end = [5, 0])
/// |> bezierCurve(
/// control1 = [-3, 0],
/// control2 = [2, 10],
/// end = [-5, 10],
/// )
/// |> line(end = [-4, 10])
/// |> line(end = [-5, -2])
/// |> close()
///
/// example = extrude(exampleSketch, length = 20, symmetric = true)
/// ```
///
/// ```kcl
/// exampleSketch = startSketchOn(XZ)
/// |> startProfile(at = [-10, 0])
/// |> arc(
/// angleStart = 120,
/// angleEnd = -60,
/// radius = 5,
/// )
/// |> line(end = [10, 0])
/// |> line(end = [5, 0])
/// |> bezierCurve(
/// control1 = [-3, 0],
/// control2 = [2, 10],
/// end = [-5, 10],
/// )
/// |> line(end = [-4, 10])
/// |> line(end = [-5, -2])
/// |> close()
///
/// example = extrude(exampleSketch, length = 10, bidirectionalLength = 50)
/// ```
@(impl = std_rust)
export fn extrude(
/// Which sketch or sketches should be extruded.
@sketches: [Sketch; 1+],
/// How far to extrude the given sketches.
length: number(Length),
/// If true, the extrusion will happen symmetrically around the sketch. Otherwise, the extrusion will happen on only one side of the sketch.
symmetric?: bool,
/// If specified, will also extrude in the opposite direction to 'distance' to the specified distance. If 'symmetric' is true, this value is ignored.
bidirectionalLength?: number(Length),
/// A named tag for the face at the start of the extrusion, i.e. the original sketch.
tagStart?: tag,
/// A named tag for the face at the end of the extrusion, i.e. the new face created by extruding the original sketch.
tagEnd?: tag,
): [Solid; 1+] {}
/// Rotate a sketch around some provided axis, creating a solid from its extent.
///
/// This, like extrude, is able to create a 3-dimensional solid from a
@ -57,7 +166,7 @@ export fn circle(
/// You can provide more than one sketch to revolve, and they will all be
/// revolved around the same axis.
///
/// ```
/// ```kcl
/// part001 = startSketchOn(XY)
/// |> startProfile(at = [4, 12])
/// |> line(end = [2, 0])
@ -71,7 +180,7 @@ export fn circle(
/// |> revolve(axis = Y) // default angle is 360
/// ```
///
/// ```
/// ```kcl
/// // A donut shape.
/// sketch001 = startSketchOn(XY)
/// |> circle( center = [15, 0], radius = 5 )
@ -81,7 +190,7 @@ export fn circle(
/// )
/// ```
///
/// ```
/// ```kcl
/// part001 = startSketchOn(XY)
/// |> startProfile(at = [4, 12])
/// |> line(end = [2, 0])
@ -95,7 +204,7 @@ export fn circle(
/// |> revolve(axis = Y, angle = 180)
/// ```
///
/// ```
/// ```kcl
/// part001 = startSketchOn(XY)
/// |> startProfile(at = [4, 12])
/// |> line(end = [2, 0])
@ -117,7 +226,7 @@ export fn circle(
/// |> extrude(length = 5)
/// ```
///
/// ```
/// ```kcl
/// box = startSketchOn(XY)
/// |> startProfile(at = [0, 0])
/// |> line(end = [0, 20])
@ -134,7 +243,7 @@ export fn circle(
/// )
/// ```
///
/// ```
/// ```kcl
/// box = startSketchOn(XY)
/// |> startProfile(at = [0, 0])
/// |> line(end = [0, 20])
@ -151,7 +260,7 @@ export fn circle(
/// )
/// ```
///
/// ```
/// ```kcl
/// box = startSketchOn(XY)
/// |> startProfile(at = [0, 0])
/// |> line(end = [0, 20])
@ -169,7 +278,7 @@ export fn circle(
/// )
/// ```
///
/// ```
/// ```kcl
/// sketch001 = startSketchOn(XY)
/// |> startProfile(at = [10, 0])
/// |> line(end = [5, -5])
@ -186,7 +295,7 @@ export fn circle(
/// )
/// ```
///
/// ```
/// ```kcl
/// // Revolve two sketches around the same axis.
///
/// sketch001 = startSketchOn(XY)
@ -210,7 +319,7 @@ export fn circle(
/// )
/// ```
///
/// ```
/// ```kcl
/// // Revolve around a path that has not been extruded.
///
/// profile001 = startSketchOn(XY)
@ -225,7 +334,7 @@ export fn circle(
/// |> revolve(angle = 90, axis = revolveAxis)
/// ```
///
/// ```
/// ```kcl
/// // Revolve around a path that has not been extruded or closed.
///
/// profile001 = startSketchOn(XY)
@ -238,7 +347,7 @@ export fn circle(
/// |> revolve(angle = 90, axis = revolveAxis)
/// ```
///
/// ```
/// ```kcl
/// // Symmetrically revolve around a path.
///
/// profile001 = startSketchOn(XY)
@ -251,7 +360,7 @@ export fn circle(
/// |> revolve(angle = 90, axis = revolveAxis, symmetric = true)
/// ```
///
/// ```
/// ```kcl
/// // Bidirectional revolve around a path.
///
/// profile001 = startSketchOn(XY)
@ -438,3 +547,351 @@ export fn getCommonEdge(
/// The tags of the faces you want to find the common edge between.
faces: [tag; 2],
): Edge {}
/// Construct a circle derived from 3 points.
///
/// ```kcl
/// exampleSketch = startSketchOn(XY)
/// |> circleThreePoint(p1 = [10,10], p2 = [20,8], p3 = [15,5])
/// |> extrude(length = 5)
/// ```
@(impl = std_rust)
export fn circleThreePoint(
/// Plane or surface to sketch on.
@sketchOrSurface: Sketch | Plane | Face,
/// 1st point to derive the circle.
p1: Point2d,
/// 2nd point to derive the circle.
p2: Point2d,
/// 3rd point to derive the circle.
p3: Point2d,
/// Identifier for the circle to reference elsewhere.
tag?: tag,
): Sketch {}
/// Create a regular polygon with the specified number of sides that is either inscribed or circumscribed around a circle of the specified radius.
///
/// ```kcl
/// // Create a regular hexagon inscribed in a circle of radius 10
/// hex = startSketchOn(XY)
/// |> polygon(
/// radius = 10,
/// numSides = 6,
/// center = [0, 0],
/// inscribed = true,
/// )
///
/// example = extrude(hex, length = 5)
/// ```
///
/// ```kcl
/// // Create a square circumscribed around a circle of radius 5
/// square = startSketchOn(XY)
/// |> polygon(
/// radius = 5.0,
/// numSides = 4,
/// center = [10, 10],
/// inscribed = false,
/// )
/// example = extrude(square, length = 5)
/// ```
@(impl = std_rust)
export fn polygon(
/// Plane or surface to sketch on.
@sketchOrSurface: Sketch | Plane | Face,
/// The radius of the polygon.
radius: number(Length),
/// The number of sides in the polygon.
numSides: number(Count),
/// The center point of the polygon.
@(snippetArray = ["0", "0"])
center: Point2d,
/// Whether the polygon is inscribed (true, the default) or circumscribed (false) about a circle with the specified radius.
inscribed?: bool = true,
): Sketch {}
/// Extrude a sketch along a path.
///
/// This, like extrude, is able to create a 3-dimensional solid from a
/// 2-dimensional sketch. However, unlike extrude, this creates a solid
/// by using the extent of the sketch as its path. This is useful for
/// creating more complex shapes that can't be created with a simple
/// extrusion.
///
/// You can provide more than one sketch to sweep, and they will all be
/// swept along the same path.
///
/// ```kcl
/// // Create a pipe using a sweep.
///
/// // Create a path for the sweep.
/// sweepPath = startSketchOn(XZ)
/// |> startProfile(at = [0.05, 0.05])
/// |> line(end = [0, 7])
/// |> tangentialArc(angle = 90, radius = 5)
/// |> line(end = [-3, 0])
/// |> tangentialArc(angle = -90, radius = 5)
/// |> line(end = [0, 7])
///
/// // Create a hole for the pipe.
/// pipeHole = startSketchOn(XY)
/// |> circle(
/// center = [0, 0],
/// radius = 1.5,
/// )
///
/// sweepSketch = startSketchOn(XY)
/// |> circle(
/// center = [0, 0],
/// radius = 2,
/// )
/// |> subtract2d(tool = pipeHole)
/// |> sweep(path = sweepPath)
/// ```
///
/// ```kcl
/// // Create a spring by sweeping around a helix path.
///
/// // Create a helix around the Z axis.
/// helixPath = helix(
/// angleStart = 0,
/// ccw = true,
/// revolutions = 4,
/// length = 10,
/// radius = 5,
/// axis = Z,
/// )
///
///
/// // Create a spring by sweeping around the helix path.
/// springSketch = startSketchOn(XZ)
/// |> circle( center = [5, 0], radius = 1)
/// |> sweep(path = helixPath)
/// ```
///
/// ```kcl
/// // Sweep two sketches along the same path.
///
/// sketch001 = startSketchOn(XY)
/// rectangleSketch = startProfile(sketch001, at = [-200, 23.86])
/// |> angledLine(angle = 0, length = 73.47, tag = $rectangleSegmentA001)
/// |> angledLine(
/// angle = segAng(rectangleSegmentA001) - 90,
/// length = 50.61,
/// )
/// |> angledLine(
/// angle = segAng(rectangleSegmentA001),
/// length = -segLen(rectangleSegmentA001),
/// )
/// |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
/// |> close()
///
/// circleSketch = circle(sketch001, center = [200, -30.29], radius = 32.63)
///
/// sketch002 = startSketchOn(YZ)
/// sweepPath = startProfile(sketch002, at = [0, 0])
/// |> yLine(length = 231.81)
/// |> tangentialArc(radius = 80, angle = -90)
/// |> xLine(length = 384.93)
///
/// sweep([rectangleSketch, circleSketch], path = sweepPath)
/// ```
///
/// ```kcl
/// // Sectionally sweep one sketch along the path
///
/// sketch001 = startSketchOn(XY)
/// circleSketch = circle(sketch001, center = [200, -30.29], radius = 32.63)
///
/// sketch002 = startSketchOn(YZ)
/// sweepPath = startProfile(sketch002, at = [0, 0])
/// |> yLine(length = 231.81)
/// |> tangentialArc(radius = 80, angle = -90)
/// |> xLine(length = 384.93)
///
/// sweep(circleSketch, path = sweepPath, sectional = true)
/// ```
@(impl = std_rust)
export fn sweep(
/// The sketch or set of sketches that should be swept in space.
@sketches: [Sketch; 1+],
/// The path to sweep the sketch along.
path: Sketch | Helix,
/// If true, the sweep will be broken up into sub-sweeps (extrusions, revolves, sweeps) based on the trajectory path components.
sectional?: bool,
/// Tolerance for this operation.
tolerance?: number(Length),
/// What is the sweep relative to? Can be either 'sketchPlane' or 'trajectoryCurve'.
relativeTo?: string = 'trajectoryCurve',
/// A named tag for the face at the start of the sweep, i.e. the original sketch.
tagStart?: tag,
/// A named tag for the face at the end of the sweep.
tagEnd?: tag,
): [Solid; 1+] {}
/// Create a 3D surface or solid by interpolating between two or more sketches.
///
/// The sketches need to closed and on the same plane.
///
/// ```kcl
/// // Loft a square and a triangle.
/// squareSketch = startSketchOn(XY)
/// |> startProfile(at = [-100, 200])
/// |> line(end = [200, 0])
/// |> line(end = [0, -200])
/// |> line(end = [-200, 0])
/// |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
/// |> close()
///
/// triangleSketch = startSketchOn(offsetPlane(XY, offset = 75))
/// |> startProfile(at = [0, 125])
/// |> line(end = [-15, -30])
/// |> line(end = [30, 0])
/// |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
/// |> close()
///
/// loft([triangleSketch, squareSketch])
/// ```
///
/// ```kcl
/// // Loft a square, a circle, and another circle.
/// squareSketch = startSketchOn(XY)
/// |> startProfile(at = [-100, 200])
/// |> line(end = [200, 0])
/// |> line(end = [0, -200])
/// |> line(end = [-200, 0])
/// |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
/// |> close()
///
/// circleSketch0 = startSketchOn(offsetPlane(XY, offset = 75))
/// |> circle( center = [0, 100], radius = 50 )
///
/// circleSketch1 = startSketchOn(offsetPlane(XY, offset = 150))
/// |> circle( center = [0, 100], radius = 20 )
///
/// loft([squareSketch, circleSketch0, circleSketch1])
/// ```
///
/// ```kcl
/// // Loft a square, a circle, and another circle with options.
/// squareSketch = startSketchOn(XY)
/// |> startProfile(at = [-100, 200])
/// |> line(end = [200, 0])
/// |> line(end = [0, -200])
/// |> line(end = [-200, 0])
/// |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
/// |> close()
///
/// circleSketch0 = startSketchOn(offsetPlane(XY, offset = 75))
/// |> circle( center = [0, 100], radius = 50 )
///
/// circleSketch1 = startSketchOn(offsetPlane(XY, offset = 150))
/// |> circle( center = [0, 100], radius = 20 )
///
/// loft([squareSketch, circleSketch0, circleSketch1],
/// baseCurveIndex = 0,
/// bezApproximateRational = false,
/// tolerance = 0.000001,
/// vDegree = 2,
/// )
/// ```
@(impl = std_rust)
export fn loft(
/// Which sketches to loft. Must include at least 2 sketches.
@sketches: [Sketch; 2+],
/// Degree of the interpolation. Must be greater than zero. For example, use 2 for quadratic, or 3 for cubic interpolation in the V direction.
vDegree?: number(Count) = 2,
/// Attempt to approximate rational curves (such as arcs) using a bezier. This will remove banding around interpolations between arcs and non-arcs. It may produce errors in other scenarios. Over time, this field won't be necessary.
bezApproximateRational?: bool = false,
/// This can be set to override the automatically determined topological base curve, which is usually the first section encountered.
baseCurveIndex?: number(Count),
/// Tolerance for the loft operation.
tolerance?: number(Length),
/// A named tag for the face at the start of the loft, i.e. the original sketch.
tagStart?: tag,
/// A named tag for the face at the end of the loft.
tagEnd?: tag,
): Solid {}
/// Repeat a 2-dimensional sketch along some dimension, with a dynamic amount
/// of distance between each repetition, some specified number of times.
///
/// ```kcl
/// /// Pattern using a named axis.
///
/// exampleSketch = startSketchOn(XZ)
/// |> circle(center = [0, 0], radius = 1)
/// |> patternLinear2d(
/// axis = X,
/// instances = 7,
/// distance = 4
/// )
///
/// example = extrude(exampleSketch, length = 1)
/// ```
///
/// ```kcl
/// /// Pattern using a raw axis.
///
/// exampleSketch = startSketchOn(XZ)
/// |> circle(center = [0, 0], radius = 1)
/// |> patternLinear2d(
/// axis = [1, 0],
/// instances = 7,
/// distance = 4
/// )
///
/// example = extrude(exampleSketch, length = 1)
/// ```
@(impl = std_rust)
export fn patternLinear2d(
/// The sketch(es) to duplicate.
@sketches: [Sketch; 1+],
/// The number of total instances. Must be greater than or equal to 1. This includes the original entity. For example, if instances is 2, there will be two copies -- the original, and one new copy. If instances is 1, this has no effect.
instances: number(Count),
/// Distance between each repetition. Also known as 'spacing'.
distance: number(Length),
/// The axis of the pattern. A 2D vector.
@(snippetArray = ["1", "0"])
axis: Axis2d | Point2d,
/// If the target was sketched on an extrusion, setting this will use the original sketch as the target, not the entire joined solid.
useOriginal?: bool = false,
): [Sketch; 1+] {}
/// Repeat a 2-dimensional sketch some number of times along a partial or
/// complete circle some specified number of times. Each object may
/// additionally be rotated along the circle, ensuring orientation of the
/// solid with respect to the center of the circle is maintained.
///
/// ```kcl
/// exampleSketch = startSketchOn(XZ)
/// |> startProfile(at = [.5, 25])
/// |> line(end = [0, 5])
/// |> line(end = [-1, 0])
/// |> line(end = [0, -5])
/// |> close()
/// |> patternCircular2d(
/// center = [0, 0],
/// instances = 13,
/// arcDegrees = 360,
/// rotateDuplicates = true
/// )
///
/// example = extrude(exampleSketch, length = 1)
/// ```
@(impl = std_rust)
export fn patternCircular2d(
/// The sketch(es) to duplicate.
@sketches: [Sketch; 1+],
/// The number of total instances. Must be greater than or equal to 1. This includes the original entity. For example, if instances is 2, there will be two copies -- the original, and one new copy. If instances is 1, this has no effect.
instances: number(Count),
/// The center about which to make the pattern. This is a 2D vector.
@(snippetArray = ["0", "0"])
center: Point2d,
/// The arc angle (in degrees) to place the repetitions. Must be greater than 0.
arcDegrees?: number(Angle) = 360deg,
/// Whether or not to rotate the duplicates as they are copied.
rotateDuplicates?: bool = true,
/// If the target was sketched on an extrusion, setting this will use the original sketch as the target, not the entire joined solid.
useOriginal?: bool = false,
): [Sketch; 1+] {}

View File

@ -9,6 +9,17 @@ KCL Engine error
╭─[7:6]
6 │ |> line(end = [-11.53311, 2.81559])
7 │ |> extrude(length = 4)
· ─────────┬─────────
· ─────────┬─────────
· ╰── tests/execute_engine_error_return/input.kcl
· ╰── tests/execute_engine_error_return/input.kcl
╰────
╰─▶ KCL Engine error
× engine: The path is not closed. Solid2D construction requires a
│ closed path!
╭─[7:6]
6 │ |> line(end = [-11.53311, 2.81559])
7 │ |> extrude(length = 4)
· ─────────┬─────────
· ╰── tests/execute_engine_error_return/input.kcl
╰────

Binary file not shown.

Before

Width:  |  Height:  |  Size: 83 KiB

After

Width:  |  Height:  |  Size: 83 KiB

View File

@ -1,138 +1,138 @@
```mermaid
flowchart LR
subgraph path3 [Path]
3["Path<br>[541, 569, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 1 }]
12["Segment<br>[575, 626, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 2 }]
13["Segment<br>[632, 680, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 3 }]
14["Segment<br>[686, 737, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 4 }]
15["Segment<br>[743, 791, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 5 }]
16["Segment<br>[797, 848, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 6 }]
17["Segment<br>[854, 902, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 7 }]
18["Segment<br>[908, 959, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 8 }]
19["Segment<br>[965, 1007, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 9 }]
20["Segment<br>[1013, 1071, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 10 }]
21["Segment<br>[1077, 1132, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 11 }]
22["Segment<br>[1138, 1196, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 12 }]
23["Segment<br>[1202, 1257, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 13 }]
24["Segment<br>[1263, 1306, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 14 }]
25["Segment<br>[1312, 1368, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 15 }]
26["Segment<br>[1374, 1429, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 16 }]
27["Segment<br>[1435, 1491, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 17 }]
28["Segment<br>[1497, 1504, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 18 }]
42[Solid2d]
end
subgraph path4 [Path]
4["Path<br>[1668, 1730, 0]"]
%% [ProgramBodyItem { index: 3 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 0 }]
29["Segment<br>[1668, 1730, 0]"]
%% [ProgramBodyItem { index: 3 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 0 }]
41[Solid2d]
end
subgraph path5 [Path]
5["Path<br>[1768, 1829, 0]"]
%% [ProgramBodyItem { index: 4 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 0 }]
30["Segment<br>[1768, 1829, 0]"]
%% [ProgramBodyItem { index: 4 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 0 }]
44[Solid2d]
end
subgraph path6 [Path]
6["Path<br>[1867, 1929, 0]"]
%% [ProgramBodyItem { index: 5 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 0 }]
31["Segment<br>[1867, 1929, 0]"]
%% [ProgramBodyItem { index: 5 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 0 }]
45[Solid2d]
end
subgraph path7 [Path]
7["Path<br>[1967, 2026, 0]"]
%% [ProgramBodyItem { index: 6 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 0 }]
32["Segment<br>[1967, 2026, 0]"]
%% [ProgramBodyItem { index: 6 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 0 }]
39[Solid2d]
end
subgraph path8 [Path]
8["Path<br>[2064, 2124, 0]"]
%% [ProgramBodyItem { index: 7 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 0 }]
33["Segment<br>[2064, 2124, 0]"]
%% [ProgramBodyItem { index: 7 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 0 }]
37[Solid2d]
end
subgraph path9 [Path]
9["Path<br>[2162, 2222, 0]"]
%% [ProgramBodyItem { index: 8 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 0 }]
34["Segment<br>[2162, 2222, 0]"]
%% [ProgramBodyItem { index: 8 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 0 }]
38[Solid2d]
end
subgraph path10 [Path]
10["Path<br>[2260, 2322, 0]"]
%% [ProgramBodyItem { index: 9 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 0 }]
35["Segment<br>[2260, 2322, 0]"]
%% [ProgramBodyItem { index: 9 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 0 }]
40[Solid2d]
10["Path<br>[541, 569, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 1 }]
19["Segment<br>[575, 626, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 2 }]
20["Segment<br>[632, 680, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 3 }]
21["Segment<br>[686, 737, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 4 }]
22["Segment<br>[743, 791, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 5 }]
23["Segment<br>[797, 848, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 6 }]
24["Segment<br>[854, 902, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 7 }]
25["Segment<br>[908, 959, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 8 }]
26["Segment<br>[965, 1007, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 9 }]
27["Segment<br>[1013, 1071, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 10 }]
28["Segment<br>[1077, 1132, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 11 }]
29["Segment<br>[1138, 1196, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 12 }]
30["Segment<br>[1202, 1257, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 13 }]
31["Segment<br>[1263, 1306, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 14 }]
32["Segment<br>[1312, 1368, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 15 }]
33["Segment<br>[1374, 1429, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 16 }]
34["Segment<br>[1435, 1491, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 17 }]
35["Segment<br>[1497, 1504, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 18 }]
47[Solid2d]
end
subgraph path11 [Path]
11["Path<br>[2360, 2421, 0]"]
%% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 0 }]
36["Segment<br>[2360, 2421, 0]"]
%% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 0 }]
43[Solid2d]
11["Path<br>[1663, 1707, 0]"]
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 0 }, ReturnStatementArg, PipeBodyItem { index: 1 }]
39["Segment<br>[1663, 1707, 0]"]
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 0 }, ReturnStatementArg, PipeBodyItem { index: 1 }]
44[Solid2d]
end
subgraph path12 [Path]
12["Path<br>[1663, 1707, 0]"]
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 0 }, ReturnStatementArg, PipeBodyItem { index: 1 }]
36["Segment<br>[1663, 1707, 0]"]
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 0 }, ReturnStatementArg, PipeBodyItem { index: 1 }]
45[Solid2d]
end
subgraph path13 [Path]
13["Path<br>[1663, 1707, 0]"]
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 0 }, ReturnStatementArg, PipeBodyItem { index: 1 }]
43["Segment<br>[1663, 1707, 0]"]
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 0 }, ReturnStatementArg, PipeBodyItem { index: 1 }]
46[Solid2d]
end
subgraph path14 [Path]
14["Path<br>[1663, 1707, 0]"]
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 0 }, ReturnStatementArg, PipeBodyItem { index: 1 }]
41["Segment<br>[1663, 1707, 0]"]
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 0 }, ReturnStatementArg, PipeBodyItem { index: 1 }]
48[Solid2d]
end
subgraph path15 [Path]
15["Path<br>[1663, 1707, 0]"]
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 0 }, ReturnStatementArg, PipeBodyItem { index: 1 }]
42["Segment<br>[1663, 1707, 0]"]
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 0 }, ReturnStatementArg, PipeBodyItem { index: 1 }]
49[Solid2d]
end
subgraph path16 [Path]
16["Path<br>[1663, 1707, 0]"]
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 0 }, ReturnStatementArg, PipeBodyItem { index: 1 }]
38["Segment<br>[1663, 1707, 0]"]
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 0 }, ReturnStatementArg, PipeBodyItem { index: 1 }]
50[Solid2d]
end
subgraph path17 [Path]
17["Path<br>[1663, 1707, 0]"]
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 0 }, ReturnStatementArg, PipeBodyItem { index: 1 }]
37["Segment<br>[1663, 1707, 0]"]
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 0 }, ReturnStatementArg, PipeBodyItem { index: 1 }]
51[Solid2d]
end
subgraph path18 [Path]
18["Path<br>[1663, 1707, 0]"]
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 0 }, ReturnStatementArg, PipeBodyItem { index: 1 }]
40["Segment<br>[1663, 1707, 0]"]
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 0 }, ReturnStatementArg, PipeBodyItem { index: 1 }]
52[Solid2d]
end
1["Plane<br>[518, 535, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 0 }]
2["Plane<br>[1641, 1658, 0]"]
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit]
46["Sweep Revolve<br>[1510, 1557, 0]"]
2["Plane<br>[1638, 1655, 0]"]
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 0 }, ReturnStatementArg, PipeBodyItem { index: 0 }]
3["Plane<br>[1638, 1655, 0]"]
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 0 }, ReturnStatementArg, PipeBodyItem { index: 0 }]
4["Plane<br>[1638, 1655, 0]"]
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 0 }, ReturnStatementArg, PipeBodyItem { index: 0 }]
5["Plane<br>[1638, 1655, 0]"]
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 0 }, ReturnStatementArg, PipeBodyItem { index: 0 }]
6["Plane<br>[1638, 1655, 0]"]
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 0 }, ReturnStatementArg, PipeBodyItem { index: 0 }]
7["Plane<br>[1638, 1655, 0]"]
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 0 }, ReturnStatementArg, PipeBodyItem { index: 0 }]
8["Plane<br>[1638, 1655, 0]"]
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 0 }, ReturnStatementArg, PipeBodyItem { index: 0 }]
9["Plane<br>[1638, 1655, 0]"]
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 0 }, ReturnStatementArg, PipeBodyItem { index: 0 }]
53["Sweep Revolve<br>[1510, 1557, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 19 }]
47["Sweep Extrusion<br>[1736, 1758, 0]"]
%% [ProgramBodyItem { index: 3 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 1 }]
48["Sweep Extrusion<br>[1835, 1857, 0]"]
%% [ProgramBodyItem { index: 4 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 1 }]
49["Sweep Extrusion<br>[1935, 1957, 0]"]
%% [ProgramBodyItem { index: 5 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 1 }]
50["Sweep Extrusion<br>[2032, 2054, 0]"]
%% [ProgramBodyItem { index: 6 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 1 }]
51["Sweep Extrusion<br>[2130, 2152, 0]"]
%% [ProgramBodyItem { index: 7 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 1 }]
52["Sweep Extrusion<br>[2228, 2250, 0]"]
%% [ProgramBodyItem { index: 8 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 1 }]
53["Sweep Extrusion<br>[2328, 2350, 0]"]
%% [ProgramBodyItem { index: 9 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 1 }]
54["Sweep Extrusion<br>[2427, 2449, 0]"]
%% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 1 }]
55["CompositeSolid Subtract<br>[2716, 2769, 0]"]
%% [ProgramBodyItem { index: 14 }, VariableDeclarationDeclaration, VariableDeclarationInit]
56["CompositeSolid Union<br>[2680, 2703, 0]"]
%% [ProgramBodyItem { index: 13 }, VariableDeclarationDeclaration, VariableDeclarationInit, CallKwArg { index: 0 }]
57["CompositeSolid Union<br>[2615, 2638, 0]"]
%% [ProgramBodyItem { index: 12 }, VariableDeclarationDeclaration, VariableDeclarationInit, CallKwArg { index: 0 }]
58["CompositeSolid Subtract<br>[2517, 2574, 0]"]
%% [ProgramBodyItem { index: 11 }, VariableDeclarationDeclaration, VariableDeclarationInit]
59["CompositeSolid Subtract<br>[2586, 2639, 0]"]
%% [ProgramBodyItem { index: 12 }, VariableDeclarationDeclaration, VariableDeclarationInit]
60["CompositeSolid Union<br>[2550, 2573, 0]"]
%% [ProgramBodyItem { index: 11 }, VariableDeclarationDeclaration, VariableDeclarationInit, CallKwArg { index: 0 }]
61["CompositeSolid Subtract<br>[2651, 2704, 0]"]
%% [ProgramBodyItem { index: 13 }, VariableDeclarationDeclaration, VariableDeclarationInit]
62["CompositeSolid Union<br>[2745, 2768, 0]"]
%% [ProgramBodyItem { index: 14 }, VariableDeclarationDeclaration, VariableDeclarationInit, CallKwArg { index: 0 }]
54["Sweep Extrusion<br>[1715, 1737, 0]"]
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 0 }, ReturnStatementArg, PipeBodyItem { index: 2 }]
55["Sweep Extrusion<br>[1715, 1737, 0]"]
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 0 }, ReturnStatementArg, PipeBodyItem { index: 2 }]
56["Sweep Extrusion<br>[1715, 1737, 0]"]
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 0 }, ReturnStatementArg, PipeBodyItem { index: 2 }]
57["Sweep Extrusion<br>[1715, 1737, 0]"]
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 0 }, ReturnStatementArg, PipeBodyItem { index: 2 }]
58["Sweep Extrusion<br>[1715, 1737, 0]"]
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 0 }, ReturnStatementArg, PipeBodyItem { index: 2 }]
59["Sweep Extrusion<br>[1715, 1737, 0]"]
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 0 }, ReturnStatementArg, PipeBodyItem { index: 2 }]
60["Sweep Extrusion<br>[1715, 1737, 0]"]
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 0 }, ReturnStatementArg, PipeBodyItem { index: 2 }]
61["Sweep Extrusion<br>[1715, 1737, 0]"]
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 0 }, ReturnStatementArg, PipeBodyItem { index: 2 }]
62["CompositeSolid Subtract<br>[2147, 2186, 0]"]
%% [ProgramBodyItem { index: 5 }, VariableDeclarationDeclaration, VariableDeclarationInit]
63[Wall]
%% face_code_ref=Missing NodePath
64[Wall]
@ -265,260 +265,253 @@ flowchart LR
150["SweepEdge Adjacent"]
151["SweepEdge Adjacent"]
152["SweepEdge Adjacent"]
1 --- 3
2 --- 4
2 --- 5
2 --- 6
2 --- 7
2 --- 8
2 --- 9
2 --- 10
2 --- 11
3 --- 12
1 --- 10
2 --- 14
3 --- 13
3 --- 14
3 --- 15
3 --- 16
3 --- 17
3 --- 18
3 --- 19
3 --- 20
3 --- 21
3 --- 22
3 --- 23
3 --- 24
3 --- 25
3 --- 26
3 --- 27
3 --- 28
3 --- 42
3 ---- 46
3 --- 58
4 --- 29
4 --- 41
4 ---- 47
4 --- 60
5 --- 30
5 --- 44
5 ---- 48
5 --- 60
6 --- 31
6 --- 45
6 ---- 49
6 --- 57
7 --- 32
7 --- 39
7 ---- 50
7 --- 57
8 --- 33
8 --- 37
8 ---- 51
8 --- 56
9 --- 34
9 --- 38
9 ---- 52
9 --- 56
4 --- 18
5 --- 12
6 --- 15
7 --- 17
8 --- 16
9 --- 11
10 --- 19
10 --- 20
10 --- 21
10 --- 22
10 --- 23
10 --- 24
10 --- 25
10 --- 26
10 --- 27
10 --- 28
10 --- 29
10 --- 30
10 --- 31
10 --- 32
10 --- 33
10 --- 34
10 --- 35
10 --- 40
10 --- 47
10 ---- 53
10 --- 62
11 --- 36
11 --- 43
11 ---- 54
11 --- 39
11 --- 44
11 ---- 58
11 --- 62
12 --- 83
12 x--> 91
12 --- 113
12 --- 137
13 --- 78
13 x--> 91
13 --- 114
13 --- 138
14 --- 77
14 x--> 91
14 --- 115
14 --- 139
15 --- 79
15 x--> 91
15 --- 116
15 --- 140
16 --- 75
16 x--> 91
16 --- 117
16 --- 141
17 --- 74
17 x--> 91
17 --- 118
17 --- 142
18 --- 82
18 x--> 91
18 --- 119
18 --- 143
19 --- 85
19 x--> 91
19 --- 120
19 --- 144
20 --- 84
20 x--> 91
20 --- 121
20 --- 145
21 --- 72
21 x--> 91
21 --- 122
21 --- 146
22 --- 73
22 x--> 91
22 --- 123
22 --- 147
23 --- 86
23 x--> 91
23 --- 124
23 --- 148
24 --- 80
24 x--> 91
24 --- 125
24 --- 149
25 --- 76
25 x--> 91
25 --- 126
25 --- 150
26 --- 71
26 x--> 91
26 --- 127
26 --- 151
27 --- 81
27 x--> 91
27 --- 128
27 --- 152
29 --- 70
29 x--> 98
29 --- 112
29 --- 136
30 --- 64
30 x--> 102
30 --- 106
30 --- 130
31 --- 65
31 x--> 104
31 --- 107
31 --- 131
32 --- 68
32 x--> 97
32 --- 110
32 --- 134
33 --- 67
33 x--> 96
33 --- 109
33 --- 133
34 --- 63
34 x--> 103
34 --- 105
34 --- 129
35 --- 66
35 x--> 99
35 --- 108
35 --- 132
36 --- 69
36 x--> 101
36 --- 111
36 --- 135
46 --- 71
46 --- 72
46 --- 73
46 --- 74
46 --- 75
46 --- 76
46 --- 77
46 --- 78
46 --- 79
46 --- 80
46 --- 81
46 --- 82
46 --- 83
46 --- 84
46 --- 85
46 --- 86
46 --- 91
46 --- 100
46 --- 113
46 --- 114
46 --- 115
46 --- 116
46 --- 117
46 --- 118
46 --- 119
46 --- 120
46 --- 121
46 --- 122
46 --- 123
46 --- 124
46 --- 125
46 --- 126
46 --- 127
46 --- 128
46 --- 137
46 --- 138
46 --- 139
46 --- 140
46 --- 141
46 --- 142
46 --- 143
46 --- 144
46 --- 145
46 --- 146
46 --- 147
46 --- 148
46 --- 149
46 --- 150
46 --- 151
46 --- 152
47 --- 70
47 --- 89
47 --- 98
47 --- 112
47 --- 136
48 --- 64
48 --- 93
48 --- 102
48 --- 106
48 --- 130
49 --- 65
49 --- 95
49 --- 104
49 --- 107
49 --- 131
50 --- 68
50 --- 88
50 --- 97
50 --- 110
50 --- 134
51 --- 67
51 --- 87
51 --- 96
51 --- 109
51 --- 133
52 --- 63
52 --- 94
52 --- 103
52 --- 105
52 --- 129
53 --- 66
53 --- 90
53 --- 99
53 --- 108
53 --- 132
54 --- 69
54 --- 92
54 --- 101
54 --- 111
54 --- 135
61 --- 55
62 --- 55
56 --- 61
57 --- 59
58 --- 59
60 --- 58
59 --- 61
12 --- 36
12 --- 45
12 ---- 61
12 --- 62
13 --- 43
13 --- 46
13 ---- 56
13 --- 62
14 --- 41
14 --- 48
14 ---- 59
14 --- 62
15 --- 42
15 --- 49
15 ---- 54
15 --- 62
16 --- 38
16 --- 50
16 ---- 57
16 --- 62
17 --- 37
17 --- 51
17 ---- 55
17 --- 62
18 --- 40
18 --- 52
18 ---- 60
18 --- 62
19 --- 83
19 x--> 92
19 --- 113
19 --- 137
20 --- 78
20 x--> 92
20 --- 114
20 --- 138
21 --- 77
21 x--> 92
21 --- 115
21 --- 139
22 --- 79
22 x--> 92
22 --- 116
22 --- 140
23 --- 75
23 x--> 92
23 --- 117
23 --- 141
24 --- 74
24 x--> 92
24 --- 118
24 --- 142
25 --- 82
25 x--> 92
25 --- 119
25 --- 143
26 --- 85
26 x--> 92
26 --- 120
26 --- 144
27 --- 84
27 x--> 92
27 --- 121
27 --- 145
28 --- 72
28 x--> 92
28 --- 122
28 --- 146
29 --- 73
29 x--> 92
29 --- 123
29 --- 147
30 --- 86
30 x--> 92
30 --- 124
30 --- 148
31 --- 80
31 x--> 92
31 --- 125
31 --- 149
32 --- 76
32 x--> 92
32 --- 126
32 --- 150
33 --- 71
33 x--> 92
33 --- 127
33 --- 151
34 --- 81
34 x--> 92
34 --- 128
34 --- 152
36 --- 70
36 x--> 99
36 --- 112
36 --- 136
37 --- 64
37 x--> 98
37 --- 106
37 --- 130
38 --- 66
38 x--> 104
38 --- 108
38 --- 132
39 --- 67
39 x--> 102
39 --- 109
39 --- 133
40 --- 69
40 x--> 100
40 --- 111
40 --- 135
41 --- 68
41 x--> 103
41 --- 110
41 --- 134
42 --- 63
42 x--> 96
42 --- 105
42 --- 129
43 --- 65
43 x--> 97
43 --- 107
43 --- 131
53 --- 71
53 --- 72
53 --- 73
53 --- 74
53 --- 75
53 --- 76
53 --- 77
53 --- 78
53 --- 79
53 --- 80
53 --- 81
53 --- 82
53 --- 83
53 --- 84
53 --- 85
53 --- 86
53 --- 92
53 --- 101
53 --- 113
53 --- 114
53 --- 115
53 --- 116
53 --- 117
53 --- 118
53 --- 119
53 --- 120
53 --- 121
53 --- 122
53 --- 123
53 --- 124
53 --- 125
53 --- 126
53 --- 127
53 --- 128
53 --- 137
53 --- 138
53 --- 139
53 --- 140
53 --- 141
53 --- 142
53 --- 143
53 --- 144
53 --- 145
53 --- 146
53 --- 147
53 --- 148
53 --- 149
53 --- 150
53 --- 151
53 --- 152
54 --- 63
54 --- 87
54 --- 96
54 --- 105
54 --- 129
55 --- 64
55 --- 89
55 --- 98
55 --- 106
55 --- 130
56 --- 65
56 --- 88
56 --- 97
56 --- 107
56 --- 131
57 --- 66
57 --- 95
57 --- 104
57 --- 108
57 --- 132
58 --- 67
58 --- 93
58 --- 102
58 --- 109
58 --- 133
59 --- 68
59 --- 94
59 --- 103
59 --- 110
59 --- 134
60 --- 69
60 --- 91
60 --- 100
60 --- 111
60 --- 135
61 --- 70
61 --- 90
61 --- 99
61 --- 112
61 --- 136
63 --- 105
63 --- 129
64 --- 106
@ -583,28 +576,28 @@ flowchart LR
86 --- 124
147 <--x 86
86 --- 148
109 <--x 87
110 <--x 88
112 <--x 89
108 <--x 90
111 <--x 92
106 <--x 93
105 <--x 94
107 <--x 95
113 <--x 100
114 <--x 100
115 <--x 100
116 <--x 100
117 <--x 100
118 <--x 100
119 <--x 100
120 <--x 100
121 <--x 100
122 <--x 100
123 <--x 100
124 <--x 100
125 <--x 100
126 <--x 100
127 <--x 100
128 <--x 100
105 <--x 87
107 <--x 88
106 <--x 89
112 <--x 90
111 <--x 91
109 <--x 93
110 <--x 94
108 <--x 95
113 <--x 101
114 <--x 101
115 <--x 101
116 <--x 101
117 <--x 101
118 <--x 101
119 <--x 101
120 <--x 101
121 <--x 101
122 <--x 101
123 <--x 101
124 <--x 101
125 <--x 101
126 <--x 101
127 <--x 101
128 <--x 101
```

File diff suppressed because it is too large Load Diff

View File

@ -138,6 +138,97 @@ description: Operations executed bone-plate.kcl
"labeledArgs": {},
"sourceRange": []
},
{
"type": "StdLibCall",
"name": "startSketchOn",
"unlabeledArg": {
"value": {
"type": "Plane",
"artifact_id": "[uuid]"
},
"sourceRange": []
},
"labeledArgs": {},
"sourceRange": []
},
{
"type": "StdLibCall",
"name": "startSketchOn",
"unlabeledArg": {
"value": {
"type": "Plane",
"artifact_id": "[uuid]"
},
"sourceRange": []
},
"labeledArgs": {},
"sourceRange": []
},
{
"type": "StdLibCall",
"name": "startSketchOn",
"unlabeledArg": {
"value": {
"type": "Plane",
"artifact_id": "[uuid]"
},
"sourceRange": []
},
"labeledArgs": {},
"sourceRange": []
},
{
"type": "StdLibCall",
"name": "startSketchOn",
"unlabeledArg": {
"value": {
"type": "Plane",
"artifact_id": "[uuid]"
},
"sourceRange": []
},
"labeledArgs": {},
"sourceRange": []
},
{
"type": "StdLibCall",
"name": "startSketchOn",
"unlabeledArg": {
"value": {
"type": "Plane",
"artifact_id": "[uuid]"
},
"sourceRange": []
},
"labeledArgs": {},
"sourceRange": []
},
{
"type": "StdLibCall",
"name": "startSketchOn",
"unlabeledArg": {
"value": {
"type": "Plane",
"artifact_id": "[uuid]"
},
"sourceRange": []
},
"labeledArgs": {},
"sourceRange": []
},
{
"type": "StdLibCall",
"name": "startSketchOn",
"unlabeledArg": {
"value": {
"type": "Plane",
"artifact_id": "[uuid]"
},
"sourceRange": []
},
"labeledArgs": {},
"sourceRange": []
},
{
"type": "StdLibCall",
"name": "extrude",
@ -394,6 +485,358 @@ description: Operations executed bone-plate.kcl
},
"sourceRange": []
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": null,
"functionSourceRange": [],
"unlabeledArg": {
"value": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 12.25,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"sourceRange": []
},
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": null,
"functionSourceRange": [],
"unlabeledArg": {
"value": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 29.5,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"sourceRange": []
},
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": null,
"functionSourceRange": [],
"unlabeledArg": {
"value": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 46.25,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"sourceRange": []
},
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": null,
"functionSourceRange": [],
"unlabeledArg": {
"value": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 77.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"sourceRange": []
},
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": null,
"functionSourceRange": [],
"unlabeledArg": {
"value": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 100.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"sourceRange": []
},
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": null,
"functionSourceRange": [],
"unlabeledArg": {
"value": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 130.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"sourceRange": []
},
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": null,
"functionSourceRange": [],
"unlabeledArg": {
"value": {
"type": "Array",
"value": [
{
"type": "Number",
"value": -20.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 130.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"sourceRange": []
},
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": null,
"functionSourceRange": [],
"unlabeledArg": {
"value": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 20.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 130.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"sourceRange": []
},
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "StdLibCall",
"name": "subtract",
@ -414,10 +857,57 @@ description: Operations executed bone-plate.kcl
"labeledArgs": {
"tools": {
"value": {
"type": "Solid",
"value": {
"artifactId": "[uuid]"
}
"type": "Array",
"value": [
{
"type": "Solid",
"value": {
"artifactId": "[uuid]"
}
},
{
"type": "Solid",
"value": {
"artifactId": "[uuid]"
}
},
{
"type": "Solid",
"value": {
"artifactId": "[uuid]"
}
},
{
"type": "Solid",
"value": {
"artifactId": "[uuid]"
}
},
{
"type": "Solid",
"value": {
"artifactId": "[uuid]"
}
},
{
"type": "Solid",
"value": {
"artifactId": "[uuid]"
}
},
{
"type": "Solid",
"value": {
"artifactId": "[uuid]"
}
},
{
"type": "Solid",
"value": {
"artifactId": "[uuid]"
}
}
]
},
"sourceRange": []
}
@ -425,197 +915,27 @@ description: Operations executed bone-plate.kcl
"sourceRange": []
},
{
"type": "StdLibCall",
"name": "union",
"unlabeledArg": {
"value": {
"type": "Array",
"value": [
{
"type": "Solid",
"value": {
"artifactId": "[uuid]"
}
},
{
"type": "Solid",
"value": {
"artifactId": "[uuid]"
}
}
]
},
"sourceRange": []
},
"labeledArgs": {},
"sourceRange": []
"type": "GroupEnd"
},
{
"type": "StdLibCall",
"name": "subtract",
"unlabeledArg": {
"value": {
"type": "Array",
"value": [
{
"type": "Solid",
"value": {
"artifactId": "[uuid]"
}
}
]
},
"sourceRange": []
},
"labeledArgs": {
"tools": {
"value": {
"type": "Solid",
"value": {
"artifactId": "[uuid]"
}
},
"sourceRange": []
}
},
"sourceRange": []
"type": "GroupEnd"
},
{
"type": "StdLibCall",
"name": "union",
"unlabeledArg": {
"value": {
"type": "Array",
"value": [
{
"type": "Solid",
"value": {
"artifactId": "[uuid]"
}
},
{
"type": "Solid",
"value": {
"artifactId": "[uuid]"
}
}
]
},
"sourceRange": []
},
"labeledArgs": {},
"sourceRange": []
"type": "GroupEnd"
},
{
"type": "StdLibCall",
"name": "subtract",
"unlabeledArg": {
"value": {
"type": "Array",
"value": [
{
"type": "Solid",
"value": {
"artifactId": "[uuid]"
}
}
]
},
"sourceRange": []
},
"labeledArgs": {
"tools": {
"value": {
"type": "Solid",
"value": {
"artifactId": "[uuid]"
}
},
"sourceRange": []
}
},
"sourceRange": []
"type": "GroupEnd"
},
{
"type": "StdLibCall",
"name": "union",
"unlabeledArg": {
"value": {
"type": "Array",
"value": [
{
"type": "Solid",
"value": {
"artifactId": "[uuid]"
}
},
{
"type": "Solid",
"value": {
"artifactId": "[uuid]"
}
}
]
},
"sourceRange": []
},
"labeledArgs": {},
"sourceRange": []
"type": "GroupEnd"
},
{
"type": "StdLibCall",
"name": "subtract",
"unlabeledArg": {
"value": {
"type": "Array",
"value": [
{
"type": "Solid",
"value": {
"artifactId": "[uuid]"
}
}
]
},
"sourceRange": []
},
"labeledArgs": {
"tools": {
"value": {
"type": "Solid",
"value": {
"artifactId": "[uuid]"
}
},
"sourceRange": []
}
},
"sourceRange": []
"type": "GroupEnd"
},
{
"type": "StdLibCall",
"name": "union",
"unlabeledArg": {
"value": {
"type": "Array",
"value": [
{
"type": "Solid",
"value": {
"artifactId": "[uuid]"
}
},
{
"type": "Solid",
"value": {
"artifactId": "[uuid]"
}
}
]
},
"sourceRange": []
},
"labeledArgs": {},
"sourceRange": []
"type": "GroupEnd"
},
{
"type": "GroupEnd"
}
]

File diff suppressed because it is too large Load Diff

View File

@ -87,24 +87,24 @@ flowchart LR
27 --- 4
8 --- 20
8 x--> 25
8 --- 33
8 --- 39
8 --- 29
8 --- 35
9 --- 21
9 x--> 25
9 --- 30
9 --- 36
9 --- 33
9 --- 39
10 --- 22
10 x--> 25
10 --- 32
10 --- 38
10 --- 30
10 --- 36
11 --- 23
11 x--> 25
11 --- 31
11 --- 37
12 --- 24
12 x--> 25
12 --- 29
12 --- 35
12 --- 32
12 --- 38
14 --- 19
14 x--> 27
14 --- 28
@ -132,21 +132,21 @@ flowchart LR
18 --- 34
19 --- 28
19 --- 34
20 --- 33
35 <--x 20
20 --- 39
21 --- 30
21 --- 36
37 <--x 21
22 --- 32
22 --- 38
39 <--x 22
20 --- 29
20 --- 35
36 <--x 20
21 --- 33
35 <--x 21
21 --- 39
22 --- 30
22 --- 36
37 <--x 22
23 --- 31
23 --- 37
38 <--x 23
24 --- 29
24 --- 35
36 <--x 24
24 --- 32
24 --- 38
39 <--x 24
28 <--x 26
29 <--x 27
30 <--x 27

View File

@ -366,12 +366,12 @@ flowchart LR
11 ---- 74
26 --- 75
26 x--> 108
26 --- 132
26 --- 164
26 --- 130
26 --- 162
27 --- 76
27 x--> 108
27 --- 134
27 --- 166
27 --- 116
27 --- 148
28 --- 77
28 x--> 108
28 --- 139
@ -382,36 +382,36 @@ flowchart LR
29 --- 167
30 --- 79
30 x--> 108
30 --- 123
30 --- 155
30 --- 128
30 --- 160
31 --- 80
31 x--> 108
31 --- 115
31 --- 147
31 --- 123
31 --- 155
32 --- 81
32 x--> 108
32 --- 117
32 --- 149
32 --- 127
32 --- 159
33 --- 82
33 x--> 108
33 --- 137
33 --- 169
33 --- 132
33 --- 164
34 --- 83
34 x--> 108
34 --- 127
34 --- 159
34 --- 133
34 --- 165
35 --- 84
35 x--> 108
35 --- 122
35 --- 154
35 --- 121
35 --- 153
36 --- 85
36 x--> 108
36 --- 126
36 --- 158
36 --- 137
36 --- 169
37 --- 86
37 x--> 108
37 --- 128
37 --- 160
37 --- 115
37 --- 147
38 --- 87
38 x--> 108
38 --- 120
@ -422,58 +422,58 @@ flowchart LR
39 --- 156
40 --- 89
40 x--> 108
40 --- 116
40 --- 148
40 --- 134
40 --- 166
41 --- 90
41 x--> 108
41 --- 131
41 --- 163
41 --- 136
41 --- 168
42 --- 91
42 x--> 108
42 --- 121
42 --- 153
42 --- 122
42 --- 154
43 --- 92
43 x--> 108
43 --- 136
43 --- 168
43 --- 114
43 --- 146
44 --- 93
44 x--> 108
44 --- 113
44 --- 145
45 --- 94
45 x--> 108
45 --- 125
45 --- 157
45 --- 131
45 --- 163
46 --- 95
46 x--> 108
46 --- 138
46 --- 170
46 --- 117
46 --- 149
47 --- 96
47 x--> 108
47 --- 114
47 --- 146
47 --- 125
47 --- 157
48 --- 97
48 x--> 108
48 --- 133
48 --- 165
48 --- 119
48 --- 151
49 --- 98
49 x--> 108
49 --- 130
49 --- 162
49 --- 126
49 --- 158
50 --- 99
50 x--> 108
50 --- 129
50 --- 161
50 --- 118
50 --- 150
51 --- 100
51 x--> 108
51 --- 119
51 --- 151
51 --- 129
51 --- 161
52 --- 101
52 x--> 108
52 --- 118
52 --- 150
52 --- 138
52 --- 170
61 --- 102
61 x--> 109
61 x--> 110
61 --- 140
61 --- 172
63 --- 103
@ -594,87 +594,87 @@ flowchart LR
74 --- 174
74 --- 175
74 --- 176
75 --- 132
75 --- 164
165 <--x 75
76 --- 134
76 --- 166
167 <--x 76
75 --- 130
75 --- 162
163 <--x 75
76 --- 116
76 --- 148
149 <--x 76
77 --- 139
145 <--x 77
77 --- 171
78 --- 135
78 --- 167
168 <--x 78
79 --- 123
79 --- 155
156 <--x 79
80 --- 115
80 --- 147
148 <--x 80
81 --- 117
81 --- 149
150 <--x 81
82 --- 137
82 --- 169
170 <--x 82
83 --- 127
83 --- 159
160 <--x 83
84 --- 122
84 --- 154
155 <--x 84
85 --- 126
85 --- 158
159 <--x 85
86 --- 128
86 --- 160
161 <--x 86
79 --- 128
79 --- 160
161 <--x 79
80 --- 123
80 --- 155
156 <--x 80
81 --- 127
81 --- 159
160 <--x 81
82 --- 132
82 --- 164
165 <--x 82
83 --- 133
83 --- 165
166 <--x 83
84 --- 121
84 --- 153
154 <--x 84
85 --- 137
85 --- 169
170 <--x 85
86 --- 115
86 --- 147
148 <--x 86
87 --- 120
87 --- 152
153 <--x 87
88 --- 124
88 --- 156
157 <--x 88
89 --- 116
89 --- 148
149 <--x 89
90 --- 131
90 --- 163
164 <--x 90
91 --- 121
91 --- 153
154 <--x 91
92 --- 136
92 --- 168
169 <--x 92
89 --- 134
89 --- 166
167 <--x 89
90 --- 136
90 --- 168
169 <--x 90
91 --- 122
91 --- 154
155 <--x 91
92 --- 114
92 --- 146
147 <--x 92
93 --- 113
93 --- 145
146 <--x 93
94 --- 125
94 --- 157
158 <--x 94
95 --- 138
95 --- 170
171 <--x 95
96 --- 114
96 --- 146
147 <--x 96
97 --- 133
97 --- 165
166 <--x 97
98 --- 130
98 --- 162
163 <--x 98
99 --- 129
99 --- 161
162 <--x 99
100 --- 119
100 --- 151
152 <--x 100
101 --- 118
101 --- 150
151 <--x 101
94 --- 131
94 --- 163
164 <--x 94
95 --- 117
95 --- 149
150 <--x 95
96 --- 125
96 --- 157
158 <--x 96
97 --- 119
97 --- 151
152 <--x 97
98 --- 126
98 --- 158
159 <--x 98
99 --- 118
99 --- 150
151 <--x 99
100 --- 129
100 --- 161
162 <--x 100
101 --- 138
101 --- 170
171 <--x 101
102 --- 140
102 --- 172
103 --- 144
@ -689,7 +689,7 @@ flowchart LR
106 --- 141
106 --- 173
174 <--x 106
140 <--x 110
140 <--x 109
141 <--x 111
142 <--x 111
143 <--x 111

View File

@ -582,48 +582,48 @@ flowchart LR
46 --- 226
72 --- 112
72 x--> 151
72 --- 160
72 --- 194
72 --- 167
72 --- 201
73 --- 113
73 x--> 151
73 --- 162
73 --- 196
73 --- 169
73 --- 203
74 --- 114
74 x--> 151
74 --- 167
74 --- 201
74 --- 168
74 --- 202
75 --- 115
75 x--> 151
75 --- 170
75 --- 204
75 --- 166
75 --- 200
76 --- 116
76 x--> 151
76 --- 166
76 --- 200
76 --- 165
76 --- 199
77 --- 117
77 x--> 151
77 --- 163
77 --- 197
77 --- 161
77 --- 195
78 --- 118
78 x--> 151
78 --- 168
78 --- 202
78 --- 162
78 --- 196
79 --- 119
79 x--> 151
79 --- 161
79 --- 195
79 --- 163
79 --- 197
80 --- 120
80 x--> 151
80 --- 164
80 --- 198
80 --- 170
80 --- 204
81 --- 121
81 x--> 151
81 --- 165
81 --- 199
81 --- 160
81 --- 194
82 --- 122
82 x--> 151
82 --- 169
82 --- 203
82 --- 164
82 --- 198
84 --- 123
84 x--> 145
84 --- 171
@ -756,39 +756,39 @@ flowchart LR
109 --- 107
111 --- 159
111 --- 193
112 --- 160
112 --- 194
195 <--x 112
113 --- 162
113 --- 196
197 <--x 113
114 --- 167
114 --- 201
202 <--x 114
115 --- 170
194 <--x 115
115 --- 204
116 --- 166
116 --- 200
201 <--x 116
117 --- 163
117 --- 197
198 <--x 117
118 --- 168
118 --- 202
203 <--x 118
119 --- 161
119 --- 195
196 <--x 119
120 --- 164
120 --- 198
199 <--x 120
121 --- 165
121 --- 199
200 <--x 121
122 --- 169
122 --- 203
204 <--x 122
112 --- 167
112 --- 201
202 <--x 112
113 --- 169
113 --- 203
204 <--x 113
114 --- 168
114 --- 202
203 <--x 114
115 --- 166
115 --- 200
201 <--x 115
116 --- 165
116 --- 199
200 <--x 116
117 --- 161
117 --- 195
196 <--x 117
118 --- 162
118 --- 196
197 <--x 118
119 --- 163
119 --- 197
198 <--x 119
120 --- 170
194 <--x 120
120 --- 204
121 --- 160
121 --- 194
195 <--x 121
122 --- 164
122 --- 198
199 <--x 122
123 --- 171
123 --- 205
124 --- 186

View File

@ -485,13 +485,8 @@ description: Operations executed herringbone-gear.kcl
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
"type": "Known",
"type": "Count"
}
},
"sourceRange": []

View File

@ -932,13 +932,8 @@ description: Operations executed herringbone-planetary-gearset.kcl
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
"type": "Known",
"type": "Count"
}
},
"sourceRange": []
@ -981,13 +976,8 @@ description: Operations executed herringbone-planetary-gearset.kcl
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
"type": "Known",
"type": "Count"
}
},
"sourceRange": []
@ -1563,13 +1553,8 @@ description: Operations executed herringbone-planetary-gearset.kcl
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
"type": "Known",
"type": "Count"
}
},
"sourceRange": []

View File

@ -177,72 +177,72 @@ flowchart LR
2 ---- 34
17 --- 35
17 x--> 52
17 --- 55
17 --- 72
17 --- 58
17 --- 75
18 --- 36
18 x--> 52
18 --- 58
18 --- 75
18 --- 66
18 --- 83
19 --- 37
19 x--> 52
19 --- 60
19 --- 77
20 --- 38
20 x--> 52
20 --- 69
20 --- 86
20 --- 61
20 --- 78
21 --- 39
21 x--> 52
21 --- 62
21 --- 79
21 --- 67
21 --- 84
22 --- 40
22 x--> 52
22 --- 59
22 --- 76
22 --- 63
22 --- 80
23 --- 41
23 x--> 52
23 --- 56
23 --- 73
24 --- 42
24 x--> 52
24 --- 64
24 --- 81
24 --- 54
24 --- 71
25 --- 43
25 x--> 52
25 --- 57
25 --- 74
25 --- 70
25 --- 87
26 --- 44
26 x--> 52
26 --- 65
26 --- 82
26 --- 68
26 --- 85
27 --- 45
27 x--> 52
27 --- 70
27 --- 87
27 --- 65
27 --- 82
28 --- 46
28 x--> 52
28 --- 54
28 --- 71
28 --- 62
28 --- 79
29 --- 47
29 x--> 52
29 --- 67
29 --- 84
29 --- 57
29 --- 74
30 --- 48
30 x--> 52
30 --- 68
30 --- 85
30 --- 55
30 --- 72
31 --- 49
31 x--> 52
31 --- 66
31 --- 83
31 --- 64
31 --- 81
32 --- 50
32 x--> 52
32 --- 63
32 --- 80
32 --- 69
32 --- 86
33 --- 51
33 x--> 52
33 --- 61
33 --- 78
33 --- 59
33 --- 76
34 --- 35
34 --- 36
34 --- 37
@ -296,57 +296,57 @@ flowchart LR
34 --- 85
34 --- 86
34 --- 87
35 --- 55
71 <--x 35
35 --- 72
36 --- 58
74 <--x 36
36 --- 75
35 --- 58
74 <--x 35
35 --- 75
36 --- 66
82 <--x 36
36 --- 83
37 --- 60
76 <--x 37
37 --- 77
38 --- 69
85 <--x 38
38 --- 86
39 --- 62
78 <--x 39
39 --- 79
40 --- 59
75 <--x 40
40 --- 76
38 --- 61
77 <--x 38
38 --- 78
39 --- 67
83 <--x 39
39 --- 84
40 --- 63
79 <--x 40
40 --- 80
41 --- 56
72 <--x 41
41 --- 73
42 --- 64
80 <--x 42
42 --- 81
43 --- 57
73 <--x 43
43 --- 74
44 --- 65
81 <--x 44
44 --- 82
45 --- 70
86 <--x 45
45 --- 87
46 --- 54
46 --- 71
87 <--x 46
47 --- 67
83 <--x 47
47 --- 84
48 --- 68
84 <--x 48
48 --- 85
49 --- 66
82 <--x 49
49 --- 83
50 --- 63
79 <--x 50
50 --- 80
51 --- 61
77 <--x 51
51 --- 78
42 --- 54
42 --- 71
87 <--x 42
43 --- 70
86 <--x 43
43 --- 87
44 --- 68
84 <--x 44
44 --- 85
45 --- 65
81 <--x 45
45 --- 82
46 --- 62
78 <--x 46
46 --- 79
47 --- 57
73 <--x 47
47 --- 74
48 --- 55
71 <--x 48
48 --- 72
49 --- 64
80 <--x 49
49 --- 81
50 --- 69
85 <--x 50
50 --- 86
51 --- 59
75 <--x 51
51 --- 76
54 <--x 53
55 <--x 53
56 <--x 53

View File

@ -112,8 +112,8 @@ flowchart LR
8 --- 20
8 ---- 25
12 <--x 32
12 <--x 33
12 --- 34
12 --- 33
12 <--x 34
13 --- 31
13 x--> 35
13 --- 39

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

View File

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 59 KiB

View File

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 62 KiB

View File

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 69 KiB

View File

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 64 KiB

View File

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 78 KiB

View File

Before

Width:  |  Height:  |  Size: 132 KiB

After

Width:  |  Height:  |  Size: 132 KiB

View File

Before

Width:  |  Height:  |  Size: 132 KiB

After

Width:  |  Height:  |  Size: 132 KiB

View File

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

View File

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 53 KiB

View File

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 73 KiB

View File

Before

Width:  |  Height:  |  Size: 185 KiB

After

Width:  |  Height:  |  Size: 185 KiB

View File

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 88 KiB

View File

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

View File

@ -1107,7 +1107,11 @@ export class SceneEntities {
(lastSegment.type === 'TangentialArc' && segmentName !== 'line') ||
segmentName === 'tangentialArc'
) {
resolvedFunctionName = 'tangentialArc'
if (snappedPoint[0] === 0 || snappedPoint[1] === 0) {
resolvedFunctionName = 'tangentialArcTo'
} else {
resolvedFunctionName = 'tangentialArc'
}
} else if (snappedToTangent) {
// Generate tag for previous arc segment and use it for the angle of angledLine:
// |> tangentialArc(endAbsolute = [5, -10], tag = $arc001)

View File

@ -21,6 +21,7 @@ import {
filterOperations,
getOperationIcon,
getOperationLabel,
getOperationVariableName,
stdLibMap,
} from '@src/lib/operations'
import { editorManager, kclManager, rustContext } from '@src/lib/singletons'
@ -236,6 +237,7 @@ const VisibilityToggle = (props: VisibilityToggleProps) => {
const OperationItemWrapper = ({
icon,
name,
variableName,
visibilityToggle,
menuItems,
errors,
@ -246,6 +248,7 @@ const OperationItemWrapper = ({
}: React.HTMLAttributes<HTMLButtonElement> & {
icon: CustomIconName
name: string
variableName?: string
visibilityToggle?: VisibilityToggleProps
customSuffix?: JSX.Element
menuItems?: ComponentProps<typeof ContextMenu>['items']
@ -264,8 +267,15 @@ const OperationItemWrapper = ({
className={`reset flex-1 flex items-center gap-2 text-left text-base ${selectable ? 'border-transparent dark:border-transparent' : 'border-none cursor-default'} ${className}`}
>
<CustomIcon name={icon} className="w-5 h-5 block" />
<div className="flex items-baseline">
<div className="mr-2">{name}</div>
<div className="flex items-baseline align-baseline">
<div className="mr-2">
{name}
{variableName && (
<span className="ml-2 opacity-50 text-[11px] font-semibold">
{variableName}
</span>
)}
</div>
{customSuffix && customSuffix}
</div>
</button>
@ -290,6 +300,11 @@ const OperationItem = (props: {
}) => {
const kclContext = useKclContext()
const name = getOperationLabel(props.item)
const variableName = useMemo(() => {
return getOperationVariableName(props.item, kclContext.ast)
}, [props.item, kclContext.ast])
const errors = useMemo(() => {
return kclContext.diagnostics.filter(
(diag) =>
@ -499,6 +514,7 @@ const OperationItem = (props: {
<OperationItemWrapper
icon={getOperationIcon(props.item)}
name={name}
variableName={variableName}
menuItems={menuItems}
onClick={selectOperation}
onDoubleClick={enterEditFlow}

View File

@ -24,6 +24,7 @@ export type ToolTip =
| 'yLineTo'
| 'angledLineThatIntersects'
| 'tangentialArc'
| 'tangentialArcTo'
| 'circle'
| 'circleThreePoint'
| 'arcTo'
@ -44,6 +45,7 @@ export const toolTips: Array<ToolTip> = [
'yLineTo',
'angledLineThatIntersects',
'tangentialArc',
'tangentialArcTo',
'circleThreePoint',
'arc',
'arcTo',

View File

@ -1018,217 +1018,61 @@ export const yLine: SketchLineHelperKw = {
export const tangentialArc: SketchLineHelperKw = {
add: ({ node, pathToNode, segmentInput, replaceExistingCallback }) => {
if (segmentInput.type !== 'straight-segment') return STRAIGHT_SEGMENT_ERR()
const { to } = segmentInput
const _node = { ...node }
const getNode = getNodeFromPathCurry(_node, pathToNode)
const _node1 = getNode<PipeExpression | CallExpressionKw>('PipeExpression')
if (err(_node1)) return _node1
const { node: pipe } = _node1
const _node2 = getNodeFromPath<VariableDeclarator>(
_node,
return tangentialArcHelpers.add({
node,
pathToNode,
'VariableDeclarator'
)
if (err(_node2)) return _node2
const { node: varDec } = _node2
const toX = createLiteral(roundOff(to[0], 2))
const toY = createLiteral(roundOff(to[1], 2))
if (replaceExistingCallback && pipe.type !== 'CallExpressionKw') {
const { index: callIndex } = splitPathAtPipeExpression(pathToNode)
const result = replaceExistingCallback([
{
type: 'labeledArgArrayItem',
key: ARG_END_ABSOLUTE,
index: 0,
argType: 'xAbsolute',
expr: toX,
},
{
type: 'labeledArgArrayItem',
key: ARG_END_ABSOLUTE,
index: 1,
argType: 'yAbsolute',
expr: toY,
},
])
if (err(result)) return result
const { callExp, valueUsedInTransform } = result
pipe.body[callIndex] = callExp
return {
modifiedAst: _node,
pathToNode,
valueUsedInTransform,
}
}
const newLine = createCallExpressionStdLibKw(
'tangentialArc',
null, // Assumes this is being called in a pipeline, so the first arg is optional and if not given, will become pipeline substitution.
[createLabeledArg(ARG_END_ABSOLUTE, createArrayExpression([toX, toY]))]
)
if (pipe.type === 'PipeExpression') {
pipe.body = [...pipe.body, newLine]
return {
modifiedAst: _node,
pathToNode: [
...pathToNode.slice(
0,
pathToNode.findIndex(([_, type]) => type === 'PipeExpression') + 1
),
['body', 'PipeExpression'],
[pipe.body.length - 1, 'CallExpressionKw'],
],
}
} else {
varDec.init = createPipeExpression([varDec.init, newLine])
}
return {
modifiedAst: _node,
pathToNode,
}
segmentInput,
replaceExistingCallback,
isAbsolute: false,
})
},
updateArgs: ({ node, pathToNode, input }) => {
if (input.type !== 'straight-segment') return STRAIGHT_SEGMENT_ERR()
const { to } = input
const _node = { ...node }
const nodeMeta = getNodeFromPath<CallExpressionKw>(_node, pathToNode)
if (err(nodeMeta)) return nodeMeta
const { node: callExpression } = nodeMeta
if (callExpression.type !== 'CallExpressionKw') {
return new Error(
`Expected CallExpressionKw, but found ${callExpression.type}`
)
}
for (const arg of callExpression.arguments) {
if (arg.label?.name !== ARG_END_ABSOLUTE && arg.label?.name !== ARG_TAG) {
console.debug(
'Trying to edit unsupported tangentialArc keyword arguments; skipping'
)
return {
modifiedAst: _node,
pathToNode,
}
}
}
const toArrExp = createArrayExpression([
createLiteral(roundOff(to[0], 2)),
createLiteral(roundOff(to[1], 2)),
])
mutateKwArg(ARG_END_ABSOLUTE, callExpression, toArrExp)
return {
modifiedAst: _node,
return tangentialArcHelpers.update({
node,
pathToNode,
}
input,
isAbsolute: false,
})
},
getTag: getTagKwArg(),
addTag: addTagKw(),
getConstraintInfo: (callExp: CallExpressionKw, code, pathToNode) => {
if (callExp.type !== 'CallExpressionKw') return []
if (callExp.callee.name.name !== 'tangentialArc') return []
const callee = callExp.callee
const pathToCallee: PathToNode = [
...pathToNode,
['callee', 'CallExpressionKw'],
]
const endAbsoluteArg = findKwArgWithIndex(ARG_END_ABSOLUTE, callExp)
return tangentialArcHelpers.getConstraintInfo({
callExp,
code,
pathToNode,
isAbsolute: false,
})
},
}
const constraints: ConstrainInfo[] = [
constrainInfo(
'tangentialWithPrevious',
true,
callee.name.name,
'tangentialArc',
undefined,
topLevelRange(callee.start, callee.end),
pathToCallee
),
]
if (endAbsoluteArg) {
const { expr, argIndex } = endAbsoluteArg
const pathToArgs: PathToNode = [
...pathToNode,
['arguments', 'CallExpressionKw'],
]
const pathToArg: PathToNode = [
...pathToArgs,
[argIndex, ARG_INDEX_FIELD],
['arg', LABELED_ARG_FIELD],
]
if (expr.type !== 'ArrayExpression' || expr.elements.length < 2) {
constraints.push({
stdLibFnName: 'tangentialArc',
type: 'xAbsolute',
isConstrained: isNotLiteralArrayOrStatic(expr),
sourceRange: topLevelRange(expr.start, expr.end),
pathToNode: pathToArg,
value: code.slice(expr.start, expr.end),
argPosition: {
type: 'labeledArgArrayItem',
index: 0,
key: ARG_END_ABSOLUTE,
},
})
constraints.push({
stdLibFnName: 'tangentialArc',
type: 'yAbsolute',
isConstrained: isNotLiteralArrayOrStatic(expr),
sourceRange: topLevelRange(expr.start, expr.end),
pathToNode: pathToArg,
value: code.slice(expr.start, expr.end),
argPosition: {
type: 'labeledArgArrayItem',
index: 1,
key: ARG_END_ABSOLUTE,
},
})
return constraints
}
const pathToX: PathToNode = [
...pathToArg,
['elements', 'ArrayExpression'],
[0, 'index'],
]
const pathToY: PathToNode = [
...pathToArg,
['elements', 'ArrayExpression'],
[1, 'index'],
]
const exprX = expr.elements[0]
const exprY = expr.elements[1]
constraints.push({
stdLibFnName: 'tangentialArc',
type: 'xAbsolute',
isConstrained: isNotLiteralArrayOrStatic(exprX),
sourceRange: topLevelRange(exprX.start, exprX.end),
pathToNode: pathToX,
value: code.slice(exprX.start, exprX.end),
argPosition: {
type: 'labeledArgArrayItem',
index: 0,
key: ARG_END_ABSOLUTE,
},
})
constraints.push({
stdLibFnName: 'tangentialArc',
type: 'yAbsolute',
isConstrained: isNotLiteralArrayOrStatic(exprY),
sourceRange: topLevelRange(exprY.start, exprY.end),
pathToNode: pathToY,
value: code.slice(exprY.start, exprY.end),
argPosition: {
type: 'labeledArgArrayItem',
index: 1,
key: ARG_END_ABSOLUTE,
},
})
}
return constraints
export const tangentialArcTo: SketchLineHelperKw = {
add: ({ node, pathToNode, segmentInput, replaceExistingCallback }) => {
return tangentialArcHelpers.add({
node,
pathToNode,
segmentInput,
replaceExistingCallback,
isAbsolute: true,
})
},
updateArgs: ({ node, pathToNode, input }) => {
return tangentialArcHelpers.update({
node,
pathToNode,
input,
isAbsolute: true,
})
},
getTag: getTagKwArg(),
addTag: addTagKw(),
getConstraintInfo: (callExp: CallExpressionKw, code, pathToNode) => {
return tangentialArcHelpers.getConstraintInfo({
callExp,
code,
pathToNode,
isAbsolute: true,
})
},
}
@ -3311,6 +3155,7 @@ export const sketchLineHelperMapKw: { [key: string]: SketchLineHelperKw } = {
angledLineToX,
angledLineToY,
tangentialArc,
tangentialArcTo,
startProfile,
} as const
@ -3386,6 +3231,7 @@ export function fnNameToToolTipFromSegment(
fnName: string
): ToolTip | Error {
switch (fnName) {
case 'arcTo':
case 'arc': {
return seg.type === 'ArcThreePoint' ? 'arcTo' : 'arc'
}
@ -3403,6 +3249,7 @@ export function fnNameToToolTipFromSegment(
case 'circleThreePoint':
case 'circle':
case 'tangentialArc':
case 'tangentialArcTo':
case 'angledLine':
case 'startProfile':
case 'arcTo':
@ -3426,8 +3273,7 @@ export function fnNameToTooltip(
argLabels: string[],
fnName: string
): ToolTip | Error {
const isAbsolute =
argLabels.findIndex((label) => label === ARG_END_ABSOLUTE) >= 0
const isAbsolute = argLabels.some((label) => label === ARG_END_ABSOLUTE)
switch (fnName) {
case 'arc': {
const isArc = argLabels.some((label) =>
@ -3441,10 +3287,11 @@ export function fnNameToTooltip(
return isAbsolute ? 'xLineTo' : 'xLine'
case 'yLine':
return isAbsolute ? 'yLineTo' : 'yLine'
case 'tangentialArc':
return isAbsolute ? 'tangentialArcTo' : 'tangentialArc'
case 'angledLineThatIntersects':
case 'circleThreePoint':
case 'circle':
case 'tangentialArc':
case 'startProfile':
return fnName
case 'angledLine': {
@ -3485,6 +3332,7 @@ export function tooltipToFnName(tooltip: ToolTip): string | Error {
case 'xLine':
case 'yLine':
case 'line':
case 'tangentialArc':
return tooltip
case 'lineTo':
return 'line'
@ -3492,6 +3340,8 @@ export function tooltipToFnName(tooltip: ToolTip): string | Error {
return 'xLine'
case 'yLineTo':
return 'yLine'
case 'tangentialArcTo':
return 'tangentialArc'
case 'angledLine':
case 'angledLineToX':
case 'angledLineToY':
@ -4099,7 +3949,6 @@ export function isAbsoluteLine(lineCall: CallExpressionKw): boolean | Error {
const name = lineCall?.callee?.name.name
switch (name) {
case 'line':
case 'tangentialArc':
if (findKwArg(ARG_END, lineCall) !== undefined) {
return false
}
@ -4120,6 +3969,8 @@ export function isAbsoluteLine(lineCall: CallExpressionKw): boolean | Error {
return new Error(
`${name} call has neither ${ARG_END} nor ${ARG_END_ABSOLUTE} params`
)
case 'tangentialArc':
return findKwArg(ARG_END_ABSOLUTE, lineCall) !== undefined
case 'angledLineThatIntersects':
case 'arc':
case 'circle':
@ -4151,6 +4002,7 @@ export function getArgForEnd(lineCall: CallExpressionKw):
switch (name) {
case 'circle':
return getCircle(lineCall)
case 'tangentialArc':
case 'line': {
const arg = findKwArgAny(DETERMINING_ARGS, lineCall)
if (arg === undefined) {
@ -4207,3 +4059,264 @@ export function getArgForEnd(lineCall: CallExpressionKw):
function removeDeterminingArgs(callExp: CallExpressionKw) {
removeKwArgs(DETERMINING_ARGS, callExp)
}
const tangentialArcHelpers = {
add: ({
node,
pathToNode,
segmentInput,
replaceExistingCallback,
isAbsolute = false,
}: {
node: Node<Program>
pathToNode: PathToNode
segmentInput: SegmentInputs
replaceExistingCallback?: (
rawArgs: RawArgs
) => CreatedSketchExprResult | Error
isAbsolute?: boolean
}) => {
if (segmentInput.type !== 'straight-segment') return STRAIGHT_SEGMENT_ERR()
const { to, from } = segmentInput
const _node = { ...node }
const getNode = getNodeFromPathCurry(_node, pathToNode)
const _node1 = getNode<PipeExpression | CallExpressionKw>('PipeExpression')
if (err(_node1)) return _node1
const { node: pipe } = _node1
const _node2 = getNodeFromPath<VariableDeclarator>(
_node,
pathToNode,
'VariableDeclarator'
)
if (err(_node2)) return _node2
const { node: varDec } = _node2
const toX = createLiteral(roundOff(isAbsolute ? to[0] : to[0] - from[0], 2))
const toY = createLiteral(roundOff(isAbsolute ? to[1] : to[1] - from[1], 2))
const argLabel = isAbsolute ? ARG_END_ABSOLUTE : ARG_END
const xArgType = isAbsolute ? 'xAbsolute' : 'xRelative'
const yArgType = isAbsolute ? 'yAbsolute' : 'yRelative'
if (replaceExistingCallback && pipe.type !== 'CallExpressionKw') {
const { index: callIndex } = splitPathAtPipeExpression(pathToNode)
const result = replaceExistingCallback([
{
type: 'labeledArgArrayItem',
key: argLabel,
index: 0,
argType: xArgType,
expr: toX,
},
{
type: 'labeledArgArrayItem',
key: argLabel,
index: 1,
argType: yArgType,
expr: toY,
},
])
if (err(result)) return result
const { callExp, valueUsedInTransform } = result
pipe.body[callIndex] = callExp
return {
modifiedAst: _node,
pathToNode,
valueUsedInTransform,
}
}
const newLine = createCallExpressionStdLibKw(
'tangentialArc',
null, // Assumes this is being called in a pipeline, so the first arg is optional and if not given, will become pipeline substitution.
[createLabeledArg(argLabel, createArrayExpression([toX, toY]))]
)
if (pipe.type === 'PipeExpression') {
pipe.body = [...pipe.body, newLine]
return {
modifiedAst: _node,
pathToNode: [
...pathToNode.slice(
0,
pathToNode.findIndex(([_, type]) => type === 'PipeExpression') + 1
),
['body', 'PipeExpression'],
[pipe.body.length - 1, 'CallExpressionKw'],
] as PathToNode,
}
} else {
varDec.init = createPipeExpression([varDec.init, newLine])
}
return {
modifiedAst: _node,
pathToNode,
}
},
update: ({
node,
pathToNode,
input,
isAbsolute = false,
}: {
node: Node<Program>
pathToNode: PathToNode
input: SegmentInputs
isAbsolute?: boolean
}) => {
if (input.type !== 'straight-segment') return STRAIGHT_SEGMENT_ERR()
const { to, from } = input
const _node = { ...node }
const nodeMeta = getNodeFromPath<CallExpressionKw>(_node, pathToNode)
if (err(nodeMeta)) return nodeMeta
const { node: callExpression } = nodeMeta
if (callExpression.type !== 'CallExpressionKw') {
return new Error(
`Expected CallExpressionKw, but found ${callExpression.type}`
)
}
const argLabel = isAbsolute ? ARG_END_ABSOLUTE : ARG_END
const functionName = isAbsolute ? 'tangentialArcTo' : 'tangentialArc'
for (const arg of callExpression.arguments) {
if (arg.label?.name !== argLabel && arg.label?.name !== ARG_TAG) {
console.debug(
`Trying to edit unsupported ${functionName} keyword arguments; skipping`
)
return {
modifiedAst: _node,
pathToNode,
}
}
}
const toArrExp = createArrayExpression([
createLiteral(roundOff(isAbsolute ? to[0] : to[0] - from[0], 2)),
createLiteral(roundOff(isAbsolute ? to[1] : to[1] - from[1], 2)),
])
mutateKwArg(argLabel, callExpression, toArrExp)
return {
modifiedAst: _node,
pathToNode,
}
},
getConstraintInfo: ({
callExp,
code,
pathToNode,
isAbsolute = false,
}: {
callExp: CallExpressionKw
code: string
pathToNode: PathToNode
isAbsolute?: boolean
}): ConstrainInfo[] => {
if (callExp.type !== 'CallExpressionKw') return []
if (callExp.callee.name.name !== 'tangentialArc') return []
const callee = callExp.callee
const pathToCallee: PathToNode = [
...pathToNode,
['callee', 'CallExpressionKw'],
]
const argLabel = isAbsolute ? ARG_END_ABSOLUTE : ARG_END
const xConstraintType = isAbsolute ? 'xAbsolute' : 'xRelative'
const yConstraintType = isAbsolute ? 'yAbsolute' : 'yRelative'
const endArg = findKwArgWithIndex(argLabel, callExp)
const constraints: ConstrainInfo[] = [
constrainInfo(
'tangentialWithPrevious',
true,
callee.name.name,
'tangentialArc',
undefined,
topLevelRange(callee.start, callee.end),
pathToCallee
),
]
if (endArg) {
const { expr, argIndex } = endArg
const pathToArgs: PathToNode = [
...pathToNode,
['arguments', 'CallExpressionKw'],
]
const pathToArg: PathToNode = [
...pathToArgs,
[argIndex, ARG_INDEX_FIELD],
['arg', LABELED_ARG_FIELD],
]
if (expr.type !== 'ArrayExpression' || expr.elements.length < 2) {
constraints.push({
stdLibFnName: 'tangentialArc',
type: xConstraintType,
isConstrained: isNotLiteralArrayOrStatic(expr),
sourceRange: topLevelRange(expr.start, expr.end),
pathToNode: pathToArg,
value: code.slice(expr.start, expr.end),
argPosition: {
type: 'labeledArgArrayItem',
index: 0,
key: argLabel,
},
})
constraints.push({
stdLibFnName: 'tangentialArc',
type: yConstraintType,
isConstrained: isNotLiteralArrayOrStatic(expr),
sourceRange: topLevelRange(expr.start, expr.end),
pathToNode: pathToArg,
value: code.slice(expr.start, expr.end),
argPosition: {
type: 'labeledArgArrayItem',
index: 1,
key: argLabel,
},
})
return constraints
}
const pathToX: PathToNode = [
...pathToArg,
['elements', 'ArrayExpression'],
[0, 'index'],
]
const pathToY: PathToNode = [
...pathToArg,
['elements', 'ArrayExpression'],
[1, 'index'],
]
const exprX = expr.elements[0]
const exprY = expr.elements[1]
constraints.push({
stdLibFnName: 'tangentialArc',
type: xConstraintType,
isConstrained: isNotLiteralArrayOrStatic(exprX),
sourceRange: topLevelRange(exprX.start, exprX.end),
pathToNode: pathToX,
value: code.slice(exprX.start, exprX.end),
argPosition: {
type: 'labeledArgArrayItem',
index: 0,
key: argLabel,
},
})
constraints.push({
stdLibFnName: 'tangentialArc',
type: yConstraintType,
isConstrained: isNotLiteralArrayOrStatic(exprY),
sourceRange: topLevelRange(exprY.start, exprY.end),
pathToNode: pathToY,
value: code.slice(exprY.start, exprY.end),
argPosition: {
type: 'labeledArgArrayItem',
index: 1,
key: argLabel,
},
})
}
return constraints
},
}

View File

@ -1502,23 +1502,20 @@ export function removeSingleConstraint({
const literal = rawArg?.overrideExpr ?? rawArg?.expr
return (arg.index === inputToReplace.index && literal) || argExpr
})
// It's a kw call.
const isAbsolute = callExp.node.callee.name.name == 'lineTo'
if (isAbsolute) {
const args = [
createLabeledArg(ARG_END_ABSOLUTE, createArrayExpression(values)),
]
return createStdlibCallExpressionKw('line', args, tag)
} else {
const args = [
createLabeledArg(ARG_END, createArrayExpression(values)),
]
return createStdlibCallExpressionKw(
callExp.node.callee.name.name as ToolTip,
args,
tag
)
}
const isAbsolute = inputs.some((input) => input.argType === 'xAbsolute')
const args = [
createLabeledArg(
isAbsolute ? ARG_END_ABSOLUTE : ARG_END,
createArrayExpression(values)
),
]
return createStdlibCallExpressionKw(
callExp.node.callee.name.name as ToolTip,
args,
tag
)
}
if (
inputToReplace.type === 'arrayInObject' ||

View File

@ -1,7 +1,12 @@
import type { Operation } from '@rust/kcl-lib/bindings/Operation'
import { topLevelRange } from '@src/lang/util'
import { defaultSourceRange } from '@src/lang/wasm'
import { filterOperations } from '@src/lib/operations'
import {
assertParse,
defaultSourceRange,
type SourceRange,
} from '@src/lang/wasm'
import { filterOperations, getOperationVariableName } from '@src/lib/operations'
function stdlib(name: string): Operation {
return {
@ -162,3 +167,75 @@ describe('operations filtering', () => {
])
})
})
function rangeOfText(fullCode: string, target: string): SourceRange {
const start = fullCode.indexOf(target)
if (start === -1) {
throw new Error(`Could not find \`${target}\` in: ${fullCode}`)
}
return topLevelRange(start, start + target.length)
}
describe('variable name of operations', () => {
it('finds the variable name with simple assignment', async () => {
const op = stdlib('stdLibFn')
if (op.type !== 'StdLibCall') {
throw new Error('Expected operation to be a StdLibCall')
}
const code = `myVar = stdLibFn()`
// Make the source range match the code.
op.sourceRange = rangeOfText(code, 'stdLibFn()')
const program = assertParse(code)
const variableName = getOperationVariableName(op, program)
expect(variableName).toBe('myVar')
})
it('finds the variable name inside a function with simple assignment', async () => {
const op = stdlib('stdLibFn')
if (op.type !== 'StdLibCall') {
throw new Error('Expected operation to be a StdLibCall')
}
const code = `fn myFunc() {
myVar = stdLibFn()
return 0
}
`
// Make the source range match the code.
op.sourceRange = rangeOfText(code, 'stdLibFn()')
const program = assertParse(code)
const variableName = getOperationVariableName(op, program)
expect(variableName).toBe('myVar')
})
it("finds the variable name when it's the last in a pipeline", async () => {
const op = stdlib('stdLibFn')
if (op.type !== 'StdLibCall') {
throw new Error('Expected operation to be a StdLibCall')
}
const code = `myVar = foo()
|> stdLibFn()
`
// Make the source range match the code.
op.sourceRange = rangeOfText(code, 'stdLibFn()')
const program = assertParse(code)
const variableName = getOperationVariableName(op, program)
expect(variableName).toBe('myVar')
})
it("finds nothing when it's not the last in a pipeline", async () => {
const op = stdlib('stdLibFn')
if (op.type !== 'StdLibCall') {
throw new Error('Expected operation to be a StdLibCall')
}
const code = `myVar = foo()
|> stdLibFn()
|> bar()
`
// Make the source range match the code.
op.sourceRange = rangeOfText(code, 'stdLibFn()')
const program = assertParse(code)
const variableName = getOperationVariableName(op, program)
expect(variableName).toBeUndefined()
})
})

View File

@ -15,7 +15,13 @@ import {
getSweepEdgeCodeRef,
getWallCodeRef,
} from '@src/lang/std/artifactGraph'
import { type PipeExpression, sourceRangeFromRust } from '@src/lang/wasm'
import {
type CallExpressionKw,
type PipeExpression,
type Program,
sourceRangeFromRust,
type VariableDeclaration,
} from '@src/lang/wasm'
import type {
HelixModes,
ModelingCommandSchema,
@ -1074,6 +1080,71 @@ export function getOperationIcon(op: Operation): CustomIconName {
}
}
/**
* If the result of the operation is assigned to a variable, returns the
* variable name.
*/
export function getOperationVariableName(
op: Operation,
program: Program
): string | undefined {
if (
op.type !== 'StdLibCall' &&
!(op.type === 'GroupBegin' && op.group.type === 'FunctionCall')
) {
return undefined
}
// Find the AST node.
const range = sourceRangeFromRust(op.sourceRange)
const pathToNode = getNodePathFromSourceRange(program, range)
if (pathToNode.length === 0) {
return undefined
}
const call = getNodeFromPath<CallExpressionKw>(
program,
pathToNode,
'CallExpressionKw'
)
if (err(call) || call.node.type !== 'CallExpressionKw') {
return undefined
}
// Find the var name from the variable declaration.
const varDec = getNodeFromPath<VariableDeclaration>(
program,
pathToNode,
'VariableDeclaration'
)
if (err(varDec)) {
return undefined
}
if (varDec.node.type !== 'VariableDeclaration') {
// There's no variable declaration for this call.
return undefined
}
const varName = varDec.node.declaration.id.name
// If the operation is a simple assignment, we can use the variable name.
if (varDec.node.declaration.init === call.node) {
return varName
}
// If the AST node is in a pipe expression, we can only use the variable
// name if it's the last operation in the pipe.
const pipe = getNodeFromPath<PipeExpression>(
program,
pathToNode,
'PipeExpression'
)
if (err(pipe)) {
return undefined
}
if (
pipe.node.type === 'PipeExpression' &&
pipe.node.body[pipe.node.body.length - 1] === call.node
) {
return varName
}
return undefined
}
/**
* Apply all filters to a list of operations.
*/