Compare commits

..

21 Commits

Author SHA1 Message Date
6c9f39e65a Fix to add NodePaths to SketchOnFace and SketchOnPlane artifacts 2025-05-14 01:33:37 -04:00
1e487ef3bd Include NodePath in artifact graph mermaid charts as comments (#6884)
* Display NodePath in artifact graph mermaid charts

* Update output

* Change node path display to be only comments

* Update output

* Update output after rebase
2025-05-14 05:31:58 +00:00
811ef3e72d fix pw test i turned off (#6921)
updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2025-05-14 04:36:52 +00:00
980e3c4bc2 remove my sins (#6919)
Signed-off-by: Jess Frazelle <github@jessfraz.com>
2025-05-14 04:28:55 +00:00
78b6854c6b bump modeling-cmds, nuke slow world (#6753)
* bump modeling-cmds, nuke slow world

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

* more stuffs

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>

* i mechanical engineered today

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

* reverse uno your revolves

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>

* retry logic

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>

* updates

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

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2025-05-14 04:07:24 +00:00
068b9129cf add a sleep for local engine disconnect/reconnect (#6918)
updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2025-05-13 16:12:37 -07:00
05fba3c50c more stable shards (#6916)
Signed-off-by: Jess Frazelle <github@jessfraz.com>
2025-05-13 15:27:18 -07:00
7944a4ce41 New single-file samples for the website (#6670)
* New single-file samples for the website

* Update kcl-samples simulation test output

* Update kcl-samples simulation test output

* Update kcl-samples simulation test output

* Update kcl-samples simulation test output

* Update kcl-samples simulation test output

* Update kcl-samples simulation test output

* Update kcl-samples simulation test output

* Update kcl-samples simulation test output

* Update kcl-samples simulation test output

* Update kcl-samples simulation test output

* Update kcl-samples simulation test output

* Update kcl-samples simulation test output

* Update kcl-samples simulation test output

* Delete public/kcl-samples/piston directory

* More

* updates

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

* updates

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

* updates

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

* updates

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

* updates

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

* updates

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

* move another test

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>

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Jess Frazelle <jessfraz@users.noreply.github.com>
Co-authored-by: Jess Frazelle <github@jessfraz.com>
2025-05-13 15:05:57 -07:00
4640f1a3ad Teaching t2c how to counterbore, countersink, and counterdrill (#6833)
* Teaching t2c how to counterbore, countersink, and counterdrill

* Delete public/kcl-samples/parametric-bearing-pillow-block directory

* Update mounting-wire.kcl

* new artifiacts

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

* Update kcl-samples simulation test output

* Update kcl-samples simulation test output

* 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>

---------

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-05-13 14:11:50 -07:00
cd79059d97 Subtract tests (#6913)
* add subtract test and cleanup some other tests

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

* updates

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

* fmt

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

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2025-05-13 14:06:10 -07:00
2d95e19048 Gears DLC (free) (#6835)
* Gears DLC (free)

Using the involuteCircular fn to create a variety of cylindrical gearsets

* Delete public/kcl-samples/gear directory

* Update main.kcl

fixing gear meshing

* new samples

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

* add link

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

---------

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>
2025-05-13 14:03:52 -07:00
d047587bc1 Avoid using full revolve for now (#6912)
Avoid using revolve for now

When we moved to concurrent execution of KCL modules, we begun to see an
error we never fully understood, and because it was pretty hard to
trigger, we wound up never being able to fix it. Today we were able to
track it down to the `revolve` call here.

Specifically, the problem is triggered when we're doing a "Full Revolve"
(e.g., `angle = 359.999999` passes, but *not* `angle = 360` or the
default, as it is in `main`), and concurrently executing modules will
see something weird happen with `getNextAdjacentEdge`.

From all the smoke I believe this happens only when we are doing a *full
revolve*, *AND* we're executing other modules which are calling
`getNextAdjacentEdge`.

When the `revolve` is present, we can lose the race in *either*
`talk-button.kcl` OR `case.kcl`.

If I move back to single-threaded execution OR I add imports to sequence
things carefully, I can get the tests to pass. If the revolve is an
`extrude` or not a full revolve, it works fine.

My best guess is that it seems like the world got flipped upside down or
something, such that "next edge" has a different orentation for two
calls. My even further guess is that inside `revolve` we mutate
something connection-global such that it alters the intepretation of
calls made during the revolve implementation's "critical section".
2025-05-13 20:20:48 +00:00
128e1093fb Update snaps (#6911)
* update pattern entity ids since that pr merged

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

* artifacts

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

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2025-05-13 19:27:34 +00:00
afdc305e3e Update new onboarding after team feedback (#6903)
* Update onboarding following @jgomez720

* Fix up TODO's in desktop conclusion (ty Ian)
2025-05-13 14:52:19 -04:00
4bc5439996 Prevent concurrent run of build-apps on main (#6909) 2025-05-13 18:20:27 +00:00
be14022f97 Update samples PNG export (#6908) 2025-05-13 18:03:27 +00:00
eda78ef5ae Fix test by closing code pane after loading the scene (#6907) 2025-05-13 18:03:16 +00:00
0cc833e687 Keep toast message around longer when testing (#6902) 2025-05-13 13:59:52 -04:00
33e83747f3 Split up example tests into smaller batches and provide info on which example is failing (#6896)
* Give example info for failing std example tests

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

* Shard example tests into 10

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

---------

Signed-off-by: Nick Cameron <nrc@ncameron.org>
2025-05-13 10:50:54 -07:00
c3a8fc6d93 Remove unneeded check on the network health text label (#6905) 2025-05-13 13:46:09 -04:00
8ff84e269c Update bug icon to not use FontAwesome (#6904)
lol we had a custom bug icon in the codebase, no clue why I didn't
update the pane config.
2025-05-13 13:45:07 -04:00
540 changed files with 223209 additions and 447851 deletions

View File

@ -13,7 +13,7 @@ env:
IS_NIGHTLY: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:

View File

@ -34,7 +34,7 @@ The 3D view in Design Studio is just a video stream from our hosted geometry eng
- WebSockets (via [KittyCAD TS client](https://github.com/KittyCAD/kittycad.ts))
- Code Editor
- [CodeMirror](https://codemirror.net/)
- Custom WASM LSP Server
- [Custom WASM LSP Server](https://github.com/KittyCAD/modeling-app/tree/main/rust/kcl-lib/src/lsp/kcl)
- Modeling
- [KittyCAD TypeScript client](https://github.com/KittyCAD/kittycad.ts)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -122515,7 +122515,7 @@
"deprecated": false,
"examples": [
[
"// Loft a square and a triangle.\nsquareSketch = startSketchOn(XY)\n |> startProfile(at = [-100, 200])\n |> line(end = [200, 0])\n |> line(end = [0, -200])\n |> line(end = [-200, 0])\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\n\ntriangleSketch = startSketchOn(offsetPlane(XY, offset = 75))\n |> startProfile(at = [0, 125])\n |> line(end = [-15, -30])\n |> line(end = [30, 0])\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\n\nloft([squareSketch, triangleSketch])",
"// Loft a square and a triangle.\nsquareSketch = startSketchOn(XY)\n |> startProfile(at = [-100, 200])\n |> line(end = [200, 0])\n |> line(end = [0, -200])\n |> line(end = [-200, 0])\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\n\ntriangleSketch = startSketchOn(offsetPlane(XY, offset = 75))\n |> startProfile(at = [0, 125])\n |> line(end = [-15, -30])\n |> line(end = [30, 0])\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\n\nloft([triangleSketch, squareSketch])",
false
],
[

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1818,7 +1818,6 @@ test(
'extrude-custom-plane.kcl',
'extrude-inside-fn-with-tags.kcl',
'fillet-and-shell.kcl',
'fillet_duplicate_tags.kcl',
'focusrite_scarlett_mounting_bracket.kcl',
'function_sketch.kcl',
'function_sketch_with_position.kcl',
@ -1826,7 +1825,6 @@ test(
'helix_defaults.kcl',
'helix_defaults_negative_extrude.kcl',
'helix_with_length.kcl',
'i_shape.kcl',
'kittycad_svg.kcl',
'lego.kcl',
'lsystem.kcl',

View File

@ -329,10 +329,10 @@ extrude002 = extrude(profile002, length = 150)
)
const websocketPromise = page.waitForEvent('websocket')
await toolbar.closePane('code')
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await toolbar.closePane('code')
const websocket = await websocketPromise
await scene.connectionEstablished()
@ -549,6 +549,44 @@ extrude002 = extrude(profile002, length = 150)
})
})
test(
`Network health indicator only appears in modeling view`,
{ tag: '@electron' },
async ({ context, page }) => {
await context.folderSetupFn(async (dir) => {
const bracketDir = path.join(dir, 'bracket')
await fsp.mkdir(bracketDir, { recursive: true })
await fsp.copyFile(
executorInputPath('cylinder-inches.kcl'),
path.join(bracketDir, 'main.kcl')
)
})
await page.setBodyDimensions({ width: 1200, height: 500 })
// Locators
const projectsHeading = page.getByRole('heading', {
name: 'Projects',
})
const projectLink = page.getByRole('link', { name: 'bracket' })
const networkHealthIndicator = page.getByTestId('network-toggle')
await test.step('Check the home page', async () => {
await expect(projectsHeading).toBeVisible()
await expect(projectLink).toBeVisible()
await expect(networkHealthIndicator).not.toBeVisible()
})
await test.step('Open the project', async () => {
await projectLink.click()
})
await test.step('Check the modeling view', async () => {
await expect(projectsHeading).not.toBeVisible()
await expect(networkHealthIndicator).toBeVisible()
})
}
)
test(`View gizmo stays visible even when zoomed out all the way`, async ({
page,
homePage,

View File

@ -809,8 +809,6 @@ export const doExport = async (
await page.getByRole('button', { name: 'Submit command' }).click()
// This usually happens immediately after. If we're too slow we don't
// catch it.
await expect(page.getByText('Exported successfully')).toBeVisible()
if (exportFrom === 'sidebarButton' || exportFrom === 'commandBar') {

View File

@ -33,8 +33,8 @@ test.describe('Testing loading external models', () => {
// Locators and constants
const newSample = {
file: 'parametric-bearing-pillow-block' + FILE_EXT,
title: 'Parametric Bearing Pillow Block',
file: 'pillow-block-bearing' + FILE_EXT,
title: 'Pillow Block Bearing',
}
const commandBarButton = page.getByRole('button', { name: 'Commands' })
const samplesCommandOption = page.getByRole('option', {
@ -100,9 +100,9 @@ test.describe('Testing loading external models', () => {
// Locators and constants
const sampleOne = {
file: 'parametric-bearing-pillow-block' + FILE_EXT,
title: 'Parametric Bearing Pillow Block',
file1: 'parametric-bearing-pillow-block-1' + FILE_EXT,
file: 'ball-bearing' + FILE_EXT,
title: 'Ball Bearing',
file1: 'ball-bearing-1' + FILE_EXT,
}
const projectCard = page.getByRole('link', { name: 'bracket' })
const overwriteWarning = page.getByText(

View File

@ -74,7 +74,7 @@
LIBCLANG_PATH = "${pkgs.libclang.lib}/lib";
ELECTRON_OVERRIDE_DIST_PATH =
if pkgs.stdenv.isDarwin
then "${pkgs.electron}/Applications"
then "${pkgs.electron}/Applications/Electron.app/Contents/MacOS/"
else "${pkgs.electron}/bin";
PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS = true;
PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH = "${pkgs.playwright-driver.browsers}/chromium-1091/chrome-linux/chrome";

View File

@ -31,14 +31,24 @@ When you submit a PR to add or modify KCL samples, images will be generated and
[![ball-bearing](screenshots/ball-bearing.png)](ball-bearing/main.kcl)
#### [bench](bench/main.kcl) ([screenshot](screenshots/bench.png))
[![bench](screenshots/bench.png)](bench/main.kcl)
#### [bone-plate](bone-plate/main.kcl) ([screenshot](screenshots/bone-plate.png))
[![bone-plate](screenshots/bone-plate.png)](bone-plate/main.kcl)
#### [bottle](bottle/main.kcl) ([screenshot](screenshots/bottle.png))
[![bottle](screenshots/bottle.png)](bottle/main.kcl)
#### [bracket](bracket/main.kcl) ([screenshot](screenshots/bracket.png))
[![bracket](screenshots/bracket.png)](bracket/main.kcl)
#### [car-wheel-assembly](car-wheel-assembly/main.kcl) ([screenshot](screenshots/car-wheel-assembly.png))
[![car-wheel-assembly](screenshots/car-wheel-assembly.png)](car-wheel-assembly/main.kcl)
#### [cold-plate](cold-plate/main.kcl) ([screenshot](screenshots/cold-plate.png))
[![cold-plate](screenshots/cold-plate.png)](cold-plate/main.kcl)
#### [color-cube](color-cube/main.kcl) ([screenshot](screenshots/color-cube.png))
[![color-cube](screenshots/color-cube.png)](color-cube/main.kcl)
#### [counterdrilled-weldment](counterdrilled-weldment/main.kcl) ([screenshot](screenshots/counterdrilled-weldment.png))
[![counterdrilled-weldment](screenshots/counterdrilled-weldment.png)](counterdrilled-weldment/main.kcl)
#### [countersunk-plate](countersunk-plate/main.kcl) ([screenshot](screenshots/countersunk-plate.png))
[![countersunk-plate](screenshots/countersunk-plate.png)](countersunk-plate/main.kcl)
#### [cpu-cooler](cpu-cooler/main.kcl) ([screenshot](screenshots/cpu-cooler.png))
[![cpu-cooler](screenshots/cpu-cooler.png)](cpu-cooler/main.kcl)
#### [cycloidal-gear](cycloidal-gear/main.kcl) ([screenshot](screenshots/cycloidal-gear.png))
[![cycloidal-gear](screenshots/cycloidal-gear.png)](cycloidal-gear/main.kcl)
#### [dodecahedron](dodecahedron/main.kcl) ([screenshot](screenshots/dodecahedron.png))
@ -55,8 +65,6 @@ When you submit a PR to add or modify KCL samples, images will be generated and
[![food-service-spatula](screenshots/food-service-spatula.png)](food-service-spatula/main.kcl)
#### [french-press](french-press/main.kcl) ([screenshot](screenshots/french-press.png))
[![french-press](screenshots/french-press.png)](french-press/main.kcl)
#### [gear](gear/main.kcl) ([screenshot](screenshots/gear.png))
[![gear](screenshots/gear.png)](gear/main.kcl)
#### [gear-rack](gear-rack/main.kcl) ([screenshot](screenshots/gear-rack.png))
[![gear-rack](screenshots/gear-rack.png)](gear-rack/main.kcl)
#### [gridfinity-baseplate](gridfinity-baseplate/main.kcl) ([screenshot](screenshots/gridfinity-baseplate.png))
@ -67,6 +75,18 @@ When you submit a PR to add or modify KCL samples, images will be generated and
[![gridfinity-bins](screenshots/gridfinity-bins.png)](gridfinity-bins/main.kcl)
#### [gridfinity-bins-stacking-lip](gridfinity-bins-stacking-lip/main.kcl) ([screenshot](screenshots/gridfinity-bins-stacking-lip.png))
[![gridfinity-bins-stacking-lip](screenshots/gridfinity-bins-stacking-lip.png)](gridfinity-bins-stacking-lip/main.kcl)
#### [hammer](hammer/main.kcl) ([screenshot](screenshots/hammer.png))
[![hammer](screenshots/hammer.png)](hammer/main.kcl)
#### [helical-gear](helical-gear/main.kcl) ([screenshot](screenshots/helical-gear.png))
[![helical-gear](screenshots/helical-gear.png)](helical-gear/main.kcl)
#### [helical-planetary-gearset](helical-planetary-gearset/main.kcl) ([screenshot](screenshots/helical-planetary-gearset.png))
[![helical-planetary-gearset](screenshots/helical-planetary-gearset.png)](helical-planetary-gearset/main.kcl)
#### [helium-tank](helium-tank/main.kcl) ([screenshot](screenshots/helium-tank.png))
[![helium-tank](screenshots/helium-tank.png)](helium-tank/main.kcl)
#### [herringbone-gear](herringbone-gear/main.kcl) ([screenshot](screenshots/herringbone-gear.png))
[![herringbone-gear](screenshots/herringbone-gear.png)](herringbone-gear/main.kcl)
#### [herringbone-planetary-gearset](herringbone-planetary-gearset/main.kcl) ([screenshot](screenshots/herringbone-planetary-gearset.png))
[![herringbone-planetary-gearset](screenshots/herringbone-planetary-gearset.png)](herringbone-planetary-gearset/main.kcl)
#### [hex-nut](hex-nut/main.kcl) ([screenshot](screenshots/hex-nut.png))
[![hex-nut](screenshots/hex-nut.png)](hex-nut/main.kcl)
#### [i-beam](i-beam/main.kcl) ([screenshot](screenshots/i-beam.png))
@ -83,8 +103,8 @@ When you submit a PR to add or modify KCL samples, images will be generated and
[![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)
#### [pillow-block-bearing](pillow-block-bearing/main.kcl) ([screenshot](screenshots/pillow-block-bearing.png))
[![pillow-block-bearing](screenshots/pillow-block-bearing.png)](pillow-block-bearing/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))
@ -93,6 +113,8 @@ When you submit a PR to add or modify KCL samples, images will be generated and
[![pipe-with-bend](screenshots/pipe-with-bend.png)](pipe-with-bend/main.kcl)
#### [poopy-shoe](poopy-shoe/main.kcl) ([screenshot](screenshots/poopy-shoe.png))
[![poopy-shoe](screenshots/poopy-shoe.png)](poopy-shoe/main.kcl)
#### [prosthetic-hip](prosthetic-hip/main.kcl) ([screenshot](screenshots/prosthetic-hip.png))
[![prosthetic-hip](screenshots/prosthetic-hip.png)](prosthetic-hip/main.kcl)
#### [router-template-cross-bar](router-template-cross-bar/main.kcl) ([screenshot](screenshots/router-template-cross-bar.png))
[![router-template-cross-bar](screenshots/router-template-cross-bar.png)](router-template-cross-bar/main.kcl)
#### [router-template-slate](router-template-slate/main.kcl) ([screenshot](screenshots/router-template-slate.png))
@ -101,10 +123,20 @@ When you submit a PR to add or modify KCL samples, images will be generated and
[![sheet-metal-bracket](screenshots/sheet-metal-bracket.png)](sheet-metal-bracket/main.kcl)
#### [socket-head-cap-screw](socket-head-cap-screw/main.kcl) ([screenshot](screenshots/socket-head-cap-screw.png))
[![socket-head-cap-screw](screenshots/socket-head-cap-screw.png)](socket-head-cap-screw/main.kcl)
#### [spur-gear](spur-gear/main.kcl) ([screenshot](screenshots/spur-gear.png))
[![spur-gear](screenshots/spur-gear.png)](spur-gear/main.kcl)
#### [spur-reduction-gearset](spur-reduction-gearset/main.kcl) ([screenshot](screenshots/spur-reduction-gearset.png))
[![spur-reduction-gearset](screenshots/spur-reduction-gearset.png)](spur-reduction-gearset/main.kcl)
#### [surgical-drill-guide](surgical-drill-guide/main.kcl) ([screenshot](screenshots/surgical-drill-guide.png))
[![surgical-drill-guide](screenshots/surgical-drill-guide.png)](surgical-drill-guide/main.kcl)
#### [tooling-nest-block](tooling-nest-block/main.kcl) ([screenshot](screenshots/tooling-nest-block.png))
[![tooling-nest-block](screenshots/tooling-nest-block.png)](tooling-nest-block/main.kcl)
#### [utility-sink](utility-sink/main.kcl) ([screenshot](screenshots/utility-sink.png))
[![utility-sink](screenshots/utility-sink.png)](utility-sink/main.kcl)
#### [walkie-talkie](walkie-talkie/main.kcl) ([screenshot](screenshots/walkie-talkie.png))
[![walkie-talkie](screenshots/walkie-talkie.png)](walkie-talkie/main.kcl)
#### [washer](washer/main.kcl) ([screenshot](screenshots/washer.png))
[![washer](screenshots/washer.png)](washer/main.kcl)
#### [wing-spar](wing-spar/main.kcl) ([screenshot](screenshots/wing-spar.png))
[![wing-spar](screenshots/wing-spar.png)](wing-spar/main.kcl)

View File

@ -0,0 +1,55 @@
// Bone Plate
// A bone plate is a medical device used in orthopedics to stabilize and fix bone fractures during the healing process. They are typically made of stainless steel or titanium and are secured to the bone with screws. Bone plates come in various types, including locking, compression, and bridge plates, each with specific applications
// Set units
@settings(defaultLengthUnit = mm)
// Define parameters
boltSize = 4.5
// Revolve the profile of a compression plate designed to fit a bone
plateRevolve = startSketchOn(YZ)
|> startProfile(at = [22.9, 0])
|> arc(angleStart = 180, angleEnd = 176, radius = 120)
|> arc(angleStart = -60, angleEnd = 54, radius = 5)
|> arc(angleStart = 180, angleEnd = 176, radius = 120)
|> arc(angleStart = -60, angleEnd = 54, radius = 5)
|> arc(angleStart = 180, angleEnd = 176, radius = 120)
|> arc(angleStart = -60, angleEnd = 54, radius = 5)
|> arc(angleStart = 180, angleEnd = 174, radius = 170)
|> tangentialArc(endAbsolute = [41.8, 91.88])
|> tangentialArc(endAbsolute = [56.92, 117.08], tag = $seg01)
|> angledLine(angle = tangentToEnd(seg01), length = 23.16)
|> tangentialArc(endAbsolute = [60.93, 140.44], tag = $seg02)
|> angledLine(angle = tangentToEnd(seg02), length = 25.65)
|> tangentialArc(endAbsolute = [48.35, 85.53])
|> tangentialArc(endAbsolute = [35.2, 67.73], tag = $seg03)
|> angledLine(angle = tangentToEnd(seg03), length = 49.06)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
|> revolve(axis = Y, angle = 65, symmetric = true)
// Create a hole sketch with the size and location of each bolt hole
holeSketch = startSketchOn(XZ)
hole01 = circle(holeSketch, center = [0, 12.25], radius = boltSize / 2)
|> extrude(length = -100)
hole02 = circle(holeSketch, center = [0, 29.5], radius = boltSize / 2)
|> extrude(length = -100)
hole03 = circle(holeSketch, center = [0, 46.25], radius = boltSize / 2)
|> extrude(length = -100)
hole04 = circle(holeSketch, center = [0, 77], radius = boltSize / 2)
|> extrude(length = -100)
hole05 = circle(holeSketch, center = [0, 100], radius = boltSize / 2)
|> extrude(length = -100)
hole06 = circle(holeSketch, center = [0, 130], radius = boltSize / 2)
|> extrude(length = -100)
hole07 = circle(holeSketch, center = [-20, 130], radius = boltSize / 2)
|> extrude(length = -100)
hole08 = circle(holeSketch, center = [20, 130], radius = boltSize / 2)
|> extrude(length = -100)
// Cut each guiding clearance hole from the bone plate
solid001 = subtract([plateRevolve], tools = union([hole01, hole02]))
solid002 = subtract([solid001], tools = union([hole03, hole04]))
solid003 = subtract([solid002], tools = union([hole05, hole06]))
solid004 = subtract([solid003], tools = union([hole07, hole08]))

View File

@ -0,0 +1,67 @@
// Cold Plate
// A cold plate is a thermal management device used to remove heat from a device or component, typically by transferring heat to a liquid coolant that flows through the plate. It's a conductive cooling solution, commonly made of materials like aluminum or copper, with internal channels or tubes for the coolant
// Set units
@settings(defaultLengthUnit = in)
// Define parameters
tubeDiameter = 5 / 8
wallThickness = 0.080
bendRadius = 1
// Create the cold plate with indentions to secure each pass of the brazed copper tube
coldPlate = startSketchOn(YZ)
|> startProfile(at = [0, tubeDiameter * 2])
|> xLine(length = bendRadius - (tubeDiameter / 2))
|> yLine(length = -tubeDiameter)
|> tangentialArc(angle = 180, radius = tubeDiameter / 2)
|> yLine(length = tubeDiameter)
|> xLine(length = bendRadius * 2 - tubeDiameter, tag = $seg07)
|> yLine(length = -tubeDiameter, tag = $seg09)
|> tangentialArc(angle = 180, radius = tubeDiameter / 2)
|> yLine(length = tubeDiameter, tag = $seg08)
|> xLine(length = bendRadius - (tubeDiameter / 2))
|> angledLine(angle = -77, length = tubeDiameter / 3)
|> tangentialArc(angle = 77, radius = tubeDiameter, tag = $seg01)
|> angledLine(angle = tangentToEnd(seg01), length = 1)
|> yLine(endAbsolute = 0)
|> xLine(endAbsolute = 0)
|> mirror2d(axis = Y)
|> close()
|> extrude(length = 10, symmetric = true)
// Sketch the path for the copper tube to follow
copperTubePath = startSketchOn(offsetPlane(XY, offset = tubeDiameter))
|> startProfile(at = [-7.35, -bendRadius * 3])
|> xLine(length = 14.13, tag = $seg05)
|> tangentialArc(angle = 180, radius = bendRadius, tag = $seg02)
|> angledLine(angle = tangentToEnd(seg02), length = 13.02, tag = $seg06)
|> tangentialArc(angle = -180, radius = bendRadius, tag = $seg03)
|> angledLine(angle = tangentToEnd(seg03), length = segLen(seg06))
|> tangentialArc(angle = 180, radius = bendRadius, tag = $seg04)
|> angledLine(angle = tangentToEnd(seg04), length = segLen(seg05))
// Create the profile for the inner and outer diameter of the hollow copper tube
tubeWall = startSketchOn(offsetPlane(YZ, offset = -7.35))
|> circle(center = [-bendRadius * 3, tubeDiameter], radius = tubeDiameter / 2)
|> subtract2d(%, tool = circle(center = [-bendRadius * 3, tubeDiameter], radius = tubeDiameter / 2 - wallThickness))
|> sweep(path = copperTubePath)
|> appearance(color = "#b81b0a")
// Model a brazed cap to cover each tube. Constrain the caps using the walls of the plate
brazedCap = startSketchOn(YZ)
|> startProfile(at = segEnd(seg07))
|> arc(interiorAbsolute = [bendRadius * 3, tubeDiameter * 1.85], endAbsolute = segEnd(seg08))
|> yLine(endAbsolute = segStartY(seg08))
|> arc(
interiorAbsolute = [
bendRadius * 3,
segEndY(seg09) + tubeDiameter / 2
],
endAbsolute = segEnd(seg09),
)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
|> extrude(length = 10, symmetric = true)
|> patternLinear3d(instances = 4, distance = bendRadius * 2, axis = [0, -1, 0])
|> appearance(color = "#6b261e")

View File

@ -0,0 +1,120 @@
// Counterdrilled Weldment
// A metal weldment consisting of a counterdrilled plate, a centrally mounted housing tube, and four structural support fins.
// Set units
@settings(defaultLengthUnit = in)
// Define parameters
boltSpacingX = 5
boltSpacingY = 3
boltDiameter = 1 / 4
counterdrillDiameter = 7 / 16
counterdrillDepth = 3 / 16
tubeInnerDiameter = 1 + 1 / 4
tubeThickness = 0.115
tubeHeight = 2
stockThickness = .5
// Calculate the dimensions of the block using the specified bolt spacing. The size of the block can be defined by adding a multiple of the counterdrill diameter to the bolt spacing
blockLength = boltSpacingX + boltDiameter * 6
blockWidth = boltSpacingY + boltDiameter * 6
// Draw the base plate
plateSketch = startSketchOn(XY)
|> startProfile(at = [-blockLength / 2, -blockWidth / 2])
|> angledLine(angle = 0, length = blockLength, tag = $rectangleSegmentA001)
|> angledLine(angle = segAng(rectangleSegmentA001) + 90, length = blockWidth, tag = $rectangleSegmentB001)
|> angledLine(angle = segAng(rectangleSegmentA001), length = -segLen(rectangleSegmentA001), tag = $rectangleSegmentC001)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $rectangleSegmentD001)
|> close()
|> subtract2d(tool = circle(center = [0, 0], radius = tubeInnerDiameter / 2))
plateBody = extrude(plateSketch, length = stockThickness)
|> chamfer(
length = boltDiameter * 2,
tags = [
getNextAdjacentEdge(rectangleSegmentB001),
getNextAdjacentEdge(rectangleSegmentA001),
getNextAdjacentEdge(rectangleSegmentC001),
getNextAdjacentEdge(rectangleSegmentD001)
],
)
// Define hole positions
holePositions = [
[-boltSpacingX / 2, -boltSpacingY / 2],
[-boltSpacingX / 2, boltSpacingY / 2],
[boltSpacingX / 2, -boltSpacingY / 2],
[boltSpacingX / 2, boltSpacingY / 2]
]
// Function to create a counterdrilled hole
fn counterdrill(@holePosition) {
cbdrill = startSketchOn(plateBody, face = END)
|> circle(center = holePosition, radius = counterdrillDiameter / 2)
|> extrude(length = -counterdrillDepth)
cbBolt = startSketchOn(cbdrill, face = START)
|> circle(center = holePosition, radius = boltDiameter / 2, tag = $hole01)
|> extrude(length = -stockThickness + counterdrillDepth)
// Use a chamfer to create a 90-degree counterdrill edge
|> chamfer(length = (counterdrillDiameter - boltDiameter) / 2 * sqrt(2), tags = [hole01])
return { }
}
// Place a counterdrilled hole at each bolt hole position
map(holePositions, f = counterdrill)
// Drill a small pin hole in the side of the tube
pinhole = startSketchOn(YZ)
|> circle(center = [0, 2.2], radius = 0.125)
|> extrude(length = -10)
// Model the central tube and subtract the pin hole
centralTube = startSketchOn(offsetPlane(XY, offset = stockThickness))
|> circle(center = [0, 0], radius = tubeInnerDiameter / 2 + tubeThickness)
|> subtract2d(tool = circle(center = [0, 0], radius = tubeInnerDiameter / 2))
|> extrude(length = tubeHeight)
|> subtract(tools = [pinhole])
// Create a function to create a fin which spans from the central tube to the bolt hole
fn fin(@i) {
diagPlane = {
origin = [0.0, 0.0, 0.0],
xAxis = [
boltSpacingX / 2 * i,
boltSpacingY / 2,
0.0
],
yAxis = [0.0, 0.0, 1.0]
}
finSketch = startSketchOn(diagPlane)
|> startProfile(at = [
tubeInnerDiameter / 2 + tubeThickness,
stockThickness
])
|> xLine(endAbsolute = sqrt((boltSpacingX / 2) ^ 2 + (boltSpacingY / 2) ^ 2) - counterdrillDiameter)
|> yLine(length = 0.15)
|> line(endAbsolute = [
profileStartX(%) + 0.15,
stockThickness + tubeHeight * .8
])
|> xLine(length = -0.15)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
|> extrude(length = tubeThickness, symmetric = true)
// Use a circular pattern to create an identical fin on the opposite side
otherFin = patternCircular3d(
finSketch,
instances = 2,
axis = [0, 0, 1],
center = [0, 0, 0],
arcDegrees = 360,
rotateDuplicates = true,
)
return { }
}
// Place a pair of support fins along each diagonal axis of the bolt pattern
fin(1)
fin(-1)

View File

@ -0,0 +1,50 @@
// Plate with countersunk holes
// A small mounting plate with a countersunk hole at each end
// Set units
@settings(defaultLengthUnit = in)
// Define parameters
boltSpacing = 5
boltDiameter = 1 / 4
centerHoleDiameter = 1 + 3 / 4
plateThickness = 0.375
// Check that the plate is thick enough to countersink a hole
// assertGreaterThan(plateThickness, boltDiameter, "This plate is not thick enough for the necessary countersink dimensions")
// A bit of math to calculate the tangent line between the two diameters
r1 = centerHoleDiameter / 2 * 1.5 + .35
r2 = boltDiameter * 2 + .25
d = boltSpacing / 2
tangentAngle = asin((r1 - r2) / d)
tangentLength = (r1 - r2) / tan(tangentAngle)
plateBody = startSketchOn(XY)
// Use polar coordinates to start the sketch at the tangent point of the larger radius
|> startProfile(at = polar(angle = 90 - tangentAngle, length = r1))
|> angledLine(angle = -tangentAngle, length = tangentLength)
|> tangentialArc(radius = r2, angle = (tangentAngle - 90) * 2)
|> angledLine(angle = tangentAngle, length = -tangentLength)
|> tangentialArc(radius = r1, angle = -tangentAngle * 2)
|> angledLine(angle = -tangentAngle, length = -tangentLength)
|> tangentialArc(radius = r2, angle = (tangentAngle - 90) * 2)
|> angledLine(angle = tangentAngle, length = tangentLength)
|> tangentialArc(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
|> subtract2d(tool = circle(center = [0, 0], radius = centerHoleDiameter / 2 * 1.5))
|> extrude(%, length = plateThickness)
// Function to create a countersunk hole
fn countersink(@holePosition) {
startSketchOn(plateBody, face = END)
|> circle(center = [holePosition, 0], radius = boltDiameter / 2, tag = $hole01)
|> extrude(length = -plateThickness)
// Use a chamfer to create a 90-degree countersink
|> chamfer(length = boltDiameter, tags = [hole01])
return { }
}
// Place a countersunk hole at each bolt hole position
countersink(-boltSpacing / 2)
countersink(boltSpacing / 2)

View File

@ -0,0 +1,153 @@
// Fan Housing
// The plastic housing that contains the fan and the motor
// Set units
@settings(defaultLengthUnit = mm)
// Import parameters
import * from "parameters.kcl"
// Model the housing which holds the motor, the fan, and the mounting provisions
// Bottom mounting face
bottomFaceSketch = startSketchOn(YZ)
|> startProfile(at = [-fanSize / 2, -fanSize / 2])
|> angledLine(angle = 0, length = fanSize, tag = $rectangleSegmentA001)
|> angledLine(angle = segAng(rectangleSegmentA001) + 90, length = fanSize, tag = $rectangleSegmentB001)
|> angledLine(angle = segAng(rectangleSegmentA001), length = -segLen(rectangleSegmentA001), tag = $rectangleSegmentC001)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $rectangleSegmentD001)
|> close()
|> subtract2d(tool = circle(center = [0, 0], radius = 4))
|> subtract2d(tool = circle(
center = [
mountingHoleSpacing / 2,
mountingHoleSpacing / 2
],
radius = mountingHoleSize / 2,
))
|> subtract2d(tool = circle(
center = [
-mountingHoleSpacing / 2,
mountingHoleSpacing / 2
],
radius = mountingHoleSize / 2,
))
|> subtract2d(tool = circle(
center = [
mountingHoleSpacing / 2,
-mountingHoleSpacing / 2
],
radius = mountingHoleSize / 2,
))
|> subtract2d(tool = circle(
center = [
-mountingHoleSpacing / 2,
-mountingHoleSpacing / 2
],
radius = mountingHoleSize / 2,
))
|> extrude(length = 4)
// Add large openings to the bottom face to allow airflow through the fan
airflowPattern = startSketchOn(bottomFaceSketch, face = END)
|> startProfile(at = [fanSize * 7 / 25, -fanSize * 9 / 25])
|> angledLine(angle = 140, length = fanSize * 12 / 25, tag = $seg01)
|> tangentialArc(radius = fanSize * 1 / 50, angle = 90)
|> angledLine(angle = -130, length = fanSize * 8 / 25)
|> tangentialArc(radius = fanSize * 1 / 50, angle = 90)
|> angledLine(angle = segAng(seg01) + 180, length = fanSize * 2 / 25)
|> tangentialArc(radius = fanSize * 8 / 25, angle = 40)
|> xLine(length = fanSize * 3 / 25)
|> tangentialArc(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
|> patternCircular2d(
instances = 4,
center = [0, 0],
arcDegrees = 360,
rotateDuplicates = true,
)
|> extrude(length = -4)
// Create the middle segment of the fan housing body
housingMiddleLength = fanSize / 3
housingMiddleRadius = fanSize / 3 - 1
bodyMiddle = startSketchOn(bottomFaceSketch, face = END)
|> startProfile(at = [
housingMiddleLength / 2,
-housingMiddleLength / 2 - housingMiddleRadius
])
|> tangentialArc(radius = housingMiddleRadius, angle = 90)
|> yLine(length = housingMiddleLength)
|> tangentialArc(radius = housingMiddleRadius, angle = 90)
|> xLine(length = -housingMiddleLength)
|> tangentialArc(radius = housingMiddleRadius, angle = 90)
|> yLine(length = -housingMiddleLength)
|> tangentialArc(radius = housingMiddleRadius, angle = 90)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> extrude(length = fanHeight - 4 - 4)
// Cut a hole in the body to accommodate the fan
bodyFanHole = startSketchOn(bodyMiddle, face = END)
|> circle(center = [0, 0], radius = fanSize * 23 / 50)
|> extrude(length = -(fanHeight - 4 - 4))
// Top mounting face. Cut a hole in the face to accommodate the fan
topFaceSketch = startSketchOn(bodyMiddle, face = END)
topHoles = startProfile(topFaceSketch, at = [-fanSize / 2, -fanSize / 2])
|> angledLine(angle = 0, length = fanSize, tag = $rectangleSegmentA002)
|> angledLine(angle = segAng(rectangleSegmentA002) + 90, length = fanSize, tag = $rectangleSegmentB002)
|> angledLine(angle = segAng(rectangleSegmentA002), length = -segLen(rectangleSegmentA002), tag = $rectangleSegmentC002)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $rectangleSegmentD002)
|> close()
|> subtract2d(tool = circle(center = [0, 0], radius = fanSize * 23 / 50))
|> subtract2d(tool = circle(
center = [
mountingHoleSpacing / 2,
mountingHoleSpacing / 2
],
radius = mountingHoleSize / 2,
))
|> subtract2d(tool = circle(
center = [
-mountingHoleSpacing / 2,
mountingHoleSpacing / 2
],
radius = mountingHoleSize / 2,
))
|> subtract2d(tool = circle(
center = [
mountingHoleSpacing / 2,
-mountingHoleSpacing / 2
],
radius = mountingHoleSize / 2,
))
|> subtract2d(tool = circle(
center = [
-mountingHoleSpacing / 2,
-mountingHoleSpacing / 2
],
radius = mountingHoleSize / 2,
))
|> extrude(length = 4)
// Create a housing for the electric motor to sit
motorHousing = startSketchOn(bottomFaceSketch, face = END)
|> circle(center = [0, 0], radius = 11.2)
|> extrude(length = 16)
startSketchOn(motorHousing, face = END)
|> circle(center = [0, 0], radius = 10)
|> extrude(length = -16)
|> appearance(color = "#a55e2c")
|> fillet(
radius = abs(fanSize - mountingHoleSpacing) / 2,
tags = [
getNextAdjacentEdge(rectangleSegmentA001),
getNextAdjacentEdge(rectangleSegmentB001),
getNextAdjacentEdge(rectangleSegmentC001),
getNextAdjacentEdge(rectangleSegmentD001),
getNextAdjacentEdge(rectangleSegmentA002),
getNextAdjacentEdge(rectangleSegmentB002),
getNextAdjacentEdge(rectangleSegmentC002),
getNextAdjacentEdge(rectangleSegmentD002)
],
)

View File

@ -0,0 +1,71 @@
// Fan
// Spinning axial fan that moves airflow
// Set units
@settings(defaultLengthUnit = mm)
// Import parameters
import * from "parameters.kcl"
// Model the center of the fan
fanCenter = startSketchOn(YZ)
|> circle(center = [0, 0], radius = fanHeight / 2, tag = $centerBend)
|> extrude(%, length = fanHeight)
|> fillet(radius = 1.5, tags = [getOppositeEdge(centerBend)])
// Create a function for a lofted fan blade cross section that rotates about the center hub of the fan
fn fanBlade(offsetHeight, startAngle) {
fanBlade = startSketchOn(offsetPlane(YZ, offset = offsetHeight))
|> startProfile(at = [
15 * cos(startAngle),
15 * sin(startAngle)
])
|> arc(angleStart = startAngle, angleEnd = startAngle + 14, radius = 15)
|> arc(
endAbsolute = [
fanSize * 22 / 50 * cos(startAngle - 20),
fanSize * 22 / 50 * sin(startAngle - 20)
],
interiorAbsolute = [
fanSize * 11 / 50 * cos(startAngle + 3),
fanSize * 11 / 50 * sin(startAngle + 3)
],
)
|> arc(
endAbsolute = [
fanSize * 22 / 50 * cos(startAngle - 24),
fanSize * 22 / 50 * sin(startAngle - 24)
],
interiorAbsolute = [
fanSize * 22 / 50 * cos(startAngle - 22),
fanSize * 22 / 50 * sin(startAngle - 22)
],
)
|> arc(
endAbsolute = [profileStartX(%), profileStartY(%)],
interiorAbsolute = [
fanSize * 11 / 50 * cos(startAngle - 5),
fanSize * 11 / 50 * sin(startAngle - 5)
],
)
|> close()
return fanBlade
}
// Loft the fan blade cross sections into a single blade, then pattern them about the fan center
crossSections = [
fanBlade(offsetHeight = 4.5, startAngle = 50),
fanBlade(offsetHeight = (fanHeight - 2 - 4) / 2, startAngle = 30),
fanBlade(offsetHeight = fanHeight - 2, startAngle = 0)
]
bladeLoft = loft(crossSections)
|> patternCircular3d(
instances = 9,
axis = [1, 0, 0],
center = [0, 0, 0],
arcDegrees = 360,
rotateDuplicates = true,
)
[fanCenter, bladeLoft]
|> appearance(color = "#110803")

View File

@ -0,0 +1,171 @@
// Heat Sink
// Conductive metal device made from brazed tubes and fins
// Set units
@settings(defaultLengthUnit = mm)
// Import parameters
import * from "parameters.kcl"
// Draw the sweep path for the outermost tubes
endTubePath = startSketchOn(offsetPlane(YZ, offset = -20))
|> startProfile(at = [fanSize / 4, fanSize + 38])
|> yLine(endAbsolute = bendRadius + 10, tag = $seg01)
|> tangentialArc(radius = bendRadius, angle = -90)
|> xLine(endAbsolute = 0, tag = $seg02)
|> xLine(length = -segLen(seg02))
|> tangentialArc(radius = bendRadius, angle = -90)
|> yLine(length = segLen(seg01))
// Sweep and translate the outermost tube on each end
endTube = startSketchOn(offsetPlane(XY, offset = fanSize + 38))
|> circle(center = [-20, fanSize / 4], radius = 3)
|> subtract2d(tool = circle(center = [-20, fanSize / 4], radius = 2.5))
|> sweep(path = endTubePath)
|> patternCircular3d(
%,
instances = 2,
axis = [0, 0, 1],
center = [0, 0, 0],
arcDegrees = 360,
rotateDuplicates = false,
)
// Draw the sweep path for the 4 interior tubes
centerTubePath = startSketchOn(offsetPlane(YZ, offset = -4))
|> startProfile(at = [fanSize / 2.67, fanSize + 38])
|> yLine(endAbsolute = bendRadius + 15 + 10)
|> tangentialArc(radius = bendRadius, angle = -45)
|> angledLine(angle = -135, lengthY = 15)
|> tangentialArc(radius = bendRadius, angle = -45)
|> xLine(endAbsolute = 0, tag = $seg03)
|> xLine(length = -segLen(seg03))
|> tangentialArc(radius = bendRadius, angle = -155)
|> tangentialArc(radius = bendRadius, angle = 65)
|> yLine(endAbsolute = fanSize + 38)
// Draw the profile and sweep the 4 interior tubes
centerTube = startSketchOn(offsetPlane(XY, offset = fanSize + 38))
|> circle(center = [-4, fanSize / 2.67], radius = 3)
|> subtract2d(tool = circle(center = [-4, fanSize / 2.67], radius = 2.5))
|> sweep(path = centerTubePath)
|> patternCircular3d(
%,
instances = 2,
axis = [0, 0, 1],
center = [-4 * 2, 0, 0],
arcDegrees = 360,
rotateDuplicates = true,
)
|> patternLinear3d(
%,
instances = 2,
distance = 4 * 4,
axis = [1, 0, 0],
)
// Draw a heat fin with built-in clips to secure the mounting wire. Pattern the fin upwards by the height of the fan
heatFins = startSketchOn(offsetPlane(XY, offset = 45))
|> startProfile(at = [0, -fanSize / 2])
|> xLine(length = 9)
|> angledLine(angle = -60, length = 2.5, tag = $seg04)
|> xLine(length = 0.75)
|> arc(interiorAbsolute = [lastSegX(%) + 1, lastSegY(%) + 1.2], endAbsolute = [lastSegX(%) + 2, lastSegY(%)])
|> xLine(length = 0.75)
|> angledLine(angle = 60, length = segLen(seg04))
|> xLine(endAbsolute = heatSinkDepth / 2 - 3)
|> tangentialArc(angle = 90, radius = 3)
|> yLine(endAbsolute = 0)
|> mirror2d(axis = X)
|> mirror2d(axis = Y)
|> close()
|> extrude(length = 1)
|> patternLinear3d(
%,
instances = 31,
distance = (fanSize - 10) / 30,
axis = [0, 0, 1],
)
// Create the mounting base for the CPU cooler. The base should consist of two pieces that secure around each of the tubes at the bottom
coolerBase = startSketchOn(-XZ)
baseLower = startProfile(coolerBase, at = [0, 10])
|> xLine(length = -0.9)
|> arc(angleStart = 0, angleEnd = -180, radius = 3.1)
|> xLine(length = -1.8)
|> arc(angleStart = 0, angleEnd = -180, radius = 3)
|> xLine(length = -1.8)
|> arc(angleStart = 0, angleEnd = -180, radius = 3)
|> xLine(length = -1.8)
|> xLine(length = -2)
|> yLine(length = -10)
|> xLine(endAbsolute = 0)
|> mirror2d(axis = Y)
|> extrude(length = 2 * segLen(seg02), symmetric = true)
baseUpper = startProfile(coolerBase, at = [0, 10])
|> xLine(length = -0.9)
|> arc(angleStart = 0, angleEnd = 180, radius = 3.1)
|> xLine(length = -1.8)
|> arc(angleStart = 0, angleEnd = 180, radius = 3)
|> xLine(length = -1.8)
|> arc(angleStart = 0, angleEnd = 180, radius = 3)
|> xLine(length = -1.8)
|> xLine(length = -1)
|> yLine(length = 4)
|> tangentialArc(angle = -90, radius = 2)
|> xLine(endAbsolute = 0)
|> mirror2d(axis = Y)
|> extrude(length = 2 * segLen(seg02) * 3 / 4, symmetric = true)
// Create a flexible mounting bracket to secure the heat sink to the motherboard once adhered
mountingBracket = startSketchOn(XZ)
|> startProfile(at = [-10, 16])
|> xLine(length = -20)
|> tangentialArc(angle = 20, radius = bendRadius)
|> angledLine(angle = -160, length = 14, tag = $seg09)
|> tangentialArc(angle = -30, radius = bendRadius + sheetThickness)
|> angledLine(angle = 170, length = 21.5, tag = $seg04Q)
|> angledLine(angle = 170 - 90, length = sheetThickness, tag = $seg08)
|> angledLine(angle = segAng(seg04Q) + 180, length = segLen(seg04Q), tag = $seg05E)
|> tangentialArc(angle = 30, radius = bendRadius)
|> angledLine(angle = segAng(seg09) + 180, length = segLen(seg09))
|> tangentialArc(angle = -20, radius = bendRadius + sheetThickness)
|> xLine(endAbsolute = profileStartX(%))
|> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $seg07)
|> close()
|> extrude(
length = 16,
symmetric = true,
tagEnd = $capEnd001,
tagStart = $capStart001,
)
|> fillet(
radius = 2,
tags = [
getCommonEdge(faces = [seg07, capEnd001]),
getCommonEdge(faces = [seg08, capEnd001]),
getCommonEdge(faces = [seg08, capStart001]),
getCommonEdge(faces = [seg07, capStart001])
],
)
// Create a clearance hole in the bracket for an M3 screw and countersink the hole
thruHole = startSketchOn(mountingBracket, face = seg05E)
|> circle(center = [70, 0], radius = 3.4 / 2, tag = $seg06E)
|> extrude(length = -sheetThickness)
|> chamfer(
length = sheetThickness * 0.75,
tags = [
getCommonEdge(faces = [seg05E, seg06E])
],
)
// Duplicate the bracket to the other side of the heat sink base
|> patternCircular3d(
instances = 2,
axis = [0, 0, 1],
center = [0, 0, 0],
arcDegrees = 360,
rotateDuplicates = true,
)

View File

@ -0,0 +1,51 @@
// CPU Cooler
// A CPU cooler is a device designed to dissipate heat generated by the CPU of a computer. They consist of a brazed heat sink made from aluminum or copper alloys, and one or two axial fans to move airflow across the heat sink.
// Set units
@settings(defaultLengthUnit = mm)
// Import all parts and parameters into assembly file
import * from "parameters.kcl"
import "fan-housing.kcl" as fanHousing
import "motor.kcl" as motor
import "fan.kcl" as fan
import "heat-sink.kcl" as heatSink
import "mounting-wire.kcl" as mountingWire
import "removable-sticker.kcl" as removableSticker
// Produce the model for each imported part
heatSink
fn translatePart(part) {
part
|> translate(x = heatSinkDepth / 2, z = 40 + fanSize / 2)
|> patternLinear3d(
%,
instances = 2,
distance = heatSinkDepth + fanHeight,
axis = [-1, 0, 0],
)
return { }
}
translatePart(part = fanHousing)
translatePart(part = motor)
translatePart(part = fan)
mountingWire
|> patternCircular3d(
%,
instances = 2,
axis = [0, 1, 0],
center = [0, 0, 40 + fanSize / 2],
arcDegrees = 360,
rotateDuplicates = true,
)
|> patternCircular3d(
%,
instances = 2,
axis = [0, 0, 1],
center = [0, 0, 0],
arcDegrees = 360,
rotateDuplicates = true,
)
removableSticker

View File

@ -0,0 +1,21 @@
// Motor
// A small electric motor to power the fan
// Set Units
@settings(defaultLengthUnit = mm)
// Import Parameters
import * from "parameters.kcl"
// Model the motor body and stem
startPlane = offsetPlane(YZ, offset = 4)
motorBody = startSketchOn(startPlane)
|> circle(center = [0, 0], radius = 10, tag = $seg04)
|> extrude(length = 17)
|> fillet(radius = 2, tags = [getOppositeEdge(seg04), seg04])
|> appearance(color = "#021b55")
motorStem = startSketchOn(offsetPlane(YZ, offset = 21))
|> circle(center = [0, 0], radius = 1)
|> extrude(length = 3.8)
|> appearance(color = "#cbcccd")
[motorBody, motorStem]

View File

@ -0,0 +1,79 @@
// Mounting Wire
// The flexible metal wire used to clip the fans onto the heat sink
// Set units
@settings(defaultLengthUnit = mm)
// Import parameters
import * from "parameters.kcl"
// Draw the XZ component of the mounting wire path
upperArm = startSketchOn(offsetPlane(XZ, offset = fanSize / 2 + 2))
|> startProfile(at = [-12, 40 + fanSize / 2])
|> yLine(length = 7)
|> tangentialArc(radius = 2, angle = 90)
|> xLine(length = -9)
|> tangentialArc(radius = 2, angle = -90)
|> yLine(length = 14)
|> tangentialArc(radius = 2, angle = 90)
|> xLine(length = -9)
|> tangentialArc(radius = 2, angle = -80)
|> angledLine(angle = 100, endAbsoluteY = 40 + fanSize / 2 + mountingHoleSpacing / 2 - 1.5)
|> tangentialArc(radius = 2, angle = 80, tag = $seg07)
// Draw the XZ component of the mounting wire path
lowerArm = startSketchOn(offsetPlane(XZ, offset = fanSize / 2 + 2))
|> startProfile(at = [-12, 40 + fanSize / 2])
|> yLine(length = -7)
|> tangentialArc(radius = 2, angle = -90)
|> xLine(length = -9)
|> tangentialArc(radius = 2, angle = 90)
|> yLine(length = -14)
|> tangentialArc(radius = 2, angle = -90)
|> xLine(length = -9)
|> tangentialArc(radius = 2, angle = 80)
|> angledLine(angle = -100, endAbsoluteY = 40 + fanSize / 2 - (mountingHoleSpacing / 2) + 1.5)
|> tangentialArc(radius = 2, angle = -80, tag = $seg08)
// Create the profile of the mounting wire and sweep along the XZ path
wireProfile = startSketchOn(offsetPlane(XY, offset = 40 + fanSize / 2))
sweepUpperArm = circle(wireProfile, center = [-12, -fanSize / 2 - 2], radius = 1)
|> sweep(%, path = upperArm)
sweepLowerArm = circle(wireProfile, center = [-12, -fanSize / 2 - 2], radius = 1)
|> sweep(%, path = lowerArm)
// Draw the XY components of the mounting wire path
upperHook = startSketchOn(offsetPlane(XY, offset = segEndY(seg07)))
|> startProfile(at = [segEndX(seg07), -fanSize / 2 - 2])
|> xLine(endAbsolute = -heatSinkDepth / 2 - fanHeight)
|> tangentialArc(radius = 2, angle = -90)
|> yLine(endAbsolute = -mountingHoleSpacing / 2 - 2)
|> tangentialArc(radius = 2, angle = -90)
|> xLine(length = fanHeight / 3)
// Draw the XY components of the mounting wire path
lowerHook = startSketchOn(offsetPlane(XY, offset = segEndY(seg08)))
|> startProfile(at = [segEndX(seg07), -fanSize / 2 - 2])
|> xLine(endAbsolute = -heatSinkDepth / 2 - fanHeight)
|> tangentialArc(radius = 2, angle = -90)
|> yLine(endAbsolute = -mountingHoleSpacing / 2 - 2)
|> tangentialArc(radius = 2, angle = -90)
|> xLine(length = fanHeight / 3)
// Sweep the wire profile around the hook-shaped segments of the mounting wire
hookProfile = startSketchOn(offsetPlane(YZ, offset = segEndX(seg07)))
sweepUpperHook = circle(hookProfile, center = [-fanSize / 2 - 2, segEndY(seg07)], radius = 1)
|> sweep(%, path = upperHook)
sweepLowerHook = circle(hookProfile, center = [-fanSize / 2 - 2, segEndY(seg08)], radius = 1)
|> sweep(%, path = lowerHook)
// Union each piece of the wire into a single continuous sweep
[
sweepLowerArm,
sweepLowerHook,
sweepUpperArm,
sweepUpperHook
]
|> appearance(color = "#0d0d0d")

View File

@ -0,0 +1,13 @@
// Global parameters for the CPU cooler
// Set units
@settings(defaultLengthUnit = mm)
// Define Parameters
export fanSize = 120
export fanHeight = 25
export mountingHoleSpacing = 105
export mountingHoleSize = 4.5
export bendRadius = 15
export sheetThickness = 2.125
export heatSinkDepth = 55

View File

@ -0,0 +1,25 @@
// Removable Sticker
// Protective sticker to be removed before adhering the heat sink to the CPU
// Set units
@settings(defaultLengthUnit = mm)
// Create a simple body to represent the removable warning sticker. Brightly color the sticker so that the user will not forget to remove it before installing the device
removableSticker = startSketchOn(-XY)
|> startProfile(at = [-12, -12])
|> angledLine(angle = 0, length = 24, tag = $rectangleSegmentA001)
|> angledLine(angle = segAng(rectangleSegmentA001) + 90, length = 24, tag = $rectangleSegmentB001)
|> angledLine(angle = segAng(rectangleSegmentA001), length = -segLen(rectangleSegmentA001), tag = $rectangleSegmentC001)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $rectangleSegmentD001)
|> close()
|> extrude(length = .3)
|> appearance(color = "#021b55")
|> chamfer(
length = 3,
tags = [
getNextAdjacentEdge(rectangleSegmentA001),
getNextAdjacentEdge(rectangleSegmentB001),
getNextAdjacentEdge(rectangleSegmentC001),
getNextAdjacentEdge(rectangleSegmentD001)
],
)

View File

@ -1,112 +0,0 @@
// 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
@settings(defaultLengthUnit = in, kclVersion = 1.0)
// Define parameters
nTeeth = 21
module = 0.5
pitchDiameter = module * nTeeth
pressureAngle = 20
addendum = module
deddendum = 1.25 * module
baseDiameter = pitchDiameter * cos(pressureAngle)
tipDiameter = pitchDiameter + 2 * module
gearHeight = 3
// Interpolate points along the involute curve
cmo = 101
rs = map(
[0..cmo],
f = fn(@i) {
return baseDiameter / 2 + i / cmo * (tipDiameter - baseDiameter) / 2
},
)
// Calculate operating pressure angle
angles = map(
rs,
f = fn(@r) {
return units::toDegrees(acos(baseDiameter / 2 / r))
},
)
// Calculate the involute function
invas = map(
angles,
f = fn(@a) {
return tan(a) - units::toRadians(a)
},
)
// Map the involute curve
xs = map(
[0..cmo],
f = fn(@i) {
return rs[i] * cos(invas[i]: number(rad))
},
)
ys = map(
[0..cmo],
f = fn(@i) {
return rs[i] * sin(invas[i]: number(rad))
},
)
// Extrude the gear body
body = startSketchOn(XY)
|> circle(center = [0, 0], radius = baseDiameter / 2)
|> extrude(length = gearHeight)
toothAngle = 360 / nTeeth / 1.5
// Plot the involute curve
fn leftInvolute(@i, accum) {
j = 100 - i // iterate backwards
return line(accum, endAbsolute = [xs[j], ys[j]])
}
fn rightInvolute(@i, accum) {
x = rs[i] * cos(-toothAngle + units::toDegrees(atan(ys[i] / xs[i])))
y = -rs[i] * sin(-toothAngle + units::toDegrees(atan(ys[i] / xs[i])))
return line(accum, endAbsolute = [x, y])
}
// Draw gear teeth
start = startSketchOn(XY)
|> startProfile(at = [xs[101], ys[101]])
teeth = reduce([0..100], initial = start, f = leftInvolute)
|> arc(angleStart = 0, angleEnd = toothAngle, radius = baseDiameter / 2)
|> reduce([1..101], initial = %, f = rightInvolute)
|> close()
|> extrude(length = gearHeight)
|> patternCircular3d(
axis = [0, 0, 1],
center = [0, 0, 0],
instances = nTeeth,
arcDegrees = 360,
rotateDuplicates = true,
)
// Define the constants of the keyway and the bore hole
keywayWidth = 0.250
keywayDepth = keywayWidth / 2
holeDiam = 2
holeRadius = 1
startAngle = asin(keywayWidth / 2 / holeRadius)
// Sketch the keyway and center hole and extrude
keyWay = startSketchOn(body, face = END)
|> startProfile(at = [
holeRadius * cos(startAngle),
holeRadius * sin(startAngle)
])
|> xLine(length = keywayDepth)
|> yLine(length = -keywayWidth)
|> xLine(length = -keywayDepth)
|> arc(angleStart = -1 * units::toDegrees(startAngle) + 360, angleEnd = 180, radius = holeRadius)
|> arc(angleStart = 180, angleEnd = units::toDegrees(startAngle), radius = holeRadius)
|> close()
|> extrude(length = -gearHeight)

View File

@ -0,0 +1,118 @@
// Claw Hammer
// Often used in construction, a claw hammer is a levered metal hand tool that is used to strike and extract nails
// Set units
@settings(defaultLengthUnit = in)
// Sketch the side profile of the hammer head
headSideProfile = startSketchOn(XZ)
|> startProfile(at = [0.33, 11.26])
|> yLine(length = 0.1)
|> tangentialArc(endAbsolute = [0.95, 11.92])
|> tangentialArc(endAbsolute = [2.72, 11.26], tag = $seg01)
|> angledLine(angle = tangentToEnd(seg01) + 90, length = .2)
|> angledLine(angle = tangentToEnd(seg01) - 10, length = -0.5)
|> tangentialArc(endAbsolute = [-0.91, 12.78], tag = $seg03)
|> tangentialArc(endAbsolute = [-1.67, 12.85])
|> xLine(length = -.25)
|> tangentialArc(angle = 90, radius = .05)
|> yLine(length = -1.125, tag = $seg02)
|> tangentialArc(angle = 90, radius = .05)
|> xLine(length = .25, tag = $seg04)
|> angledLine(angle = 23, length = 0.1)
|> tangentialArc(endAbsolute = [-0.33, profileStartY(%)])
|> xLine(endAbsolute = profileStartX(%))
|> close()
|> extrude(length = 3, symmetric = true)
// Sketch the top profile of the hammer head
headTopProfile = startSketchOn(offsetPlane(XY, offset = 13))
leftSideCut = startProfile(headTopProfile, at = [-4, -1.6])
|> line(endAbsolute = [segEndX(seg02), -segLen(seg02) / 2])
|> arc(
%,
angleStart = 180,
angleEnd = 270,
radius = .05,
)
|> xLine(endAbsolute = segEndX(seg04))
|> arc(interiorAbsolute = [segEndX(seg03) - .1, lastSegY(%) + .03], endAbsolute = [segEndX(seg03), lastSegY(%)])
|> tangentialArc(endAbsolute = [3.39, -1.15])
|> yLine(endAbsolute = profileStartY(%))
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
|> extrude(length = -14)
rearCut = startProfile(headTopProfile, at = [3.39, -0.56])
|> angledLine(angle = 177, length = 0.1)
|> tangentialArc(endAbsolute = [1.86, -0.37])
|> tangentialArc(endAbsolute = [lastSegX(%), -lastSegY(%)])
|> tangentialArc(endAbsolute = [profileStartX(%), -profileStartY(%)])
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
|> extrude(length = -14)
rightSideCut = startProfile(headTopProfile, at = [-4, 1.6])
|> line(endAbsolute = [segEndX(seg02), segLen(seg02) / 2])
|> arc(
%,
angleStart = -180,
angleEnd = -270,
radius = .05,
)
|> xLine(endAbsolute = segEndX(seg04))
|> arc(interiorAbsolute = [segEndX(seg03) - .1, lastSegY(%) - .03], endAbsolute = [segEndX(seg03), lastSegY(%)])
|> tangentialArc(endAbsolute = [3.39, 1.15])
|> yLine(endAbsolute = profileStartY(%))
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
|> extrude(length = -14)
// Subtract the top profiles from the side profile to create a CSG hammer shape
firstProfiles = subtract(
[headSideProfile],
tools = [
union([
leftSideCut,
union([rearCut, rightSideCut])
])
],
)
// Extrude a polygon through the center of the hammer head to create the mounting hole for the handle
handleHole = startSketchOn(XY)
|> polygon(
%,
radius = .28,
numSides = 10,
center = [0, 0],
)
|> extrude(length = 14)
// Add an additional fillet feature to support the handle, and union it to the rest of the head
baseSupport = startSketchOn(offsetPlane(XY, offset = 11.5))
|> circle(center = [0, 0], radius = .45, tag = $seg05)
|> extrude(length = 1, tagStart = $capStart001)
|> fillet(
radius = .05,
tags = [
getCommonEdge(faces = [seg05, capStart001])
],
)
// Union all pieces into a single solid, then cut the handle hole
hammerHead = union([firstProfiles, baseSupport])
|> subtract(tools = [handleHole])
// Draw a profile for the handle, then revolve around the center axis
handleSketch = startSketchOn(XZ)
|> startProfile(at = [0.01, 0])
|> xLine(length = 1.125 / 2)
|> tangentialArc(angle = 90, radius = 0.05)
|> tangentialArc(endAbsolute = [0.38, 12.8 / 1.612])
|> tangentialArc(endAbsolute = [0.28, 12.8])
|> xLine(endAbsolute = profileStartX(%))
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
handle = revolve(handleSketch, angle = 360, axis = Y)
|> appearance(color = "#f14f04")

View File

@ -0,0 +1,99 @@
// Helical Gear
// A helical gear is a type of cylindrical gear where the teeth are slanted at an angle relative to the axis of rotation. This greatly reduces noise and wear when transmitting torque across meshed spinning gears
// Set units
@settings(defaultLengthUnit = mm)
// Define a function to create a helical gear
fn helicalGear(nTeeth, module, pressureAngle, helixAngle, gearHeight) {
// Calculate gear parameters
pitchDiameter = module * nTeeth
addendum = module
deddendum = 1.25 * module
baseDiameter = pitchDiameter * cos(pressureAngle)
tipDiameter = pitchDiameter + 2 * module
// Define the constants of the keyway and the bore hole
keywayWidth = 2
keywayDepth = keywayWidth / 2
holeDiam = 7
holeRadius = holeDiam / 2
startAngle = asin(keywayWidth / 2 / holeRadius)
// Sketch the keyway and center hole
holeWithKeyway = startSketchOn(XY)
|> startProfile(at = [
holeRadius * cos(startAngle),
holeRadius * sin(startAngle)
])
|> xLine(length = keywayDepth)
|> yLine(length = -keywayWidth)
|> xLine(length = -keywayDepth)
|> arc(angleStart = -1 * startAngle + 360, angleEnd = 180, radius = holeRadius)
|> arc(angleStart = 180, angleEnd = startAngle, radius = holeRadius)
|> close()
// Define a function to create a rotated gear sketch on an offset plane
fn helicalGearSketch(offsetHeight) {
// Calculate the amount to rotate each planar sketch of the gear given the gear helix angle and total gear height
helixCalc = acos(offsetHeight * tan(helixAngle) / (tipDiameter / 2))
// Using the gear parameters, sketch an involute tooth spanning from the base diameter to the tip diameter
helicalGearSketch = startSketchOn(offsetPlane(XY, offset = offsetHeight))
|> startProfile(at = polar(angle = helixCalc, length = baseDiameter / 2))
|> involuteCircular(
startRadius = baseDiameter / 2,
endRadius = tipDiameter / 2,
angle = helixCalc,
tag = $seg01,
)
|> line(endAbsolute = polar(angle = 160 / nTeeth + helixCalc, length = tipDiameter / 2))
|> involuteCircular(
startRadius = baseDiameter / 2,
endRadius = tipDiameter / 2,
angle = -(4 * atan(segEndY(seg01) / segEndX(seg01)) - (3 * helixCalc)),
reverse = true,
)
// Position the end line of the sketch at the start of the next tooth
|> line(endAbsolute = polar(angle = 360 / nTeeth + helixCalc, length = baseDiameter / 2))
// Pattern the sketch about the center by the specified number of teeth, then close the sketch
|> patternCircular2d(
%,
instances = nTeeth,
center = [0, 0],
arcDegrees = 360,
rotateDuplicates = true,
)
|> close()
|> subtract2d(tool = holeWithKeyway)
return helicalGearSketch
}
// Draw a gear sketch on the base plane
gearSketch001 = helicalGearSketch(offsetHeight = 0)
// Draw a rotated gear sketch on a middle interstitial plane
gearSketch002 = helicalGearSketch(offsetHeight = gearHeight / 2)
// Draw a rotated gear sketch at the gear height offset plane
gearSketch003 = helicalGearSketch(offsetHeight = gearHeight)
// Loft each rotated gear sketch together to form a helical gear
helicalGear = loft([
gearSketch001,
gearSketch002,
gearSketch003
])
return helicalGear
}
helicalGear(
nTeeth = 21,
module = 2,
pressureAngle = 20,
helixAngle = 35,
gearHeight = 7,
)

View File

@ -0,0 +1,197 @@
// Helical Planetary Gearset
// A helical planetary gearset is a type of planetary gear system where the teeth of the sun gear, planet gears, and/or ring gear are helical rather than straight. This design allows for smoother, quieter operation, greater load-carrying capacity, and more flexible shaft alignment.
// Set units
@settings(defaultLengthUnit = mm)
// Define a function to create a helical gear
fn helicalGear(nTeeth, module, pressureAngle, helixAngle, gearHeight) {
// Calculate gear parameters
pitchDiameter = module * nTeeth
addendum = module
deddendum = 1.25 * module
baseDiameter = pitchDiameter * cos(pressureAngle)
tipDiameter = pitchDiameter + 2 * module
// Define the constants of the keyway and the bore hole
keywayWidth = 1
keywayDepth = keywayWidth / 2
holeDiam = 7
holeRadius = holeDiam / 2
startAngle = asin(keywayWidth / 2 / holeRadius)
// Sketch the keyway and center hole
holeWithKeyway = startSketchOn(XY)
|> startProfile(at = [
holeRadius * cos(startAngle),
holeRadius * sin(startAngle)
])
|> xLine(length = keywayDepth)
|> yLine(length = -keywayWidth)
|> xLine(length = -keywayDepth)
|> arc(angleStart = -1 * startAngle + 360, angleEnd = 180, radius = holeRadius)
|> arc(angleStart = 180, angleEnd = startAngle, radius = holeRadius)
|> close()
// Define a function to create a rotated gear sketch on an offset plane
fn helicalGearSketch(offsetHeight) {
// Calculate the amount to rotate each planar sketch of the gear given the gear helix angle and total gear height
helixCalc = acos(offsetHeight * tan(helixAngle) / (tipDiameter / 2))
// Using the gear parameters, sketch an involute tooth spanning from the base diameter to the tip diameter
helicalGearSketch = startSketchOn(offsetPlane(XY, offset = offsetHeight))
|> startProfile(at = polar(angle = helixCalc, length = baseDiameter / 2))
|> involuteCircular(
startRadius = baseDiameter / 2,
endRadius = tipDiameter / 2,
angle = helixCalc,
tag = $seg01,
)
|> line(endAbsolute = polar(angle = 160 / nTeeth + helixCalc, length = tipDiameter / 2))
|> involuteCircular(
startRadius = baseDiameter / 2,
endRadius = tipDiameter / 2,
angle = -(4 * atan(segEndY(seg01) / segEndX(seg01)) - (3 * helixCalc)),
reverse = true,
)
// Position the end line of the sketch at the start of the next tooth
|> line(endAbsolute = polar(angle = 360 / nTeeth + helixCalc, length = baseDiameter / 2))
// Pattern the sketch about the center by the specified number of teeth, then close the sketch
|> patternCircular2d(
%,
instances = nTeeth,
center = [0, 0],
arcDegrees = 360,
rotateDuplicates = true,
)
|> close()
|> subtract2d(tool = holeWithKeyway)
return helicalGearSketch
}
// Draw a gear sketch on the base plane
gearSketch001 = helicalGearSketch(offsetHeight = 0)
// Draw a rotated gear sketch on a middle interstitial plane
gearSketch002 = helicalGearSketch(offsetHeight = gearHeight / 2)
// Draw a rotated gear sketch at the gear height offset plane
gearSketch003 = helicalGearSketch(offsetHeight = gearHeight)
// Loft each rotated gear sketch together to form a helical gear
helicalGear = loft([
gearSketch001,
gearSketch002,
gearSketch003
])
return helicalGear
}
// Define a function to create a ring gear
fn ringGear(nTeeth, module, pressureAngle, helixAngle, gearHeight) {
// Calculate gear parameters
pitchDiameter = module * nTeeth
addendum = module
deddendum = 1.25 * module
baseDiameter = pitchDiameter * cos(pressureAngle)
tipDiameter = pitchDiameter + 2 * module
// Define a function to create a rotated gear sketch on an offset plane
fn ringGearSketch(offsetHeight) {
// Calculate the amount to rotate each planar sketch of the gear given the gear helix angle and total gear height
helixCalc = acos(offsetHeight * tan(helixAngle) / (tipDiameter / 2))
// Using the gear parameters, sketch an involute tooth spanning from the base diameter to the tip diameter
ringTeeth = startSketchOn(offsetPlane(XY, offset = offsetHeight))
|> startProfile(at = polar(angle = helixCalc, length = baseDiameter / 2))
|> involuteCircular(
startRadius = baseDiameter / 2,
endRadius = tipDiameter / 2,
angle = helixCalc,
tag = $seg01,
)
|> line(endAbsolute = polar(angle = 200 / nTeeth + helixCalc, length = tipDiameter / 2))
|> involuteCircular(
startRadius = baseDiameter / 2,
endRadius = tipDiameter / 2,
angle = -(4 * atan(segEndY(seg01) / segEndX(seg01)) - (3 * helixCalc)),
reverse = true,
)
// Position the end line of the sketch at the start of the next tooth
|> line(endAbsolute = polar(angle = 360 / nTeeth + helixCalc, length = baseDiameter / 2))
// Pattern the sketch about the center by the specified number of teeth, then close the sketch
|> patternCircular2d(
%,
instances = nTeeth,
center = [0, 0],
arcDegrees = 360,
rotateDuplicates = true,
)
|> close()
// Create a circular body that is larger than the tip diameter of the gear, then subtract the gear profile from the body
ringGearSketch = startSketchOn(offsetPlane(XY, offset = offsetHeight))
|> circle(center = [0, 0], radius = tipDiameter / 1.85)
|> subtract2d(tool = ringTeeth)
return ringGearSketch
}
// Draw a gear sketch on the base plane
gearSketch001 = ringGearSketch(offsetHeight = 0)
// Draw a rotated gear sketch on a middle interstitial plane
gearSketch002 = ringGearSketch(offsetHeight = gearHeight / 2)
// Draw a rotated gear sketch at the gear height offset plane
gearSketch003 = ringGearSketch(offsetHeight = gearHeight)
// Loft each rotated gear sketch together to form a ring gear
ringGear = loft([
gearSketch001,
gearSketch002,
gearSketch003
])
return ringGear
}
// Create the outer ring gear for the planetary gearset
ringGear(
nTeeth = 42,
module = 1.5,
pressureAngle = 14,
helixAngle = -25,
gearHeight = 5,
)
// Create a central sun gear using a small helical gear
helicalGear(
nTeeth = 12,
module = 1.5,
pressureAngle = 14,
helixAngle = 25,
gearHeight = 5,
)
// Create the helical planet gears
numPlanetGears = 3
helicalGear(
nTeeth = 12,
module = 1.5,
pressureAngle = 14,
helixAngle = -25,
gearHeight = 5,
)
|> translate(y = (12 + 12) / 2 * 1.5 + 2.7)
|> patternCircular3d(
instances = numPlanetGears,
axis = [0, 0, 1],
center = [0, 0, 0],
arcDegrees = 360,
rotateDuplicates = false,
)

View File

@ -0,0 +1,123 @@
// Helium Tank
// A helium tank is a portable pressure vessel used to store and dispense helium gas for a variety of commercial and entertainment purposes
// Set units
@settings(defaultLengthUnit = in)
// Define parameters
tankHeight = 2.5ft
tankDiameter = 9
wallThickness = 0.125
portDiameter = 1.25
bracketThickness = 0.090
boltSize = 1 / 4
// Sketch the perimeter of the gas tank- inside and out, then revolve around the vertical axis.
tankSketch = startSketchOn(YZ)
|> startProfile(at = [portDiameter / 2, tankHeight])
|> yLine(length = -0.6)
|> xLine(length = 0.1)
|> tangentialArc(angle = -110, radius = 0.1)
|> tangentialArc(angle = 40, radius = 0.6)
|> tangentialArc(angle = -110, radius = 0.1)
|> tangentialArc(angle = 180, radius = 0.1)
|> tangentialArc(angle = -90, radius = tankDiameter / 2 - lastSegX(%), tag = $seg01)
|> angledLine(angle = tangentToEnd(seg01), endAbsoluteY = 1.5, tag = $seg09)
|> tangentialArc(angle = -90, radius = 2, tag = $seg02)
|> angledLine(angle = tangentToEnd(seg02), endAbsoluteX = 0.001, tag = $seg08)
|> yLine(length = wallThickness)
|> xLine(length = segLen(seg08))
|> tangentialArc(angle = 90, radius = 2 - wallThickness)
|> yLine(length = segLen(seg09))
|> tangentialArc(angle = 90, radius = tankDiameter / 2 - wallThickness - 1.3)
|> xLine(endAbsolute = profileStartX(%) - .1)
|> yLine(endAbsolute = profileStartY(%))
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
// Only revolving to 220deg so that the interior of the tank is visible. It should ultimately be closed at 360deg
tankRevolve = revolve(tankSketch, angle = 220, axis = Y)
// Model the brass valve on top of the tank port
valveBody = startSketchOn(offsetPlane(XY, offset = tankHeight - 0.5))
|> circle(center = [0, 0], radius = portDiameter / 1.9, tag = $seg03)
|> extrude(length = 1.5, tagEnd = $capEnd001)
|> fillet(
radius = 0.1,
tags = [
getCommonEdge(faces = [seg03, capEnd001])
],
)
// Model the outlet port of the valve, then union it all together
valvePort = startSketchOn(YZ)
|> circle(center = [0, tankHeight + 0.3], radius = portDiameter / 3)
|> subtract2d(tool = circle(center = [0, tankHeight + 0.3], radius = portDiameter / 3.25))
|> extrude(length = 1.3)
valve = union([valveBody, valvePort])
|> appearance(color = "#9a4618")
// Sketch the offset profile of the mounting bracket
bracketOffsetProfile = startSketchOn(offsetPlane(XY, offset = tankHeight * 0.67))
|> startProfile(at = [0, tankDiameter / 2 + wallThickness])
|> xLine(length = -0.1)
|> tangentialArc(angle = 35, radius = tankDiameter / 2 + wallThickness)
|> tangentialArc(angle = -135, radius = 0.25 - wallThickness, tag = $seg06)
|> angledLine(angle = tangentToEnd(seg06), length = tankDiameter / 7)
|> tangentialArc(angle = -80, radius = 0.25 - wallThickness, tag = $seg07)
|> angledLine(angle = tangentToEnd(seg07), endAbsoluteX = 0)
|> mirror2d(axis = Y)
|> close()
// Sketch the outer perimeter of the offset bracket, then subtract the inner offset to create a constant thickness sheet metal hoop
bracketProfile = startSketchOn(offsetPlane(XY, offset = tankHeight * 0.67))
|> startProfile(at = [0, tankDiameter / 2])
|> xLine(length = -0.1)
|> tangentialArc(angle = 35, radius = tankDiameter / 2)
|> tangentialArc(angle = -135, radius = 0.25, tag = $seg04)
|> angledLine(angle = tangentToEnd(seg04), length = tankDiameter / 7)
|> tangentialArc(angle = -80, radius = 0.25, tag = $seg05)
|> angledLine(angle = tangentToEnd(seg05), endAbsoluteX = 0)
|> mirror2d(axis = Y)
|> close()
|> subtract2d(tool = bracketOffsetProfile)
|> extrude(length = 1, symmetric = true)
// Cut holes in the bracket for a mounting strap
strapSleeve = startSketchOn(offsetPlane(XY, offset = tankHeight * 0.67))
|> circle(center = [0, .125 / 2], radius = 4.75)
|> subtract2d(tool = circle(center = [0, .125 / 2], radius = 4.65))
|> extrude(length = .8, symmetric = true)
bracketSleeve = subtract([bracketProfile], tools = [strapSleeve])
// Create holes in the bracket for anchor mounts to secure the bracket to a wall
mountingHoles = startSketchOn(offsetPlane(XZ, offset = -tankDiameter / 1.9))
|> circle(center = [tankDiameter / 4.5, tankHeight * 0.67], radius = boltSize / 2)
|> extrude(length = -5)
bracket = subtract(
[bracketSleeve],
tools = union(patternLinear3d(
mountingHoles,
instances = 2,
distance = tankDiameter / 2.25,
axis = [-1, 0, 0],
)),
)
|> appearance(color = "#cd0404")
// Model a circular strap to secure the tank to the bracket
mountingStrap = startSketchOn(offsetPlane(XY, offset = tankHeight * 0.67))
|> circle(center = [0, .155 / 2], radius = tankDiameter / 1.9)
|> subtract2d(tool = circle(center = [0, .155 / 2], radius = tankDiameter / 1.9 - 0.1))
|> extrude(length = .75, symmetric = true)
|> appearance(color = "#210d03")
// Create a second instance of the bracket and strap at a lower point on the tank
[bracket, mountingStrap]
|> patternLinear3d(
%,
instances = 2,
distance = tankHeight * 0.33,
axis = [0, 0, -1],
)

View File

@ -0,0 +1,84 @@
// Herringbone Gear
// A herringbone, or double-helical gear, is a cylindrical gear type with angled teeth in opposing directions. This allows the quietness and smoothness of a helical gear, without applying a directional load while turning
// Set units
@settings(defaultLengthUnit = mm)
// Define a function to create a herringbone gear
fn herringboneGear(nTeeth, module, pressureAngle, helixAngle, gearHeight) {
// Calculate gear parameters
pitchDiameter = module * nTeeth
addendum = module
deddendum = 1.25 * module
baseDiameter = pitchDiameter * cos(pressureAngle)
tipDiameter = pitchDiameter + 2 * module
// Define a function to create a rotated gear sketch on an offset plane
fn herringboneGearSketch(offsetHeight) {
// Calculate the amount to rotate each planar sketch of the gear given the gear helix angle and total gear height
helixCalc = acos(offsetHeight * tan(helixAngle) / (tipDiameter / 2))
// Using the gear parameters, sketch an involute tooth spanning from the base diameter to the tip diameter
herringboneGearSketch = startSketchOn(offsetPlane(XY, offset = offsetHeight))
|> startProfile(at = polar(angle = helixCalc, length = baseDiameter / 2))
|> involuteCircular(
startRadius = baseDiameter / 2,
endRadius = tipDiameter / 2,
angle = helixCalc,
tag = $seg01,
)
|> line(endAbsolute = polar(angle = 160 / nTeeth + helixCalc, length = tipDiameter / 2))
|> involuteCircular(
startRadius = baseDiameter / 2,
endRadius = tipDiameter / 2,
angle = -(4 * atan(segEndY(seg01) / segEndX(seg01)) - (3 * helixCalc)),
reverse = true,
)
// Position the end line of the sketch at the start of the next tooth
|> line(endAbsolute = polar(angle = 360 / nTeeth + helixCalc, length = baseDiameter / 2))
// Pattern the sketch about the center by the specified number of teeth, then close the sketch
|> patternCircular2d(
%,
instances = nTeeth,
center = [0, 0],
arcDegrees = 360,
rotateDuplicates = true,
)
|> close()
// Create a center hole with an 8mm diameter
|> subtract2d(tool = circle(center = [0, 0], radius = 4))
return herringboneGearSketch
}
// Draw a gear sketch on the base plane
gearSketch001 = herringboneGearSketch(offsetHeight = 0)
// Draw a gear sketch that has been rotated by the helix angle
gearSketch002 = herringboneGearSketch(offsetHeight = gearHeight / 2)
// Draw a gear sketch at the total gear height that reverses the angle direction
gearSketch003 = clone(gearSketch001)
|> translate(z = gearHeight)
// Loft each rotated gear sketch together to form a herringbone gear
herringboneGear = loft(
[
gearSketch001,
gearSketch002,
gearSketch003
],
vDegree = 1,
)
return herringboneGear
}
herringboneGear(
nTeeth = 25,
module = 1,
pressureAngle = 14,
helixAngle = 40,
gearHeight = 8,
)

View File

@ -0,0 +1,186 @@
// Herringbone Planetary Gearset
// A herringbone planetary gearset is a type of planetary gear system where the teeth of the sun gear, planet gears, and/or ring gear are herringbone rather than straight. This design allows for smoother, quieter operation, greater load-carrying capacity, and more flexible shaft alignment.
// Set units
@settings(defaultLengthUnit = mm)
// Define a function to create a herringbone gear
fn herringboneGear(nTeeth, module, pressureAngle, helixAngle, gearHeight) {
// Calculate gear parameters
pitchDiameter = module * nTeeth
addendum = module
deddendum = 1.25 * module
baseDiameter = pitchDiameter * cos(pressureAngle)
tipDiameter = pitchDiameter + 2 * module
// Define a function to create a rotated gear sketch on an offset plane
fn herringboneGearSketch(offsetHeight) {
// Calculate the amount to rotate each planar sketch of the gear given the gear helix angle and total gear height
helixCalc = acos(offsetHeight * tan(helixAngle) / (tipDiameter / 2))
// Using the gear parameters, sketch an involute tooth spanning from the base diameter to the tip diameter
herringboneGearSketch = startSketchOn(offsetPlane(XY, offset = offsetHeight))
|> startProfile(at = polar(angle = helixCalc, length = baseDiameter / 2))
|> involuteCircular(
startRadius = baseDiameter / 2,
endRadius = tipDiameter / 2,
angle = helixCalc,
tag = $seg01,
)
|> line(endAbsolute = polar(angle = 160 / nTeeth + helixCalc, length = tipDiameter / 2))
|> involuteCircular(
startRadius = baseDiameter / 2,
endRadius = tipDiameter / 2,
angle = -(4 * atan(segEndY(seg01) / segEndX(seg01)) - (3 * helixCalc)),
reverse = true,
)
// Position the end line of the sketch at the start of the next tooth
|> line(endAbsolute = polar(angle = 360 / nTeeth + helixCalc, length = baseDiameter / 2))
// Pattern the sketch about the center by the specified number of teeth, then close the sketch
|> patternCircular2d(
%,
instances = nTeeth,
center = [0, 0],
arcDegrees = 360,
rotateDuplicates = true,
)
|> close()
// Create a center hole with an 8mm diameter
|> subtract2d(tool = circle(center = [0, 0], radius = 4))
return herringboneGearSketch
}
// Draw a gear sketch on the base plane
gearSketch001 = herringboneGearSketch(offsetHeight = 0)
// Draw a gear sketch that has been rotated by the helix angle
gearSketch002 = herringboneGearSketch(offsetHeight = gearHeight / 2)
// Draw a gear sketch at the total gear height that reverses the angle direction
gearSketch003 = clone(gearSketch001)
|> translate(z = gearHeight)
// Loft each rotated gear sketch together to form a herringbone gear
herringboneGear = loft(
[
gearSketch001,
gearSketch002,
gearSketch003
],
vDegree = 1,
)
return herringboneGear
}
// Define a function to create a ring gear
fn ringGear(nTeeth, module, pressureAngle, helixAngle, gearHeight) {
// Calculate gear parameters
pitchDiameter = module * nTeeth
addendum = module
deddendum = 1.25 * module
baseDiameter = pitchDiameter * cos(pressureAngle)
tipDiameter = pitchDiameter + 2 * module
// Define a function to create a rotated gear sketch on an offset plane
fn ringGearSketch(offsetHeight) {
// Calculate the amount to rotate each planar sketch of the gear given the gear helix angle and total gear height
helixCalc = acos(offsetHeight * tan(helixAngle) / (tipDiameter / 2))
// Using the gear parameters, sketch an involute tooth spanning from the base diameter to the tip diameter
ringTeeth = startSketchOn(offsetPlane(XY, offset = offsetHeight))
|> startProfile(at = polar(angle = helixCalc, length = baseDiameter / 2))
|> involuteCircular(
startRadius = baseDiameter / 2,
endRadius = tipDiameter / 2,
angle = helixCalc,
tag = $seg01,
)
|> line(endAbsolute = polar(angle = 220 / nTeeth + helixCalc, length = tipDiameter / 2))
|> involuteCircular(
startRadius = baseDiameter / 2,
endRadius = tipDiameter / 2,
angle = -(4 * atan(segEndY(seg01) / segEndX(seg01)) - (3 * helixCalc)),
reverse = true,
)
// Position the end line of the sketch at the start of the next tooth
|> line(endAbsolute = polar(angle = 360 / nTeeth + helixCalc, length = baseDiameter / 2))
// Pattern the sketch about the center by the specified number of teeth, then close the sketch
|> patternCircular2d(
%,
instances = nTeeth,
center = [0, 0],
arcDegrees = 360,
rotateDuplicates = true,
)
|> close()
// Create a circular body that is larger than the tip diameter of the gear, then subtract the gear profile from the body
ringGearSketch = startSketchOn(offsetPlane(XY, offset = offsetHeight))
|> circle(center = [0, 0], radius = tipDiameter / 1.8)
|> subtract2d(tool = ringTeeth)
return ringGearSketch
}
// Draw a gear sketch on the base plane
gearSketch001 = ringGearSketch(offsetHeight = 0)
// Draw a rotated gear sketch on a middle interstitial plane
gearSketch002 = ringGearSketch(offsetHeight = gearHeight / 2)
// Draw a gear sketch at the total gear height that reverses the angle direction
gearSketch003 = clone(gearSketch001)
|> translate(z = gearHeight)
// Loft each rotated gear sketch together to form a ring gear
ringGear = loft(
[
gearSketch001,
gearSketch002,
gearSketch003
],
vDegree = 1,
)
return ringGear
}
// Create the outer ring gear for the planetary gearset
ringGear(
nTeeth = 58,
module = 1.5,
pressureAngle = 14,
helixAngle = -35,
gearHeight = 8,
)
// Create a central sun gear using a small herringbone gear
herringboneGear(
nTeeth = 18,
module = 1.5,
pressureAngle = 14,
helixAngle = 35,
gearHeight = 8,
)
// Create the herringbone planet gears
numPlanetGears = 4
herringboneGear(
nTeeth = 18,
module = 1.5,
pressureAngle = 14,
helixAngle = -35,
gearHeight = 8,
)
|> translate(y = 18 * 1.5 + 1.95)
|> patternCircular3d(
instances = numPlanetGears,
axis = [0, 0, 1],
center = [0, 0, 0],
arcDegrees = 360,
rotateDuplicates = false,
)

View File

@ -44,6 +44,16 @@
"main.kcl"
]
},
{
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "bone-plate/main.kcl",
"multipleFiles": false,
"title": "Bone Plate",
"description": "A bone plate is a medical device used in orthopedics to stabilize and fix bone fractures during the healing process. They are typically made of stainless steel or titanium and are secured to the bone with screws. Bone plates come in various types, including locking, compression, and bridge plates, each with specific applications",
"files": [
"main.kcl"
]
},
{
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "bottle/main.kcl",
@ -80,6 +90,16 @@
"parameters.kcl"
]
},
{
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "cold-plate/main.kcl",
"multipleFiles": false,
"title": "Cold Plate",
"description": "A cold plate is a thermal management device used to remove heat from a device or component, typically by transferring heat to a liquid coolant that flows through the plate. It's a conductive cooling solution, commonly made of materials like aluminum or copper, with internal channels or tubes for the coolant",
"files": [
"main.kcl"
]
},
{
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "color-cube/main.kcl",
@ -90,6 +110,43 @@
"main.kcl"
]
},
{
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "counterdrilled-weldment/main.kcl",
"multipleFiles": false,
"title": "Counterdrilled Weldment",
"description": "A metal weldment consisting of a counterdrilled plate, a centrally mounted housing tube, and four structural support fins.",
"files": [
"main.kcl"
]
},
{
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "countersunk-plate/main.kcl",
"multipleFiles": false,
"title": "Plate with countersunk holes",
"description": "A small mounting plate with a countersunk hole at each end",
"files": [
"main.kcl"
]
},
{
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "cpu-cooler/main.kcl",
"multipleFiles": true,
"title": "CPU Cooler",
"description": "A CPU cooler is a device designed to dissipate heat generated by the CPU of a computer. They consist of a brazed heat sink made from aluminum or copper alloys, and one or two axial fans to move airflow across the heat sink.",
"files": [
"fan-housing.kcl",
"fan.kcl",
"heat-sink.kcl",
"main.kcl",
"motor.kcl",
"mounting-wire.kcl",
"parameters.kcl",
"removable-sticker.kcl"
]
},
{
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "cycloidal-gear/main.kcl",
@ -170,16 +227,6 @@
"main.kcl"
]
},
{
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "gear/main.kcl",
"multipleFiles": false,
"title": "Spur Gear",
"description": "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.",
"files": [
"main.kcl"
]
},
{
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "gear-rack/main.kcl",
@ -230,6 +277,66 @@
"main.kcl"
]
},
{
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "hammer/main.kcl",
"multipleFiles": false,
"title": "Claw Hammer",
"description": "Often used in construction, a claw hammer is a levered metal hand tool that is used to strike and extract nails",
"files": [
"main.kcl"
]
},
{
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "helical-gear/main.kcl",
"multipleFiles": false,
"title": "Helical Gear",
"description": "A helical gear is a type of cylindrical gear where the teeth are slanted at an angle relative to the axis of rotation. This greatly reduces noise and wear when transmitting torque across meshed spinning gears",
"files": [
"main.kcl"
]
},
{
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "helical-planetary-gearset/main.kcl",
"multipleFiles": false,
"title": "Helical Planetary Gearset",
"description": "A helical planetary gearset is a type of planetary gear system where the teeth of the sun gear, planet gears, and/or ring gear are helical rather than straight. This design allows for smoother, quieter operation, greater load-carrying capacity, and more flexible shaft alignment.",
"files": [
"main.kcl"
]
},
{
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "helium-tank/main.kcl",
"multipleFiles": false,
"title": "Helium Tank",
"description": "A helium tank is a portable pressure vessel used to store and dispense helium gas for a variety of commercial and entertainment purposes",
"files": [
"main.kcl"
]
},
{
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "herringbone-gear/main.kcl",
"multipleFiles": false,
"title": "Herringbone Gear",
"description": "A herringbone, or double-helical gear, is a cylindrical gear type with angled teeth in opposing directions. This allows the quietness and smoothness of a helical gear, without applying a directional load while turning",
"files": [
"main.kcl"
]
},
{
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "herringbone-planetary-gearset/main.kcl",
"multipleFiles": false,
"title": "Herringbone Planetary Gearset",
"description": "A herringbone planetary gearset is a type of planetary gear system where the teeth of the sun gear, planet gears, and/or ring gear are herringbone rather than straight. This design allows for smoother, quieter operation, greater load-carrying capacity, and more flexible shaft alignment.",
"files": [
"main.kcl"
]
},
{
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "hex-nut/main.kcl",
@ -317,12 +424,15 @@
},
{
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "parametric-bearing-pillow-block/main.kcl",
"multipleFiles": false,
"title": "Parametric Bearing Pillow Block",
"pathFromProjectDirectoryToFirstFile": "pillow-block-bearing/main.kcl",
"multipleFiles": true,
"title": "Pillow Block Bearing",
"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.",
"files": [
"main.kcl"
"ball-bearing.kcl",
"block.kcl",
"main.kcl",
"parameters.kcl"
]
},
{
@ -372,6 +482,16 @@
"main.kcl"
]
},
{
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "prosthetic-hip/main.kcl",
"multipleFiles": false,
"title": "Prosthetic Hip",
"description": "A prosthetic hip is a surgically implanted ball-and-socket intended to replace a damaged or worn hip joint",
"files": [
"main.kcl"
]
},
{
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "router-template-cross-bar/main.kcl",
@ -412,6 +532,46 @@
"main.kcl"
]
},
{
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "spur-gear/main.kcl",
"multipleFiles": false,
"title": "Spur Gear",
"description": "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.",
"files": [
"main.kcl"
]
},
{
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "spur-reduction-gearset/main.kcl",
"multipleFiles": false,
"title": "Spur Reduction Gearset",
"description": "A pair of spur gears meshed together, with an equal module and different number of teeth",
"files": [
"main.kcl"
]
},
{
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "surgical-drill-guide/main.kcl",
"multipleFiles": false,
"title": "Surgical Drill Guide",
"description": "A surgical drill guide is a tool used in medical procedures to assist in drilling holes to a desired depth, ensuring proper orientation and minimizing intraosseal pressure",
"files": [
"main.kcl"
]
},
{
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "tooling-nest-block/main.kcl",
"multipleFiles": false,
"title": "Tooling Nest Block",
"description": "A tooling nest block is a block-shaped tool made from high-carbon steel. It features an assortment of conical or hemispherical indentions, which are used to form or shape metal, particularly in crafting bells or jewelry",
"files": [
"main.kcl"
]
},
{
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "utility-sink/main.kcl",
@ -449,5 +609,15 @@
"files": [
"main.kcl"
]
},
{
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "wing-spar/main.kcl",
"multipleFiles": false,
"title": "Wing Spar",
"description": "In a fixed-wing aircraft, the spar is often the main structural member of the wing, running spanwise at right angles (or thereabouts depending on wing sweep) to the fuselage. The spar carries flight loads and the weight of the wings while on the ground. Other structural and forming members such as ribs may be attached to the spars",
"files": [
"main.kcl"
]
}
]

View File

@ -1,51 +0,0 @@
// 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, kclVersion = 1.0)
// Define parameters
length = 6
width = 4
height = 1
cbDepth = .25
cbDia = .7
holeDia = .375
padding = 1.5
bearingDia = 3
// Sketch the block body
body = startSketchOn(XY)
|> startProfile(at = [-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)
counterBoreHoles = startSketchOn(body, face = END)
|> circle(
center = [
-(width / 2 - (padding / 2)),
-(length / 2 - (padding / 2))
],
radius = cbDia / 2,
)
|> patternLinear2d(instances = 2, distance = length - padding, axis = [0, 1])
|> patternLinear2d(instances = 2, distance = width - padding, axis = [1, 0])
|> extrude(%, length = -cbDepth)
boltHoles = startSketchOn(body, face = START)
|> circle(
center = [
-(width / 2 - (padding / 2)),
-(length / 2 - (padding / 2))
],
radius = holeDia / 2,
)
|> patternLinear2d(instances = 2, distance = length - padding, axis = [0, 1])
|> patternLinear2d(instances = 2, distance = width - padding, axis = [1, 0])
|> extrude(length = -height + cbDepth)
centerHole = startSketchOn(body, face = END)
|> circle(center = [0, 0], radius = bearingDia / 2)
|> extrude(length = -height)

View File

@ -0,0 +1,101 @@
// Pillow Block Bearing
// The ball bearing for the pillow block bearing assembly
// Set units
@settings(defaultLengthUnit = in)
// Import Parameters
import * from "parameters.kcl"
// Create the sketch of one of the balls. The ball diameter is sized as a fraction of the difference between inner and outer radius of the bearing
ballsSketch = startSketchOn(offsetPlane(XY, offset = stockThickness / 2))
|> startProfile(at = [bearingBoreDiameter / 2 + 0.1, 0.001])
|> arc(angleEnd = 0, angleStart = 180, radius = sphereDia / 2)
|> close()
// Revolve the ball to make a sphere and pattern around the inside wall
balls = revolve(ballsSketch, axis = X)
|> patternCircular3d(
arcDegrees = 360,
axis = [0, 0, 1],
center = [0, 0, 0],
instances = 16,
rotateDuplicates = true,
)
// Create the sketch for the chain around the balls
chainSketch = startSketchOn(offsetPlane(XY, offset = stockThickness / 2))
|> startProfile(at = [
bearingBoreDiameter / 2 + 0.1 + sphereDia / 2 - (chainWidth / 2),
0.125 * sin(60deg)
])
|> arc(angleEnd = 60, angleStart = 120, radius = sphereDia / 2)
|> line(end = [0, chainThickness])
|> line(end = [-chainWidth, 0])
|> close()
// Revolve the chain sketch
chainHead = revolve(chainSketch, axis = X)
|> patternCircular3d(
arcDegrees = 360,
axis = [0, 0, 1],
center = [0, 0, 0],
instances = 16,
rotateDuplicates = true,
)
// Create the sketch for the links in between the chains
linkSketch = startSketchOn(XZ)
|> circle(
center = [
bearingBoreDiameter / 2 + 0.1 + sphereDia / 2,
stockThickness / 2
],
radius = linkDiameter / 2,
)
// Create the walls of the bearing
bearingBody = startSketchOn(XZ)
bearingUpper = startProfile(
bearingBody,
at = [
bearingOuterDiameter / 2 - .07,
stockThickness
],
)
|> angledLine(angle = -91, length = 0.05)
|> xLine(length = -(bearingOuterDiameter / 2 - (bearingBoreDiameter / 2)) + .145)
|> yLine(endAbsolute = 0.105)
|> xLine(length = -0.025)
|> angledLine(angle = 91, endAbsoluteY = profileStartY(%))
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
|> revolve(angle = 360, axis = Y)
|> appearance(%, color = "#121212")
bearingLower = startProfile(bearingBody, at = [bearingBoreDiameter / 2, 0.025])
|> xLine(length = 0.05)
|> angledLine(angle = 75, length = 0.04, tag = $seg01)
|> xLine(length = 0.05)
|> angledLine(angle = -75, length = segLen(seg01))
|> xLine(endAbsolute = bearingOuterDiameter / 2)
|> yLine(length = stockThickness)
|> xLine(length = -0.07)
|> angledLine(angle = -91, endAbsoluteY = profileStartY(%) + .075)
|> xLine(endAbsolute = profileStartX(%) + .05)
|> angledLine(angle = 91, endAbsoluteY = stockThickness * 1.25)
|> xLine(endAbsolute = profileStartX(%))
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
|> revolve(angle = 360, axis = Y)
|> appearance(%, color = "#f0f0f0")
// Revolve the link sketch
revolve(linkSketch, axis = Y, angle = 360 / 16)
|> patternCircular3d(
arcDegrees = 360,
axis = [0, 0, 1],
center = [0, 0, 0],
instances = 16,
rotateDuplicates = true,
)

View File

@ -0,0 +1,56 @@
// Pillow Block Bearing
// The machined block for the pillow block bearing assembly. The block is dimensioned using the bolt pattern spacing, and each bolt hole includes a counterbore
// Set units
@settings(defaultLengthUnit = in)
// Import Parameters
import * from "parameters.kcl"
// Calculate the dimensions of the block using the specified bolt spacing. The size of the block can be defined by adding a multiple of the counterbore diameter to the bolt spacing
blockLength = boltSpacingX + counterboreDiameter + boltDiameter
blockWidth = boltSpacingY + counterboreDiameter + boltDiameter
// Draw the base plate
plateSketch = startSketchOn(XY)
|> startProfile(at = [-blockLength / 2, -blockWidth / 2])
|> angledLine(angle = 0, length = blockLength, tag = $rectangleSegmentA001)
|> angledLine(angle = segAng(rectangleSegmentA001) + 90, length = blockWidth, tag = $rectangleSegmentB001)
|> angledLine(angle = segAng(rectangleSegmentA001), length = -segLen(rectangleSegmentA001), tag = $rectangleSegmentC001)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $rectangleSegmentD001)
|> close()
|> subtract2d(tool = circle(center = [0, 0], radius = bearingOuterDiameter / 2))
plateBody = extrude(plateSketch, length = stockThickness)
|> appearance(%, color = "#1e62eb")
|> fillet(
radius = boltDiameter * 1 / 3,
tags = [
getNextAdjacentEdge(rectangleSegmentB001),
getNextAdjacentEdge(rectangleSegmentA001),
getNextAdjacentEdge(rectangleSegmentC001),
getNextAdjacentEdge(rectangleSegmentD001)
],
)
// Define hole positions
holePositions = [
[-boltSpacingX / 2, -boltSpacingY / 2],
[-boltSpacingX / 2, boltSpacingY / 2],
[boltSpacingX / 2, -boltSpacingY / 2],
[boltSpacingX / 2, boltSpacingY / 2]
]
// Function to create a counterbored hole
fn counterbore(@holePosition) {
cbBore = startSketchOn(plateBody, face = END)
|> circle(center = holePosition, radius = counterboreDiameter / 2)
|> extrude(length = -counterboreDepth)
cbBolt = startSketchOn(cbBore, face = START)
|> circle(center = holePosition, radius = boltDiameter / 2, tag = $hole01)
|> extrude(length = -stockThickness + counterboreDepth)
return { }
}
// Place a counterbored hole at each bolt hole position
map(holePositions, f = counterbore)

View File

@ -0,0 +1,14 @@
// Pillow Block Bearing
// 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)
// Import parts and parameters
import * from "parameters.kcl"
import "ball-bearing.kcl" as ballBearing
import "block.kcl" as block
// Render each part
ballBearing
block

View File

@ -0,0 +1,18 @@
// Global parameters for the pillow block bearing
// Set units
@settings(defaultLengthUnit = in)
// Export parameters
export boltSpacingX = 5
export boltSpacingY = 3
export boltDiameter = 3 / 8
export counterboreDiameter = 3 / 4
export counterboreDepth = 3 / 16
export stockThickness = .5
export bearingBoreDiameter = 1 + 3 / 4
export bearingOuterDiameter = bearingBoreDiameter * 1.5
export sphereDia = (bearingOuterDiameter - bearingBoreDiameter) / 4
export chainWidth = sphereDia / 2
export chainThickness = sphereDia / 8
export linkDiameter = sphereDia / 4

View File

@ -0,0 +1,176 @@
// Prosthetic Hip
// A prosthetic hip is a surgically implanted ball-and-socket intended to replace a damaged or worn hip joint
// Set units
@settings(defaultLengthUnit = mm)
// Create the femur using a series of lofts. Draw the profile for the first loft on the XY plane.
l1 = 1
r1 = 3
stemLoftProfile1 = startSketchOn(XY)
|> startProfile(at = [-3, -l1 / 2])
|> yLine(length = l1, tag = $seg01)
|> tangentialArc(angle = -120, radius = r1)
|> angledLine(angle = -30, length = segLen(seg01))
|> tangentialArc(angle = -120, radius = r1)
|> angledLine(angle = 30, length = -segLen(seg01))
|> tangentialArc(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
// Draw the second profile for the lofted femur
l2 = 19
r2 = 3
stemLoftProfile2 = startSketchOn(offsetPlane(XY, offset = 75))
|> startProfile(at = [-8, -l2 / 2])
|> yLine(length = l2, tag = $seg02)
|> tangentialArc(angle = -120, radius = r2)
|> angledLine(angle = -30, length = segLen(seg02))
|> tangentialArc(angle = -120, radius = r2)
|> angledLine(angle = 30, length = -segLen(seg02))
|> tangentialArc(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
// Draw the third profile for the lofted femur
p3Z = 110
p3A = 25
plane003 = {
origin = [0, 0.0, p3Z],
xAxis = [cos(p3A), 0, sin(p3A)],
yAxis = [0.0, 1.0, 0.0]
}
l3 = 32
r3 = 4
stemLoftProfile3 = startSketchOn(plane003)
|> startProfile(at = [-15.5, -l3 / 2])
|> yLine(length = l3, tag = $seg03)
|> tangentialArc(angle = -120, radius = r3)
|> angledLine(angle = -30, length = segLen(seg03))
|> tangentialArc(angle = -120, radius = r3)
|> angledLine(angle = 30, length = -segLen(seg03))
|> tangentialArc(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
// Draw the fourth profile for the lofted femur
p4Z = 130
p4A = 36.5
plane004 = {
origin = [0, 0.0, p4Z],
xAxis = [cos(p4A), 0, sin(p4A)],
yAxis = [0.0, 1.0, 0.0]
}
l4 = 16
r4 = 5
stemLoftProfile4 = startSketchOn(plane004)
|> startProfile(at = [-23, -l4 / 2])
|> yLine(length = l4, tag = $seg04)
|> tangentialArc(angle = -120, radius = r4)
|> angledLine(angle = -30, length = segLen(seg04))
|> tangentialArc(angle = -120, radius = r4)
|> angledLine(angle = 30, length = -segLen(seg04))
|> tangentialArc(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
// Draw the first profile for the femoral stem
p5Z = 140
p5A = 36.5
plane005 = {
origin = [0, 0.0, p5Z],
xAxis = [cos(p5A), 0, sin(p5A)],
yAxis = [0.0, 1.0, 0.0]
}
l5 = 1.6
r5 = 1.6
stemLoftProfile5 = startSketchOn(plane005)
|> startProfile(at = [-19.5, -l5 / 2])
|> yLine(length = l5, tag = $seg05)
|> tangentialArc(angle = -120, radius = r5)
|> angledLine(angle = -30, length = segLen(seg05))
|> tangentialArc(angle = -120, radius = r5)
|> angledLine(angle = 30, length = -segLen(seg05))
|> tangentialArc(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
// Draw the second profile for the femoral stem
p6Z = 145
p6A = 36.5
plane006 = {
origin = [0, 0.0, p6Z],
xAxis = [cos(p6A), 0, sin(p6A)],
yAxis = [0.0, 1.0, 0.0]
}
l6 = 1
r6 = 3
stemLoftProfile6 = startSketchOn(plane006)
|> startProfile(at = [-23.4, -l6 / 2])
|> yLine(length = l6, tag = $seg06)
|> tangentialArc(angle = -120, radius = r6)
|> angledLine(angle = -30, length = segLen(seg06))
|> tangentialArc(angle = -120, radius = r6)
|> angledLine(angle = 30, length = -segLen(seg06))
|> tangentialArc(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
// Draw the third profile for the femoral stem
stemTab = clone(stemLoftProfile6)
|> extrude(%, length = 6)
// Loft the femur using all profiles in sequence
femur = loft([
stemLoftProfile1,
stemLoftProfile2,
stemLoftProfile3,
stemLoftProfile4
])
// Loft the femoral stem
femoralStem = loft([
clone(stemLoftProfile4),
stemLoftProfile5,
stemLoftProfile6
])
// Revolve a hollow socket to represent the femoral head
femoralHead = startSketchOn(XZ)
|> startProfile(at = [4, 0])
|> xLine(length = 1.1)
|> tangentialArc(angle = 90, radius = 3)
|> tangentialArc(angle = 90, radius = 8)
|> yLine(length = -1)
|> tangentialArc(angle = 90, radius = .1)
|> tangentialArc(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
|> revolve(angle = 360, axis = Y)
|> translate(x = -16.1, z = 133)
|> rotate(pitch = -36.5)
|> appearance(color = "#d64398")
// Place a polyethylene cap over the femoral head
polyethyleneInsert = startSketchOn(XZ)
|> startProfile(at = [8.36, 3])
|> xLine(length = 0.5)
|> yLine(length = .1)
|> tangentialArc(endAbsolute = [0.1, 12.55])
|> yLine(length = -0.85)
|> xLine(length = 0.58)
|> tangentialArc(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
|> revolve(angle = 360, axis = Y)
|> translate(x = -16.1, z = 133)
|> rotate(pitch = -36.5)
|> appearance(color = "#3cadd3")
// Place a ceramic or metal shell over the cap
acetabularShell = startSketchOn(XZ)
|> startProfile(at = [8.84, 4.7])
|> xLine(length = 1)
|> yLine(length = .5)
|> tangentialArc(endAbsolute = [0.1, 14])
|> yLine(endAbsolute = 12.56)
|> xLine(length = 0.1)
|> tangentialArc(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
|> revolve(angle = 360, axis = Y)
|> translate(x = -16.1, z = 133)
|> rotate(pitch = -36.5)
|> appearance(color = "#a55e2c")

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 KiB

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

View File

@ -0,0 +1,76 @@
// 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
@settings(defaultLengthUnit = mm)
// Define a function to create a spur gear
fn spurGear(nTeeth, module, pressureAngle, gearHeight) {
// Define gear parameters
pitchDiameter = module * nTeeth
addendum = module
deddendum = 1.25 * module
baseDiameter = pitchDiameter * cos(pressureAngle)
tipDiameter = pitchDiameter + 2 * module
// Define the constants of the keyway and the bore hole
keywayWidth = 2
keywayDepth = keywayWidth / 2
holeDiam = 5
holeRadius = holeDiam / 2
startAngle = asin(keywayWidth / 2 / holeRadius)
// Sketch the keyway and center hole
holeWithKeyway = startSketchOn(XY)
|> startProfile(at = [
holeRadius * cos(startAngle),
holeRadius * sin(startAngle)
])
|> xLine(length = keywayDepth)
|> yLine(length = -keywayWidth)
|> xLine(length = -keywayDepth)
|> arc(angleStart = -1 * startAngle + 360, angleEnd = 180, radius = holeRadius)
|> arc(angleStart = 180, angleEnd = startAngle, radius = holeRadius)
|> close()
// Using the gear parameters, sketch an involute tooth spanning from the base diameter to the tip diameter
gearSketch = startSketchOn(XY)
|> startProfile(at = polar(angle = 0, length = baseDiameter / 2))
|> involuteCircular(
startRadius = baseDiameter / 2,
endRadius = tipDiameter / 2,
angle = 0,
tag = $seg01,
)
|> line(endAbsolute = polar(angle = 160 / nTeeth, length = tipDiameter / 2))
|> involuteCircular(
startRadius = baseDiameter / 2,
endRadius = tipDiameter / 2,
angle = -atan(segEndY(seg01) / segEndX(seg01)) - (180 / nTeeth),
reverse = true,
)
// Position the end line of the sketch at the start of the next tooth
|> line(endAbsolute = polar(angle = 360 / nTeeth, length = baseDiameter / 2))
// Pattern the sketch about the center by the specified number of teeth, then close the sketch
|> patternCircular2d(
%,
instances = nTeeth,
center = [0, 0],
arcDegrees = 360,
rotateDuplicates = true,
)
|> close()
// Subtract the keyway sketch from the gear sketch
|> subtract2d(tool = holeWithKeyway)
// Extrude the gear to the specified height
|> extrude(length = gearHeight)
return gearSketch
}
spurGear(
nTeeth = 21,
module = 1.5,
pressureAngle = 14,
gearHeight = 6,
)

View File

@ -0,0 +1,70 @@
// Spur Reduction Gearset
// A pair of spur gears meshed together, with an equal module and different number of teeth
// Set units
@settings(defaultLengthUnit = mm)
// Define a function to create a spur gear
fn spurGear(nTeeth, module, pressureAngle, gearHeight) {
// Calculate gear parameters
pitchDiameter = module * nTeeth
addendum = module
deddendum = 1.25 * module
baseDiameter = pitchDiameter * cos(pressureAngle)
tipDiameter = pitchDiameter + 2 * module
// Using the gear parameters, sketch an involute tooth spanning from the base diameter to the tip diameter
gearSketch = startSketchOn(XY)
|> startProfile(at = polar(angle = 0, length = baseDiameter / 2))
|> involuteCircular(
startRadius = baseDiameter / 2,
endRadius = tipDiameter / 2,
angle = 0,
tag = $seg01,
)
|> line(endAbsolute = polar(angle = 160 / nTeeth, length = tipDiameter / 2))
|> involuteCircular(
startRadius = baseDiameter / 2,
endRadius = tipDiameter / 2,
angle = -atan(segEndY(seg01) / segEndX(seg01)) - (180 / nTeeth),
reverse = true,
)
// Position the end line of the sketch at the start of the next tooth
|> line(endAbsolute = polar(angle = 360 / nTeeth, length = baseDiameter / 2))
// Pattern the sketch about the center by the specified number of teeth, then close the sketch
|> patternCircular2d(
%,
instances = nTeeth,
center = [0, 0],
arcDegrees = 360,
rotateDuplicates = true,
)
|> close()
// Subtract a 10mm diameter center hole from the gear
|> subtract2d(tool = circle(center = [0, 0], radius = 5))
// Extrude the gear to the specified height
|> extrude(length = gearHeight)
return gearSketch
}
// Model a small gear
spurGear(
nTeeth = 17,
module = 1.5,
pressureAngle = 14,
gearHeight = 9,
)
// Model a larger gear with the same module
spurGear(
nTeeth = 51,
module = 1.5,
pressureAngle = 14,
gearHeight = 7,
)
// Translate the larger gear by the combined pitch radius of both gears, plus a small gap
|> translate(x = (51 + 17) / 2 * 1.5 + 1.3)
// Rotate the gear so that the teeth mesh but do not intersect
|> rotate(yaw = 3)

View File

@ -0,0 +1,116 @@
// Surgical Drill Guide
// A surgical drill guide is a tool used in medical procedures to assist in drilling holes to a desired depth, ensuring proper orientation and minimizing intraosseal pressure
// Set units
@settings(defaultLengthUnit = mm)
// Define parameters
handleLength = 150
handleWidth = 30
stockThickness = 6
bendRadius = stockThickness * 1.25
bitSize01 = 2
bitSize02 = 3.2
bitLength = 45
// Model a small sheet metal bracket to represent the handle of the drill guide
bracket = startSketchOn(YZ)
|> startProfile(at = [0, 0])
|> xLine(length = handleLength, tag = $seg02)
|> yLine(length = stockThickness, tag = $seg06)
|> xLine(length = -segLen(seg02), tag = $seg04)
|> tangentialArc(angle = -60, radius = bendRadius, tag = $seg01)
|> angledLine(angle = tangentToEnd(seg01), length = handleLength / 3, tag = $seg03)
|> angledLine(angle = tangentToEnd(seg01) + 90, length = stockThickness, tag = $seg05)
|> angledLine(angle = segAng(seg03) + 180, length = segLen(seg03), tag = $seg07)
|> tangentialArc(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
|> extrude(
length = handleWidth,
symmetric = true,
tagEnd = $capEnd001,
tagStart = $capStart001,
)
// Create a cut in the bracket to mount the first bit
bitCut01 = startSketchOn(XZ)
|> circle(center = [0, segEndY(seg03) + .1], radius = handleWidth / 1.9)
|> extrude(length = 100)
// Create a cut in the bracket to mount the second bit
bitCut02 = startSketchOn(offsetPlane(XY, offset = 35))
|> circle(center = [0, segEndX(seg02)], radius = handleWidth / 1.9)
|> extrude(length = -100)
// Cut the bracket
handle = subtract([bracket], tools = union([bitCut01, bitCut02]))
// Model the support for the first drill bit
bitSupport01 = startSketchOn(offsetPlane(XZ, offset = -segEndX(seg03) - 3))
|> circle(center = [0, segEndY(seg03) + .1], radius = handleWidth / 1.9)
|> extrude(length = -15, symmetric = true)
// Model the stem for the first drill bit
stem01 = startSketchOn(bitSupport01, face = END)
|> circle(center = [0, segEndY(seg03) + .1], radius = bitSize01, tag = $seg10)
|> extrude(length = bitLength, tagEnd = $capEnd004)
|> chamfer(
length = bitSize01 / 3,
tags = [
getCommonEdge(faces = [seg10, capEnd004])
],
)
// Negative extrude the clearance hole for the first drill bit
bitClearance01 = startSketchOn(stem01, face = END)
|> circle(center = [0, segEndY(seg03) + .1], radius = bitSize01 / 2)
|> extrude(length = -15 - bitLength)
// Model a rotating grip for the first drill bit
grip01 = startSketchOn(offsetPlane(XZ, offset = -segEndX(seg03) + 16))
|> circle(center = [0, segEndY(seg03) + .1], radius = handleWidth / 1.85, tag = $seg11)
|> subtract2d(tool = circle(center = [0, segEndY(seg03) + .1], radius = bitSize01))
|> extrude(length = -10, tagEnd = $capEnd005, tagStart = $capStart003)
|> fillet(
radius = 1,
tags = [
getCommonEdge(faces = [seg11, capEnd005]),
getCommonEdge(faces = [seg11, capStart003])
],
)
|> appearance(color = "#af7b23")
// Model the support for the second drill bit
bitSupport02 = startSketchOn(offsetPlane(XY, offset = -2))
|> circle(center = [0, segEndX(seg02)], radius = handleWidth / 1.9)
|> extrude(length = 15)
// Model the stem for the second drill bit
stem02 = startSketchOn(bitSupport02, face = START)
|> circle(center = [0, segEndX(seg02)], radius = bitSize02, tag = $seg09)
|> extrude(length = bitLength, tagEnd = $capEnd003)
|> chamfer(
length = bitSize02 / 3,
tags = [
getCommonEdge(faces = [seg09, capEnd003])
],
)
// Negative extrude the clearance hole for the second drill bit
bitClearance02 = startSketchOn(stem02, face = END)
|> circle(center = [0, segEndX(seg02)], radius = bitSize02 / 2)
|> extrude(length = -15 - bitLength)
// Model a rotating grip for the second drill bit
grip02 = startSketchOn(offsetPlane(XY, offset = -3))
|> circle(center = [0, segEndX(seg02)], radius = handleWidth / 1.85, tag = $seg08)
|> subtract2d(tool = circle(center = [0, segEndX(seg02)], radius = bitSize02))
|> extrude(length = -10, tagStart = $capStart002, tagEnd = $capEnd002)
|> fillet(
radius = 1,
tags = [
getCommonEdge(faces = [seg08, capStart002]),
getCommonEdge(faces = [seg08, capEnd002])
],
)
|> appearance(color = "#23af93")

View File

@ -0,0 +1,167 @@
// Tooling Nest Block
// A tooling nest block is a block-shaped tool made from high-carbon steel. It features an assortment of conical or hemispherical indentions, which are used to form or shape metal, particularly in crafting bells or jewelry
// Set units
@settings(defaultLengthUnit = mm)
// Define parameters
sideLength = 50
size01 = 15
size02 = 10
size03 = 6
size04 = 0.375in
size05 = 0.25in
size06 = 0.5in
size07 = 0.75in
size08 = 5
size09 = 4.5
size10 = 4
size11 = 3.5
size12 = 3
size13 = 2.5
size14 = 2
size15 = 1
// Sketch and extrude the base cube
cubeSketch = startSketchOn(XY)
|> startProfile(at = [0, 0])
|> angledLine(angle = 0, length = sideLength, tag = $rectangleSegmentA001)
|> angledLine(angle = segAng(rectangleSegmentA001) + 90, length = sideLength, tag = $rectangleSegmentB001)
|> angledLine(angle = segAng(rectangleSegmentA001), length = -segLen(rectangleSegmentA001), tag = $rectangleSegmentC001)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $rectangleSegmentD001)
|> close()
cubeExtrude = extrude(cubeSketch, length = sideLength)
// Write a function to create a hemispherical nest in a given cube side
fn nest(cubeFace, xPos, yPos, nestSize) {
nestFn = startSketchOn(cubeExtrude, face = cubeFace)
|> circle(center = [xPos * sideLength, yPos * sideLength], radius = nestSize, tag = $seg01)
|> extrude(length = -nestSize, tagStart = $capStart001)
|> fillet(
radius = nestSize * .99,
tags = [
getCommonEdge(faces = [seg01, capStart001])
],
)
return { }
}
// Model each nest on the top face
nest(
cubeFace = END,
xPos = 0.5,
yPos = 0.5,
nestSize = size01,
)
// Model each nest on side 1
nest(
cubeFace = rectangleSegmentA001,
xPos = 0.65,
yPos = 0.5,
nestSize = size02,
)
nest(
cubeFace = rectangleSegmentA001,
xPos = 0.25,
yPos = 0.25,
nestSize = size03,
)
nest(
cubeFace = rectangleSegmentA001,
xPos = 0.25,
yPos = 0.75,
nestSize = size03,
)
// Model each nest on side 2
nest(
cubeFace = rectangleSegmentB001,
xPos = 0.7,
yPos = 0.3,
nestSize = size04,
)
nest(
cubeFace = rectangleSegmentB001,
xPos = 0.25,
yPos = 0.3,
nestSize = size05,
)
nest(
cubeFace = rectangleSegmentB001,
xPos = 0.25,
yPos = 0.7,
nestSize = size05,
)
nest(
cubeFace = rectangleSegmentB001,
xPos = 0.7,
yPos = 0.7,
nestSize = size05,
)
// Model each nest on side 3
nest(
cubeFace = rectangleSegmentC001,
xPos = -0.5,
yPos = 0.5,
nestSize = size06,
)
// Model each nest on side 4
nest(
cubeFace = rectangleSegmentD001,
xPos = -0.2,
yPos = 0.2,
nestSize = size15,
)
nest(
cubeFace = rectangleSegmentD001,
xPos = -0.2,
yPos = 0.5,
nestSize = size14,
)
nest(
cubeFace = rectangleSegmentD001,
xPos = -0.2,
yPos = 0.8,
nestSize = size13,
)
nest(
cubeFace = rectangleSegmentD001,
xPos = -0.8,
yPos = 0.2,
nestSize = size12,
)
nest(
cubeFace = rectangleSegmentD001,
xPos = -0.8,
yPos = 0.5,
nestSize = size10,
)
nest(
cubeFace = rectangleSegmentD001,
xPos = -0.8,
yPos = 0.8,
nestSize = size08,
)
nest(
cubeFace = rectangleSegmentD001,
xPos = -0.5,
yPos = 0.33,
nestSize = size09,
)
nest(
cubeFace = rectangleSegmentD001,
xPos = -0.5,
yPos = 0.67,
nestSize = size11,
)
// Model each nest on the bottom face
nest(
cubeFace = START,
xPos = -0.5,
yPos = 0.5,
nestSize = size07,
)

View File

@ -9,7 +9,10 @@ import antennaLength, antennaBaseWidth, antennaBaseHeight, antennaTopWidth, ante
// Create the antenna base sketch
antennaBaseSketch = startSketchOn(XY)
|> startProfile(at = [0, 0])
|> startProfile(at = [
-antennaBaseWidth / 2,
antennaBaseHeight / 2
])
|> line(end = [antennaBaseWidth, 0])
|> line(end = [0, -antennaBaseHeight])
|> line(end = [-antennaBaseWidth, 0])
@ -19,7 +22,7 @@ antennaBaseSketch = startSketchOn(XY)
loftPlane = offsetPlane(XY, offset = antennaLength)
antennaTopSketch = startSketchOn(loftPlane)
|> startProfile(at = [
(antennaBaseWidth - antennaTopWidth) / 2,
-(antennaBaseWidth - antennaTopWidth) / 2,
(antennaBaseHeight - antennaTopHeight) / 2
])
|> xLine(length = antennaTopWidth)

View File

@ -5,15 +5,11 @@
@settings(defaultLengthUnit = in, kclVersion = 1.0)
// Import parameters
import width, thickness, height, knobDiameter, knobHeight, knobRadius from "parameters.kcl"
import width, thickness, height, knobDiameter, knobHeight, knobFilletRadius from "parameters.kcl"
// Create the knob sketch and revolve
startSketchOn(XZ)
|> startProfile(at = [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)
startSketchOn(XY)
|> circle(center = [0, 0], radius = knobDiameter / 2, tag = $knobBend)
|> extrude(%, length = knobHeight)
|> fillet(radius = knobFilletRadius, tags = [getOppositeEdge(knobBend)])
|> appearance(%, color = "#afbf36")

View File

@ -20,7 +20,7 @@ body
// Import the antenna
antenna
|> translate(x = -width / 2 + .45, y = -0.10, z = height / 2)
|> translate(x = -width / 2 + .60, y = -0.20, z = height / 2)
// Import the case
case

View File

@ -19,9 +19,9 @@ export speakerBoxHeight = 1.25
// antenna
export antennaBaseWidth = .5
export antennaBaseHeight = .25
export antennaTopWidth = .30
export antennaTopHeight = .05
export antennaLength = 3
export antennaTopWidth = antennaBaseWidth * .5
export antennaTopHeight = antennaBaseHeight * .5
export antennaLength = 2
// button
export buttonWidth = .15
@ -36,7 +36,7 @@ export caseTolerance = 0.010
// knob
export knobDiameter = .5
export knobHeight = .25
export knobRadius = 0.050
export knobFilletRadius = 0.050
// talk-button
export talkButtonSideLength = 0.5

View File

@ -0,0 +1,121 @@
// Wing Spar
// In a fixed-wing aircraft, the spar is often the main structural member of the wing, running spanwise at right angles (or thereabouts depending on wing sweep) to the fuselage. The spar carries flight loads and the weight of the wings while on the ground. Other structural and forming members such as ribs may be attached to the spars
// Set units
@settings(defaultLengthUnit = mm)
// Define parameters
chordLength = 355
rearSpar = 205
frontSpar = 33
upperCamber = 30
lowerCamber = 18
foilThickness = 8
nSections = 5
sparSpan = 700
sparStockThicknes = 2.102
sparBendRadius = 2.102
// Sketch an airfoil using the chord length, spar positions, and camber heights
ribSketch = startSketchOn(offsetPlane(-XZ, offset = -foilThickness))
|> startProfile(at = [chordLength, 0])
|> line(endAbsolute = [rearSpar, upperCamber])
|> tangentialArc(endAbsolute = [frontSpar, upperCamber * 1.3])
|> tangentialArc(endAbsolute = [0, 0])
|> tangentialArc(angle = 76, radius = lowerCamber)
|> tangentialArc(endAbsolute = [rearSpar, -lowerCamber])
|> tangentialArc(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
// Cut circular holes along the chord curve of the airfoil to reduce the mass of each part
|> subtract2d(tool = circle(center = [62, 9], radius = 17))
|> subtract2d(tool = circle(center = [113, 10], radius = 19))
|> subtract2d(tool = circle(center = [164, 9], radius = 17))
|> subtract2d(tool = circle(center = [228, 5], radius = 11))
|> subtract2d(tool = circle(center = [260, 3.5], radius = 6.5))
// Extrude the airfoil to material thicknes, then pattern along the length of the wing spars
|> extrude(length = -foilThickness)
|> patternLinear3d(instances = nSections, distance = (sparSpan - (3 * foilThickness)) / (nSections - 1), axis = [0, -1, 0])
// Model a thin sheet spar with a hemmed top edge for structure
sparSketch = startSketchOn(-XZ)
// Sketch the sheet metal profile for the front spar, then extrude
frontSparProfile = startProfile(sparSketch, at = [frontSpar, -lowerCamber * 0.85])
|> yLine(endAbsolute = upperCamber, tag = $seg01)
|> tangentialArc(angle = -90, radius = sparBendRadius + sparStockThicknes)
|> xLine(length = 4, tag = $seg02)
|> tangentialArc(angle = -90, radius = sparBendRadius + sparStockThicknes)
|> yLine(length = -4, tag = $seg03)
|> tangentialArc(angle = -90, radius = sparBendRadius + sparStockThicknes)
|> xLine(length = -3, tag = $seg04)
|> yLine(length = sparStockThicknes)
|> xLine(length = segLen(seg04))
|> tangentialArc(angle = 90, radius = sparBendRadius)
|> yLine(length = segLen(seg03))
|> tangentialArc(angle = 90, radius = sparBendRadius)
|> xLine(length = -segLen(seg02))
|> tangentialArc(angle = 90, radius = sparBendRadius)
|> yLine(length = -segLen(seg01), tag = $seg10)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
|> extrude(length = -sparSpan)
// Sketch the sheet metal profile for the rear spar, then extrude
rearSparProfile = startProfile(sparSketch, at = [rearSpar, -lowerCamber * 0.7])
|> yLine(endAbsolute = upperCamber * 0.7, tag = $seg05)
|> tangentialArc(angle = 90, radius = sparBendRadius + sparStockThicknes)
|> xLine(length = -4, tag = $seg06)
|> tangentialArc(angle = 90, radius = sparBendRadius + sparStockThicknes)
|> yLine(length = -4, tag = $seg07)
|> tangentialArc(angle = 90, radius = sparBendRadius + sparStockThicknes)
|> xLine(length = 3, tag = $seg08)
|> yLine(length = sparStockThicknes)
|> xLine(length = -segLen(seg08))
|> tangentialArc(angle = -90, radius = sparBendRadius)
|> yLine(length = segLen(seg07))
|> tangentialArc(angle = -90, radius = sparBendRadius)
|> xLine(length = segLen(seg06))
|> tangentialArc(angle = -90, radius = sparBendRadius)
|> yLine(length = -segLen(seg05), tag = $seg09)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
|> extrude(length = -sparSpan)
// Cut rectangular holes along the spar length between each rib
frontSparHoles = startSketchOn(frontSparProfile, face = seg10)
|> startProfile(at = [-lowerCamber * 0.1, -foilThickness * 3])
|> xLine(endAbsolute = upperCamber * 0.4, tag = $seg11)
|> tangentialArc(angle = -90, radius = 5)
|> yLine(endAbsolute = -(sparSpan - (3 * foilThickness)) / (nSections - 1) + 5, tag = $seg12)
|> tangentialArc(angle = -90, radius = 5)
|> xLine(length = -segLen(seg11))
|> tangentialArc(angle = -90, radius = 5)
|> yLine(length = segLen(seg12))
|> tangentialArc(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
|> patternLinear2d(
%,
instances = nSections - 1,
distance = (sparSpan - (3 * foilThickness)) / (nSections - 1),
axis = [0, -1],
)
|> extrude(length = -10)
rearSparHoles = startSketchOn(rearSparProfile, face = seg09)
|> startProfile(at = [-lowerCamber * 0.3, -foilThickness * 3])
|> xLine(endAbsolute = -upperCamber * 0.01, tag = $seg14)
|> tangentialArc(angle = -90, radius = 5)
|> yLine(length = -segLen(seg12))
|> tangentialArc(angle = -90, radius = 5)
|> xLine(length = -segLen(seg14))
|> tangentialArc(angle = -90, radius = 5)
|> yLine(length = segLen(seg12))
|> tangentialArc(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
|> patternLinear2d(
%,
instances = nSections - 1,
distance = (sparSpan - (3 * foilThickness)) / (nSections - 1),
axis = [0, -1],
)
|> extrude(length = -10)

4
rust/Cargo.lock generated
View File

@ -2080,9 +2080,9 @@ dependencies = [
[[package]]
name = "kittycad-modeling-cmds"
version = "0.2.117"
version = "0.2.120"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6b8c7b34292486704ebd6339709f0bcef821d1926a0edfc0db30837646e7b8d"
checksum = "48b71e06ee5d711d0085864a756fb6a304531246689ea00c6ef5d740670c3701"
dependencies = [
"anyhow",
"chrono",

View File

@ -36,7 +36,7 @@ dashmap = { version = "6.1.0" }
http = "1"
indexmap = "2.9.0"
kittycad = { version = "0.3.37", default-features = false, features = ["js", "requests"] }
kittycad-modeling-cmds = { version = "0.2.117", features = ["ts-rs", "websocket"] }
kittycad-modeling-cmds = { version = "0.2.120", features = ["ts-rs", "websocket"] }
lazy_static = "1.5.0"
miette = "7.5.0"
pyo3 = { version = "0.24.1" }

View File

@ -100,19 +100,22 @@ fn do_for_each_std_mod(item: proc_macro2::TokenStream) -> proc_macro2::TokenStre
let filename = e.file_name();
filename.to_str().unwrap().strip_suffix(".kcl").map(str::to_owned)
}) {
for i in 0..10_usize {
let mut item = item.clone();
item.sig.ident = syn::Ident::new(&format!("{}_{}", item.sig.ident, name), Span::call_site());
item.sig.ident = syn::Ident::new(&format!("{}_{}_shard_{i}", item.sig.ident, name), Span::call_site());
let stmts = &item.block.stmts;
//let name = format!("\"{name}\"");
let block = quote! {
{
const STD_MOD_NAME: &str = #name;
const SHARD: usize = #i;
const SHARD_COUNT: usize = 10;
#(#stmts)*
}
};
item.block = Box::new(syn::parse2(block).unwrap());
result.extend(Some(item.into_token_stream()));
}
}
result
}

View File

@ -1,53 +0,0 @@
d_wrist_circumference = [22.8, 10.7, 16.4, 18.5]
width = d_wrist_circumference[0] + d_wrist_circumference[1] + d_wrist_circumference[2] + d_wrist_circumference[3]
length = 120.0
hand_thickness = 24.0
corner_radius = 5.0
// At first I thought this was going to be symmetric,
// but I measured intentionally to not be symmetric,
// because your wrist isn't a perfect cylindrical surface
brace_base = startSketchOn(XY)
|> startProfile(at = [corner_radius, 0])
|> line(end = [width - corner_radius, 0.0])
|> tangentialArc(end = [corner_radius, corner_radius])
|> yLine(length = 25.0 - corner_radius)
|> tangentialArc(end = [-corner_radius, corner_radius])
|> xLine(length = -(d_wrist_circumference[0] - (corner_radius * 2)))
|> tangentialArc(end = [-corner_radius, corner_radius])
|> yLine(length = length - 25.0 - 23.0 - (corner_radius * 2))
|> tangentialArc(end = [corner_radius, corner_radius])
|> xLine(length = 15.0 - (corner_radius * 2))
|> tangentialArc(end = [corner_radius, corner_radius])
|> yLine(length = 23.0 - corner_radius)
|> tangentialArc(end = [-corner_radius, corner_radius])
|> xLine(length = -(hand_thickness + 15.0 + 15.0 - (corner_radius * 2)))
|> tangentialArc(end = [-corner_radius, -corner_radius])
|> yLine(length = -(23.0 - corner_radius))
|> tangentialArc(end = [corner_radius, -corner_radius])
|> xLine(length = 15.0 - (corner_radius * 2))
|> tangentialArc(end = [corner_radius, -corner_radius])
|> yLine(length = -(length - 25.0 - 23.0 - (corner_radius * 2)))
|> tangentialArc(end = [-corner_radius, -corner_radius])
|> xLine(length = -(d_wrist_circumference[1] + d_wrist_circumference[2] + d_wrist_circumference[3] - hand_thickness - corner_radius))
|> tangentialArc(end = [-corner_radius, -corner_radius])
|> yLine(length = -(25.0 - corner_radius))
|> tangentialArc(end = [corner_radius, -corner_radius])
|> close()
inner = startSketchOn(XY)
|> startProfile(at = [0, 0])
|> xLine(length = 1.0)
|> tangentialArc(end = [corner_radius, corner_radius])
|> yLine(length = 25.0 - (corner_radius * 2))
|> tangentialArc(end = [-corner_radius, corner_radius])
|> xLine(length = -1.0)
|> tangentialArc(end = [-corner_radius, -corner_radius])
|> yLine(length = -(25.0 - (corner_radius * 2)))
|> tangentialArc(end = [corner_radius, -corner_radius])
|> close()
final = brace_base
|> subtract2d(tool = inner)
|> extrude(length = 3.0)

View File

@ -22,47 +22,6 @@ pub(crate) fn assert_out(test_name: &str, result: &image::DynamicImage) -> Strin
path
}
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_fillet_duplicate_tags() {
let code = kcl_input!("fillet_duplicate_tags");
let result = execute_and_snapshot(code, None).await;
let err = result.expect_err("Code should have failed due to the duplicate edges being filletted");
let err = err.as_kcl_error().unwrap();
assert_eq!(
err.message(),
"The same edge ID is being referenced multiple times, which is not allowed. Please select a different edge"
);
assert_eq!(err.source_ranges().len(), 3);
}
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_execute_engine_error_return() {
let code = r#"part001 = startSketchOn(XY)
|> startProfile(at = [5.5229, 5.25217])
|> line(end = [10.50433, -1.19122])
|> line(end = [8.01362, -5.48731])
|> line(end = [-1.02877, -6.76825])
|> line(end = [-11.53311, 2.81559])
|> extrude(length = 4)
"#;
let result = execute_and_snapshot(code, None).await;
let expected_msg = "engine: Modeling command failed: [ApiError { error_code: BadRequest, message: \"The path is not closed. Solid2D construction requires a closed path!\" }]";
let err = result.unwrap_err().as_kcl_error().unwrap().get_message();
assert_eq!(err, expected_msg);
}
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_execute_i_shape() {
// This is some code from lee that starts a pipe expression with a variable.
let code = kcl_input!("i_shape");
let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("i_shape", &result);
}
#[tokio::test(flavor = "multi_thread")]
#[ignore] // No longer a stack overflow problem, instead it causes an engine internal error.
async fn kcl_test_execute_pipes_on_pipes() {
@ -1094,20 +1053,6 @@ sketch001 = startSketchOn(box, face = END)
assert_out("revolve_on_face", &result);
}
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_basic_revolve_circle() {
let code = r#"sketch001 = startSketchOn(XY)
|> circle(center = [15, 0], radius= 5)
|> revolve(
angle = 360,
axis = Y
)
"#;
let result = execute_and_snapshot(code, None).await.unwrap();
assert_out("basic_revolve_circle", &result);
}
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_simple_revolve_sketch_on_edge() {
let code = r#"part001 = startSketchOn(XY)
@ -1941,27 +1886,6 @@ someFunction('INVALID')
);
}
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_error_inside_fn_also_has_source_range_of_call_site_recursive() {
let code = r#"fn someFunction(@something) {
fn someNestedFunction(@something2) {
startSketchOn(something2)
}
someNestedFunction(something)
}
someFunction('INVALID')
"#;
let result = execute_and_snapshot(code, None).await;
assert!(result.is_err());
assert_eq!(
result.err().unwrap().to_string(),
r#"semantic: KclErrorDetails { source_ranges: [SourceRange([93, 103, 0]), SourceRange([116, 145, 0]), SourceRange([149, 172, 0])], message: "This function expected the input argument to be Solid or Plane but it's actually of type string (text)" }"#
);
}
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_error_no_auth_websocket() {
let code = r#"sketch001 = startSketchOn(XZ)

View File

@ -1,5 +1,6 @@
use std::{collections::HashMap, fmt, str::FromStr};
use std::{fmt, str::FromStr};
use indexmap::IndexMap;
use regex::Regex;
use tower_lsp::lsp_types::{
CompletionItem, CompletionItemKind, CompletionItemLabelDetails, Documentation, InsertTextFormat, MarkupContent,
@ -449,7 +450,7 @@ pub struct ModData {
pub description: Option<String>,
pub module_name: String,
pub children: HashMap<String, DocData>,
pub children: IndexMap<String, DocData>,
}
impl ModData {
@ -465,7 +466,7 @@ impl ModData {
qual_name,
summary: None,
description: None,
children: HashMap::new(),
children: IndexMap::new(),
module_name,
}
}
@ -1236,23 +1237,21 @@ mod test {
.expect_mod()
};
#[allow(clippy::iter_over_hash_type)]
let mut count = 0;
for d in data.children.values() {
if let DocData::Mod(_) = d {
continue;
}
for (i, eg) in d.examples().enumerate() {
count += 1;
if count % SHARD_COUNT != SHARD {
continue;
}
let result = match crate::test_server::execute_and_snapshot(eg, None).await {
Err(crate::errors::ExecError::Kcl(e)) => {
errs.push(
miette::Report::new(crate::errors::Report {
error: e.error,
filename: format!("{}{i}", d.name()),
kcl_source: eg.to_string(),
})
.to_string(),
);
errs.push(format!("Error testing example {}{i}: {}", d.name(), e.error.message()));
continue;
}
Err(other_err) => panic!("{}", other_err),

View File

@ -313,6 +313,9 @@ pub struct SweepEdge {
pub sub_type: SweepEdgeSubType,
pub seg_id: ArtifactId,
pub cmd_id: uuid::Uuid,
// This is only used for sorting, not for the actual artifact.
#[serde(skip)]
pub index: usize,
pub sweep_id: ArtifactId,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub common_surface_ids: Vec<ArtifactId>,
@ -438,6 +441,9 @@ impl PartialOrd for Artifact {
if a.cmd_id != b.cmd_id {
return Some(a.cmd_id.cmp(&b.cmd_id));
}
if a.index != b.index {
return Some(a.index.cmp(&b.index));
}
Some(a.id.cmp(&b.id))
}
(Artifact::EdgeCut(a), Artifact::EdgeCut(b)) => {
@ -750,12 +756,31 @@ pub(super) fn build_artifact_graph(
}
for exec_artifact in exec_artifacts.values() {
merge_artifact_into_map(&mut map, exec_artifact.clone());
let mut new_artifact = exec_artifact.clone();
// Fill in NodePaths for artifacts that were added directly to the map
// during execution.
fill_in_node_paths(&mut new_artifact, ast);
merge_artifact_into_map(&mut map, new_artifact);
}
Ok(ArtifactGraph { map })
}
/// These may have been created with placeholder `CodeRef`s because we didn't
/// have the entire AST available. Now we fill them in.
fn fill_in_node_paths(artifact: &mut Artifact, program: &Node<Program>) {
match artifact {
Artifact::StartSketchOnFace(face) => {
face.code_ref.node_path = NodePath::from_range(program, face.code_ref.range).unwrap_or_default();
}
Artifact::StartSketchOnPlane(plane) => {
plane.code_ref.node_path = NodePath::from_range(program, plane.code_ref.range).unwrap_or_default();
}
_ => {}
}
}
/// Flatten the responses into a map of command IDs to modeling command
/// responses. The raw responses from the engine contain batches.
fn flatten_modeling_command_responses(
@ -1182,90 +1207,93 @@ fn artifacts_to_update(
}
return Ok(return_arr);
}
ModelingCmd::Solid3dGetNextAdjacentEdge(kcmc::Solid3dGetNextAdjacentEdge { face_id, edge_id, .. })
| ModelingCmd::Solid3dGetOppositeEdge(kcmc::Solid3dGetOppositeEdge { face_id, edge_id, .. }) => {
let sub_type = match cmd {
ModelingCmd::Solid3dGetNextAdjacentEdge(_) => SweepEdgeSubType::Adjacent,
ModelingCmd::Solid3dGetOppositeEdge(_) => SweepEdgeSubType::Opposite,
_ => unreachable!(),
};
let face_id = ArtifactId::new(*face_id);
let edge_id = ArtifactId::new(*edge_id);
let Some(Artifact::Wall(wall)) = artifacts.get(&face_id) else {
ModelingCmd::Solid3dGetAdjacencyInfo(kcmc::Solid3dGetAdjacencyInfo { .. }) => {
let OkModelingCmdResponse::Solid3dGetAdjacencyInfo(info) = response else {
return Ok(Vec::new());
};
let Some(Artifact::Sweep(sweep)) = artifacts.get(&wall.sweep_id) else {
return Ok(Vec::new());
};
let Some(Artifact::Path(_)) = artifacts.get(&sweep.path_id) else {
return Ok(Vec::new());
};
let Some(Artifact::Segment(segment)) = artifacts.get(&edge_id) else {
return Ok(Vec::new());
};
let response_edge_id = match response {
OkModelingCmdResponse::Solid3dGetNextAdjacentEdge(r) => {
let Some(edge_id) = r.edge else {
return Err(KclError::Internal(KclErrorDetails {
message:format!(
"Expected Solid3dGetNextAdjacentEdge response to have an edge ID, but found none: id={id:?}, {response:?}"
),
source_ranges: vec![range],
}));
};
edge_id.into()
}
OkModelingCmdResponse::Solid3dGetOppositeEdge(r) => r.edge.into(),
_ => {
return Err(KclError::Internal(KclErrorDetails {
message:format!(
"Expected Solid3dGetNextAdjacentEdge or Solid3dGetOppositeEdge response, but got: id={id:?}, {response:?}"
),
source_ranges: vec![range],
}));
}
};
let mut return_arr = Vec::new();
return_arr.push(Artifact::SweepEdge(SweepEdge {
id: response_edge_id,
sub_type,
seg_id: edge_id,
cmd_id: artifact_command.cmd_id,
sweep_id: sweep.id,
common_surface_ids: Vec::new(),
}));
let mut new_segment = segment.clone();
new_segment.edge_ids = vec![response_edge_id];
return_arr.push(Artifact::Segment(new_segment));
let mut new_sweep = sweep.clone();
new_sweep.edge_ids = vec![response_edge_id];
return_arr.push(Artifact::Sweep(new_sweep));
return Ok(return_arr);
}
ModelingCmd::Solid3dGetAllEdgeFaces(kcmc::Solid3dGetAllEdgeFaces { edge_id, .. }) => {
let OkModelingCmdResponse::Solid3dGetAllEdgeFaces(faces) = response else {
return Ok(Vec::new());
for (index, edge) in info.edges.iter().enumerate() {
let Some(original_info) = &edge.original_info else {
continue;
};
let edge_id = ArtifactId::new(*edge_id);
let edge_id = ArtifactId::new(original_info.edge_id);
let Some(artifact) = artifacts.get(&edge_id) else {
return Ok(Vec::new());
continue;
};
let mut return_arr = Vec::new();
match artifact {
Artifact::Segment(segment) => {
let mut new_segment = segment.clone();
new_segment.common_surface_ids = faces.faces.iter().map(|face| ArtifactId::new(*face)).collect();
new_segment.common_surface_ids =
original_info.faces.iter().map(|face| ArtifactId::new(*face)).collect();
return_arr.push(Artifact::Segment(new_segment));
}
Artifact::SweepEdge(sweep_edge) => {
let mut new_sweep_edge = sweep_edge.clone();
new_sweep_edge.common_surface_ids = faces.faces.iter().map(|face| ArtifactId::new(*face)).collect();
new_sweep_edge.common_surface_ids =
original_info.faces.iter().map(|face| ArtifactId::new(*face)).collect();
return_arr.push(Artifact::SweepEdge(new_sweep_edge));
}
_ => {}
};
let Some(Artifact::Segment(segment)) = artifacts.get(&edge_id) else {
continue;
};
let Some(surface_id) = segment.surface_id else {
continue;
};
let Some(Artifact::Wall(wall)) = artifacts.get(&surface_id) else {
continue;
};
let Some(Artifact::Sweep(sweep)) = artifacts.get(&wall.sweep_id) else {
continue;
};
let Some(Artifact::Path(_)) = artifacts.get(&sweep.path_id) else {
continue;
};
if let Some(opposite_info) = &edge.opposite_info {
return_arr.push(Artifact::SweepEdge(SweepEdge {
id: opposite_info.edge_id.into(),
sub_type: SweepEdgeSubType::Opposite,
seg_id: edge_id,
cmd_id: artifact_command.cmd_id,
index,
sweep_id: sweep.id,
common_surface_ids: opposite_info.faces.iter().map(|face| ArtifactId::new(*face)).collect(),
}));
let mut new_segment = segment.clone();
new_segment.edge_ids = vec![opposite_info.edge_id.into()];
return_arr.push(Artifact::Segment(new_segment));
let mut new_sweep = sweep.clone();
new_sweep.edge_ids = vec![opposite_info.edge_id.into()];
return_arr.push(Artifact::Sweep(new_sweep));
let mut new_wall = wall.clone();
new_wall.edge_cut_edge_ids = vec![opposite_info.edge_id.into()];
return_arr.push(Artifact::Wall(new_wall));
}
if let Some(adjacent_info) = &edge.adjacent_info {
return_arr.push(Artifact::SweepEdge(SweepEdge {
id: adjacent_info.edge_id.into(),
sub_type: SweepEdgeSubType::Adjacent,
seg_id: edge_id,
cmd_id: artifact_command.cmd_id,
index,
sweep_id: sweep.id,
common_surface_ids: adjacent_info.faces.iter().map(|face| ArtifactId::new(*face)).collect(),
}));
let mut new_segment = segment.clone();
new_segment.edge_ids = vec![adjacent_info.edge_id.into()];
return_arr.push(Artifact::Segment(new_segment));
let mut new_sweep = sweep.clone();
new_sweep.edge_ids = vec![adjacent_info.edge_id.into()];
return_arr.push(Artifact::Sweep(new_sweep));
let mut new_wall = wall.clone();
new_wall.edge_cut_edge_ids = vec![adjacent_info.edge_id.into()];
return_arr.push(Artifact::Wall(new_wall));
}
}
return Ok(return_arr);
}
ModelingCmd::Solid3dFilletEdge(cmd) => {

View File

@ -298,40 +298,48 @@ impl ArtifactGraph {
let range = code_ref.range;
[range.start(), range.end(), range.module_id().as_usize()]
}
fn node_path_display<W: Write>(output: &mut W, prefix: &str, code_ref: &CodeRef) -> std::fmt::Result {
// %% is a mermaid comment. Prefix is increased one level since it's
// a child of the line above it.
if code_ref.node_path.is_empty() {
return writeln!(output, "{prefix} %% Missing NodePath");
}
writeln!(output, "{prefix} %% {:?}", code_ref.node_path.steps)
}
match artifact {
Artifact::CompositeSolid(composite_solid) => {
writeln!(
output,
"{prefix}{}[\"CompositeSolid {:?}<br>{:?}\"]",
id,
"{prefix}{id}[\"CompositeSolid {:?}<br>{:?}\"]",
composite_solid.sub_type,
code_ref_display(&composite_solid.code_ref)
)?;
node_path_display(output, prefix, &composite_solid.code_ref)?;
}
Artifact::Plane(plane) => {
writeln!(
output,
"{prefix}{}[\"Plane<br>{:?}\"]",
id,
"{prefix}{id}[\"Plane<br>{:?}\"]",
code_ref_display(&plane.code_ref)
)?;
node_path_display(output, prefix, &plane.code_ref)?;
}
Artifact::Path(path) => {
writeln!(
output,
"{prefix}{}[\"Path<br>{:?}\"]",
id,
"{prefix}{id}[\"Path<br>{:?}\"]",
code_ref_display(&path.code_ref)
)?;
node_path_display(output, prefix, &path.code_ref)?;
}
Artifact::Segment(segment) => {
writeln!(
output,
"{prefix}{}[\"Segment<br>{:?}\"]",
id,
"{prefix}{id}[\"Segment<br>{:?}\"]",
code_ref_display(&segment.code_ref)
)?;
node_path_display(output, prefix, &segment.code_ref)?;
}
Artifact::Solid2d(_solid2d) => {
writeln!(output, "{prefix}{}[Solid2d]", id)?;
@ -339,56 +347,56 @@ impl ArtifactGraph {
Artifact::StartSketchOnFace(StartSketchOnFace { code_ref, .. }) => {
writeln!(
output,
"{prefix}{}[\"StartSketchOnFace<br>{:?}\"]",
id,
"{prefix}{id}[\"StartSketchOnFace<br>{:?}\"]",
code_ref_display(code_ref)
)?;
node_path_display(output, prefix, code_ref)?;
}
Artifact::StartSketchOnPlane(StartSketchOnPlane { code_ref, .. }) => {
writeln!(
output,
"{prefix}{}[\"StartSketchOnPlane<br>{:?}\"]",
id,
"{prefix}{id}[\"StartSketchOnPlane<br>{:?}\"]",
code_ref_display(code_ref)
)?;
node_path_display(output, prefix, code_ref)?;
}
Artifact::Sweep(sweep) => {
writeln!(
output,
"{prefix}{}[\"Sweep {:?}<br>{:?}\"]",
id,
"{prefix}{id}[\"Sweep {:?}<br>{:?}\"]",
sweep.sub_type,
code_ref_display(&sweep.code_ref)
)?;
node_path_display(output, prefix, &sweep.code_ref)?;
}
Artifact::Wall(_wall) => {
writeln!(output, "{prefix}{}[Wall]", id)?;
writeln!(output, "{prefix}{id}[Wall]")?;
}
Artifact::Cap(cap) => {
writeln!(output, "{prefix}{}[\"Cap {:?}\"]", id, cap.sub_type)?;
writeln!(output, "{prefix}{id}[\"Cap {:?}\"]", cap.sub_type)?;
}
Artifact::SweepEdge(sweep_edge) => {
writeln!(output, "{prefix}{}[\"SweepEdge {:?}\"]", id, sweep_edge.sub_type)?;
writeln!(output, "{prefix}{id}[\"SweepEdge {:?}\"]", sweep_edge.sub_type)?;
}
Artifact::EdgeCut(edge_cut) => {
writeln!(
output,
"{prefix}{}[\"EdgeCut {:?}<br>{:?}\"]",
id,
"{prefix}{id}[\"EdgeCut {:?}<br>{:?}\"]",
edge_cut.sub_type,
code_ref_display(&edge_cut.code_ref)
)?;
node_path_display(output, prefix, &edge_cut.code_ref)?;
}
Artifact::EdgeCutEdge(_edge_cut_edge) => {
writeln!(output, "{prefix}{}[EdgeCutEdge]", id)?;
writeln!(output, "{prefix}{id}[EdgeCutEdge]")?;
}
Artifact::Helix(helix) => {
writeln!(
output,
"{prefix}{}[\"Helix<br>{:?}\"]",
id,
"{prefix}{id}[\"Helix<br>{:?}\"]",
code_ref_display(&helix.code_ref)
)?;
node_path_display(output, prefix, &helix.code_ref)?;
}
}
Ok(())

View File

@ -2,9 +2,9 @@
use anyhow::Result;
use crate::execution::typed_path::TypedPath;
use crate::{
errors::{KclError, KclErrorDetails},
execution::typed_path::TypedPath,
fs::FileSystem,
SourceRange,
};

View File

@ -2,8 +2,7 @@
use anyhow::Result;
use crate::execution::typed_path::TypedPath;
use crate::SourceRange;
use crate::{execution::typed_path::TypedPath, SourceRange};
#[cfg(not(target_arch = "wasm32"))]
pub mod local;

View File

@ -11,8 +11,7 @@ use tower_lsp::lsp_types::{
TextDocumentItem, WorkspaceFolder,
};
use crate::execution::typed_path::TypedPath;
use crate::fs::FileSystem;
use crate::{execution::typed_path::TypedPath, fs::FileSystem};
/// A trait for the backend of the language server.
#[async_trait::async_trait]

View File

@ -318,6 +318,10 @@ impl NodePath {
Some(path)
}
pub fn is_empty(&self) -> bool {
self.steps.is_empty()
}
fn push(&mut self, step: Step) {
self.steps.push(step);
}

View File

@ -280,11 +280,11 @@ fn assert_common_snapshots(
let result1 = catch_unwind(AssertUnwindSafe(|| {
assert_snapshot(test, "Operations executed", || {
insta::assert_json_snapshot!("ops", operations, {
"[].unlabeledArg.*.value.**[].from[]" => rounded_redaction(4),
"[].unlabeledArg.*.value.**[].to[]" => rounded_redaction(4),
"[].*.unlabeledArg.value.value" => rounded_redaction(4),
"[].labeledArgs.*.value.**[].from[]" => rounded_redaction(4),
"[].labeledArgs.*.value.**[].to[]" => rounded_redaction(4),
"[].*.unlabeledArg.*.value.**[].from[]" => rounded_redaction(4),
"[].*.unlabeledArg.*.value.**[].to[]" => rounded_redaction(4),
"[].**.value.value" => rounded_redaction(4),
"[].*.labeledArgs.*.value.**[].from[]" => rounded_redaction(4),
"[].*.labeledArgs.*.value.**[].to[]" => rounded_redaction(4),
".**.sourceRange" => Vec::new(),
".**.functionSourceRange" => Vec::new(),
".**.moduleId" => 0,
@ -294,9 +294,10 @@ fn assert_common_snapshots(
let result2 = catch_unwind(AssertUnwindSafe(|| {
assert_snapshot(test, "Artifact commands", || {
insta::assert_json_snapshot!("artifact_commands", artifact_commands, {
"[].command.segment.*.x" => rounded_redaction(4),
"[].command.segment.*.y" => rounded_redaction(4),
"[].command.segment.*.z" => rounded_redaction(4),
"[].command.**.value" => rounded_redaction(4),
"[].command.**.x" => rounded_redaction(4),
"[].command.**.y" => rounded_redaction(4),
"[].command.**.z" => rounded_redaction(4),
".**.range" => Vec::new(),
});
})
@ -312,7 +313,10 @@ fn assert_common_snapshots(
.unwrap_or_else(|e| format!("Failed to convert artifact graph to flowchart: {e}"));
// Change the snapshot suffix so that it is rendered as a Markdown file
// in GitHub.
// Ignore the cpu cooler for now because its being a little bitch.
if test.name == "cpu_cooler" {
insta::assert_binary_snapshot!("artifact_graph_flowchart.md", flowchart.as_bytes().to_owned());
}
})
}));
@ -2767,6 +2771,7 @@ mod clone_w_fillets {
/// Test that KCL is executed correctly.
#[tokio::test(flavor = "multi_thread")]
#[ignore] // turn on when https://github.com/KittyCAD/engine/pull/3380 is merged
async fn kcl_test_execute() {
super::execute(TEST_NAME, true).await
}
@ -2788,6 +2793,7 @@ mod clone_w_shell {
/// Test that KCL is executed correctly.
#[tokio::test(flavor = "multi_thread")]
#[ignore] // turn on when https://github.com/KittyCAD/engine/pull/3380 is merged
async fn kcl_test_execute() {
super::execute(TEST_NAME, true).await
}
@ -2960,3 +2966,108 @@ mod subtract_regression05 {
super::execute(TEST_NAME, true).await
}
}
mod subtract_regression06 {
const TEST_NAME: &str = "subtract_regression06";
/// Test parsing KCL.
#[test]
fn parse() {
super::parse(TEST_NAME)
}
/// Test that parsing and unparsing KCL produces the original KCL input.
#[tokio::test(flavor = "multi_thread")]
async fn unparse() {
super::unparse(TEST_NAME).await
}
/// Test that KCL is executed correctly.
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_execute() {
super::execute(TEST_NAME, true).await
}
}
mod fillet_duplicate_tags {
const TEST_NAME: &str = "fillet_duplicate_tags";
/// Test parsing KCL.
#[test]
fn parse() {
super::parse(TEST_NAME)
}
/// Test that parsing and unparsing KCL produces the original KCL input.
#[tokio::test(flavor = "multi_thread")]
async fn unparse() {
super::unparse(TEST_NAME).await
}
/// Test that KCL is executed correctly.
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_execute() {
super::execute(TEST_NAME, true).await
}
}
mod execute_engine_error_return {
const TEST_NAME: &str = "execute_engine_error_return";
/// Test parsing KCL.
#[test]
fn parse() {
super::parse(TEST_NAME)
}
/// Test that parsing and unparsing KCL produces the original KCL input.
#[tokio::test(flavor = "multi_thread")]
async fn unparse() {
super::unparse(TEST_NAME).await
}
/// Test that KCL is executed correctly.
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_execute() {
super::execute(TEST_NAME, true).await
}
}
mod basic_revolve_circle {
const TEST_NAME: &str = "basic_revolve_circle";
/// Test parsing KCL.
#[test]
fn parse() {
super::parse(TEST_NAME)
}
/// Test that parsing and unparsing KCL produces the original KCL input.
#[tokio::test(flavor = "multi_thread")]
async fn unparse() {
super::unparse(TEST_NAME).await
}
/// Test that KCL is executed correctly.
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_execute() {
super::execute(TEST_NAME, true).await
}
}
mod error_inside_fn_also_has_source_range_of_call_site_recursive {
const TEST_NAME: &str = "error_inside_fn_also_has_source_range_of_call_site_recursive";
/// Test parsing KCL.
#[test]
fn parse() {
super::parse(TEST_NAME)
}
/// Test that parsing and unparsing KCL produces the original KCL input.
#[tokio::test(flavor = "multi_thread")]
async fn unparse() {
super::unparse(TEST_NAME).await
}
/// Test that KCL is executed correctly.
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_execute() {
super::execute(TEST_NAME, true).await
}
}

View File

@ -618,6 +618,7 @@ clonedCube = clone(cube)
// references.
// WITH TAGS AND EDGE CUTS.
#[tokio::test(flavor = "multi_thread")]
#[ignore] // until https://github.com/KittyCAD/engine/pull/3380 lands
async fn kcl_test_clone_solid_with_edge_cuts() {
let code = r#"cube = startSketchOn(XY)
|> startProfile(at = [0,0]) // tag this one

View File

@ -291,85 +291,21 @@ pub(crate) async fn do_post_extrude<'a>(
vec![]
};
// Face filtering attempt in order to resolve https://github.com/KittyCAD/modeling-app/issues/5328
// In case of a sectional sweep, empirically it looks that the first n faces that are yielded from the sweep
// are the ones that work with GetOppositeEdge and GetNextAdjacentEdge, aka the n sides in the sweep.
// So here we're figuring out that n number as yielded_sides_count here,
// making sure that circle() calls count but close() don't (no length)
#[cfg(feature = "artifact-graph")]
let count_of_first_set_of_faces_if_sectional = if sectional {
sketch
.paths
.iter()
.filter(|p| {
let is_circle = matches!(p, Path::Circle { .. });
let has_length = p.get_base().from != p.get_base().to;
is_circle || has_length
})
.count()
} else {
usize::MAX
};
// Only do this if we need the artifact graph.
#[cfg(feature = "artifact-graph")]
for (curve_id, face_id) in face_infos
.iter()
.filter(|face_info| face_info.cap == ExtrusionFaceCapType::None)
.filter_map(|face_info| {
if let (Some(curve_id), Some(face_id)) = (face_info.curve_id, face_info.face_id) {
Some((curve_id, face_id))
} else {
None
}
})
.take(count_of_first_set_of_faces_if_sectional)
{
// Batch these commands, because the Rust code doesn't actually care about the outcome.
// So, there's no need to await them.
// Instead, the Typescript codebases (which handles WebSocket sends when compiled via Wasm)
// uses this to build the artifact graph, which the UI needs.
//
// Spawn this in the background, because we don't care about the result.
// Only the artifact graph needs at the end.
let args_cloned = args.clone();
let opposite_edge_uuid = exec_state.next_uuid();
let next_adjacent_edge_uuid = exec_state.next_uuid();
let get_all_edge_faces_opposite_uuid = exec_state.next_uuid();
let get_all_edge_faces_next_uuid = exec_state.next_uuid();
// Get faces for original edge
// Since this one is batched we can just run it.
// Getting the ids of a sectional sweep does not work well and we cannot guarantee that
// any of these call will not just fail.
if !sectional {
args.batch_modeling_cmd(
exec_state.next_uuid(),
ModelingCmd::from(mcmd::Solid3dGetAllEdgeFaces {
edge_id: curve_id,
ModelingCmd::from(mcmd::Solid3dGetAdjacencyInfo {
object_id: sketch.id,
edge_id: any_edge_id,
}),
)
.await?;
get_bg_edge_info_opposite(
args_cloned.clone(),
curve_id,
sketch.id,
face_id,
opposite_edge_uuid,
get_all_edge_faces_opposite_uuid,
true,
)
.await?;
get_bg_edge_info_next(
args_cloned,
curve_id,
sketch.id,
face_id,
next_adjacent_edge_uuid,
get_all_edge_faces_next_uuid,
true,
)
.await?;
}
}
let Faces {
@ -541,101 +477,3 @@ async fn analyze_faces(exec_state: &mut ExecState, args: &Args, face_infos: Vec<
}
faces
}
#[cfg(feature = "artifact-graph")]
async fn send_fn(args: &Args, id: uuid::Uuid, cmd: ModelingCmd, single_threaded: bool) -> Result<(), KclError> {
if single_threaded {
// In single threaded mode, we can safely batch the command.
args.batch_modeling_cmd(id, cmd).await
} else {
// We cannot batch this call, because otherwise it might batch after say
// a shell that makes this edge no longer relevant.
args.send_modeling_cmd(id, cmd).await.map(|_| ())
}
}
#[cfg(feature = "artifact-graph")]
#[allow(clippy::too_many_arguments)]
async fn get_bg_edge_info_next(
args: Args,
curve_id: uuid::Uuid,
sketch_id: uuid::Uuid,
face_id: uuid::Uuid,
edge_uuid: uuid::Uuid,
get_all_edge_faces_uuid: uuid::Uuid,
single_threaded: bool,
) -> Result<(), KclError> {
let next_adjacent_edge_id = args
.send_modeling_cmd(
edge_uuid,
ModelingCmd::from(mcmd::Solid3dGetNextAdjacentEdge {
edge_id: curve_id,
object_id: sketch_id,
face_id,
}),
)
.await?;
// Get faces for next adjacent edge
if let OkWebSocketResponseData::Modeling {
modeling_response: OkModelingCmdResponse::Solid3dGetNextAdjacentEdge(next_adjacent_edge),
} = next_adjacent_edge_id
{
if let Some(edge_id) = next_adjacent_edge.edge {
send_fn(
&args,
get_all_edge_faces_uuid,
ModelingCmd::from(mcmd::Solid3dGetAllEdgeFaces {
edge_id,
object_id: sketch_id,
}),
single_threaded,
)
.await?;
}
}
Ok(())
}
#[cfg(feature = "artifact-graph")]
#[allow(clippy::too_many_arguments)]
async fn get_bg_edge_info_opposite(
args: Args,
curve_id: uuid::Uuid,
sketch_id: uuid::Uuid,
face_id: uuid::Uuid,
edge_uuid: uuid::Uuid,
get_all_edge_faces_uuid: uuid::Uuid,
single_threaded: bool,
) -> Result<(), KclError> {
let opposite_edge_id = args
.send_modeling_cmd(
edge_uuid,
ModelingCmd::from(mcmd::Solid3dGetOppositeEdge {
edge_id: curve_id,
object_id: sketch_id,
face_id,
}),
)
.await?;
// Get faces for opposite edge
if let OkWebSocketResponseData::Modeling {
modeling_response: OkModelingCmdResponse::Solid3dGetOppositeEdge(opposite_edge),
} = opposite_edge_id
{
send_fn(
&args,
get_all_edge_faces_uuid,
ModelingCmd::from(mcmd::Solid3dGetAllEdgeFaces {
edge_id: opposite_edge.edge,
object_id: sketch_id,
}),
single_threaded,
)
.await?;
}
Ok(())
}

View File

@ -73,7 +73,7 @@ pub async fn loft(exec_state: &mut ExecState, args: Args) -> Result<KclValue, Kc
/// |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
/// |> close()
///
/// loft([squareSketch, triangleSketch])
/// loft([triangleSketch, squareSketch])
/// ```
///
/// ```no_run

View File

@ -387,11 +387,7 @@ async fn send_pattern_transform<T: GeometryTrait>(
modeling_response: OkModelingCmdResponse::EntityLinearPatternTransform(pattern_info),
} = &resp
{
if !pattern_info.entity_ids.is_empty() {
&pattern_info.entity_ids
} else {
&pattern_info.entity_face_edge_ids.iter().map(|x| x.object_id).collect()
}
} else if args.ctx.no_engine_commands().await {
mock_ids.reserve(extra_instances);
for _ in 0..extra_instances {
@ -1341,11 +1337,7 @@ async fn pattern_circular(
modeling_response: OkModelingCmdResponse::EntityCircularPattern(pattern_info),
} = &resp
{
if !pattern_info.entity_ids.is_empty() {
&pattern_info.entity_ids.clone()
} else {
&pattern_info.entity_face_edge_ids.iter().map(|e| e.object_id).collect()
}
} else if args.ctx.no_engine_commands().await {
mock_ids.reserve(num_repetitions as usize);
for _ in 0..num_repetitions {

View File

@ -236,160 +236,7 @@ description: Artifact commands angled_line.kcl
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"type": "solid3d_get_adjacency_info",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
@ -402,125 +249,5 @@ description: Artifact commands angled_line.kcl
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
}
]

View File

@ -2,16 +2,25 @@
flowchart LR
subgraph path2 [Path]
2["Path<br>[33, 65, 0]"]
%% [ProgramBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 1 }]
3["Segment<br>[71, 95, 0]"]
%% [ProgramBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 2 }]
4["Segment<br>[101, 140, 0]"]
%% [ProgramBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 3 }]
5["Segment<br>[146, 172, 0]"]
%% [ProgramBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 4 }]
6["Segment<br>[178, 227, 0]"]
%% [ProgramBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 5 }]
7["Segment<br>[233, 260, 0]"]
%% [ProgramBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 6 }]
8["Segment<br>[266, 273, 0]"]
%% [ProgramBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 7 }]
9[Solid2d]
end
1["Plane<br>[10, 27, 0]"]
%% [ProgramBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 0 }]
10["Sweep Extrusion<br>[279, 298, 0]"]
%% [ProgramBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 8 }]
11[Wall]
12[Wall]
13[Wall]
@ -43,28 +52,28 @@ flowchart LR
2 ---- 10
3 --- 16
3 x--> 17
3 --- 23
3 --- 25
3 --- 24
3 --- 30
4 --- 14
4 x--> 17
4 --- 21
4 --- 27
4 --- 23
4 --- 29
5 --- 13
5 x--> 17
5 --- 19
5 --- 29
5 --- 22
5 --- 28
6 --- 15
6 x--> 17
6 --- 22
6 --- 26
6 --- 21
6 --- 27
7 --- 12
7 x--> 17
7 --- 20
7 --- 30
7 --- 26
8 --- 11
8 x--> 17
8 --- 24
8 --- 28
8 --- 19
8 --- 25
10 --- 11
10 --- 12
10 --- 13
@ -85,24 +94,24 @@ flowchart LR
10 --- 28
10 --- 29
10 --- 30
24 <--x 11
28 <--x 11
30 <--x 11
20 <--x 12
26 <--x 12
30 <--x 12
19 <--x 13
27 <--x 13
11 --- 19
11 --- 25
26 <--x 11
12 --- 20
12 --- 26
27 <--x 12
13 --- 22
13 --- 28
29 <--x 13
21 <--x 14
25 <--x 14
27 <--x 14
22 <--x 15
26 <--x 15
29 <--x 15
23 <--x 16
14 --- 23
14 --- 29
30 <--x 14
15 --- 21
15 --- 27
28 <--x 15
16 --- 24
25 <--x 16
28 <--x 16
16 --- 30
19 <--x 18
20 <--x 18
21 <--x 18

View File

@ -219,106 +219,7 @@ description: Artifact commands artifact_graph_example_code1.kcl
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"type": "solid3d_get_adjacency_info",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
@ -332,86 +233,6 @@ description: Artifact commands artifact_graph_example_code1.kcl
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
@ -569,79 +390,7 @@ description: Artifact commands artifact_graph_example_code1.kcl
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"type": "solid3d_get_adjacency_info",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
@ -654,65 +403,5 @@ description: Artifact commands artifact_graph_example_code1.kcl
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
}
]

View File

@ -2,25 +2,40 @@
flowchart LR
subgraph path3 [Path]
3["Path<br>[35, 62, 0]"]
%% [ProgramBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 1 }]
5["Segment<br>[68, 87, 0]"]
%% [ProgramBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 2 }]
6["Segment<br>[93, 129, 0]"]
%% [ProgramBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 3 }]
7["Segment<br>[135, 169, 0]"]
%% [ProgramBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 4 }]
8["Segment<br>[175, 231, 0]"]
%% [ProgramBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 5 }]
9["Segment<br>[237, 244, 0]"]
%% [ProgramBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 6 }]
15[Solid2d]
end
subgraph path4 [Path]
4["Path<br>[388, 415, 0]"]
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 1 }]
10["Segment<br>[421, 439, 0]"]
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 2 }]
11["Segment<br>[445, 464, 0]"]
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 3 }]
12["Segment<br>[470, 526, 0]"]
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 4 }]
13["Segment<br>[532, 539, 0]"]
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 5 }]
14[Solid2d]
end
1["Plane<br>[12, 29, 0]"]
%% [ProgramBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 0 }]
2["StartSketchOnFace<br>[343, 382, 0]"]
%% Missing NodePath
16["Sweep Extrusion<br>[258, 290, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 0 }]
17["Sweep Extrusion<br>[553, 583, 0]"]
%% [ProgramBodyItem { index: 3 }, VariableDeclarationDeclaration, VariableDeclarationInit]
18[Wall]
19[Wall]
20[Wall]
@ -46,6 +61,7 @@ flowchart LR
40["SweepEdge Adjacent"]
41["SweepEdge Adjacent"]
42["EdgeCut Fillet<br>[296, 330, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 1 }]
1 --- 3
21 x--> 2
3 --- 5
@ -64,8 +80,8 @@ flowchart LR
21 --- 4
5 --- 20
5 x--> 26
5 --- 29
5 --- 35
5 --- 31
5 --- 38
6 --- 18
6 x--> 26
6 --- 30
@ -73,24 +89,24 @@ flowchart LR
6 --- 42
7 --- 21
7 x--> 26
7 --- 31
7 --- 29
7 --- 36
8 --- 19
8 x--> 26
8 --- 28
8 --- 38
8 --- 35
10 x--> 21
10 --- 23
10 --- 33
10 --- 39
10 --- 24
10 --- 34
10 --- 41
11 x--> 21
11 --- 22
11 --- 32
11 --- 33
11 --- 40
12 x--> 21
12 --- 24
12 --- 34
12 --- 41
12 --- 23
12 --- 32
12 --- 39
16 --- 18
16 --- 19
16 --- 20
@ -115,27 +131,27 @@ flowchart LR
17 --- 39
17 --- 40
17 --- 41
30 <--x 18
35 <--x 18
37 <--x 18
28 <--x 19
18 --- 30
18 --- 37
38 <--x 18
19 --- 28
19 --- 35
36 <--x 19
38 <--x 19
29 <--x 20
20 --- 31
35 <--x 20
38 <--x 20
31 <--x 21
36 <--x 21
20 --- 38
21 --- 29
21 --- 36
37 <--x 21
32 <--x 22
39 <--x 22
40 <--x 22
33 <--x 23
39 <--x 23
41 <--x 23
34 <--x 24
40 <--x 24
41 <--x 24
22 --- 33
22 --- 40
41 <--x 22
23 --- 32
23 --- 39
40 <--x 23
24 --- 34
39 <--x 24
24 --- 41
28 <--x 25
29 <--x 25
30 <--x 25

View File

@ -2,21 +2,33 @@
flowchart LR
subgraph path3 [Path]
3["Path<br>[35, 63, 0]"]
%% [ProgramBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 1 }]
5["Segment<br>[69, 137, 0]"]
%% [ProgramBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 2 }]
6["Segment<br>[143, 240, 0]"]
%% [ProgramBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 3 }]
7["Segment<br>[246, 363, 0]"]
%% [ProgramBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 4 }]
8["Segment<br>[369, 425, 0]"]
%% [ProgramBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 5 }]
9["Segment<br>[431, 438, 0]"]
%% [ProgramBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 6 }]
13[Solid2d]
end
subgraph path4 [Path]
4["Path<br>[475, 504, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 1 }]
10["Segment<br>[510, 535, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 2 }]
11["Segment<br>[541, 576, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 3 }]
12["Segment<br>[582, 623, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 4 }]
end
1["Plane<br>[12, 29, 0]"]
%% [ProgramBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 0 }]
2["Plane<br>[451, 469, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 0 }]
1 --- 3
2 --- 4
3 --- 5

View File

@ -2,12 +2,18 @@
flowchart LR
subgraph path5 [Path]
5["Path<br>[187, 212, 0]"]
%% [ProgramBodyItem { index: 3 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 1 }]
6["Segment<br>[218, 243, 0]"]
%% [ProgramBodyItem { index: 3 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 2 }]
end
1["Plane<br>[17, 45, 0]"]
%% [ProgramBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit]
2["Plane<br>[63, 92, 0]"]
%% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit]
3["Plane<br>[110, 138, 0]"]
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit]
4["StartSketchOnPlane<br>[152, 181, 0]"]
%% Missing NodePath
1 <--x 4
1 --- 5
5 --- 6

View File

@ -202,79 +202,7 @@ description: Artifact commands artifact_graph_sketch_on_face_etc.kcl
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"type": "solid3d_get_adjacency_info",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
@ -288,66 +216,6 @@ description: Artifact commands artifact_graph_sketch_on_face_etc.kcl
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
@ -488,79 +356,7 @@ description: Artifact commands artifact_graph_sketch_on_face_etc.kcl
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"type": "solid3d_get_adjacency_info",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
@ -574,66 +370,6 @@ description: Artifact commands artifact_graph_sketch_on_face_etc.kcl
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
@ -774,79 +510,7 @@ description: Artifact commands artifact_graph_sketch_on_face_etc.kcl
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"type": "solid3d_get_adjacency_info",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
@ -860,66 +524,6 @@ description: Artifact commands artifact_graph_sketch_on_face_etc.kcl
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
@ -1060,79 +664,7 @@ description: Artifact commands artifact_graph_sketch_on_face_etc.kcl
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"type": "solid3d_get_adjacency_info",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
@ -1145,65 +677,5 @@ description: Artifact commands artifact_graph_sketch_on_face_etc.kcl
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
}
]

View File

@ -6,7 +6,7 @@ flowchart LR
10["Segment<br>[90, 123, 0]"]
11["Segment<br>[129, 185, 0]"]
12["Segment<br>[191, 198, 0]"]
27[Solid2d]
25[Solid2d]
end
subgraph path6 [Path]
6["Path<br>[300, 330, 0]"]
@ -14,7 +14,7 @@ flowchart LR
14["Segment<br>[360, 379, 0]"]
15["Segment<br>[385, 441, 0]"]
16["Segment<br>[447, 454, 0]"]
25[Solid2d]
26[Solid2d]
end
subgraph path7 [Path]
7["Path<br>[556, 583, 0]"]
@ -30,12 +30,12 @@ flowchart LR
22["Segment<br>[884, 905, 0]"]
23["Segment<br>[911, 967, 0]"]
24["Segment<br>[973, 980, 0]"]
26[Solid2d]
27[Solid2d]
end
1["Plane<br>[12, 29, 0]"]
2["StartSketchOnFace<br>[255, 294, 0]"]
3["StartSketchOnFace<br>[780, 819, 0]"]
4["StartSketchOnFace<br>[511, 550, 0]"]
3["StartSketchOnFace<br>[511, 550, 0]"]
4["StartSketchOnFace<br>[780, 819, 0]"]
29["Sweep Extrusion<br>[212, 242, 0]"]
30["Sweep Extrusion<br>[468, 498, 0]"]
31["Sweep Extrusion<br>[737, 767, 0]"]
@ -82,99 +82,99 @@ flowchart LR
72["SweepEdge Adjacent"]
73["SweepEdge Adjacent"]
1 --- 5
41 x--> 2
44 x--> 3
47 x--> 4
35 x--> 2
46 x--> 3
44 x--> 4
5 --- 9
5 --- 10
5 --- 11
5 --- 12
5 --- 27
5 --- 25
5 ---- 29
6 --- 13
6 --- 14
6 --- 15
6 --- 16
6 --- 25
6 --- 26
6 ---- 30
41 --- 6
35 --- 6
7 --- 17
7 --- 18
7 --- 19
7 --- 20
7 --- 28
7 ---- 31
47 --- 7
46 --- 7
8 --- 21
8 --- 22
8 --- 23
8 --- 24
8 --- 26
8 --- 27
8 ---- 32
44 --- 8
9 --- 40
9 --- 34
9 x--> 45
9 --- 58
9 --- 69
10 --- 41
9 --- 52
9 --- 64
10 --- 35
10 x--> 45
10 --- 56
10 --- 70
11 --- 39
10 --- 51
10 --- 63
11 --- 33
11 x--> 45
11 --- 57
11 --- 68
13 --- 38
13 x--> 41
13 --- 53
13 --- 66
14 --- 37
14 x--> 41
11 --- 50
11 --- 62
13 x--> 35
13 --- 37
13 --- 55
13 --- 67
14 x--> 35
14 --- 36
14 --- 54
14 --- 65
15 --- 36
15 x--> 41
15 --- 55
15 --- 67
14 --- 66
15 x--> 35
15 --- 38
15 --- 53
15 --- 65
17 --- 44
17 x--> 47
17 --- 60
17 --- 72
17 x--> 46
17 --- 61
17 --- 73
18 --- 42
18 x--> 47
18 --- 61
18 --- 71
18 x--> 46
18 --- 60
18 --- 72
19 --- 43
19 x--> 47
19 x--> 46
19 --- 59
19 --- 73
21 --- 33
19 --- 71
21 --- 41
21 x--> 44
21 --- 51
21 --- 64
22 --- 35
21 --- 58
21 --- 70
22 --- 40
22 x--> 44
22 --- 50
22 --- 62
23 --- 34
22 --- 57
22 --- 69
23 --- 39
23 x--> 44
23 --- 52
23 --- 63
29 --- 39
29 --- 40
29 --- 41
23 --- 56
23 --- 68
29 --- 33
29 --- 34
29 --- 35
29 --- 45
29 --- 49
29 --- 56
29 --- 57
29 --- 58
29 --- 68
29 --- 69
29 --- 70
29 --- 50
29 --- 51
29 --- 52
29 --- 62
29 --- 63
29 --- 64
30 --- 36
30 --- 37
30 --- 38
30 --- 47
30 --- 46
30 --- 53
30 --- 54
30 --- 55
@ -184,69 +184,69 @@ flowchart LR
31 --- 42
31 --- 43
31 --- 44
31 --- 46
31 --- 47
31 --- 59
31 --- 60
31 --- 61
31 --- 71
31 --- 72
31 --- 73
32 --- 33
32 --- 34
32 --- 35
32 --- 39
32 --- 40
32 --- 41
32 --- 48
32 --- 50
32 --- 51
32 --- 52
32 --- 62
32 --- 63
32 --- 64
51 <--x 33
32 --- 56
32 --- 57
32 --- 58
32 --- 68
32 --- 69
32 --- 70
33 --- 50
33 --- 62
63 <--x 33
64 <--x 33
52 <--x 34
34 --- 52
62 <--x 34
63 <--x 34
50 <--x 35
62 <--x 35
34 --- 64
35 --- 51
35 --- 63
64 <--x 35
55 <--x 36
65 <--x 36
36 --- 54
36 --- 66
67 <--x 36
54 <--x 37
37 --- 55
65 <--x 37
66 <--x 37
53 <--x 38
37 --- 67
38 --- 53
38 --- 65
66 <--x 38
67 <--x 38
57 <--x 39
68 <--x 39
70 <--x 39
58 <--x 40
68 <--x 40
69 <--x 40
56 <--x 41
69 <--x 41
70 <--x 41
61 <--x 42
71 <--x 42
72 <--x 42
59 <--x 43
71 <--x 43
73 <--x 43
60 <--x 44
72 <--x 44
73 <--x 44
59 <--x 46
60 <--x 46
61 <--x 46
53 <--x 47
54 <--x 47
55 <--x 47
50 <--x 48
51 <--x 48
52 <--x 48
56 <--x 49
57 <--x 49
58 <--x 49
39 --- 56
39 --- 68
69 <--x 39
40 --- 57
40 --- 69
70 <--x 40
41 --- 58
68 <--x 41
41 --- 70
42 --- 60
42 --- 72
73 <--x 42
43 --- 59
43 --- 71
72 <--x 43
44 --- 61
71 <--x 44
44 --- 73
53 <--x 46
54 <--x 46
55 <--x 46
59 <--x 47
60 <--x 47
61 <--x 47
56 <--x 48
57 <--x 48
58 <--x 48
50 <--x 49
51 <--x 49
52 <--x 49
```

View File

@ -219,106 +219,7 @@ description: Artifact commands assembly_mixed_units_cubes.kcl
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"type": "solid3d_get_adjacency_info",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
@ -332,86 +233,6 @@ description: Artifact commands assembly_mixed_units_cubes.kcl
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
@ -602,106 +423,7 @@ description: Artifact commands assembly_mixed_units_cubes.kcl
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_all_edge_faces",
"type": "solid3d_get_adjacency_info",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
@ -714,85 +436,5 @@ description: Artifact commands assembly_mixed_units_cubes.kcl
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
}
]

View File

@ -2,26 +2,42 @@
flowchart LR
subgraph path3 [Path]
3["Path<br>[74, 114, 1]"]
%% Missing NodePath
5["Segment<br>[120, 137, 1]"]
%% Missing NodePath
6["Segment<br>[143, 161, 1]"]
%% Missing NodePath
7["Segment<br>[167, 185, 1]"]
%% Missing NodePath
8["Segment<br>[191, 247, 1]"]
%% Missing NodePath
9["Segment<br>[253, 260, 1]"]
%% Missing NodePath
15[Solid2d]
end
subgraph path4 [Path]
4["Path<br>[74, 112, 2]"]
%% Missing NodePath
10["Segment<br>[118, 135, 2]"]
%% Missing NodePath
11["Segment<br>[141, 159, 2]"]
%% Missing NodePath
12["Segment<br>[165, 183, 2]"]
%% Missing NodePath
13["Segment<br>[189, 245, 2]"]
%% Missing NodePath
14["Segment<br>[251, 258, 2]"]
%% Missing NodePath
16[Solid2d]
end
1["Plane<br>[47, 64, 1]"]
%% Missing NodePath
2["Plane<br>[47, 64, 2]"]
%% Missing NodePath
17["Sweep Extrusion<br>[266, 288, 1]"]
%% Missing NodePath
18["Sweep Extrusion<br>[264, 286, 2]"]
%% Missing NodePath
19[Wall]
20[Wall]
21[Wall]
@ -68,24 +84,24 @@ flowchart LR
4 ---- 18
5 --- 25
5 x--> 28
5 --- 36
5 --- 43
5 --- 38
5 --- 46
6 --- 24
6 x--> 28
6 --- 37
6 --- 45
7 --- 23
7 x--> 28
7 --- 35
7 --- 36
7 --- 44
8 --- 26
8 x--> 28
8 --- 38
8 --- 46
8 --- 35
8 --- 43
10 --- 19
10 x--> 27
10 --- 31
10 --- 40
10 --- 34
10 --- 42
11 --- 22
11 x--> 27
11 --- 33
@ -93,11 +109,11 @@ flowchart LR
12 --- 21
12 x--> 27
12 --- 32
12 --- 39
12 --- 40
13 --- 20
13 x--> 27
13 --- 34
13 --- 42
13 --- 31
13 --- 39
17 --- 23
17 --- 24
17 --- 25
@ -126,30 +142,30 @@ flowchart LR
18 --- 40
18 --- 41
18 --- 42
31 <--x 19
40 <--x 19
42 <--x 19
34 <--x 20
39 <--x 20
42 <--x 20
32 <--x 21
39 <--x 21
19 --- 34
39 <--x 19
19 --- 42
20 --- 31
20 --- 39
40 <--x 20
21 --- 32
21 --- 40
41 <--x 21
33 <--x 22
40 <--x 22
41 <--x 22
35 <--x 23
44 <--x 23
22 --- 33
22 --- 41
42 <--x 22
23 --- 36
23 --- 44
45 <--x 23
37 <--x 24
43 <--x 24
45 <--x 24
36 <--x 25
24 --- 37
24 --- 45
46 <--x 24
25 --- 38
43 <--x 25
46 <--x 25
38 <--x 26
25 --- 46
26 --- 35
26 --- 43
44 <--x 26
46 <--x 26
31 <--x 29
32 <--x 29
33 <--x 29

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