Compare commits

...

12 Commits

Author SHA1 Message Date
324b1d0251 pierremtb/adhoc/quick-eval-stream-offset-impact-on-e2e 2025-04-24 15:19:02 -04:00
305d613d40 Nadro/adhoc/system io machine (#6352)
* chore: saving off skeleton

* fix: saving skeleton

* chore: skeleton for loading projects from project directory path

* chore: cleaning up useless state transition to be an on event direct to action state

* fix: new structure for web vs desktop vs react machine provider code

* chore: saving off skeleton

* fix: skeleton logic for react? going to move it from a string to obj.string

* fix: trying to prevent error element unmount on global react components. This is bricking JS state

* fix: we are so back

* chore: implemented navigating to specfic KCL file

* chore: implementing renaming project

* chore: deleting project

* fix: auto fixes

* fix: old debug/testing file oops

* chore: generic create new file

* chore: skeleton for web create file provide

* chore: basic machine vitest... need to figure out how to get window.electron implemented in vitest?

* chore: save off progress before deleting other project implementation, a few missing features still

* chore: trying a different init skeleton? most likely will migrate

* chore: first attempt of purging projects context provider

* chore: enabling toast for some machine state

* chore: enabling more toast success and error

* chore: writing read write state to the system io based on the project path

* fix: tsc fixes

* fix: use file system watcher, navigate to project after creation via the requestProjectName

* chore: open project command, hooks vs snapshot context helpers

* chore: implemented open and create project for e2e testing. They are hard coded in poor spot for now.

* fix: codespell fixes

* chore: implementing more project commands

* chore: PR improvements for root.tsx

* chore: leaving comment about new Router.tsx layout

* fix: removing debugging code

* fix: rewriting component for readability

* fix: improving web initialization

* chore: implementing import file from url which is not actually that?

* fix: clearing search params on import file from url

* fix: fixed two e2e tests, forgot needsReview when making new command

* fix: fixing some import from url business logic to pass e2e tests

* chore: script for diffing circular deps +/-

* fix: formatting

* fix: massive fix for circular depsga!

* fix: trying to fix some errors and auto fmt

* fix: updating deps

* fix: removing debugging code

* fix: big clean up

* fix: more deletion

* fix: tsc cleanup

* fix: TSC TSC TSC TSC!

* fix: typo fix

* fix: clear query params on web only, desktop not required

* fix: removing unused code

* fmt

* Bring back `trap` removed in merge

* Use explicit types instead of `any`s on arg configs

* Add project commands directly to command palette

* fix: deleting debugging code, from PR review

* fix: this got added back(?)

* fix: using referred type

* fix: more PR clean up

* fix: big block comment for xstate architecture decision

* fix: more pr comment fixes

* fix: merge conflict just added them back why dude

* fix: more PR comments

* fix: big ciruclar deps fix, commandBarActor in appActor

---------

Co-authored-by: Frank Noirot <frankjohnson1993@gmail.com>
2025-04-24 13:32:49 -05:00
95f2caacab Fix testing-selections test / clicking on empty space (#6481)
fix clicking on empty space which happened to click on UI, causing the test to fail
2025-04-24 17:46:07 +00:00
8f61ee1d2f Change getOppositeEdge, getNextAdjacentEdge, and getPreviousAdjacentEdge to keyword args (#6469)
* Change getOppositeEdge, getNextAdjacentEdge, and getPreviousAdjacentEdge to keyword args

* Update generated docs
2025-04-24 12:39:37 -04:00
b02dbd4fe6 Kwargs: leg helpers (#6459)
legLen, legAngX, legAngY moved to keyword arguments
2025-04-24 09:53:19 -05:00
668f6671a9 BREAKING: Remove angleToMatchLengthX and angleToMatchLengthY (#6451)
* Remove angleToMatchLengthX and angleToMatchLengthY from constraint code generation

* Change KCL stdlib functions to be deprecated

* Remove references from TS tests

* Remove angleToMatchLengthX and angleToMatchLengthY

* Update docs

* Fix file paths
2025-04-24 14:33:27 +00:00
f6387eb7e9 fmt (#6473) 2025-04-24 13:10:06 +00:00
83a87b046f Declare std::offsetPlane in KCL (#6344)
* Declare std::offsetPlane in KCL

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

* Use two axes to define planes in KCL

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

---------

Signed-off-by: Nick Cameron <nrc@ncameron.org>
2025-04-24 22:01:27 +12:00
20c2ce3bac Shorten tronapp setup fail (#6362)
* shorten tron app setup fail

* fmt

* more tweaks to tronapp setup

* bump initial timeout back to 120s

* Update e2e/playwright/zoo-test.ts

---------

Co-authored-by: Zookeeper Lee <lee@zoo.dev>
2025-04-24 06:35:57 +00:00
2956f9ed55 YOU FOOLS I WON THE CONTEST (#6328)
* dodec

* fmt

* comment

* Update kcl-samples simulation test output

* Update kcl-samples simulation test output

* Fix so that just commands regenerate ast output

* overwrite

* Update just command to include manifest

* Update generated output

* merge main post

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-04-24 06:08:45 +00:00
510d74f2c7 Add clone (#5462)
* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

update the extrude idds

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

fix sample

Signed-off-by: Jess Frazelle <github@jessfraz.com>

better docs

Signed-off-by: Jess Frazelle <github@jessfraz.com>

fix the start and end tag

Signed-off-by: Jess Frazelle <github@jessfraz.com>

better docs

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

new tests

Signed-off-by: Jess Frazelle <github@jessfraz.com>

codespell

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix examples

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix some stuff

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fixes

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* add another test for fillet

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* Update rust/kcl-lib/src/std/clone.rs

Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>

* fixes

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* add sweep test

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* revolve test;

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* Update rust/kcl-lib/src/std/clone.rs

Co-authored-by: Jonathan Tran <jonnytran@gmail.com>

* add another test for fillet

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* allow cloning an imported geometry;

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* allow for imported geometry

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* update docs

Signed-off-by: Jess Frazelle <github@jessfraz.com>

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-04-24 04:26:09 +00:00
457ab28f74 Appearance import fixes (#6466)
* fix appearance imports

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix appearance

Signed-off-by: Jess Frazelle <github@jessfraz.com>

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2025-04-24 00:43:16 +00:00
357 changed files with 31255 additions and 40663 deletions

View File

@ -4,6 +4,7 @@ on:
branches: branches:
- main - main
- all-e2e # this bypasses `fixme()` using `orRunWhenFullSuiteEnabled()` - all-e2e # this bypasses `fixme()` using `orRunWhenFullSuiteEnabled()`
- pierremtb/adhoc/quick-eval-stream-offset-impact-on-e2e
pull_request: pull_request:
schedule: schedule:
- cron: 0 * * * * # hourly - cron: 0 * * * * # hourly

File diff suppressed because one or more lines are too long

258
docs/kcl/clone.md Normal file

File diff suppressed because one or more lines are too long

View File

@ -9,7 +9,7 @@ Get the next adjacent edge to the edge given.
```js ```js
getNextAdjacentEdge(tag: TagIdentifier): Uuid getNextAdjacentEdge(edge: TagIdentifier): Uuid
``` ```
@ -17,7 +17,7 @@ getNextAdjacentEdge(tag: TagIdentifier): Uuid
| Name | Type | Description | Required | | Name | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| [`tag`](/docs/kcl/types/tag) | [`TagIdentifier`](/docs/kcl/types#tag-identifier) | | Yes | | `edge` | [`TagIdentifier`](/docs/kcl/types#tag-identifier) | The tag of the edge you want to find the next adjacent edge of. | Yes |
### Returns ### Returns

View File

@ -9,7 +9,7 @@ Get the opposite edge to the edge given.
```js ```js
getOppositeEdge(tag: TagIdentifier): Uuid getOppositeEdge(edge: TagIdentifier): Uuid
``` ```
@ -17,7 +17,7 @@ getOppositeEdge(tag: TagIdentifier): Uuid
| Name | Type | Description | Required | | Name | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| [`tag`](/docs/kcl/types/tag) | [`TagIdentifier`](/docs/kcl/types#tag-identifier) | | Yes | | `edge` | [`TagIdentifier`](/docs/kcl/types#tag-identifier) | The tag of the edge you want to find the opposite edge of. | Yes |
### Returns ### Returns

View File

@ -9,7 +9,7 @@ Get the previous adjacent edge to the edge given.
```js ```js
getPreviousAdjacentEdge(tag: TagIdentifier): Uuid getPreviousAdjacentEdge(edge: TagIdentifier): Uuid
``` ```
@ -17,7 +17,7 @@ getPreviousAdjacentEdge(tag: TagIdentifier): Uuid
| Name | Type | Description | Required | | Name | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| [`tag`](/docs/kcl/types/tag) | [`TagIdentifier`](/docs/kcl/types#tag-identifier) | | Yes | | `edge` | [`TagIdentifier`](/docs/kcl/types#tag-identifier) | The tag of the edge you want to find the previous adjacent edge of. | Yes |
### Returns ### Returns

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -32,8 +32,6 @@ layout: manual
* [`Z`](kcl/consts/std-Z) * [`Z`](kcl/consts/std-Z)
* [`abs`](kcl/abs) * [`abs`](kcl/abs)
* [`acos`](kcl/acos) * [`acos`](kcl/acos)
* [`angleToMatchLengthX`](kcl/angleToMatchLengthX)
* [`angleToMatchLengthY`](kcl/angleToMatchLengthY)
* [`angledLine`](kcl/angledLine) * [`angledLine`](kcl/angledLine)
* [`angledLineThatIntersects`](kcl/angledLineThatIntersects) * [`angledLineThatIntersects`](kcl/angledLineThatIntersects)
* [`appearance`](kcl/appearance) * [`appearance`](kcl/appearance)
@ -47,6 +45,7 @@ layout: manual
* [`ceil`](kcl/ceil) * [`ceil`](kcl/ceil)
* [`chamfer`](kcl/chamfer) * [`chamfer`](kcl/chamfer)
* [`circleThreePoint`](kcl/circleThreePoint) * [`circleThreePoint`](kcl/circleThreePoint)
* [`clone`](kcl/clone)
* [`close`](kcl/close) * [`close`](kcl/close)
* [`extrude`](kcl/extrude) * [`extrude`](kcl/extrude)
* [`fillet`](kcl/fillet) * [`fillet`](kcl/fillet)
@ -74,7 +73,7 @@ layout: manual
* [`map`](kcl/map) * [`map`](kcl/map)
* [`max`](kcl/max) * [`max`](kcl/max)
* [`min`](kcl/min) * [`min`](kcl/min)
* [`offsetPlane`](kcl/offsetPlane) * [`offsetPlane`](kcl/std-offsetPlane)
* [`patternCircular2d`](kcl/patternCircular2d) * [`patternCircular2d`](kcl/patternCircular2d)
* [`patternCircular3d`](kcl/patternCircular3d) * [`patternCircular3d`](kcl/patternCircular3d)
* [`patternLinear2d`](kcl/patternLinear2d) * [`patternLinear2d`](kcl/patternLinear2d)

View File

@ -22,6 +22,5 @@ once fixed in engine will just start working here with no language changes.
chamfer cases work currently. chamfer cases work currently.
- **Appearance**: Changing the appearance on a loft does not work. - **Appearance**: Changing the appearance on a loft does not work.
Changing the appearance on an imported model does not work.
- **CSG Booleans**: Coplanar (bodies that share a plane) unions, subtractions, and intersections are not currently supported. - **CSG Booleans**: Coplanar (bodies that share a plane) unions, subtractions, and intersections are not currently supported.

View File

@ -24,8 +24,8 @@ legAngX(
| Name | Type | Description | Required | | Name | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `hypotenuse` | [`number`](/docs/kcl/types/number) | | Yes | | `hypotenuse` | [`number`](/docs/kcl/types/number) | The length of the triangle's hypotenuse | Yes |
| `leg` | [`number`](/docs/kcl/types/number) | | Yes | | `leg` | [`number`](/docs/kcl/types/number) | The length of one of the triangle's legs (i.e. non-hypotenuse side) | Yes |
### Returns ### Returns
@ -35,7 +35,7 @@ legAngX(
### Examples ### Examples
```js ```js
legAngX(5, 3) legAngX(hypotenuse = 5, leg = 3)
``` ```

View File

@ -24,8 +24,8 @@ legAngY(
| Name | Type | Description | Required | | Name | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `hypotenuse` | [`number`](/docs/kcl/types/number) | | Yes | | `hypotenuse` | [`number`](/docs/kcl/types/number) | The length of the triangle's hypotenuse | Yes |
| `leg` | [`number`](/docs/kcl/types/number) | | Yes | | `leg` | [`number`](/docs/kcl/types/number) | The length of one of the triangle's legs (i.e. non-hypotenuse side) | Yes |
### Returns ### Returns
@ -35,7 +35,7 @@ legAngY(
### Examples ### Examples
```js ```js
legAngY(5, 3) legAngY(hypotenuse = 5, leg = 3)
``` ```

View File

@ -24,8 +24,8 @@ legLen(
| Name | Type | Description | Required | | Name | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `hypotenuse` | [`number`](/docs/kcl/types/number) | | Yes | | `hypotenuse` | [`number`](/docs/kcl/types/number) | The length of the triangle's hypotenuse | Yes |
| `leg` | [`number`](/docs/kcl/types/number) | | Yes | | `leg` | [`number`](/docs/kcl/types/number) | The length of one of the triangle's legs (i.e. non-hypotenuse side) | Yes |
### Returns ### Returns
@ -35,7 +35,7 @@ legLen(
### Examples ### Examples
```js ```js
legLen(5, 3) legLen(hypotenuse = 5, leg = 3)
``` ```

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

122
docs/kcl/std-offsetPlane.md Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,84 @@
---
title: "GeometryWithImportedGeometry"
excerpt: "A geometry including an imported geometry."
layout: manual
---
A geometry including an imported geometry.
**This schema accepts exactly one of the following:**
**Type:** `object`
## Properties
| Property | Type | Description | Required |
|----------|------|-------------|----------|
| `type` |enum: [`Sketch`](/docs/kcl/types/Sketch)| | No |
| `id` |[`string`](/docs/kcl/types/string)| The id of the sketch (this will change when the engine's reference to it changes). | No |
| `paths` |`[` [`Path`](/docs/kcl/types/Path) `]`| The paths in the sketch. | No |
| `on` |[`SketchSurface`](/docs/kcl/types/SketchSurface)| What the sketch is on (can be a plane or a face). | No |
| `start` |[`BasePath`](/docs/kcl/types/BasePath)| The starting path. | No |
| `tags` |`object`| Tag identifiers that have been declared in this sketch. | No |
| `artifactId` |[`string`](/docs/kcl/types/string)| The original id of the sketch. This stays the same even if the sketch is is sketched on face etc. | No |
| `originalId` |[`string`](/docs/kcl/types/string)| | No |
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A unit of length. | No |
----
**Type:** `object`
## Properties
| Property | Type | Description | Required |
|----------|------|-------------|----------|
| `type` |enum: [`Solid`](/docs/kcl/types/Solid)| | No |
| `id` |[`string`](/docs/kcl/types/string)| The id of the solid. | No |
| `artifactId` |[`string`](/docs/kcl/types/string)| The artifact ID of the solid. Unlike `id`, this doesn't change. | No |
| `value` |`[` [`ExtrudeSurface`](/docs/kcl/types/ExtrudeSurface) `]`| The extrude surfaces. | No |
| `sketch` |[`Sketch`](/docs/kcl/types/Sketch)| The sketch. | No |
| `height` |[`number`](/docs/kcl/types/number)| The height of the solid. | No |
| `startCapId` |[`string`](/docs/kcl/types/string)| The id of the extrusion start cap | No |
| `endCapId` |[`string`](/docs/kcl/types/string)| The id of the extrusion end cap | No |
| `edgeCuts` |`[` [`EdgeCut`](/docs/kcl/types/EdgeCut) `]`| Chamfers or fillets on this solid. | No |
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| The units of the solid. | No |
| `sectional` |`boolean`| Is this a sectional solid? | No |
----
Data for an imported geometry.
**Type:** `object`
## Properties
| Property | Type | Description | Required |
|----------|------|-------------|----------|
| `type` |enum: `ImportedGeometry`| | No |
| `id` |[`string`](/docs/kcl/types/string)| The ID of the imported geometry. | No |
| `value` |`[` [`string`](/docs/kcl/types/string) `]`| The original file paths. | No |
----

View File

@ -30,7 +30,6 @@ A sketch type.
| `origin` |[`Point3d`](/docs/kcl/types/Point3d)| Origin of the plane. | No | | `origin` |[`Point3d`](/docs/kcl/types/Point3d)| Origin of the plane. | No |
| `xAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the plane's X axis be? | No | | `xAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the plane's X axis be? | No |
| `yAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the plane's Y axis be? | No | | `yAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the plane's Y axis be? | No |
| `zAxis` |[`Point3d`](/docs/kcl/types/Point3d)| The z-axis (normal). | No |
---- ----
@ -52,7 +51,6 @@ A face.
| `value` |[`string`](/docs/kcl/types/string)| The tag of the face. | No | | `value` |[`string`](/docs/kcl/types/string)| The tag of the face. | No |
| `xAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the face's X axis be? | No | | `xAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the face's X axis be? | No |
| `yAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the face's Y axis be? | No | | `yAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the face's Y axis be? | No |
| `zAxis` |[`Point3d`](/docs/kcl/types/Point3d)| The z-axis (normal). | No |
| `solid` |[`Solid`](/docs/kcl/types/Solid)| The solid the face is on. | No | | `solid` |[`Solid`](/docs/kcl/types/Solid)| The solid the face is on. | No |
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A unit of length. | No | | `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A unit of length. | No |

View File

@ -21,7 +21,7 @@ test.describe(
clickCoords: { x: number; y: number } clickCoords: { x: number; y: number }
) => { ) => {
const u = await getUtils(page) const u = await getUtils(page)
await page.setBodyDimensions({ width: 1200, height: 500 }) await page.setBodyDimensions({ width: 1700, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
const XYPlanRed: [number, number, number] = [98, 50, 51] const XYPlanRed: [number, number, number] = [98, 50, 51]

View File

@ -406,6 +406,7 @@ profile003 = startProfileAt([0, -4.93], sketch001)
await fsp.mkdir(testProject, { recursive: true }) await fsp.mkdir(testProject, { recursive: true })
await fsp.writeFile(join(testProject, 'main.kcl'), beforeKclCode, 'utf-8') await fsp.writeFile(join(testProject, 'main.kcl'), beforeKclCode, 'utf-8')
}) })
await page.setBodyDimensions({ width: 1500, height: 500 })
// One dumb hardcoded screen pixel value // One dumb hardcoded screen pixel value
const testPoint = { x: 650, y: 250 } const testPoint = { x: 650, y: 250 }
const sketchColor: [number, number, number] = [149, 149, 149] const sketchColor: [number, number, number] = [149, 149, 149]

View File

@ -488,6 +488,7 @@ test('Restarting onboarding on desktop takes one attempt', async ({
join(routerTemplateDir, 'main.kcl') join(routerTemplateDir, 'main.kcl')
) )
}) })
await page.setBodyDimensions({ width: 1500, height: 500 })
// Our constants // Our constants
const u = await getUtils(page) const u = await getUtils(page)

View File

@ -87,7 +87,7 @@ test.describe('Point-and-click assemblies tests', () => {
fsp.writeFile(path.join(bracketDir, 'main.kcl'), ''), fsp.writeFile(path.join(bracketDir, 'main.kcl'), ''),
]) ])
}) })
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.openProject(projectName) await homePage.openProject(projectName)
await scene.settled(cmdBar) await scene.settled(cmdBar)
await toolbar.closePane('code') await toolbar.closePane('code')
@ -225,7 +225,7 @@ test.describe('Point-and-click assemblies tests', () => {
fsp.writeFile(path.join(bracketDir, 'main.kcl'), ''), fsp.writeFile(path.join(bracketDir, 'main.kcl'), ''),
]) ])
}) })
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.openProject(projectName) await homePage.openProject(projectName)
await scene.settled(cmdBar) await scene.settled(cmdBar)
await toolbar.closePane('code') await toolbar.closePane('code')
@ -403,7 +403,7 @@ test.describe('Point-and-click assemblies tests', () => {
fsp.writeFile(path.join(bracketDir, 'main.kcl'), ''), fsp.writeFile(path.join(bracketDir, 'main.kcl'), ''),
]) ])
}) })
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.openProject(projectName) await homePage.openProject(projectName)
await scene.settled(cmdBar) await scene.settled(cmdBar)
await toolbar.closePane('code') await toolbar.closePane('code')

View File

@ -203,7 +203,7 @@ test.describe('Point-and-click tests', () => {
await context.addInitScript((file) => { await context.addInitScript((file) => {
localStorage.setItem('persistCode', file) localStorage.setItem('persistCode', file)
}, file) }, file)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.settled(cmdBar) await scene.settled(cmdBar)
@ -366,7 +366,7 @@ profile001 = startProfileAt([205.96, 254.59], sketch002)
await context.addInitScript((file) => { await context.addInitScript((file) => {
localStorage.setItem('persistCode', file) localStorage.setItem('persistCode', file)
}, file) }, file)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.settled(cmdBar) await scene.settled(cmdBar)
@ -689,7 +689,7 @@ openSketch = startSketchOn(XY)
await context.addInitScript((initialCode) => { await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode) localStorage.setItem('persistCode', initialCode)
}, initialCode) }, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
// Wait for the scene and stream to load // Wait for the scene and stream to load
@ -864,7 +864,7 @@ openSketch = startSketchOn(XY)
// Setup // Setup
await test.step(`Initial test setup`, async () => { await test.step(`Initial test setup`, async () => {
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
// Wait for the scene and stream to load // Wait for the scene and stream to load
@ -1215,7 +1215,7 @@ openSketch = startSketchOn(XY)
await context.addInitScript((initialCode) => { await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode) localStorage.setItem('persistCode', initialCode)
}, initialCode) }, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.settled(cmdBar) await scene.settled(cmdBar)
@ -1360,7 +1360,7 @@ extrude001 = extrude(profile001, length = 100)
await context.addInitScript((initialCode) => { await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode) localStorage.setItem('persistCode', initialCode)
}, initialCode) }, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.settled(cmdBar) await scene.settled(cmdBar)
@ -1496,7 +1496,7 @@ extrude001 = extrude(profile001, length = 100)
await context.addInitScript((initialCode) => { await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode) localStorage.setItem('persistCode', initialCode)
}, initialCode) }, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
// One dumb hardcoded screen pixel value // One dumb hardcoded screen pixel value
@ -1587,7 +1587,7 @@ loft001 = loft([sketch001, sketch002])
await context.addInitScript((initialCode) => { await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode) localStorage.setItem('persistCode', initialCode)
}, initialCode) }, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.settled(cmdBar) await scene.settled(cmdBar)
@ -1676,7 +1676,7 @@ sketch002 = startSketchOn(XZ)
await context.addInitScript((initialCode) => { await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode) localStorage.setItem('persistCode', initialCode)
}, initialCode) }, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.settled(cmdBar) await scene.settled(cmdBar)
@ -1818,7 +1818,7 @@ sketch002 = startSketchOn(XZ)
await context.addInitScript((initialCode) => { await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode) localStorage.setItem('persistCode', initialCode)
}, initialCode) }, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.settled(cmdBar) await scene.settled(cmdBar)
@ -1924,7 +1924,7 @@ extrude001 = extrude(sketch001, length = -12)
await context.addInitScript((initialCode) => { await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode) localStorage.setItem('persistCode', initialCode)
}, initialCode) }, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
// verify modeling scene is loaded // verify modeling scene is loaded
@ -2199,7 +2199,7 @@ fillet001 = fillet(extrude001, radius = 5, tags = [getOppositeEdge(seg01)])
await context.addInitScript((initialCode) => { await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode) localStorage.setItem('persistCode', initialCode)
}, initialCode) }, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.settled(cmdBar) await scene.settled(cmdBar)
@ -2263,7 +2263,7 @@ fillet04 = fillet(extrude001, radius = 5, tags = [getOppositeEdge(seg02)])
await context.addInitScript((initialCode) => { await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode) localStorage.setItem('persistCode', initialCode)
}, initialCode) }, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
// verify modeling scene is loaded // verify modeling scene is loaded
@ -2397,7 +2397,7 @@ extrude001 = extrude(profile001, length = 5)
await context.addInitScript((initialCode) => { await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode) localStorage.setItem('persistCode', initialCode)
}, initialCode) }, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
// verify modeling scene is loaded // verify modeling scene is loaded
@ -2520,7 +2520,7 @@ extrude001 = extrude(sketch001, length = -12)
await context.addInitScript((initialCode) => { await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode) localStorage.setItem('persistCode', initialCode)
}, initialCode) }, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.settled(cmdBar) await scene.settled(cmdBar)
}) })
@ -2821,7 +2821,7 @@ chamfer04 = chamfer(extrude001, length = 5, tags = [getOppositeEdge(seg02)])
await context.addInitScript((initialCode) => { await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode) localStorage.setItem('persistCode', initialCode)
}, initialCode) }, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.settled(cmdBar) await scene.settled(cmdBar)
@ -2946,7 +2946,7 @@ extrude001 = extrude(sketch001, length = 30)
localStorage.setItem('persistCode', initialCode) localStorage.setItem('persistCode', initialCode)
}, initialCode) }, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.connectionEstablished() await scene.connectionEstablished()
@ -3089,7 +3089,7 @@ extrude001 = extrude(sketch001, length = 40)
await context.addInitScript((initialCode) => { await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode) localStorage.setItem('persistCode', initialCode)
}, initialCode) }, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.settled(cmdBar) await scene.settled(cmdBar)
@ -3236,7 +3236,7 @@ extrude002 = extrude(sketch002, length = 50)
await context.addInitScript((initialCode) => { await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode) localStorage.setItem('persistCode', initialCode)
}, initialCode) }, initialCode)
await page.setBodyDimensions({ width: 1200, height: 500 }) await page.setBodyDimensions({ width: 1700, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.settled(cmdBar) await scene.settled(cmdBar)
@ -3325,7 +3325,7 @@ profile001 = startProfileAt([-20, 20], sketch001)
await context.addInitScript((initialCode) => { await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode) localStorage.setItem('persistCode', initialCode)
}, initialCode) }, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.settled(cmdBar) await scene.settled(cmdBar)
await toolbar.openPane('feature-tree') await toolbar.openPane('feature-tree')
@ -3405,7 +3405,7 @@ sweep001 = sweep(sketch001, path = sketch002)
await context.addInitScript((initialCode) => { await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode) localStorage.setItem('persistCode', initialCode)
}, initialCode) }, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.settled(cmdBar) await scene.settled(cmdBar)
@ -3487,7 +3487,7 @@ tag=$rectangleSegmentC002,
await context.addInitScript((initialCode) => { await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode) localStorage.setItem('persistCode', initialCode)
}, initialCode) }, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.settled(cmdBar) await scene.settled(cmdBar)
@ -3565,7 +3565,7 @@ sketch002 = startSketchOn(extrude001, face = rectangleSegmentA001)
await context.addInitScript((initialCode) => { await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode) localStorage.setItem('persistCode', initialCode)
}, initialCode) }, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.connectionEstablished() await scene.connectionEstablished()
await scene.settled(cmdBar) await scene.settled(cmdBar)
@ -3656,7 +3656,7 @@ sketch002 = startSketchOn(extrude001, face = rectangleSegmentA001)
await context.addInitScript((initialCode) => { await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode) localStorage.setItem('persistCode', initialCode)
}, initialCode) }, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.connectionEstablished() await scene.connectionEstablished()
await scene.settled(cmdBar) await scene.settled(cmdBar)
@ -3736,7 +3736,7 @@ extrude001 = extrude(profile001, length = 100)
await context.addInitScript((initialCode) => { await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode) localStorage.setItem('persistCode', initialCode)
}, initialCode) }, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.settled(cmdBar) await scene.settled(cmdBar)
@ -3867,7 +3867,7 @@ extrude001 = extrude(profile001, length = 100)
await context.addInitScript((initialCode) => { await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode) localStorage.setItem('persistCode', initialCode)
}, initialCode) }, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.settled(cmdBar) await scene.settled(cmdBar)
@ -4023,7 +4023,7 @@ extrude001 = extrude(profile001, length = 100)
await context.addInitScript((initialCode) => { await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode) localStorage.setItem('persistCode', initialCode)
}, initialCode) }, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.settled(cmdBar) await scene.settled(cmdBar)
@ -4152,7 +4152,7 @@ extrude001 = extrude(profile001, length = 1)
await context.addInitScript((initialCode) => { await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode) localStorage.setItem('persistCode', initialCode)
}, initialCode) }, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.settled(cmdBar) await scene.settled(cmdBar)

View File

@ -1815,8 +1815,8 @@ test(
'basic_fillet_cube_next_adjacent.kcl', 'basic_fillet_cube_next_adjacent.kcl',
'basic_fillet_cube_previous_adjacent.kcl', 'basic_fillet_cube_previous_adjacent.kcl',
'basic_fillet_cube_start.kcl', 'basic_fillet_cube_start.kcl',
'big_number_angle_to_match_length_x.kcl', 'broken-code-test.kcl',
'big_number_angle_to_match_length_y.kcl', 'circular_pattern3d_a_pattern.kcl',
'close_arc.kcl', 'close_arc.kcl',
'computed_var.kcl', 'computed_var.kcl',
'cube-embedded.gltf', 'cube-embedded.gltf',

View File

@ -53,6 +53,7 @@ test.describe('Prompt-to-edit tests', { tag: '@skipWin' }, () => {
await context.addInitScript((file) => { await context.addInitScript((file) => {
localStorage.setItem('persistCode', file) localStorage.setItem('persistCode', file)
}, file) }, file)
await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.settled(cmdBar) await scene.settled(cmdBar)
@ -148,6 +149,7 @@ test.describe('Prompt-to-edit tests', { tag: '@skipWin' }, () => {
await context.addInitScript((file) => { await context.addInitScript((file) => {
localStorage.setItem('persistCode', file) localStorage.setItem('persistCode', file)
}, file) }, file)
await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.settled(cmdBar) await scene.settled(cmdBar)
@ -203,6 +205,7 @@ test.describe('Prompt-to-edit tests', { tag: '@skipWin' }, () => {
await context.addInitScript((file) => { await context.addInitScript((file) => {
localStorage.setItem('persistCode', file) localStorage.setItem('persistCode', file)
}, file) }, file)
await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.settled(cmdBar) await scene.settled(cmdBar)
@ -272,6 +275,7 @@ test.describe('Prompt-to-edit tests', { tag: '@skipWin' }, () => {
await context.addInitScript((file) => { await context.addInitScript((file) => {
localStorage.setItem('persistCode', file) localStorage.setItem('persistCode', file)
}, file) }, file)
await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.settled(cmdBar) await scene.settled(cmdBar)

View File

@ -343,7 +343,7 @@ extrude002 = extrude(profile002, length = 150)
) )
const websocketPromise = page.waitForEvent('websocket') const websocketPromise = page.waitForEvent('websocket')
await page.setBodyDimensions({ width: 500, height: 500 }) await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
const websocket = await websocketPromise const websocket = await websocketPromise
@ -679,10 +679,12 @@ extrude002 = extrude(profile002, length = 150)
scene, scene,
toolbar, toolbar,
viewport, viewport,
page,
}) => { }) => {
await context.folderSetupFn(async (dir) => { await context.folderSetupFn(async (dir) => {
const legoDir = path.join(dir, 'lego') const legoDir = path.join(dir, 'lego')
await fsp.mkdir(legoDir, { recursive: true }) await fsp.mkdir(legoDir, { recursive: true })
await page.setBodyDimensions({ width: 1500, height: 500 })
await fsp.copyFile( await fsp.copyFile(
executorInputPath('e2e-can-sketch-on-chamfer.kcl'), executorInputPath('e2e-can-sketch-on-chamfer.kcl'),
path.join(legoDir, 'main.kcl') path.join(legoDir, 'main.kcl')

View File

@ -115,6 +115,7 @@ sketch001 = startSketchOn(XZ)
) )
}) })
await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.settled(cmdBar) await scene.settled(cmdBar)
@ -1541,6 +1542,7 @@ profile003 = startProfileAt([206.63, -56.73], sketch001)
) )
}) })
await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.settled(cmdBar) await scene.settled(cmdBar)
@ -2230,7 +2232,7 @@ profile003 = circle(sketch001, center = [6.92, -4.2], radius = 3.16)
) )
}) })
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.settled(cmdBar) await scene.settled(cmdBar)
await expect( await expect(
@ -2339,7 +2341,7 @@ extrude001 = extrude(profile003, length = 5)
) )
}) })
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.connectionEstablished() await scene.connectionEstablished()
await scene.settled(cmdBar) await scene.settled(cmdBar)
@ -2437,7 +2439,7 @@ profile002 = startProfileAt([85.81, 52.55], sketch002)
) )
}) })
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await expect( await expect(
page.getByRole('button', { name: 'Start Sketch' }) page.getByRole('button', { name: 'Start Sketch' })
@ -2595,7 +2597,7 @@ extrude003 = extrude(profile011, length = 2.5)
) )
}) })
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.connectionEstablished() await scene.connectionEstablished()
await scene.settled(cmdBar) await scene.settled(cmdBar)
@ -2710,7 +2712,7 @@ loft([profile001, profile002])
) )
}) })
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await expect( await expect(
page.getByRole('button', { name: 'Start Sketch' }) page.getByRole('button', { name: 'Start Sketch' })
@ -2768,7 +2770,7 @@ loft([profile001, profile002])
) )
}) })
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await expect( await expect(
page.getByRole('button', { name: 'Start Sketch' }) page.getByRole('button', { name: 'Start Sketch' })
@ -3260,6 +3262,7 @@ profile003 = startProfileAt([-201.08, 254.17], sketch002)
await context.addInitScript((file) => { await context.addInitScript((file) => {
localStorage.setItem('persistCode', file) localStorage.setItem('persistCode', file)
}, file) }, file)
await page.setBodyDimensions({ width: 1500, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
const [objClick] = scene.makeMouseHelpers(600, 250) const [objClick] = scene.makeMouseHelpers(600, 250)

View File

@ -39,12 +39,12 @@ test.describe('Testing selections', { tag: ['@skipWin'] }, () => {
}) })
const emptySpaceHover = () => const emptySpaceHover = () =>
test.step('Hover over empty space', async () => { test.step('Hover over empty space', async () => {
await page.mouse.move(700, 143, { steps: 5 }) await page.mouse.move(1000, 143, { steps: 5 })
await expect(page.locator('.hover-highlight')).not.toBeVisible() await expect(page.locator('.hover-highlight')).not.toBeVisible()
}) })
const emptySpaceClick = () => const emptySpaceClick = () =>
test.step(`Click in empty space`, async () => { test.step(`Click in empty space`, async () => {
await page.mouse.click(700, 143) await page.mouse.click(1000, 143)
await expect(page.locator('.cm-line').last()).toHaveClass( await expect(page.locator('.cm-line').last()).toHaveClass(
/cm-activeLine/ /cm-activeLine/
) )

View File

@ -30,21 +30,68 @@ declare module '@playwright/test' {
// *for one worker*. // *for one worker*.
const electronZooInstance = new ElectronZoo() const electronZooInstance = new ElectronZoo()
// Track whether this is the first run for this worker process
// Mac needs more time for the first window creation
let isFirstRun = true
// Our custom decorated Zoo test object. Makes it easier to add fixtures, and // Our custom decorated Zoo test object. Makes it easier to add fixtures, and
// switch between web and electron if needed. // switch between web and electron if needed.
const playwrightTestFnWithFixtures_ = playwrightTestFn.extend<{ const playwrightTestFnWithFixtures_ = playwrightTestFn.extend<{
tronApp?: ElectronZoo tronApp?: ElectronZoo
}>({ }>({
tronApp: async ({}, use, testInfo) => { tronApp: [
if (process.env.PLATFORM === 'web') { async ({}, use, testInfo) => {
await use(undefined) if (process.env.PLATFORM === 'web') {
return await use(undefined)
} return
}
await electronZooInstance.createInstanceIfMissing(testInfo) // Create a single timeout for the entire tronApp setup process
await use(electronZooInstance) // This will ensure tests fail faster if there's an issue with setup
await electronZooInstance.makeAvailableAgain() // instead of waiting for the full global timeout (120s)
}, // First runs need more time especially on Mac for window creation
const setupTimeout = isFirstRun ? 120_000 : 30_000
let timeoutId: NodeJS.Timeout | undefined
const setupPromise = new Promise<void>((resolve, reject) => {
timeoutId = setTimeout(() => {
reject(
new Error(
`tronApp setup timed out after ${setupTimeout}ms${isFirstRun ? ' (first run)' : ' (subsequent run)'}`
)
)
}, setupTimeout)
// Execute the async setup in a separate function
const doSetup = async () => {
try {
await electronZooInstance.createInstanceIfMissing(testInfo)
resolve()
} catch (error) {
reject(error)
}
}
// Start the setup process
void doSetup()
})
try {
await setupPromise
if (timeoutId) clearTimeout(timeoutId)
// First run is complete at this point
isFirstRun = false
await use(electronZooInstance)
await electronZooInstance.makeAvailableAgain()
} catch (error) {
if (timeoutId) clearTimeout(timeoutId)
throw error
}
},
{ timeout: 120_000 }, // Keep the global timeout as fallback
],
}) })
const test = playwrightTestFnWithFixtures_.extend<Fixtures>( const test = playwrightTestFnWithFixtures_.extend<Fixtures>(

View File

@ -3,14 +3,13 @@
> dpdm --no-warning --no-tree -T --skip-dynamic-imports=circular src/index.tsx > dpdm --no-warning --no-tree -T --skip-dynamic-imports=circular src/index.tsx
• Circular Dependencies • Circular Dependencies
01) src/lang/std/sketch.ts -> src/lang/modifyAst.ts -> src/lang/modifyAst/addEdgeTreatment.ts 1) src/lang/std/sketch.ts -> src/lang/modifyAst.ts -> src/lang/modifyAst/addEdgeTreatment.ts
02) src/lang/std/sketch.ts -> src/lang/modifyAst.ts 2) src/lang/std/sketch.ts -> src/lang/modifyAst.ts
03) src/lang/std/sketch.ts -> src/lang/modifyAst.ts -> src/lang/std/sketchcombos.ts 3) src/lang/std/sketch.ts -> src/lang/modifyAst.ts -> src/lang/std/sketchcombos.ts
04) src/lib/singletons.ts -> src/editor/manager.ts -> src/lib/selections.ts 4) src/lib/singletons.ts -> src/editor/manager.ts -> src/lib/selections.ts
05) src/lib/singletons.ts -> src/editor/manager.ts -> src/lib/selections.ts -> src/machines/appMachine.ts -> src/machines/engineStreamMachine.ts 5) src/lib/singletons.ts -> src/editor/manager.ts -> src/lib/selections.ts
06) src/lib/singletons.ts -> src/editor/manager.ts -> src/lib/selections.ts -> src/machines/appMachine.ts -> src/machines/settingsMachine.ts 6) src/lib/singletons.ts -> src/lang/codeManager.ts
07) src/machines/appMachine.ts -> src/machines/settingsMachine.ts -> src/machines/commandBarMachine.ts -> src/lib/commandBarConfigs/authCommandConfig.ts 7) src/lib/singletons.ts -> src/clientSideScene/sceneEntities.ts -> src/clientSideScene/segments.ts -> src/components/Toolbar/angleLengthInfo.ts
08) src/lib/singletons.ts -> src/lang/codeManager.ts 8) src/lib/singletons.ts -> src/clientSideScene/sceneEntities.ts -> src/clientSideScene/segments.ts
09) src/lib/singletons.ts -> src/clientSideScene/sceneEntities.ts -> src/clientSideScene/segments.ts -> src/components/Toolbar/angleLengthInfo.ts 9) src/hooks/useModelingContext.ts -> src/components/ModelingMachineProvider.tsx -> src/components/Toolbar/Intersect.tsx -> src/components/SetHorVertDistanceModal.tsx -> src/lib/useCalculateKclExpression.ts
10) src/hooks/useModelingContext.ts -> src/components/ModelingMachineProvider.tsx -> src/components/Toolbar/Intersect.tsx -> src/components/SetHorVertDistanceModal.tsx -> src/lib/useCalculateKclExpression.ts 10) src/routes/Onboarding/index.tsx -> src/routes/Onboarding/Camera.tsx -> src/routes/Onboarding/utils.tsx
11) src/routes/Onboarding/index.tsx -> src/routes/Onboarding/Camera.tsx -> src/routes/Onboarding/utils.tsx

View File

@ -114,6 +114,7 @@
"circular-deps": "dpdm --no-warning --no-tree -T --skip-dynamic-imports=circular src/index.tsx", "circular-deps": "dpdm --no-warning --no-tree -T --skip-dynamic-imports=circular src/index.tsx",
"circular-deps:overwrite": "npm run circular-deps | sed '$d' | grep -v '^npm run' > known-circular.txt", "circular-deps:overwrite": "npm run circular-deps | sed '$d' | grep -v '^npm run' > known-circular.txt",
"circular-deps:diff": "./scripts/diff-circular-deps.sh", "circular-deps:diff": "./scripts/diff-circular-deps.sh",
"circular-deps:diff:nodejs": "npm run circular-deps:diff || node ./scripts/diff.js",
"files:set-version": "echo \"$(jq --arg v \"$VERSION\" '.version=$v' package.json --indent 2)\" > package.json", "files:set-version": "echo \"$(jq --arg v \"$VERSION\" '.version=$v' package.json --indent 2)\" > package.json",
"files:set-notes": "./scripts/set-files-notes.sh", "files:set-notes": "./scripts/set-files-notes.sh",
"files:flip-to-nightly": "./scripts/flip-files-to-nightly.sh", "files:flip-to-nightly": "./scripts/flip-files-to-nightly.sh",

View File

@ -126,7 +126,7 @@ fn armRestProfile(plane, offset) {
export fn armRest(plane, offset) { export fn armRest(plane, offset) {
path = armRestPath( offsetPlane(plane, offset = offset)) path = armRestPath( offsetPlane(plane, offset = offset))
profile = armRestProfile( offsetPlane(-XZ, offset = 20), offset) profile = armRestProfile( offsetPlane(-XZ, offset = 20), -offset)
sweep(profile, path = path) sweep(profile, path = path)
return 0 return 0
} }

View File

@ -17,8 +17,8 @@ import armRest from "bench-parts.kcl"
// Create the dividers, these hold the seat and back slats // Create the dividers, these hold the seat and back slats
divider(YZ) divider(YZ)
divider(offsetPlane(-YZ, offset = benchLength / 2))
divider(offsetPlane(YZ, offset = benchLength / 2)) divider(offsetPlane(YZ, offset = benchLength / 2))
divider(offsetPlane(YZ, offset = -benchLength / 2))
// Create the connectors to join the dividers // Create the connectors to join the dividers
connector(offsetPlane(YZ, offset = -benchLength / 2), benchLength) connector(offsetPlane(YZ, offset = -benchLength / 2), benchLength)
@ -30,5 +30,5 @@ seatSlats(offsetPlane(YZ, offset = -benchLength / 2 - (dividerThickness / 2)), b
backSlats(offsetPlane(YZ, offset = -benchLength / 2 - (dividerThickness / 2)), benchLength + dividerThickness) backSlats(offsetPlane(YZ, offset = -benchLength / 2 - (dividerThickness / 2)), benchLength + dividerThickness)
// Create the arm rests // Create the arm rests
armRest(-YZ, benchLength / 2) armRest(YZ, benchLength / 2)
armRest(-YZ, -benchLength / 2) armRest(YZ, -benchLength / 2)

View File

@ -1,88 +1,79 @@
// Hollow Dodecahedron // Dodecahedron
// A regular dodecahedron or pentagonal dodecahedron is a dodecahedron composed of regular pentagonal faces, three meeting at each vertex. This example shows constructing the individual faces of the dodecahedron and extruding inwards. // A regular dodecahedron or pentagonal dodecahedron is a dodecahedron composed of regular pentagonal faces, three meeting at each vertex. This example shows constructing the a dodecahedron with a series of intersects.
// Set units // Set units
@settings(defaultLengthUnit = in) @settings(defaultLengthUnit = in)
// Input parameters // Define the dihedral angle for a regular dodecahedron
// circumscribed radius dihedral = 116.565
circR = 25
// Calculated parameters // Create a face template function that makes a large thin cube
// Thickness of the dodecahedron fn createFaceTemplate(dither) {
wallThickness = circR * 0.2 baseSketch = startSketchOn(XY)
|> startProfileAt([-1000 - dither, -1000 - dither], %)
// Angle between faces in radians |> line(endAbsolute = [1000 + dither, -1000 - dither])
dihedral = acos(-(sqrt(5) / 5)) |> line(endAbsolute = [1000 + dither, 1000 + dither])
|> line(endAbsolute = [-1000 - dither, 1000 + dither])
// Inscribed radius |> close()
inscR = circR / 15 * sqrt(75 + 30 * sqrt(5)) extruded = extrude(baseSketch, length = 1000 + dither + 1000)
return extruded
// Pentagon edge length |> translate(x = 0, y = 0, z = -260 - dither)
edgeL = 4 * circR / (sqrt(3) * (1 + sqrt(5)))
// Pentagon radius
pentR = edgeL / 2 / sin(toRadians(36))
// Define a plane for the bottom angled face
plane = {
origin = [
-inscR * cos(toRadians(toDegrees(dihedral) - 90)),
0,
inscR - (inscR * sin(toRadians(toDegrees(dihedral) - 90)))
],
xAxis = [cos(dihedral), 0.0, sin(dihedral)],
yAxis = [0, 1, 0],
zAxis = [sin(dihedral), 0, -cos(dihedral)]
} }
// Create a regular pentagon inscribed in a circle of radius pentR // Define the rotations array with [pitch, roll, yaw, dither] for each face
bottomFace = startSketchOn(XY) faceRotations = [
|> polygon( [0, 0, 0, 0],
radius = pentR, // face1 - reference face
numSides = 5, [dihedral, 0, 0, 0.1],
center = [0, 0], // face2
inscribed = true, [dihedral, 0, 72, 0.2],
) // face3
[dihedral, 0, 144, 0.3],
// face4
[dihedral, 0, 216, 0.4],
// face5
[dihedral, 0, 288, 0.5],
// face6
[180, 0, 0, 0.6],
// face7
[180 - dihedral, 0, 36, 0.7],
// face8
[180 - dihedral, 0, 108, 0.8],
// face9
[180 - dihedral, 0, 180, 0.9],
// face10
[180 - dihedral, 0, 252, 0.11],
// face11
[180 - dihedral, 0, 324, 0.12],
// face12
]
bottomSideFace = startSketchOn(plane) // Create faces by mapping over the rotations array
|> polygon( dodecFaces = map(faceRotations, fn(rotation) {
radius = pentR, return createFaceTemplate(rotation[3])
numSides = 5, |> rotate(
center = [0, 0], pitch = rotation[0],
inscribed = true, roll = rotation[1],
) yaw = rotation[2],
global = true,
)
})
// Extrude the faces in each plane fn calculateArrayLength(arr) {
bottom = extrude(bottomFace, length = wallThickness) return reduce(arr, 0, fn(item, accumulator) {
bottomSide = extrude(bottomSideFace, length = wallThickness) return accumulator + 1
})
}
// Pattern the sides so we have a full dodecahedron fn createIntersection(solids) {
bottomBowl = patternCircular3d( fn reduceIntersect(previous, current) {
bottomSide, return intersect([previous, current])
instances = 5, }
axis = [0, 0, 1], lastIndex = calculateArrayLength(solids) - 1
center = [0, 0, 0], lastSolid = solids[lastIndex]
arcDegrees = 360, remainingSolids = pop(solids)
rotateDuplicates = true, return reduce(remainingSolids, lastSolid, reduceIntersect)
) }
// Pattern the bottom to create the top face // Apply intersection to all faces
patternCircular3d( createIntersection(dodecFaces)
bottom,
instances = 2,
axis = [0, 1, 0],
center = [0, 0, inscR],
arcDegrees = 360,
rotateDuplicates = true,
)
// Pattern the bottom angled faces to create the top
patternCircular3d(
bottomBowl,
instances = 2,
axis = [0, 1, 0],
center = [0, 0, inscR],
arcDegrees = 360,
rotateDuplicates = true,
)

View File

@ -202,19 +202,17 @@ plane000 = {
height + binHeight * countBinHeight height + binHeight * countBinHeight
], ],
xAxis = [0.0, 1.0, 0.0], xAxis = [0.0, 1.0, 0.0],
yAxis = [0.0, 0.0, 1.0], yAxis = [0.0, 0.0, 1.0]
zAxis = [1.0, 0.0, 0.0]
} }
plane001 = { plane001 = {
origin = [ origin = [
0.0, 0.0,
cornerRadius, countBinLength * (binLength + 2 * binTol) - cornerRadius,
height + binHeight * countBinHeight height + binHeight * countBinHeight
], ],
xAxis = [1.0, 0.0, 0.0], xAxis = [1.0, 0.0, 0.0],
yAxis = [0.0, 0.0, 1.0], yAxis = [0.0, 0.0, 1.0]
zAxis = [0.0, 1.0, 0.0]
} }
plane002 = { plane002 = {
@ -224,8 +222,7 @@ plane002 = {
height + binHeight * countBinHeight height + binHeight * countBinHeight
], ],
xAxis = [0.0, 1.0, 0.0], xAxis = [0.0, 1.0, 0.0],
yAxis = [0.0, 0.0, 1.0], yAxis = [0.0, 0.0, 1.0]
zAxis = [1.0, 0.0, 0.0]
} }
// Extrude a single side of the lip of the bin // Extrude a single side of the lip of the bin

View File

@ -66,8 +66,8 @@
"file": "main.kcl", "file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "dodecahedron/main.kcl", "pathFromProjectDirectoryToFirstFile": "dodecahedron/main.kcl",
"multipleFiles": false, "multipleFiles": false,
"title": "Hollow Dodecahedron", "title": "Dodecahedron",
"description": "A regular dodecahedron or pentagonal dodecahedron is a dodecahedron composed of regular pentagonal faces, three meeting at each vertex. This example shows constructing the individual faces of the dodecahedron and extruding inwards." "description": "A regular dodecahedron or pentagonal dodecahedron is a dodecahedron composed of regular pentagonal faces, three meeting at each vertex. This example shows constructing the a dodecahedron with a series of intersects."
}, },
{ {
"file": "main.kcl", "file": "main.kcl",

View File

@ -4,10 +4,10 @@
@settings(defaultLengthUnit = in) @settings(defaultLengthUnit = in)
// Axis Angles // Axis Angles
export axisJ4 = 25 export axisJ4 = 25deg
export axisJ3 = 60 export axisJ3 = 60deg
export axisJ2 = 110 export axisJ2 = 110deg
export axisJ1 = 80 export axisJ1 = 80deg
// Robot Arm Base // Robot Arm Base
export basePlateRadius = 5 export basePlateRadius = 5
@ -30,29 +30,26 @@ export axisJ3CArmThickness = 2.5
export plane001 = { export plane001 = {
origin = [0.0, 0.0, baseHeight - 1.5 + 0.1], origin = [0.0, 0.0, baseHeight - 1.5 + 0.1],
xAxis = [1.0, 0.0, 0.0], xAxis = [1.0, 0.0, 0.0],
yAxis = [0.0, 1.0, 0.0], yAxis = [0.0, 1.0, 0.0]
zAxis = [0.0, 0.0, 1.0]
} }
export plane002 = { export plane002 = {
origin = [0.0, 0.0, 0.0], origin = [0.0, 0.0, 0.0],
xAxis = [ xAxis = [
sin(toRadians(axisJ1)), sin(axisJ1): number(in),
cos(toRadians(axisJ1)), cos(axisJ1): number(in),
0.0 0.0
], ],
yAxis = [0.0, 0.0, 1.0], yAxis = [0.0, 0.0, 1.0]
zAxis = [1.0, 0.0, 0.0]
} }
// Define Plane to Move J2 Axis Robot Arm // Define Plane to Move J2 Axis Robot Arm
export plane003 = { export plane003 = {
origin = [-0.1, 0.0, 0.0], origin = [-0.1, 0.0, 0.0],
xAxis = [ xAxis = [
sin(toRadians(axisJ1)), sin(axisJ1): number(in),
cos(toRadians(axisJ1)), cos(axisJ1): number(in),
0.0 0.0
], ],
yAxis = [0.0, 0.0, 1.0], yAxis = [0.0, 0.0, 1.0]
zAxis = [1.0, 0.0, 0.0]
} }

View File

@ -62,8 +62,7 @@ customPlane = {
z = 0 z = 0
}, },
xAxis = { x = 1, y = 0, z = 0 }, xAxis = { x = 1, y = 0, z = 0 },
yAxis = { x = 0, y = 0, z = 1 }, yAxis = { x = 0, y = 0, z = 1 }
zAxis = { x = 0, y = -1, z = 0 }
} }
sketch003 = startSketchOn(customPlane) sketch003 = startSketchOn(customPlane)
|> startProfileAt([0, 0], %) |> startProfileAt([0, 0], %)
@ -98,19 +97,18 @@ customPlane2 = {
y = 0, y = 0,
z = 0 z = 0
}, },
xAxis = { x = 0, y = -1, z = 0 }, xAxis = { x = 0, y = 1, z = 0 },
yAxis = { x = 0, y = 0, z = 1 }, yAxis = { x = 0, y = 0, z = 1 }
zAxis = { x = 1, y = 0, z = 0 }
} }
sketch005 = startSketchOn(customPlane2) sketch005 = startSketchOn(customPlane2)
|> startProfileAt([0, 0], %) |> startProfileAt([0, 0], %)
|> yLine(endAbsolute = height) |> yLine(endAbsolute = height)
|> xLine(endAbsolute = wallsWidth) |> xLine(endAbsolute = -wallsWidth)
|> tangentialArc(endAbsolute = [ |> tangentialArc(endAbsolute = [
(frontLength - wallsWidth) / 2 + wallsWidth, -1 * ((frontLength - wallsWidth) / 2 + wallsWidth),
height - ((height - exitHeight) / 2) height - ((height - exitHeight) / 2)
]) ])
|> tangentialArc(endAbsolute = [frontLength, exitHeight]) |> tangentialArc(endAbsolute = [-frontLength, exitHeight])
|> yLine(endAbsolute = 0, tag = $seg03) |> yLine(endAbsolute = 0, tag = $seg03)
|> close() |> close()
|> extrude(length = wallThickness) |> extrude(length = wallThickness)
@ -138,8 +136,7 @@ customPlane3 = {
z = wallThickness z = wallThickness
}, },
xAxis = { x = 0, y = -1, z = 0 }, xAxis = { x = 0, y = -1, z = 0 },
yAxis = { x = 1, y = 0, z = 0 }, yAxis = { x = 1, y = 0, z = 0 }
zAxis = { x = 0, y = 0, z = 1 }
} }
sketch008 = startSketchOn(customPlane3) sketch008 = startSketchOn(customPlane3)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 78 KiB

View File

@ -6,7 +6,7 @@ uses-engine = { max-threads = 4 }
after-engine = { max-threads = 12 } after-engine = { max-threads = 12 }
[profile.default] [profile.default]
slow-timeout = { period = "90s", terminate-after = 1 } slow-timeout = { period = "180s", terminate-after = 1 }
[profile.ci] [profile.ci]
slow-timeout = { period = "50s", terminate-after = 5 } slow-timeout = { period = "50s", terminate-after = 5 }

View File

@ -6,11 +6,12 @@
mod tests; mod tests;
mod unbox; mod unbox;
use std::collections::HashMap; use std::{collections::HashMap, fs};
use convert_case::Casing; use convert_case::Casing;
use inflector::{cases::camelcase::to_camel_case, Inflector}; use inflector::{cases::camelcase::to_camel_case, Inflector};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use proc_macro2::Span;
use quote::{format_ident, quote, quote_spanned, ToTokens}; use quote::{format_ident, quote, quote_spanned, ToTokens};
use regex::Regex; use regex::Regex;
use serde::Deserialize; use serde::Deserialize;
@ -21,6 +22,16 @@ use syn::{
}; };
use unbox::unbox; use unbox::unbox;
#[proc_macro_attribute]
pub fn stdlib(attr: proc_macro::TokenStream, item: proc_macro::TokenStream) -> proc_macro::TokenStream {
do_output(do_stdlib(attr.into(), item.into()))
}
#[proc_macro_attribute]
pub fn for_each_std_mod(_attr: proc_macro::TokenStream, item: proc_macro::TokenStream) -> proc_macro::TokenStream {
do_for_each_std_mod(item.into()).into()
}
/// Describes an argument of a stdlib function. /// Describes an argument of a stdlib function.
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
struct ArgMetadata { struct ArgMetadata {
@ -73,11 +84,6 @@ struct StdlibMetadata {
args: HashMap<String, ArgMetadata>, args: HashMap<String, ArgMetadata>,
} }
#[proc_macro_attribute]
pub fn stdlib(attr: proc_macro::TokenStream, item: proc_macro::TokenStream) -> proc_macro::TokenStream {
do_output(do_stdlib(attr.into(), item.into()))
}
fn do_stdlib( fn do_stdlib(
attr: proc_macro2::TokenStream, attr: proc_macro2::TokenStream,
item: proc_macro2::TokenStream, item: proc_macro2::TokenStream,
@ -86,6 +92,31 @@ fn do_stdlib(
do_stdlib_inner(metadata, attr, item) do_stdlib_inner(metadata, attr, item)
} }
fn do_for_each_std_mod(item: proc_macro2::TokenStream) -> proc_macro2::TokenStream {
let item: syn::ItemFn = syn::parse2(item.clone()).unwrap();
let mut result = proc_macro2::TokenStream::new();
for name in fs::read_dir("kcl-lib/std").unwrap().filter_map(|e| {
let e = e.unwrap();
let filename = e.file_name();
filename.to_str().unwrap().strip_suffix(".kcl").map(str::to_owned)
}) {
let mut item = item.clone();
item.sig.ident = syn::Ident::new(&format!("{}_{}", item.sig.ident, name), Span::call_site());
let stmts = &item.block.stmts;
//let name = format!("\"{name}\"");
let block = quote! {
{
const STD_MOD_NAME: &str = #name;
#(#stmts)*
}
};
item.block = Box::new(syn::parse2(block).unwrap());
result.extend(Some(item.into_token_stream()));
}
result
}
fn do_output(res: Result<(proc_macro2::TokenStream, Vec<Error>), Error>) -> proc_macro::TokenStream { fn do_output(res: Result<(proc_macro2::TokenStream, Vec<Error>), Error>) -> proc_macro::TokenStream {
match res { match res {
Err(err) => err.to_compile_error().into(), Err(err) => err.to_compile_error().into(),
@ -671,6 +702,7 @@ fn normalize_comment_string(s: String) -> Vec<String> {
/// Represent an item without concern for its body which may (or may not) /// Represent an item without concern for its body which may (or may not)
/// contain syntax errors. /// contain syntax errors.
#[derive(Clone)]
struct ItemFnForSignature { struct ItemFnForSignature {
pub attrs: Vec<Attribute>, pub attrs: Vec<Attribute>,
pub vis: Visibility, pub vis: Visibility,

View File

@ -1,9 +0,0 @@
const part001 = startSketchOn(XY)
|> startProfileAt([0, 0], %)
|> line(end = [1, 3.82], tag = $seg01)
|> angled(
angle = -angleToMatchLengthX(seg01, 3, %),
endAbsoluteX = 3,
)
|> close()
|> extrude(length = 10)

View File

@ -1,9 +0,0 @@
const part001 = startSketchOn(XY)
|> startProfileAt([0, 0], %)
|> line(end = [1, 3.82], tag = $seg01)
|> angledLine(
angle = -angleToMatchLengthY(seg01, 3, %),
endAbsoluteX = 3,
)
|> close()
|> extrude(length = 10)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 68 KiB

View File

@ -61,8 +61,10 @@ impl CollectionVisitor {
format!("std::{}::", self.name) format!("std::{}::", self.name)
}; };
let mut dd = match var.kind { let mut dd = match var.kind {
VariableKind::Fn => DocData::Fn(FnData::from_ast(var, qual_name, preferred_prefix)), VariableKind::Fn => DocData::Fn(FnData::from_ast(var, qual_name, preferred_prefix, name)),
VariableKind::Const => DocData::Const(ConstData::from_ast(var, qual_name, preferred_prefix)), VariableKind::Const => {
DocData::Const(ConstData::from_ast(var, qual_name, preferred_prefix, name))
}
}; };
dd.with_meta(&var.outer_attrs); dd.with_meta(&var.outer_attrs);
@ -79,7 +81,7 @@ impl CollectionVisitor {
} else { } else {
format!("std::{}::", self.name) format!("std::{}::", self.name)
}; };
let mut dd = DocData::Ty(TyData::from_ast(ty, qual_name, preferred_prefix)); let mut dd = DocData::Ty(TyData::from_ast(ty, qual_name, preferred_prefix, name));
dd.with_meta(&ty.outer_attrs); dd.with_meta(&ty.outer_attrs);
for a in &ty.outer_attrs { for a in &ty.outer_attrs {
@ -114,6 +116,16 @@ impl DocData {
} }
} }
/// The name of the module in which the item is declared, e.g., `sketch`
#[allow(dead_code)]
pub fn module_name(&self) -> &str {
match self {
DocData::Fn(f) => &f.module_name,
DocData::Const(c) => &c.module_name,
DocData::Ty(t) => &t.module_name,
}
}
#[allow(dead_code)] #[allow(dead_code)]
pub fn file_name(&self) -> String { pub fn file_name(&self) -> String {
match self { match self {
@ -132,6 +144,7 @@ impl DocData {
} }
} }
/// The path to the module through which the item is accessed, e.g., `std::sketch`
#[allow(dead_code)] #[allow(dead_code)]
pub fn mod_name(&self) -> String { pub fn mod_name(&self) -> String {
let q = match self { let q = match self {
@ -217,6 +230,8 @@ pub struct ConstData {
/// Code examples. /// Code examples.
/// These are tested and we know they compile and execute. /// These are tested and we know they compile and execute.
pub examples: Vec<(String, ExampleProperties)>, pub examples: Vec<(String, ExampleProperties)>,
pub module_name: String,
} }
impl ConstData { impl ConstData {
@ -224,6 +239,7 @@ impl ConstData {
var: &crate::parsing::ast::types::VariableDeclaration, var: &crate::parsing::ast::types::VariableDeclaration,
mut qual_name: String, mut qual_name: String,
preferred_prefix: &str, preferred_prefix: &str,
module_name: &str,
) -> Self { ) -> Self {
assert_eq!(var.kind, crate::parsing::ast::types::VariableKind::Const); assert_eq!(var.kind, crate::parsing::ast::types::VariableKind::Const);
@ -263,6 +279,7 @@ impl ConstData {
summary: None, summary: None,
description: None, description: None,
examples: Vec::new(), examples: Vec::new(),
module_name: module_name.to_owned(),
} }
} }
@ -334,6 +351,8 @@ pub struct FnData {
pub examples: Vec<(String, ExampleProperties)>, pub examples: Vec<(String, ExampleProperties)>,
#[allow(dead_code)] #[allow(dead_code)]
pub referenced_types: Vec<String>, pub referenced_types: Vec<String>,
pub module_name: String,
} }
impl FnData { impl FnData {
@ -341,6 +360,7 @@ impl FnData {
var: &crate::parsing::ast::types::VariableDeclaration, var: &crate::parsing::ast::types::VariableDeclaration,
mut qual_name: String, mut qual_name: String,
preferred_prefix: &str, preferred_prefix: &str,
module_name: &str,
) -> Self { ) -> Self {
assert_eq!(var.kind, crate::parsing::ast::types::VariableKind::Fn); assert_eq!(var.kind, crate::parsing::ast::types::VariableKind::Fn);
let crate::parsing::ast::types::Expr::FunctionExpression(expr) = &var.declaration.init else { let crate::parsing::ast::types::Expr::FunctionExpression(expr) = &var.declaration.init else {
@ -375,6 +395,7 @@ impl FnData {
description: None, description: None,
examples: Vec::new(), examples: Vec::new(),
referenced_types: referenced_types.into_iter().collect(), referenced_types: referenced_types.into_iter().collect(),
module_name: module_name.to_owned(),
} }
} }
@ -654,6 +675,8 @@ pub struct TyData {
pub examples: Vec<(String, ExampleProperties)>, pub examples: Vec<(String, ExampleProperties)>,
#[allow(dead_code)] #[allow(dead_code)]
pub referenced_types: Vec<String>, pub referenced_types: Vec<String>,
pub module_name: String,
} }
impl TyData { impl TyData {
@ -661,6 +684,7 @@ impl TyData {
ty: &crate::parsing::ast::types::TypeDeclaration, ty: &crate::parsing::ast::types::TypeDeclaration,
mut qual_name: String, mut qual_name: String,
preferred_prefix: &str, preferred_prefix: &str,
module_name: &str,
) -> Self { ) -> Self {
let name = ty.name.name.clone(); let name = ty.name.name.clone();
qual_name.push_str(&name); qual_name.push_str(&name);
@ -684,6 +708,7 @@ impl TyData {
description: None, description: None,
examples: Vec::new(), examples: Vec::new(),
referenced_types: referenced_types.into_iter().collect(), referenced_types: referenced_types.into_iter().collect(),
module_name: module_name.to_owned(),
} }
} }
@ -1009,6 +1034,8 @@ fn collect_type_names_from_primitive(ty: &PrimitiveType) -> String {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use kcl_derive_docs::for_each_std_mod;
use super::*; use super::*;
#[test] #[test]
@ -1047,18 +1074,28 @@ mod test {
); );
} }
#[tokio::test(flavor = "multi_thread", worker_threads = 5)] #[for_each_std_mod]
async fn test_examples() -> miette::Result<()> { #[tokio::test(flavor = "multi_thread")]
async fn test_examples() {
let std = walk_prelude(); let std = walk_prelude();
let mut errs = Vec::new();
for d in std { for d in std {
if d.module_name() != STD_MOD_NAME {
continue;
}
for (i, eg) in d.examples().enumerate() { for (i, eg) in d.examples().enumerate() {
let result = match crate::test_server::execute_and_snapshot(eg, None).await { let result = match crate::test_server::execute_and_snapshot(eg, None).await {
Err(crate::errors::ExecError::Kcl(e)) => { Err(crate::errors::ExecError::Kcl(e)) => {
return Err(miette::Report::new(crate::errors::Report { errs.push(
error: e.error, miette::Report::new(crate::errors::Report {
filename: format!("{}{i}", d.name()), error: e.error,
kcl_source: eg.to_string(), filename: format!("{}{i}", d.name()),
})); kcl_source: eg.to_string(),
})
.to_string(),
);
continue;
} }
Err(other_err) => panic!("{}", other_err), Err(other_err) => panic!("{}", other_err),
Ok(img) => img, Ok(img) => img,
@ -1071,6 +1108,8 @@ mod test {
} }
} }
Ok(()) if !errs.is_empty() {
panic!("{}", errs.join("\n\n"));
}
} }
} }

View File

@ -129,6 +129,8 @@ impl StdLibFnArg {
}; };
if (self.type_ == "Sketch" if (self.type_ == "Sketch"
|| self.type_ == "[Sketch]" || self.type_ == "[Sketch]"
|| self.type_ == "Geometry"
|| self.type_ == "GeometryWithImportedGeometry"
|| self.type_ == "Solid" || self.type_ == "Solid"
|| self.type_ == "[Solid]" || self.type_ == "[Solid]"
|| self.type_ == "SketchSurface" || self.type_ == "SketchSurface"
@ -502,6 +504,8 @@ pub trait StdLibFn: std::fmt::Debug + Send + Sync {
fn to_autocomplete_snippet(&self) -> Result<String> { fn to_autocomplete_snippet(&self) -> Result<String> {
if self.name() == "loft" { if self.name() == "loft" {
return Ok("loft([${0:sketch000}, ${1:sketch001}])".to_string()); return Ok("loft([${0:sketch000}, ${1:sketch001}])".to_string());
} else if self.name() == "clone" {
return Ok("clone(${0:part001})".to_string());
} else if self.name() == "union" { } else if self.name() == "union" {
return Ok("union([${0:extrude001}, ${1:extrude002}])".to_string()); return Ok("union([${0:extrude001}, ${1:extrude002}])".to_string());
} else if self.name() == "subtract" { } else if self.name() == "subtract" {
@ -1089,6 +1093,14 @@ mod tests {
); );
} }
#[test]
#[allow(clippy::literal_string_with_formatting_args)]
fn get_autocomplete_snippet_clone() {
let clone_fn: Box<dyn StdLibFn> = Box::new(crate::std::clone::Clone);
let snippet = clone_fn.to_autocomplete_snippet().unwrap();
assert_eq!(snippet, r#"clone(${0:part001})"#);
}
// We want to test the snippets we compile at lsp start. // We want to test the snippets we compile at lsp start.
#[test] #[test]
fn get_all_stdlib_autocomplete_snippets() { fn get_all_stdlib_autocomplete_snippets() {

View File

@ -1142,9 +1142,15 @@ impl Node<UnaryExpression> {
} }
KclValue::Plane { value } => { KclValue::Plane { value } => {
let mut plane = value.clone(); let mut plane = value.clone();
plane.z_axis.x *= -1.0; if plane.x_axis.x != 0.0 {
plane.z_axis.y *= -1.0; plane.x_axis.x *= -1.0;
plane.z_axis.z *= -1.0; }
if plane.x_axis.y != 0.0 {
plane.x_axis.y *= -1.0;
}
if plane.x_axis.z != 0.0 {
plane.x_axis.z *= -1.0;
}
plane.value = PlaneType::Uninit; plane.value = PlaneType::Uninit;
plane.id = exec_state.next_uuid(); plane.id = exec_state.next_uuid();
@ -2637,7 +2643,6 @@ p = {
origin = { x = 0, y = 0, z = 0 }, origin = { x = 0, y = 0, z = 0 },
xAxis = { x = 1, y = 0, z = 0 }, xAxis = { x = 1, y = 0, z = 0 },
yAxis = { x = 0, y = 1, z = 0 }, yAxis = { x = 0, y = 1, z = 0 },
zAxis = { x = 0, y = 0, z = 1 }
}: Plane }: Plane
p2 = -p p2 = -p
"#; "#;
@ -2649,7 +2654,11 @@ p2 = -p
.get_from("p2", result.mem_env, SourceRange::default(), 0) .get_from("p2", result.mem_env, SourceRange::default(), 0)
.unwrap() .unwrap()
{ {
KclValue::Plane { value } => assert_eq!(value.z_axis.z, -1.0), KclValue::Plane { value } => {
assert_eq!(value.x_axis.x, -1.0);
assert_eq!(value.x_axis.y, 0.0);
assert_eq!(value.x_axis.z, 0.0);
}
_ => unreachable!(), _ => unreachable!(),
} }
} }

View File

@ -47,6 +47,29 @@ impl Geometry {
} }
} }
/// A geometry including an imported geometry.
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[serde(tag = "type")]
pub enum GeometryWithImportedGeometry {
Sketch(Sketch),
Solid(Solid),
ImportedGeometry(Box<ImportedGeometry>),
}
impl GeometryWithImportedGeometry {
pub async fn id(&mut self, ctx: &ExecutorContext) -> Result<uuid::Uuid, KclError> {
match self {
GeometryWithImportedGeometry::Sketch(s) => Ok(s.id),
GeometryWithImportedGeometry::Solid(e) => Ok(e.id),
GeometryWithImportedGeometry::ImportedGeometry(i) => {
let id = i.id(ctx).await?;
Ok(id)
}
}
}
}
/// A set of geometry. /// A set of geometry.
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)] #[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)] #[ts(export)]
@ -262,8 +285,6 @@ pub struct Plane {
pub x_axis: Point3d, pub x_axis: Point3d,
/// What should the plane's Y axis be? /// What should the plane's Y axis be?
pub y_axis: Point3d, pub y_axis: Point3d,
/// The z-axis (normal).
pub z_axis: Point3d,
#[serde(skip)] #[serde(skip)]
pub meta: Vec<Metadata>, pub meta: Vec<Metadata>,
} }
@ -296,13 +317,6 @@ impl Plane {
z: 0.0, z: 0.0,
units: UnitLen::Mm, units: UnitLen::Mm,
}, },
z_axis:
Point3d {
x: 0.0,
y: 0.0,
z: 1.0,
units: UnitLen::Mm,
},
.. ..
} => return PlaneData::XY, } => return PlaneData::XY,
Self { Self {
@ -315,7 +329,7 @@ impl Plane {
}, },
x_axis: x_axis:
Point3d { Point3d {
x: 1.0, x: -1.0,
y: 0.0, y: 0.0,
z: 0.0, z: 0.0,
units: UnitLen::Mm, units: UnitLen::Mm,
@ -327,13 +341,6 @@ impl Plane {
z: 0.0, z: 0.0,
units: UnitLen::Mm, units: UnitLen::Mm,
}, },
z_axis:
Point3d {
x: 0.0,
y: 0.0,
z: -1.0,
units: UnitLen::Mm,
},
.. ..
} => return PlaneData::NegXY, } => return PlaneData::NegXY,
Self { Self {
@ -358,13 +365,6 @@ impl Plane {
z: 1.0, z: 1.0,
units: UnitLen::Mm, units: UnitLen::Mm,
}, },
z_axis:
Point3d {
x: 0.0,
y: -1.0,
z: 0.0,
units: UnitLen::Mm,
},
.. ..
} => return PlaneData::XZ, } => return PlaneData::XZ,
Self { Self {
@ -377,7 +377,7 @@ impl Plane {
}, },
x_axis: x_axis:
Point3d { Point3d {
x: 1.0, x: -1.0,
y: 0.0, y: 0.0,
z: 0.0, z: 0.0,
units: UnitLen::Mm, units: UnitLen::Mm,
@ -389,13 +389,6 @@ impl Plane {
z: 1.0, z: 1.0,
units: UnitLen::Mm, units: UnitLen::Mm,
}, },
z_axis:
Point3d {
x: 0.0,
y: 1.0,
z: 0.0,
units: UnitLen::Mm,
},
.. ..
} => return PlaneData::NegXZ, } => return PlaneData::NegXZ,
Self { Self {
@ -420,13 +413,6 @@ impl Plane {
z: 1.0, z: 1.0,
units: UnitLen::Mm, units: UnitLen::Mm,
}, },
z_axis:
Point3d {
x: 1.0,
y: 0.0,
z: 0.0,
units: UnitLen::Mm,
},
.. ..
} => return PlaneData::YZ, } => return PlaneData::YZ,
Self { Self {
@ -440,7 +426,7 @@ impl Plane {
x_axis: x_axis:
Point3d { Point3d {
x: 0.0, x: 0.0,
y: 1.0, y: -1.0,
z: 0.0, z: 0.0,
units: UnitLen::Mm, units: UnitLen::Mm,
}, },
@ -451,13 +437,6 @@ impl Plane {
z: 1.0, z: 1.0,
units: UnitLen::Mm, units: UnitLen::Mm,
}, },
z_axis:
Point3d {
x: -1.0,
y: 0.0,
z: 0.0,
units: UnitLen::Mm,
},
.. ..
} => return PlaneData::NegYZ, } => return PlaneData::NegYZ,
_ => {} _ => {}
@ -468,7 +447,6 @@ impl Plane {
origin: self.origin, origin: self.origin,
x_axis: self.x_axis, x_axis: self.x_axis,
y_axis: self.y_axis, y_axis: self.y_axis,
z_axis: self.z_axis,
} }
} }
@ -481,7 +459,6 @@ impl Plane {
origin: Point3d::new(0.0, 0.0, 0.0, UnitLen::Mm), origin: Point3d::new(0.0, 0.0, 0.0, UnitLen::Mm),
x_axis: Point3d::new(1.0, 0.0, 0.0, UnitLen::Mm), x_axis: Point3d::new(1.0, 0.0, 0.0, UnitLen::Mm),
y_axis: Point3d::new(0.0, 1.0, 0.0, UnitLen::Mm), y_axis: Point3d::new(0.0, 1.0, 0.0, UnitLen::Mm),
z_axis: Point3d::new(0.0, 0.0, 1.0, UnitLen::Mm),
value: PlaneType::XY, value: PlaneType::XY,
meta: vec![], meta: vec![],
}, },
@ -489,9 +466,8 @@ impl Plane {
id, id,
artifact_id: id.into(), artifact_id: id.into(),
origin: Point3d::new(0.0, 0.0, 0.0, UnitLen::Mm), origin: Point3d::new(0.0, 0.0, 0.0, UnitLen::Mm),
x_axis: Point3d::new(1.0, 0.0, 0.0, UnitLen::Mm), x_axis: Point3d::new(-1.0, 0.0, 0.0, UnitLen::Mm),
y_axis: Point3d::new(0.0, 1.0, 0.0, UnitLen::Mm), y_axis: Point3d::new(0.0, 1.0, 0.0, UnitLen::Mm),
z_axis: Point3d::new(0.0, 0.0, -1.0, UnitLen::Mm),
value: PlaneType::XY, value: PlaneType::XY,
meta: vec![], meta: vec![],
}, },
@ -501,7 +477,6 @@ impl Plane {
origin: Point3d::new(0.0, 0.0, 0.0, UnitLen::Mm), origin: Point3d::new(0.0, 0.0, 0.0, UnitLen::Mm),
x_axis: Point3d::new(1.0, 0.0, 0.0, UnitLen::Mm), x_axis: Point3d::new(1.0, 0.0, 0.0, UnitLen::Mm),
y_axis: Point3d::new(0.0, 0.0, 1.0, UnitLen::Mm), y_axis: Point3d::new(0.0, 0.0, 1.0, UnitLen::Mm),
z_axis: Point3d::new(0.0, -1.0, 0.0, UnitLen::Mm),
value: PlaneType::XZ, value: PlaneType::XZ,
meta: vec![], meta: vec![],
}, },
@ -511,7 +486,6 @@ impl Plane {
origin: Point3d::new(0.0, 0.0, 0.0, UnitLen::Mm), origin: Point3d::new(0.0, 0.0, 0.0, UnitLen::Mm),
x_axis: Point3d::new(-1.0, 0.0, 0.0, UnitLen::Mm), x_axis: Point3d::new(-1.0, 0.0, 0.0, UnitLen::Mm),
y_axis: Point3d::new(0.0, 0.0, 1.0, UnitLen::Mm), y_axis: Point3d::new(0.0, 0.0, 1.0, UnitLen::Mm),
z_axis: Point3d::new(0.0, 1.0, 0.0, UnitLen::Mm),
value: PlaneType::XZ, value: PlaneType::XZ,
meta: vec![], meta: vec![],
}, },
@ -521,7 +495,6 @@ impl Plane {
origin: Point3d::new(0.0, 0.0, 0.0, UnitLen::Mm), origin: Point3d::new(0.0, 0.0, 0.0, UnitLen::Mm),
x_axis: Point3d::new(0.0, 1.0, 0.0, UnitLen::Mm), x_axis: Point3d::new(0.0, 1.0, 0.0, UnitLen::Mm),
y_axis: Point3d::new(0.0, 0.0, 1.0, UnitLen::Mm), y_axis: Point3d::new(0.0, 0.0, 1.0, UnitLen::Mm),
z_axis: Point3d::new(1.0, 0.0, 0.0, UnitLen::Mm),
value: PlaneType::YZ, value: PlaneType::YZ,
meta: vec![], meta: vec![],
}, },
@ -529,18 +502,12 @@ impl Plane {
id, id,
artifact_id: id.into(), artifact_id: id.into(),
origin: Point3d::new(0.0, 0.0, 0.0, UnitLen::Mm), origin: Point3d::new(0.0, 0.0, 0.0, UnitLen::Mm),
x_axis: Point3d::new(0.0, 1.0, 0.0, UnitLen::Mm), x_axis: Point3d::new(0.0, -1.0, 0.0, UnitLen::Mm),
y_axis: Point3d::new(0.0, 0.0, 1.0, UnitLen::Mm), y_axis: Point3d::new(0.0, 0.0, 1.0, UnitLen::Mm),
z_axis: Point3d::new(-1.0, 0.0, 0.0, UnitLen::Mm),
value: PlaneType::YZ, value: PlaneType::YZ,
meta: vec![], meta: vec![],
}, },
PlaneData::Plane { PlaneData::Plane { origin, x_axis, y_axis } => {
origin,
x_axis,
y_axis,
z_axis,
} => {
let id = exec_state.next_uuid(); let id = exec_state.next_uuid();
Plane { Plane {
id, id,
@ -548,7 +515,6 @@ impl Plane {
origin, origin,
x_axis, x_axis,
y_axis, y_axis,
z_axis,
value: PlaneType::Custom, value: PlaneType::Custom,
meta: vec![], meta: vec![],
} }
@ -577,8 +543,6 @@ pub struct Face {
pub x_axis: Point3d, pub x_axis: Point3d,
/// What should the face's Y axis be? /// What should the face's Y axis be?
pub y_axis: Point3d, pub y_axis: Point3d,
/// The z-axis (normal).
pub z_axis: Point3d,
/// The solid the face is on. /// The solid the face is on.
pub solid: Box<Solid>, pub solid: Box<Solid>,
pub units: UnitLen, pub units: UnitLen,
@ -656,7 +620,8 @@ impl Sketch {
adjust_camera: false, adjust_camera: false,
planar_normal: if let SketchSurface::Plane(plane) = &self.on { planar_normal: if let SketchSurface::Plane(plane) = &self.on {
// We pass in the normal for the plane here. // We pass in the normal for the plane here.
Some(plane.z_axis.into()) let normal = plane.x_axis.cross(&plane.y_axis);
Some(normal.into())
} else { } else {
None None
}, },
@ -700,12 +665,6 @@ impl SketchSurface {
SketchSurface::Face(face) => face.y_axis, SketchSurface::Face(face) => face.y_axis,
} }
} }
pub(crate) fn z_axis(&self) -> Point3d {
match self {
SketchSurface::Plane(plane) => plane.z_axis,
SketchSurface::Face(face) => face.z_axis,
}
}
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -807,7 +766,10 @@ pub struct Solid {
/// Chamfers or fillets on this solid. /// Chamfers or fillets on this solid.
#[serde(default, skip_serializing_if = "Vec::is_empty")] #[serde(default, skip_serializing_if = "Vec::is_empty")]
pub edge_cuts: Vec<EdgeCut>, pub edge_cuts: Vec<EdgeCut>,
/// The units of the solid.
pub units: UnitLen, pub units: UnitLen,
/// Is this a sectional solid?
pub sectional: bool,
/// Metadata. /// Metadata.
#[serde(skip)] #[serde(skip)]
pub meta: Vec<Metadata>, pub meta: Vec<Metadata>,
@ -858,6 +820,13 @@ impl EdgeCut {
} }
} }
pub fn set_id(&mut self, id: uuid::Uuid) {
match self {
EdgeCut::Fillet { id: ref mut i, .. } => *i = id,
EdgeCut::Chamfer { id: ref mut i, .. } => *i = id,
}
}
pub fn edge_id(&self) -> uuid::Uuid { pub fn edge_id(&self) -> uuid::Uuid {
match self { match self {
EdgeCut::Fillet { edge_id, .. } => *edge_id, EdgeCut::Fillet { edge_id, .. } => *edge_id,
@ -865,6 +834,13 @@ impl EdgeCut {
} }
} }
pub fn set_edge_id(&mut self, id: uuid::Uuid) {
match self {
EdgeCut::Fillet { edge_id: ref mut i, .. } => *i = id,
EdgeCut::Chamfer { edge_id: ref mut i, .. } => *i = id,
}
}
pub fn tag(&self) -> Option<TagNode> { pub fn tag(&self) -> Option<TagNode> {
match self { match self {
EdgeCut::Fillet { tag, .. } => *tag.clone(), EdgeCut::Fillet { tag, .. } => *tag.clone(),
@ -929,6 +905,27 @@ impl Point3d {
pub const fn is_zero(&self) -> bool { pub const fn is_zero(&self) -> bool {
self.x == 0.0 && self.y == 0.0 && self.z == 0.0 self.x == 0.0 && self.y == 0.0 && self.z == 0.0
} }
/// Calculate the cross product of this vector with another
pub fn cross(&self, other: &Self) -> Self {
let other = if other.units == self.units {
other
} else {
&Point3d {
x: self.units.adjust_to(other.x, self.units).0,
y: self.units.adjust_to(other.y, self.units).0,
z: self.units.adjust_to(other.z, self.units).0,
units: self.units,
}
};
Self {
x: self.y * other.z - self.z * other.y,
y: self.z * other.x - self.x * other.z,
z: self.x * other.y - self.y * other.x,
units: self.units,
}
}
} }
impl From<[TyF64; 3]> for Point3d { impl From<[TyF64; 3]> for Point3d {
@ -1184,6 +1181,21 @@ impl Path {
} }
} }
pub fn set_id(&mut self, id: uuid::Uuid) {
match self {
Path::ToPoint { base } => base.geo_meta.id = id,
Path::Horizontal { base, .. } => base.geo_meta.id = id,
Path::AngledLineTo { base, .. } => base.geo_meta.id = id,
Path::Base { base } => base.geo_meta.id = id,
Path::TangentialArcTo { base, .. } => base.geo_meta.id = id,
Path::TangentialArc { base, .. } => base.geo_meta.id = id,
Path::Circle { base, .. } => base.geo_meta.id = id,
Path::CircleThreePoint { base, .. } => base.geo_meta.id = id,
Path::Arc { base, .. } => base.geo_meta.id = id,
Path::ArcThreePoint { base, .. } => base.geo_meta.id = id,
}
}
pub fn get_tag(&self) -> Option<TagNode> { pub fn get_tag(&self) -> Option<TagNode> {
match self { match self {
Path::ToPoint { base } => base.tag.clone(), Path::ToPoint { base } => base.tag.clone(),

View File

@ -9,8 +9,8 @@ use crate::{
execution::{ execution::{
annotations::{SETTINGS, SETTINGS_UNIT_LENGTH}, annotations::{SETTINGS, SETTINGS_UNIT_LENGTH},
types::{NumericType, PrimitiveType, RuntimeType, UnitLen}, types::{NumericType, PrimitiveType, RuntimeType, UnitLen},
EnvironmentRef, ExecState, Face, Helix, ImportedGeometry, MetaSettings, Metadata, Plane, Sketch, Solid, EnvironmentRef, ExecState, Face, Geometry, GeometryWithImportedGeometry, Helix, ImportedGeometry, MetaSettings,
TagIdentifier, Metadata, Plane, Sketch, Solid, TagIdentifier,
}, },
parsing::ast::types::{ parsing::ast::types::{
DefaultParamVal, FunctionExpression, KclNone, Literal, LiteralValue, Node, TagDeclarator, TagNode, DefaultParamVal, FunctionExpression, KclNone, Literal, LiteralValue, Node, TagDeclarator, TagNode,
@ -611,3 +611,22 @@ impl KclValue {
} }
} }
} }
impl From<Geometry> for KclValue {
fn from(value: Geometry) -> Self {
match value {
Geometry::Sketch(x) => Self::Sketch { value: Box::new(x) },
Geometry::Solid(x) => Self::Solid { value: Box::new(x) },
}
}
}
impl From<GeometryWithImportedGeometry> for KclValue {
fn from(value: GeometryWithImportedGeometry) -> Self {
match value {
GeometryWithImportedGeometry::Sketch(x) => Self::Sketch { value: Box::new(x) },
GeometryWithImportedGeometry::Solid(x) => Self::Solid { value: Box::new(x) },
GeometryWithImportedGeometry::ImportedGeometry(x) => Self::ImportedGeometry(*x),
}
}
}

View File

@ -1277,7 +1277,7 @@ const part001 = startSketchOn(XY)
|> line(end = [3, 4], tag = $seg01) |> line(end = [3, 4], tag = $seg01)
|> line(end = [ |> line(end = [
min(segLen(seg01), myVar), min(segLen(seg01), myVar),
-legLen(segLen(seg01), myVar) -legLen(hypotenuse = segLen(seg01), leg = myVar)
]) ])
"#; "#;
@ -1292,7 +1292,7 @@ const part001 = startSketchOn(XY)
|> line(end = [3, 4], tag = $seg01) |> line(end = [3, 4], tag = $seg01)
|> line(end = [ |> line(end = [
min(segLen(seg01), myVar), min(segLen(seg01), myVar),
legLen(segLen(seg01), myVar) legLen(hypotenuse = segLen(seg01), leg = myVar)
]) ])
"#; "#;
@ -1684,7 +1684,7 @@ let shape = layer() |> patternTransform(instances = 10, transform = transform)
#[tokio::test(flavor = "multi_thread")] #[tokio::test(flavor = "multi_thread")]
async fn test_math_execute_with_functions() { async fn test_math_execute_with_functions() {
let ast = r#"const myVar = 2 + min(100, -1 + legLen(5, 3))"#; let ast = r#"const myVar = 2 + min(100, -1 + legLen(hypotenuse = 5, leg = 3))"#;
let result = parse_execute(ast).await.unwrap(); let result = parse_execute(ast).await.unwrap();
assert_eq!( assert_eq!(
5.0, 5.0,

View File

@ -28,6 +28,10 @@ pub enum RuntimeType {
} }
impl RuntimeType { impl RuntimeType {
pub fn edge() -> Self {
RuntimeType::Primitive(PrimitiveType::Edge)
}
pub fn sketch() -> Self { pub fn sketch() -> Self {
RuntimeType::Primitive(PrimitiveType::Sketch) RuntimeType::Primitive(PrimitiveType::Sketch)
} }
@ -1043,10 +1047,6 @@ impl KclValue {
.get("yAxis") .get("yAxis")
.and_then(Point3d::from_kcl_val) .and_then(Point3d::from_kcl_val)
.ok_or(CoercionError::from(self))?; .ok_or(CoercionError::from(self))?;
let z_axis = value
.get("zAxis")
.and_then(Point3d::from_kcl_val)
.ok_or(CoercionError::from(self))?;
let id = exec_state.mod_local.id_generator.next_uuid(); let id = exec_state.mod_local.id_generator.next_uuid();
let plane = Plane { let plane = Plane {
@ -1055,7 +1055,6 @@ impl KclValue {
origin, origin,
x_axis, x_axis,
y_axis, y_axis,
z_axis,
value: super::PlaneType::Uninit, value: super::PlaneType::Uninit,
meta: meta.clone(), meta: meta.clone(),
}; };

View File

@ -43,5 +43,5 @@ async fn main() {
.await .await
.unwrap(); .unwrap();
let mut exec_state = ExecState::new(&ctx); let mut exec_state = ExecState::new(&ctx);
ctx.run(&program, &mut exec_state).await.unwrap(); ctx.run(&program, &mut exec_state).await.map_err(|e| e.error).unwrap();
} }

View File

@ -1354,48 +1354,6 @@ mod tangential_arc {
super::execute(TEST_NAME, true).await super::execute(TEST_NAME, true).await
} }
} }
mod big_number_angle_to_match_length_x {
const TEST_NAME: &str = "big_number_angle_to_match_length_x";
/// Test parsing KCL.
#[test]
fn parse() {
super::parse(TEST_NAME)
}
/// Test that parsing and unparsing KCL produces the original KCL input.
#[tokio::test(flavor = "multi_thread")]
async fn unparse() {
super::unparse(TEST_NAME).await
}
/// Test that KCL is executed correctly.
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_execute() {
super::execute(TEST_NAME, true).await
}
}
mod big_number_angle_to_match_length_y {
const TEST_NAME: &str = "big_number_angle_to_match_length_y";
/// Test parsing KCL.
#[test]
fn parse() {
super::parse(TEST_NAME)
}
/// Test that parsing and unparsing KCL produces the original KCL input.
#[tokio::test(flavor = "multi_thread")]
async fn unparse() {
super::unparse(TEST_NAME).await
}
/// Test that KCL is executed correctly.
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_execute() {
super::execute(TEST_NAME, true).await
}
}
mod sketch_on_face_circle_tagged { mod sketch_on_face_circle_tagged {
const TEST_NAME: &str = "sketch_on_face_circle_tagged"; const TEST_NAME: &str = "sketch_on_face_circle_tagged";

View File

@ -277,11 +277,11 @@ pub async fn appearance(exec_state: &mut ExecState, args: Args) -> Result<KclVal
/// import "tests/inputs/cube.sldprt" as cube /// import "tests/inputs/cube.sldprt" as cube
/// ///
/// cube /// cube
/// // |> appearance( /// |> appearance(
/// // color = "#ff0000", /// color = "#ff0000",
/// // metalness = 50, /// metalness = 50,
/// // roughness = 50 /// roughness = 50
/// // ) /// )
/// ``` /// ```
#[stdlib { #[stdlib {
name = "appearance", name = "appearance",

View File

@ -615,22 +615,6 @@ impl Args {
Ok(numbers) Ok(numbers)
} }
pub(crate) fn get_hypotenuse_leg(&self) -> Result<(f64, f64, NumericType), KclError> {
let numbers = self.get_number_array_with_types()?;
if numbers.len() != 2 {
return Err(KclError::Type(KclErrorDetails {
message: format!("Expected a number array of length 2, found `{:?}`", numbers),
source_ranges: vec![self.source_range],
}));
}
let mut numbers = numbers.into_iter();
let a = numbers.next().unwrap();
let b = numbers.next().unwrap();
Ok(NumericType::combine_eq_coerce(a, b))
}
pub(crate) fn get_sketches(&self, exec_state: &mut ExecState) -> Result<(Vec<Sketch>, Sketch), KclError> { pub(crate) fn get_sketches(&self, exec_state: &mut ExecState) -> Result<(Vec<Sketch>, Sketch), KclError> {
let Some(arg0) = self.args.first() else { let Some(arg0) = self.args.first() else {
return Err(KclError::Semantic(KclErrorDetails { return Err(KclError::Semantic(KclErrorDetails {
@ -675,21 +659,10 @@ impl Args {
Ok((sketches, sketch)) Ok((sketches, sketch))
} }
pub(crate) fn get_data<'a, T>(&'a self) -> Result<T, KclError>
where
T: FromArgs<'a>,
{
FromArgs::from_args(self, 0)
}
pub(crate) fn get_data_and_sketch_surface(&self) -> Result<([TyF64; 2], SketchSurface, Option<TagNode>), KclError> { pub(crate) fn get_data_and_sketch_surface(&self) -> Result<([TyF64; 2], SketchSurface, Option<TagNode>), KclError> {
FromArgs::from_args(self, 0) FromArgs::from_args(self, 0)
} }
pub(crate) fn get_tag_to_number_sketch(&self) -> Result<(TagIdentifier, TyF64, Sketch), KclError> {
FromArgs::from_args(self, 0)
}
pub(crate) async fn get_adjacent_face_to_tag( pub(crate) async fn get_adjacent_face_to_tag(
&self, &self,
exec_state: &mut ExecState, exec_state: &mut ExecState,
@ -1028,6 +1001,27 @@ impl<'a> FromKclValue<'a> for kittycad_modeling_cmds::coord::Direction {
} }
} }
impl<'a> FromKclValue<'a> for crate::execution::Geometry {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
match arg {
KclValue::Sketch { value } => Some(Self::Sketch(*value.to_owned())),
KclValue::Solid { value } => Some(Self::Solid(*value.to_owned())),
_ => None,
}
}
}
impl<'a> FromKclValue<'a> for crate::execution::GeometryWithImportedGeometry {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
match arg {
KclValue::Sketch { value } => Some(Self::Sketch(*value.to_owned())),
KclValue::Solid { value } => Some(Self::Solid(*value.to_owned())),
KclValue::ImportedGeometry(value) => Some(Self::ImportedGeometry(Box::new(value.clone()))),
_ => None,
}
}
}
impl<'a> FromKclValue<'a> for FaceTag { impl<'a> FromKclValue<'a> for FaceTag {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> { fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
let case1 = || match arg.as_str() { let case1 = || match arg.as_str() {
@ -1087,7 +1081,6 @@ impl<'a> FromKclValue<'a> for super::sketch::PlaneData {
origin: value.origin, origin: value.origin,
x_axis: value.x_axis, x_axis: value.x_axis,
y_axis: value.y_axis, y_axis: value.y_axis,
z_axis: value.z_axis,
}); });
} }
// Case 1: predefined plane // Case 1: predefined plane
@ -1108,13 +1101,7 @@ impl<'a> FromKclValue<'a> for super::sketch::PlaneData {
let origin = plane.get("origin").and_then(FromKclValue::from_kcl_val)?; let origin = plane.get("origin").and_then(FromKclValue::from_kcl_val)?;
let x_axis = plane.get("xAxis").and_then(FromKclValue::from_kcl_val)?; let x_axis = plane.get("xAxis").and_then(FromKclValue::from_kcl_val)?;
let y_axis = plane.get("yAxis").and_then(FromKclValue::from_kcl_val)?; let y_axis = plane.get("yAxis").and_then(FromKclValue::from_kcl_val)?;
let z_axis = plane.get("zAxis").and_then(FromKclValue::from_kcl_val)?; Some(Self::Plane { origin, x_axis, y_axis })
Some(Self::Plane {
origin,
x_axis,
y_axis,
z_axis,
})
} }
} }

View File

@ -0,0 +1,909 @@
//! Standard library clone.
use std::collections::HashMap;
use anyhow::Result;
use kcl_derive_docs::stdlib;
use kcmc::{
each_cmd as mcmd,
ok_response::{output::EntityGetAllChildUuids, OkModelingCmdResponse},
websocket::OkWebSocketResponseData,
ModelingCmd,
};
use kittycad_modeling_cmds::{self as kcmc};
use super::extrude::do_post_extrude;
use crate::{
errors::{KclError, KclErrorDetails},
execution::{
types::{NumericType, PrimitiveType, RuntimeType},
ExecState, GeometryWithImportedGeometry, KclValue, Sketch, Solid,
},
parsing::ast::types::TagNode,
std::{extrude::NamedCapTags, Args},
};
/// Clone a sketch or solid.
///
/// This works essentially like a copy-paste operation.
pub async fn clone(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let geometry = args.get_unlabeled_kw_arg_typed(
"geometry",
&RuntimeType::Union(vec![
RuntimeType::Primitive(PrimitiveType::Sketch),
RuntimeType::Primitive(PrimitiveType::Solid),
RuntimeType::imported(),
]),
exec_state,
)?;
let cloned = inner_clone(geometry, exec_state, args).await?;
Ok(cloned.into())
}
/// Clone a sketch or solid.
///
/// This works essentially like a copy-paste operation.
///
/// This doesn't really have much utility unless you need the equivalent of a double
/// instance pattern with zero transformations.
///
/// Really only use this function if YOU ARE SURE you need it. In most cases you
/// do not need clone and using a pattern with `instance = 2` is more appropriate.
///
/// ```no_run
/// // Clone a basic sketch and move it and extrude it.
/// exampleSketch = startSketchOn(XY)
/// |> startProfileAt([0, 0], %)
/// |> line(end = [10, 0])
/// |> line(end = [0, 10])
/// |> line(end = [-10, 0])
/// |> close()
///
/// clonedSketch = clone(exampleSketch)
/// |> scale(
/// x = 1.0,
/// y = 1.0,
/// z = 2.5,
/// )
/// |> translate(
/// x = 15.0,
/// y = 0,
/// z = 0,
/// )
/// |> extrude(length = 5)
/// ```
///
/// ```no_run
/// // Clone a basic solid and move it.
///
/// exampleSketch = startSketchOn(XY)
/// |> startProfileAt([0, 0], %)
/// |> line(end = [10, 0])
/// |> line(end = [0, 10])
/// |> line(end = [-10, 0])
/// |> close()
///
/// myPart = extrude(exampleSketch, length = 5)
/// clonedPart = clone(myPart)
/// |> translate(
/// x = 25.0,
/// )
/// ```
///
/// ```no_run
/// // Translate and rotate a cloned sketch to create a loft.
///
/// sketch001 = startSketchOn(XY)
/// |> startProfileAt([-10, 10], %)
/// |> xLine(length = 20)
/// |> yLine(length = -20)
/// |> xLine(length = -20)
/// |> close()
///
/// sketch002 = clone(sketch001)
/// |> translate(x = 0, y = 0, z = 20)
/// |> rotate(axis = [0, 0, 1.0], angle = 45)
///
/// loft([sketch001, sketch002])
/// ```
///
/// ```no_run
/// // Translate a cloned solid. Fillet only the clone.
///
/// sketch001 = startSketchOn(XY)
/// |> startProfileAt([-10, 10], %)
/// |> xLine(length = 20)
/// |> yLine(length = -20)
/// |> xLine(length = -20, tag = $filletTag)
/// |> close()
/// |> extrude(length = 5)
///
///
/// sketch002 = clone(sketch001)
/// |> translate(x = 0, y = 0, z = 20)
/// |> fillet(
/// radius = 2,
/// tags = [getNextAdjacentEdge(filletTag)],
/// )
/// ```
///
/// ```no_run
/// // You can reuse the tags from the original geometry with the cloned geometry.
///
/// sketch001 = startSketchOn(XY)
/// |> startProfileAt([0, 0], %)
/// |> line(end = [10, 0])
/// |> line(end = [0, 10], tag = $sketchingFace)
/// |> line(end = [-10, 0])
/// |> close()
///
/// sketch002 = clone(sketch001)
/// |> translate(x = 10, y = 20, z = 0)
/// |> extrude(length = 5)
///
/// startSketchOn(sketch002, face = sketchingFace)
/// |> startProfileAt([1, 1], %)
/// |> line(end = [8, 0])
/// |> line(end = [0, 8])
/// |> line(end = [-8, 0])
/// |> close(tag = $sketchingFace002)
/// |> extrude(length = 10)
/// ```
///
/// ```no_run
/// // You can also use the tags from the original geometry to fillet the cloned geometry.
///
/// width = 20
/// length = 10
/// thickness = 1
/// filletRadius = 2
///
/// mountingPlateSketch = startSketchOn(XY)
/// |> startProfileAt([-width/2, -length/2], %)
/// |> line(endAbsolute = [width/2, -length/2], tag = $edge1)
/// |> line(endAbsolute = [width/2, length/2], tag = $edge2)
/// |> line(endAbsolute = [-width/2, length/2], tag = $edge3)
/// |> close(tag = $edge4)
///
/// mountingPlate = extrude(mountingPlateSketch, length = thickness)
///
/// clonedMountingPlate = clone(mountingPlate)
/// |> fillet(
/// radius = filletRadius,
/// tags = [
/// getNextAdjacentEdge(edge1),
/// getNextAdjacentEdge(edge2),
/// getNextAdjacentEdge(edge3),
/// getNextAdjacentEdge(edge4)
/// ],
/// )
/// |> translate(x = 0, y = 50, z = 0)
/// ```
///
/// ```no_run
/// // Create a spring by sweeping around a helix path from a cloned sketch.
///
/// // Create a helix around the Z axis.
/// helixPath = helix(
/// angleStart = 0,
/// ccw = true,
/// revolutions = 4,
/// length = 10,
/// radius = 5,
/// axis = Z,
/// )
///
///
/// springSketch = startSketchOn(YZ)
/// |> circle( center = [0, 0], radius = 1)
///
/// // Create a spring by sweeping around the helix path.
/// sweepedSpring = clone(springSketch)
/// |> translate(x=100)
/// |> sweep(path = helixPath)
/// ```
///
/// ```
/// // A donut shape from a cloned sketch.
/// sketch001 = startSketchOn(XY)
/// |> circle( center = [15, 0], radius = 5 )
///
/// sketch002 = clone(sketch001)
/// |> translate( z = 30)
/// |> revolve(
/// angle = 360,
/// axis = Y,
/// )
/// ```
///
/// ```no_run
/// // Sketch on the end of a revolved face by tagging the end face.
/// // This shows the cloned geometry will have the same tags as the original geometry.
///
/// exampleSketch = startSketchOn(XY)
/// |> startProfileAt([4, 12], %)
/// |> line(end = [2, 0])
/// |> line(end = [0, -6])
/// |> line(end = [4, -6])
/// |> line(end = [0, -6])
/// |> line(end = [-3.75, -4.5])
/// |> line(end = [0, -5.5])
/// |> line(end = [-2, 0])
/// |> close()
///
/// example001 = revolve(exampleSketch, axis = Y, angle = 180, tagEnd = $end01)
///
/// // example002 = clone(example001)
/// // |> translate(x = 0, y = 20, z = 0)
///
/// // Sketch on the cloned face.
/// // exampleSketch002 = startSketchOn(example002, face = end01)
/// // |> startProfileAt([4.5, -5], %)
/// // |> line(end = [0, 5])
/// // |> line(end = [5, 0])
/// // |> line(end = [0, -5])
/// // |> close()
///
/// // example003 = extrude(exampleSketch002, length = 5)
/// ```
///
/// ```no_run
/// // Clone an imported model.
///
/// import "tests/inputs/cube.sldprt" as cube
///
/// myCube = cube
///
/// clonedCube = clone(myCube)
/// |> translate(
/// x = 1020,
/// )
/// |> appearance(
/// color = "#ff0000",
/// metalness = 50,
/// roughness = 50
/// )
/// ```
#[stdlib {
name = "clone",
feature_tree_operation = true,
keywords = true,
unlabeled_first = true,
args = {
geometry = { docs = "The sketch, solid, or imported geometry to be cloned" },
}
}]
async fn inner_clone(
geometry: GeometryWithImportedGeometry,
exec_state: &mut ExecState,
args: Args,
) -> Result<GeometryWithImportedGeometry, KclError> {
let new_id = exec_state.next_uuid();
let mut geometry = geometry.clone();
let old_id = geometry.id(&args.ctx).await?;
let mut new_geometry = match &geometry {
GeometryWithImportedGeometry::ImportedGeometry(imported) => {
let mut new_imported = imported.clone();
new_imported.id = new_id;
GeometryWithImportedGeometry::ImportedGeometry(new_imported)
}
GeometryWithImportedGeometry::Sketch(sketch) => {
let mut new_sketch = sketch.clone();
new_sketch.id = new_id;
new_sketch.original_id = new_id;
new_sketch.artifact_id = new_id.into();
GeometryWithImportedGeometry::Sketch(new_sketch)
}
GeometryWithImportedGeometry::Solid(solid) => {
let mut new_solid = solid.clone();
new_solid.id = new_id;
new_solid.sketch.original_id = new_id;
new_solid.artifact_id = new_id.into();
GeometryWithImportedGeometry::Solid(new_solid)
}
};
if args.ctx.no_engine_commands().await {
return Ok(new_geometry);
}
args.batch_modeling_cmd(new_id, ModelingCmd::from(mcmd::EntityClone { entity_id: old_id }))
.await?;
fix_tags_and_references(&mut new_geometry, old_id, exec_state, &args)
.await
.map_err(|e| {
KclError::Internal(KclErrorDetails {
message: format!("failed to fix tags and references: {:?}", e),
source_ranges: vec![args.source_range],
})
})?;
Ok(new_geometry)
}
/// Fix the tags and references of the cloned geometry.
async fn fix_tags_and_references(
new_geometry: &mut GeometryWithImportedGeometry,
old_geometry_id: uuid::Uuid,
exec_state: &mut ExecState,
args: &Args,
) -> Result<()> {
let new_geometry_id = new_geometry.id(&args.ctx).await?;
let entity_id_map = get_old_new_child_map(new_geometry_id, old_geometry_id, exec_state, args).await?;
// Fix the path references in the new geometry.
match new_geometry {
GeometryWithImportedGeometry::ImportedGeometry(_) => {}
GeometryWithImportedGeometry::Sketch(sketch) => {
fix_sketch_tags_and_references(sketch, &entity_id_map, exec_state).await?;
}
GeometryWithImportedGeometry::Solid(solid) => {
// Make the sketch id the new geometry id.
solid.sketch.id = new_geometry_id;
solid.sketch.original_id = new_geometry_id;
solid.sketch.artifact_id = new_geometry_id.into();
fix_sketch_tags_and_references(&mut solid.sketch, &entity_id_map, exec_state).await?;
let (start_tag, end_tag) = get_named_cap_tags(solid);
// Fix the edge cuts.
for edge_cut in solid.edge_cuts.iter_mut() {
let Some(new_edge_id) = entity_id_map.get(&edge_cut.edge_id()) else {
anyhow::bail!("Failed to find new edge id for old edge id: {:?}", edge_cut.edge_id());
};
edge_cut.set_edge_id(*new_edge_id);
let Some(id) = entity_id_map.get(&edge_cut.id()) else {
anyhow::bail!(
"Failed to find new edge cut id for old edge cut id: {:?}",
edge_cut.id()
);
};
edge_cut.set_id(*id);
}
// Do the after extrude things to update those ids, based on the new sketch
// information.
let new_solid = do_post_extrude(
&solid.sketch,
new_geometry_id.into(),
crate::std::args::TyF64::new(
solid.height,
NumericType::Known(crate::execution::types::UnitType::Length(solid.units)),
),
solid.sectional,
&NamedCapTags {
start: start_tag.as_ref(),
end: end_tag.as_ref(),
},
exec_state,
args,
)
.await?;
*solid = new_solid;
}
}
Ok(())
}
async fn get_old_new_child_map(
new_geometry_id: uuid::Uuid,
old_geometry_id: uuid::Uuid,
exec_state: &mut ExecState,
args: &Args,
) -> Result<HashMap<uuid::Uuid, uuid::Uuid>> {
// Get the new geometries entity ids.
let response = args
.send_modeling_cmd(
exec_state.next_uuid(),
ModelingCmd::from(mcmd::EntityGetAllChildUuids {
entity_id: new_geometry_id,
}),
)
.await?;
let OkWebSocketResponseData::Modeling {
modeling_response:
OkModelingCmdResponse::EntityGetAllChildUuids(EntityGetAllChildUuids {
entity_ids: new_entity_ids,
}),
} = response
else {
anyhow::bail!("Expected EntityGetAllChildUuids response, got: {:?}", response);
};
// Get the old geometries entity ids.
let response = args
.send_modeling_cmd(
exec_state.next_uuid(),
ModelingCmd::from(mcmd::EntityGetAllChildUuids {
entity_id: old_geometry_id,
}),
)
.await?;
let OkWebSocketResponseData::Modeling {
modeling_response:
OkModelingCmdResponse::EntityGetAllChildUuids(EntityGetAllChildUuids {
entity_ids: old_entity_ids,
}),
} = response
else {
anyhow::bail!("Expected EntityGetAllChildUuids response, got: {:?}", response);
};
// Create a map of old entity ids to new entity ids.
Ok(HashMap::from_iter(
old_entity_ids
.iter()
.zip(new_entity_ids.iter())
.map(|(old_id, new_id)| (*old_id, *new_id)),
))
}
/// Fix the tags and references of a sketch.
async fn fix_sketch_tags_and_references(
new_sketch: &mut Sketch,
entity_id_map: &HashMap<uuid::Uuid, uuid::Uuid>,
exec_state: &mut ExecState,
) -> Result<()> {
// Fix the path references in the sketch.
for path in new_sketch.paths.as_mut_slice() {
let Some(new_path_id) = entity_id_map.get(&path.get_id()) else {
anyhow::bail!("Failed to find new path id for old path id: {:?}", path.get_id());
};
path.set_id(*new_path_id);
}
// Fix the tags
// This is annoying, in order to fix the tags we need to iterate over the paths again, but not
// mutable borrow the paths.
for path in new_sketch.paths.clone() {
// Check if this path has a tag.
if let Some(tag) = path.get_tag() {
new_sketch.add_tag(&tag, &path, exec_state);
}
}
// Fix the base path.
// TODO: Right now this one does not work, ignore for now and see if we really need it.
/* let Some(new_base_path) = entity_id_map.get(&new_sketch.start.geo_meta.id) else {
anyhow::bail!(
"Failed to find new base path id for old base path id: {:?}",
new_sketch.start.geo_meta.id
);
};
new_sketch.start.geo_meta.id = *new_base_path;*/
Ok(())
}
// Return the named cap tags for the original solid.
fn get_named_cap_tags(solid: &Solid) -> (Option<TagNode>, Option<TagNode>) {
let mut start_tag = None;
let mut end_tag = None;
// Check the start cap.
if let Some(start_cap_id) = solid.start_cap_id {
// Check if we had a value for that cap.
for value in &solid.value {
if value.get_id() == start_cap_id {
start_tag = value.get_tag().clone();
break;
}
}
}
// Check the end cap.
if let Some(end_cap_id) = solid.end_cap_id {
// Check if we had a value for that cap.
for value in &solid.value {
if value.get_id() == end_cap_id {
end_tag = value.get_tag().clone();
break;
}
}
}
(start_tag, end_tag)
}
#[cfg(test)]
mod tests {
use pretty_assertions::{assert_eq, assert_ne};
use crate::exec::KclValue;
// Ensure the clone function returns a sketch with different ids for all the internal paths and
// the resulting sketch.
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_clone_sketch() {
let code = r#"cube = startSketchOn(XY)
|> startProfileAt([0,0], %)
|> line(end = [0, 10])
|> line(end = [10, 0])
|> line(end = [0, -10])
|> close()
clonedCube = clone(cube)
"#;
let ctx = crate::test_server::new_context(true, None).await.unwrap();
let program = crate::Program::parse_no_errs(code).unwrap();
// Execute the program.
let result = ctx.run_with_caching(program.clone()).await.unwrap();
let cube = result.variables.get("cube").unwrap();
let cloned_cube = result.variables.get("clonedCube").unwrap();
assert_ne!(cube, cloned_cube);
let KclValue::Sketch { value: cube } = cube else {
panic!("Expected a sketch, got: {:?}", cube);
};
let KclValue::Sketch { value: cloned_cube } = cloned_cube else {
panic!("Expected a sketch, got: {:?}", cloned_cube);
};
assert_ne!(cube.id, cloned_cube.id);
assert_ne!(cube.original_id, cloned_cube.original_id);
assert_ne!(cube.artifact_id, cloned_cube.artifact_id);
assert_eq!(cloned_cube.artifact_id, cloned_cube.id.into());
assert_eq!(cloned_cube.original_id, cloned_cube.id);
for (path, cloned_path) in cube.paths.iter().zip(cloned_cube.paths.iter()) {
assert_ne!(path.get_id(), cloned_path.get_id());
assert_eq!(path.get_tag(), cloned_path.get_tag());
}
assert_eq!(cube.tags.len(), 0);
assert_eq!(cloned_cube.tags.len(), 0);
}
// Ensure the clone function returns a solid with different ids for all the internal paths and
// references.
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_clone_solid() {
let code = r#"cube = startSketchOn(XY)
|> startProfileAt([0,0], %)
|> line(end = [0, 10])
|> line(end = [10, 0])
|> line(end = [0, -10])
|> close()
|> extrude(length = 5)
clonedCube = clone(cube)
"#;
let ctx = crate::test_server::new_context(true, None).await.unwrap();
let program = crate::Program::parse_no_errs(code).unwrap();
// Execute the program.
let result = ctx.run_with_caching(program.clone()).await.unwrap();
let cube = result.variables.get("cube").unwrap();
let cloned_cube = result.variables.get("clonedCube").unwrap();
assert_ne!(cube, cloned_cube);
let KclValue::Solid { value: cube } = cube else {
panic!("Expected a solid, got: {:?}", cube);
};
let KclValue::Solid { value: cloned_cube } = cloned_cube else {
panic!("Expected a solid, got: {:?}", cloned_cube);
};
assert_ne!(cube.id, cloned_cube.id);
assert_ne!(cube.sketch.id, cloned_cube.sketch.id);
assert_ne!(cube.sketch.original_id, cloned_cube.sketch.original_id);
assert_ne!(cube.artifact_id, cloned_cube.artifact_id);
assert_ne!(cube.sketch.artifact_id, cloned_cube.sketch.artifact_id);
assert_eq!(cloned_cube.artifact_id, cloned_cube.id.into());
for (path, cloned_path) in cube.sketch.paths.iter().zip(cloned_cube.sketch.paths.iter()) {
assert_ne!(path.get_id(), cloned_path.get_id());
assert_eq!(path.get_tag(), cloned_path.get_tag());
}
for (value, cloned_value) in cube.value.iter().zip(cloned_cube.value.iter()) {
assert_ne!(value.get_id(), cloned_value.get_id());
assert_eq!(value.get_tag(), cloned_value.get_tag());
}
assert_eq!(cube.sketch.tags.len(), 0);
assert_eq!(cloned_cube.sketch.tags.len(), 0);
assert_eq!(cube.edge_cuts.len(), 0);
assert_eq!(cloned_cube.edge_cuts.len(), 0);
}
// Ensure the clone function returns a sketch with different ids for all the internal paths and
// the resulting sketch.
// AND TAGS.
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_clone_sketch_with_tags() {
let code = r#"cube = startSketchOn(XY)
|> startProfileAt([0,0], %) // tag this one
|> line(end = [0, 10], tag = $tag02)
|> line(end = [10, 0], tag = $tag03)
|> line(end = [0, -10], tag = $tag04)
|> close(tag = $tag05)
clonedCube = clone(cube)
"#;
let ctx = crate::test_server::new_context(true, None).await.unwrap();
let program = crate::Program::parse_no_errs(code).unwrap();
// Execute the program.
let result = ctx.run_with_caching(program.clone()).await.unwrap();
let cube = result.variables.get("cube").unwrap();
let cloned_cube = result.variables.get("clonedCube").unwrap();
assert_ne!(cube, cloned_cube);
let KclValue::Sketch { value: cube } = cube else {
panic!("Expected a sketch, got: {:?}", cube);
};
let KclValue::Sketch { value: cloned_cube } = cloned_cube else {
panic!("Expected a sketch, got: {:?}", cloned_cube);
};
assert_ne!(cube.id, cloned_cube.id);
assert_ne!(cube.original_id, cloned_cube.original_id);
for (path, cloned_path) in cube.paths.iter().zip(cloned_cube.paths.iter()) {
assert_ne!(path.get_id(), cloned_path.get_id());
assert_eq!(path.get_tag(), cloned_path.get_tag());
}
for (tag_name, tag) in &cube.tags {
let cloned_tag = cloned_cube.tags.get(tag_name).unwrap();
let tag_info = tag.get_cur_info().unwrap();
let cloned_tag_info = cloned_tag.get_cur_info().unwrap();
assert_ne!(tag_info.id, cloned_tag_info.id);
assert_ne!(tag_info.sketch, cloned_tag_info.sketch);
assert_ne!(tag_info.path, cloned_tag_info.path);
assert_eq!(tag_info.surface, None);
assert_eq!(cloned_tag_info.surface, None);
}
}
// Ensure the clone function returns a solid with different ids for all the internal paths and
// references.
// WITH TAGS.
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_clone_solid_with_tags() {
let code = r#"cube = startSketchOn(XY)
|> startProfileAt([0,0], %) // tag this one
|> line(end = [0, 10], tag = $tag02)
|> line(end = [10, 0], tag = $tag03)
|> line(end = [0, -10], tag = $tag04)
|> close(tag = $tag05)
|> extrude(length = 5) // TODO: Tag these
clonedCube = clone(cube)
"#;
let ctx = crate::test_server::new_context(true, None).await.unwrap();
let program = crate::Program::parse_no_errs(code).unwrap();
// Execute the program.
let result = ctx.run_with_caching(program.clone()).await.unwrap();
let cube = result.variables.get("cube").unwrap();
let cloned_cube = result.variables.get("clonedCube").unwrap();
assert_ne!(cube, cloned_cube);
let KclValue::Solid { value: cube } = cube else {
panic!("Expected a solid, got: {:?}", cube);
};
let KclValue::Solid { value: cloned_cube } = cloned_cube else {
panic!("Expected a solid, got: {:?}", cloned_cube);
};
assert_ne!(cube.id, cloned_cube.id);
assert_ne!(cube.sketch.id, cloned_cube.sketch.id);
assert_ne!(cube.sketch.original_id, cloned_cube.sketch.original_id);
assert_ne!(cube.artifact_id, cloned_cube.artifact_id);
assert_ne!(cube.sketch.artifact_id, cloned_cube.sketch.artifact_id);
assert_eq!(cloned_cube.artifact_id, cloned_cube.id.into());
for (path, cloned_path) in cube.sketch.paths.iter().zip(cloned_cube.sketch.paths.iter()) {
assert_ne!(path.get_id(), cloned_path.get_id());
assert_eq!(path.get_tag(), cloned_path.get_tag());
}
for (value, cloned_value) in cube.value.iter().zip(cloned_cube.value.iter()) {
assert_ne!(value.get_id(), cloned_value.get_id());
assert_eq!(value.get_tag(), cloned_value.get_tag());
}
for (tag_name, tag) in &cube.sketch.tags {
let cloned_tag = cloned_cube.sketch.tags.get(tag_name).unwrap();
let tag_info = tag.get_cur_info().unwrap();
let cloned_tag_info = cloned_tag.get_cur_info().unwrap();
assert_ne!(tag_info.id, cloned_tag_info.id);
assert_ne!(tag_info.sketch, cloned_tag_info.sketch);
assert_ne!(tag_info.path, cloned_tag_info.path);
assert_ne!(tag_info.surface, cloned_tag_info.surface);
}
assert_eq!(cube.edge_cuts.len(), 0);
assert_eq!(cloned_cube.edge_cuts.len(), 0);
}
// Ensure we can get all paths even on a sketch where we closed it and it was already closed.
#[tokio::test(flavor = "multi_thread")]
#[ignore = "this test is not working yet, need to fix the getting of ids if sketch already closed"]
async fn kcl_test_clone_cube_already_closed_sketch() {
let code = r#"// Clone a basic solid and move it.
exampleSketch = startSketchOn(XY)
|> startProfileAt([0, 0], %)
|> line(end = [10, 0])
|> line(end = [0, 10])
|> line(end = [-10, 0])
|> line(end = [0, -10])
|> close()
cube = extrude(exampleSketch, length = 5)
clonedCube = clone(cube)
|> translate(
x = 25.0,
)"#;
let ctx = crate::test_server::new_context(true, None).await.unwrap();
let program = crate::Program::parse_no_errs(code).unwrap();
// Execute the program.
let result = ctx.run_with_caching(program.clone()).await.unwrap();
let cube = result.variables.get("cube").unwrap();
let cloned_cube = result.variables.get("clonedCube").unwrap();
assert_ne!(cube, cloned_cube);
let KclValue::Solid { value: cube } = cube else {
panic!("Expected a solid, got: {:?}", cube);
};
let KclValue::Solid { value: cloned_cube } = cloned_cube else {
panic!("Expected a solid, got: {:?}", cloned_cube);
};
assert_ne!(cube.id, cloned_cube.id);
assert_ne!(cube.sketch.id, cloned_cube.sketch.id);
assert_ne!(cube.sketch.original_id, cloned_cube.sketch.original_id);
assert_ne!(cube.artifact_id, cloned_cube.artifact_id);
assert_ne!(cube.sketch.artifact_id, cloned_cube.sketch.artifact_id);
assert_eq!(cloned_cube.artifact_id, cloned_cube.id.into());
for (path, cloned_path) in cube.sketch.paths.iter().zip(cloned_cube.sketch.paths.iter()) {
assert_ne!(path.get_id(), cloned_path.get_id());
assert_eq!(path.get_tag(), cloned_path.get_tag());
}
for (value, cloned_value) in cube.value.iter().zip(cloned_cube.value.iter()) {
assert_ne!(value.get_id(), cloned_value.get_id());
assert_eq!(value.get_tag(), cloned_value.get_tag());
}
for (tag_name, tag) in &cube.sketch.tags {
let cloned_tag = cloned_cube.sketch.tags.get(tag_name).unwrap();
let tag_info = tag.get_cur_info().unwrap();
let cloned_tag_info = cloned_tag.get_cur_info().unwrap();
assert_ne!(tag_info.id, cloned_tag_info.id);
assert_ne!(tag_info.sketch, cloned_tag_info.sketch);
assert_ne!(tag_info.path, cloned_tag_info.path);
assert_ne!(tag_info.surface, cloned_tag_info.surface);
}
for (edge_cut, cloned_edge_cut) in cube.edge_cuts.iter().zip(cloned_cube.edge_cuts.iter()) {
assert_ne!(edge_cut.id(), cloned_edge_cut.id());
assert_ne!(edge_cut.edge_id(), cloned_edge_cut.edge_id());
assert_eq!(edge_cut.tag(), cloned_edge_cut.tag());
}
}
// Ensure the clone function returns a solid with different ids for all the internal paths and
// references.
// WITH TAGS AND EDGE CUTS.
#[tokio::test(flavor = "multi_thread")]
#[ignore = "this test is not working yet, need to fix the edge cut ids"]
async fn kcl_test_clone_solid_with_edge_cuts() {
let code = r#"cube = startSketchOn(XY)
|> startProfileAt([0,0], %) // tag this one
|> line(end = [0, 10], tag = $tag02)
|> line(end = [10, 0], tag = $tag03)
|> line(end = [0, -10], tag = $tag04)
|> close(tag = $tag05)
|> extrude(length = 5) // TODO: Tag these
|> fillet(
radius = 2,
tags = [
getNextAdjacentEdge(tag02),
],
tag = $fillet01,
)
|> fillet(
radius = 2,
tags = [
getNextAdjacentEdge(tag04),
],
tag = $fillet02,
)
|> chamfer(
length = 2,
tags = [
getNextAdjacentEdge(tag03),
],
tag = $chamfer01,
)
|> chamfer(
length = 2,
tags = [
getNextAdjacentEdge(tag05),
],
tag = $chamfer02,
)
clonedCube = clone(cube)
"#;
let ctx = crate::test_server::new_context(true, None).await.unwrap();
let program = crate::Program::parse_no_errs(code).unwrap();
// Execute the program.
let result = ctx.run_with_caching(program.clone()).await.unwrap();
let cube = result.variables.get("cube").unwrap();
let cloned_cube = result.variables.get("clonedCube").unwrap();
assert_ne!(cube, cloned_cube);
let KclValue::Solid { value: cube } = cube else {
panic!("Expected a solid, got: {:?}", cube);
};
let KclValue::Solid { value: cloned_cube } = cloned_cube else {
panic!("Expected a solid, got: {:?}", cloned_cube);
};
assert_ne!(cube.id, cloned_cube.id);
assert_ne!(cube.sketch.id, cloned_cube.sketch.id);
assert_ne!(cube.sketch.original_id, cloned_cube.sketch.original_id);
assert_ne!(cube.artifact_id, cloned_cube.artifact_id);
assert_ne!(cube.sketch.artifact_id, cloned_cube.sketch.artifact_id);
assert_eq!(cloned_cube.artifact_id, cloned_cube.id.into());
for (path, cloned_path) in cube.sketch.paths.iter().zip(cloned_cube.sketch.paths.iter()) {
assert_ne!(path.get_id(), cloned_path.get_id());
assert_eq!(path.get_tag(), cloned_path.get_tag());
}
for (value, cloned_value) in cube.value.iter().zip(cloned_cube.value.iter()) {
assert_ne!(value.get_id(), cloned_value.get_id());
assert_eq!(value.get_tag(), cloned_value.get_tag());
}
for (tag_name, tag) in &cube.sketch.tags {
let cloned_tag = cloned_cube.sketch.tags.get(tag_name).unwrap();
let tag_info = tag.get_cur_info().unwrap();
let cloned_tag_info = cloned_tag.get_cur_info().unwrap();
assert_ne!(tag_info.id, cloned_tag_info.id);
assert_ne!(tag_info.sketch, cloned_tag_info.sketch);
assert_ne!(tag_info.path, cloned_tag_info.path);
assert_ne!(tag_info.surface, cloned_tag_info.surface);
}
for (edge_cut, cloned_edge_cut) in cube.edge_cuts.iter().zip(cloned_cube.edge_cuts.iter()) {
assert_ne!(edge_cut.id(), cloned_edge_cut.id());
assert_ne!(edge_cut.edge_id(), cloned_edge_cut.edge_id());
assert_eq!(edge_cut.tag(), cloned_edge_cut.tag());
}
}
}

View File

@ -8,15 +8,15 @@ use uuid::Uuid;
use crate::{ use crate::{
errors::{KclError, KclErrorDetails}, errors::{KclError, KclErrorDetails},
execution::{ExecState, ExtrudeSurface, KclValue, TagIdentifier}, execution::{types::RuntimeType, ExecState, ExtrudeSurface, KclValue, TagIdentifier},
std::Args, std::Args,
}; };
/// Get the opposite edge to the edge given. /// Get the opposite edge to the edge given.
pub async fn get_opposite_edge(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> { pub async fn get_opposite_edge(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let tag: TagIdentifier = args.get_data()?; let input_edge = args.get_unlabeled_kw_arg_typed("edge", &RuntimeType::edge(), exec_state)?;
let edge = inner_get_opposite_edge(tag, exec_state, args.clone()).await?; let edge = inner_get_opposite_edge(input_edge, exec_state, args.clone()).await?;
Ok(KclValue::Uuid { Ok(KclValue::Uuid {
value: edge, value: edge,
meta: vec![args.source_range.into()], meta: vec![args.source_range.into()],
@ -53,15 +53,24 @@ pub async fn get_opposite_edge(exec_state: &mut ExecState, args: Args) -> Result
/// ``` /// ```
#[stdlib { #[stdlib {
name = "getOppositeEdge", name = "getOppositeEdge",
keywords = true,
unlabeled_first = true,
args = {
edge = { docs = "The tag of the edge you want to find the opposite edge of." },
}
}] }]
async fn inner_get_opposite_edge(tag: TagIdentifier, exec_state: &mut ExecState, args: Args) -> Result<Uuid, KclError> { async fn inner_get_opposite_edge(
edge: TagIdentifier,
exec_state: &mut ExecState,
args: Args,
) -> Result<Uuid, KclError> {
if args.ctx.no_engine_commands().await { if args.ctx.no_engine_commands().await {
return Ok(exec_state.next_uuid()); return Ok(exec_state.next_uuid());
} }
let face_id = args.get_adjacent_face_to_tag(exec_state, &tag, false).await?; let face_id = args.get_adjacent_face_to_tag(exec_state, &edge, false).await?;
let id = exec_state.next_uuid(); let id = exec_state.next_uuid();
let tagged_path = args.get_tag_engine_info(exec_state, &tag)?; let tagged_path = args.get_tag_engine_info(exec_state, &edge)?;
let resp = args let resp = args
.send_modeling_cmd( .send_modeling_cmd(
@ -88,9 +97,9 @@ async fn inner_get_opposite_edge(tag: TagIdentifier, exec_state: &mut ExecState,
/// Get the next adjacent edge to the edge given. /// Get the next adjacent edge to the edge given.
pub async fn get_next_adjacent_edge(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> { pub async fn get_next_adjacent_edge(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let tag: TagIdentifier = args.get_data()?; let input_edge = args.get_unlabeled_kw_arg_typed("edge", &RuntimeType::edge(), exec_state)?;
let edge = inner_get_next_adjacent_edge(tag, exec_state, args.clone()).await?; let edge = inner_get_next_adjacent_edge(input_edge, exec_state, args.clone()).await?;
Ok(KclValue::Uuid { Ok(KclValue::Uuid {
value: edge, value: edge,
meta: vec![args.source_range.into()], meta: vec![args.source_range.into()],
@ -127,19 +136,24 @@ pub async fn get_next_adjacent_edge(exec_state: &mut ExecState, args: Args) -> R
/// ``` /// ```
#[stdlib { #[stdlib {
name = "getNextAdjacentEdge", name = "getNextAdjacentEdge",
keywords = true,
unlabeled_first = true,
args = {
edge = { docs = "The tag of the edge you want to find the next adjacent edge of." },
}
}] }]
async fn inner_get_next_adjacent_edge( async fn inner_get_next_adjacent_edge(
tag: TagIdentifier, edge: TagIdentifier,
exec_state: &mut ExecState, exec_state: &mut ExecState,
args: Args, args: Args,
) -> Result<Uuid, KclError> { ) -> Result<Uuid, KclError> {
if args.ctx.no_engine_commands().await { if args.ctx.no_engine_commands().await {
return Ok(exec_state.next_uuid()); return Ok(exec_state.next_uuid());
} }
let face_id = args.get_adjacent_face_to_tag(exec_state, &tag, false).await?; let face_id = args.get_adjacent_face_to_tag(exec_state, &edge, false).await?;
let id = exec_state.next_uuid(); let id = exec_state.next_uuid();
let tagged_path = args.get_tag_engine_info(exec_state, &tag)?; let tagged_path = args.get_tag_engine_info(exec_state, &edge)?;
let resp = args let resp = args
.send_modeling_cmd( .send_modeling_cmd(
@ -167,7 +181,7 @@ async fn inner_get_next_adjacent_edge(
adjacent_edge.edge.ok_or_else(|| { adjacent_edge.edge.ok_or_else(|| {
KclError::Type(KclErrorDetails { KclError::Type(KclErrorDetails {
message: format!("No edge found next adjacent to tag: `{}`", tag.value), message: format!("No edge found next adjacent to tag: `{}`", edge.value),
source_ranges: vec![args.source_range], source_ranges: vec![args.source_range],
}) })
}) })
@ -175,9 +189,9 @@ async fn inner_get_next_adjacent_edge(
/// Get the previous adjacent edge to the edge given. /// Get the previous adjacent edge to the edge given.
pub async fn get_previous_adjacent_edge(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> { pub async fn get_previous_adjacent_edge(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let tag: TagIdentifier = args.get_data()?; let input_edge = args.get_unlabeled_kw_arg_typed("edge", &RuntimeType::edge(), exec_state)?;
let edge = inner_get_previous_adjacent_edge(tag, exec_state, args.clone()).await?; let edge = inner_get_previous_adjacent_edge(input_edge, exec_state, args.clone()).await?;
Ok(KclValue::Uuid { Ok(KclValue::Uuid {
value: edge, value: edge,
meta: vec![args.source_range.into()], meta: vec![args.source_range.into()],
@ -214,19 +228,24 @@ pub async fn get_previous_adjacent_edge(exec_state: &mut ExecState, args: Args)
/// ``` /// ```
#[stdlib { #[stdlib {
name = "getPreviousAdjacentEdge", name = "getPreviousAdjacentEdge",
keywords = true,
unlabeled_first = true,
args = {
edge = { docs = "The tag of the edge you want to find the previous adjacent edge of." },
}
}] }]
async fn inner_get_previous_adjacent_edge( async fn inner_get_previous_adjacent_edge(
tag: TagIdentifier, edge: TagIdentifier,
exec_state: &mut ExecState, exec_state: &mut ExecState,
args: Args, args: Args,
) -> Result<Uuid, KclError> { ) -> Result<Uuid, KclError> {
if args.ctx.no_engine_commands().await { if args.ctx.no_engine_commands().await {
return Ok(exec_state.next_uuid()); return Ok(exec_state.next_uuid());
} }
let face_id = args.get_adjacent_face_to_tag(exec_state, &tag, false).await?; let face_id = args.get_adjacent_face_to_tag(exec_state, &edge, false).await?;
let id = exec_state.next_uuid(); let id = exec_state.next_uuid();
let tagged_path = args.get_tag_engine_info(exec_state, &tag)?; let tagged_path = args.get_tag_engine_info(exec_state, &edge)?;
let resp = args let resp = args
.send_modeling_cmd( .send_modeling_cmd(
@ -253,7 +272,7 @@ async fn inner_get_previous_adjacent_edge(
adjacent_edge.edge.ok_or_else(|| { adjacent_edge.edge.ok_or_else(|| {
KclError::Type(KclErrorDetails { KclError::Type(KclErrorDetails {
message: format!("No edge found previous adjacent to tag: `{}`", tag.value), message: format!("No edge found previous adjacent to tag: `{}`", edge.value),
source_ranges: vec![args.source_range], source_ranges: vec![args.source_range],
}) })
}) })

View File

@ -471,6 +471,7 @@ pub(crate) async fn do_post_extrude<'a>(
meta: sketch.meta.clone(), meta: sketch.meta.clone(),
units: sketch.units, units: sketch.units,
height: length.to_length_units(sketch.units), height: length.to_length_units(sketch.units),
sectional,
sketch, sketch,
start_cap_id, start_cap_id,
end_cap_id, end_cap_id,

View File

@ -6,6 +6,7 @@ pub mod array;
pub mod assert; pub mod assert;
pub mod axis_or_reference; pub mod axis_or_reference;
pub mod chamfer; pub mod chamfer;
pub mod clone;
pub mod convert; pub mod convert;
pub mod csg; pub mod csg;
pub mod edge; pub mod edge;
@ -29,6 +30,7 @@ pub mod utils;
use anyhow::Result; use anyhow::Result;
pub use args::Args; pub use args::Args;
use args::TyF64;
use indexmap::IndexMap; use indexmap::IndexMap;
use kcl_derive_docs::stdlib; use kcl_derive_docs::stdlib;
use lazy_static::lazy_static; use lazy_static::lazy_static;
@ -39,7 +41,10 @@ use serde::{Deserialize, Serialize};
use crate::{ use crate::{
docs::StdLibFn, docs::StdLibFn,
errors::KclError, errors::KclError,
execution::{types::PrimitiveType, ExecState, KclValue}, execution::{
types::{NumericType, PrimitiveType, RuntimeType, UnitAngle, UnitType},
ExecState, KclValue,
},
parsing::ast::types::Name, parsing::ast::types::Name,
}; };
@ -67,8 +72,6 @@ lazy_static! {
Box::new(crate::std::segment::SegLen), Box::new(crate::std::segment::SegLen),
Box::new(crate::std::segment::SegAng), Box::new(crate::std::segment::SegAng),
Box::new(crate::std::segment::TangentToEnd), Box::new(crate::std::segment::TangentToEnd),
Box::new(crate::std::segment::AngleToMatchLengthX),
Box::new(crate::std::segment::AngleToMatchLengthY),
Box::new(crate::std::shapes::CircleThreePoint), Box::new(crate::std::shapes::CircleThreePoint),
Box::new(crate::std::shapes::Polygon), Box::new(crate::std::shapes::Polygon),
Box::new(crate::std::sketch::InvoluteCircular), Box::new(crate::std::sketch::InvoluteCircular),
@ -87,6 +90,7 @@ lazy_static! {
Box::new(crate::std::sketch::TangentialArc), Box::new(crate::std::sketch::TangentialArc),
Box::new(crate::std::sketch::BezierCurve), Box::new(crate::std::sketch::BezierCurve),
Box::new(crate::std::sketch::Hole), Box::new(crate::std::sketch::Hole),
Box::new(crate::std::clone::Clone),
Box::new(crate::std::patterns::PatternLinear2D), Box::new(crate::std::patterns::PatternLinear2D),
Box::new(crate::std::patterns::PatternLinear3D), Box::new(crate::std::patterns::PatternLinear3D),
Box::new(crate::std::patterns::PatternCircular2D), Box::new(crate::std::patterns::PatternCircular2D),
@ -107,7 +111,6 @@ lazy_static! {
Box::new(crate::std::shell::Hollow), Box::new(crate::std::shell::Hollow),
Box::new(crate::std::sweep::Sweep), Box::new(crate::std::sweep::Sweep),
Box::new(crate::std::loft::Loft), Box::new(crate::std::loft::Loft),
Box::new(crate::std::planes::OffsetPlane),
Box::new(crate::std::math::Acos), Box::new(crate::std::math::Acos),
Box::new(crate::std::math::Asin), Box::new(crate::std::math::Asin),
Box::new(crate::std::math::Atan), Box::new(crate::std::math::Atan),
@ -205,6 +208,10 @@ pub(crate) fn std_fn(path: &str, fn_name: &str) -> (crate::std::StdFn, StdFnProp
|e, a| Box::pin(crate::std::revolve::revolve(e, a)), |e, a| Box::pin(crate::std::revolve::revolve(e, a)),
StdFnProps::default("std::revolve").include_in_feature_tree(), StdFnProps::default("std::revolve").include_in_feature_tree(),
), ),
("prelude", "offsetPlane") => (
|e, a| Box::pin(crate::std::planes::offset_plane(e, a)),
StdFnProps::default("std::offsetPlane").include_in_feature_tree(),
),
_ => unreachable!(), _ => unreachable!(),
} }
} }
@ -284,8 +291,10 @@ pub enum FunctionKind {
const DEFAULT_TOLERANCE: f64 = 0.0000001; const DEFAULT_TOLERANCE: f64 = 0.0000001;
/// Compute the length of the given leg. /// Compute the length of the given leg.
pub async fn leg_length(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> { pub async fn leg_length(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let (hypotenuse, leg, ty) = args.get_hypotenuse_leg()?; let hypotenuse: TyF64 = args.get_kw_arg_typed("hypotenuse", &RuntimeType::length(), exec_state)?;
let leg: TyF64 = args.get_kw_arg_typed("leg", &RuntimeType::length(), exec_state)?;
let (hypotenuse, leg, ty) = NumericType::combine_eq_coerce(hypotenuse, leg);
let result = inner_leg_length(hypotenuse, leg); let result = inner_leg_length(hypotenuse, leg);
Ok(KclValue::from_number_with_type(result, ty, vec![args.into()])) Ok(KclValue::from_number_with_type(result, ty, vec![args.into()]))
} }
@ -293,10 +302,16 @@ pub async fn leg_length(_exec_state: &mut ExecState, args: Args) -> Result<KclVa
/// Compute the length of the given leg. /// Compute the length of the given leg.
/// ///
/// ```no_run /// ```no_run
/// legLen(5, 3) /// legLen(hypotenuse = 5, leg = 3)
/// ``` /// ```
#[stdlib { #[stdlib {
name = "legLen", name = "legLen",
keywords = true,
unlabeled_first = false,
args = {
hypotenuse = { docs = "The length of the triangle's hypotenuse" },
leg = { docs = "The length of one of the triangle's legs (i.e. non-hypotenuse side)" },
},
tags = ["utilities"], tags = ["utilities"],
}] }]
fn inner_leg_length(hypotenuse: f64, leg: f64) -> f64 { fn inner_leg_length(hypotenuse: f64, leg: f64) -> f64 {
@ -304,19 +319,31 @@ fn inner_leg_length(hypotenuse: f64, leg: f64) -> f64 {
} }
/// Compute the angle of the given leg for x. /// Compute the angle of the given leg for x.
pub async fn leg_angle_x(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> { pub async fn leg_angle_x(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let (hypotenuse, leg, ty) = args.get_hypotenuse_leg()?; let hypotenuse: TyF64 = args.get_kw_arg_typed("hypotenuse", &RuntimeType::length(), exec_state)?;
let leg: TyF64 = args.get_kw_arg_typed("leg", &RuntimeType::length(), exec_state)?;
let (hypotenuse, leg, _ty) = NumericType::combine_eq_coerce(hypotenuse, leg);
let result = inner_leg_angle_x(hypotenuse, leg); let result = inner_leg_angle_x(hypotenuse, leg);
Ok(KclValue::from_number_with_type(result, ty, vec![args.into()])) Ok(KclValue::from_number_with_type(
result,
NumericType::Known(UnitType::Angle(UnitAngle::Degrees)),
vec![args.into()],
))
} }
/// Compute the angle of the given leg for x. /// Compute the angle of the given leg for x.
/// ///
/// ```no_run /// ```no_run
/// legAngX(5, 3) /// legAngX(hypotenuse = 5, leg = 3)
/// ``` /// ```
#[stdlib { #[stdlib {
name = "legAngX", name = "legAngX",
keywords = true,
unlabeled_first = false,
args = {
hypotenuse = { docs = "The length of the triangle's hypotenuse" },
leg = { docs = "The length of one of the triangle's legs (i.e. non-hypotenuse side)" },
},
tags = ["utilities"], tags = ["utilities"],
}] }]
fn inner_leg_angle_x(hypotenuse: f64, leg: f64) -> f64 { fn inner_leg_angle_x(hypotenuse: f64, leg: f64) -> f64 {
@ -324,19 +351,31 @@ fn inner_leg_angle_x(hypotenuse: f64, leg: f64) -> f64 {
} }
/// Compute the angle of the given leg for y. /// Compute the angle of the given leg for y.
pub async fn leg_angle_y(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> { pub async fn leg_angle_y(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let (hypotenuse, leg, ty) = args.get_hypotenuse_leg()?; let hypotenuse: TyF64 = args.get_kw_arg_typed("hypotenuse", &RuntimeType::length(), exec_state)?;
let leg: TyF64 = args.get_kw_arg_typed("leg", &RuntimeType::length(), exec_state)?;
let (hypotenuse, leg, _ty) = NumericType::combine_eq_coerce(hypotenuse, leg);
let result = inner_leg_angle_y(hypotenuse, leg); let result = inner_leg_angle_y(hypotenuse, leg);
Ok(KclValue::from_number_with_type(result, ty, vec![args.into()])) Ok(KclValue::from_number_with_type(
result,
NumericType::Known(UnitType::Angle(UnitAngle::Degrees)),
vec![args.into()],
))
} }
/// Compute the angle of the given leg for y. /// Compute the angle of the given leg for y.
/// ///
/// ```no_run /// ```no_run
/// legAngY(5, 3) /// legAngY(hypotenuse = 5, leg = 3)
/// ``` /// ```
#[stdlib { #[stdlib {
name = "legAngY", name = "legAngY",
keywords = true,
unlabeled_first = false,
args = {
hypotenuse = { docs = "The length of the triangle's hypotenuse" },
leg = { docs = "The length of one of the triangle's legs (i.e. non-hypotenuse side)" },
},
tags = ["utilities"], tags = ["utilities"],
}] }]
fn inner_leg_angle_y(hypotenuse: f64, leg: f64) -> f64 { fn inner_leg_angle_y(hypotenuse: f64, leg: f64) -> f64 {

View File

@ -1,6 +1,5 @@
//! Standard library plane helpers. //! Standard library plane helpers.
use kcl_derive_docs::stdlib;
use kcmc::{each_cmd as mcmd, length_unit::LengthUnit, shared::Color, ModelingCmd}; use kcmc::{each_cmd as mcmd, length_unit::LengthUnit, shared::Color, ModelingCmd};
use kittycad_modeling_cmds as kcmc; use kittycad_modeling_cmds as kcmc;
@ -19,98 +18,6 @@ pub async fn offset_plane(exec_state: &mut ExecState, args: Args) -> Result<KclV
Ok(KclValue::Plane { value: Box::new(plane) }) Ok(KclValue::Plane { value: Box::new(plane) })
} }
/// Offset a plane by a distance along its normal.
///
/// For example, if you offset the 'XZ' plane by 10, the new plane will be parallel to the 'XZ'
/// plane and 10 units away from it.
///
/// ```no_run
/// // Loft a square and a circle on the `XY` plane using offset.
/// squareSketch = startSketchOn('XY')
/// |> startProfileAt([-100, 200], %)
/// |> line(end = [200, 0])
/// |> line(end = [0, -200])
/// |> line(end = [-200, 0])
/// |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
/// |> close()
///
/// circleSketch = startSketchOn(offsetPlane('XY', offset = 150))
/// |> circle( center = [0, 100], radius = 50 )
///
/// loft([squareSketch, circleSketch])
/// ```
///
/// ```no_run
/// // Loft a square and a circle on the `XZ` plane using offset.
/// squareSketch = startSketchOn('XZ')
/// |> startProfileAt([-100, 200], %)
/// |> line(end = [200, 0])
/// |> line(end = [0, -200])
/// |> line(end = [-200, 0])
/// |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
/// |> close()
///
/// circleSketch = startSketchOn(offsetPlane('XZ', offset = 150))
/// |> circle( center = [0, 100], radius = 50 )
///
/// loft([squareSketch, circleSketch])
/// ```
///
/// ```no_run
/// // Loft a square and a circle on the `YZ` plane using offset.
/// squareSketch = startSketchOn('YZ')
/// |> startProfileAt([-100, 200], %)
/// |> line(end = [200, 0])
/// |> line(end = [0, -200])
/// |> line(end = [-200, 0])
/// |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
/// |> close()
///
/// circleSketch = startSketchOn(offsetPlane('YZ', offset = 150))
/// |> circle( center = [0, 100], radius = 50 )
///
/// loft([squareSketch, circleSketch])
/// ```
///
/// ```no_run
/// // Loft a square and a circle on the `-XZ` plane using offset.
/// squareSketch = startSketchOn('-XZ')
/// |> startProfileAt([-100, 200], %)
/// |> line(end = [200, 0])
/// |> line(end = [0, -200])
/// |> line(end = [-200, 0])
/// |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
/// |> close()
///
/// circleSketch = startSketchOn(offsetPlane('-XZ', offset = -150))
/// |> circle( center = [0, 100], radius = 50 )
///
/// loft([squareSketch, circleSketch])
/// ```
/// ```no_run
/// // A circle on the XY plane
/// startSketchOn("XY")
/// |> startProfileAt([0, 0], %)
/// |> circle( radius = 10, center = [0, 0] )
///
/// // Triangle on the plane 4 units above
/// startSketchOn(offsetPlane("XY", offset = 4))
/// |> startProfileAt([0, 0], %)
/// |> line(end = [10, 0])
/// |> line(end = [0, 10])
/// |> close()
/// ```
#[stdlib {
name = "offsetPlane",
feature_tree_operation = true,
keywords = true,
unlabeled_first = true,
args = {
plane = { docs = "The plane (e.g. XY) which this new plane is created from." },
offset = { docs = "Distance from the standard plane this new plane will be created at." },
}
}]
async fn inner_offset_plane( async fn inner_offset_plane(
plane: PlaneData, plane: PlaneData,
offset: TyF64, offset: TyF64,
@ -122,7 +29,8 @@ async fn inner_offset_plane(
// standard planes themselves. // standard planes themselves.
plane.value = PlaneType::Custom; plane.value = PlaneType::Custom;
plane.origin += plane.z_axis * offset.to_length_units(plane.origin.units); let normal = plane.x_axis.cross(&plane.y_axis);
plane.origin += normal * offset.to_length_units(plane.origin.units);
make_offset_plane_in_engine(&plane, exec_state, args).await?; make_offset_plane_in_engine(&plane, exec_state, args).await?;
Ok(plane) Ok(plane)

View File

@ -4,6 +4,7 @@ use anyhow::Result;
use kcl_derive_docs::stdlib; use kcl_derive_docs::stdlib;
use kittycad_modeling_cmds::shared::Angle; use kittycad_modeling_cmds::shared::Angle;
use super::utils::untype_point;
use crate::{ use crate::{
errors::{KclError, KclErrorDetails}, errors::{KclError, KclErrorDetails},
execution::{ execution::{
@ -13,8 +14,6 @@ use crate::{
std::{args::TyF64, utils::between, Args}, std::{args::TyF64, utils::between, Args},
}; };
use super::utils::untype_point;
/// Returns the point at the end of the given segment. /// Returns the point at the end of the given segment.
pub async fn segment_end(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> { pub async fn segment_end(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let tag: TagIdentifier = args.get_unlabeled_kw_arg("tag")?; let tag: TagIdentifier = args.get_unlabeled_kw_arg("tag")?;
@ -580,130 +579,3 @@ async fn inner_tangent_to_end(tag: &TagIdentifier, exec_state: &mut ExecState, a
Ok(previous_end_tangent.to_degrees()) Ok(previous_end_tangent.to_degrees())
} }
/// Returns the angle to match the given length for x.
pub async fn angle_to_match_length_x(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let (tag, to, sketch) = args.get_tag_to_number_sketch()?;
let result = inner_angle_to_match_length_x(&tag, to, sketch, exec_state, args.clone())?;
Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, NumericType::degrees())))
}
/// Returns the angle to match the given length for x.
///
/// ```no_run
/// sketch001 = startSketchOn('XZ')
/// |> startProfileAt([0, 0], %)
/// |> line(end = [2, 5], tag = $seg01)
/// |> angledLine(
/// angle = -angleToMatchLengthX(seg01, 7, %),
/// endAbsoluteX = 10,
/// )
/// |> close()
///
/// extrusion = extrude(sketch001, length = 5)
/// ```
#[stdlib {
name = "angleToMatchLengthX",
}]
fn inner_angle_to_match_length_x(
tag: &TagIdentifier,
to: TyF64,
sketch: Sketch,
exec_state: &mut ExecState,
args: Args,
) -> Result<f64, KclError> {
let line = args.get_tag_engine_info(exec_state, tag)?;
let path = line.path.clone().ok_or_else(|| {
KclError::Type(KclErrorDetails {
message: format!("Expected a line segment with a path, found `{:?}`", line),
source_ranges: vec![args.source_range],
})
})?;
let length = path.length().n;
let last_line = sketch
.paths
.last()
.ok_or_else(|| {
KclError::Type(KclErrorDetails {
message: format!("Expected a Sketch with at least one segment, found `{:?}`", sketch),
source_ranges: vec![args.source_range],
})
})?
.get_base();
let diff = (to.to_length_units(sketch.units) - last_line.to[0]).abs();
let angle_r = (diff / length).acos();
if diff > length {
Ok(0.0)
} else {
Ok(angle_r.to_degrees())
}
}
/// Returns the angle to match the given length for y.
pub async fn angle_to_match_length_y(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let (tag, to, sketch) = args.get_tag_to_number_sketch()?;
let result = inner_angle_to_match_length_y(&tag, to, sketch, exec_state, args.clone())?;
Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, NumericType::degrees())))
}
/// Returns the angle to match the given length for y.
///
/// ```no_run
/// sketch001 = startSketchOn('XZ')
/// |> startProfileAt([0, 0], %)
/// |> line(end = [1, 2], tag = $seg01)
/// |> angledLine(
/// angle = angleToMatchLengthY(seg01, 15, %),
/// length = 5,
/// )
/// |> yLine(endAbsolute = 0)
/// |> close()
///
/// extrusion = extrude(sketch001, length = 5)
/// ```
#[stdlib {
name = "angleToMatchLengthY",
}]
fn inner_angle_to_match_length_y(
tag: &TagIdentifier,
to: TyF64,
sketch: Sketch,
exec_state: &mut ExecState,
args: Args,
) -> Result<f64, KclError> {
let line = args.get_tag_engine_info(exec_state, tag)?;
let path = line.path.clone().ok_or_else(|| {
KclError::Type(KclErrorDetails {
message: format!("Expected a line segment with a path, found `{:?}`", line),
source_ranges: vec![args.source_range],
})
})?;
let length = path.length().n;
let last_line = sketch
.paths
.last()
.ok_or_else(|| {
KclError::Type(KclErrorDetails {
message: format!("Expected a Sketch with at least one segment, found `{:?}`", sketch),
source_ranges: vec![args.source_range],
})
})?
.get_base();
let diff = (to.to_length_units(sketch.units) - last_line.to[1]).abs();
let angle_r = (diff / length).asin();
if diff > length {
Ok(0.0)
} else {
Ok(angle_r.to_degrees())
}
}

View File

@ -960,9 +960,6 @@ pub enum PlaneData {
/// What should the planes Y axis be? /// What should the planes Y axis be?
#[serde(rename = "yAxis")] #[serde(rename = "yAxis")]
y_axis: Point3d, y_axis: Point3d,
/// The z-axis (normal).
#[serde(rename = "zAxis")]
z_axis: Point3d,
}, },
} }
@ -1229,7 +1226,6 @@ async fn start_sketch_on_face(
// TODO: get this from the extrude plane data. // TODO: get this from the extrude plane data.
x_axis: solid.sketch.on.x_axis(), x_axis: solid.sketch.on.x_axis(),
y_axis: solid.sketch.on.y_axis(), y_axis: solid.sketch.on.y_axis(),
z_axis: solid.sketch.on.z_axis(),
units: solid.units, units: solid.units,
solid, solid,
meta: vec![args.source_range.into()], meta: vec![args.source_range.into()],
@ -1247,49 +1243,18 @@ async fn make_sketch_plane_from_orientation(
let clobber = false; let clobber = false;
let size = LengthUnit(60.0); let size = LengthUnit(60.0);
let hide = Some(true); let hide = Some(true);
match data { args.batch_modeling_cmd(
PlaneData::XY | PlaneData::NegXY | PlaneData::XZ | PlaneData::NegXZ | PlaneData::YZ | PlaneData::NegYZ => { plane.id,
// TODO: ignoring the default planes here since we already created them, breaks the ModelingCmd::from(mcmd::MakePlane {
// front end for the feature tree which is stupid and we should fix it. clobber,
let x_axis = match data { origin: plane.origin.into(),
PlaneData::NegXY => Point3d::new(-1.0, 0.0, 0.0, UnitLen::Mm), size,
PlaneData::NegXZ => Point3d::new(-1.0, 0.0, 0.0, UnitLen::Mm), x_axis: plane.x_axis.into(),
PlaneData::NegYZ => Point3d::new(0.0, -1.0, 0.0, UnitLen::Mm), y_axis: plane.y_axis.into(),
_ => plane.x_axis, hide,
}; }),
args.batch_modeling_cmd( )
plane.id, .await?;
ModelingCmd::from(mcmd::MakePlane {
clobber,
origin: plane.origin.into(),
size,
x_axis: x_axis.into(),
y_axis: plane.y_axis.into(),
hide,
}),
)
.await?;
}
PlaneData::Plane {
origin,
x_axis,
y_axis,
z_axis: _,
} => {
args.batch_modeling_cmd(
plane.id,
ModelingCmd::from(mcmd::MakePlane {
clobber,
origin: origin.into(),
size,
x_axis: x_axis.into(),
y_axis: y_axis.into(),
hide,
}),
)
.await?;
}
}
Ok(Box::new(plane)) Ok(Box::new(plane))
} }
@ -1384,7 +1349,8 @@ pub(crate) async fn inner_start_profile_at(
adjust_camera: false, adjust_camera: false,
planar_normal: if let SketchSurface::Plane(plane) = &sketch_surface { planar_normal: if let SketchSurface::Plane(plane) = &sketch_surface {
// We pass in the normal for the plane here. // We pass in the normal for the plane here.
Some(plane.z_axis.into()) let normal = plane.x_axis.cross(&plane.y_axis);
Some(normal.into())
} else { } else {
None None
}, },

View File

@ -2219,8 +2219,8 @@ myAng2 = 134
part001 = startSketchOn(XY) part001 = startSketchOn(XY)
|> startProfileAt([0, 0], %) |> startProfileAt([0, 0], %)
|> line([1, 3.82], %, $seg01) // ln-should-get-tag |> line([1, 3.82], %, $seg01) // ln-should-get-tag
|> angledLine(angle = -angleToMatchLengthX(seg01, myVar, %), length = myVar) // ln-lineTo-xAbsolute should use angleToMatchLengthX helper |> angledLine(angle = -foo(seg01, myVar, %), length = myVar) // ln-lineTo-xAbsolute should use angleToMatchLengthX helper
|> angledLine(angle = -angleToMatchLengthY(seg01, myVar, %), length = myVar) // ln-lineTo-yAbsolute should use angleToMatchLengthY helper"#; |> angledLine(angle = -bar(seg01, myVar, %), length = myVar) // ln-lineTo-yAbsolute should use angleToMatchLengthY helper"#;
let program = crate::parsing::top_level_parse(some_program_string).unwrap(); let program = crate::parsing::top_level_parse(some_program_string).unwrap();
let recasted = program.recast(&Default::default(), 0); let recasted = program.recast(&Default::default(), 0);
@ -2237,8 +2237,8 @@ myAng2 = 134
part001 = startSketchOn(XY) part001 = startSketchOn(XY)
|> startProfileAt([0, 0], %) |> startProfileAt([0, 0], %)
|> line([1, 3.82], %, $seg01) // ln-should-get-tag |> line([1, 3.82], %, $seg01) // ln-should-get-tag
|> angledLine(angle = -angleToMatchLengthX(seg01, myVar, %), length = myVar) // ln-lineTo-xAbsolute should use angleToMatchLengthX helper |> angledLine(angle = -foo(seg01, myVar, %), length = myVar) // ln-lineTo-xAbsolute should use angleToMatchLengthX helper
|> angledLine(angle = -angleToMatchLengthY(seg01, myVar, %), length = myVar) // ln-lineTo-yAbsolute should use angleToMatchLengthY helper |> angledLine(angle = -bar(seg01, myVar, %), length = myVar) // ln-lineTo-yAbsolute should use angleToMatchLengthY helper
"#; "#;
let program = crate::parsing::top_level_parse(some_program_string).unwrap(); let program = crate::parsing::top_level_parse(some_program_string).unwrap();

View File

@ -12,21 +12,18 @@ export XY = {
origin = { x = 0, y = 0, z = 0 }, origin = { x = 0, y = 0, z = 0 },
xAxis = { x = 1, y = 0, z = 0 }, xAxis = { x = 1, y = 0, z = 0 },
yAxis = { x = 0, y = 1, z = 0 }, yAxis = { x = 0, y = 1, z = 0 },
zAxis = { x = 0, y = 0, z = 1 },
}: Plane }: Plane
export XZ = { export XZ = {
origin = { x = 0, y = 0, z = 0 }, origin = { x = 0, y = 0, z = 0 },
xAxis = { x = 1, y = 0, z = 0 }, xAxis = { x = 1, y = 0, z = 0 },
yAxis = { x = 0, y = 0, z = 1 }, yAxis = { x = 0, y = 0, z = 1 },
zAxis = { x = 0, y = -1, z = 0 },
}: Plane }: Plane
export YZ = { export YZ = {
origin = { x = 0, y = 0, z = 0 }, origin = { x = 0, y = 0, z = 0 },
xAxis = { x = 0, y = 1, z = 0 }, xAxis = { x = 0, y = 1, z = 0 },
yAxis = { x = 0, y = 0, z = 1 }, yAxis = { x = 0, y = 0, z = 1 },
zAxis = { x = 1, y = 0, z = 0 },
}: Plane }: Plane
export X = { export X = {
@ -449,3 +446,93 @@ export fn toRadians(@num: number(rad)): number(rad) {
export fn toDegrees(@num: number(deg)): number(deg) { export fn toDegrees(@num: number(deg)): number(deg) {
return num return num
} }
/// Offset a plane by a distance along its normal.
///
/// For example, if you offset the `XZ` plane by 10, the new plane will be parallel to the `XZ`
/// plane and 10 units away from it.
///
/// ```
/// // Loft a square and a circle on the `XY` plane using offset.
/// squareSketch = startSketchOn(XY)
/// |> startProfileAt([-100, 200], %)
/// |> line(end = [200, 0])
/// |> line(end = [0, -200])
/// |> line(end = [-200, 0])
/// |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
/// |> close()
///
/// circleSketch = startSketchOn(offsetPlane(XY, offset = 150))
/// |> circle( center = [0, 100], radius = 50 )
///
/// loft([squareSketch, circleSketch])
/// ```
///
/// ```
/// // Loft a square and a circle on the `XZ` plane using offset.
/// squareSketch = startSketchOn(XZ)
/// |> startProfileAt([-100, 200], %)
/// |> line(end = [200, 0])
/// |> line(end = [0, -200])
/// |> line(end = [-200, 0])
/// |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
/// |> close()
///
/// circleSketch = startSketchOn(offsetPlane(XZ, offset = 150))
/// |> circle( center = [0, 100], radius = 50 )
///
/// loft([squareSketch, circleSketch])
/// ```
///
/// ```
/// // Loft a square and a circle on the `YZ` plane using offset.
/// squareSketch = startSketchOn(YZ)
/// |> startProfileAt([-100, 200], %)
/// |> line(end = [200, 0])
/// |> line(end = [0, -200])
/// |> line(end = [-200, 0])
/// |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
/// |> close()
///
/// circleSketch = startSketchOn(offsetPlane(YZ, offset = 150))
/// |> circle( center = [0, 100], radius = 50 )
///
/// loft([squareSketch, circleSketch])
/// ```
///
/// ```
/// // Loft a square and a circle on the `-XZ` plane using offset.
/// squareSketch = startSketchOn(-XZ)
/// |> startProfileAt([-100, 200], %)
/// |> line(end = [200, 0])
/// |> line(end = [0, -200])
/// |> line(end = [-200, 0])
/// |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
/// |> close()
///
/// circleSketch = startSketchOn(offsetPlane(-XZ, offset = 150))
/// |> circle(center = [0, 100], radius = 50)
///
/// loft([squareSketch, circleSketch])
/// ```
///
/// ```
/// // A circle on the XY plane
/// startSketchOn(XY)
/// |> startProfileAt([0, 0], %)
/// |> circle( radius = 10, center = [0, 0] )
///
/// // Triangle on the plane 4 units above
/// startSketchOn(offsetPlane(XY, offset = 4))
/// |> startProfileAt([0, 0], %)
/// |> line(end = [10, 0])
/// |> line(end = [0, 10])
/// |> close()
/// ```
@(impl = std_rust)
export fn offsetPlane(
/// The plane (e.g. `XY`) which this new plane is created from.
@plane: Plane,
/// Distance from the standard plane this new plane will be created at.
offset: number(Length),
): Plane {}

View File

@ -212,14 +212,6 @@ description: Variables in memory after executing angled_line.kcl
"units": { "units": {
"type": "Mm" "type": "Mm"
} }
},
"zAxis": {
"x": 0.0,
"y": 0.0,
"z": 1.0,
"units": {
"type": "Mm"
}
} }
}, },
"start": { "start": {
@ -257,7 +249,8 @@ description: Variables in memory after executing angled_line.kcl
"endCapId": "[uuid]", "endCapId": "[uuid]",
"units": { "units": {
"type": "Mm" "type": "Mm"
} },
"sectional": false
} }
}, },
"seg01": { "seg01": {

View File

@ -191,14 +191,6 @@ description: Variables in memory after executing artifact_graph_example_code1.kc
"units": { "units": {
"type": "Mm" "type": "Mm"
} }
},
"zAxis": {
"x": 0.0,
"y": 0.0,
"z": 1.0,
"units": {
"type": "Mm"
}
} }
}, },
"start": { "start": {
@ -260,7 +252,8 @@ description: Variables in memory after executing artifact_graph_example_code1.kc
], ],
"units": { "units": {
"type": "Mm" "type": "Mm"
} },
"sectional": false
} }
}, },
"extrude002": { "extrude002": {
@ -394,14 +387,6 @@ description: Variables in memory after executing artifact_graph_example_code1.kc
"type": "Mm" "type": "Mm"
} }
}, },
"zAxis": {
"x": 0.0,
"y": 0.0,
"z": 1.0,
"units": {
"type": "Mm"
}
},
"solid": { "solid": {
"type": "Solid", "type": "Solid",
"id": "[uuid]", "id": "[uuid]",
@ -588,14 +573,6 @@ description: Variables in memory after executing artifact_graph_example_code1.kc
"units": { "units": {
"type": "Mm" "type": "Mm"
} }
},
"zAxis": {
"x": 0.0,
"y": 0.0,
"z": 1.0,
"units": {
"type": "Mm"
}
} }
}, },
"start": { "start": {
@ -657,7 +634,8 @@ description: Variables in memory after executing artifact_graph_example_code1.kc
], ],
"units": { "units": {
"type": "Mm" "type": "Mm"
} },
"sectional": false
}, },
"units": { "units": {
"type": "Mm" "type": "Mm"
@ -692,7 +670,8 @@ description: Variables in memory after executing artifact_graph_example_code1.kc
"endCapId": "[uuid]", "endCapId": "[uuid]",
"units": { "units": {
"type": "Mm" "type": "Mm"
} },
"sectional": false
} }
}, },
"seg01": { "seg01": {
@ -847,14 +826,6 @@ description: Variables in memory after executing artifact_graph_example_code1.kc
"units": { "units": {
"type": "Mm" "type": "Mm"
} }
},
"zAxis": {
"x": 0.0,
"y": 0.0,
"z": 1.0,
"units": {
"type": "Mm"
}
} }
}, },
"start": { "start": {
@ -996,14 +967,6 @@ description: Variables in memory after executing artifact_graph_example_code1.kc
"type": "Mm" "type": "Mm"
} }
}, },
"zAxis": {
"x": 0.0,
"y": 0.0,
"z": 1.0,
"units": {
"type": "Mm"
}
},
"solid": { "solid": {
"type": "Solid", "type": "Solid",
"id": "[uuid]", "id": "[uuid]",
@ -1190,14 +1153,6 @@ description: Variables in memory after executing artifact_graph_example_code1.kc
"units": { "units": {
"type": "Mm" "type": "Mm"
} }
},
"zAxis": {
"x": 0.0,
"y": 0.0,
"z": 1.0,
"units": {
"type": "Mm"
}
} }
}, },
"start": { "start": {
@ -1259,7 +1214,8 @@ description: Variables in memory after executing artifact_graph_example_code1.kc
], ],
"units": { "units": {
"type": "Mm" "type": "Mm"
} },
"sectional": false
}, },
"units": { "units": {
"type": "Mm" "type": "Mm"

View File

@ -210,7 +210,7 @@ description: Artifact commands artifact_graph_example_code_no_3d.kcl
"planar_normal": { "planar_normal": {
"x": 0.0, "x": 0.0,
"y": 1.0, "y": 1.0,
"z": 0.0 "z": -0.0
} }
} }
}, },

View File

@ -166,14 +166,6 @@ description: Variables in memory after executing artifact_graph_example_code_no_
"units": { "units": {
"type": "Mm" "type": "Mm"
} }
},
"zAxis": {
"x": 1.0,
"y": 0.0,
"z": 0.0,
"units": {
"type": "Mm"
}
} }
}, },
"start": { "start": {
@ -317,14 +309,6 @@ description: Variables in memory after executing artifact_graph_example_code_no_
"units": { "units": {
"type": "Mm" "type": "Mm"
} }
},
"zAxis": {
"x": 0.0,
"y": 1.0,
"z": 0.0,
"units": {
"type": "Mm"
}
} }
}, },
"start": { "start": {

View File

@ -4,6 +4,15 @@ description: Operations executed artifact_graph_example_code_offset_planes.kcl
--- ---
[ [
{ {
"type": "KclStdLibCall",
"name": "offsetPlane",
"unlabeledArg": {
"value": {
"type": "String",
"value": "XY"
},
"sourceRange": []
},
"labeledArgs": { "labeledArgs": {
"offset": { "offset": {
"value": { "value": {
@ -22,18 +31,18 @@ description: Operations executed artifact_graph_example_code_offset_planes.kcl
"sourceRange": [] "sourceRange": []
} }
}, },
"sourceRange": []
},
{
"type": "KclStdLibCall",
"name": "offsetPlane", "name": "offsetPlane",
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": { "unlabeledArg": {
"value": { "value": {
"type": "String", "type": "String",
"value": "XY" "value": "XZ"
}, },
"sourceRange": [] "sourceRange": []
} },
},
{
"labeledArgs": { "labeledArgs": {
"offset": { "offset": {
"value": { "value": {
@ -52,18 +61,18 @@ description: Operations executed artifact_graph_example_code_offset_planes.kcl
"sourceRange": [] "sourceRange": []
} }
}, },
"sourceRange": []
},
{
"type": "KclStdLibCall",
"name": "offsetPlane", "name": "offsetPlane",
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": { "unlabeledArg": {
"value": { "value": {
"type": "String", "type": "String",
"value": "XZ" "value": "YZ"
}, },
"sourceRange": [] "sourceRange": []
} },
},
{
"labeledArgs": { "labeledArgs": {
"offset": { "offset": {
"value": { "value": {
@ -82,16 +91,7 @@ description: Operations executed artifact_graph_example_code_offset_planes.kcl
"sourceRange": [] "sourceRange": []
} }
}, },
"name": "offsetPlane", "sourceRange": []
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": {
"value": {
"type": "String",
"value": "YZ"
},
"sourceRange": []
}
}, },
{ {
"labeledArgs": { "labeledArgs": {

View File

@ -32,14 +32,6 @@ description: Variables in memory after executing artifact_graph_example_code_off
"units": { "units": {
"type": "Mm" "type": "Mm"
} }
},
"zAxis": {
"x": 0.0,
"y": 0.0,
"z": 1.0,
"units": {
"type": "Mm"
}
} }
} }
}, },
@ -72,14 +64,6 @@ description: Variables in memory after executing artifact_graph_example_code_off
"units": { "units": {
"type": "Mm" "type": "Mm"
} }
},
"zAxis": {
"x": 0.0,
"y": -1.0,
"z": 0.0,
"units": {
"type": "Mm"
}
} }
} }
}, },
@ -112,14 +96,6 @@ description: Variables in memory after executing artifact_graph_example_code_off
"units": { "units": {
"type": "Mm" "type": "Mm"
} }
},
"zAxis": {
"x": 1.0,
"y": 0.0,
"z": 0.0,
"units": {
"type": "Mm"
}
} }
} }
}, },
@ -177,14 +153,6 @@ description: Variables in memory after executing artifact_graph_example_code_off
"units": { "units": {
"type": "Mm" "type": "Mm"
} }
},
"zAxis": {
"x": 0.0,
"y": 0.0,
"z": 1.0,
"units": {
"type": "Mm"
}
} }
}, },
"start": { "start": {

View File

@ -153,14 +153,6 @@ description: Variables in memory after executing artifact_graph_sketch_on_face_e
"units": { "units": {
"type": "Mm" "type": "Mm"
} }
},
"zAxis": {
"x": 0.0,
"y": -1.0,
"z": 0.0,
"units": {
"type": "Mm"
}
} }
}, },
"start": { "start": {
@ -198,7 +190,8 @@ description: Variables in memory after executing artifact_graph_sketch_on_face_e
"endCapId": "[uuid]", "endCapId": "[uuid]",
"units": { "units": {
"type": "Mm" "type": "Mm"
} },
"sectional": false
} }
}, },
"extrude002": { "extrude002": {
@ -332,14 +325,6 @@ description: Variables in memory after executing artifact_graph_sketch_on_face_e
"type": "Mm" "type": "Mm"
} }
}, },
"zAxis": {
"x": 0.0,
"y": -1.0,
"z": 0.0,
"units": {
"type": "Mm"
}
},
"solid": { "solid": {
"type": "Solid", "type": "Solid",
"id": "[uuid]", "id": "[uuid]",
@ -488,14 +473,6 @@ description: Variables in memory after executing artifact_graph_sketch_on_face_e
"units": { "units": {
"type": "Mm" "type": "Mm"
} }
},
"zAxis": {
"x": 0.0,
"y": -1.0,
"z": 0.0,
"units": {
"type": "Mm"
}
} }
}, },
"start": { "start": {
@ -533,7 +510,8 @@ description: Variables in memory after executing artifact_graph_sketch_on_face_e
"endCapId": "[uuid]", "endCapId": "[uuid]",
"units": { "units": {
"type": "Mm" "type": "Mm"
} },
"sectional": false
}, },
"units": { "units": {
"type": "Mm" "type": "Mm"
@ -568,7 +546,8 @@ description: Variables in memory after executing artifact_graph_sketch_on_face_e
"endCapId": "[uuid]", "endCapId": "[uuid]",
"units": { "units": {
"type": "Mm" "type": "Mm"
} },
"sectional": false
} }
}, },
"extrude003": { "extrude003": {
@ -714,14 +693,6 @@ description: Variables in memory after executing artifact_graph_sketch_on_face_e
"type": "Mm" "type": "Mm"
} }
}, },
"zAxis": {
"x": 0.0,
"y": -1.0,
"z": 0.0,
"units": {
"type": "Mm"
}
},
"solid": { "solid": {
"type": "Solid", "type": "Solid",
"id": "[uuid]", "id": "[uuid]",
@ -851,14 +822,6 @@ description: Variables in memory after executing artifact_graph_sketch_on_face_e
"type": "Mm" "type": "Mm"
} }
}, },
"zAxis": {
"x": 0.0,
"y": -1.0,
"z": 0.0,
"units": {
"type": "Mm"
}
},
"solid": { "solid": {
"type": "Solid", "type": "Solid",
"id": "[uuid]", "id": "[uuid]",
@ -1007,14 +970,6 @@ description: Variables in memory after executing artifact_graph_sketch_on_face_e
"units": { "units": {
"type": "Mm" "type": "Mm"
} }
},
"zAxis": {
"x": 0.0,
"y": -1.0,
"z": 0.0,
"units": {
"type": "Mm"
}
} }
}, },
"start": { "start": {
@ -1052,7 +1007,8 @@ description: Variables in memory after executing artifact_graph_sketch_on_face_e
"endCapId": "[uuid]", "endCapId": "[uuid]",
"units": { "units": {
"type": "Mm" "type": "Mm"
} },
"sectional": false
}, },
"units": { "units": {
"type": "Mm" "type": "Mm"
@ -1087,7 +1043,8 @@ description: Variables in memory after executing artifact_graph_sketch_on_face_e
"endCapId": "[uuid]", "endCapId": "[uuid]",
"units": { "units": {
"type": "Mm" "type": "Mm"
} },
"sectional": false
}, },
"units": { "units": {
"type": "Mm" "type": "Mm"
@ -1128,7 +1085,8 @@ description: Variables in memory after executing artifact_graph_sketch_on_face_e
"endCapId": "[uuid]", "endCapId": "[uuid]",
"units": { "units": {
"type": "Mm" "type": "Mm"
} },
"sectional": false
} }
}, },
"extrude004": { "extrude004": {
@ -1262,14 +1220,6 @@ description: Variables in memory after executing artifact_graph_sketch_on_face_e
"type": "Mm" "type": "Mm"
} }
}, },
"zAxis": {
"x": 0.0,
"y": -1.0,
"z": 0.0,
"units": {
"type": "Mm"
}
},
"solid": { "solid": {
"type": "Solid", "type": "Solid",
"id": "[uuid]", "id": "[uuid]",
@ -1411,14 +1361,6 @@ description: Variables in memory after executing artifact_graph_sketch_on_face_e
"type": "Mm" "type": "Mm"
} }
}, },
"zAxis": {
"x": 0.0,
"y": -1.0,
"z": 0.0,
"units": {
"type": "Mm"
}
},
"solid": { "solid": {
"type": "Solid", "type": "Solid",
"id": "[uuid]", "id": "[uuid]",
@ -1548,14 +1490,6 @@ description: Variables in memory after executing artifact_graph_sketch_on_face_e
"type": "Mm" "type": "Mm"
} }
}, },
"zAxis": {
"x": 0.0,
"y": -1.0,
"z": 0.0,
"units": {
"type": "Mm"
}
},
"solid": { "solid": {
"type": "Solid", "type": "Solid",
"id": "[uuid]", "id": "[uuid]",
@ -1704,14 +1638,6 @@ description: Variables in memory after executing artifact_graph_sketch_on_face_e
"units": { "units": {
"type": "Mm" "type": "Mm"
} }
},
"zAxis": {
"x": 0.0,
"y": -1.0,
"z": 0.0,
"units": {
"type": "Mm"
}
} }
}, },
"start": { "start": {
@ -1749,7 +1675,8 @@ description: Variables in memory after executing artifact_graph_sketch_on_face_e
"endCapId": "[uuid]", "endCapId": "[uuid]",
"units": { "units": {
"type": "Mm" "type": "Mm"
} },
"sectional": false
}, },
"units": { "units": {
"type": "Mm" "type": "Mm"
@ -1784,7 +1711,8 @@ description: Variables in memory after executing artifact_graph_sketch_on_face_e
"endCapId": "[uuid]", "endCapId": "[uuid]",
"units": { "units": {
"type": "Mm" "type": "Mm"
} },
"sectional": false
}, },
"units": { "units": {
"type": "Mm" "type": "Mm"
@ -1825,7 +1753,8 @@ description: Variables in memory after executing artifact_graph_sketch_on_face_e
"endCapId": "[uuid]", "endCapId": "[uuid]",
"units": { "units": {
"type": "Mm" "type": "Mm"
} },
"sectional": false
}, },
"units": { "units": {
"type": "Mm" "type": "Mm"
@ -1860,7 +1789,8 @@ description: Variables in memory after executing artifact_graph_sketch_on_face_e
"endCapId": "[uuid]", "endCapId": "[uuid]",
"units": { "units": {
"type": "Mm" "type": "Mm"
} },
"sectional": false
} }
}, },
"seg01": { "seg01": {
@ -1990,14 +1920,6 @@ description: Variables in memory after executing artifact_graph_sketch_on_face_e
"units": { "units": {
"type": "Mm" "type": "Mm"
} }
},
"zAxis": {
"x": 0.0,
"y": -1.0,
"z": 0.0,
"units": {
"type": "Mm"
}
} }
}, },
"start": { "start": {
@ -2135,14 +2057,6 @@ description: Variables in memory after executing artifact_graph_sketch_on_face_e
"type": "Mm" "type": "Mm"
} }
}, },
"zAxis": {
"x": 0.0,
"y": -1.0,
"z": 0.0,
"units": {
"type": "Mm"
}
},
"solid": { "solid": {
"type": "Solid", "type": "Solid",
"id": "[uuid]", "id": "[uuid]",
@ -2291,14 +2205,6 @@ description: Variables in memory after executing artifact_graph_sketch_on_face_e
"units": { "units": {
"type": "Mm" "type": "Mm"
} }
},
"zAxis": {
"x": 0.0,
"y": -1.0,
"z": 0.0,
"units": {
"type": "Mm"
}
} }
}, },
"start": { "start": {
@ -2336,7 +2242,8 @@ description: Variables in memory after executing artifact_graph_sketch_on_face_e
"endCapId": "[uuid]", "endCapId": "[uuid]",
"units": { "units": {
"type": "Mm" "type": "Mm"
} },
"sectional": false
}, },
"units": { "units": {
"type": "Mm" "type": "Mm"
@ -2477,14 +2384,6 @@ description: Variables in memory after executing artifact_graph_sketch_on_face_e
"type": "Mm" "type": "Mm"
} }
}, },
"zAxis": {
"x": 0.0,
"y": -1.0,
"z": 0.0,
"units": {
"type": "Mm"
}
},
"solid": { "solid": {
"type": "Solid", "type": "Solid",
"id": "[uuid]", "id": "[uuid]",
@ -2614,14 +2513,6 @@ description: Variables in memory after executing artifact_graph_sketch_on_face_e
"type": "Mm" "type": "Mm"
} }
}, },
"zAxis": {
"x": 0.0,
"y": -1.0,
"z": 0.0,
"units": {
"type": "Mm"
}
},
"solid": { "solid": {
"type": "Solid", "type": "Solid",
"id": "[uuid]", "id": "[uuid]",
@ -2770,14 +2661,6 @@ description: Variables in memory after executing artifact_graph_sketch_on_face_e
"units": { "units": {
"type": "Mm" "type": "Mm"
} }
},
"zAxis": {
"x": 0.0,
"y": -1.0,
"z": 0.0,
"units": {
"type": "Mm"
}
} }
}, },
"start": { "start": {
@ -2815,7 +2698,8 @@ description: Variables in memory after executing artifact_graph_sketch_on_face_e
"endCapId": "[uuid]", "endCapId": "[uuid]",
"units": { "units": {
"type": "Mm" "type": "Mm"
} },
"sectional": false
}, },
"units": { "units": {
"type": "Mm" "type": "Mm"
@ -2850,7 +2734,8 @@ description: Variables in memory after executing artifact_graph_sketch_on_face_e
"endCapId": "[uuid]", "endCapId": "[uuid]",
"units": { "units": {
"type": "Mm" "type": "Mm"
} },
"sectional": false
}, },
"units": { "units": {
"type": "Mm" "type": "Mm"
@ -2991,14 +2876,6 @@ description: Variables in memory after executing artifact_graph_sketch_on_face_e
"type": "Mm" "type": "Mm"
} }
}, },
"zAxis": {
"x": 0.0,
"y": -1.0,
"z": 0.0,
"units": {
"type": "Mm"
}
},
"solid": { "solid": {
"type": "Solid", "type": "Solid",
"id": "[uuid]", "id": "[uuid]",
@ -3140,14 +3017,6 @@ description: Variables in memory after executing artifact_graph_sketch_on_face_e
"type": "Mm" "type": "Mm"
} }
}, },
"zAxis": {
"x": 0.0,
"y": -1.0,
"z": 0.0,
"units": {
"type": "Mm"
}
},
"solid": { "solid": {
"type": "Solid", "type": "Solid",
"id": "[uuid]", "id": "[uuid]",
@ -3277,14 +3146,6 @@ description: Variables in memory after executing artifact_graph_sketch_on_face_e
"type": "Mm" "type": "Mm"
} }
}, },
"zAxis": {
"x": 0.0,
"y": -1.0,
"z": 0.0,
"units": {
"type": "Mm"
}
},
"solid": { "solid": {
"type": "Solid", "type": "Solid",
"id": "[uuid]", "id": "[uuid]",
@ -3433,14 +3294,6 @@ description: Variables in memory after executing artifact_graph_sketch_on_face_e
"units": { "units": {
"type": "Mm" "type": "Mm"
} }
},
"zAxis": {
"x": 0.0,
"y": -1.0,
"z": 0.0,
"units": {
"type": "Mm"
}
} }
}, },
"start": { "start": {
@ -3478,7 +3331,8 @@ description: Variables in memory after executing artifact_graph_sketch_on_face_e
"endCapId": "[uuid]", "endCapId": "[uuid]",
"units": { "units": {
"type": "Mm" "type": "Mm"
} },
"sectional": false
}, },
"units": { "units": {
"type": "Mm" "type": "Mm"
@ -3513,7 +3367,8 @@ description: Variables in memory after executing artifact_graph_sketch_on_face_e
"endCapId": "[uuid]", "endCapId": "[uuid]",
"units": { "units": {
"type": "Mm" "type": "Mm"
} },
"sectional": false
}, },
"units": { "units": {
"type": "Mm" "type": "Mm"
@ -3554,7 +3409,8 @@ description: Variables in memory after executing artifact_graph_sketch_on_face_e
"endCapId": "[uuid]", "endCapId": "[uuid]",
"units": { "units": {
"type": "Mm" "type": "Mm"
} },
"sectional": false
}, },
"units": { "units": {
"type": "Mm" "type": "Mm"

View File

@ -184,14 +184,6 @@ description: Variables in memory after executing basic_fillet_cube_close_opposit
"units": { "units": {
"type": "Mm" "type": "Mm"
} }
},
"zAxis": {
"x": 0.0,
"y": 0.0,
"z": 1.0,
"units": {
"type": "Mm"
}
} }
}, },
"start": { "start": {
@ -275,7 +267,8 @@ description: Variables in memory after executing basic_fillet_cube_close_opposit
], ],
"units": { "units": {
"type": "Mm" "type": "Mm"
} },
"sectional": false
} }
}, },
"thing": { "thing": {

View File

@ -172,14 +172,6 @@ description: Variables in memory after executing basic_fillet_cube_end.kcl
"units": { "units": {
"type": "Mm" "type": "Mm"
} }
},
"zAxis": {
"x": 0.0,
"y": 0.0,
"z": 1.0,
"units": {
"type": "Mm"
}
} }
}, },
"start": { "start": {
@ -259,7 +251,8 @@ description: Variables in memory after executing basic_fillet_cube_end.kcl
], ],
"units": { "units": {
"type": "Mm" "type": "Mm"
} },
"sectional": false
} }
}, },
"thing": { "thing": {

View File

@ -196,14 +196,6 @@ description: Variables in memory after executing basic_fillet_cube_next_adjacent
"units": { "units": {
"type": "Mm" "type": "Mm"
} }
},
"zAxis": {
"x": 0.0,
"y": 0.0,
"z": 1.0,
"units": {
"type": "Mm"
}
} }
}, },
"start": { "start": {
@ -273,7 +265,8 @@ description: Variables in memory after executing basic_fillet_cube_next_adjacent
], ],
"units": { "units": {
"type": "Mm" "type": "Mm"
} },
"sectional": false
} }
}, },
"thing": { "thing": {

View File

@ -196,14 +196,6 @@ description: Variables in memory after executing basic_fillet_cube_previous_adja
"units": { "units": {
"type": "Mm" "type": "Mm"
} }
},
"zAxis": {
"x": 0.0,
"y": 0.0,
"z": 1.0,
"units": {
"type": "Mm"
}
} }
}, },
"start": { "start": {
@ -273,7 +265,8 @@ description: Variables in memory after executing basic_fillet_cube_previous_adja
], ],
"units": { "units": {
"type": "Mm" "type": "Mm"
} },
"sectional": false
} }
}, },
"thing": { "thing": {

View File

@ -172,14 +172,6 @@ description: Variables in memory after executing basic_fillet_cube_start.kcl
"units": { "units": {
"type": "Mm" "type": "Mm"
} }
},
"zAxis": {
"x": 0.0,
"y": 0.0,
"z": 1.0,
"units": {
"type": "Mm"
}
} }
}, },
"start": { "start": {
@ -259,7 +251,8 @@ description: Variables in memory after executing basic_fillet_cube_start.kcl
], ],
"units": { "units": {
"type": "Mm" "type": "Mm"
} },
"sectional": false
} }
}, },
"thing": { "thing": {

View File

@ -1,253 +0,0 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Artifact commands big_number_angle_to_match_length_x.kcl
---
[
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "edge_lines_visible",
"hidden": false
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "object_visible",
"object_id": "[uuid]",
"hidden": true
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "object_visible",
"object_id": "[uuid]",
"hidden": true
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "make_plane",
"origin": {
"x": 0.0,
"y": 0.0,
"z": 0.0
},
"x_axis": {
"x": 1.0,
"y": 0.0,
"z": 0.0
},
"y_axis": {
"x": 0.0,
"y": 1.0,
"z": 0.0
},
"size": 60.0,
"clobber": false,
"hide": true
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "enable_sketch_mode",
"entity_id": "[uuid]",
"ortho": false,
"animated": false,
"adjust_camera": false,
"planar_normal": {
"x": 0.0,
"y": 0.0,
"z": 1.0
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "start_path"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "move_path_pen",
"path": "[uuid]",
"to": {
"x": 0.0,
"y": 0.0,
"z": 0.0
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "sketch_mode_disable"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extend_path",
"path": "[uuid]",
"segment": {
"type": "line",
"end": {
"x": 1.0,
"y": 3.82,
"z": 0.0
},
"relative": true
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extend_path",
"path": "[uuid]",
"segment": {
"type": "line",
"end": {
"x": 3.0,
"y": 0.4152,
"z": 0.0
},
"relative": false
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "close_path",
"path_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "enable_sketch_mode",
"entity_id": "[uuid]",
"ortho": false,
"animated": false,
"adjust_camera": false,
"planar_normal": {
"x": 0.0,
"y": 0.0,
"z": 1.0
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extrude",
"target": "[uuid]",
"distance": 10.0,
"faces": null,
"opposite": "None"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "sketch_mode_disable"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "object_bring_to_front",
"object_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_extrusion_face_info",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
}
]

View File

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

View File

@ -1,49 +0,0 @@
```mermaid
flowchart LR
subgraph path2 [Path]
2["Path<br>[35, 60, 0]"]
3["Segment<br>[66, 101, 0]"]
4["Segment<br>[107, 178, 0]"]
5["Segment<br>[184, 192, 0]"]
6[Solid2d]
end
1["Plane<br>[10, 29, 0]"]
7["Sweep Extrusion<br>[198, 218, 0]"]
8[Wall]
9[Wall]
10[Wall]
11["Cap Start"]
12["Cap End"]
13["SweepEdge Opposite"]
14["SweepEdge Adjacent"]
15["SweepEdge Opposite"]
16["SweepEdge Adjacent"]
17["SweepEdge Opposite"]
18["SweepEdge Adjacent"]
1 --- 2
2 --- 3
2 --- 4
2 --- 5
2 ---- 7
2 --- 6
3 --- 10
3 --- 17
3 --- 18
4 --- 9
4 --- 15
4 --- 16
5 --- 8
5 --- 13
5 --- 14
7 --- 8
7 --- 9
7 --- 10
7 --- 11
7 --- 12
7 --- 13
7 --- 14
7 --- 15
7 --- 16
7 --- 17
7 --- 18
```

View File

@ -1,428 +0,0 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Result of parsing big_number_angle_to_match_length_x.kcl
---
{
"Ok": {
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 0,
"id": {
"commentStart": 0,
"end": 0,
"name": "part001",
"start": 0,
"type": "Identifier"
},
"init": {
"body": [
{
"arguments": [
{
"commentStart": 0,
"end": 0,
"raw": "'XY'",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": "XY"
}
],
"callee": {
"abs_path": false,
"commentStart": 0,
"end": 0,
"name": {
"commentStart": 0,
"end": 0,
"name": "startSketchOn",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Name"
},
"commentStart": 0,
"end": 0,
"start": 0,
"type": "CallExpression",
"type": "CallExpression"
},
{
"arguments": [
{
"commentStart": 0,
"elements": [
{
"commentStart": 0,
"end": 0,
"raw": "0",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 0.0,
"suffix": "None"
}
},
{
"commentStart": 0,
"end": 0,
"raw": "0",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 0.0,
"suffix": "None"
}
}
],
"end": 0,
"start": 0,
"type": "ArrayExpression",
"type": "ArrayExpression"
},
{
"commentStart": 0,
"end": 0,
"start": 0,
"type": "PipeSubstitution",
"type": "PipeSubstitution"
}
],
"callee": {
"abs_path": false,
"commentStart": 0,
"end": 0,
"name": {
"commentStart": 0,
"end": 0,
"name": "startProfileAt",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Name"
},
"commentStart": 0,
"end": 0,
"start": 0,
"type": "CallExpression",
"type": "CallExpression"
},
{
"arguments": [
{
"type": "LabeledArg",
"label": {
"commentStart": 0,
"end": 0,
"name": "end",
"start": 0,
"type": "Identifier"
},
"arg": {
"commentStart": 0,
"elements": [
{
"commentStart": 0,
"end": 0,
"raw": "1",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 1.0,
"suffix": "None"
}
},
{
"commentStart": 0,
"end": 0,
"raw": "3.82",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 3.82,
"suffix": "None"
}
}
],
"end": 0,
"start": 0,
"type": "ArrayExpression",
"type": "ArrayExpression"
}
},
{
"type": "LabeledArg",
"label": {
"commentStart": 0,
"end": 0,
"name": "tag",
"start": 0,
"type": "Identifier"
},
"arg": {
"commentStart": 0,
"end": 0,
"start": 0,
"type": "TagDeclarator",
"type": "TagDeclarator",
"value": "seg01"
}
}
],
"callee": {
"abs_path": false,
"commentStart": 0,
"end": 0,
"name": {
"commentStart": 0,
"end": 0,
"name": "line",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Name"
},
"commentStart": 0,
"end": 0,
"start": 0,
"type": "CallExpressionKw",
"type": "CallExpressionKw",
"unlabeled": null
},
{
"arguments": [
{
"type": "LabeledArg",
"label": {
"commentStart": 0,
"end": 0,
"name": "angle",
"start": 0,
"type": "Identifier"
},
"arg": {
"argument": {
"arguments": [
{
"abs_path": false,
"commentStart": 0,
"end": 0,
"name": {
"commentStart": 0,
"end": 0,
"name": "seg01",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Name",
"type": "Name"
},
{
"commentStart": 0,
"end": 0,
"raw": "3",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 3.0,
"suffix": "None"
}
},
{
"commentStart": 0,
"end": 0,
"start": 0,
"type": "PipeSubstitution",
"type": "PipeSubstitution"
}
],
"callee": {
"abs_path": false,
"commentStart": 0,
"end": 0,
"name": {
"commentStart": 0,
"end": 0,
"name": "angleToMatchLengthX",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Name"
},
"commentStart": 0,
"end": 0,
"start": 0,
"type": "CallExpression",
"type": "CallExpression"
},
"commentStart": 0,
"end": 0,
"operator": "-",
"start": 0,
"type": "UnaryExpression",
"type": "UnaryExpression"
}
},
{
"type": "LabeledArg",
"label": {
"commentStart": 0,
"end": 0,
"name": "endAbsoluteX",
"start": 0,
"type": "Identifier"
},
"arg": {
"commentStart": 0,
"end": 0,
"raw": "3",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 3.0,
"suffix": "None"
}
}
}
],
"callee": {
"abs_path": false,
"commentStart": 0,
"end": 0,
"name": {
"commentStart": 0,
"end": 0,
"name": "angledLine",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Name"
},
"commentStart": 0,
"end": 0,
"start": 0,
"type": "CallExpressionKw",
"type": "CallExpressionKw",
"unlabeled": null
},
{
"arguments": [
{
"commentStart": 0,
"end": 0,
"start": 0,
"type": "PipeSubstitution",
"type": "PipeSubstitution"
}
],
"callee": {
"abs_path": false,
"commentStart": 0,
"end": 0,
"name": {
"commentStart": 0,
"end": 0,
"name": "close",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Name"
},
"commentStart": 0,
"end": 0,
"start": 0,
"type": "CallExpression",
"type": "CallExpression"
},
{
"arguments": [
{
"type": "LabeledArg",
"label": {
"commentStart": 0,
"end": 0,
"name": "length",
"start": 0,
"type": "Identifier"
},
"arg": {
"commentStart": 0,
"end": 0,
"raw": "10",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 10.0,
"suffix": "None"
}
}
}
],
"callee": {
"abs_path": false,
"commentStart": 0,
"end": 0,
"name": {
"commentStart": 0,
"end": 0,
"name": "extrude",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Name"
},
"commentStart": 0,
"end": 0,
"start": 0,
"type": "CallExpressionKw",
"type": "CallExpressionKw",
"unlabeled": null
}
],
"commentStart": 0,
"end": 0,
"start": 0,
"type": "PipeExpression",
"type": "PipeExpression"
},
"start": 0,
"type": "VariableDeclarator"
},
"end": 0,
"kind": "const",
"start": 0,
"type": "VariableDeclaration",
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 0,
"start": 0
}
}

View File

@ -1,6 +0,0 @@
part001 = startSketchOn('XY')
|> startProfileAt([0, 0], %)
|> line(end = [1, 3.82], tag = $seg01)
|> angledLine(angle = -angleToMatchLengthX(seg01, 3, %), endAbsoluteX = 3)
|> close(%)
|> extrude(length = 10)

View File

@ -1,53 +0,0 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Operations executed big_number_angle_to_match_length_x.kcl
---
[
{
"labeledArgs": {
"planeOrSolid": {
"value": {
"type": "String",
"value": "XY"
},
"sourceRange": []
}
},
"name": "startSketchOn",
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": null
},
{
"labeledArgs": {
"length": {
"value": {
"type": "Number",
"value": 10.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"sourceRange": []
}
},
"name": "extrude",
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": {
"value": {
"type": "Sketch",
"value": {
"artifactId": "[uuid]"
}
},
"sourceRange": []
}
}
]

View File

@ -1,190 +0,0 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Variables in memory after executing big_number_angle_to_match_length_x.kcl
---
{
"part001": {
"type": "Solid",
"value": {
"type": "Solid",
"id": "[uuid]",
"artifactId": "[uuid]",
"value": [
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": {
"commentStart": 94,
"end": 100,
"start": 94,
"type": "TagDeclarator",
"value": "seg01"
},
"type": "extrudePlane"
},
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": null,
"type": "extrudePlane"
},
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": null,
"type": "extrudePlane"
}
],
"sketch": {
"type": "Sketch",
"id": "[uuid]",
"paths": [
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
0.0,
0.0
],
"tag": {
"commentStart": 94,
"end": 100,
"start": 94,
"type": "TagDeclarator",
"value": "seg01"
},
"to": [
1.0,
3.82
],
"type": "ToPoint",
"units": {
"type": "Mm"
}
},
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
1.0,
3.82
],
"tag": null,
"to": [
3.0,
0.4152
],
"type": "ToPoint",
"units": {
"type": "Mm"
}
},
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
3.0,
0.4152
],
"tag": null,
"to": [
0.0,
0.0
],
"type": "ToPoint",
"units": {
"type": "Mm"
}
}
],
"on": {
"type": "plane",
"id": "[uuid]",
"artifactId": "[uuid]",
"value": "XY",
"origin": {
"x": 0.0,
"y": 0.0,
"z": 0.0,
"units": {
"type": "Mm"
}
},
"xAxis": {
"x": 1.0,
"y": 0.0,
"z": 0.0,
"units": {
"type": "Mm"
}
},
"yAxis": {
"x": 0.0,
"y": 1.0,
"z": 0.0,
"units": {
"type": "Mm"
}
},
"zAxis": {
"x": 0.0,
"y": 0.0,
"z": 1.0,
"units": {
"type": "Mm"
}
}
},
"start": {
"from": [
0.0,
0.0
],
"to": [
0.0,
0.0
],
"units": {
"type": "Mm"
},
"tag": null,
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
}
},
"tags": {
"seg01": {
"type": "TagIdentifier",
"value": "seg01"
}
},
"artifactId": "[uuid]",
"originalId": "[uuid]",
"units": {
"type": "Mm"
}
},
"height": 10.0,
"startCapId": "[uuid]",
"endCapId": "[uuid]",
"units": {
"type": "Mm"
}
}
},
"seg01": {
"type": "TagIdentifier",
"type": "TagIdentifier",
"value": "seg01"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

View File

@ -1,10 +0,0 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Result of unparsing big_number_angle_to_match_length_x.kcl
---
part001 = startSketchOn(XY)
|> startProfileAt([0, 0], %)
|> line(end = [1, 3.82], tag = $seg01)
|> angledLine(angle = -angleToMatchLengthX(seg01, 3, %), endAbsoluteX = 3)
|> close(%)
|> extrude(length = 10)

View File

@ -1,253 +0,0 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Artifact commands big_number_angle_to_match_length_y.kcl
---
[
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "edge_lines_visible",
"hidden": false
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "object_visible",
"object_id": "[uuid]",
"hidden": true
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "object_visible",
"object_id": "[uuid]",
"hidden": true
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "make_plane",
"origin": {
"x": 0.0,
"y": 0.0,
"z": 0.0
},
"x_axis": {
"x": 1.0,
"y": 0.0,
"z": 0.0
},
"y_axis": {
"x": 0.0,
"y": 1.0,
"z": 0.0
},
"size": 60.0,
"clobber": false,
"hide": true
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "enable_sketch_mode",
"entity_id": "[uuid]",
"ortho": false,
"animated": false,
"adjust_camera": false,
"planar_normal": {
"x": 0.0,
"y": 0.0,
"z": 1.0
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "start_path"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "move_path_pen",
"path": "[uuid]",
"to": {
"x": 0.0,
"y": 0.0,
"z": 0.0
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "sketch_mode_disable"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extend_path",
"path": "[uuid]",
"segment": {
"type": "line",
"end": {
"x": 1.0,
"y": 3.82,
"z": 0.0
},
"relative": true
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extend_path",
"path": "[uuid]",
"segment": {
"type": "line",
"end": {
"x": 3.0,
"y": 3.3954,
"z": 0.0
},
"relative": false
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "close_path",
"path_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "enable_sketch_mode",
"entity_id": "[uuid]",
"ortho": false,
"animated": false,
"adjust_camera": false,
"planar_normal": {
"x": 0.0,
"y": 0.0,
"z": 1.0
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extrude",
"target": "[uuid]",
"distance": 10.0,
"faces": null,
"opposite": "None"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "sketch_mode_disable"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "object_bring_to_front",
"object_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_extrusion_face_info",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
}
]

View File

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

View File

@ -1,49 +0,0 @@
```mermaid
flowchart LR
subgraph path2 [Path]
2["Path<br>[35, 60, 0]"]
3["Segment<br>[66, 101, 0]"]
4["Segment<br>[107, 178, 0]"]
5["Segment<br>[184, 192, 0]"]
6[Solid2d]
end
1["Plane<br>[10, 29, 0]"]
7["Sweep Extrusion<br>[198, 218, 0]"]
8[Wall]
9[Wall]
10[Wall]
11["Cap Start"]
12["Cap End"]
13["SweepEdge Opposite"]
14["SweepEdge Adjacent"]
15["SweepEdge Opposite"]
16["SweepEdge Adjacent"]
17["SweepEdge Opposite"]
18["SweepEdge Adjacent"]
1 --- 2
2 --- 3
2 --- 4
2 --- 5
2 ---- 7
2 --- 6
3 --- 10
3 --- 17
3 --- 18
4 --- 9
4 --- 15
4 --- 16
5 --- 8
5 --- 13
5 --- 14
7 --- 8
7 --- 9
7 --- 10
7 --- 11
7 --- 12
7 --- 13
7 --- 14
7 --- 15
7 --- 16
7 --- 17
7 --- 18
```

View File

@ -1,428 +0,0 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Result of parsing big_number_angle_to_match_length_y.kcl
---
{
"Ok": {
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 0,
"id": {
"commentStart": 0,
"end": 0,
"name": "part001",
"start": 0,
"type": "Identifier"
},
"init": {
"body": [
{
"arguments": [
{
"commentStart": 0,
"end": 0,
"raw": "'XY'",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": "XY"
}
],
"callee": {
"abs_path": false,
"commentStart": 0,
"end": 0,
"name": {
"commentStart": 0,
"end": 0,
"name": "startSketchOn",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Name"
},
"commentStart": 0,
"end": 0,
"start": 0,
"type": "CallExpression",
"type": "CallExpression"
},
{
"arguments": [
{
"commentStart": 0,
"elements": [
{
"commentStart": 0,
"end": 0,
"raw": "0",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 0.0,
"suffix": "None"
}
},
{
"commentStart": 0,
"end": 0,
"raw": "0",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 0.0,
"suffix": "None"
}
}
],
"end": 0,
"start": 0,
"type": "ArrayExpression",
"type": "ArrayExpression"
},
{
"commentStart": 0,
"end": 0,
"start": 0,
"type": "PipeSubstitution",
"type": "PipeSubstitution"
}
],
"callee": {
"abs_path": false,
"commentStart": 0,
"end": 0,
"name": {
"commentStart": 0,
"end": 0,
"name": "startProfileAt",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Name"
},
"commentStart": 0,
"end": 0,
"start": 0,
"type": "CallExpression",
"type": "CallExpression"
},
{
"arguments": [
{
"type": "LabeledArg",
"label": {
"commentStart": 0,
"end": 0,
"name": "end",
"start": 0,
"type": "Identifier"
},
"arg": {
"commentStart": 0,
"elements": [
{
"commentStart": 0,
"end": 0,
"raw": "1",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 1.0,
"suffix": "None"
}
},
{
"commentStart": 0,
"end": 0,
"raw": "3.82",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 3.82,
"suffix": "None"
}
}
],
"end": 0,
"start": 0,
"type": "ArrayExpression",
"type": "ArrayExpression"
}
},
{
"type": "LabeledArg",
"label": {
"commentStart": 0,
"end": 0,
"name": "tag",
"start": 0,
"type": "Identifier"
},
"arg": {
"commentStart": 0,
"end": 0,
"start": 0,
"type": "TagDeclarator",
"type": "TagDeclarator",
"value": "seg01"
}
}
],
"callee": {
"abs_path": false,
"commentStart": 0,
"end": 0,
"name": {
"commentStart": 0,
"end": 0,
"name": "line",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Name"
},
"commentStart": 0,
"end": 0,
"start": 0,
"type": "CallExpressionKw",
"type": "CallExpressionKw",
"unlabeled": null
},
{
"arguments": [
{
"type": "LabeledArg",
"label": {
"commentStart": 0,
"end": 0,
"name": "angle",
"start": 0,
"type": "Identifier"
},
"arg": {
"argument": {
"arguments": [
{
"abs_path": false,
"commentStart": 0,
"end": 0,
"name": {
"commentStart": 0,
"end": 0,
"name": "seg01",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Name",
"type": "Name"
},
{
"commentStart": 0,
"end": 0,
"raw": "3",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 3.0,
"suffix": "None"
}
},
{
"commentStart": 0,
"end": 0,
"start": 0,
"type": "PipeSubstitution",
"type": "PipeSubstitution"
}
],
"callee": {
"abs_path": false,
"commentStart": 0,
"end": 0,
"name": {
"commentStart": 0,
"end": 0,
"name": "angleToMatchLengthY",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Name"
},
"commentStart": 0,
"end": 0,
"start": 0,
"type": "CallExpression",
"type": "CallExpression"
},
"commentStart": 0,
"end": 0,
"operator": "-",
"start": 0,
"type": "UnaryExpression",
"type": "UnaryExpression"
}
},
{
"type": "LabeledArg",
"label": {
"commentStart": 0,
"end": 0,
"name": "endAbsoluteX",
"start": 0,
"type": "Identifier"
},
"arg": {
"commentStart": 0,
"end": 0,
"raw": "3",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 3.0,
"suffix": "None"
}
}
}
],
"callee": {
"abs_path": false,
"commentStart": 0,
"end": 0,
"name": {
"commentStart": 0,
"end": 0,
"name": "angledLine",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Name"
},
"commentStart": 0,
"end": 0,
"start": 0,
"type": "CallExpressionKw",
"type": "CallExpressionKw",
"unlabeled": null
},
{
"arguments": [
{
"commentStart": 0,
"end": 0,
"start": 0,
"type": "PipeSubstitution",
"type": "PipeSubstitution"
}
],
"callee": {
"abs_path": false,
"commentStart": 0,
"end": 0,
"name": {
"commentStart": 0,
"end": 0,
"name": "close",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Name"
},
"commentStart": 0,
"end": 0,
"start": 0,
"type": "CallExpression",
"type": "CallExpression"
},
{
"arguments": [
{
"type": "LabeledArg",
"label": {
"commentStart": 0,
"end": 0,
"name": "length",
"start": 0,
"type": "Identifier"
},
"arg": {
"commentStart": 0,
"end": 0,
"raw": "10",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 10.0,
"suffix": "None"
}
}
}
],
"callee": {
"abs_path": false,
"commentStart": 0,
"end": 0,
"name": {
"commentStart": 0,
"end": 0,
"name": "extrude",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Name"
},
"commentStart": 0,
"end": 0,
"start": 0,
"type": "CallExpressionKw",
"type": "CallExpressionKw",
"unlabeled": null
}
],
"commentStart": 0,
"end": 0,
"start": 0,
"type": "PipeExpression",
"type": "PipeExpression"
},
"start": 0,
"type": "VariableDeclarator"
},
"end": 0,
"kind": "const",
"start": 0,
"type": "VariableDeclaration",
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 0,
"start": 0
}
}

View File

@ -1,6 +0,0 @@
part001 = startSketchOn('XY')
|> startProfileAt([0, 0], %)
|> line(end = [1, 3.82], tag = $seg01)
|> angledLine(angle = -angleToMatchLengthY(seg01, 3, %), endAbsoluteX = 3)
|> close(%)
|> extrude(length = 10)

View File

@ -1,53 +0,0 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Operations executed big_number_angle_to_match_length_y.kcl
---
[
{
"labeledArgs": {
"planeOrSolid": {
"value": {
"type": "String",
"value": "XY"
},
"sourceRange": []
}
},
"name": "startSketchOn",
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": null
},
{
"labeledArgs": {
"length": {
"value": {
"type": "Number",
"value": 10.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"sourceRange": []
}
},
"name": "extrude",
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": {
"value": {
"type": "Sketch",
"value": {
"artifactId": "[uuid]"
}
},
"sourceRange": []
}
}
]

View File

@ -1,190 +0,0 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Variables in memory after executing big_number_angle_to_match_length_y.kcl
---
{
"part001": {
"type": "Solid",
"value": {
"type": "Solid",
"id": "[uuid]",
"artifactId": "[uuid]",
"value": [
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": {
"commentStart": 94,
"end": 100,
"start": 94,
"type": "TagDeclarator",
"value": "seg01"
},
"type": "extrudePlane"
},
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": null,
"type": "extrudePlane"
},
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": null,
"type": "extrudePlane"
}
],
"sketch": {
"type": "Sketch",
"id": "[uuid]",
"paths": [
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
0.0,
0.0
],
"tag": {
"commentStart": 94,
"end": 100,
"start": 94,
"type": "TagDeclarator",
"value": "seg01"
},
"to": [
1.0,
3.82
],
"type": "ToPoint",
"units": {
"type": "Mm"
}
},
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
1.0,
3.82
],
"tag": null,
"to": [
3.0,
3.3954
],
"type": "ToPoint",
"units": {
"type": "Mm"
}
},
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
3.0,
3.3954
],
"tag": null,
"to": [
0.0,
0.0
],
"type": "ToPoint",
"units": {
"type": "Mm"
}
}
],
"on": {
"type": "plane",
"id": "[uuid]",
"artifactId": "[uuid]",
"value": "XY",
"origin": {
"x": 0.0,
"y": 0.0,
"z": 0.0,
"units": {
"type": "Mm"
}
},
"xAxis": {
"x": 1.0,
"y": 0.0,
"z": 0.0,
"units": {
"type": "Mm"
}
},
"yAxis": {
"x": 0.0,
"y": 1.0,
"z": 0.0,
"units": {
"type": "Mm"
}
},
"zAxis": {
"x": 0.0,
"y": 0.0,
"z": 1.0,
"units": {
"type": "Mm"
}
}
},
"start": {
"from": [
0.0,
0.0
],
"to": [
0.0,
0.0
],
"units": {
"type": "Mm"
},
"tag": null,
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
}
},
"tags": {
"seg01": {
"type": "TagIdentifier",
"value": "seg01"
}
},
"artifactId": "[uuid]",
"originalId": "[uuid]",
"units": {
"type": "Mm"
}
},
"height": 10.0,
"startCapId": "[uuid]",
"endCapId": "[uuid]",
"units": {
"type": "Mm"
}
}
},
"seg01": {
"type": "TagIdentifier",
"type": "TagIdentifier",
"value": "seg01"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

View File

@ -1,10 +0,0 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Result of unparsing big_number_angle_to_match_length_y.kcl
---
part001 = startSketchOn(XY)
|> startProfileAt([0, 0], %)
|> line(end = [1, 3.82], tag = $seg01)
|> angledLine(angle = -angleToMatchLengthY(seg01, 3, %), endAbsoluteX = 3)
|> close(%)
|> extrude(length = 10)

View File

@ -82,14 +82,6 @@ description: Variables in memory after executing circle_three_point.kcl
"units": { "units": {
"type": "Mm" "type": "Mm"
} }
},
"zAxis": {
"x": 0.0,
"y": 0.0,
"z": 1.0,
"units": {
"type": "Mm"
}
} }
}, },
"start": { "start": {
@ -121,7 +113,8 @@ description: Variables in memory after executing circle_three_point.kcl
"endCapId": "[uuid]", "endCapId": "[uuid]",
"units": { "units": {
"type": "Mm" "type": "Mm"
} },
"sectional": false
} }
} }
} }

Some files were not shown because too many files have changed in this diff Show More