Compare commits

...

44 Commits

Author SHA1 Message Date
495727d617 hacky shit
Signed-off-by: Jess Frazelle <github@jessfraz.com>
2025-04-05 13:05:04 -07:00
e943303434 logs
Signed-off-by: Jess Frazelle <github@jessfraz.com>
2025-04-05 10:20:35 -07:00
8ce175f006 clippy
Signed-off-by: Jess Frazelle <github@jessfraz.com>
2025-04-05 09:48:45 -07:00
13aa178734 get rid of execution kind
Signed-off-by: Jess Frazelle <github@jessfraz.com>
2025-04-05 09:44:18 -07:00
de137ff13b Merge remote-tracking branch 'origin/main' into jess/changes-import
* origin/main: (26 commits)
  attempt to import win-ca on windows (#6136)
  Upgrade e2e-tests windows runner from 4 cores to 8 (#6166)
  Follow-up fixes after bearing sample rename (#6164)
  Add test for #5799: "Only showing axis planes when there are no errors" (#6007)
  Wait for export button to make test more reliable (#6143)
  sketching on a mirror2d thats been extruded fixed! (#6149)
  Bump vite from 5.4.16 to 5.4.17 in /packages/codemirror-lang-kcl in the security group (#6150)
  Bump vite from 5.4.16 to 5.4.17 in the security group (#6151)
  Update all KCL-Samples to be more ME friendly (#6132)
  Shorten feedback cycle for legitimate failures (#6146)
  Remove the camera projection toggle from the UI (#6077)
  Use all available CPUs to run tests on CI (#6138)
  [fix] Get rid of risky useEffect in restart onboarding flow (#6133)
  Feature: Traditional menu actions in desktop application part II (#6030)
  [Bug] fix some UI friction from imports (#6139)
  Use scene fixture to make test more reliable on macOS (#6140)
  Fix: function composition during playwright setup created a massive page.reload loop (#6137)
  Alternative way to make appMachine spawned children type safe (#5890)
  [BUG] mutate ast to keep comments for pipe split ast-mod (#6128)
  Rename the app to Zoo Design Studio (#5974)
  ...
2025-04-05 09:33:50 -07:00
48e1a8ed02 attempt to import win-ca on windows (#6136)
* attempt to import win-ca on windows

otherwise we won't see system x509 cert authorities, which leaves people
high and dry if they're using an enterprise mitm tls box (😢)
2025-04-05 16:30:48 +00:00
a059166b9c Upgrade e2e-tests windows runner from 4 cores to 8 (#6166)
* Change e2e-tests runner to windows-latest-8-cores

* Clean up for PR
2025-04-05 08:44:50 -07:00
086a2b851d Follow-up fixes after bearing sample rename (#6164) 2025-04-05 11:00:47 +00:00
8e4c5fb24d Add test for #5799: "Only showing axis planes when there are no errors" (#6007)
* first pass at adding test for Only showing axis planes when there are no errors

* fix test Only show axis planes when there are no errors

* PR feedback
2025-04-04 23:41:09 +02:00
6993893600 Wait for export button to make test more reliable (#6143) 2025-04-04 16:53:57 -04:00
bfdf8babed sketching on a mirror2d thats been extruded fixed! (#6149)
* updates

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

* snap

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

* fixes

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

* add sample

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>

* fixes

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

* snap

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

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2025-04-04 12:55:21 -07:00
4d31fb890d Bump vite from 5.4.16 to 5.4.17 in /packages/codemirror-lang-kcl in the security group (#6150)
Bump vite in /packages/codemirror-lang-kcl in the security group

Bumps the security group in /packages/codemirror-lang-kcl with 1 update: [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite).


Updates `vite` from 5.4.16 to 5.4.17
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v5.4.17/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.4.17/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 5.4.17
  dependency-type: indirect
  dependency-group: security
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-04 18:57:20 +00:00
ef451fd8f7 Bump vite from 5.4.16 to 5.4.17 in the security group (#6151)
Bumps the security group with 1 update: [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite).


Updates `vite` from 5.4.16 to 5.4.17
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v5.4.17/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.4.17/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 5.4.17
  dependency-type: direct:development
  dependency-group: security
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-04 18:40:35 +00:00
656eb0abec Update all KCL-Samples to be more ME friendly (#6132)
* update all kcl-samples

* updates

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>

* Update kcl-samples simulation test output

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: Jess Frazelle <jessfraz@users.noreply.github.com>
Co-authored-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-04-04 11:03:13 -07:00
a7896329f7 Shorten feedback cycle for legitimate failures (#6146)
Stop sooner with legitimate failures
2025-04-04 17:29:29 +00:00
b9e11ac201 Remove the camera projection toggle from the UI (#6077)
* Remove E2E test behavior for projection toggle UI

Even though the test is `fixme`'d this should make it easier to
ressurect. The test is still flaky but it runs now.

* Remove projection toggle from the UI
2025-04-04 16:41:56 +00:00
3504b9246f Merge remote-tracking branch 'origin/main' into paultag/import 2025-04-03 10:15:28 -04:00
a035f7879b Merge remote-tracking branch 'origin/main' into paultag/import 2025-04-02 11:36:59 -04:00
d122d7a224 fix rebase add feature flag
Signed-off-by: Jess Frazelle <github@jessfraz.com>
2025-04-01 12:34:42 -07:00
198e7c4bd2 Merge remote-tracking branch 'origin/main' into paultag/import 2025-04-01 15:18:23 -04:00
14d8903acc man this is bad 2025-04-01 15:16:59 -04:00
275c23f294 chip away more 2025-04-01 13:35:50 -04:00
0ac9ac3896 Reapply "this was a bad idea"
This reverts commit fafdf41093.
2025-04-01 11:56:36 -04:00
0220d0f9de ok 2025-04-01 11:55:08 -04:00
4523dc209b Merge remote-tracking branch 'origin/main' into paultag/import 2025-04-01 11:55:02 -04:00
ea73eb011c :( 2025-03-31 16:51:46 -04:00
0aa2824c20 yike 2025-03-31 16:20:29 -04:00
e66893c5d0 poop 2025-03-31 16:17:35 -04:00
60274127df error 2025-03-31 15:57:13 -04:00
a0d1750829 prepare prelude before spawning 2025-03-31 15:54:35 -04:00
00ffa8c0bf Merge remote-tracking branch 'origin/main' into paultag/import 2025-03-31 15:46:26 -04:00
fafdf41093 Revert "this was a bad idea"
This reverts commit a2092e7ed6.
2025-03-28 17:07:29 -04:00
a2092e7ed6 this was a bad idea 2025-03-28 15:03:13 -04:00
aa103d299c Merge branch 'main' into paultag/import 2025-03-28 14:40:34 -04:00
aaaab495bc Merge remote-tracking branch 'origin' into paultag/import 2025-03-18 16:24:05 -04:00
364e38fda2 Merge remote-tracking branch 'origin' into paultag/import 2025-03-18 09:17:51 -04:00
b085af139b lock start things 2025-03-13 14:58:24 -04:00
ec537cd8dc Merge remote-tracking branch 'origin/main' into paultag/import 2025-03-13 11:17:34 -04:00
8debbc5241 wip 2025-03-13 11:17:22 -04:00
a590ed99cf Merge branch 'main' of github.com:KittyCAD/modeling-app into paultag/import 2025-03-12 12:00:46 -04:00
a002bb60a0 Merge remote-tracking branch 'origin/main' into paultag/import 2025-03-11 16:18:58 -04:00
6ba01b8dfa sketch a bit more; going to pull this out of tests next 2025-03-10 15:43:43 -04:00
ca9e6e0944 Merge remote-tracking branch 'origin/main' into paultag/import 2025-03-10 12:27:50 -04:00
e85e54215c wip 2025-03-10 12:27:47 -04:00
235 changed files with 35109 additions and 35634 deletions

View File

@ -281,7 +281,7 @@ jobs:
os:
- "runs-on=${{ github.run_id }}/family=i7ie.2xlarge/image=ubuntu22-full-x64"
- namespace-profile-macos-8-cores
- windows-latest
- windows-latest-8-cores
shardIndex: [1, 2, 3, 4]
shardTotal: [4]
# Disable macos and windows tests on hourly e2e tests since we only care
@ -292,7 +292,7 @@ jobs:
exclude:
- os: namespace-profile-macos-8-cores
isScheduled: true
- os: windows-latest
- os: windows-latest-8-cores
isScheduled: true
# TODO: add ref here for main and latest release tag
runs-on: ${{ matrix.os }}
@ -370,8 +370,8 @@ jobs:
with:
shell: bash
command: .github/ci-cd-scripts/playwright-electron.sh ${{matrix.shardIndex}} ${{matrix.shardTotal}} ${{ env.OS_NAME }}
timeout_minutes: 45
max_attempts: 15
timeout_minutes: 30
max_attempts: 9
env:
FAIL_ON_CONSOLE_ERRORS: true
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}

File diff suppressed because one or more lines are too long

View File

@ -32,53 +32,44 @@ test(
})
await page.setBodyDimensions({ width: 1200, height: 500 })
page.on('console', console.log)
await test.step('on open of project', async () => {
await expect(page.getByText(`bracket`)).toBeVisible()
// Open the project
const projectName = page.getByText(`bracket`)
await expect(projectName).toBeVisible()
await projectName.click()
await scene.waitForExecutionDone()
await page.waitForTimeout(1_000) // wait for panel buttons to be available
// open the project
await page.getByText(`bracket`).click()
// expect zero errors in guter
// Expect zero errors in gutter
await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
// export the model
// Click the export button
const exportButton = page.getByTestId('export-pane-button')
await expect(exportButton).toBeVisible()
await scene.waitForExecutionDone()
const gltfOption = page.getByText('glTF')
const submitButton = page.getByText('Confirm Export')
const exportingToastMessage = page.getByText(`Exporting...`)
const errorToastMessage = page.getByText(`Error while exporting`)
const engineErrorToastMessage = page.getByText(`Nothing to export`)
const alreadyExportingToastMessage = page.getByText(`Already exporting`)
// The open file's name is `main.kcl`, so the export file name should be `main.gltf`
const exportFileName = `main.gltf`
// Click the export button
await exportButton.click()
await page.waitForTimeout(1_000) // wait for export options to be available
// Select the first format option
const gltfOption = page.getByText('glTF')
const exportFileName = `main.gltf` // source file is named `main.kcl`
await expect(gltfOption).toBeVisible()
await expect(page.getByText('STL')).toBeVisible()
await page.keyboard.press('Enter')
// Click the checkbox
const submitButton = page.getByText('Confirm Export')
await expect(submitButton).toBeVisible()
await page.waitForTimeout(500)
await page.keyboard.press('Enter')
// Find the toast.
// Look out for the toast message
const exportingToastMessage = page.getByText(`Exporting...`)
const alreadyExportingToastMessage = page.getByText(`Already exporting`)
await expect(exportingToastMessage).toBeVisible()
await expect(alreadyExportingToastMessage).not.toBeVisible()
// Expect it to succeed.
// Expect it to succeed
const errorToastMessage = page.getByText(`Error while exporting`)
const engineErrorToastMessage = page.getByText(`Nothing to export`)
await expect(errorToastMessage).not.toBeVisible()
await expect(engineErrorToastMessage).not.toBeVisible()
@ -86,6 +77,7 @@ test(
await expect(successToastMessage).toBeVisible()
await expect(exportingToastMessage).not.toBeVisible()
// Check for the exported file
const firstFileFullPath = path.resolve(
getPlaywrightDownloadDir(tronApp.projectDirName),
exportFileName
@ -112,60 +104,53 @@ test(
const u = await getUtils(page)
await u.openFilePanel()
// Click on the other file
const otherKclButton = page.getByRole('button', { name: 'other.kcl' })
// Click the file
await otherKclButton.click()
// Close the file pane
await u.closeFilePanel()
await scene.waitForExecutionDone()
await page.waitForTimeout(1_000) // wait for panel buttons to be available
// FIXME: await scene.waitForExecutionDone() does not work. The modeling indicator stays in -receive-reliable and not execution done
await page.waitForTimeout(10000)
// expect zero errors in guter
// Expect zero errors in gutter
await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
// export the model
// Click the export button
const exportButton = page.getByTestId('export-pane-button')
await expect(exportButton).toBeVisible()
const gltfOption = page.getByText('glTF')
const submitButton = page.getByText('Confirm Export')
const exportingToastMessage = page.getByText(`Exporting...`)
const errorToastMessage = page.getByText(`Error while exporting`)
const engineErrorToastMessage = page.getByText(`Nothing to export`)
const alreadyExportingToastMessage = page.getByText(`Already exporting`)
// The open file's name is `other.kcl`, so the export file name should be `other.gltf`
const exportFileName = `other.gltf`
// Click the export button
await exportButton.click()
await page.waitForTimeout(1_000) // wait for export options to be available
// Select the first format option
const gltfOption = page.getByText('glTF')
const exportFileName = `other.gltf` // source file is named `other.kcl`
await expect(gltfOption).toBeVisible()
await expect(page.getByText('STL')).toBeVisible()
await page.keyboard.press('Enter')
// Click the checkbox
const submitButton = page.getByText('Confirm Export')
await expect(submitButton).toBeVisible()
await page.waitForTimeout(500)
await page.keyboard.press('Enter')
// Find the toast.
// Look out for the toast message
const exportingToastMessage = page.getByText(`Exporting...`)
const alreadyExportingToastMessage = page.getByText(`Already exporting`)
await expect(exportingToastMessage).toBeVisible()
await expect(alreadyExportingToastMessage).not.toBeVisible()
// Expect it to succeed
const errorToastMessage = page.getByText(`Error while exporting`)
const engineErrorToastMessage = page.getByText(`Nothing to export`)
await expect(errorToastMessage).not.toBeVisible()
await expect(engineErrorToastMessage).not.toBeVisible()
const successToastMessage = page.getByText(`Exported successfully`)
await test.step('Check the success toast message shows and nothing else', async () =>
Promise.all([
expect(alreadyExportingToastMessage).not.toBeVisible(),
expect(errorToastMessage).not.toBeVisible(),
expect(engineErrorToastMessage).not.toBeVisible(),
expect(successToastMessage).toBeVisible(),
expect(exportingToastMessage).not.toBeVisible(),
]))
await expect(successToastMessage).toBeVisible()
await expect(exportingToastMessage).not.toBeVisible()
// Check for the exported file=
const secondFileFullPath = path.resolve(
getPlaywrightDownloadDir(tronApp.projectDirName),
exportFileName

View File

@ -1315,4 +1315,38 @@ sketch001 = startSketchOn(XZ)
const element = page.locator('[data-overlay-index="1"]')
await expect(element).toHaveAttribute('data-overlay-visible', 'true')
})
test(`Only show axis planes when there are no errors`, async ({
page,
homePage,
scene,
cmdBar,
}) => {
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
`sketch001 = startSketchOn(XZ)
profile001 = circle(sketch001, center = [-100.0, -100.0], radius = 50.0)
sketch002 = startSketchOn(XZ)
profile002 = circle(sketch002, center = [-100.0, 100.0], radius = 50.0)
extrude001 = extrude(profile002, length = 0)` // length = 0 is causing the error
)
})
const viewportSize = { width: 1200, height: 800 }
await page.setBodyDimensions(viewportSize)
await homePage.goToModelingScene()
await scene.connectionEstablished()
await scene.settled(cmdBar)
await scene.expectPixelColor(
TEST_COLORS.DARK_MODE_BKGD,
// This is a position where the blue part of the axis plane is visible if its rendered
{ x: viewportSize.width * 0.75, y: viewportSize.height * 0.2 },
15
)
})
})

View File

@ -80,7 +80,8 @@ export const TEST_SETTINGS_CORRUPTED = {
},
} satisfies Partial<SaveSettingsPayload>
export const TEST_CODE_GIZMO = `part001 = startSketchOn(XZ)
export const TEST_CODE_GIZMO = `@settings(defaultLengthUnit = in)
part001 = startSketchOn(XZ)
|> startProfileAt([20, 0], %)
|> line(end = [7.13, 4 + 0])
|> angledLine({ angle: 3 + 0, length: 3.14 + 0 }, %)

View File

@ -8,37 +8,37 @@ test.describe('Testing Gizmo', { tag: ['@skipWin'] }, () => {
const cases = [
{
testDescription: 'top view',
clickPosition: { x: 951, y: 347 },
clickPosition: { x: 951, y: 385 },
expectedCameraPosition: { x: 800, y: -152, z: 4886.02 },
expectedCameraTarget: { x: 800, y: -152, z: 26 },
},
{
testDescription: 'bottom view',
clickPosition: { x: 951, y: 391 },
clickPosition: { x: 951, y: 429 },
expectedCameraPosition: { x: 800, y: -152, z: -4834.02 },
expectedCameraTarget: { x: 800, y: -152, z: 26 },
},
{
testDescription: 'right view',
clickPosition: { x: 929, y: 379 },
clickPosition: { x: 929, y: 417 },
expectedCameraPosition: { x: 5660.02, y: -152, z: 26 },
expectedCameraTarget: { x: 800, y: -152, z: 26 },
},
{
testDescription: 'left view',
clickPosition: { x: 974, y: 359 },
clickPosition: { x: 974, y: 397 },
expectedCameraPosition: { x: -4060.02, y: -152, z: 26 },
expectedCameraTarget: { x: 800, y: -152, z: 26 },
},
{
testDescription: 'back view',
clickPosition: { x: 967, y: 383 },
clickPosition: { x: 967, y: 421 },
expectedCameraPosition: { x: 800, y: 4708.02, z: 26 },
expectedCameraTarget: { x: 800, y: -152, z: 26 },
},
{
testDescription: 'front view',
clickPosition: { x: 935, y: 355 },
clickPosition: { x: 935, y: 393 },
expectedCameraPosition: { x: 800, y: -5012.02, z: 26 },
expectedCameraTarget: { x: 800, y: -152, z: 26 },
},

View File

@ -2,7 +2,11 @@ import { getUtils, orRunWhenFullSuiteEnabled } from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Test toggling perspective', () => {
test('via command palette and toggle', async ({ page, homePage }) => {
test('via command palette and toggle', async ({
page,
homePage,
toolbar,
}) => {
test.fixme(orRunWhenFullSuiteEnabled())
const u = await getUtils(page)
@ -14,7 +18,7 @@ test.describe('Test toggling perspective', () => {
y: screenHeight * 0.2,
}
const backgroundColor: [number, number, number] = [29, 29, 29]
const xzPlaneColor: [number, number, number] = [82, 55, 96]
const xzPlaneColor: [number, number, number] = [72, 55, 96]
const locationToHaveColor = async (color: [number, number, number]) => {
return u.getGreatestPixDiff(checkedScreenLocation, color)
}
@ -26,9 +30,29 @@ test.describe('Test toggling perspective', () => {
const commandToast = page.getByText(
`Set camera projection to "orthographic"`
)
const projectionToggle = page.getByRole('switch', {
name: 'Camera projection: ',
})
const checkSettingValue = async () => {
const settingsButton = page.getByRole('link', {
name: 'Settings',
exact: false,
})
let settingValue: string | null = null
await test.step(`Check the setting value`, async () => {
await settingsButton.click()
const userTab = page.getByRole('radio', { name: 'User' })
await userTab.click()
await expect(userTab).toBeChecked()
const setting = page.locator('#cameraProjection').first()
await expect(setting).toBeAttached()
await setting.scrollIntoViewIfNeeded()
settingValue = await setting.getByRole('combobox').inputValue()
await page.getByTestId('settings-close-button').click()
})
return settingValue
}
await test.step('Setup', async () => {
await page.setBodyDimensions({ width: screenWidth, height: screenHeight })
@ -39,8 +63,8 @@ test.describe('Test toggling perspective', () => {
timeout: 5000,
message: 'This spot should have the background color',
})
.toBeLessThan(15)
await expect(projectionToggle).toHaveAttribute('aria-checked', 'true')
.toBeLessThan(30)
expect(await checkSettingValue()).toBe('perspective')
})
// Extremely wild note: flicking between ortho and persp actually changes
@ -59,33 +83,22 @@ test.describe('Test toggling perspective', () => {
timeout: 5000,
message: 'This spot should have the XZ plane color',
})
.toBeLessThan(15)
await expect(projectionToggle).toHaveAttribute('aria-checked', 'false')
.toBeLessThan(30)
expect(await checkSettingValue()).toBe('orthographic')
})
await test.step(`Refresh the page and ensure the stream is loaded in ortho`, async () => {
await page.reload()
await page.waitForTimeout(1000)
await expect(toolbar.startSketchBtn).toBeEnabled({ timeout: 15_000 })
await u.closeKclCodePanel()
await expect
.poll(async () => locationToHaveColor(xzPlaneColor), {
timeout: 5000,
message: 'This spot should have the XZ plane color',
})
.toBeLessThan(15)
.toBeLessThan(30)
await expect(commandToast).not.toBeVisible()
await expect(projectionToggle).toHaveAttribute('aria-checked', 'false')
})
await test.step(`Switch to perspective via toggle`, async () => {
await projectionToggle.click()
await expect(projectionToggle).toHaveAttribute('aria-checked', 'true')
await expect
.poll(async () => locationToHaveColor(backgroundColor), {
timeout: 5000,
message: 'This spot should have the background color',
})
.toBeLessThan(15)
expect(await checkSettingValue()).toBe('orthographic')
})
})
})

View File

@ -8,8 +8,8 @@ import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Testing in-app sample loading', () => {
/**
* Note this test implicitly depends on the KCL sample "a-parametric-bearing-pillow-block",
* its title, and its units settings. https://github.com/KittyCAD/kcl-samples/blob/main/a-parametric-bearing-pillow-block/main.kcl
* Note this test implicitly depends on the KCL sample "parametric-bearing-pillow-block",
* its title, and its units settings. https://github.com/KittyCAD/kcl-samples/blob/main/parametric-bearing-pillow-block/main.kcl
*/
test('Web: should overwrite current code, cannot create new file', async ({
editor,
@ -29,8 +29,8 @@ test.describe('Testing in-app sample loading', () => {
// Locators and constants
const newSample = {
file: 'a-parametric-bearing-pillow-block' + FILE_EXT,
title: 'A Parametric Bearing Pillow Block',
file: 'parametric-bearing-pillow-block' + FILE_EXT,
title: 'Parametric Bearing Pillow Block',
}
const commandBarButton = page.getByRole('button', { name: 'Commands' })
const samplesCommandOption = page.getByRole('option', {
@ -72,7 +72,7 @@ test.describe('Testing in-app sample loading', () => {
/**
* Note this test implicitly depends on the KCL samples:
* "a-parametric-bearing-pillow-block": https://github.com/KittyCAD/kcl-samples/blob/main/a-parametric-bearing-pillow-block/main.kcl
* "parametric-bearing-pillow-block": https://github.com/KittyCAD/kcl-samples/blob/main/parametric-bearing-pillow-block/main.kcl
* "gear-rack": https://github.com/KittyCAD/kcl-samples/blob/main/gear-rack/main.kcl
*/
test(
@ -90,8 +90,8 @@ test.describe('Testing in-app sample loading', () => {
// Locators and constants
const sampleOne = {
file: 'a-parametric-bearing-pillow-block' + FILE_EXT,
title: 'A Parametric Bearing Pillow Block',
file: 'parametric-bearing-pillow-block' + FILE_EXT,
title: 'Parametric Bearing Pillow Block',
}
const sampleTwo = {
file: 'gear-rack' + FILE_EXT,

View File

@ -4,6 +4,7 @@ directories:
buildResources: assets
files:
- .vite/**
- "!node_modules/win-ca/pem/**"
mac:
category: public.app-category.developer-tools
artifactName: "${productName}-${version}-${arch}-${os}.${ext}"

View File

@ -66,6 +66,7 @@
"vscode-languageserver-protocol": "^3.17.5",
"vscode-uri": "^3.1.0",
"web-vitals": "^3.5.2",
"win-ca": "^3.5.1",
"xstate": "^5.19.2",
"yargs": "^17.7.2"
},
@ -233,7 +234,7 @@
"ts-node": "^10.0.0",
"typescript": "^5.8.2",
"typescript-eslint": "^8.26.1",
"vite": "^5.4.16",
"vite": "^5.4.17",
"vite-plugin-package-version": "^1.1.0",
"vite-plugin-top-level-await": "^1.5.0",
"vite-tsconfig-paths": "^4.3.2",

View File

@ -683,9 +683,9 @@ vite-tsconfig-paths@^4.3.2:
tsconfck "^3.0.3"
vite@^5.0.0:
version "5.4.16"
resolved "https://registry.yarnpkg.com/vite/-/vite-5.4.16.tgz#471983257a890ef33f2700cbbbc2134f2d08abf1"
integrity sha512-Y5gnfp4NemVfgOTDQAunSD4346fal44L9mszGGY/e+qxsRT5y1sMlS/8tiQ8AFAp+MFgYNSINdfEchJiPm41vQ==
version "5.4.17"
resolved "https://registry.yarnpkg.com/vite/-/vite-5.4.17.tgz#4bf61dd4cdbf64b0d6661f5dba76954cc81d5082"
integrity sha512-5+VqZryDj4wgCs55o9Lp+p8GE78TLVg0lasCH5xFZ4jacZjtqZa6JUw9/p0WeAojaOfncSM6v77InkFPGnvPvg==
dependencies:
esbuild "^0.21.3"
postcss "^8.4.43"

View File

@ -4,7 +4,7 @@
// Set units
@settings(defaultLengthUnit = in)
// Define function
// Create a function to make the 80-20 rail
fn rail8020(originStart, railHeight, railLength) {
// Sketch side 1 of profile
sketch001 = startSketchOn(-XZ)

View File

@ -25,8 +25,6 @@ When you submit a PR to add or modify KCL samples, images and STEP files will be
---
#### [80-20-rail](80-20-rail/main.kcl) ([screenshot](screenshots/80-20-rail.png))
[![80-20-rail](screenshots/80-20-rail.png)](80-20-rail/main.kcl)
#### [a-parametric-bearing-pillow-block](a-parametric-bearing-pillow-block/main.kcl) ([screenshot](screenshots/a-parametric-bearing-pillow-block.png))
[![a-parametric-bearing-pillow-block](screenshots/a-parametric-bearing-pillow-block.png)](a-parametric-bearing-pillow-block/main.kcl)
#### [ball-bearing](ball-bearing/main.kcl) ([screenshot](screenshots/ball-bearing.png))
[![ball-bearing](screenshots/ball-bearing.png)](ball-bearing/main.kcl)
#### [bench](bench/main.kcl) ([screenshot](screenshots/bench.png))
@ -83,6 +81,8 @@ When you submit a PR to add or modify KCL samples, images and STEP files will be
[![mounting-plate](screenshots/mounting-plate.png)](mounting-plate/main.kcl)
#### [multi-axis-robot](multi-axis-robot/main.kcl) ([screenshot](screenshots/multi-axis-robot.png))
[![multi-axis-robot](screenshots/multi-axis-robot.png)](multi-axis-robot/main.kcl)
#### [parametric-bearing-pillow-block](parametric-bearing-pillow-block/main.kcl) ([screenshot](screenshots/parametric-bearing-pillow-block.png))
[![parametric-bearing-pillow-block](screenshots/parametric-bearing-pillow-block.png)](parametric-bearing-pillow-block/main.kcl)
#### [pipe](pipe/main.kcl) ([screenshot](screenshots/pipe.png))
[![pipe](screenshots/pipe.png)](pipe/main.kcl)
#### [pipe-flange-assembly](pipe-flange-assembly/main.kcl) ([screenshot](screenshots/pipe-flange-assembly.png))

View File

@ -4,7 +4,7 @@
// Set units
@settings(defaultLengthUnit = in)
// Define constants like ball diameter, inside diamter, overhange length, and thickness
// Define parameters
outsideDiameter = 1.625
sphereDia = 0.25
shaftDia = 0.75
@ -95,5 +95,3 @@ outsideWallSketch = startSketchOn(offsetPlane(XY, offset = -overallThickness / 2
|> hole(circle(center = [0, 0], radius = shaftDia / 2 + wallThickness + sphereDia), %)
outsideWall = extrude(outsideWallSketch, length = overallThickness)
// https://www.mcmaster.com/60355K185/

View File

@ -4,8 +4,8 @@
// Set units
@settings(defaultLengthUnit = in)
// Import Constants
import caliperTolerance, caliperPadLength, caliperThickness, caliperOuterEdgeRadius, caliperInnerEdgeRadius, rotorDiameter, rotorTotalThickness, yAxisOffset from "globals.kcl"
// Import parameters
import caliperTolerance, caliperPadLength, caliperThickness, caliperOuterEdgeRadius, caliperInnerEdgeRadius, rotorDiameter, rotorTotalThickness, yAxisOffset from "parameters.kcl"
// Sketch the brake caliper profile
brakeCaliperSketch = startSketchOn(XY)

View File

@ -4,8 +4,8 @@
// Set units
@settings(defaultLengthUnit = in)
// Import Constants
import rotorDiameter, rotorInnerDiameter, rotorSinglePlateThickness, rotorInnerDiameterThickness, lugHolePatternDia, lugSpacing, rotorTotalThickness, spacerPatternDiameter, spacerDiameter, spacerLength, spacerCount, wheelDiameter, lugCount, yAxisOffset, drillAndSlotCount from "globals.kcl"
// Import parameters
import rotorDiameter, rotorInnerDiameter, rotorSinglePlateThickness, rotorInnerDiameterThickness, lugHolePatternDia, lugSpacing, rotorTotalThickness, spacerPatternDiameter, spacerDiameter, spacerLength, spacerCount, wheelDiameter, lugCount, yAxisOffset, drillAndSlotCount from "parameters.kcl"
rotorSketch = startSketchOn(XZ)
|> circle(center = [0, 0], radius = rotorDiameter / 2)

View File

@ -4,8 +4,8 @@
// Set units
@settings(defaultLengthUnit = in)
// Import Constants
import tireInnerDiameter, tireOuterDiameter, tireDepth, bendRadius, tireTreadWidth, tireTreadDepth, tireTreadOffset from "globals.kcl"
// Import parameters
import tireInnerDiameter, tireOuterDiameter, tireDepth, bendRadius, tireTreadWidth, tireTreadDepth, tireTreadOffset from "parameters.kcl"
// Create the sketch of the tire
tireSketch = startSketchOn(XY)

View File

@ -4,8 +4,8 @@
// Set units
@settings(defaultLengthUnit = in)
// Import Constants
import lugCount, lugSpacing, offset, backSpacing, wheelWidth, wheelDiameter, spokeCount, spokeGap, spokeAngle, spokeThickness from "globals.kcl"
// Import parameters
import lugCount, lugSpacing, offset, backSpacing, wheelWidth, wheelDiameter, spokeCount, spokeGap, spokeAngle, spokeThickness from "parameters.kcl"
// Create the wheel center
lugBase = startSketchOn(XZ)

View File

@ -4,8 +4,8 @@
// Set units
@settings(defaultLengthUnit = in)
// Import Constants
import lugDiameter, lugHeadLength, lugThreadDiameter, lugLength, lugThreadDepth, lugSpacing from "globals.kcl"
// Import parameters
import lugDiameter, lugHeadLength, lugThreadDiameter, lugLength, lugThreadDepth, lugSpacing from "parameters.kcl"
customPlane = {
plane = {

View File

@ -4,16 +4,24 @@
// Set units
@settings(defaultLengthUnit = in)
// Import parts
import "car-wheel.kcl" as carWheel
import "car-rotor.kcl" as carRotor
import "brake-caliper.kcl" as brakeCaliper
import "lug-nut.kcl" as lugNut
import "car-tire.kcl" as carTire
import lugCount from "globals.kcl"
// Import parameters
import * from "parameters.kcl"
// Place the car rotor
carRotor
|> translate(x = 0, y = 0.5, z = 0)
// Place the car wheel
carWheel
// Place the lug nuts
lugNut
|> patternCircular3d(
arcDegrees = 360,
@ -22,6 +30,10 @@ lugNut
instances = lugCount,
rotateDuplicates = false,
)
// Place the brake caliper
brakeCaliper
|> translate(x = 0, y = 0.5, z = 0)
// Place the car tire
carTire

View File

@ -1,9 +1,9 @@
// Car wheel assembly global constants
// Car wheel assembly parameters
// Set units
@settings(defaultLengthUnit = in)
// Car Wheel
// Car wheel
export lugCount = 5
export lugSpacing = 114.3 * mm()
export offset = -35 * mm()
@ -22,7 +22,7 @@ export lugThreadDiameter = lugDiameter / 2 * .85
export lugLength = 30 * mm()
export lugThreadDepth = lugLength - (12.7 * mm())
// Car Rotor
// Car rotor
export rotorDiameter = 12
export rotorInnerDiameter = 6
export rotorSinglePlateThickness = 0.25
@ -36,7 +36,7 @@ export spacerCount = 16
export yAxisOffset = 0.5
export drillAndSlotCount = 5
// Car Tire
// Car tire
export tireInnerDiameter = 19
export tireOuterDiameter = 24
export tireDepth = 11.02
@ -45,7 +45,7 @@ export tireTreadWidth = 0.39
export tireTreadDepth = 0.39
export tireTreadOffset = 3.15
// Brake Caliper
// Brake caliper
export caliperTolerance = 0.050
export caliperPadLength = 1.6
export caliperThickness = 0.39

View File

@ -1,10 +1,10 @@
// Color Cube
// This is a color cube centered about the origin. It is used to help determine orientation in the scene.
// Set unit
// Set units
@settings(defaultLengthUnit = mm)
// Globals referenced in drawRectangle
// Parameters referenced in drawRectangle
size = 100
halfSize = size / 2
extrudeLength = 1.0

View File

@ -1,9 +1,10 @@
// Cycloidal Gear
// A cycloidal gear is a gear with a continuous, curved tooth profile. They are used in watchmaking and high precision robotics actuation
// Set Units
// Set units
@settings(defaultLengthUnit = in)
// Create a function for the cycloidal gear
fn cycloidalGear(gearPitch, gearHeight, holeDiameter, helixAngle) {
// Create a function to draw the gear profile as a sketch. Rotate each profile about the gear's axis by an helix angle proportional to the total gear height
fn gearSketch(gHeight) {
@ -44,4 +45,5 @@ fn cycloidalGear(gearPitch, gearHeight, holeDiameter, helixAngle) {
return gearLoft
}
// Call the cycloidal gear function
cycloidalGear(.3, 1.5, 0.297, -80)

View File

@ -9,19 +9,19 @@
circR = 25
// Calculated parameters
// thickness of the dodecahedron
// Thickness of the dodecahedron
wallThickness = circR * 0.2
// angle between faces in radians
// Angle between faces in radians
dihedral = acos(-(sqrt(5) / 5))
// inscribed radius
// Inscribed radius
inscR = circR / 15 * sqrt(75 + 30 * sqrt(5))
// pentagon edge length
// Pentagon edge length
edgeL = 4 * circR / (sqrt(3) * (1 + sqrt(5)))
// pentagon radius
// Pentagon radius
pentR = edgeL / 2 / sin(toRadians(36))
// Define a plane for the bottom angled face
@ -69,7 +69,7 @@ bottomBowl = patternCircular3d(
rotateDuplicates = true,
)
// pattern the bottom to create the top face
// Pattern the bottom to create the top face
patternCircular3d(
bottom,
instances = 2,
@ -79,7 +79,7 @@ patternCircular3d(
rotateDuplicates = true,
)
// pattern the bottom angled faces to create the top
// Pattern the bottom angled faces to create the top
patternCircular3d(
bottomBowl,
instances = 2,

View File

@ -1,10 +1,10 @@
// Dual-Basin Utility Sink
// A stainless steel sink unit with dual rectangular basins and six under-counter storage compartments.
// set units
// Set units
@settings(defaultLengthUnit = mm)
// globals
// Define parameters
tableHeight = 850
tableWidth = 3400
tableDepth = 400

View File

@ -4,6 +4,7 @@
// Set units
@settings(defaultLengthUnit = mm)
// Define parameters
length = 175
width = 125
height = 70

View File

@ -1,10 +1,10 @@
// Exhaust Manifold
// A welded exhaust header for an inline 4-cylinder engine
// Set Units
// Set units
@settings(defaultLengthUnit = in)
// Define Constants
// Define parameters
primaryTubeDiameter = 1.625
wallThickness = 0.080
plateHeight = 0.125

View File

@ -4,7 +4,7 @@
// Set units
@settings(defaultLengthUnit = in)
// Define constants
// Define parameters
mountingHoleDia = .625
baseDia = 4.625
pipeDia = 1.25

View File

@ -4,7 +4,7 @@
// Set units
@settings(defaultLengthUnit = mm)
// define constants in mm
// define parameters
radius = 6.0
width = 144.0
length = 80.0
@ -15,7 +15,7 @@ tabLength = 25
tabWidth = 12
tabThk = 4
// define a rectangular shape func
// Define a rectangular shape func
fn rectShape(pos, w, l) {
rr = startSketchOn('xy')
|> startProfileAt([pos[0] - (w / 2), pos[1] - (l / 2)], %)
@ -26,7 +26,7 @@ fn rectShape(pos, w, l) {
return rr
}
// define the bracket plane
// Define the bracket plane
bracketPlane = {
plane = {
origin = { x = 0, y = length / 2 + thk, z = 0 },
@ -36,7 +36,7 @@ bracketPlane = {
}
}
// build the bracket sketch around the body
// Build the bracket sketch around the body
fn bracketSketch(w, d, t) {
s = startSketchOn(bracketPlane)
|> startProfileAt([-w / 2 - t, d + t], %)
@ -51,7 +51,7 @@ fn bracketSketch(w, d, t) {
return s
}
// build the body of the bracket
// Build the body of the bracket
bs = bracketSketch(width, depth, thk)
bracketBody = bs
|> extrude(length = length + 2 * thk)
@ -65,7 +65,7 @@ bracketBody = bs
],
)
// define the tab plane
// Define the tab plane
tabPlane = {
plane = {
origin = { x = 0, y = 0, z = depth + thk },
@ -75,7 +75,7 @@ tabPlane = {
}
}
// build the tabs of the mounting bracket (right side)
// Build the tabs of the mounting bracket (right side)
tabsR = startSketchOn(tabPlane)
|> startProfileAt([width / 2 + thk, length / 2 + thk], %)
|> line(end = [tabWidth, -tabLength / 3], tag = $edge11)
@ -99,7 +99,7 @@ tabsR = startSketchOn(tabPlane)
)
|> patternLinear3d(axis = [0, -1, 0], instances = 2, distance = length + 2 * thk - (tabLength * 4 / 3))
// build the tabs of the mounting bracket (left side)
// Build the tabs of the mounting bracket (left side)
tabsL = startSketchOn(tabPlane)
|> startProfileAt([-width / 2 - thk, length / 2 + thk], %)
|> line(end = [-tabWidth, -tabLength / 3], tag = $edge21)
@ -123,7 +123,7 @@ tabsL = startSketchOn(tabPlane)
)
|> patternLinear3d(axis = [0, -1, 0], instances = 2, distance = length + 2 * thk - (tabLength * 4 / 3))
// define a plane for retention bumps
// Define a plane for retention bumps
retPlane = {
plane = {
origin = { x = -width / 2 + 20, y = 0, z = 0 },
@ -133,7 +133,7 @@ retPlane = {
}
}
// build the retention bump in the front
// Build the retention bump in the front
retFront = startSketchOn(retPlane)
|> startProfileAt([-length / 2 - thk, 0], %)
|> line(end = [0, thk])
@ -141,7 +141,7 @@ retFront = startSketchOn(retPlane)
|> close()
|> extrude(length = width - 40)
// build the retention bump in the back
// Build the retention bump in the back
retBack = startSketchOn(retPlane)
|> startProfileAt([length / 2 + thk, 0], %)
|> line(end = [0, thk])

View File

@ -4,7 +4,7 @@
// Set units
@settings(defaultLengthUnit = mm)
// Define constants in millimeters (mm)
// Define parameters
flipperThickness = 3.5
flipperLength = 70.0
handleWidth = 15.0
@ -16,7 +16,7 @@ gripHeight = 20.0
gripFilletRadius = 3.0
gripSlotWidth = 8.0
// function for drawing slots on a sketch given the start and end points as well as a width
// Function for drawing slots on a sketch given the start and end points as well as a width
fn slot(sketch1, start, end, width) {
angle = if start[0] == end[0] {
if end[1] > start[1] {
@ -43,10 +43,10 @@ fn slot(sketch1, start, end, width) {
return slotSketch
}
// create a sketch on the "XY" plane
// Create a sketch on the "XY" plane
sketch000 = startSketchOn(XY)
// create a profile of the flipper
// Create a profile of the flipper
flipperProfile = startProfileAt([-flipperLength, -32.0], sketch000)
|> line(end = [flipperLength, 2.0])
|> yLine(length = 60.0, tag = $backEdge)
@ -58,25 +58,25 @@ flipperProfile = startProfileAt([-flipperLength, -32.0], sketch000)
}, %)
|> close()
// create a profile of the middle
// Create a profile of the middle
slotProfile000 = slot(sketch000, [-25, 0], [-55, 0], flipperSlotWidth)
// create a profile of the top slot
// Create a profile of the top slot
slotProfile001 = slot(sketch000, [-25, 18], [-55, 19], flipperSlotWidth)
// create a profile of the bottom slot
// Create a profile of the bottom slot
slotProfile002 = slot(sketch000, [-25, -18], [-55, -19], flipperSlotWidth)
// create a profile with slots for the spatula
// Create a profile with slots for the spatula
spatulaProfile = flipperProfile
|> hole(slotProfile000, %)
|> hole(slotProfile001, %)
|> hole(slotProfile002, %)
// extrude the profile to create the spatula flipper
// Extrude the profile to create the spatula flipper
flipper = extrude(spatulaProfile, length = flipperThickness)
// fillet the edges of the flipper
// Fillet the edges of the flipper
fillet(
flipper,
radius = flipperFilletRadius,
@ -86,10 +86,10 @@ fillet(
],
)
// create a sketch on the "XZ" plane offset by half the thickness
// Create a sketch on the "XZ" plane offset by half the thickness
sketch001 = startSketchOn(offsetPlane(XZ, offset = -handleWidth / 2))
// create a profile of the spatula handle
// Create a profile of the spatula handle
handleProfile = startProfileAt([0.0, flipperThickness], sketch001)
|> line(end = [31.819805, 31.819805], tag = $handleBottomEdge)
|> line(end = [140.953893, 51.303021])
@ -99,10 +99,10 @@ handleProfile = startProfileAt([0.0, flipperThickness], sketch001)
|> xLine(length = 7.071068)
|> close()
// create an extrusion extrude001
// Create an extrusion extrude001
handle = extrude(handleProfile, length = handleWidth)
// fillet the bend of the spatula handle
// Fillet the bend of the spatula handle
fillet(
handle,
radius = 4,
@ -112,7 +112,7 @@ fillet(
],
)
// define a plane which is at the end of the handle
// Define a plane which is at the end of the handle
handlePlane = {
plane = {
origin = [208.593833, 0.0, 75.921946],
@ -122,10 +122,10 @@ handlePlane = {
}
}
// create a sketch on the handle plane
// Create a sketch on the handle plane
sketch002 = startSketchOn(handlePlane)
// create a profile of the grip
// Create a profile of the grip
gripProfile = startProfileAt([-26.806746, -10.0], sketch002)
|> xLine(length = gripWidth - (2 * gripFilletRadius))
|> arc({
@ -153,14 +153,14 @@ gripProfile = startProfileAt([-26.806746, -10.0], sketch002)
}, %)
|> close()
// extrude the grip profile to create the grip
// Extrude the grip profile to create the grip
grip = extrude(gripProfile, length = -gripLength)
// create a sketch on the grip for the hole
// Create a sketch on the grip for the hole
sketch003 = startSketchOn(grip, gripEdgeTop)
// create a profile for the grip hole
// Create a profile for the grip hole
gripHoleProfile = slot(sketch003, [0, 200], [0, 210], gripSlotWidth)
// cut a hole in the grip
// Cut a hole in the grip
extrude(gripHoleProfile, length = -gripWidth - 20)

View File

@ -4,7 +4,7 @@
// Set units
@settings(defaultLengthUnit = in)
// Define constants
// Define parameters
carafeDiameter = 4.41
carafeHeight = 7.32
handleThickness = 0.65

View File

@ -1,10 +1,10 @@
// 100mm Gear Rack
// A flat bar or rail that is engraved with teeth along its length. These teeth are designed to mesh with the teeth of a gear, known as a pinion. When the pinion, a small cylindrical gear, rotates, its teeth engage with the teeth on the rack, causing the rack to move linearly. Conversely, linear motion applied to the rack will cause the pinion to rotate.
// Set Units
// Set units
@settings(defaultLengthUnit = mm)
// Define constants
// Define parameters
length = 100
pitchHeight = 11.5
width = 5

View File

@ -1,10 +1,10 @@
// Spur Gear
// A rotating machine part having cut teeth or, in the case of a cogwheel, inserted teeth (called cogs), which mesh with another toothed part to transmit torque. Geared devices can change the speed, torque, and direction of a power source. The two elements that define a gear are its circular shape and the teeth that are integrated into its outer edge, which are designed to fit into the teeth of another gear.
// Set Units
// Set units
@settings(defaultLengthUnit = in)
// Define constants
// Define parameters
nTeeth = 21
module = 0.5
pitchDiameter = module * nTeeth

View File

@ -4,7 +4,7 @@
// Set units in millimeters (mm)
@settings(defaultLengthUnit = mm)
// Define constants
// Define parameters
binLength = 42.0
cornerRadius = 4.0
firstStep = 0.7
@ -21,7 +21,7 @@ countBinLength = 3
// The total height of the baseplate is a summation of the vertical heights of the baseplate steps
height = firstStep + secondStep + thirdStep
// define a function which builds the profile of the baseplate bin
// Define a function which builds the profile of the baseplate bin
fn face(plane) {
faceSketch = startSketchOn(plane)
|> startProfileAt([0, 0], %)
@ -33,10 +33,10 @@ fn face(plane) {
return faceSketch
}
// extrude a single side of the bin
// Extrude a single side of the bin
singleSide = extrude(face(offsetPlane(YZ, offset = cornerRadius)), length = binLength - (cornerRadius * 2))
// create the other sides of the bin by using a circular pattern
// Create the other sides of the bin by using a circular pattern
sides = patternCircular3d(
singleSide,
arcDegrees = 360,
@ -46,16 +46,16 @@ sides = patternCircular3d(
rotateDuplicates = true,
)
// define an axis axis000
// Define an axis axis000
axis000 = {
direction = [0.0, 1.0],
origin = [cornerRadius, cornerRadius]
}
// create a single corner of the bin
// Create a single corner of the bin
singleCorner = revolve(face(offsetPlane(YZ, offset = cornerRadius)), angle = -90, axis = axis000)
// create the corners of the bin
// Create the corners of the bin
corners = patternCircular3d(
singleCorner,
arcDegrees = 360,
@ -65,7 +65,7 @@ corners = patternCircular3d(
rotateDuplicates = true,
)
// create the baseplate by patterning sides
// Create the baseplate by patterning sides
basePlateSides = patternLinear3d(
sides,
axis = [1.0, 0.0, 0.0],
@ -74,7 +74,7 @@ basePlateSides = patternLinear3d(
)
|> patternLinear3d(axis = [0.0, 1.0, 0.0], instances = countBinLength, distance = binLength)
// create the corners of the baseplate by patterning the corners
// Create the corners of the baseplate by patterning the corners
basePlateCorners = patternLinear3d(
corners,
axis = [1.0, 0.0, 0.0],
@ -83,7 +83,7 @@ basePlateCorners = patternLinear3d(
)
|> patternLinear3d(axis = [0.0, 1.0, 0.0], instances = countBinLength, distance = binLength)
// create the center cutout for the magnet profile
// Create the center cutout for the magnet profile
fn magnetCenterCutout(plane) {
magnetSketch = startSketchOn(plane)
|> startProfileAt([
@ -126,7 +126,7 @@ fn magnetCenterCutout(plane) {
return magnetSketch
}
// create the outside profile of the magnets
// Create the outside profile of the magnets
fn magnetBase(plane) {
magnetBaseSketch = startSketchOn(plane)
|> startProfileAt([0, 0], %)
@ -138,7 +138,7 @@ fn magnetBase(plane) {
return magnetBaseSketch
}
// create sketch profile sketch000Profile002
// Create sketch profile sketch000Profile002
magnetsSketch = startSketchOn(XY)
|> circle(center = [cornerRadius * 2, cornerRadius * 2], radius = magOuterDiam / 2)
|> patternCircular2d(
@ -148,14 +148,14 @@ magnetsSketch = startSketchOn(XY)
rotateDuplicates = true,
)
// create a profile with holes for the magnets
// Create a profile with holes for the magnets
magnetProfile = magnetBase(XY)
|> hole(magnetsSketch, %)
// create an extrusion of the magnet cutout with holes
// Create an extrusion of the magnet cutout with holes
magnetHolesExtrude = extrude(magnetProfile, length = -magDepth)
// add a fillet to the extrusion
// Add a fillet to the extrusion
magnetHolesExtrudeFillets = fillet(
magnetHolesExtrude,
radius = cornerRadius,
@ -167,13 +167,13 @@ magnetHolesExtrudeFillets = fillet(
],
)
// create a profile without the holes for the magnets
// Create a profile without the holes for the magnets
magnetProfileNoMagnets = magnetBase(offsetPlane(XY, offset = -magDepth))
// create an extrusion of the magnet cutout without holes
// Create an extrusion of the magnet cutout without holes
magnetCutoutExtrude = extrude(magnetProfileNoMagnets, length = -magDepth)
// add a fillet to the extrusion
// Add a fillet to the extrusion
magnetCutoutExtrudeFillets = fillet(
magnetCutoutExtrude,
radius = cornerRadius,
@ -185,7 +185,7 @@ magnetCutoutExtrudeFillets = fillet(
],
)
// pattern the magnet cutouts with holes
// Pattern the magnet cutouts with holes
patternLinear3d(
magnetHolesExtrudeFillets,
axis = [1.0, 0.0, 0.0],
@ -194,7 +194,7 @@ patternLinear3d(
)
|> patternLinear3d(axis = [0.0, 1.0, 0.0], instances = countBinLength, distance = binLength)
// pattern the magnet cutouts without holes
// Pattern the magnet cutouts without holes
patternLinear3d(
magnetCutoutExtrudeFillets,
axis = [1.0, 0.0, 0.0],

View File

@ -4,7 +4,7 @@
// Set units in millimeters (mm)
@settings(defaultLengthUnit = mm)
// Define constants
// Define parameters
binLength = 42.0
cornerRadius = 4.0
firstStep = 0.7
@ -18,7 +18,7 @@ countBinLength = 3
// The total height of the baseplate is a summation of the vertical heights of the baseplate steps
height = firstStep + secondStep + thirdStep
// define a function which builds the profile of the baseplate bin
// Define a function which builds the profile of the baseplate bin
fn face(plane) {
faceSketch = startSketchOn(plane)
|> startProfileAt([0, 0], %)
@ -30,10 +30,10 @@ fn face(plane) {
return faceSketch
}
// extrude a single side of the bin
// Extrude a single side of the bin
singleSide = extrude(face(offsetPlane(YZ, offset = cornerRadius)), length = binLength - (cornerRadius * 2))
// create the other sides of the bin by using a circular pattern
// Create the other sides of the bin by using a circular pattern
sides = patternCircular3d(
singleSide,
arcDegrees = 360,
@ -43,16 +43,16 @@ sides = patternCircular3d(
rotateDuplicates = true,
)
// define an axis axis000
// Define an axis axis000
axis000 = {
direction = [0.0, 1.0],
origin = [cornerRadius, cornerRadius]
}
// create a single corner of the bin
// Create a single corner of the bin
singleCorner = revolve(face(offsetPlane(YZ, offset = cornerRadius)), angle = -90, axis = axis000)
// create the corners of the bin
// Create the corners of the bin
corners = patternCircular3d(
singleCorner,
arcDegrees = 360,
@ -62,7 +62,7 @@ corners = patternCircular3d(
rotateDuplicates = true,
)
// create the baseplate by patterning sides
// Create the baseplate by patterning sides
basePlateSides = patternLinear3d(
sides,
axis = [1.0, 0.0, 0.0],
@ -71,7 +71,7 @@ basePlateSides = patternLinear3d(
)
|> patternLinear3d(axis = [0.0, 1.0, 0.0], instances = countBinLength, distance = binLength)
// create the corners of the baseplate by patterning the corners
// Create the corners of the baseplate by patterning the corners
basePlateCorners = patternLinear3d(
corners,
axis = [1.0, 0.0, 0.0],

View File

@ -4,7 +4,7 @@
// Set units in millimeters (mm)
@settings(defaultLengthUnit = mm)
// Define constants
// Define parameters
binLength = 41.5
binHeight = 7.0
binBaseLength = 2.95
@ -33,7 +33,7 @@ countBinHeight = 1
height = firstStep + secondStep + thirdStep
lipHeight = lipStep1 + lipStep2 + lipStep3 + lipStep4 + lipStep5
// define a function which builds the profile of the baseplate bin
// Define a function which builds the profile of the baseplate bin
fn face(plane) {
faceSketch = startSketchOn(plane)
|> startProfileAt([binBaseLength + binTol, 0], %)
@ -46,10 +46,10 @@ fn face(plane) {
return faceSketch
}
// extrude a single side of the bin
// Extrude a single side of the bin
singleSide = extrude(face(offsetPlane(YZ, offset = cornerRadius + binTol)), length = binLength - (cornerRadius * 2))
// create the other sides of the bin by using a circular pattern
// Create the other sides of the bin by using a circular pattern
sides = patternCircular3d(
singleSide,
arcDegrees = 360,
@ -63,7 +63,7 @@ sides = patternCircular3d(
rotateDuplicates = true,
)
// define an axis axis000
// Define an axis axis000
axis000 = {
direction = [0.0, 1.0],
origin = [
@ -72,10 +72,10 @@ axis000 = {
]
}
// create a single corner of the bin
// Create a single corner of the bin
singleCorner = revolve(face(offsetPlane(YZ, offset = cornerRadius + binTol)), angle = -90, axis = axis000)
// create the corners of the bin
// Create the corners of the bin
corners = patternCircular3d(
singleCorner,
arcDegrees = 360,
@ -128,7 +128,7 @@ magCutout000 = startSketchOn(singleBinFill, "start")
)
|> extrude(length = -magDepth)
// create the baseplate by patterning sides
// Create the baseplate by patterning sides
binSides = patternLinear3d(
sides,
axis = [1.0, 0.0, 0.0],
@ -137,7 +137,7 @@ binSides = patternLinear3d(
)
|> patternLinear3d(axis = [0.0, 1.0, 0.0], instances = countBinLength, distance = binLength + binTol * 2)
// create the corners of the baseplate by patterning the corners
// Create the corners of the baseplate by patterning the corners
binCorners = patternLinear3d(
corners,
axis = [1.0, 0.0, 0.0],
@ -146,7 +146,7 @@ binCorners = patternLinear3d(
)
|> patternLinear3d(axis = [0.0, 1.0, 0.0], instances = countBinLength, distance = binLength + binTol * 2)
// create the fill of the bin by patterning the corners
// Create the fill of the bin by patterning the corners
binFill = patternLinear3d(
singleBinFill,
axis = [1.0, 0.0, 0.0],
@ -155,7 +155,6 @@ binFill = patternLinear3d(
)
|> patternLinear3d(axis = [0.0, 1.0, 0.0], instances = countBinLength, distance = binLength + binTol * 2)
//
binTop = startSketchOn(offsetPlane(XY, offset = height))
|> startProfileAt([0, 0], %)
|> xLine(length = (binLength + 2 * binTol) * countBinWidth, tag = $line010)
@ -174,7 +173,7 @@ binTop = startSketchOn(offsetPlane(XY, offset = height))
)
|> shell(faces = ["end"], thickness = binThk)
// define a function which builds the profile of the baseplate bin
// Define a function which builds the profile of the baseplate bin
fn lipFace(plane) {
faceSketch = startSketchOn(plane)
|> startProfileAt([0, 0], %)
@ -234,13 +233,13 @@ plane002 = {
}
}
// extrude a single side of the lip of the bin
// Extrude a single side of the lip of the bin
lipSingleLength = extrude(lipFace(plane000), length = binLength * countBinWidth - (2 * cornerRadius) + 2 * binTol * countBinWidth)
// extrude a single side of the lip of the bin
// Extrude a single side of the lip of the bin
lipSingleWidth = extrude(lipFace(plane001), length = binLength * countBinLength - (2 * cornerRadius) + 2 * binTol * countBinLength)
// create the other sides of the lips by using a circular pattern
// Create the other sides of the lips by using a circular pattern
lipLengths = patternCircular3d(
lipSingleLength,
arcDegrees = 360,
@ -254,7 +253,7 @@ lipLengths = patternCircular3d(
rotateDuplicates = true,
)
// create the other sides of the lips by using a circular pattern
// Create the other sides of the lips by using a circular pattern
lipWidths = patternCircular3d(
lipSingleWidth,
arcDegrees = 360,
@ -268,19 +267,19 @@ lipWidths = patternCircular3d(
rotateDuplicates = true,
)
// define an axis axis000
// Define an axis axis000
axis001 = {
direction = [0.0, 1.0],
origin = [cornerRadius, cornerRadius]
}
// create a single corner of the bin
// Create a single corner of the bin
lipSingleLengthCorner = revolve(lipFace(plane000), angle = -90, axis = axis001)
// create a single corner of the bin
// Create a single corner of the bin
lipSingleWidthCorner = revolve(lipFace(plane002), angle = 90, axis = axis001)
// create the corners of the bin
// Create the corners of the bin
lipCorners000 = patternCircular3d(
lipSingleLengthCorner,
arcDegrees = 360,
@ -294,7 +293,7 @@ lipCorners000 = patternCircular3d(
rotateDuplicates = true,
)
// create the corners of the bin
// Create the corners of the bin
lipCorners001 = patternCircular3d(
lipSingleWidthCorner,
arcDegrees = 360,

View File

@ -4,7 +4,7 @@
// Set units in millimeters (mm)
@settings(defaultLengthUnit = mm)
// Define constants
// Define parameters
binLength = 41.5
binHeight = 7.0
binBaseLength = 2.95
@ -26,7 +26,7 @@ countBinHeight = 2
// The total height of the baseplate is a summation of the vertical heights of the baseplate steps
height = firstStep + secondStep + thirdStep
// define a function which builds the profile of the baseplate bin
// Define a function which builds the profile of the baseplate bin
fn face(plane) {
faceSketch = startSketchOn(plane)
|> startProfileAt([binBaseLength + binTol, 0], %)
@ -39,10 +39,10 @@ fn face(plane) {
return faceSketch
}
// extrude a single side of the bin
// Extrude a single side of the bin
singleSide = extrude(face(offsetPlane(YZ, offset = cornerRadius + binTol)), length = binLength - (cornerRadius * 2))
// create the other sides of the bin by using a circular pattern
// Create the other sides of the bin by using a circular pattern
sides = patternCircular3d(
singleSide,
arcDegrees = 360,
@ -56,7 +56,7 @@ sides = patternCircular3d(
rotateDuplicates = true,
)
// define an axis axis000
// Define an axis axis000
axis000 = {
direction = [0.0, 1.0],
origin = [
@ -65,10 +65,10 @@ axis000 = {
]
}
// create a single corner of the bin
// Create a single corner of the bin
singleCorner = revolve(face(offsetPlane(YZ, offset = cornerRadius + binTol)), angle = -90, axis = axis000)
// create the corners of the bin
// Create the corners of the bin
corners = patternCircular3d(
singleCorner,
arcDegrees = 360,
@ -121,7 +121,7 @@ magCutout000 = startSketchOn(singleBinFill, "start")
)
|> extrude(length = -magDepth)
// create the baseplate by patterning sides
// Create the baseplate by patterning sides
binSides = patternLinear3d(
sides,
axis = [1.0, 0.0, 0.0],
@ -130,7 +130,7 @@ binSides = patternLinear3d(
)
|> patternLinear3d(axis = [0.0, 1.0, 0.0], instances = countBinLength, distance = binLength + binTol * 2)
// create the corners of the baseplate by patterning the corners
// Create the corners of the baseplate by patterning the corners
binCorners = patternLinear3d(
corners,
axis = [1.0, 0.0, 0.0],
@ -139,7 +139,7 @@ binCorners = patternLinear3d(
)
|> patternLinear3d(axis = [0.0, 1.0, 0.0], instances = countBinLength, distance = binLength + binTol * 2)
// create the fill of the bin by patterning the corners
// Create the fill of the bin by patterning the corners
binFill = patternLinear3d(
singleBinFill,
axis = [1.0, 0.0, 0.0],
@ -148,7 +148,7 @@ binFill = patternLinear3d(
)
|> patternLinear3d(axis = [0.0, 1.0, 0.0], instances = countBinLength, distance = binLength + binTol * 2)
// create the top of the bin
// Create the top of the bin
binTop = startSketchOn(offsetPlane(XY, offset = height))
|> startProfileAt([0, 0], %)
|> xLine(length = (binLength + 2 * binTol) * countBinWidth, tag = $line010)

View File

@ -1,10 +1,10 @@
// Hex nut
// Hex Nut
// A hex nut is a type of fastener with a threaded hole and a hexagonal outer shape, used in a wide variety of applications to secure parts together. The hexagonal shape allows for a greater torque to be applied with wrenches or tools, making it one of the most common nut types in hardware.
// Set Units
@settings(defaultLengthUnit = in)
// Define constants (5/16" - 24 thread size)
// Define parameters (5/16" - 24 thread size)
wallToWallLength = 0.5
thickness = 0.266
diameter = 0.3125

View File

@ -1,10 +1,10 @@
// I-beam
// A structural metal beam with an I shaped cross section. Often used in construction and architecture
// Set Units
// Set units
@settings(defaultLengthUnit = in)
// Define Beam Dimensions
// Define parameters
beamLength = 6 * ft()
beamHeight = 4
flangeWidth = 2.663
@ -13,7 +13,7 @@ webThickness = 0.193
rootRadius = 0.457
// Sketch a quadrant of the beam cross section, then mirror for symmetry across each axis. Extrude to the appropriate length
sketch001 = startSketchOn(-XZ)
iBeam = startSketchOn(-XZ)
|> startProfileAt([0, beamHeight / 2], %)
|> xLine(length = flangeWidth / 2)
|> yLine(length = -flangeThickness)

View File

@ -1,10 +1,10 @@
// Zoo Keyboard
// A custom keyboard with Zoo brand lettering
// Set Units
// Set units
@settings(defaultLengthUnit = in)
// Define constants
// Define parameters
baseColor = "#0f0f0f"
highlightColor1 = "#b0b0b0"
highlightColor2 = "#23af93"

View File

@ -1,7 +1,7 @@
// Kitt
// The beloved KittyCAD mascot in a voxelized style.
// pixel box function
// Pixel box function
fn pixelBox(kitExtrude, extrudeTag, positionY, positionZ, width, height, depth) {
pixelBoxBody = startSketchOn(kitExtrude, extrudeTag)
|> startProfileAt([positionY, positionZ], %)

View File

@ -4,8 +4,8 @@
// Set Units
@settings(defaultLengthUnit = in)
// Define constants
lbumps = 4 // number of bumps long
// Define parameters
lbumps = 3 // number of bumps long
wbumps = 2 // number of bumps wide
pitch = 8.0
clearance = 0.1

View File

@ -1,19 +1,19 @@
// Makeup Mirror
// A circular vanity mirror mounted on a swiveling arm with pivot joints, used for personal grooming.
// Settings
// Set units
@settings(defaultLengthUnit = mm)
// hinge
// Hinge parameters
hingeRadius = 8
hingeHeight = hingeRadius * 3
hingeGap = 0.5
// arm
// Arm parameters
armLength = 170
armRadius = 5
// mirror
// Mirror parameters
mirrorRadius = 170 / 2
mirrorThickness = 10
archToMirrorGap = 5
@ -21,7 +21,7 @@ archThickness = 1
archRadius = mirrorRadius + archToMirrorGap
// Geometry
// hinge
// Add a function to create the hinge
fn hingeFn(x, y, z) {
hingeBody = startSketchOn(offsetPlane(XY, offset = z))
|> circle(center = [x, y], radius = hingeRadius)
@ -39,7 +39,7 @@ hingePartB3 = hingeFn(armLength, 0, hingeHeight * 2 + hingeGap * 2)
hingePartC2 = hingeFn(armLength, -armLength, hingeHeight * 2 + hingeGap * 2)
hingePartC3 = hingeFn(armLength, -armLength, hingeHeight * 3 + hingeGap * 3)
// arm
// Add a function to create the arm
fn armFn(plane, offset, altitude) {
armBody = startSketchOn(plane)
|> circle(center = [offset, altitude], radius = armRadius)
@ -50,7 +50,7 @@ fn armFn(plane, offset, altitude) {
armPartA = armFn(YZ, 0, hingeHeight * 1.5 + hingeGap)
armPartB = armFn(XZ, armLength, hingeHeight * 2.5 + hingeGap * 2)
// mirror
// Add a function to create the mirror
fn mirrorFn(plane, offsetX, offsetY, altitude, radius, tiefe, gestellR, gestellD) {
armPlane = startSketchOn( offsetPlane(plane, offset = offsetY - (tiefe / 2)))
armBody = circle(armPlane, center = [offsetX, altitude], radius = radius)

View File

@ -6,13 +6,6 @@
"title": "80/20 Rail",
"description": "An 80/20 extruded aluminum linear rail. T-slot profile adjustable by profile height, rail length, and origin position"
},
{
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "a-parametric-bearing-pillow-block/main.kcl",
"multipleFiles": false,
"title": "A Parametric Bearing Pillow Block",
"description": "A bearing pillow block, also known as a plummer block or pillow block bearing, is a pedestal used to provide support for a rotating shaft with the help of compatible bearings and various accessories. Housing a bearing, the pillow block provides a secure and stable foundation that allows the shaft to rotate smoothly within its machinery setup. These components are essential in a wide range of mechanical systems and machinery, playing a key role in reducing friction and supporting radial and axial loads."
},
{
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "ball-bearing/main.kcl",
@ -157,7 +150,7 @@
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "hex-nut/main.kcl",
"multipleFiles": false,
"title": "Hex nut",
"title": "Hex Nut",
"description": "A hex nut is a type of fastener with a threaded hole and a hexagonal outer shape, used in a wide variety of applications to secure parts together. The hexagonal shape allows for a greater torque to be applied with wrenches or tools, making it one of the most common nut types in hardware."
},
{
@ -209,12 +202,19 @@
"title": "Robot Arm",
"description": "A 4 axis robotic arm for industrial use. These machines can be used for assembly, packaging, organization of goods, and quality inspection processes"
},
{
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "parametric-bearing-pillow-block/main.kcl",
"multipleFiles": false,
"title": "Parametric Bearing Pillow Block",
"description": "A bearing pillow block, also known as a plummer block or pillow block bearing, is a pedestal used to provide support for a rotating shaft with the help of compatible bearings and various accessories. Housing a bearing, the pillow block provides a secure and stable foundation that allows the shaft to rotate smoothly within its machinery setup. These components are essential in a wide range of mechanical systems and machinery, playing a key role in reducing friction and supporting radial and axial loads."
},
{
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "pipe/main.kcl",
"multipleFiles": false,
"title": "Pipe",
"description": "A tubular section or hollow cylinder, usually but not necessarily of circular cross-section, used mainly to convey substances that can flow."
"description": "Piping for the pipe flange assembly"
},
{
"file": "main.kcl",
@ -248,7 +248,7 @@
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "router-template-slate/main.kcl",
"multipleFiles": false,
"title": "Router template for a slate",
"title": "Router Template for a Slate",
"description": "A guide for routing a slate for a cross bar."
},
{

View File

@ -1,10 +1,10 @@
// Mounting Plate
// A flat piece of material, often metal or plastic, that serves as a support or base for attaching, securing, or mounting various types of equipment, devices, or components.
// Set Units
// Set units
@settings(defaultLengthUnit = in)
// Define constants
// Define parameters
plateLength = 10
plateWidth = 6
filletRadius = 0.5

View File

@ -4,6 +4,7 @@
// Set Units
@settings(defaultLengthUnit = in)
// Import parts
import "robot-arm-base.kcl" as robotArmBase
import "robot-rotating-base.kcl" as rotatingBase
import "robot-arm-j2.kcl" as j2RobotArm

View File

@ -1,10 +1,10 @@
// A Parametric Bearing Pillow Block
// Parametric Bearing Pillow Block
// A bearing pillow block, also known as a plummer block or pillow block bearing, is a pedestal used to provide support for a rotating shaft with the help of compatible bearings and various accessories. Housing a bearing, the pillow block provides a secure and stable foundation that allows the shaft to rotate smoothly within its machinery setup. These components are essential in a wide range of mechanical systems and machinery, playing a key role in reducing friction and supporting radial and axial loads.
// Set units
@settings(defaultLengthUnit = in)
// Define constants such as length, width, height, counter-bore depth and diameter, bearing diameter, hole location padding, and more
// Define parameters
length = 6
width = 4
height = 1
@ -14,15 +14,15 @@ holeDia = .375
padding = 1.5
bearingDia = 3
// (Needs to be updated). Sketch the block and extrude up to where the counterbore diameter starts.
extrude001 = startSketchOn(XY)
// Sketch the block body
body = startSketchOn(XY)
|> startProfileAt([-width / 2, -length / 2], %)
|> line(endAbsolute = [width / 2, -length / 2])
|> line(endAbsolute = [width / 2, length / 2])
|> line(endAbsolute = [-width / 2, length / 2])
|> close()
|> extrude(length = height)
extrude002 = startSketchOn(extrude001, 'end')
counterBoreHoles = startSketchOn(body, 'end')
|> circle(
center = [
-(width / 2 - (padding / 2)),
@ -34,7 +34,7 @@ extrude002 = startSketchOn(extrude001, 'end')
|> patternLinear2d(instances = 2, distance = width - padding, axis = [1, 0])
|> extrude(%, length = -cbDepth)
extrude003 = startSketchOn(extrude001, 'start')
boltHoles = startSketchOn(body, 'start')
|> circle(
center = [
-(width / 2 - (padding / 2)),
@ -46,6 +46,6 @@ extrude003 = startSketchOn(extrude001, 'start')
|> patternLinear2d(instances = 2, distance = width - padding, axis = [1, 0])
|> extrude(length = -height + cbDepth)
extrude004 = startSketchOn(extrude001, 'end')
centerHole = startSketchOn(body, 'end')
|> circle(center = [0, 0], radius = bearingDia / 2)
|> extrude(length = -height)

View File

@ -1,25 +1,23 @@
// Pipe
// piping for the pipe flange assembly
// Piping for the pipe flange assembly
// set units
// Set units
@settings(defaultLengthUnit = in)
// import constants
import pipeInnerDiameter, pipeOuterDiameter, pipeLength from "globals.kcl"
// Import parameters
import pipeInnerDiameter, pipeOuterDiameter, pipeLength from "parameters.kcl"
// create a function to make the pipe
// Create a function to make the pipe. Export
export fn pipe() {
// create the pipe base
// Create the pipe base
pipeBase = startSketchOn(XZ)
|> circle(%, center = [0, 0], radius = pipeOuterDiameter / 2)
|> extrude(%, length = pipeLength)
// extrude a hole through the length of the pipe
// Extrude a hole through the length of the pipe
pipe = startSketchOn(pipeBase, 'end')
|> circle(center = [0, 0], radius = pipeInnerDiameter / 2)
|> extrude(%, length = -pipeLength)
|> appearance(color = "#a24ed0")
return pipe
}
// https://www.mcmaster.com/1120T74/

View File

@ -1,15 +1,15 @@
// 68095k348 flange
// flange used for mating two pipes together in the pipe flange assembly.
// Flange
// Flange used for mating two pipes together in the pipe flange assembly.
// set units
// Set units
@settings(defaultLengthUnit = in)
// import constants
import pipeDiameter, mountingHoleDiameter, mountingHolePlacementDiameter, flangeDiameter, flangeTotalThickness, flangeBackHeight, flangeFrontHeight, flangeBaseThickness, flangeBackDiameter, flangeFrontDiameter from "globals.kcl"
// Import parameters
import pipeDiameter, mountingHoleDiameter, mountingHolePlacementDiameter, flangeDiameter, flangeTotalThickness, flangeBackHeight, flangeFrontHeight, flangeBaseThickness, flangeBackDiameter, flangeFrontDiameter from "parameters.kcl"
// create a function to create the flange
// Create a function to create the flange. We must create a function since we are using multiple flanges.
export fn flange() {
// sketch the mounting hole pattern
// Sketch the mounting hole pattern
mountingHoles = startSketchOn(XY)
|> circle(%, center = [0, mountingHolePlacementDiameter / 2], radius = mountingHoleDiameter / 2)
|> patternCircular2d(
@ -20,13 +20,13 @@ export fn flange() {
rotateDuplicates = false,
)
// create the flange base
// Create the flange base
flangeBase = startSketchOn(XY)
|> circle(%, center = [0, 0], radius = flangeDiameter / 2)
|> hole(mountingHoles, %)
|> extrude(%, length = flangeBaseThickness)
// create both the raised portions on the front and back of the flange base
// Create both the raised portions on the front and back of the flange base
flangeBack = startSketchOn(flangeBase, 'start')
|> circle(%, center = [0, 0], radius = flangeBackDiameter / 2)
|> extrude(%, length = flangeBackHeight)
@ -34,7 +34,7 @@ export fn flange() {
|> circle(%, center = [0, 0], radius = flangeFrontDiameter / 2)
|> extrude(%, length = flangeFrontHeight)
// create the circular cut in the center for the pipe
// Create the circular cut in the center for the pipe
pipeCut = startSketchOn(flangeFront, 'end')
|> circle(%, center = [0, 0], radius = pipeDiameter / 2)
|> extrude(%, length = -flangeTotalThickness)
@ -42,5 +42,3 @@ export fn flange() {
return pipeCut
}
// https://www.mcmaster.com/68095K348/

View File

@ -1,13 +1,13 @@
// 91251A404 Socket Head Cap Screw
// Socket Head Cap Screw
// screw for mating the flanges together in the pipe flange assembly
// set units
// Set units
@settings(defaultLengthUnit = in)
// import constants
import boltDiameter, boltLength, boltHeadLength, boltHeadDiameter, boltHexDrive, boltHexFlatLength, boltThreadLength from "globals.kcl"
// Import parameters
import boltDiameter, boltLength, boltHeadLength, boltHeadDiameter, boltHexDrive, boltHexFlatLength, boltThreadLength from "parameters.kcl"
// create a function to make a the bolt
// Create a function to make a the bolt
export fn bolt() {
// Create the head of the cap screw
boltHead = startSketchOn(XZ)
@ -52,5 +52,3 @@ export fn bolt() {
return boltBody
}
// https://www.mcmaster.com/91251a404/

View File

@ -1,26 +1,19 @@
// 9472K188 Gasket
// gasket for the pipe flange assembly. A gasket is a mechanical seal that fills the space between two or more mating surfaces, preventing leaks of liquids or gases under compression
// Gasket
// Gasket for the pipe flange assembly. A gasket is a mechanical seal that fills the space between two or more mating surfaces, preventing leaks of liquids or gases under compression
// set units
// Set units
@settings(defaultLengthUnit = in)
// import constants
import gasketOutsideDiameter, gasketInnerDiameter, gasketThickness from "globals.kcl"
// Import parameters
import gasketOutsideDiameter, gasketInnerDiameter, gasketThickness from "parameters.kcl"
// create a function to make the gasket
export fn gasket() {
// create the base of the gasket
gasketBase = startSketchOn(XY)
|> circle(%, center = [0, 0], radius = gasketOutsideDiameter / 2)
|> extrude(%, length = gasketThickness)
// Create the base of the gasket
gasketBase = startSketchOn(XY)
|> circle(%, center = [0, 0], radius = gasketOutsideDiameter / 2)
|> extrude(%, length = gasketThickness)
// extrude a circular hole through the gasket base
gasket = startSketchOn(gasketBase, 'end')
|> circle(%, center = [0, 0], radius = gasketInnerDiameter / 2)
|> extrude(%, length = -gasketThickness)
|> appearance(%, color = "#d0cb3e")
return gasket
}
// https://www.mcmaster.com/9472K616/
// Extrude a circular hole through the gasket base
startSketchOn(gasketBase, 'end')
|> circle(%, center = [0, 0], radius = gasketInnerDiameter / 2)
|> extrude(%, length = -gasketThickness)
|> appearance(%, color = "#d0cb3e")

View File

@ -1,15 +1,15 @@
// 95479A127 Hex Nut
// hex nut for the screws in the pipe flange assembly.
// Hex Nut
// Hex nut for the screws in the pipe flange assembly.
// set units
// Set units
@settings(defaultLengthUnit = in)
// import constants
import hexNutDiameter, hexNutFlatToFlat, hexNutThickness, hexNutFlatLength from "globals.kcl"
// Import parameters
import hexNutDiameter, hexNutFlatToFlat, hexNutThickness, hexNutFlatLength from "parameters.kcl"
// create a function to make the hex nut
// Create a function to make the hex nut. Must be a function since multiple hex nuts are used
export fn hexNut() {
// create the base of the hex nut
// Create the base of the hex nut
hexNutBase = startSketchOn(XY)
|> startProfileAt([
hexNutFlatToFlat / 2,
@ -38,7 +38,7 @@ export fn hexNut() {
|> close()
|> extrude(length = hexNutThickness)
// create the hole in the center of the hex nut
// Create the hole in the center of the hex nut
hexNut = startSketchOn(hexNutBase, 'end')
|> circle(center = [0, 0], radius = hexNutDiameter / 2)
|> extrude(%, length = -hexNutThickness)
@ -46,4 +46,3 @@ export fn hexNut() {
return hexNut
}
// https://www.mcmaster.com/95479A127/

View File

@ -1,20 +1,20 @@
// 98017A257 Washer
// washer for the screws in the pipe flange assembly.
// Washer for the screws in the pipe flange assembly.
// set units
// Set units
@settings(defaultLengthUnit = in)
// import constants
import washerInnerDia, washerOuterDia, washerThickness from "globals.kcl"
// Import parameters
import washerInnerDia, washerOuterDia, washerThickness from "parameters.kcl"
// create a function to make the washer
// Create a function to make the washer. Must be a function since multiple washers are used.
export fn washer() {
// create the base of the washer
// Create the base of the washer
washerBase = startSketchOn(XY)
|> circle(center = [0, 0], radius = washerOuterDia / 2)
|> extrude(length = washerThickness)
// extrude a hole through the washer
// Extrude a hole through the washer
washer = startSketchOn(washerBase, 'end')
|> circle(center = [0, 0], radius = washerInnerDia / 2)
|> extrude(%, length = -washerThickness)
@ -22,5 +22,3 @@ export fn washer() {
return washer
}
// https://www.mcmaster.com/98017A257/

View File

@ -1,31 +1,31 @@
// Pipe and Flange Assembly
// A crucial component in various piping systems, designed to facilitate the connection, disconnection, and access to piping for inspection, cleaning, and modifications. This assembly combines pipes (long cylindrical conduits) with flanges (plate-like fittings) to create a secure yet detachable joint.
// set units
// Set units
@settings(defaultLengthUnit = in)
// import constants
import * from "globals.kcl"
// Import parameters
import * from "parameters.kcl"
// import parts
// Import parts
import "9472k188-gasket.kcl" as gasket
import flange from "68095k348-flange.kcl"
import gasket from "9472k188-gasket.kcl"
import washer from "98017a257-washer.kcl"
import bolt from "91251a404-bolt.kcl"
import hexNut from "95479a127-hex-nut.kcl"
import pipe from "1120t74-pipe.kcl"
// place flanges
// Place flanges
flange()
flange()
|> rotate(axis = [0, 1, 0], angle = 180)
|> translate(x = 0, y = 0, z = flangeBackHeight * 2 + gasketThickness)
// place gasket between the flanges
gasket()
// Place gasket between the flanges
gasket
|> translate(x = 0, y = 0, z = -flangeBackHeight - gasketThickness)
// place eight washers (four front, four back)
// Place eight washers (four front, four back)
washer()
|> translate(x = mountingHolePlacementDiameter / 2, y = 0, z = flangeBaseThickness)
|> patternCircular3d(
@ -43,7 +43,7 @@ washer()
axis = [0, 0, 1],
)
// place four bolts
// Place four bolts
bolt()
|> translate(x = mountingHolePlacementDiameter / 2, y = 0, z = flangeBaseThickness + washerThickness)
|> rotate(roll = 90, pitch = 0, yaw = 0)
@ -56,7 +56,7 @@ bolt()
rotateDuplicates = false,
)
// place four hex nuts
// Place four hex nuts
hexNut()
|> translate(x = mountingHolePlacementDiameter / 2, y = 0, z = -(flangeBackHeight * 2 + gasketThickness + flangeBaseThickness + washerThickness + hexNutThickness))
|> patternCircular3d(
@ -68,7 +68,7 @@ hexNut()
rotateDuplicates = false,
)
// place both pieces of pipe
// Place both pieces of pipe
pipe()
|> rotate(
%,

View File

@ -1,9 +1,9 @@
// Globals
// Parameters
// set units
// Set units
@settings(defaultLengthUnit = in)
// flange (68095K348)
// Flange (68095K348)
export pipeDiameter = 2.440
export mountingHoleDiameter = 0.750
export mountingHolePlacementDiameter = 4.750
@ -17,12 +17,12 @@ export flangeBaseThickness = flangeTotalThickness - flangeBackHeight - flangeFro
export flangeBackDiameter = 3.620
export flangeFrontDiameter = 3.060
// washer (98017A257)
// Washer (98017A257)
export washerInnerDia = 0.640
export washerOuterDia = 1.188
export washerThickness = 0.032
// bolt (91251A404)
// Bolt (91251A404)
export boltDiameter = 0.625
export boltLength = 2.500
export boltHeadLength = boltDiameter
@ -31,18 +31,18 @@ export boltHexDrive = 1 / 2
export boltHexFlatLength = boltHexDrive / (2 * cos(toRadians(30)))
export boltThreadLength = 1.750
// hex nut (95479A127)
// Hex nut (95479A127)
export hexNutDiameter = 5 / 8
export hexNutFlatToFlat = 15 / 16
export hexNutThickness = 35 / 64
export hexNutFlatLength = hexNutFlatToFlat / (2 * cos(toRadians(30)))
// gasket (9472K188)
// Gasket (9472K188)
export gasketOutsideDiameter = 4.125
export gasketInnerDiameter = 2.375
export gasketThickness = 0.031
// pipe (1120T74)
// Pipe (1120T74)
export pipeInnerDiameter = 2.0
export pipeOuterDiameter = 2.375
export pipeLength = 6

View File

@ -4,24 +4,24 @@
// Set units
@settings(defaultLengthUnit = in)
// Define constants
// Define parameters
innerDiameter = 10
outerDiameter = 20
bendRadius = 30
bendAngle = 90
// create a sketch in the 'XZ' plane
// Create a sketch in the 'XZ' plane
sketch000 = startSketchOn(XZ)
// create a profile for the outer diameter
// Create a profile for the outer diameter
outerProfile = circle(sketch000, center = [bendRadius, 0], radius = outerDiameter / 2)
// create a profile for the inner diameter
// Create a profile for the inner diameter
innerProfile = circle(sketch000, center = [bendRadius, 0], radius = innerDiameter / 2)
// create the profile of the pipe
// Create the profile of the pipe
pipeProfile = outerProfile
|> hole(innerProfile, %)
// revolve the pipe profile at the desired angle
// Revolve the pipe profile at the desired angle
pipe = revolve(pipeProfile, axis = Y, angle = bendAngle)

View File

@ -1,36 +1,21 @@
// Pipe
// A tubular section or hollow cylinder, usually but not necessarily of circular cross-section, used mainly to convey substances that can flow.
// Piping for the pipe flange assembly
// Set Units
// Set units
@settings(defaultLengthUnit = in)
// Define constants
pipeTotalLength = 20
pipeLargeDiaLength = 1
pipeLargeDia = 1
pipeSmallDia = .75
thickness = 0.125
pipeTransitionAngle = 60
pipeTransitionLength = 0.5
pipeSmallDiaLength = pipeTotalLength - pipeTransitionLength - pipeLargeDiaLength
// Define parameters
pipeInnerDiameter = 2.0
pipeOuterDiameter = 2.375
pipeLength = 6
// Create the sketch to be revolved around the y-axis. Use the small diameter, large diameter, length, and thickness to define the sketch.
pipeSketch = startSketchOn(XY)
|> startProfileAt([pipeSmallDia - (thickness / 2), 38], %)
|> line(end = [thickness, 0])
|> line(end = [0, -pipeSmallDiaLength])
|> angledLineOfYLength({
angle = -60,
length = pipeTransitionLength
}, %)
|> line(end = [0, -pipeLargeDiaLength])
|> xLine(length = -thickness)
|> line(end = [0, pipeLargeDiaLength])
|> angledLineToX({
angle = -pipeTransitionAngle + 180,
to = pipeSmallDia - (thickness / 2)
}, %)
|> close()
// Create the pipe base
pipeBase = startSketchOn(XZ)
|> circle(%, center = [0, 0], radius = pipeOuterDiameter / 2)
|> extrude(%, length = pipeLength)
// Revolve the sketch to create the pipe
pipe = revolve(pipeSketch, axis = Y)
// Extrude a hole through the length of the pipe
pipe = startSketchOn(pipeBase, 'end')
|> circle(center = [0, 0], radius = pipeInnerDiameter / 2)
|> extrude(%, length = -pipeLength)
|> appearance(color = "#a24ed0")

View File

@ -4,6 +4,7 @@
// Set units
@settings(defaultLengthUnit = in)
// Define parameters
wallThickness = 0.125
wallsWidth = 3
height = 5.125
@ -12,6 +13,7 @@ backLength = 6
exitHeight = 1
frontLength = 7
// Create the curved portion that catches the printer poop
sketch001 = startSketchOn(-YZ)
|> startProfileAt([wallsWidth / 2, 0], %)
|> xLine(length = wallThickness / 2)
@ -78,6 +80,7 @@ sketch003 = startSketchOn(customPlane)
|> close()
|> extrude(length = wallThickness)
// Create the right side wall of the tub
sketch004 = startSketchOn(sketch002, 'END')
|> startProfileAt([0, 0], %)
|> yLine(endAbsolute = height)

View File

@ -1,18 +1,23 @@
// Router template for a cross bar
// A guide for routing a notch into a cross bar.
// Set Units
// Set units
@settings(defaultLengthUnit = mm)
// Define parameters
routerDiameter = 12.7
templateDiameter = 11 / 16 * inch()
templateGap = (templateDiameter - routerDiameter) / 2 - 0.5
slateWidthHalf = 41.5 / 2
minClampingDistance = 50 + 30
templateThickness = 10
radius = 10
depth = 30
// Calculated parameters
templateGap = (templateDiameter - routerDiameter) / 2 - 0.5
distanceToInsideEdge = slateWidthHalf + templateThickness + templateGap
// Create the first sketch
sketch001 = startSketchOn(XZ)
|> startProfileAt([0, depth + templateGap], %)
|> xLine(length = slateWidthHalf - radius, tag = $seg01)
@ -44,9 +49,12 @@ sketch001 = startSketchOn(XZ)
}, %)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
// Extrude the first sketch
extrude001 = extrude(sketch001, length = 5)
sketch003 = startSketchOn(extrude001, 'START')
// Create the second sketch
sketch002 = startSketchOn(extrude001, 'START')
|> startProfileAt([distanceToInsideEdge, 0], %)
|> angledLine([180, templateThickness], %, $rectangleSegmentA002)
|> angledLine([
@ -59,9 +67,12 @@ sketch003 = startSketchOn(extrude001, 'START')
], %, $rectangleSegmentC002)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
extrude003 = extrude(sketch003, length = 13)
sketch002 = startSketchOn(extrude001, 'START')
// Extrude the second sketch
extrude002 = extrude(sketch002, length = 13)
// Create the third sketch
sketch003 = startSketchOn(extrude001, 'START')
|> startProfileAt([-distanceToInsideEdge, 0], %)
|> angledLine([0, templateThickness], %, $rectangleSegmentA001)
|> angledLine([
@ -75,8 +86,10 @@ sketch002 = startSketchOn(extrude001, 'START')
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
extrude002 = extrude(sketch002, length = 13)
// Extrude the third sketch
extrude003 = extrude(sketch003, length = 13)
// Create the fourth sketch
sketch004 = startSketchOn(extrude002, 'END')
|> startProfileAt([-distanceToInsideEdge, 0], %)
|> angledLine([0, distanceToInsideEdge * 2], %, $rectangleSegmentA003)
@ -90,4 +103,6 @@ sketch004 = startSketchOn(extrude002, 'END')
], %, $rectangleSegmentC003)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
// Extrude the fourth sketch
extrude004 = extrude(sketch004, length = 4)

View File

@ -1,18 +1,20 @@
// Router template for a slate
// Router Template for a Slate
// A guide for routing a slate for a cross bar.
// Set Units
// Set units
@settings(defaultLengthUnit = mm)
// Define constants
// Define parameters
routerDiameter = 12.7
templateDiameter = 11 / 16 * inch()
templateGap = (templateDiameter - routerDiameter) / 2 - 0.5
slateWidthHalf = 41.5 / 2
minClampingDistance = 50 + 30
templateThickness = 10
radius = 10
depth = 30
// Calculated parameters
templateGap = (templateDiameter - routerDiameter) / 2 - 0.5
length001 = slateWidthHalf - radius
length002 = depth + minClampingDistance

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 87 KiB

View File

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 57 KiB

View File

@ -1,7 +1,7 @@
// Sheet Metal Bracket
// A component typically made from flat sheet metal through various manufacturing processes such as bending, punching, cutting, and forming. These brackets are used to support, attach, or mount other hardware components, often providing a structural or functional base for assembly.
// Set Units
// Set units
@settings(defaultLengthUnit = in)
// Input bolt pattern dimensions to mount the bracket
@ -14,13 +14,13 @@ componentBoltDiameter = 3 / 16
componentBoltPatternX = 2
componentBoltPatternY = 3
// Define bracket constants such as sheet metal thickness, bend radius, flange length, etc.
// Define bracket parameters such as sheet metal thickness, bend radius, flange length, etc.
hatHeight = 2.5
bendAngle = 75
thickness = 0.125
interiorBendRadius = 0.125
// Calculate Remaining Parameters
// Calculate remaining parameters
exteriorBendRadius = interiorBendRadius + thickness
overhang = 3 * mountingBoltDiameter
flangeLength = 6 * mountingBoltDiameter

View File

@ -1,58 +1,53 @@
// Socket Head Cap Screw
// This is for a #10-24 screw that is 1.00 inches long. A socket head cap screw is a type of fastener that is widely used in a variety of applications requiring a high strength fastening solution. It is characterized by its cylindrical head and internal hexagonal drive, which allows for tightening with an Allen wrench or hex key.
// set units
@settings(defaultLengthUnit = in, defaultAngleUnit = deg)
// Set units
@settings(defaultLengthUnit = in)
export boltDiameter = 0.190
export boltLength = 1.0
export boltHeadLength = boltDiameter
export boltHeadDiameter = 0.313
export boltHexDrive = 5 / 32
export boltHexFlatLength = boltHexDrive / (2 * cos(toRadians(30)))
// Define parameters
boltDiameter = 0.190
boltLength = 1.0
boltHeadLength = boltDiameter
boltHeadDiameter = 0.313
boltHexDrive = 5 / 32
boltHexFlatLength = boltHexDrive / (2 * cos(toRadians(30)))
export fn bolt() {
// Create the head of the cap screw
boltHead = startSketchOn(XZ)
|> circle(center = [0, 0], radius = boltHeadDiameter / 2, tag = $topEdge)
|> extrude(length = -boltHeadLength)
|> fillet(radius = 0.020, tags = [topEdge, getOppositeEdge(topEdge)])
// Create the head of the cap screw
boltHead = startSketchOn(XZ)
|> circle(center = [0, 0], radius = boltHeadDiameter / 2, tag = $topEdge)
|> extrude(length = -boltHeadLength)
|> fillet(radius = 0.020, tags = [topEdge, getOppositeEdge(topEdge)])
// Define the sketch of the hex pattern on the screw head
hexPatternSketch = startSketchOn(boltHead, 'start')
|> startProfileAt([
boltHexDrive / 2,
boltHexFlatLength / 2
], %)
|> angledLine({
angle = 270,
length = boltHexFlatLength
}, %)
|> angledLine({
angle = 210,
length = boltHexFlatLength
}, %)
|> angledLine({
angle = 150,
length = boltHexFlatLength
}, %)
|> angledLine({
angle = 90,
length = boltHexFlatLength
}, %)
|> angledLine({
angle = 30,
length = boltHexFlatLength
}, %)
|> close()
|> extrude(length = -boltHeadLength * 0.75)
boltBody = startSketchOn(boltHead, 'end')
|> circle(center = [0, 0], radius = boltDiameter / 2, tag = $filletEdge)
|> extrude(length = boltLength)
|> fillet(radius = .020, tags = [getOppositeEdge(filletEdge)])
|> appearance(color = "#4dd043", metalness = 90, roughness = 90)
return boltBody
}
bolt()
// Define the sketch of the hex pattern on the screw head
hexPatternSketch = startSketchOn(boltHead, 'start')
|> startProfileAt([
boltHexDrive / 2,
boltHexFlatLength / 2
], %)
|> angledLine({
angle = 270,
length = boltHexFlatLength
}, %)
|> angledLine({
angle = 210,
length = boltHexFlatLength
}, %)
|> angledLine({
angle = 150,
length = boltHexFlatLength
}, %)
|> angledLine({
angle = 90,
length = boltHexFlatLength
}, %)
|> angledLine({
angle = 30,
length = boltHexFlatLength
}, %)
|> close()
|> extrude(length = -boltHeadLength * 0.75)
boltBody = startSketchOn(boltHead, 'end')
|> circle(center = [0, 0], radius = boltDiameter / 2, tag = $filletEdge)
|> extrude(length = boltLength)
|> fillet(radius = .020, tags = [getOppositeEdge(filletEdge)])
|> appearance(color = "#4dd043", metalness = 90, roughness = 90)

View File

@ -1,35 +1,32 @@
// Walkie talkie antenna
// antenna for the walkie talkie assembly
// Walkie Talkie Antenna
// Antenna for the walkie talkie assembly
// Set units
@settings(defaultLengthUnit = in)
// import constants
import antennaLength, antennaBaseWidth, antennaBaseHeight, antennaTopWidth, antennaTopHeight from "globals.kcl"
// Import parameters
import antennaLength, antennaBaseWidth, antennaBaseHeight, antennaTopWidth, antennaTopHeight from "parameters.kcl"
export fn antenna() {
// Create the antenna base sketch
sketch001 = startSketchOn(XY)
|> startProfileAt([0, 0], %)
|> line(end = [antennaBaseWidth, 0])
|> line(end = [0, -antennaBaseHeight])
|> line(end = [-antennaBaseWidth, 0])
|> close()
// Create the antenna base sketch
antennaBaseSketch = startSketchOn(XY)
|> startProfileAt([0, 0], %)
|> line(end = [antennaBaseWidth, 0])
|> line(end = [0, -antennaBaseHeight])
|> line(end = [-antennaBaseWidth, 0])
|> close()
// Create the antenna top sketch
loftPlane = offsetPlane(XY, offset = antennaLength)
sketch002 = startSketchOn(loftPlane)
|> startProfileAt([
(antennaBaseWidth - antennaTopWidth) / 2,
(antennaBaseHeight - antennaTopHeight) / 2
], %)
|> xLine(length = antennaTopWidth)
|> yLine(length = -antennaTopHeight)
|> xLine(length = -antennaTopWidth)
|> close()
// Create the antenna top sketch
loftPlane = offsetPlane(XY, offset = antennaLength)
antennaTopSketch = startSketchOn(loftPlane)
|> startProfileAt([
(antennaBaseWidth - antennaTopWidth) / 2,
(antennaBaseHeight - antennaTopHeight) / 2
], %)
|> xLine(length = antennaTopWidth)
|> yLine(length = -antennaTopHeight)
|> xLine(length = -antennaTopWidth)
|> close()
// Create the antenna using a loft
antenna = loft([sketch001, sketch002])
|> appearance(color = "#000000")
return antenna
}
// Create the antenna using a loft
loft([antennaBaseSketch, antennaTopSketch])
|> appearance(color = "#000000")

View File

@ -1,84 +1,78 @@
// Walkie talkie body
// the main body of the walkie talkie assembly
// Walkie Talkie Body
// The main body of the walkie talkie assembly
// set units
// Set units
@settings(defaultLengthUnit = in)
// import constants
import height, width, thickness, chamferLength, offset, screenWidth, screenHeight, screenYPosition, screenDepth, speakerBoxWidth, speakerBoxHeight from "globals.kcl"
// Import parameters
import height, width, thickness, chamferLength, offset, screenWidth, screenHeight, screenYPosition, screenDepth, speakerBoxWidth, speakerBoxHeight from "parameters.kcl"
// create a function to define the body
export fn body() {
// sketch and extrude the body of the walkie talkie
bodySketch = startSketchOn(XZ)
|> startProfileAt([-width / 2, height / 2], %)
|> xLine(length = width, tag = $chamfer1)
|> yLine(length = -height, tag = $chamfer2)
|> xLine(length = -width, tag = $chamfer3)
|> close(tag = $chamfer4)
bodyExtrude = extrude(bodySketch, length = thickness)
|> chamfer(
length = chamferLength,
tags = [
getNextAdjacentEdge(chamfer1),
getNextAdjacentEdge(chamfer2),
getNextAdjacentEdge(chamfer3),
getNextAdjacentEdge(chamfer4)
],
)
// Sketch and extrude the body of the walkie talkie
body = startSketchOn(XZ)
|> startProfileAt([-width / 2, height / 2], %)
|> xLine(length = width, tag = $chamfer1)
|> yLine(length = -height, tag = $chamfer2)
|> xLine(length = -width, tag = $chamfer3)
|> close(tag = $chamfer4)
|> extrude(%, length = thickness)
|> chamfer(
length = chamferLength,
tags = [
getNextAdjacentEdge(chamfer1),
getNextAdjacentEdge(chamfer2),
getNextAdjacentEdge(chamfer3),
getNextAdjacentEdge(chamfer4)
],
)
// cut out the indentation for the case
sketch002 = startSketchOn(bodyExtrude, 'END')
|> startProfileAt([
-width / 2 + offset,
height / 2 - (chamferLength + offset / 2 * cos(toRadians(45)))
], %)
|> angledLineToY({ angle = 45, to = height / 2 - offset }, %)
|> line(endAbsolute = [
width / 2 - (chamferLength + offset / 2 * cos(toRadians(45))),
height / 2 - offset
])
|> angledLineToX({ angle = -45, to = width / 2 - offset }, %)
|> line(endAbsolute = [
width / 2 - offset,
-(height / 2 - (chamferLength + offset / 2 * cos(toRadians(45))))
])
|> angledLineToY({
angle = -135,
to = -height / 2 + offset
}, %)
|> line(endAbsolute = [
-(width / 2 - (chamferLength + offset / 2 * cos(toRadians(45)))),
-height / 2 + offset
])
|> angledLineToX({
angle = -225,
to = -width / 2 + offset
}, %)
|> close()
extrude002 = extrude(sketch002, length = -0.0625)
// Cut out the indentation for the case
caseIndentSketch = startSketchOn(body, 'END')
|> startProfileAt([
-width / 2 + offset,
height / 2 - (chamferLength + offset / 2 * cos(toRadians(45)))
], %)
|> angledLineToY({ angle = 45, to = height / 2 - offset }, %)
|> line(endAbsolute = [
width / 2 - (chamferLength + offset / 2 * cos(toRadians(45))),
height / 2 - offset
])
|> angledLineToX({ angle = -45, to = width / 2 - offset }, %)
|> line(endAbsolute = [
width / 2 - offset,
-(height / 2 - (chamferLength + offset / 2 * cos(toRadians(45))))
])
|> angledLineToY({
angle = -135,
to = -height / 2 + offset
}, %)
|> line(endAbsolute = [
-(width / 2 - (chamferLength + offset / 2 * cos(toRadians(45)))),
-height / 2 + offset
])
|> angledLineToX({
angle = -225,
to = -width / 2 + offset
}, %)
|> close()
extrude002 = extrude(caseIndentSketch, length = -0.0625)
// Create the pocket for the screen
sketch003 = startSketchOn(extrude002, 'start')
|> startProfileAt([-screenWidth / 2, screenYPosition], %)
|> xLine(length = screenWidth, tag = $seg01)
|> yLine(length = -screenHeight)
|> xLine(length = -segLen(seg01))
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
extrude003 = extrude(sketch003, length = screenDepth)
// Create the pocket for the screen
screenCutout = startSketchOn(extrude002, 'start')
|> startProfileAt([-screenWidth / 2, screenYPosition], %)
|> xLine(length = screenWidth, tag = $seg01)
|> yLine(length = -screenHeight)
|> xLine(length = -segLen(seg01))
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
extrude003 = extrude(screenCutout, length = screenDepth)
// Create the speaker box
sketch004 = startSketchOn(extrude002, 'start')
|> startProfileAt([-1.25 / 2, -.125], %)
|> xLine(length = speakerBoxWidth)
|> yLine(length = -speakerBoxHeight)
|> xLine(length = -speakerBoxWidth)
|> close()
// Create the speaker box
speakerBox = startSketchOn(extrude002, 'start')
|> startProfileAt([-1.25 / 2, -.125], %)
|> xLine(length = speakerBoxWidth)
|> yLine(length = -speakerBoxHeight)
|> xLine(length = -speakerBoxWidth)
|> close()
body = extrude(sketch004, length = -.5)
|> appearance(color = "#277bb0")
return body
}
body()
extrude(speakerBox, length = -.5)
|> appearance(color = "#277bb0")

View File

@ -1,21 +1,24 @@
// Walkie Talkie button
// Walkie Talkie Button
// Button for the walkie talkie
// set units
// Set units
@settings(defaultLengthUnit = in)
// import constants
import buttonWidth, buttonHeight, buttonThickness from "globals.kcl"
// Import parameters
import buttonWidth, buttonHeight, buttonThickness from "parameters.kcl"
// Create a function for the button. We need to create a function to use multiple buttons.
// create a function to define the button
export fn button() {
// sketch the button profile and extrude
// Sketch the button profile and extrude
buttonSketch = startSketchOn(XZ)
|> startProfileAt([0, 0], %)
|> angledLine({ angle = 180, length = buttonWidth }, %, $tag1)
|> angledLine({ angle = 270, length = buttonHeight }, %, $tag2)
|> angledLine({ angle = 0, length = buttonWidth }, %)
|> close()
buttonExtrude = extrude(buttonSketch, length = buttonThickness)
button = extrude(buttonSketch, length = buttonThickness)
|> chamfer(
length = .050,
tags = [
@ -25,5 +28,5 @@ export fn button() {
)
|> appearance(color = "#ff0000")
return buttonExtrude
return button
}

View File

@ -1,88 +1,83 @@
// Walkie talkie case
// the plastic case for the front of the walkie talkie
// Walkie Talkie Case
// The plastic case for the front of the walkie talkie
// set units
// Set units
@settings(defaultLengthUnit = in)
// import constants and Zoo logo
import width, height, chamferLength, offset, screenWidth, screenHeight, screenYPosition, screenDepth, speakerBoxWidth, speakerBoxHeight, squareHoleSideLength, caseTolerance from "globals.kcl"
// Import parameters and Zoo logo
import width, height, chamferLength, offset, screenWidth, screenHeight, screenYPosition, screenDepth, speakerBoxWidth, speakerBoxHeight, squareHoleSideLength, caseTolerance from "parameters.kcl"
import zLogo, oLogo, oLogo2 from "zoo-logo.kcl"
// create a function to define the case
export fn case() {
// sketch the profile of the screen
sketch006 = startSketchOn(startSketchOn(XZ))
|> startProfileAt([-screenWidth / 2, screenYPosition], %)
|> xLine(length = screenWidth)
|> yLine(length = -screenHeight)
|> xLine(length = -screenWidth)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
// Sketch the profile of the screen
screenSketch = startSketchOn(XZ)
|> startProfileAt([-screenWidth / 2, screenYPosition], %)
|> xLine(length = screenWidth)
|> yLine(length = -screenHeight)
|> xLine(length = -screenWidth)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
// create transform functions for the speaker grid pattern
fn transformX(i) {
return { translate = [.125 * i, 0] }
}
fn transformY(i) {
return { translate = [0, -.125 * i] }
}
// sketch the square hole grid pattern
squareHolePatternSketch = startSketchOn(startSketchOn(XZ))
|> startProfileAt([-screenWidth / 2 + .100, 0], %)
|> line(end = [squareHoleSideLength / 2, 0])
|> line(end = [0, -squareHoleSideLength / 2])
|> line(end = [-squareHoleSideLength / 2, 0])
|> close()
|> patternTransform2d(instances = 13, transform = transformX)
|> patternTransform2d(instances = 11, transform = transformY)
// sketch the outer profile of the case and extrude with holes using the previously made profiles
sketch005 = startSketchOn(startSketchOn(XZ))
|> startProfileAt([
-width / 2 + offset + caseTolerance,
height / 2 - (chamferLength + (offset + caseTolerance) / 2 * cos(toRadians(45)))
], %)
|> angledLineToY({
angle = 45,
to = height / 2 - (offset + caseTolerance)
}, %)
|> line(endAbsolute = [
width / 2 - (chamferLength + (offset + caseTolerance) / 2 * cos(toRadians(45))),
height / 2 - (offset + caseTolerance)
])
|> angledLineToX({
angle = -45,
to = width / 2 - (offset + caseTolerance)
}, %)
|> line(endAbsolute = [
width / 2 - (offset + caseTolerance),
-(height / 2 - (chamferLength + (offset + caseTolerance) / 2 * cos(toRadians(45))))
])
|> angledLineToY({
angle = -135,
to = -height / 2 + offset + caseTolerance
}, %)
|> line(endAbsolute = [
-(width / 2 - (chamferLength + (offset + caseTolerance) / 2 * cos(toRadians(45)))),
-height / 2 + offset + caseTolerance
])
|> angledLineToX({
angle = -225,
to = -width / 2 + offset + caseTolerance
}, %)
|> close()
|> hole(sketch006, %)
|> hole(squareHolePatternSketch, %)
// create the Zoo logo
|> hole(zLogo(startSketchOn(XZ), [-.30, -1.825], .20), %)
|> hole(oLogo(startSketchOn(XZ), [-.075, -1.825], .20), %)
|> hole(oLogo2(startSketchOn(XZ), [-.075, -1.825], .20), %)
|> hole(oLogo(startSketchOn(XZ), [.175, -1.825], .20), %)
|> hole(oLogo2(startSketchOn(XZ), [.175, -1.825], .20), %)
case = extrude(sketch005, length = -0.0625)
|> appearance(color = '#D0FF01', metalness = 0, roughness = 50)
return case
// Create transform functions for the speaker grid pattern
fn transformX(i) {
return { translate = [.125 * i, 0] }
}
fn transformY(i) {
return { translate = [0, -.125 * i] }
}
// Sketch the square hole grid pattern
squareHolePatternSketch = startSketchOn(XZ)
|> startProfileAt([-screenWidth / 2 + .100, 0], %)
|> line(end = [squareHoleSideLength / 2, 0])
|> line(end = [0, -squareHoleSideLength / 2])
|> line(end = [-squareHoleSideLength / 2, 0])
|> close()
|> patternTransform2d(instances = 13, transform = transformX)
|> patternTransform2d(instances = 11, transform = transformY)
// Sketch the outer profile of the case and extrude with holes using the previously made profiles
case = startSketchOn(XZ)
|> startProfileAt([
-width / 2 + offset + caseTolerance,
height / 2 - (chamferLength + (offset + caseTolerance) / 2 * cos(toRadians(45)))
], %)
|> angledLineToY({
angle = 45,
to = height / 2 - (offset + caseTolerance)
}, %)
|> line(endAbsolute = [
width / 2 - (chamferLength + (offset + caseTolerance) / 2 * cos(toRadians(45))),
height / 2 - (offset + caseTolerance)
])
|> angledLineToX({
angle = -45,
to = width / 2 - (offset + caseTolerance)
}, %)
|> line(endAbsolute = [
width / 2 - (offset + caseTolerance),
-(height / 2 - (chamferLength + (offset + caseTolerance) / 2 * cos(toRadians(45))))
])
|> angledLineToY({
angle = -135,
to = -height / 2 + offset + caseTolerance
}, %)
|> line(endAbsolute = [
-(width / 2 - (chamferLength + (offset + caseTolerance) / 2 * cos(toRadians(45)))),
-height / 2 + offset + caseTolerance
])
|> angledLineToX({
angle = -225,
to = -width / 2 + offset + caseTolerance
}, %)
|> close()
|> hole(screenSketch, %)
|> hole(squareHolePatternSketch, %)
// Create the Zoo logo
|> hole(zLogo(startSketchOn(XZ), [-.30, -1.825], .20), %)
|> hole(oLogo(startSketchOn(XZ), [-.075, -1.825], .20), %)
|> hole(oLogo2(startSketchOn(XZ), [-.075, -1.825], .20), %)
|> hole(oLogo(startSketchOn(XZ), [.175, -1.825], .20), %)
|> hole(oLogo2(startSketchOn(XZ), [.175, -1.825], .20), %)
extrude(case, length = -0.0625)
|> appearance(color = '#D0FF01', metalness = 0, roughness = 50)

View File

@ -1,28 +1,23 @@
// Walkie talkie frequency knob
// the frequency knob for the walkie talkie assembly
// Walkie Talkie Frequency Knob
// The frequency knob for the walkie talkie assembly
// set units
// Set units
@settings(defaultLengthUnit = in)
// import constants
import width, thickness, height, knobDiameter, knobHeight, knobRadius from "globals.kcl"
// Import parameters
import width, thickness, height, knobDiameter, knobHeight, knobRadius from "parameters.kcl"
// create a function to define the knob
export fn knob() {
// Create the knob sketch and revolve
knob = startSketchOn(XZ)
|> startProfileAt([0.0001, 0], %)
|> xLine(length = knobDiameter / 2)
|> yLine(length = knobHeight - 0.05)
|> arc({
angleStart = 0,
angleEnd = 90,
radius = .05
}, %)
|> xLine(endAbsolute = 0.0001)
|> close()
|> revolve(axis = Y)
|> appearance(color = '#D0FF01', metalness = 90, roughness = 50)
return knob
}
// Create the knob sketch and revolve
startSketchOn(XZ)
|> startProfileAt([0.0001, 0], %)
|> xLine(length = knobDiameter / 2)
|> yLine(length = knobHeight - 0.05)
|> arc({
angleStart = 0,
angleEnd = 90,
radius = .05
}, %)
|> xLine(endAbsolute = 0.0001)
|> close()
|> revolve(axis = Y)
|> appearance(color = '#D0FF01', metalness = 90, roughness = 50)

View File

@ -5,36 +5,36 @@
@settings(defaultLengthUnit = in)
// import constants
import * from "globals.kcl"
import * from "parameters.kcl"
// import parts and constants
import body from "body.kcl"
import case from "case.kcl"
import antenna from "antenna.kcl"
import talkButton from "talk-button.kcl"
import knob from "knob.kcl"
// import parts and parameters
import "body.kcl" as body
import "case.kcl" as case
import "antenna.kcl" as antenna
import "talk-button.kcl" as talkButton
import "knob.kcl" as knob
import button from "button.kcl"
// import the body
body()
// Import the body
body
// import the antenna
antenna()
// Import the antenna
antenna
|> translate(x = -width / 2 + .45, y = -0.10, z = height / 2)
// import the case
case()
// Import the case
case
|> translate(x = 0, y = -1, z = 0)
// import the talk button
talkButton()
// Import the talk button
talkButton
|> translate(x = width / 2, y = -thickness / 2, z = .5)
// import the frequency knob
knob()
// Import the frequency knob
knob
|> translate(x = width / 2 - 0.70, y = -thickness / 2, z = height / 2)
// import the buttons
// Import the buttons
button()
|> translate(x = -(screenWidth / 2 + tolerance), y = -1, z = screenYPosition)
button()

View File

@ -1,4 +1,4 @@
// Global constants for the walkie talkie
// Global parameters for the walkie talkie
// Set units
@settings(defaultLengthUnit = in)

View File

@ -1,35 +1,31 @@
// Walkie talkie talk button
// set units
// Set units
@settings(defaultLengthUnit = in)
// import constants
import width, thickness, talkButtonSideLength, talkButtonHeight from "globals.kcl"
// Import parameters
import width, thickness, talkButtonSideLength, talkButtonHeight from "parameters.kcl"
export fn talkButton() {
// create the talk button sketch
talkButtonSketch = startSketchOn(YZ)
|> startProfileAt([
-talkButtonSideLength / 2,
talkButtonSideLength / 2
], %)
|> xLine(length = talkButtonSideLength, tag = $tag1)
|> yLine(length = -talkButtonSideLength, tag = $tag2)
|> xLine(length = -talkButtonSideLength, tag = $tag3)
|> close(tag = $tag4)
// Create the talk button sketch
talkButtonSketch = startSketchOn(YZ)
|> startProfileAt([
-talkButtonSideLength / 2,
talkButtonSideLength / 2
], %)
|> xLine(length = talkButtonSideLength, tag = $tag1)
|> yLine(length = -talkButtonSideLength, tag = $tag2)
|> xLine(length = -talkButtonSideLength, tag = $tag3)
|> close(tag = $tag4)
// create the talk button and apply fillets
talkButton = extrude(talkButtonSketch, length = talkButtonHeight)
|> fillet(
radius = 0.050,
tags = [
getNextAdjacentEdge(tag1),
getNextAdjacentEdge(tag2),
getNextAdjacentEdge(tag3),
getNextAdjacentEdge(tag4)
],
)
|> appearance(color = '#D0FF01', metalness = 90, roughness = 90)
return talkButton
}
// create the talk button and apply fillets
extrude(talkButtonSketch, length = talkButtonHeight)
|> fillet(
radius = 0.050,
tags = [
getNextAdjacentEdge(tag1),
getNextAdjacentEdge(tag2),
getNextAdjacentEdge(tag3),
getNextAdjacentEdge(tag4)
],
)
|> appearance(color = '#D0FF01', metalness = 90, roughness = 90)

View File

@ -4,21 +4,16 @@
// Set units
@settings(defaultLengthUnit = in)
// Define constants in inches (in)
// Define parameters
innerDiameter = 0.203
outerDiameter = 0.438
thicknessMax = 0.038
thicknessNom = 0.032
thicknessMin = 0.024
// Write a function that defines the washer and extrude it.
fn washer(plane, innerDia, outerDia, thk) {
// Define the sketch of the washer
washerSketch = startSketchOn(plane)
|> circle(center = [0, 0], radius = outerDia / 2)
|> hole(circle(center = [0, 0], radius = innerDia / 2), %)
// Define the sketch of the washer
washerSketch = startSketchOn(XY)
|> circle(center = [0, 0], radius = outerDiameter / 2)
|> hole(circle(center = [0, 0], radius = innerDiameter / 2), %)
washer = extrude(washerSketch, length = thk)
return washer
}
washer(XY, innerDiameter, outerDiameter, thicknessMax)
washer = extrude(washerSketch, length = thicknessNom)

20
rust/Cargo.lock generated
View File

@ -1907,6 +1907,7 @@ dependencies = [
"serde_json",
"sha2",
"tabled",
"tempdir",
"thiserror 2.0.12",
"tokio",
"tokio-tungstenite",
@ -3084,6 +3085,15 @@ version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]]
name = "remove_dir_all"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
dependencies = [
"winapi",
]
[[package]]
name = "reqwest"
version = "0.12.15"
@ -3779,6 +3789,16 @@ version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e502f78cdbb8ba4718f566c418c52bc729126ffd16baee5baa718cf25dd5a69a"
[[package]]
name = "tempdir"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8"
dependencies = [
"rand 0.4.6",
"remove_dir_all",
]
[[package]]
name = "tempfile"
version = "3.19.0"

View File

@ -22,7 +22,6 @@ debug = 0
[profile.dev.package]
insta = { opt-level = 3 }
similar = { opt-level = 3 }
[profile.test]
debug = "line-tables-only"

View File

@ -69,6 +69,7 @@ serde = { workspace = true }
serde_json = { workspace = true }
sha2 = "0.10.8"
tabled = { version = "0.18.0", optional = true }
tempdir = "0.3.7"
thiserror = "2.0.0"
toml = "0.8.19"
ts-rs = { version = "10.1.0", features = [

View File

@ -18,7 +18,7 @@ use tokio::sync::{mpsc, oneshot, RwLock};
use tokio_tungstenite::tungstenite::Message as WsMsg;
use uuid::Uuid;
use super::{EngineStats, ExecutionKind};
use super::EngineStats;
use crate::{
engine::EngineManager,
errors::{KclError, KclErrorDetails},
@ -51,7 +51,6 @@ pub struct EngineConnection {
/// If the server sends session data, it'll be copied to here.
session_data: Arc<RwLock<Option<ModelingSessionData>>>,
execution_kind: Arc<RwLock<ExecutionKind>>,
stats: EngineStats,
}
@ -344,7 +343,6 @@ impl EngineConnection {
artifact_commands: Arc::new(RwLock::new(Vec::new())),
default_planes: Default::default(),
session_data,
execution_kind: Default::default(),
stats: Default::default(),
})
}
@ -368,18 +366,6 @@ impl EngineManager for EngineConnection {
self.artifact_commands.clone()
}
async fn execution_kind(&self) -> ExecutionKind {
let guard = self.execution_kind.read().await;
*guard
}
async fn replace_execution_kind(&self, execution_kind: ExecutionKind) -> ExecutionKind {
let mut guard = self.execution_kind.write().await;
let original = *guard;
*guard = execution_kind;
original
}
fn stats(&self) -> &EngineStats {
&self.stats
}

View File

@ -16,7 +16,7 @@ use kittycad_modeling_cmds::{self as kcmc};
use tokio::sync::RwLock;
use uuid::Uuid;
use super::{EngineStats, ExecutionKind};
use super::EngineStats;
use crate::{
errors::KclError,
exec::DefaultPlanes,
@ -29,7 +29,6 @@ pub struct EngineConnection {
batch: Arc<RwLock<Vec<(WebSocketRequest, SourceRange)>>>,
batch_end: Arc<RwLock<IndexMap<uuid::Uuid, (WebSocketRequest, SourceRange)>>>,
artifact_commands: Arc<RwLock<Vec<ArtifactCommand>>>,
execution_kind: Arc<RwLock<ExecutionKind>>,
/// The default planes for the scene.
default_planes: Arc<RwLock<Option<DefaultPlanes>>>,
stats: EngineStats,
@ -41,7 +40,6 @@ impl EngineConnection {
batch: Arc::new(RwLock::new(Vec::new())),
batch_end: Arc::new(RwLock::new(IndexMap::new())),
artifact_commands: Arc::new(RwLock::new(Vec::new())),
execution_kind: Default::default(),
default_planes: Default::default(),
stats: Default::default(),
})
@ -70,18 +68,6 @@ impl crate::engine::EngineManager for EngineConnection {
self.artifact_commands.clone()
}
async fn execution_kind(&self) -> ExecutionKind {
let guard = self.execution_kind.read().await;
*guard
}
async fn replace_execution_kind(&self, execution_kind: ExecutionKind) -> ExecutionKind {
let mut guard = self.execution_kind.write().await;
let original = *guard;
*guard = execution_kind;
original
}
fn get_default_planes(&self) -> Arc<RwLock<Option<DefaultPlanes>>> {
self.default_planes.clone()
}

View File

@ -11,7 +11,7 @@ use uuid::Uuid;
use wasm_bindgen::prelude::*;
use crate::{
engine::{EngineStats, ExecutionKind},
engine::EngineStats,
errors::{KclError, KclErrorDetails},
execution::{ArtifactCommand, DefaultPlanes, IdGenerator},
SourceRange,
@ -42,7 +42,6 @@ pub struct EngineConnection {
batch_end: Arc<RwLock<IndexMap<uuid::Uuid, (WebSocketRequest, SourceRange)>>>,
responses: Arc<RwLock<IndexMap<Uuid, WebSocketResponse>>>,
artifact_commands: Arc<RwLock<Vec<ArtifactCommand>>>,
execution_kind: Arc<RwLock<ExecutionKind>>,
/// The default planes for the scene.
default_planes: Arc<RwLock<Option<DefaultPlanes>>>,
stats: EngineStats,
@ -61,7 +60,6 @@ impl EngineConnection {
batch_end: Arc::new(RwLock::new(IndexMap::new())),
responses: Arc::new(RwLock::new(IndexMap::new())),
artifact_commands: Arc::new(RwLock::new(Vec::new())),
execution_kind: Default::default(),
default_planes: Default::default(),
stats: Default::default(),
})
@ -164,18 +162,6 @@ impl crate::engine::EngineManager for EngineConnection {
self.artifact_commands.clone()
}
async fn execution_kind(&self) -> ExecutionKind {
let guard = self.execution_kind.read().await;
*guard
}
async fn replace_execution_kind(&self, execution_kind: ExecutionKind) -> ExecutionKind {
let mut guard = self.execution_kind.write().await;
let original = *guard;
*guard = execution_kind;
original
}
fn get_default_planes(&self) -> Arc<RwLock<Option<DefaultPlanes>>> {
self.default_planes.clone()
}
@ -218,11 +204,6 @@ impl crate::engine::EngineManager for EngineConnection {
.do_send_modeling_cmd(id, source_range, cmd, id_to_source_range)
.await?;
// In isolated mode, we don't save the response.
if self.execution_kind().await.is_isolated() {
return Ok(ws_result);
}
let mut responses = self.responses.write().await;
responses.insert(id, ws_result.clone());
drop(responses);

View File

@ -47,23 +47,6 @@ lazy_static::lazy_static! {
pub static ref GRID_SCALE_TEXT_OBJECT_ID: uuid::Uuid = uuid::Uuid::parse_str("10782f33-f588-4668-8bcd-040502d26590").unwrap();
}
/// The mode of execution. When isolated, like during an import, attempting to
/// send a command results in an error.
#[derive(Debug, Default, Clone, Copy, Deserialize, Serialize, PartialEq, Eq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
pub enum ExecutionKind {
#[default]
Normal,
Isolated,
}
impl ExecutionKind {
pub fn is_isolated(&self) -> bool {
matches!(self, ExecutionKind::Isolated)
}
}
#[derive(Default, Debug)]
pub struct EngineStats {
pub commands_batched: AtomicUsize,
@ -108,13 +91,6 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
std::mem::take(&mut *self.responses().write().await)
}
/// Get the current execution kind.
async fn execution_kind(&self) -> ExecutionKind;
/// Replace the current execution kind with a new value and return the
/// existing value.
async fn replace_execution_kind(&self, execution_kind: ExecutionKind) -> ExecutionKind;
/// Get the default planes.
fn get_default_planes(&self) -> Arc<RwLock<Option<DefaultPlanes>>>;
@ -279,11 +255,6 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
source_range: SourceRange,
cmd: &ModelingCmd,
) -> Result<(), crate::errors::KclError> {
// In isolated mode, we don't send the command to the engine.
if self.execution_kind().await.is_isolated() {
return Ok(());
}
let req = WebSocketRequest::ModelingCmdReq(ModelingCmdReq {
cmd: cmd.clone(),
cmd_id: id.into(),
@ -305,11 +276,6 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
source_range: SourceRange,
cmds: &[ModelingCmdReq],
) -> Result<(), crate::errors::KclError> {
// In isolated mode, we don't send the command to the engine.
if self.execution_kind().await.is_isolated() {
return Ok(());
}
// Add cmds to the batch.
let mut extended_cmds = Vec::with_capacity(cmds.len());
for cmd in cmds {
@ -332,11 +298,6 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
source_range: SourceRange,
cmd: &ModelingCmd,
) -> Result<(), crate::errors::KclError> {
// In isolated mode, we don't send the command to the engine.
if self.execution_kind().await.is_isolated() {
return Ok(());
}
let req = WebSocketRequest::ModelingCmdReq(ModelingCmdReq {
cmd: cmd.clone(),
cmd_id: id.into(),

View File

@ -5,7 +5,6 @@ use indexmap::IndexMap;
use super::{cad_op::Group, kcl_value::TypeDef, types::PrimitiveType};
use crate::{
engine::ExecutionKind,
errors::{KclError, KclErrorDetails},
execution::{
annotations,
@ -62,15 +61,13 @@ impl ExecutorContext {
exec_state.mod_local.explicit_length_units = true;
}
let new_units = exec_state.length_unit();
if !self.engine.execution_kind().await.is_isolated() {
self.engine
.set_units(
new_units.into(),
annotation.as_source_range(),
exec_state.id_generator(),
)
.await?;
}
self.engine
.set_units(
new_units.into(),
annotation.as_source_range(),
exec_state.id_generator(),
)
.await?;
} else {
exec_state.err(CompilationError::err(
annotation.as_source_range(),
@ -100,15 +97,13 @@ impl ExecutorContext {
&self,
program: &Node<Program>,
exec_state: &mut ExecState,
exec_kind: ExecutionKind,
preserve_mem: bool,
module_id: ModuleId,
path: &ModulePath,
) -> Result<(Option<KclValue>, EnvironmentRef, Vec<String>), KclError> {
crate::log::log(format!("enter module {path} {} {exec_kind:?}", exec_state.stack()));
crate::log::log(format!("enter module {path} {}", exec_state.stack()));
let old_units = exec_state.length_unit();
let original_execution = self.engine.replace_execution_kind(exec_kind).await;
let mut local_state = ModuleState::new(path.std_path(), exec_state.stack().memory.clone(), Some(module_id));
if !preserve_mem {
@ -141,23 +136,71 @@ impl ExecutorContext {
// If we reset at the end of the main path, then we just add on an extra
// command and we'd need to flush the batch again.
// This avoids that.
if !exec_kind.is_isolated() && new_units != old_units && *path != ModulePath::Main {
if new_units != old_units && *path != ModulePath::Main {
self.engine
.set_units(old_units.into(), Default::default(), exec_state.id_generator())
.await?;
}
self.engine.replace_execution_kind(original_execution).await;
crate::log::log(format!("leave {path}"));
result.map(|result| (result, env_ref, local_state.module_exports))
}
/// Execute an AST's program.
#[async_recursion]
pub(super) async fn preload_all_modules<'a>(
&'a self,
modules: &mut HashMap<String, Program>,
program: NodeRef<'a, Program>,
exec_state: &mut ExecState,
) -> Result<(), KclError> {
for statement in &program.body {
if let BodyItem::ImportStatement(import_stmt) = statement {
let path_str = import_stmt.path.to_string();
if modules.contains_key(&path_str) {
// don't waste our time if we've already loaded the
// module.
continue;
}
let source_range = SourceRange::from(import_stmt);
let attrs = &import_stmt.outer_attrs;
let module_id = self
.open_module(&import_stmt.path, attrs, exec_state, source_range)
.await?;
let Some(module) = exec_state.get_module(module_id) else {
crate::log::log("we got back a module id that doesn't exist");
unreachable!();
};
let progn = {
// this dance is to avoid taking out a mut borrow
// below on exec_state after borrowing here. As a
// result, we need to clone (ugh) the program for
// now.
let ModuleRepr::Kcl(ref progn, _) = module.repr else {
// not a kcl file, we can skip this
continue;
};
progn.clone()
};
modules.insert(path_str, progn.clone().inner);
self.preload_all_modules(modules, &progn, exec_state).await?;
};
}
Ok(())
}
/// Execute an AST's program.
#[async_recursion]
pub(super) async fn exec_block<'a>(
&'a self,
program: NodeRef<'a, crate::parsing::ast::types::Program>,
program: NodeRef<'a, Program>,
exec_state: &mut ExecState,
body_type: BodyType,
) -> Result<Option<KclValue>, KclError> {
@ -181,9 +224,9 @@ impl ExecutorContext {
match &import_stmt.selector {
ImportSelector::List { items } => {
let (env_ref, module_exports) = self
.exec_module_for_items(module_id, exec_state, ExecutionKind::Isolated, source_range)
.await?;
println!("Importing items from module {}", import_stmt.path,);
let (env_ref, module_exports) =
self.exec_module_for_items(module_id, exec_state, source_range).await?;
for import_item in items {
// Extract the item from the module.
let item = exec_state
@ -224,9 +267,9 @@ impl ExecutorContext {
}
}
ImportSelector::Glob(_) => {
let (env_ref, module_exports) = self
.exec_module_for_items(module_id, exec_state, ExecutionKind::Isolated, source_range)
.await?;
println!("Importing all items from module {}", import_stmt.path);
let (env_ref, module_exports) =
self.exec_module_for_items(module_id, exec_state, source_range).await?;
for name in module_exports.iter() {
let item = exec_state
.stack()
@ -417,7 +460,7 @@ impl ExecutorContext {
Ok(last_expr)
}
pub(super) async fn open_module(
pub async fn open_module(
&self,
path: &ImportPath,
attrs: &[Node<Annotation>],
@ -425,6 +468,7 @@ impl ExecutorContext {
source_range: SourceRange,
) -> Result<ModuleId, KclError> {
let resolved_path = ModulePath::from_import_path(path, &self.settings.project_directory);
match path {
ImportPath::Kcl { .. } => {
exec_state.global.mod_loader.cycle_check(&resolved_path, source_range)?;
@ -481,7 +525,6 @@ impl ExecutorContext {
&self,
module_id: ModuleId,
exec_state: &mut ExecState,
exec_kind: ExecutionKind,
source_range: SourceRange,
) -> Result<(EnvironmentRef, Vec<String>), KclError> {
let path = exec_state.global.module_infos[&module_id].path.clone();
@ -492,7 +535,7 @@ impl ExecutorContext {
ModuleRepr::Root => Err(exec_state.circular_import_error(&path, source_range)),
ModuleRepr::Kcl(_, Some((env_ref, items))) => Ok((*env_ref, items.clone())),
ModuleRepr::Kcl(program, cache) => self
.exec_module_from_ast(program, module_id, &path, exec_state, exec_kind, source_range)
.exec_module_from_ast(program, module_id, &path, exec_state, source_range)
.await
.map(|(_, er, items)| {
*cache = Some((er, items.clone()));
@ -514,7 +557,6 @@ impl ExecutorContext {
module_id: ModuleId,
module_name: &BoxNode<Name>,
exec_state: &mut ExecState,
exec_kind: ExecutionKind,
source_range: SourceRange,
) -> Result<Option<KclValue>, KclError> {
exec_state.global.operations.push(Operation::GroupBegin {
@ -533,7 +575,7 @@ impl ExecutorContext {
ModuleRepr::Root => Err(exec_state.circular_import_error(&path, source_range)),
ModuleRepr::Kcl(program, cached_items) => {
let result = self
.exec_module_from_ast(program, module_id, &path, exec_state, exec_kind, source_range)
.exec_module_from_ast(program, module_id, &path, exec_state, source_range)
.await;
match result {
Ok((val, env, items)) => {
@ -556,19 +598,17 @@ impl ExecutorContext {
result
}
async fn exec_module_from_ast(
pub async fn exec_module_from_ast(
&self,
program: &Node<Program>,
module_id: ModuleId,
path: &ModulePath,
exec_state: &mut ExecState,
exec_kind: ExecutionKind,
source_range: SourceRange,
) -> Result<(Option<KclValue>, EnvironmentRef, Vec<String>), KclError> {
println!("exec_module_from_ast {path}");
exec_state.global.mod_loader.enter_module(path);
let result = self
.exec_module_body(program, exec_state, exec_kind, false, module_id, path)
.await;
let result = self.exec_module_body(program, exec_state, false, module_id, path).await;
exec_state.global.mod_loader.leave_module(path);
result.map_err(|err| {
@ -604,7 +644,7 @@ impl ExecutorContext {
Expr::Name(name) => {
let value = name.get_result(exec_state, self).await?.clone();
if let KclValue::Module { value: module_id, meta } = value {
self.exec_module_for_result(module_id, name, exec_state, ExecutionKind::Normal, metadata.source_range)
self.exec_module_for_result(module_id, name, exec_state, metadata.source_range)
.await?
.unwrap_or_else(|| {
exec_state.warn(CompilationError::err(
@ -792,7 +832,7 @@ impl Node<Name> {
};
mem_spec = Some(
ctx.exec_module_for_items(*module_id, exec_state, ExecutionKind::Normal, p.as_source_range())
ctx.exec_module_for_items(*module_id, exec_state, p.as_source_range())
.await?,
);
}
@ -1273,7 +1313,7 @@ impl Node<CallExpressionKw> {
));
}
let op = if func.feature_tree_operation() && !ctx.is_isolated_execution().await {
let op = if func.feature_tree_operation() {
let op_labeled_args = args
.kw_args
.labeled
@ -1359,7 +1399,7 @@ impl Node<CallExpressionKw> {
e.add_source_ranges(vec![callsite])
})?;
if matches!(fn_src, FunctionSource::User { .. }) && !ctx.is_isolated_execution().await {
if matches!(fn_src, FunctionSource::User { .. }) {
// Track return operation.
exec_state.global.operations.push(Operation::GroupEnd);
}
@ -1411,7 +1451,7 @@ impl Node<CallExpression> {
));
}
let op = if func.feature_tree_operation() && !ctx.is_isolated_execution().await {
let op = if func.feature_tree_operation() {
let op_labeled_args = func
.args(false)
.iter()
@ -1469,19 +1509,17 @@ impl Node<CallExpression> {
// exec_state.
let func = fn_name.get_result(exec_state, ctx).await?.clone();
if !ctx.is_isolated_execution().await {
// Track call operation.
exec_state.global.operations.push(Operation::GroupBegin {
group: Group::FunctionCall {
name: Some(fn_name.to_string()),
function_source_range: func.function_def_source_range().unwrap_or_default(),
unlabeled_arg: None,
// TODO: Add the arguments for legacy positional parameters.
labeled_args: Default::default(),
},
source_range: callsite,
});
}
// Track call operation.
exec_state.global.operations.push(Operation::GroupBegin {
group: Group::FunctionCall {
name: Some(fn_name.to_string()),
function_source_range: func.function_def_source_range().unwrap_or_default(),
unlabeled_arg: None,
// TODO: Add the arguments for legacy positional parameters.
labeled_args: Default::default(),
},
source_range: callsite,
});
let Some(fn_src) = func.as_fn() else {
return Err(KclError::Semantic(KclErrorDetails {
@ -1510,10 +1548,8 @@ impl Node<CallExpression> {
})
})?;
if !ctx.is_isolated_execution().await {
// Track return operation.
exec_state.global.operations.push(Operation::GroupEnd);
}
// Track return operation.
exec_state.global.operations.push(Operation::GroupEnd);
Ok(result)
}
@ -2241,7 +2277,7 @@ impl FunctionSource {
}
}
let op = if props.include_in_feature_tree && !ctx.is_isolated_execution().await {
let op = if props.include_in_feature_tree {
let op_labeled_args = args
.kw_args
.labeled
@ -2285,28 +2321,26 @@ impl FunctionSource {
Ok(Some(result))
}
FunctionSource::User { ast, memory, .. } => {
if !ctx.is_isolated_execution().await {
// Track call operation.
let op_labeled_args = args
.kw_args
.labeled
.iter()
.map(|(k, arg)| (k.clone(), OpArg::new(OpKclValue::from(&arg.value), arg.source_range)))
.collect();
exec_state.global.operations.push(Operation::GroupBegin {
group: Group::FunctionCall {
name: fn_name,
function_source_range: ast.as_source_range(),
unlabeled_arg: args
.kw_args
.unlabeled
.as_ref()
.map(|arg| OpArg::new(OpKclValue::from(&arg.value), arg.source_range)),
labeled_args: op_labeled_args,
},
source_range: callsite,
});
}
// Track call operation.
let op_labeled_args = args
.kw_args
.labeled
.iter()
.map(|(k, arg)| (k.clone(), OpArg::new(OpKclValue::from(&arg.value), arg.source_range)))
.collect();
exec_state.global.operations.push(Operation::GroupBegin {
group: Group::FunctionCall {
name: fn_name,
function_source_range: ast.as_source_range(),
unlabeled_arg: args
.kw_args
.unlabeled
.as_ref()
.map(|arg| OpArg::new(OpKclValue::from(&arg.value), arg.source_range)),
labeled_args: op_labeled_args,
},
source_range: callsite,
});
call_user_defined_function_kw(args.kw_args, *memory, ast, exec_state, ctx).await
}
@ -2317,13 +2351,14 @@ impl FunctionSource {
#[cfg(test)]
mod test {
use std::sync::Arc;
use super::*;
use crate::{
execution::{memory::Stack, parse_execute, ContextType},
parsing::ast::types::{DefaultParamVal, Identifier, Parameter},
ExecutorSettings,
};
use std::sync::Arc;
use tokio::io::AsyncWriteExt;
#[tokio::test(flavor = "multi_thread")]
async fn test_assign_args_to_params() {
@ -2432,7 +2467,7 @@ mod test {
// Run each test.
let func_expr = &Node::no_src(FunctionExpression {
params,
body: crate::parsing::ast::types::Program::empty(),
body: Program::empty(),
return_type: None,
digest: None,
});
@ -2534,4 +2569,100 @@ a = foo()
let result = parse_execute(program).await;
assert!(result.unwrap_err().to_string().contains("return"));
}
#[tokio::test(flavor = "multi_thread")]
async fn load_all_modules() {
// program a.kcl
let programa_kcl = r#"
export a = 1
"#;
// program b.kcl
let programb_kcl = r#"
import a from 'a.kcl'
export b = a + 1
"#;
// program c.kcl
let programc_kcl = r#"
import a from 'a.kcl'
export c = a + 2
"#;
// program main.kcl
let main_kcl = r#"
import b from 'b.kcl'
import c from 'c.kcl'
d = b + c
"#;
let main = crate::parsing::parse_str(main_kcl, ModuleId::default())
.parse_errs_as_err()
.unwrap();
let tmpdir = tempdir::TempDir::new("zma_kcl_load_all_modules").unwrap();
tokio::fs::File::create(tmpdir.path().join("main.kcl"))
.await
.unwrap()
.write_all(main_kcl.as_bytes())
.await
.unwrap();
tokio::fs::File::create(tmpdir.path().join("a.kcl"))
.await
.unwrap()
.write_all(programa_kcl.as_bytes())
.await
.unwrap();
tokio::fs::File::create(tmpdir.path().join("b.kcl"))
.await
.unwrap()
.write_all(programb_kcl.as_bytes())
.await
.unwrap();
tokio::fs::File::create(tmpdir.path().join("c.kcl"))
.await
.unwrap()
.write_all(programc_kcl.as_bytes())
.await
.unwrap();
let exec_ctxt = ExecutorContext {
engine: Arc::new(Box::new(
crate::engine::conn_mock::EngineConnection::new()
.await
.map_err(|err| {
KclError::Internal(crate::errors::KclErrorDetails {
message: format!("Failed to create mock engine connection: {}", err),
source_ranges: vec![SourceRange::default()],
})
})
.unwrap(),
)),
fs: Arc::new(crate::fs::FileManager::new()),
settings: ExecutorSettings {
project_directory: Some(tmpdir.path().into()),
..Default::default()
},
stdlib: Arc::new(crate::std::StdLib::new()),
context_type: ContextType::Mock,
};
let mut exec_state = ExecState::new(&exec_ctxt);
exec_ctxt
.run_concurrent(
&crate::Program {
ast: main.clone(),
original_file_contents: "".to_owned(),
},
&mut exec_state,
false,
)
.await
.unwrap();
}
}

View File

@ -418,6 +418,9 @@ pub struct Sketch {
pub artifact_id: ArtifactId,
#[ts(skip)]
pub original_id: uuid::Uuid,
/// If the sketch includes a mirror.
#[serde(skip)]
pub mirror: Option<uuid::Uuid>,
pub units: UnitLen,
/// Metadata.
#[serde(skip)]

View File

@ -27,21 +27,22 @@ pub use memory::EnvironmentRef;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
pub use state::{ExecState, MetaSettings};
use tokio::task::JoinSet;
use crate::{
engine::EngineManager,
errors::KclError,
errors::{KclError, KclErrorDetails},
execution::{
artifact::build_artifact_graph,
cache::{CacheInformation, CacheResult},
types::{UnitAngle, UnitLen},
},
fs::FileManager,
modules::{ModuleId, ModulePath},
modules::{ModuleId, ModulePath, ModuleRepr},
parsing::ast::types::{Expr, ImportPath, NodeRef},
source_range::SourceRange,
std::StdLib,
CompilationError, ExecError, ExecutionKind, KclErrorWithOutputs,
CompilationError, ExecError, KclErrorWithOutputs,
};
pub(crate) mod annotations;
@ -497,13 +498,9 @@ impl ExecutorContext {
self.context_type == ContextType::Mock || self.context_type == ContextType::MockCustomForwarded
}
pub async fn is_isolated_execution(&self) -> bool {
self.engine.execution_kind().await.is_isolated()
}
/// Returns true if we should not send engine commands for any reason.
pub async fn no_engine_commands(&self) -> bool {
self.is_mock() || self.is_isolated_execution().await
self.is_mock()
}
pub async fn send_clear_scene(
@ -674,7 +671,7 @@ impl ExecutorContext {
(program, exec_state, false)
};
let result = self.inner_run(&program, &mut exec_state, preserve_mem).await;
let result = self.run_concurrent(&program, &mut exec_state, preserve_mem).await;
if result.is_err() {
cache::bust_cache().await;
@ -707,7 +704,124 @@ impl ExecutorContext {
program: &crate::Program,
exec_state: &mut ExecState,
) -> Result<(EnvironmentRef, Option<ModelingSessionData>), KclErrorWithOutputs> {
self.inner_run(program, exec_state, false).await
self.run_concurrent(program, exec_state, false).await
}
/// Perform the execution of a program using an (experimental!) concurrent
/// execution model. This has the same signature as [Self::run].
///
/// For now -- do not use this unless you're willing to accept some
/// breakage.
///
/// You can optionally pass in some initialization memory for partial
/// execution.
///
/// To access non-fatal errors and warnings, extract them from the `ExecState`.
pub async fn run_concurrent(
&self,
program: &crate::Program,
exec_state: &mut ExecState,
preserve_mem: bool,
) -> Result<(EnvironmentRef, Option<ModelingSessionData>), KclErrorWithOutputs> {
self.prepare_mem(exec_state).await.unwrap();
let mut universe = std::collections::HashMap::new();
let mut out_id_map = std::collections::HashMap::new();
crate::walk::import_universe(self, &program.ast, &mut universe, &mut out_id_map, exec_state)
.await
.unwrap();
for modules in crate::walk::import_graph(&universe).unwrap().into_iter() {
println!("Running module {modules:?}");
//let mut set = JoinSet::new();
println!("AFTER Running module {modules:?}");
let (results_tx, mut results_rx): (
tokio::sync::mpsc::Sender<(
String,
Result<(Option<KclValue>, EnvironmentRef, Vec<String>), KclError>,
)>,
tokio::sync::mpsc::Receiver<_>,
) = tokio::sync::mpsc::channel(1);
for module in modules {
let program = universe.get(&module).unwrap().clone();
let Some(module_id) = out_id_map.get(&module) else {
panic!("Module {module} not found in exec_state");
};
let module_id = module_id.clone();
let module_path = {
let module_info = exec_state.get_module(module_id).unwrap();
let module_path = module_info.path.clone();
module_path
};
let exec_state = exec_state.clone();
let exec_ctxt = self.clone();
let results_tx = results_tx.clone();
println!("before spawn");
#[cfg(target_arch = "wasm32")]
{
wasm_bindgen_futures::spawn_local(async move {
//set.spawn(async move {
println!("Running module {module} from run_concurrent");
let mut exec_state = exec_state;
let exec_ctxt = exec_ctxt;
let program = program;
let result = exec_ctxt
.exec_module_from_ast(
&program,
module_id,
&module_path,
&mut exec_state,
Default::default(),
)
.await;
results_tx.send((module, result)).await.unwrap();
});
}
}
drop(results_tx);
while let Some((module, result)) = results_rx.recv().await {
match result {
Ok((env_ref, session_data, variables)) => {
println!("{module} {:?}", variables);
let Some(module_id) = out_id_map.get(&module) else {
//let snapshot_png_bytes = self.prepare_snapshot().await.unwrap().contents.0;
// Save to a file.
//tokio::fs::write("snapshot.png", snapshot_png_bytes).await.unwrap();
return Err(KclErrorWithOutputs::no_outputs(KclError::Internal(KclErrorDetails {
message: format!("Module {module} not found in exec_state"),
source_ranges: Default::default(),
})));
};
let path = exec_state.global.module_infos[module_id].path.clone();
let mut repr = exec_state.global.module_infos[module_id].take_repr();
let ModuleRepr::Kcl(program, cache) = &mut repr else {
continue;
};
*cache = Some((session_data, variables.clone()));
exec_state.global.module_infos[module_id].restore_repr(repr);
}
Err(e) => {
//let snapshot_png_bytes = self.prepare_snapshot().await.unwrap().contents.0;
// Save to a file.
//tokio::fs::write("snapshot.png", snapshot_png_bytes).await.unwrap();
return Err(KclErrorWithOutputs::no_outputs(e));
}
}
}
}
self.inner_run(program, exec_state, preserve_mem).await
}
/// Perform the execution of a program. Accept all possible parameters and
@ -758,11 +872,11 @@ impl ExecutorContext {
)
})?;
if !self.is_mock() {
/* if !self.is_mock() {
let mut mem = exec_state.stack().deep_clone();
mem.restore_env(env_ref);
cache::write_old_memory((mem, exec_state.global.module_infos.clone())).await;
}
}*/
let session_data = self.engine.get_session_data().await;
Ok((env_ref, session_data))
}
@ -785,7 +899,6 @@ impl ExecutorContext {
.exec_module_body(
program,
exec_state,
ExecutionKind::Normal,
preserve_mem,
ModuleId::default(),
&ModulePath::Main,
@ -839,9 +952,7 @@ impl ExecutorContext {
source_range,
)
.await?;
let (module_memory, _) = self
.exec_module_for_items(id, exec_state, ExecutionKind::Isolated, source_range)
.await?;
let (module_memory, _) = self.exec_module_for_items(id, exec_state, source_range).await?;
exec_state.mut_stack().memory.set_std(module_memory);
}

View File

@ -228,6 +228,10 @@ impl ExecState {
self.global.module_infos.insert(id, module_info);
}
pub fn get_module(&mut self, id: ModuleId) -> Option<&ModuleInfo> {
self.global.module_infos.get(&id)
}
pub fn length_unit(&self) -> UnitLen {
self.mod_local.settings.default_length_units
}

View File

@ -76,12 +76,12 @@ pub mod std;
pub mod test_server;
mod thread;
mod unparser;
mod walk;
pub mod walk;
#[cfg(target_arch = "wasm32")]
mod wasm;
pub use coredump::CoreDump;
pub use engine::{EngineManager, EngineStats, ExecutionKind};
pub use engine::{EngineManager, EngineStats};
pub use errors::{
CompilationError, ConnectionError, ExecError, KclError, KclErrorWithOutputs, Report, ReportWithOutputs,
};

View File

@ -13,7 +13,7 @@ use kcmc::{
websocket::{ModelingCmdReq, OkWebSocketResponseData},
ModelingCmd,
};
use kittycad_modeling_cmds as kcmc;
use kittycad_modeling_cmds::{self as kcmc};
use uuid::Uuid;
use crate::{
@ -168,13 +168,18 @@ pub(crate) async fn do_post_extrude<'a>(
)
.await?;
// The "get extrusion face info" API call requires *any* edge on the sketch being extruded.
// So, let's just use the first one.
let Some(any_edge_id) = sketch.paths.first().map(|edge| edge.get_base().geo_meta.id) else {
return Err(KclError::Type(KclErrorDetails {
message: "Expected a non-empty sketch".to_string(),
source_ranges: vec![args.source_range],
}));
let any_edge_id = if let Some(edge_id) = sketch.mirror {
edge_id
} else {
// The "get extrusion face info" API call requires *any* edge on the sketch being extruded.
// So, let's just use the first one.
let Some(any_edge_id) = sketch.paths.first().map(|edge| edge.get_base().geo_meta.id) else {
return Err(KclError::Type(KclErrorDetails {
message: "Expected a non-empty sketch".to_string(),
source_ranges: vec![args.source_range],
}));
};
any_edge_id
};
let mut sketch = sketch.clone();

View File

@ -2,10 +2,13 @@
use anyhow::Result;
use kcmc::{each_cmd as mcmd, ModelingCmd};
use kittycad_modeling_cmds::{self as kcmc, length_unit::LengthUnit, shared::Point3d};
use kittycad_modeling_cmds::{
self as kcmc, length_unit::LengthUnit, ok_response::OkModelingCmdResponse, output::EntityGetAllChildUuids,
shared::Point3d, websocket::OkWebSocketResponseData,
};
use crate::{
errors::KclError,
errors::{KclError, KclErrorDetails},
execution::{
types::{PrimitiveType, RuntimeType},
ExecState, KclValue, Sketch,
@ -31,13 +34,21 @@ pub async fn mirror_2d(exec_state: &mut ExecState, args: Args) -> Result<KclValu
Ok(sketches.into())
}
/// Mirror a sketch.
///
/// Only works on unclosed sketches for now.
async fn inner_mirror_2d(
sketches: Vec<Sketch>,
axis: Axis2dOrEdgeReference,
exec_state: &mut ExecState,
args: Args,
) -> Result<Vec<Sketch>, KclError> {
let starting_sketches = sketches;
let mut starting_sketches = sketches.clone();
// Update all to have a mirror.
starting_sketches.iter_mut().for_each(|sketch| {
sketch.mirror = Some(exec_state.next_uuid());
});
if args.ctx.no_engine_commands().await {
return Ok(starting_sketches);
@ -77,5 +88,40 @@ async fn inner_mirror_2d(
}
};
// After the mirror, get the first child uuid for the path.
// The "get extrusion face info" API call requires *any* edge on the sketch being extruded.
// But if you mirror2d a sketch these IDs might change so we need to get the children versus
// using the IDs we already have.
// We only do this with mirrors because otherwise it is a waste of a websocket call.
for sketch in &mut starting_sketches {
let response = args
.send_modeling_cmd(
exec_state.next_uuid(),
ModelingCmd::from(mcmd::EntityGetAllChildUuids { entity_id: sketch.id }),
)
.await?;
let OkWebSocketResponseData::Modeling {
modeling_response:
OkModelingCmdResponse::EntityGetAllChildUuids(EntityGetAllChildUuids { entity_ids: child_ids }),
} = response
else {
return Err(KclError::Internal(KclErrorDetails {
message: "Expected a successful response from EntityGetAllChildUuids".to_string(),
source_ranges: vec![args.source_range],
}));
};
if child_ids.len() >= 2 {
// The first child is the original sketch, the second is the mirrored sketch.
let child_id = child_ids[1];
sketch.mirror = Some(child_id);
} else {
return Err(KclError::Type(KclErrorDetails {
message: "Expected child uuids to be >= 2".to_string(),
source_ranges: vec![args.source_range],
}));
}
}
Ok(starting_sketches)
}

View File

@ -1343,6 +1343,7 @@ pub(crate) async fn inner_start_profile_at(
on: sketch_surface.clone(),
paths: vec![],
units: sketch_surface.units(),
mirror: Default::default(),
meta: vec![args.source_range.into()],
tags: if let Some(tag) = &tag {
let mut tag_identifier: TagIdentifier = tag.into();

View File

@ -6,8 +6,10 @@ use std::{
use anyhow::Result;
use crate::{
parsing::ast::types::{ImportPath, NodeRef, Program},
modules::ModuleRepr,
parsing::ast::types::{ImportPath, Node as AstNode, NodeRef, Program},
walk::{Node, Visitable},
ExecState, ExecutorContext, ModuleId,
};
/// Specific dependency between two modules. The 0th element of this tuple
@ -23,7 +25,7 @@ type Graph = Vec<Dependency>;
/// run concurrently. Each "stage" is blocking in this model, which will
/// change in the future. Don't use this function widely, yet.
#[allow(clippy::iter_over_hash_type)]
pub fn import_graph(progs: HashMap<String, NodeRef<'_, Program>>) -> Result<Vec<Vec<String>>> {
pub fn import_graph(progs: &HashMap<String, AstNode<Program>>) -> Result<Vec<Vec<String>>> {
let mut graph = Graph::new();
for (name, program) in progs.iter() {
@ -41,6 +43,9 @@ pub fn import_graph(progs: HashMap<String, NodeRef<'_, Program>>) -> Result<Vec<
#[allow(clippy::iter_over_hash_type)]
fn topsort(all_modules: &[&str], graph: Graph) -> Result<Vec<Vec<String>>> {
if all_modules.is_empty() {
return Ok(vec![]);
}
let mut dep_map = HashMap::<String, Vec<String>>::new();
for (dependent, dependency) in graph.iter() {
@ -57,6 +62,7 @@ fn topsort(all_modules: &[&str], graph: Graph) -> Result<Vec<Vec<String>>> {
let mut order = vec![];
loop {
println!("waiting_modules: {:?}", waiting_modules);
// Each pass through we need to find any modules which have nothing
// "pointing at it" -- so-called reverse dependencies. This is an entry
// that is either not in the dep_map OR an empty list.
@ -101,7 +107,7 @@ fn topsort(all_modules: &[&str], graph: Graph) -> Result<Vec<Vec<String>>> {
Ok(order)
}
pub(crate) fn import_dependencies(prog: NodeRef<'_, Program>) -> Result<Vec<String>> {
pub(crate) fn import_dependencies(prog: NodeRef<Program>) -> Result<Vec<String>> {
let ret = Arc::new(Mutex::new(vec![]));
fn walk(ret: Arc<Mutex<Vec<String>>>, node: Node<'_>) {
@ -125,6 +131,51 @@ pub(crate) fn import_dependencies(prog: NodeRef<'_, Program>) -> Result<Vec<Stri
Ok(ret)
}
pub(crate) async fn import_universe<'prog>(
ctx: &ExecutorContext,
prog: NodeRef<'prog, Program>,
out: &mut HashMap<String, AstNode<Program>>,
out_id_map: &mut HashMap<String, ModuleId>,
exec_state: &mut ExecState,
) -> Result<()> {
let modules = import_dependencies(prog)?;
for module in modules {
eprintln!("{:?}", module);
if out.contains_key(&module) {
continue;
}
let module_id = ctx
.open_module(
&ImportPath::Kcl {
filename: module.to_string(),
},
&[],
exec_state,
Default::default(),
)
.await?;
out_id_map.insert(module.clone(), module_id);
let program = {
let Some(module_info) = exec_state.get_module(module_id) else {
// We should never get here we just fucking added it.
anyhow::bail!("Module {} not found", module);
};
let ModuleRepr::Kcl(program, _) = &module_info.repr else {
anyhow::bail!("Module {} is not a KCL program", module);
};
program.clone()
};
out.insert(module.clone(), program.clone());
Box::pin(import_universe(ctx, &program, out, out_id_map, exec_state)).await?;
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
@ -140,16 +191,16 @@ mod tests {
let mut modules = HashMap::new();
let a = kcl!("");
modules.insert("a.kcl".to_owned(), &a);
modules.insert("a.kcl".to_owned(), a);
let b = kcl!(
"
import \"a.kcl\"
"
);
modules.insert("b.kcl".to_owned(), &b);
modules.insert("b.kcl".to_owned(), b);
let order = import_graph(modules).unwrap();
let order = import_graph(&modules).unwrap();
assert_eq!(vec![vec!["a.kcl".to_owned()], vec!["b.kcl".to_owned()]], order);
}
@ -162,16 +213,16 @@ import \"a.kcl\"
y = 2
"
);
modules.insert("a.kcl".to_owned(), &a);
modules.insert("a.kcl".to_owned(), a);
let b = kcl!(
"
x = 1
"
);
modules.insert("b.kcl".to_owned(), &b);
modules.insert("b.kcl".to_owned(), b);
let order = import_graph(modules).unwrap();
let order = import_graph(&modules).unwrap();
assert_eq!(vec![vec!["a.kcl".to_owned(), "b.kcl".to_owned()]], order);
}
@ -180,23 +231,23 @@ x = 1
let mut modules = HashMap::new();
let a = kcl!("");
modules.insert("a.kcl".to_owned(), &a);
modules.insert("a.kcl".to_owned(), a);
let b = kcl!(
"
import \"a.kcl\"
"
);
modules.insert("b.kcl".to_owned(), &b);
modules.insert("b.kcl".to_owned(), b);
let c = kcl!(
"
import \"a.kcl\"
"
);
modules.insert("c.kcl".to_owned(), &c);
modules.insert("c.kcl".to_owned(), c);
let order = import_graph(modules).unwrap();
let order = import_graph(&modules).unwrap();
assert_eq!(
vec![vec!["a.kcl".to_owned()], vec!["b.kcl".to_owned(), "c.kcl".to_owned()]],
order
@ -212,15 +263,15 @@ import \"a.kcl\"
import \"b.kcl\"
"
);
modules.insert("a.kcl".to_owned(), &a);
modules.insert("a.kcl".to_owned(), a);
let b = kcl!(
"
import \"a.kcl\"
"
);
modules.insert("b.kcl".to_owned(), &b);
modules.insert("b.kcl".to_owned(), b);
import_graph(modules).unwrap_err();
import_graph(&modules).unwrap_err();
}
}

View File

@ -8,3 +8,5 @@ mod import_graph;
pub use ast_node::Node;
pub use ast_visitor::Visitable;
pub use ast_walk::walk;
pub use import_graph::import_graph;
pub(crate) use import_graph::import_universe;

View File

@ -96,6 +96,25 @@ export fn circle(
///
/// example = extrude(sketch001, length = 10)
/// ```
///
/// ```
/// // Sketch on the face of a mirrored sketch, that has been extruded.
/// sketch0011 = startSketchOn(XY)
/// |> startProfileAt([6.77, 0], %)
/// |> yLine(length = 1.27)
/// |> tangentialArcTo([5.96, 2.37], %)
/// |> tangentialArcTo([-6.2, 2.44], %)
/// |> tangentialArcTo([-6.6, 1.82], %)
/// |> yLine(length = -1.82)
/// |> mirror2d( axis = X )
/// |> extrude(length = 10)
///
/// sketch002 = startSketchOn(sketch0011, 'END')
/// |> circle( center = [-0.01, 1.58], radius = 1.2 )
/// |> extrude(length = 1.2)
///
/// shell([sketch002], faces = ['end'], thickness = .1 )
/// ```
@(impl = std_rust)
export fn mirror2d(
/// The sketch or sketches to be reflected.

View File

@ -1,81 +1,81 @@
```mermaid
flowchart LR
subgraph path2 [Path]
2["Path<br>[324, 421, 0]"]
3["Segment<br>[429, 534, 0]"]
4["Segment<br>[542, 651, 0]"]
5["Segment<br>[659, 691, 0]"]
6["Segment<br>[699, 808, 0]"]
7["Segment<br>[816, 863, 0]"]
8["Segment<br>[871, 919, 0]"]
9["Segment<br>[927, 976, 0]"]
10["Segment<br>[984, 1101, 0]"]
11["Segment<br>[1109, 1157, 0]"]
12["Segment<br>[1165, 1273, 0]"]
13["Segment<br>[1281, 1330, 0]"]
14["Segment<br>[1338, 1387, 0]"]
15["Segment<br>[1395, 1428, 0]"]
16["Segment<br>[1436, 1545, 0]"]
17["Segment<br>[1553, 1585, 0]"]
18["Segment<br>[1593, 1702, 0]"]
19["Segment<br>[1710, 1813, 0]"]
20["Segment<br>[1854, 1964, 0]"]
21["Segment<br>[1972, 2004, 0]"]
22["Segment<br>[2012, 2122, 0]"]
23["Segment<br>[2130, 2177, 0]"]
24["Segment<br>[2185, 2235, 0]"]
25["Segment<br>[2243, 2293, 0]"]
26["Segment<br>[2311, 2440, 0]"]
27["Segment<br>[2458, 2507, 0]"]
28["Segment<br>[2521, 2635, 0]"]
29["Segment<br>[2649, 2699, 0]"]
30["Segment<br>[2713, 2762, 0]"]
31["Segment<br>[2770, 2803, 0]"]
32["Segment<br>[2811, 2921, 0]"]
33["Segment<br>[2929, 2961, 0]"]
34["Segment<br>[2969, 3079, 0]"]
35["Segment<br>[3120, 3222, 0]"]
36["Segment<br>[3230, 3340, 0]"]
37["Segment<br>[3348, 3381, 0]"]
38["Segment<br>[3389, 3499, 0]"]
39["Segment<br>[3507, 3556, 0]"]
40["Segment<br>[3564, 3614, 0]"]
41["Segment<br>[3622, 3671, 0]"]
42["Segment<br>[3679, 3807, 0]"]
43["Segment<br>[3815, 3865, 0]"]
44["Segment<br>[3873, 3988, 0]"]
45["Segment<br>[3996, 4045, 0]"]
46["Segment<br>[4053, 4102, 0]"]
47["Segment<br>[4110, 4144, 0]"]
48["Segment<br>[4152, 4262, 0]"]
49["Segment<br>[4270, 4303, 0]"]
50["Segment<br>[4311, 4421, 0]"]
51["Segment<br>[4429, 4533, 0]"]
52["Segment<br>[4574, 4684, 0]"]
53["Segment<br>[4692, 4725, 0]"]
54["Segment<br>[4733, 4843, 0]"]
55["Segment<br>[4851, 4900, 0]"]
56["Segment<br>[4908, 4957, 0]"]
57["Segment<br>[4965, 5014, 0]"]
58["Segment<br>[5022, 5141, 0]"]
59["Segment<br>[5149, 5199, 0]"]
60["Segment<br>[5207, 5315, 0]"]
61["Segment<br>[5323, 5372, 0]"]
62["Segment<br>[5380, 5430, 0]"]
63["Segment<br>[5438, 5472, 0]"]
64["Segment<br>[5480, 5590, 0]"]
65["Segment<br>[5598, 5631, 0]"]
66["Segment<br>[5639, 5749, 0]"]
67["Segment<br>[5757, 5764, 0]"]
2["Path<br>[349, 446, 0]"]
3["Segment<br>[454, 559, 0]"]
4["Segment<br>[567, 676, 0]"]
5["Segment<br>[684, 716, 0]"]
6["Segment<br>[724, 833, 0]"]
7["Segment<br>[841, 888, 0]"]
8["Segment<br>[896, 944, 0]"]
9["Segment<br>[952, 1001, 0]"]
10["Segment<br>[1009, 1126, 0]"]
11["Segment<br>[1134, 1182, 0]"]
12["Segment<br>[1190, 1298, 0]"]
13["Segment<br>[1306, 1355, 0]"]
14["Segment<br>[1363, 1412, 0]"]
15["Segment<br>[1420, 1453, 0]"]
16["Segment<br>[1461, 1570, 0]"]
17["Segment<br>[1578, 1610, 0]"]
18["Segment<br>[1618, 1727, 0]"]
19["Segment<br>[1735, 1838, 0]"]
20["Segment<br>[1879, 1989, 0]"]
21["Segment<br>[1997, 2029, 0]"]
22["Segment<br>[2037, 2147, 0]"]
23["Segment<br>[2155, 2202, 0]"]
24["Segment<br>[2210, 2260, 0]"]
25["Segment<br>[2268, 2318, 0]"]
26["Segment<br>[2336, 2465, 0]"]
27["Segment<br>[2483, 2532, 0]"]
28["Segment<br>[2546, 2660, 0]"]
29["Segment<br>[2674, 2724, 0]"]
30["Segment<br>[2738, 2787, 0]"]
31["Segment<br>[2795, 2828, 0]"]
32["Segment<br>[2836, 2946, 0]"]
33["Segment<br>[2954, 2986, 0]"]
34["Segment<br>[2994, 3104, 0]"]
35["Segment<br>[3145, 3247, 0]"]
36["Segment<br>[3255, 3365, 0]"]
37["Segment<br>[3373, 3406, 0]"]
38["Segment<br>[3414, 3524, 0]"]
39["Segment<br>[3532, 3581, 0]"]
40["Segment<br>[3589, 3639, 0]"]
41["Segment<br>[3647, 3696, 0]"]
42["Segment<br>[3704, 3832, 0]"]
43["Segment<br>[3840, 3890, 0]"]
44["Segment<br>[3898, 4013, 0]"]
45["Segment<br>[4021, 4070, 0]"]
46["Segment<br>[4078, 4127, 0]"]
47["Segment<br>[4135, 4169, 0]"]
48["Segment<br>[4177, 4287, 0]"]
49["Segment<br>[4295, 4328, 0]"]
50["Segment<br>[4336, 4446, 0]"]
51["Segment<br>[4454, 4558, 0]"]
52["Segment<br>[4599, 4709, 0]"]
53["Segment<br>[4717, 4750, 0]"]
54["Segment<br>[4758, 4868, 0]"]
55["Segment<br>[4876, 4925, 0]"]
56["Segment<br>[4933, 4982, 0]"]
57["Segment<br>[4990, 5039, 0]"]
58["Segment<br>[5047, 5166, 0]"]
59["Segment<br>[5174, 5224, 0]"]
60["Segment<br>[5232, 5340, 0]"]
61["Segment<br>[5348, 5397, 0]"]
62["Segment<br>[5405, 5455, 0]"]
63["Segment<br>[5463, 5497, 0]"]
64["Segment<br>[5505, 5615, 0]"]
65["Segment<br>[5623, 5656, 0]"]
66["Segment<br>[5664, 5774, 0]"]
67["Segment<br>[5782, 5789, 0]"]
68[Solid2d]
end
subgraph path69 [Path]
69["Path<br>[5815, 5993, 0]"]
70["Segment<br>[5815, 5993, 0]"]
69["Path<br>[5840, 6018, 0]"]
70["Segment<br>[5840, 6018, 0]"]
71[Solid2d]
end
1["Plane<br>[298, 316, 0]"]
72["Sweep Extrusion<br>[6005, 6033, 0]"]
1["Plane<br>[323, 341, 0]"]
72["Sweep Extrusion<br>[6030, 6058, 0]"]
73[Wall]
74[Wall]
75[Wall]
@ -270,38 +270,38 @@ flowchart LR
264["SweepEdge Adjacent"]
265["SweepEdge Opposite"]
266["SweepEdge Adjacent"]
267["EdgeCut Fillet<br>[6041, 6746, 0]"]
268["EdgeCut Fillet<br>[6041, 6746, 0]"]
269["EdgeCut Fillet<br>[6041, 6746, 0]"]
270["EdgeCut Fillet<br>[6041, 6746, 0]"]
271["EdgeCut Fillet<br>[6041, 6746, 0]"]
272["EdgeCut Fillet<br>[6041, 6746, 0]"]
273["EdgeCut Fillet<br>[6041, 6746, 0]"]
274["EdgeCut Fillet<br>[6041, 6746, 0]"]
275["EdgeCut Fillet<br>[6041, 6746, 0]"]
276["EdgeCut Fillet<br>[6041, 6746, 0]"]
277["EdgeCut Fillet<br>[6041, 6746, 0]"]
278["EdgeCut Fillet<br>[6041, 6746, 0]"]
279["EdgeCut Fillet<br>[6041, 6746, 0]"]
280["EdgeCut Fillet<br>[6041, 6746, 0]"]
281["EdgeCut Fillet<br>[6041, 6746, 0]"]
282["EdgeCut Fillet<br>[6041, 6746, 0]"]
283["EdgeCut Fillet<br>[6754, 7458, 0]"]
284["EdgeCut Fillet<br>[6754, 7458, 0]"]
285["EdgeCut Fillet<br>[6754, 7458, 0]"]
286["EdgeCut Fillet<br>[6754, 7458, 0]"]
287["EdgeCut Fillet<br>[6754, 7458, 0]"]
288["EdgeCut Fillet<br>[6754, 7458, 0]"]
289["EdgeCut Fillet<br>[6754, 7458, 0]"]
290["EdgeCut Fillet<br>[6754, 7458, 0]"]
291["EdgeCut Fillet<br>[6754, 7458, 0]"]
292["EdgeCut Fillet<br>[6754, 7458, 0]"]
293["EdgeCut Fillet<br>[6754, 7458, 0]"]
294["EdgeCut Fillet<br>[6754, 7458, 0]"]
295["EdgeCut Fillet<br>[6754, 7458, 0]"]
296["EdgeCut Fillet<br>[6754, 7458, 0]"]
297["EdgeCut Fillet<br>[6754, 7458, 0]"]
298["EdgeCut Fillet<br>[6754, 7458, 0]"]
267["EdgeCut Fillet<br>[6066, 6771, 0]"]
268["EdgeCut Fillet<br>[6066, 6771, 0]"]
269["EdgeCut Fillet<br>[6066, 6771, 0]"]
270["EdgeCut Fillet<br>[6066, 6771, 0]"]
271["EdgeCut Fillet<br>[6066, 6771, 0]"]
272["EdgeCut Fillet<br>[6066, 6771, 0]"]
273["EdgeCut Fillet<br>[6066, 6771, 0]"]
274["EdgeCut Fillet<br>[6066, 6771, 0]"]
275["EdgeCut Fillet<br>[6066, 6771, 0]"]
276["EdgeCut Fillet<br>[6066, 6771, 0]"]
277["EdgeCut Fillet<br>[6066, 6771, 0]"]
278["EdgeCut Fillet<br>[6066, 6771, 0]"]
279["EdgeCut Fillet<br>[6066, 6771, 0]"]
280["EdgeCut Fillet<br>[6066, 6771, 0]"]
281["EdgeCut Fillet<br>[6066, 6771, 0]"]
282["EdgeCut Fillet<br>[6066, 6771, 0]"]
283["EdgeCut Fillet<br>[6779, 7483, 0]"]
284["EdgeCut Fillet<br>[6779, 7483, 0]"]
285["EdgeCut Fillet<br>[6779, 7483, 0]"]
286["EdgeCut Fillet<br>[6779, 7483, 0]"]
287["EdgeCut Fillet<br>[6779, 7483, 0]"]
288["EdgeCut Fillet<br>[6779, 7483, 0]"]
289["EdgeCut Fillet<br>[6779, 7483, 0]"]
290["EdgeCut Fillet<br>[6779, 7483, 0]"]
291["EdgeCut Fillet<br>[6779, 7483, 0]"]
292["EdgeCut Fillet<br>[6779, 7483, 0]"]
293["EdgeCut Fillet<br>[6779, 7483, 0]"]
294["EdgeCut Fillet<br>[6779, 7483, 0]"]
295["EdgeCut Fillet<br>[6779, 7483, 0]"]
296["EdgeCut Fillet<br>[6779, 7483, 0]"]
297["EdgeCut Fillet<br>[6779, 7483, 0]"]
298["EdgeCut Fillet<br>[6779, 7483, 0]"]
1 --- 2
1 --- 69
2 --- 3

File diff suppressed because it is too large Load Diff

View File

@ -9,8 +9,8 @@ description: Operations executed 80-20-rail.kcl
"type": "FunctionCall",
"name": "rail8020",
"functionSourceRange": [
214,
7479,
239,
7504,
0
],
"unlabeledArg": null,

View File

@ -1,58 +1,58 @@
```mermaid
flowchart LR
subgraph path2 [Path]
2["Path<br>[731, 793, 0]"]
3["Segment<br>[731, 793, 0]"]
2["Path<br>[664, 726, 0]"]
3["Segment<br>[664, 726, 0]"]
4[Solid2d]
end
subgraph path5 [Path]
5["Path<br>[804, 850, 0]"]
6["Segment<br>[804, 850, 0]"]
5["Path<br>[737, 783, 0]"]
6["Segment<br>[737, 783, 0]"]
7[Solid2d]
end
subgraph path15 [Path]
15["Path<br>[1037, 1093, 0]"]
16["Segment<br>[1099, 1191, 0]"]
17["Segment<br>[1197, 1204, 0]"]
15["Path<br>[970, 1026, 0]"]
16["Segment<br>[1032, 1124, 0]"]
17["Segment<br>[1130, 1137, 0]"]
18[Solid2d]
end
subgraph path24 [Path]
24["Path<br>[1574, 1707, 0]"]
25["Segment<br>[1713, 1806, 0]"]
26["Segment<br>[1812, 1843, 0]"]
27["Segment<br>[1849, 1877, 0]"]
28["Segment<br>[1883, 1890, 0]"]
24["Path<br>[1507, 1640, 0]"]
25["Segment<br>[1646, 1739, 0]"]
26["Segment<br>[1745, 1776, 0]"]
27["Segment<br>[1782, 1810, 0]"]
28["Segment<br>[1816, 1823, 0]"]
29[Solid2d]
end
subgraph path40 [Path]
40["Path<br>[2224, 2366, 0]"]
41["Segment<br>[2224, 2366, 0]"]
40["Path<br>[2157, 2299, 0]"]
41["Segment<br>[2157, 2299, 0]"]
42[Solid2d]
end
subgraph path50 [Path]
50["Path<br>[2760, 2813, 0]"]
51["Segment<br>[2760, 2813, 0]"]
50["Path<br>[2693, 2746, 0]"]
51["Segment<br>[2693, 2746, 0]"]
52[Solid2d]
end
subgraph path53 [Path]
53["Path<br>[2824, 2898, 0]"]
54["Segment<br>[2824, 2898, 0]"]
53["Path<br>[2757, 2831, 0]"]
54["Segment<br>[2757, 2831, 0]"]
55[Solid2d]
end
1["Plane<br>[677, 724, 0]"]
8["Sweep Extrusion<br>[905, 957, 0]"]
1["Plane<br>[610, 657, 0]"]
8["Sweep Extrusion<br>[838, 890, 0]"]
9[Wall]
10["Cap Start"]
11["Cap End"]
12["SweepEdge Opposite"]
13["SweepEdge Adjacent"]
14["Plane<br>[1014, 1031, 0]"]
19["Sweep Revolve<br>[1286, 1316, 0]"]
14["Plane<br>[947, 964, 0]"]
19["Sweep Revolve<br>[1219, 1249, 0]"]
20[Wall]
21[Wall]
22["SweepEdge Adjacent"]
23["Plane<br>[1551, 1568, 0]"]
30["Sweep Revolve<br>[1932, 1962, 0]"]
23["Plane<br>[1484, 1501, 0]"]
30["Sweep Revolve<br>[1865, 1895, 0]"]
31[Wall]
32[Wall]
33[Wall]
@ -61,22 +61,22 @@ flowchart LR
36["SweepEdge Adjacent"]
37["SweepEdge Adjacent"]
38["SweepEdge Adjacent"]
39["Plane<br>[2201, 2218, 0]"]
43["Sweep Revolve<br>[2409, 2460, 0]"]
39["Plane<br>[2134, 2151, 0]"]
43["Sweep Revolve<br>[2342, 2393, 0]"]
44[Wall]
45["Cap Start"]
46["Cap End"]
47["SweepEdge Opposite"]
48["SweepEdge Adjacent"]
49["Plane<br>[2706, 2753, 0]"]
56["Sweep Extrusion<br>[2918, 2971, 0]"]
49["Plane<br>[2639, 2686, 0]"]
56["Sweep Extrusion<br>[2851, 2904, 0]"]
57[Wall]
58["Cap Start"]
59["Cap End"]
60["SweepEdge Opposite"]
61["SweepEdge Adjacent"]
62["StartSketchOnPlane<br>[663, 725, 0]"]
63["StartSketchOnPlane<br>[2692, 2754, 0]"]
62["StartSketchOnPlane<br>[596, 658, 0]"]
63["StartSketchOnPlane<br>[2625, 2687, 0]"]
1 --- 2
1 --- 5
2 --- 3

File diff suppressed because it is too large Load Diff

View File

@ -1,264 +1,264 @@
```mermaid
flowchart LR
subgraph path2 [Path]
2["Path<br>[567, 618, 6]"]
3["Segment<br>[567, 618, 6]"]
2["Path<br>[571, 622, 6]"]
3["Segment<br>[571, 622, 6]"]
4[Solid2d]
end
subgraph path11 [Path]
11["Path<br>[803, 859, 6]"]
12["Segment<br>[803, 859, 6]"]
11["Path<br>[807, 863, 6]"]
12["Segment<br>[807, 863, 6]"]
13[Solid2d]
end
subgraph path19 [Path]
19["Path<br>[984, 1037, 6]"]
20["Segment<br>[984, 1037, 6]"]
19["Path<br>[988, 1041, 6]"]
20["Segment<br>[988, 1041, 6]"]
21[Solid2d]
end
subgraph path30 [Path]
30["Path<br>[1420, 1460, 6]"]
31["Segment<br>[1420, 1460, 6]"]
30["Path<br>[1424, 1464, 6]"]
31["Segment<br>[1424, 1464, 6]"]
32[Solid2d]
end
subgraph path38 [Path]
38["Path<br>[1564, 1615, 6]"]
39["Segment<br>[1564, 1615, 6]"]
38["Path<br>[1568, 1619, 6]"]
39["Segment<br>[1568, 1619, 6]"]
40[Solid2d]
end
subgraph path47 [Path]
47["Path<br>[1748, 1801, 6]"]
48["Segment<br>[1748, 1801, 6]"]
47["Path<br>[1752, 1805, 6]"]
48["Segment<br>[1752, 1805, 6]"]
49[Solid2d]
end
subgraph path58 [Path]
58["Path<br>[2044, 2116, 6]"]
59["Segment<br>[2044, 2116, 6]"]
58["Path<br>[2048, 2120, 6]"]
59["Segment<br>[2048, 2120, 6]"]
60[Solid2d]
end
subgraph path81 [Path]
81["Path<br>[2373, 2404, 6]"]
82["Segment<br>[2410, 2430, 6]"]
83["Segment<br>[2436, 2456, 6]"]
84["Segment<br>[2462, 2483, 6]"]
85["Segment<br>[2489, 2545, 6]"]
86["Segment<br>[2551, 2558, 6]"]
81["Path<br>[2377, 2408, 6]"]
82["Segment<br>[2414, 2434, 6]"]
83["Segment<br>[2440, 2460, 6]"]
84["Segment<br>[2466, 2487, 6]"]
85["Segment<br>[2493, 2549, 6]"]
86["Segment<br>[2555, 2562, 6]"]
87[Solid2d]
end
subgraph path106 [Path]
106["Path<br>[2860, 2892, 6]"]
107["Segment<br>[2898, 2919, 6]"]
108["Segment<br>[2925, 2945, 6]"]
109["Segment<br>[2951, 2971, 6]"]
110["Segment<br>[2977, 3033, 6]"]
111["Segment<br>[3039, 3046, 6]"]
106["Path<br>[2864, 2896, 6]"]
107["Segment<br>[2902, 2923, 6]"]
108["Segment<br>[2929, 2949, 6]"]
109["Segment<br>[2955, 2975, 6]"]
110["Segment<br>[2981, 3037, 6]"]
111["Segment<br>[3043, 3050, 6]"]
112[Solid2d]
end
subgraph path132 [Path]
132["Path<br>[350, 406, 5]"]
133["Segment<br>[350, 406, 5]"]
132["Path<br>[354, 410, 5]"]
133["Segment<br>[354, 410, 5]"]
134[Solid2d]
end
subgraph path135 [Path]
135["Path<br>[417, 473, 5]"]
136["Segment<br>[417, 473, 5]"]
135["Path<br>[421, 477, 5]"]
136["Segment<br>[421, 477, 5]"]
137[Solid2d]
end
subgraph path144 [Path]
144["Path<br>[638, 694, 5]"]
145["Segment<br>[638, 694, 5]"]
144["Path<br>[642, 698, 5]"]
145["Segment<br>[642, 698, 5]"]
146[Solid2d]
end
subgraph path147 [Path]
147["Path<br>[705, 761, 5]"]
148["Segment<br>[705, 761, 5]"]
147["Path<br>[709, 765, 5]"]
148["Segment<br>[709, 765, 5]"]
149[Solid2d]
end
subgraph path156 [Path]
156["Path<br>[905, 959, 5]"]
157["Segment<br>[905, 959, 5]"]
156["Path<br>[909, 963, 5]"]
157["Segment<br>[909, 963, 5]"]
158[Solid2d]
end
subgraph path167 [Path]
167["Path<br>[1237, 1297, 5]"]
168["Segment<br>[1237, 1297, 5]"]
167["Path<br>[1241, 1301, 5]"]
168["Segment<br>[1241, 1301, 5]"]
169[Solid2d]
end
subgraph path179 [Path]
179["Path<br>[1655, 1701, 5]"]
180["Segment<br>[1707, 1759, 5]"]
181["Segment<br>[1765, 1870, 5]"]
182["Segment<br>[1876, 1898, 5]"]
183["Segment<br>[1904, 1960, 5]"]
184["Segment<br>[1966, 1973, 5]"]
179["Path<br>[1659, 1705, 5]"]
180["Segment<br>[1711, 1763, 5]"]
181["Segment<br>[1769, 1874, 5]"]
182["Segment<br>[1880, 1902, 5]"]
183["Segment<br>[1908, 1964, 5]"]
184["Segment<br>[1970, 1977, 5]"]
185[Solid2d]
end
subgraph path195 [Path]
195["Path<br>[2105, 2151, 5]"]
196["Segment<br>[2157, 2209, 5]"]
197["Segment<br>[2215, 2322, 5]"]
198["Segment<br>[2328, 2365, 5]"]
199["Segment<br>[2371, 2427, 5]"]
200["Segment<br>[2433, 2440, 5]"]
195["Path<br>[2109, 2155, 5]"]
196["Segment<br>[2161, 2213, 5]"]
197["Segment<br>[2219, 2326, 5]"]
198["Segment<br>[2332, 2369, 5]"]
199["Segment<br>[2375, 2431, 5]"]
200["Segment<br>[2437, 2444, 5]"]
201[Solid2d]
end
subgraph path212 [Path]
212["Path<br>[2949, 2996, 5]"]
213["Segment<br>[3004, 3344, 5]"]
214["Segment<br>[3352, 3384, 5]"]
215["Segment<br>[3392, 3736, 5]"]
216["Segment<br>[3744, 3800, 5]"]
217["Segment<br>[3808, 3815, 5]"]
212["Path<br>[2953, 3000, 5]"]
213["Segment<br>[3008, 3348, 5]"]
214["Segment<br>[3356, 3388, 5]"]
215["Segment<br>[3396, 3740, 5]"]
216["Segment<br>[3748, 3804, 5]"]
217["Segment<br>[3812, 3819, 5]"]
218[Solid2d]
end
subgraph path235 [Path]
235["Path<br>[2949, 2996, 5]"]
236["Segment<br>[3004, 3344, 5]"]
237["Segment<br>[3352, 3384, 5]"]
238["Segment<br>[3392, 3736, 5]"]
239["Segment<br>[3744, 3800, 5]"]
240["Segment<br>[3808, 3815, 5]"]
235["Path<br>[2953, 3000, 5]"]
236["Segment<br>[3008, 3348, 5]"]
237["Segment<br>[3356, 3388, 5]"]
238["Segment<br>[3396, 3740, 5]"]
239["Segment<br>[3748, 3804, 5]"]
240["Segment<br>[3812, 3819, 5]"]
241[Solid2d]
end
subgraph path258 [Path]
258["Path<br>[4343, 4438, 5]"]
259["Segment<br>[4444, 4477, 5]"]
260["Segment<br>[4483, 4534, 5]"]
261["Segment<br>[4540, 4573, 5]"]
262["Segment<br>[4579, 4629, 5]"]
263["Segment<br>[4635, 4676, 5]"]
264["Segment<br>[4682, 4731, 5]"]
265["Segment<br>[4737, 4770, 5]"]
266["Segment<br>[4776, 4810, 5]"]
267["Segment<br>[4816, 4850, 5]"]
268["Segment<br>[4856, 4908, 5]"]
269["Segment<br>[4914, 4948, 5]"]
270["Segment<br>[4954, 5030, 5]"]
271["Segment<br>[5036, 5069, 5]"]
272["Segment<br>[5075, 5151, 5]"]
273["Segment<br>[5157, 5191, 5]"]
274["Segment<br>[5197, 5271, 5]"]
275["Segment<br>[5277, 5311, 5]"]
276["Segment<br>[5317, 5368, 5]"]
277["Segment<br>[5374, 5436, 5]"]
278["Segment<br>[5442, 5493, 5]"]
279["Segment<br>[5499, 5533, 5]"]
280["Segment<br>[5539, 5572, 5]"]
281["Segment<br>[5578, 5611, 5]"]
282["Segment<br>[5617, 5624, 5]"]
258["Path<br>[4347, 4442, 5]"]
259["Segment<br>[4448, 4481, 5]"]
260["Segment<br>[4487, 4538, 5]"]
261["Segment<br>[4544, 4577, 5]"]
262["Segment<br>[4583, 4633, 5]"]
263["Segment<br>[4639, 4680, 5]"]
264["Segment<br>[4686, 4735, 5]"]
265["Segment<br>[4741, 4774, 5]"]
266["Segment<br>[4780, 4814, 5]"]
267["Segment<br>[4820, 4854, 5]"]
268["Segment<br>[4860, 4912, 5]"]
269["Segment<br>[4918, 4952, 5]"]
270["Segment<br>[4958, 5034, 5]"]
271["Segment<br>[5040, 5073, 5]"]
272["Segment<br>[5079, 5155, 5]"]
273["Segment<br>[5161, 5195, 5]"]
274["Segment<br>[5201, 5275, 5]"]
275["Segment<br>[5281, 5315, 5]"]
276["Segment<br>[5321, 5372, 5]"]
277["Segment<br>[5378, 5440, 5]"]
278["Segment<br>[5446, 5497, 5]"]
279["Segment<br>[5503, 5537, 5]"]
280["Segment<br>[5543, 5576, 5]"]
281["Segment<br>[5582, 5615, 5]"]
282["Segment<br>[5621, 5628, 5]"]
283[Solid2d]
end
subgraph path334 [Path]
334["Path<br>[740, 780, 8]"]
335["Segment<br>[788, 850, 8]"]
336["Segment<br>[858, 894, 8]"]
337["Segment<br>[902, 932, 8]"]
338["Segment<br>[940, 992, 8]"]
339["Segment<br>[1000, 1040, 8]"]
340["Segment<br>[1048, 1083, 8]"]
341["Segment<br>[1091, 1129, 8]"]
342["Segment<br>[1137, 1159, 8]"]
343["Segment<br>[1167, 1174, 8]"]
334["Path<br>[744, 784, 8]"]
335["Segment<br>[792, 854, 8]"]
336["Segment<br>[862, 898, 8]"]
337["Segment<br>[906, 936, 8]"]
338["Segment<br>[944, 996, 8]"]
339["Segment<br>[1004, 1044, 8]"]
340["Segment<br>[1052, 1087, 8]"]
341["Segment<br>[1095, 1133, 8]"]
342["Segment<br>[1141, 1163, 8]"]
343["Segment<br>[1171, 1178, 8]"]
344[Solid2d]
end
subgraph path365 [Path]
365["Path<br>[507, 588, 7]"]
366["Segment<br>[594, 695, 7]"]
367["Segment<br>[701, 786, 7]"]
368["Segment<br>[792, 876, 7]"]
369["Segment<br>[882, 968, 7]"]
370["Segment<br>[974, 1059, 7]"]
371["Segment<br>[1065, 1151, 7]"]
372["Segment<br>[1157, 1280, 7]"]
373["Segment<br>[1286, 1372, 7]"]
374["Segment<br>[1378, 1513, 7]"]
375["Segment<br>[1519, 1605, 7]"]
376["Segment<br>[1611, 1735, 7]"]
377["Segment<br>[1741, 1827, 7]"]
378["Segment<br>[1833, 1918, 7]"]
379["Segment<br>[1924, 2010, 7]"]
380["Segment<br>[2016, 2101, 7]"]
381["Segment<br>[2107, 2192, 7]"]
382["Segment<br>[2198, 2205, 7]"]
365["Path<br>[511, 592, 7]"]
366["Segment<br>[598, 699, 7]"]
367["Segment<br>[705, 790, 7]"]
368["Segment<br>[796, 880, 7]"]
369["Segment<br>[886, 972, 7]"]
370["Segment<br>[978, 1063, 7]"]
371["Segment<br>[1069, 1155, 7]"]
372["Segment<br>[1161, 1284, 7]"]
373["Segment<br>[1290, 1376, 7]"]
374["Segment<br>[1382, 1517, 7]"]
375["Segment<br>[1523, 1609, 7]"]
376["Segment<br>[1615, 1739, 7]"]
377["Segment<br>[1745, 1831, 7]"]
378["Segment<br>[1837, 1922, 7]"]
379["Segment<br>[1928, 2014, 7]"]
380["Segment<br>[2020, 2105, 7]"]
381["Segment<br>[2111, 2196, 7]"]
382["Segment<br>[2202, 2209, 7]"]
383[Solid2d]
end
subgraph path439 [Path]
439["Path<br>[483, 540, 9]"]
440["Segment<br>[546, 680, 9]"]
441["Segment<br>[686, 741, 9]"]
442["Segment<br>[747, 844, 9]"]
443["Segment<br>[850, 882, 9]"]
444["Segment<br>[888, 920, 9]"]
445["Segment<br>[926, 957, 9]"]
446["Segment<br>[963, 1078, 9]"]
447["Segment<br>[1084, 1116, 9]"]
448["Segment<br>[1122, 1154, 9]"]
449["Segment<br>[1160, 1191, 9]"]
450["Segment<br>[1197, 1290, 9]"]
451["Segment<br>[1296, 1351, 9]"]
452["Segment<br>[1357, 1430, 9]"]
453["Segment<br>[1436, 1443, 9]"]
439["Path<br>[487, 544, 9]"]
440["Segment<br>[550, 684, 9]"]
441["Segment<br>[690, 745, 9]"]
442["Segment<br>[751, 848, 9]"]
443["Segment<br>[854, 886, 9]"]
444["Segment<br>[892, 924, 9]"]
445["Segment<br>[930, 961, 9]"]
446["Segment<br>[967, 1082, 9]"]
447["Segment<br>[1088, 1120, 9]"]
448["Segment<br>[1126, 1158, 9]"]
449["Segment<br>[1164, 1195, 9]"]
450["Segment<br>[1201, 1294, 9]"]
451["Segment<br>[1300, 1355, 9]"]
452["Segment<br>[1361, 1434, 9]"]
453["Segment<br>[1440, 1447, 9]"]
454[Solid2d]
end
1["Plane<br>[544, 561, 6]"]
5["Sweep Extrusion<br>[627, 683, 6]"]
1["Plane<br>[548, 565, 6]"]
5["Sweep Extrusion<br>[631, 687, 6]"]
6[Wall]
7["Cap Start"]
8["Cap End"]
9["SweepEdge Opposite"]
10["SweepEdge Adjacent"]
14["Sweep Extrusion<br>[872, 934, 6]"]
14["Sweep Extrusion<br>[876, 938, 6]"]
15[Wall]
16["Cap End"]
17["SweepEdge Opposite"]
18["SweepEdge Adjacent"]
22["Sweep Extrusion<br>[1184, 1263, 6]"]
22["Sweep Extrusion<br>[1188, 1267, 6]"]
23[Wall]
24["SweepEdge Opposite"]
25["SweepEdge Adjacent"]
26["Sweep Extrusion<br>[1184, 1263, 6]"]
27["Sweep Extrusion<br>[1184, 1263, 6]"]
28["Sweep Extrusion<br>[1184, 1263, 6]"]
29["Sweep Extrusion<br>[1184, 1263, 6]"]
33["Sweep Extrusion<br>[1466, 1499, 6]"]
26["Sweep Extrusion<br>[1188, 1267, 6]"]
27["Sweep Extrusion<br>[1188, 1267, 6]"]
28["Sweep Extrusion<br>[1188, 1267, 6]"]
29["Sweep Extrusion<br>[1188, 1267, 6]"]
33["Sweep Extrusion<br>[1470, 1503, 6]"]
34[Wall]
35["Cap End"]
36["SweepEdge Opposite"]
37["SweepEdge Adjacent"]
41["Sweep Extrusion<br>[1630, 1695, 6]"]
41["Sweep Extrusion<br>[1634, 1699, 6]"]
42[Wall]
43["Cap Start"]
44["Cap End"]
45["SweepEdge Opposite"]
46["SweepEdge Adjacent"]
50["Sweep Extrusion<br>[1948, 1992, 6]"]
50["Sweep Extrusion<br>[1952, 1996, 6]"]
51[Wall]
52["SweepEdge Opposite"]
53["SweepEdge Adjacent"]
54["Sweep Extrusion<br>[1948, 1992, 6]"]
55["Sweep Extrusion<br>[1948, 1992, 6]"]
56["Sweep Extrusion<br>[1948, 1992, 6]"]
57["Sweep Extrusion<br>[1948, 1992, 6]"]
61["Sweep Extrusion<br>[2271, 2315, 6]"]
54["Sweep Extrusion<br>[1952, 1996, 6]"]
55["Sweep Extrusion<br>[1952, 1996, 6]"]
56["Sweep Extrusion<br>[1952, 1996, 6]"]
57["Sweep Extrusion<br>[1952, 1996, 6]"]
61["Sweep Extrusion<br>[2275, 2319, 6]"]
62[Wall]
63["Cap End"]
64["SweepEdge Opposite"]
65["SweepEdge Adjacent"]
66["Sweep Extrusion<br>[2271, 2315, 6]"]
67["Sweep Extrusion<br>[2271, 2315, 6]"]
68["Sweep Extrusion<br>[2271, 2315, 6]"]
69["Sweep Extrusion<br>[2271, 2315, 6]"]
70["Sweep Extrusion<br>[2271, 2315, 6]"]
71["Sweep Extrusion<br>[2271, 2315, 6]"]
72["Sweep Extrusion<br>[2271, 2315, 6]"]
73["Sweep Extrusion<br>[2271, 2315, 6]"]
74["Sweep Extrusion<br>[2271, 2315, 6]"]
75["Sweep Extrusion<br>[2271, 2315, 6]"]
76["Sweep Extrusion<br>[2271, 2315, 6]"]
77["Sweep Extrusion<br>[2271, 2315, 6]"]
78["Sweep Extrusion<br>[2271, 2315, 6]"]
79["Sweep Extrusion<br>[2271, 2315, 6]"]
80["Sweep Extrusion<br>[2271, 2315, 6]"]
88["Sweep Extrusion<br>[2724, 2792, 6]"]
66["Sweep Extrusion<br>[2275, 2319, 6]"]
67["Sweep Extrusion<br>[2275, 2319, 6]"]
68["Sweep Extrusion<br>[2275, 2319, 6]"]
69["Sweep Extrusion<br>[2275, 2319, 6]"]
70["Sweep Extrusion<br>[2275, 2319, 6]"]
71["Sweep Extrusion<br>[2275, 2319, 6]"]
72["Sweep Extrusion<br>[2275, 2319, 6]"]
73["Sweep Extrusion<br>[2275, 2319, 6]"]
74["Sweep Extrusion<br>[2275, 2319, 6]"]
75["Sweep Extrusion<br>[2275, 2319, 6]"]
76["Sweep Extrusion<br>[2275, 2319, 6]"]
77["Sweep Extrusion<br>[2275, 2319, 6]"]
78["Sweep Extrusion<br>[2275, 2319, 6]"]
79["Sweep Extrusion<br>[2275, 2319, 6]"]
80["Sweep Extrusion<br>[2275, 2319, 6]"]
88["Sweep Extrusion<br>[2728, 2796, 6]"]
89[Wall]
90[Wall]
91[Wall]
@ -272,11 +272,11 @@ flowchart LR
99["SweepEdge Adjacent"]
100["SweepEdge Opposite"]
101["SweepEdge Adjacent"]
102["Sweep Extrusion<br>[2724, 2792, 6]"]
103["Sweep Extrusion<br>[2724, 2792, 6]"]
104["Sweep Extrusion<br>[2724, 2792, 6]"]
105["Sweep Extrusion<br>[2724, 2792, 6]"]
113["Sweep Extrusion<br>[3198, 3272, 6]"]
102["Sweep Extrusion<br>[2728, 2796, 6]"]
103["Sweep Extrusion<br>[2728, 2796, 6]"]
104["Sweep Extrusion<br>[2728, 2796, 6]"]
105["Sweep Extrusion<br>[2728, 2796, 6]"]
113["Sweep Extrusion<br>[3202, 3276, 6]"]
114[Wall]
115[Wall]
116[Wall]
@ -290,41 +290,41 @@ flowchart LR
124["SweepEdge Adjacent"]
125["SweepEdge Opposite"]
126["SweepEdge Adjacent"]
127["Sweep Extrusion<br>[3198, 3272, 6]"]
128["Sweep Extrusion<br>[3198, 3272, 6]"]
129["Sweep Extrusion<br>[3198, 3272, 6]"]
130["Sweep Extrusion<br>[3198, 3272, 6]"]
131["Plane<br>[327, 344, 5]"]
138["Sweep Extrusion<br>[483, 516, 5]"]
127["Sweep Extrusion<br>[3202, 3276, 6]"]
128["Sweep Extrusion<br>[3202, 3276, 6]"]
129["Sweep Extrusion<br>[3202, 3276, 6]"]
130["Sweep Extrusion<br>[3202, 3276, 6]"]
131["Plane<br>[331, 348, 5]"]
138["Sweep Extrusion<br>[487, 520, 5]"]
139[Wall]
140["Cap Start"]
141["Cap End"]
142["SweepEdge Opposite"]
143["SweepEdge Adjacent"]
150["Sweep Extrusion<br>[771, 804, 5]"]
150["Sweep Extrusion<br>[775, 808, 5]"]
151[Wall]
152["Cap Start"]
153["Cap End"]
154["SweepEdge Opposite"]
155["SweepEdge Adjacent"]
159["Sweep Extrusion<br>[1106, 1140, 5]"]
159["Sweep Extrusion<br>[1110, 1144, 5]"]
160[Wall]
161["SweepEdge Opposite"]
162["SweepEdge Adjacent"]
163["Sweep Extrusion<br>[1106, 1140, 5]"]
164["Sweep Extrusion<br>[1106, 1140, 5]"]
165["Sweep Extrusion<br>[1106, 1140, 5]"]
166["Sweep Extrusion<br>[1106, 1140, 5]"]
170["Sweep Extrusion<br>[1444, 1478, 5]"]
163["Sweep Extrusion<br>[1110, 1144, 5]"]
164["Sweep Extrusion<br>[1110, 1144, 5]"]
165["Sweep Extrusion<br>[1110, 1144, 5]"]
166["Sweep Extrusion<br>[1110, 1144, 5]"]
170["Sweep Extrusion<br>[1448, 1482, 5]"]
171[Wall]
172["SweepEdge Opposite"]
173["SweepEdge Adjacent"]
174["Sweep Extrusion<br>[1444, 1478, 5]"]
175["Sweep Extrusion<br>[1444, 1478, 5]"]
176["Sweep Extrusion<br>[1444, 1478, 5]"]
177["Sweep Extrusion<br>[1444, 1478, 5]"]
178["Plane<br>[1632, 1649, 5]"]
186["Sweep Revolve<br>[1979, 1996, 5]"]
174["Sweep Extrusion<br>[1448, 1482, 5]"]
175["Sweep Extrusion<br>[1448, 1482, 5]"]
176["Sweep Extrusion<br>[1448, 1482, 5]"]
177["Sweep Extrusion<br>[1448, 1482, 5]"]
178["Plane<br>[1636, 1653, 5]"]
186["Sweep Revolve<br>[1983, 2000, 5]"]
187[Wall]
188[Wall]
189[Wall]
@ -332,8 +332,8 @@ flowchart LR
191["SweepEdge Adjacent"]
192["SweepEdge Adjacent"]
193["SweepEdge Adjacent"]
194["Plane<br>[2082, 2099, 5]"]
202["Sweep Revolve<br>[2446, 2463, 5]"]
194["Plane<br>[2086, 2103, 5]"]
202["Sweep Revolve<br>[2450, 2467, 5]"]
203[Wall]
204[Wall]
205[Wall]
@ -342,8 +342,8 @@ flowchart LR
208["SweepEdge Adjacent"]
209["SweepEdge Adjacent"]
210["SweepEdge Adjacent"]
211["Plane<br>[2918, 2941, 5]"]
219["Sweep Extrusion<br>[3863, 3909, 5]"]
211["Plane<br>[2922, 2945, 5]"]
219["Sweep Extrusion<br>[3867, 3913, 5]"]
220[Wall]
221[Wall]
222[Wall]
@ -358,8 +358,8 @@ flowchart LR
231["SweepEdge Adjacent"]
232["SweepEdge Opposite"]
233["SweepEdge Adjacent"]
234["Plane<br>[2918, 2941, 5]"]
242["Sweep Extrusion<br>[3863, 3909, 5]"]
234["Plane<br>[2922, 2945, 5]"]
242["Sweep Extrusion<br>[3867, 3913, 5]"]
243[Wall]
244[Wall]
245[Wall]
@ -374,8 +374,8 @@ flowchart LR
254["SweepEdge Adjacent"]
255["SweepEdge Opposite"]
256["SweepEdge Adjacent"]
257["Plane<br>[4320, 4337, 5]"]
284["Sweep Revolve<br>[5630, 5647, 5]"]
257["Plane<br>[4324, 4341, 5]"]
284["Sweep Revolve<br>[5634, 5651, 5]"]
285[Wall]
286[Wall]
287[Wall]
@ -424,8 +424,8 @@ flowchart LR
330["SweepEdge Adjacent"]
331["SweepEdge Adjacent"]
332["SweepEdge Adjacent"]
333["Plane<br>[706, 732, 8]"]
345["Sweep Revolve<br>[1182, 1199, 8]"]
333["Plane<br>[710, 736, 8]"]
345["Sweep Revolve<br>[1186, 1203, 8]"]
346[Wall]
347[Wall]
348[Wall]
@ -444,8 +444,8 @@ flowchart LR
361["SweepEdge Adjacent"]
362["SweepEdge Adjacent"]
363["SweepEdge Adjacent"]
364["Plane<br>[484, 501, 7]"]
384["Sweep Revolve<br>[2243, 2293, 7]"]
364["Plane<br>[488, 505, 7]"]
384["Sweep Revolve<br>[2247, 2297, 7]"]
385[Wall]
386[Wall]
387[Wall]
@ -499,8 +499,8 @@ flowchart LR
435["SweepEdge Adjacent"]
436["SweepEdge Opposite"]
437["SweepEdge Adjacent"]
438["Plane<br>[460, 477, 9]"]
455["Sweep Revolve<br>[1486, 1515, 9]"]
438["Plane<br>[464, 481, 9]"]
455["Sweep Revolve<br>[1490, 1519, 9]"]
456[Wall]
457[Wall]
458[Wall]
@ -529,17 +529,17 @@ flowchart LR
481["SweepEdge Adjacent"]
482["SweepEdge Adjacent"]
483["SweepEdge Adjacent"]
484["StartSketchOnFace<br>[770, 797, 6]"]
485["StartSketchOnFace<br>[947, 978, 6]"]
486["StartSketchOnFace<br>[1385, 1414, 6]"]
487["StartSketchOnFace<br>[1524, 1558, 6]"]
488["StartSketchOnFace<br>[1709, 1742, 6]"]
489["StartSketchOnFace<br>[2009, 2038, 6]"]
490["StartSketchOnFace<br>[2338, 2367, 6]"]
491["StartSketchOnFace<br>[2821, 2854, 6]"]
492["StartSketchOnFace<br>[603, 632, 5]"]
493["StartSketchOnFace<br>[865, 899, 5]"]
494["StartSketchOnFace<br>[1202, 1231, 5]"]
484["StartSketchOnFace<br>[774, 801, 6]"]
485["StartSketchOnFace<br>[951, 982, 6]"]
486["StartSketchOnFace<br>[1389, 1418, 6]"]
487["StartSketchOnFace<br>[1528, 1562, 6]"]
488["StartSketchOnFace<br>[1713, 1746, 6]"]
489["StartSketchOnFace<br>[2013, 2042, 6]"]
490["StartSketchOnFace<br>[2342, 2371, 6]"]
491["StartSketchOnFace<br>[2825, 2858, 6]"]
492["StartSketchOnFace<br>[607, 636, 5]"]
493["StartSketchOnFace<br>[869, 903, 5]"]
494["StartSketchOnFace<br>[1206, 1235, 5]"]
1 --- 2
2 --- 3
2 ---- 5

View File

@ -12,10 +12,13 @@ description: Result of parsing car-wheel-assembly.kcl
"type": "Kcl",
"filename": "car-wheel.kcl"
},
"preComments": [
"// Import parts"
],
"selector": {
"type": "None",
"alias": {
"commentStart": 155,
"commentStart": 171,
"end": 0,
"name": "carWheel",
"start": 0,
@ -27,7 +30,7 @@ description: Result of parsing car-wheel-assembly.kcl
"type": "ImportStatement"
},
{
"commentStart": 164,
"commentStart": 180,
"end": 0,
"path": {
"type": "Kcl",
@ -36,7 +39,7 @@ description: Result of parsing car-wheel-assembly.kcl
"selector": {
"type": "None",
"alias": {
"commentStart": 190,
"commentStart": 206,
"end": 0,
"name": "carRotor",
"start": 0,
@ -48,7 +51,7 @@ description: Result of parsing car-wheel-assembly.kcl
"type": "ImportStatement"
},
{
"commentStart": 199,
"commentStart": 215,
"end": 0,
"path": {
"type": "Kcl",
@ -57,7 +60,7 @@ description: Result of parsing car-wheel-assembly.kcl
"selector": {
"type": "None",
"alias": {
"commentStart": 229,
"commentStart": 245,
"end": 0,
"name": "brakeCaliper",
"start": 0,
@ -69,7 +72,7 @@ description: Result of parsing car-wheel-assembly.kcl
"type": "ImportStatement"
},
{
"commentStart": 242,
"commentStart": 258,
"end": 0,
"path": {
"type": "Kcl",
@ -78,7 +81,7 @@ description: Result of parsing car-wheel-assembly.kcl
"selector": {
"type": "None",
"alias": {
"commentStart": 266,
"commentStart": 282,
"end": 0,
"name": "lugNut",
"start": 0,
@ -90,7 +93,7 @@ description: Result of parsing car-wheel-assembly.kcl
"type": "ImportStatement"
},
{
"commentStart": 273,
"commentStart": 289,
"end": 0,
"path": {
"type": "Kcl",
@ -99,7 +102,7 @@ description: Result of parsing car-wheel-assembly.kcl
"selector": {
"type": "None",
"alias": {
"commentStart": 298,
"commentStart": 314,
"end": 0,
"name": "carTire",
"start": 0,
@ -111,46 +114,38 @@ description: Result of parsing car-wheel-assembly.kcl
"type": "ImportStatement"
},
{
"commentStart": 306,
"commentStart": 321,
"end": 0,
"path": {
"type": "Kcl",
"filename": "globals.kcl"
"filename": "parameters.kcl"
},
"preComments": [
"",
"",
"// Import parameters"
],
"selector": {
"type": "List",
"items": [
{
"alias": null,
"commentStart": 313,
"end": 0,
"name": {
"commentStart": 313,
"end": 0,
"name": "lugCount",
"start": 0,
"type": "Identifier"
},
"start": 0,
"type": "ImportItem"
}
]
"commentStart": 351,
"end": 0,
"start": 0,
"type": "Glob"
},
"start": 0,
"type": "ImportStatement",
"type": "ImportStatement"
},
{
"commentStart": 340,
"commentStart": 374,
"end": 0,
"expression": {
"body": [
{
"abs_path": false,
"commentStart": 342,
"commentStart": 399,
"end": 0,
"name": {
"commentStart": 342,
"commentStart": 399,
"end": 0,
"name": "carRotor",
"start": 0,
@ -166,14 +161,14 @@ description: Result of parsing car-wheel-assembly.kcl
{
"type": "LabeledArg",
"label": {
"commentStart": 366,
"commentStart": 423,
"end": 0,
"name": "x",
"start": 0,
"type": "Identifier"
},
"arg": {
"commentStart": 370,
"commentStart": 427,
"end": 0,
"raw": "0",
"start": 0,
@ -188,14 +183,14 @@ description: Result of parsing car-wheel-assembly.kcl
{
"type": "LabeledArg",
"label": {
"commentStart": 373,
"commentStart": 430,
"end": 0,
"name": "y",
"start": 0,
"type": "Identifier"
},
"arg": {
"commentStart": 377,
"commentStart": 434,
"end": 0,
"raw": "0.5",
"start": 0,
@ -210,14 +205,14 @@ description: Result of parsing car-wheel-assembly.kcl
{
"type": "LabeledArg",
"label": {
"commentStart": 382,
"commentStart": 439,
"end": 0,
"name": "z",
"start": 0,
"type": "Identifier"
},
"arg": {
"commentStart": 386,
"commentStart": 443,
"end": 0,
"raw": "0",
"start": 0,
@ -232,10 +227,10 @@ description: Result of parsing car-wheel-assembly.kcl
],
"callee": {
"abs_path": false,
"commentStart": 356,
"commentStart": 413,
"end": 0,
"name": {
"commentStart": 356,
"commentStart": 413,
"end": 0,
"name": "translate",
"start": 0,
@ -245,7 +240,7 @@ description: Result of parsing car-wheel-assembly.kcl
"start": 0,
"type": "Name"
},
"commentStart": 356,
"commentStart": 413,
"end": 0,
"start": 0,
"type": "CallExpressionKw",
@ -253,25 +248,48 @@ description: Result of parsing car-wheel-assembly.kcl
"unlabeled": null
}
],
"commentStart": 342,
"commentStart": 399,
"end": 0,
"nonCodeMeta": {
"nonCodeNodes": {
"1": [
{
"commentStart": 445,
"end": 0,
"start": 0,
"type": "NonCodeNode",
"value": {
"type": "newLineBlockComment",
"value": "Place the car wheel",
"style": "line"
}
}
]
},
"startNodes": []
},
"start": 0,
"type": "PipeExpression",
"type": "PipeExpression"
},
"preComments": [
"",
"",
"// Place the car rotor"
],
"start": 0,
"type": "ExpressionStatement",
"type": "ExpressionStatement"
},
{
"commentStart": 389,
"commentStart": 470,
"end": 0,
"expression": {
"abs_path": false,
"commentStart": 389,
"commentStart": 470,
"end": 0,
"name": {
"commentStart": 389,
"commentStart": 470,
"end": 0,
"name": "carWheel",
"start": 0,
@ -287,16 +305,16 @@ description: Result of parsing car-wheel-assembly.kcl
"type": "ExpressionStatement"
},
{
"commentStart": 398,
"commentStart": 478,
"end": 0,
"expression": {
"body": [
{
"abs_path": false,
"commentStart": 398,
"commentStart": 502,
"end": 0,
"name": {
"commentStart": 398,
"commentStart": 502,
"end": 0,
"name": "lugNut",
"start": 0,
@ -312,14 +330,14 @@ description: Result of parsing car-wheel-assembly.kcl
{
"type": "LabeledArg",
"label": {
"commentStart": 436,
"commentStart": 540,
"end": 0,
"name": "arcDegrees",
"start": 0,
"type": "Identifier"
},
"arg": {
"commentStart": 449,
"commentStart": 553,
"end": 0,
"raw": "360",
"start": 0,
@ -334,17 +352,17 @@ description: Result of parsing car-wheel-assembly.kcl
{
"type": "LabeledArg",
"label": {
"commentStart": 461,
"commentStart": 565,
"end": 0,
"name": "axis",
"start": 0,
"type": "Identifier"
},
"arg": {
"commentStart": 468,
"commentStart": 572,
"elements": [
{
"commentStart": 469,
"commentStart": 573,
"end": 0,
"raw": "0",
"start": 0,
@ -356,7 +374,7 @@ description: Result of parsing car-wheel-assembly.kcl
}
},
{
"commentStart": 472,
"commentStart": 576,
"end": 0,
"raw": "1",
"start": 0,
@ -368,7 +386,7 @@ description: Result of parsing car-wheel-assembly.kcl
}
},
{
"commentStart": 475,
"commentStart": 579,
"end": 0,
"raw": "0",
"start": 0,
@ -389,17 +407,17 @@ description: Result of parsing car-wheel-assembly.kcl
{
"type": "LabeledArg",
"label": {
"commentStart": 486,
"commentStart": 590,
"end": 0,
"name": "center",
"start": 0,
"type": "Identifier"
},
"arg": {
"commentStart": 495,
"commentStart": 599,
"elements": [
{
"commentStart": 496,
"commentStart": 600,
"end": 0,
"raw": "0",
"start": 0,
@ -411,7 +429,7 @@ description: Result of parsing car-wheel-assembly.kcl
}
},
{
"commentStart": 499,
"commentStart": 603,
"end": 0,
"raw": "0",
"start": 0,
@ -423,7 +441,7 @@ description: Result of parsing car-wheel-assembly.kcl
}
},
{
"commentStart": 502,
"commentStart": 606,
"end": 0,
"raw": "0",
"start": 0,
@ -444,7 +462,7 @@ description: Result of parsing car-wheel-assembly.kcl
{
"type": "LabeledArg",
"label": {
"commentStart": 513,
"commentStart": 617,
"end": 0,
"name": "instances",
"start": 0,
@ -452,10 +470,10 @@ description: Result of parsing car-wheel-assembly.kcl
},
"arg": {
"abs_path": false,
"commentStart": 525,
"commentStart": 629,
"end": 0,
"name": {
"commentStart": 525,
"commentStart": 629,
"end": 0,
"name": "lugCount",
"start": 0,
@ -470,14 +488,14 @@ description: Result of parsing car-wheel-assembly.kcl
{
"type": "LabeledArg",
"label": {
"commentStart": 542,
"commentStart": 646,
"end": 0,
"name": "rotateDuplicates",
"start": 0,
"type": "Identifier"
},
"arg": {
"commentStart": 561,
"commentStart": 665,
"end": 0,
"raw": "false",
"start": 0,
@ -489,10 +507,10 @@ description: Result of parsing car-wheel-assembly.kcl
],
"callee": {
"abs_path": false,
"commentStart": 410,
"commentStart": 514,
"end": 0,
"name": {
"commentStart": 410,
"commentStart": 514,
"end": 0,
"name": "patternCircular3d",
"start": 0,
@ -502,7 +520,7 @@ description: Result of parsing car-wheel-assembly.kcl
"start": 0,
"type": "Name"
},
"commentStart": 410,
"commentStart": 514,
"end": 0,
"start": 0,
"type": "CallExpressionKw",
@ -510,27 +528,50 @@ description: Result of parsing car-wheel-assembly.kcl
"unlabeled": null
}
],
"commentStart": 398,
"commentStart": 502,
"end": 0,
"nonCodeMeta": {
"nonCodeNodes": {
"1": [
{
"commentStart": 678,
"end": 0,
"start": 0,
"type": "NonCodeNode",
"value": {
"type": "newLineBlockComment",
"value": "Place the brake caliper",
"style": "line"
}
}
]
},
"startNodes": []
},
"start": 0,
"type": "PipeExpression",
"type": "PipeExpression"
},
"preComments": [
"",
"",
"// Place the lug nuts"
],
"start": 0,
"type": "ExpressionStatement",
"type": "ExpressionStatement"
},
{
"commentStart": 575,
"commentStart": 707,
"end": 0,
"expression": {
"body": [
{
"abs_path": false,
"commentStart": 575,
"commentStart": 707,
"end": 0,
"name": {
"commentStart": 575,
"commentStart": 707,
"end": 0,
"name": "brakeCaliper",
"start": 0,
@ -546,14 +587,14 @@ description: Result of parsing car-wheel-assembly.kcl
{
"type": "LabeledArg",
"label": {
"commentStart": 603,
"commentStart": 735,
"end": 0,
"name": "x",
"start": 0,
"type": "Identifier"
},
"arg": {
"commentStart": 607,
"commentStart": 739,
"end": 0,
"raw": "0",
"start": 0,
@ -568,14 +609,14 @@ description: Result of parsing car-wheel-assembly.kcl
{
"type": "LabeledArg",
"label": {
"commentStart": 610,
"commentStart": 742,
"end": 0,
"name": "y",
"start": 0,
"type": "Identifier"
},
"arg": {
"commentStart": 614,
"commentStart": 746,
"end": 0,
"raw": "0.5",
"start": 0,
@ -590,14 +631,14 @@ description: Result of parsing car-wheel-assembly.kcl
{
"type": "LabeledArg",
"label": {
"commentStart": 619,
"commentStart": 751,
"end": 0,
"name": "z",
"start": 0,
"type": "Identifier"
},
"arg": {
"commentStart": 623,
"commentStart": 755,
"end": 0,
"raw": "0",
"start": 0,
@ -612,10 +653,10 @@ description: Result of parsing car-wheel-assembly.kcl
],
"callee": {
"abs_path": false,
"commentStart": 593,
"commentStart": 725,
"end": 0,
"name": {
"commentStart": 593,
"commentStart": 725,
"end": 0,
"name": "translate",
"start": 0,
@ -625,7 +666,7 @@ description: Result of parsing car-wheel-assembly.kcl
"start": 0,
"type": "Name"
},
"commentStart": 593,
"commentStart": 725,
"end": 0,
"start": 0,
"type": "CallExpressionKw",
@ -633,8 +674,26 @@ description: Result of parsing car-wheel-assembly.kcl
"unlabeled": null
}
],
"commentStart": 575,
"commentStart": 707,
"end": 0,
"nonCodeMeta": {
"nonCodeNodes": {
"1": [
{
"commentStart": 757,
"end": 0,
"start": 0,
"type": "NonCodeNode",
"value": {
"type": "newLineBlockComment",
"value": "Place the car tire",
"style": "line"
}
}
]
},
"startNodes": []
},
"start": 0,
"type": "PipeExpression",
"type": "PipeExpression"
@ -644,14 +703,14 @@ description: Result of parsing car-wheel-assembly.kcl
"type": "ExpressionStatement"
},
{
"commentStart": 626,
"commentStart": 781,
"end": 0,
"expression": {
"abs_path": false,
"commentStart": 626,
"commentStart": 781,
"end": 0,
"name": {
"commentStart": 626,
"commentStart": 781,
"end": 0,
"name": "carTire",
"start": 0,
@ -723,19 +782,7 @@ description: Result of parsing car-wheel-assembly.kcl
}
],
"nonCodeMeta": {
"nonCodeNodes": {
"5": [
{
"commentStart": 340,
"end": 0,
"start": 0,
"type": "NonCodeNode",
"value": {
"type": "newLine"
}
}
]
},
"nonCodeNodes": {},
"startNodes": [
{
"commentStart": 127,

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