test: Vendor kcl-samples and add simulation tests for them (#5460)
* Change to unzip * Download kcl-samples as zip to public dir * Fix fetch:samples, e2e electron still not working * Change error message to be clearer * Refactor so that input and output directories of sim tests can be different * Add kcl samples test implementation * Update output since adding kcl_samples tests * Update kcl-samples branch * Fix git-ignore pattern to only apply to the root * Fix yarn install and yarn fetch:samples to work the first time * Remove unneeded exists check * Change to use kcl-samples in public directory * Add kcl-samples * Update output since updating kcl-samples * Update output files * Change to not fetch samples during yarn install * Update output after merge * Ignore kcl-samples in codespell * WIP: Don't run e2e if only kcl-samples changed * Conditionally run cargo tests * Fix to round floating point values in program memory arrays * Update output since merge and rounding numbers in memory * Fix memory redaction for floating point to find more values * Fix float redaction pattern * Update output since rounding floating point numbers * Add center to floating point pattern * Fix trigger to use picomatch syntax * Update output since rounding center * Remove kcl-samples github workflows * Enable Rust backtrace * Update output after re-running * Update output after changing order of post-extrude commands * Fix to have deterministic order of commands * Update output after reverting ordering changes * Update kcl-samples * Update output after updating samples * Fix error messages to show the names of all samples that failed * Change cargo test command to match current one * Update kcl-samples * Update output since updating kcl-samples * Add generate manifest workflow and yarn script * Fix error check to actually work * Change util function to be what we actually need * Move new files after merge * Fix paths since directory move * Add dependabot updates for kcl-samples * Add GitHub workflow to make PR to kcl-samples repo * Add GitHub workflow to check kcl-samples header comments * Fix worfklow to change to the right directory * Add auto-commit simulation test output changes * Add permissions to workflows * Fix to run git commit step * Install just if needed * Fix directory of justfile * Add installation of cargo-insta * Fix to use underscore * Fix to allow just command failure * Change to always install CLI tools and cache them * Trying to fix overwrite failing * Combine commands * Change reviewer * Change to PR targeting the next branch * Change git commands to not do unnecessary fetch * Comment out trigger for creating a PR * Update kcl-samples from next branch * Update outputs after kcl-samples change * Fix to use bash pipefail * Add rust backtrace * Print full env from sim tests * Change command to use long option name * Fix to use ci profile even when calling through just * Add INSTA_UPDATE=always * Fix git push by using an app token on checkout * Add comments * Fix to use bash options * Change to echo when no changes are found * Fix so that kcl-samples updates don't trigger full run * Fix paths to reflect new crate location * Fix path detection * Fix e2e job to ignore kcl_samples simulation test output * Fix the fetch logic for the KCL samples after vendoring (#5661) Fixes the last 2 E2E tests for #5460. --------- Co-authored-by: Pierre Jacquier <pierre@zoo.dev> Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com> Co-authored-by: Frank Noirot <frank@zoo.dev>
This commit is contained in:
@ -1,3 +1,3 @@
|
||||
[codespell]
|
||||
ignore-words-list: crate,everytime,inout,co-ordinate,ot,nwo,atleast,ue,afterall,ser
|
||||
skip: **/target,node_modules,build,dist,./out,**/Cargo.lock,./docs/kcl/*.md,.yarn.lock,**/yarn.lock,./openapi/*.json,./packages/codemirror-lang-kcl/test/all.test.ts,tsconfig.tsbuildinfo
|
||||
skip: **/target,node_modules,build,dist,./out,**/Cargo.lock,./docs/kcl/*.md,.yarn.lock,**/yarn.lock,./openapi/*.json,./packages/codemirror-lang-kcl/test/all.test.ts,./public/kcl-samples,./rust/kcl-lib/tests/kcl_samples,tsconfig.tsbuildinfo
|
||||
|
6
.github/dependabot.yml
vendored
6
.github/dependabot.yml
vendored
@ -40,8 +40,10 @@ updates:
|
||||
wasm-bindgen-deps:
|
||||
patterns:
|
||||
- "wasm-bindgen*"
|
||||
- package-ecosystem: "pip" # See documentation for possible values
|
||||
directory: "/rust/kcl-python-bindings/" # Location of package manifests
|
||||
- package-ecosystem: "pip"
|
||||
directories:
|
||||
- "/public/kcl-samples/"
|
||||
- "/rust/kcl-python-bindings/"
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: monday
|
||||
|
85
.github/workflows/cargo-test.yml
vendored
85
.github/workflows/cargo-test.yml
vendored
@ -5,7 +5,9 @@ on:
|
||||
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
permissions: read-all
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
@ -15,7 +17,15 @@ jobs:
|
||||
name: cargo test
|
||||
runs-on: ubuntu-latest-8-cores
|
||||
steps:
|
||||
- uses: actions/create-github-app-token@v1
|
||||
id: app-token
|
||||
with:
|
||||
app-id: ${{ secrets.MODELING_APP_GH_APP_ID }}
|
||||
private-key: ${{ secrets.MODELING_APP_GH_APP_PRIVATE_KEY }}
|
||||
owner: ${{ github.repository_owner }}
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
token: ${{ steps.app-token.outputs.token }}
|
||||
- name: Use correct Rust toolchain
|
||||
shell: bash
|
||||
run: |
|
||||
@ -40,11 +50,81 @@ jobs:
|
||||
${HOME}/.vector/bin/vector --config /tmp/vector.toml &
|
||||
- uses: taiki-e/install-action@cargo-llvm-cov
|
||||
- uses: taiki-e/install-action@nextest
|
||||
- name: Install just
|
||||
uses: taiki-e/install-action@just
|
||||
- name: Install cargo-insta
|
||||
shell: bash
|
||||
run: |
|
||||
cargo install cargo-insta
|
||||
- name: Rust Cache
|
||||
uses: Swatinem/rust-cache@v2.6.1
|
||||
uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
workspaces: rust
|
||||
- name: Fetch the base branch
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
run: git fetch origin ${{ github.base_ref }} --depth=1
|
||||
- name: Check for path changes
|
||||
id: path-changes
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
# Manual runs or push should run all tests.
|
||||
if [[ ${{ github.event_name }} != 'pull_request' ]]; then
|
||||
echo "outside-kcl-samples=true" >> $GITHUB_OUTPUT
|
||||
exit 0
|
||||
fi
|
||||
|
||||
changed_files=$(git diff --name-only origin/${{ github.base_ref }})
|
||||
echo "$changed_files"
|
||||
if grep -Evq '^public/kcl-samples/|^rust/kcl-lib/tests/kcl_samples/' <<< "$changed_files" ; then
|
||||
echo "outside-kcl-samples=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "outside-kcl-samples=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
- name: cargo test only kcl-samples
|
||||
id: cargo-test-kcl-samples
|
||||
if: steps.path-changes.outputs.outside-kcl-samples == 'false'
|
||||
continue-on-error: true
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cd rust
|
||||
cargo nextest run --workspace --retries=2 --no-fail-fast --profile ci simulation_tests::kcl_samples 2>&1 | tee /tmp/github-actions.log
|
||||
env:
|
||||
KITTYCAD_API_TOKEN: ${{secrets.KITTYCAD_API_TOKEN}}
|
||||
RUST_BACKTRACE: full
|
||||
RUST_MIN_STACK: 10485760000
|
||||
- name: Commit differences
|
||||
if: steps.path-changes.outputs.outside-kcl-samples == 'false' && steps.cargo-test-kcl-samples.outcome == 'failure'
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cd rust
|
||||
just overwrite-sim-test kcl_samples
|
||||
git add kcl-lib/tests
|
||||
git config --local user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git config --local user.name "github-actions[bot]"
|
||||
git remote set-url origin https://${{ github.actor }}:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git
|
||||
git fetch origin
|
||||
echo ${{ github.head_ref }}
|
||||
git checkout ${{ github.head_ref }}
|
||||
if ! git commit -m "Update kcl-samples simulation test output" ; then
|
||||
echo "No changes to commit"
|
||||
# This only runs if tests failed, so we should fail the step.
|
||||
exit 1
|
||||
fi
|
||||
git push origin ${{ github.head_ref }}
|
||||
env:
|
||||
# The default is auto, and insta behaves differently in CI vs. not.
|
||||
INSTA_UPDATE: always
|
||||
KITTYCAD_API_TOKEN: ${{secrets.KITTYCAD_API_TOKEN}}
|
||||
# Configure nextest when it's run by insta (via just).
|
||||
NEXTEST_PROFILE: ci
|
||||
RUST_BACKTRACE: full
|
||||
RUST_MIN_STACK: 10485760000
|
||||
- name: cargo test
|
||||
if: steps.path-changes.outputs.outside-kcl-samples == 'true'
|
||||
shell: bash
|
||||
run: |-
|
||||
cd rust
|
||||
@ -53,6 +133,7 @@ jobs:
|
||||
KITTYCAD_API_TOKEN: ${{secrets.KITTYCAD_API_TOKEN}}
|
||||
RUST_MIN_STACK: 10485760000
|
||||
- name: Upload to codecov.io
|
||||
if: steps.path-changes.outputs.outside-kcl-samples == 'true'
|
||||
uses: codecov/codecov-action@v5
|
||||
with:
|
||||
token: ${{secrets.CODECOV_TOKEN}}
|
||||
|
48
.github/workflows/check-kcl-header.yml
vendored
Normal file
48
.github/workflows/check-kcl-header.yml
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
name: Check kcl-samples files for proper header structure
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'public/kcl-samples/**/*.kcl'
|
||||
- .github/workflows/check-kcl-header.yml
|
||||
branches:
|
||||
- main
|
||||
push:
|
||||
paths:
|
||||
- 'public/kcl-samples/**/*.kcl'
|
||||
- .github/workflows/check-kcl-header.yml
|
||||
branches:
|
||||
- main
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
check-kcl-header:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Check KCL files for header comment block and blank line
|
||||
run: |
|
||||
files=$(find public/kcl-samples -type f -name '*.kcl')
|
||||
failed_files=()
|
||||
|
||||
for file in $files; do
|
||||
if ! awk '
|
||||
NR == 1 && $0 !~ /^\/\// { exit 1 }
|
||||
BEGIN { in_comment = 1 }
|
||||
NF == 0 && in_comment == 1 { in_comment = 0; next }
|
||||
$1 !~ /^\/\// && in_comment == 1 { exit 1 }
|
||||
in_comment == 0 && NF > 0 { exit 0 }
|
||||
END { if (in_comment == 1) exit 1 }
|
||||
' "$file"; then
|
||||
failed_files+=("$file")
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ${#failed_files[@]} -ne 0 ]; then
|
||||
echo "One or more KCL files do not begin with a header comment block followed by a blank line:"
|
||||
printf '%s\n' "${failed_files[@]}"
|
||||
exit 1
|
||||
fi
|
37
.github/workflows/e2e-tests.yml
vendored
37
.github/workflows/e2e-tests.yml
vendored
@ -17,6 +17,41 @@ permissions:
|
||||
|
||||
|
||||
jobs:
|
||||
|
||||
path-changes:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
significant: ${{ steps.path-changes.outputs.significant }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Fetch the base branch
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
run: git fetch origin ${{ github.base_ref }} --depth=1
|
||||
- name: Check for path changes
|
||||
id: path-changes
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
# Manual runs or push should run all tests.
|
||||
if [[ ${{ github.event_name }} != 'pull_request' ]]; then
|
||||
echo "significant=true" >> $GITHUB_OUTPUT
|
||||
exit 0
|
||||
fi
|
||||
|
||||
changed_files=$(git diff --name-only origin/${{ github.base_ref }})
|
||||
echo "$changed_files"
|
||||
if grep -Evq '^README.md|^public/kcl-samples/|^rust/kcl-lib/tests/kcl_samples/' <<< "$changed_files" ; then
|
||||
echo "significant=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "significant=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
- name: Display path changes
|
||||
run: |
|
||||
# For debugging purposes.
|
||||
echo "significant: ${{ steps.path-changes.outputs.significant }}"
|
||||
|
||||
electron:
|
||||
timeout-minutes: 60
|
||||
name: playwright:electron:${{ matrix.os }} ${{ matrix.shardIndex }} ${{ matrix.shardTotal }}
|
||||
@ -29,6 +64,8 @@ jobs:
|
||||
shardTotal: [4]
|
||||
# TODO: add ref here for main and latest release tag
|
||||
runs-on: ${{ matrix.os }}
|
||||
needs: path-changes
|
||||
if: ${{ needs.path-changes.outputs.significant == 'true' }}
|
||||
steps:
|
||||
- uses: actions/create-github-app-token@v1
|
||||
id: app-token
|
||||
|
52
.github/workflows/kcl-samples-manifest.yml
vendored
Normal file
52
.github/workflows/kcl-samples-manifest.yml
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
name: KCL Samples Manifest
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
workflow_dispatch: # Allows manual triggering from the Actions tab
|
||||
|
||||
jobs:
|
||||
generate-manifest:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
# Checkout the repository
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Set up Node.js
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
|
||||
# Run the script to generate the manifest.json
|
||||
- name: Run manifest generation script
|
||||
working-directory: public/kcl-samples
|
||||
run: node generate-manifest.js
|
||||
|
||||
# Check if the manifest.json has changed
|
||||
- name: Check for changes
|
||||
id: check-for-changes
|
||||
working-directory: public/kcl-samples
|
||||
run: |
|
||||
git diff --exit-code ./manifest.json || echo "changed=changes detected" >> "$GITHUB_OUTPUT"
|
||||
|
||||
# Stage and commit the changes if any were made
|
||||
- name: Commit and push changes
|
||||
if: ${{ success() && (steps.check-for-changes.outputs.changed == 'changes detected') }}
|
||||
working-directory: public/kcl-samples
|
||||
run: |
|
||||
git add ./manifest.json
|
||||
git config --local user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git config --local user.name "github-actions[bot]"
|
||||
git remote set-url origin https://${{ github.actor }}:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git
|
||||
git fetch origin
|
||||
echo ${{ github.head_ref }}
|
||||
git checkout ${{ github.head_ref }}
|
||||
git commit -m "Update manifest.json"
|
||||
git push origin ${{ github.head_ref }}
|
64
.github/workflows/pr-kcl-samples-repo.yml
vendored
Normal file
64
.github/workflows/pr-kcl-samples-repo.yml
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- 'public/kcl-samples/**'
|
||||
# pull_request:
|
||||
# paths:
|
||||
# - .github/workflows/pr-kcl-samples-repo.yml
|
||||
workflow_dispatch:
|
||||
name: Create PR in kcl-samples repo
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
jobs:
|
||||
pr-kcl-samples-repo:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/create-github-app-token@v1
|
||||
id: app-token
|
||||
with:
|
||||
# required
|
||||
app-id: ${{ secrets.GH_ORG_APP_ID }}
|
||||
private-key: ${{ secrets.GH_ORG_APP_PRIVATE_KEY }}
|
||||
owner: ${{ github.repository_owner }}
|
||||
- uses: actions/checkout@v4
|
||||
# Checkout the other repo since we want to update the files there.
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
repository: 'KittyCAD/kcl-samples'
|
||||
ref: next
|
||||
path: kcl-samples-repo
|
||||
token: ${{ steps.app-token.outputs.token }}
|
||||
- name: Move files to repo work tree
|
||||
shell: bash
|
||||
run: |
|
||||
rsync -av --delete \
|
||||
--exclude='.git' \
|
||||
--exclude='.github' \
|
||||
--exclude='screenshots' \
|
||||
--exclude='step' \
|
||||
public/kcl-samples/ kcl-samples-repo/
|
||||
- name: Commit the changes in the repo
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cd kcl-samples-repo
|
||||
git config --local user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git config --local user.name "github-actions[bot]"
|
||||
export NEW_BRANCH="update-from-modeling-app"
|
||||
git switch -c "$NEW_BRANCH"
|
||||
git add --all .
|
||||
git commit -m "Updates from modeling-app repo" || exit 0
|
||||
git push -f origin "$NEW_BRANCH"
|
||||
gh pr create --title "Update from modeling-app" \
|
||||
--body "Updating files from the modeling-app repo" \
|
||||
--head "$NEW_BRANCH" \
|
||||
--reviewer jtran \
|
||||
--base next || true
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ steps.app-token.outputs.token }}
|
5
.gitignore
vendored
5
.gitignore
vendored
@ -51,7 +51,10 @@ e2e/playwright/export-snapshots/*
|
||||
!e2e/playwright/export-snapshots/*.png
|
||||
!e2e/playwright/snapshot-tests.spec.ts-snapshots/*.png
|
||||
|
||||
/kcl-samples
|
||||
/public/kcl-samples.zip
|
||||
/public/kcl-samples/.github
|
||||
/public/kcl-samples/screenshots
|
||||
/public/kcl-samples/step
|
||||
/test-results/
|
||||
/playwright-report/
|
||||
/blob-report/
|
||||
|
@ -91,7 +91,7 @@
|
||||
"fmt-check": "prettier --check ./src *.ts *.json *.js ./e2e ./packages ./rust/kcl-language-server",
|
||||
"fetch:wasm": "./scripts/get-latest-wasm-bundle.sh",
|
||||
"fetch:wasm:windows": "./scripts/get-latest-wasm-bundle.ps1",
|
||||
"fetch:samples": "echo \"Fetching latest KCL samples...\" && curl -o public/kcl-samples-manifest-fallback.json https://raw.githubusercontent.com/KittyCAD/kcl-samples/next/manifest.json",
|
||||
"fetch:samples": "rm -rf public/kcl-samples* && curl -L -o public/kcl-samples.zip https://github.com/KittyCAD/kcl-samples/archive/refs/heads/next.zip && unzip -o public/kcl-samples.zip -d public && mv public/kcl-samples-* public/kcl-samples",
|
||||
"build:wasm-dev": "yarn wasm-prep && (cd rust && wasm-pack build kcl-wasm-lib --dev --target web --out-dir pkg && cargo test -p kcl-lib export_bindings) && yarn isomorphic-copy-wasm && yarn fmt",
|
||||
"build:wasm:nocopy": "yarn wasm-prep && cd rust && wasm-pack build kcl-wasm-lib --release --target web --out-dir pkg && cargo test -p kcl-lib export_bindings",
|
||||
"build:wasm": "yarn build:wasm:nocopy && cp rust/kcl-wasm-lib/pkg/kcl_wasm_lib_bg.wasm public && yarn fmt",
|
||||
@ -106,10 +106,11 @@
|
||||
"files:flip-to-nightly:windows": "./scripts/flip-files-to-nightly.ps1",
|
||||
"files:invalidate-bucket": "./scripts/invalidate-files-bucket.sh",
|
||||
"files:invalidate-bucket:nightly": "./scripts/invalidate-files-bucket.sh --nightly",
|
||||
"postinstall": "yarn fetch:samples && yarn xstate:typegen && ./node_modules/.bin/electron-rebuild",
|
||||
"postinstall": "yarn xstate:typegen && ./node_modules/.bin/electron-rebuild",
|
||||
"xstate:typegen": "yarn xstate typegen \"src/**/*.ts?(x)\"",
|
||||
"make:dev": "make dev",
|
||||
"generate:machine-api": "npx openapi-typescript ./openapi/machine-api.json -o src/lib/machine-api.d.ts",
|
||||
"generate:samples-manifest": "cd public/kcl-samples && node generate-manifest.js",
|
||||
"tron:start": "electron-forge start",
|
||||
"chrome:test": "PLATFORM=web NODE_ENV=development yarn playwright test --config=playwright.config.ts --project='Google Chrome' --grep-invert='@snapshot'",
|
||||
"tronb:vite:dev": "vite build -c vite.main.config.ts -m development && vite build -c vite.preload.config.ts -m development && vite build -c vite.renderer.config.ts -m development",
|
||||
|
7
public/kcl-samples/.gitignore
vendored
Normal file
7
public/kcl-samples/.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
.vscode
|
||||
.idea
|
||||
.DS_Store
|
||||
screenshots/main.kcl
|
||||
step/main.kcl
|
||||
/project.toml
|
||||
thumbnail.png
|
136
public/kcl-samples/3d-boaty/boat-parts.kcl
Normal file
136
public/kcl-samples/3d-boaty/boat-parts.kcl
Normal file
@ -0,0 +1,136 @@
|
||||
// 3D Boaty Function Library
|
||||
// The following file describes various functions to build the 3D boaty. The name of this file is a bit of misnomer, the shape of the object is a typical park bench.
|
||||
|
||||
// Set units in millimeters (mm)
|
||||
@settings(defaultLengthUnit = mm)
|
||||
|
||||
export dividerThickness = 4
|
||||
|
||||
fn dividerSketch(plane) {
|
||||
sketch000 = startSketchOn(plane)
|
||||
|> startProfileAt([-16.82, 21.2], %)
|
||||
|> line(end = [-0.13, -1.27])
|
||||
|> tangentialArcTo([-15.94, profileStartY(%) - 7.73], %)
|
||||
|> tangentialArcTo([-16.6, profileStartY(%) - 15.52], %)
|
||||
|> tangentialArcTo([-18.38, profileStartY(%) - 18.63], %)
|
||||
|> line(end = [-1.25, -2.6])
|
||||
|> xLine(6.04, %)
|
||||
|> line(end = [6.68, 7.87])
|
||||
|> tangentialArcTo([10.06, profileStartY(%) - 12.69], %)
|
||||
|> line(end = [7.28, -8.47])
|
||||
|> xLine(5.98, %)
|
||||
|> line(end = [-1.3, 3.01])
|
||||
|> tangentialArcTo([22.45, profileStartY(%) - 2.84], %)
|
||||
|> tangentialArcTo([25.08, profileStartY(%) + 6.42], %)
|
||||
|> line(end = [2.35, 16.36])
|
||||
|> line(end = [1.78, 1.15])
|
||||
|> tangentialArcTo([23.93, profileStartY(%) + 27.29], %)
|
||||
|> line(end = [-1.92, 0.21])
|
||||
|> line(end = [-3.74, -26.54])
|
||||
|> tangentialArcTo([15.13, profileStartY(%) - 1.72], %)
|
||||
|> tangentialArcTo(profileStart(%), %)
|
||||
|> close()
|
||||
return sketch000
|
||||
}
|
||||
|
||||
export fn divider(plane) {
|
||||
right = dividerSketch(plane)
|
||||
|> extrude(length = dividerThickness / 2)
|
||||
left = dividerSketch(plane)
|
||||
|> extrude(length = -dividerThickness / 2)
|
||||
shell(right, thickness = 1.5, faces = ["end"])
|
||||
shell(left, thickness = 1.5, faces = ["start"])
|
||||
return 0
|
||||
}
|
||||
|
||||
fn connectorSketch(plane, start) {
|
||||
sketch001 = startSketchOn(plane)
|
||||
|> startProfileAt(start, %)
|
||||
|> polygon({
|
||||
radius = 1.2,
|
||||
numSides = 6,
|
||||
center = profileStart(%),
|
||||
inscribed = false
|
||||
}, %)
|
||||
return sketch001
|
||||
}
|
||||
|
||||
export fn connector(plane, length) {
|
||||
connectorSketch(plane, [-12, 8])
|
||||
|> extrude(length = length)
|
||||
connectorSketch(plane, [16, 8])
|
||||
|> extrude(length = length)
|
||||
return 0
|
||||
}
|
||||
|
||||
fn seatSlatSketch(plane) {
|
||||
sketch003 = startSketchOn(plane)
|
||||
|> startProfileAt([-7, 19], %)
|
||||
|> line(end = [-10, 0.5])
|
||||
|> line(end = [0.2, 2.5])
|
||||
|> line(end = [1.5, 1.5])
|
||||
|> line(end = [6.9, -0.5])
|
||||
|> line(end = [1.5, -1.5])
|
||||
|> line(endAbsolute = profileStart(%))
|
||||
|> close()
|
||||
|> patternLinear2d(instances = 3, distance = 11, axis = [1, -0.05])
|
||||
return sketch003
|
||||
}
|
||||
|
||||
export fn seatSlats(plane, length) {
|
||||
seatSlatSketch(plane)
|
||||
|> extrude(length = length)
|
||||
return 0
|
||||
}
|
||||
|
||||
fn backSlatsSketch(plane) {
|
||||
sketch004 = startSketchOn(plane)
|
||||
|> startProfileAt([22, 38.5], %)
|
||||
|> angledLine([173, 2], %)
|
||||
|> line(end = [-1.74, 2.03])
|
||||
|> angledLine([82, 6.6], %)
|
||||
|> line(end = [2.23, 1.42])
|
||||
|> angledLine([-7, 2], %)
|
||||
|> line(endAbsolute = profileStart(%))
|
||||
|> close()
|
||||
|> patternLinear2d(instances = 2, distance = 11, axis = [-0.137, -1])
|
||||
return sketch004
|
||||
}
|
||||
|
||||
export fn backSlats(plane, length) {
|
||||
b = backSlatsSketch(plane)
|
||||
|> extrude(length = length)
|
||||
return b
|
||||
}
|
||||
|
||||
fn armRestPath(plane) {
|
||||
sketch005 = startSketchOn(plane)
|
||||
|> startProfileAt([20, 33], %)
|
||||
|> xLine(-20, %)
|
||||
|> arc({
|
||||
angleStart = 90,
|
||||
angleEnd = 180,
|
||||
radius = 10
|
||||
}, %)
|
||||
return sketch005
|
||||
}
|
||||
|
||||
fn armRestProfile(plane, offset) {
|
||||
sketch006 = startSketchOn(plane)
|
||||
|> startProfileAt([offset, 32.4], %)
|
||||
|> xLine(1.3, %)
|
||||
|> line(end = [0.3, 0.6])
|
||||
|> line(end = [-0.3, 0.6])
|
||||
|> xLine(-2.6, %)
|
||||
|> line(end = [-0.3, -0.6])
|
||||
|> line(end = [0.3, -0.6])
|
||||
|> close()
|
||||
return sketch006
|
||||
}
|
||||
|
||||
export fn armRest(plane, offset) {
|
||||
path = armRestPath( offsetPlane(plane, offset = offset))
|
||||
profile = armRestProfile( offsetPlane("-XZ", offset = 20), offset)
|
||||
sweep(profile, path = path)
|
||||
return 0
|
||||
}
|
34
public/kcl-samples/3d-boaty/main.kcl
Normal file
34
public/kcl-samples/3d-boaty/main.kcl
Normal file
@ -0,0 +1,34 @@
|
||||
// 3D Boaty
|
||||
// This is a slight remix of Depep1's original 3D Boaty (https://www.printables.com/model/1141963-3d-boaty). This is a tool used for benchmarking 3D FDM printers for bed adhesion, overhangs, bridging and top surface quality. The name of this file is a bit of misnomer, the shape of the object is a typical park bench.
|
||||
|
||||
// Set units in millimeters (mm)
|
||||
@settings(defaultLengthUnit = mm)
|
||||
|
||||
// Define the bench length
|
||||
benchLength = 56
|
||||
|
||||
// Import various constants and functions from our library
|
||||
import dividerThickness from "boat-parts.kcl"
|
||||
import divider from "boat-parts.kcl"
|
||||
import connector from "boat-parts.kcl"
|
||||
import seatSlats from "boat-parts.kcl"
|
||||
import backSlats from "boat-parts.kcl"
|
||||
import armRest from "boat-parts.kcl"
|
||||
|
||||
// Create the dividers, these hold the seat and back slats
|
||||
divider("YZ")
|
||||
divider(offsetPlane("-YZ", offset = benchLength / 2))
|
||||
divider(offsetPlane("YZ", offset = benchLength / 2))
|
||||
|
||||
// Create the connectors to join the dividers
|
||||
connector(offsetPlane("YZ", offset = -benchLength / 2), benchLength)
|
||||
|
||||
// Create the seat slats
|
||||
seatSlats(offsetPlane("YZ", offset = -benchLength / 2 - dividerThickness / 2), benchLength + dividerThickness)
|
||||
|
||||
// Create the back slats
|
||||
backSlats(offsetPlane("YZ", offset = -benchLength / 2 - dividerThickness / 2), benchLength + dividerThickness)
|
||||
|
||||
// Create the arm rests
|
||||
armRest("-YZ", benchLength / 2)
|
||||
armRest("-YZ", -benchLength / 2)
|
246
public/kcl-samples/80-20-rail/main.kcl
Normal file
246
public/kcl-samples/80-20-rail/main.kcl
Normal file
@ -0,0 +1,246 @@
|
||||
// 80/20 Rail
|
||||
// An 80/20 extruded aluminum linear rail. T-slot profile adjustable by profile height, rail length, and origin position
|
||||
|
||||
// Set units
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
// Define function
|
||||
fn rail8020(originStart, railHeight, railLength) {
|
||||
// Sketch side 1 of profile
|
||||
sketch001 = startSketchOn('-XZ')
|
||||
|> startProfileAt([
|
||||
originStart[0],
|
||||
0.1 * railHeight + originStart[1]
|
||||
], %)
|
||||
|> arc({
|
||||
angleStart = 180,
|
||||
angleEnd = 270,
|
||||
radius = 0.1 * railHeight
|
||||
}, %)
|
||||
|> arc({
|
||||
angleStart = 180,
|
||||
angleEnd = 0,
|
||||
radius = 0.072 / 4 * railHeight
|
||||
}, %)
|
||||
|> xLine(0.1 * railHeight, %)
|
||||
|> arc({
|
||||
angleStart = 180,
|
||||
angleEnd = 0,
|
||||
radius = 0.072 / 4 * railHeight
|
||||
}, %)
|
||||
|> xLine(0.06 * railHeight, %, $edge1)
|
||||
|> yLine(0.087 * railHeight, %, $edge2)
|
||||
|> xLine(-0.183 * railHeight, %, $edge3)
|
||||
|> angledLineToY({
|
||||
angle = 45,
|
||||
to = (1 - 0.356) / 2 * railHeight + originStart[1]
|
||||
}, %, $edge4)
|
||||
|> xLine(0.232 * railHeight, %, $edge5)
|
||||
|> angledLineToY({
|
||||
angle = -45,
|
||||
to = 0.087 * railHeight + originStart[1]
|
||||
}, %, $edge6)
|
||||
|> xLine(-0.183 * railHeight, %, $edge7)
|
||||
|> yLine(-0.087 * railHeight, %, $edge8)
|
||||
|> xLine(0.06 * railHeight, %)
|
||||
|> arc({
|
||||
angleStart = 180,
|
||||
angleEnd = 0,
|
||||
radius = 0.072 / 4 * railHeight
|
||||
}, %)
|
||||
|> xLine(0.1 * railHeight, %)
|
||||
|> arc({
|
||||
angleStart = 180,
|
||||
angleEnd = 0,
|
||||
radius = 0.072 / 4 * railHeight
|
||||
}, %)
|
||||
|> arc({
|
||||
angleStart = -90,
|
||||
angleEnd = 0,
|
||||
radius = 0.1 * railHeight
|
||||
}, %)
|
||||
|
||||
// Sketch side 2 of profile
|
||||
|> arc({
|
||||
angleStart = 270,
|
||||
angleEnd = 90,
|
||||
radius = 0.072 / 4 * railHeight
|
||||
}, %)
|
||||
|> yLine(0.1 * railHeight, %)
|
||||
|> arc({
|
||||
angleStart = 270,
|
||||
angleEnd = 90,
|
||||
radius = 0.072 / 4 * railHeight
|
||||
}, %)
|
||||
|> yLine(0.06 * railHeight, %, $edge9)
|
||||
|> xLine(-0.087 * railHeight, %, $edge10)
|
||||
|> yLine(-0.183 * railHeight, %, $edge11) // edge11
|
||||
|> angledLineToX({
|
||||
angle = 135,
|
||||
to = ((1 - 0.356) / 2 + 0.356) * railHeight + originStart[0]
|
||||
}, %, $edge12) // edge12
|
||||
|> yLine(0.232 * railHeight, %, $edge13) // 13
|
||||
|> angledLineToX({
|
||||
angle = 45,
|
||||
to = (1 - 0.087) * railHeight + originStart[0]
|
||||
}, %, $edge14) // 14
|
||||
|> yLine(-0.183 * railHeight, %, $edge15) // 15
|
||||
|> xLine(0.087 * railHeight, %, $edge16)
|
||||
|> yLine(0.06 * railHeight, %)
|
||||
|> arc({
|
||||
angleStart = 270,
|
||||
angleEnd = 90,
|
||||
radius = 0.072 / 4 * railHeight
|
||||
}, %)
|
||||
|> yLine(0.1 * railHeight, %)
|
||||
|> arc({
|
||||
angleStart = 270,
|
||||
angleEnd = 90,
|
||||
radius = 0.072 / 4 * railHeight
|
||||
}, %)
|
||||
|
||||
// Sketch side 3 of profile
|
||||
|> arc({
|
||||
angleStart = 0,
|
||||
angleEnd = 90,
|
||||
radius = 0.1 * railHeight
|
||||
}, %)
|
||||
|> arc({
|
||||
angleStart = 0,
|
||||
angleEnd = -180,
|
||||
radius = 0.072 / 4 * railHeight
|
||||
}, %)
|
||||
|> xLine(-0.1 * railHeight, %)
|
||||
|> arc({
|
||||
angleStart = 0,
|
||||
angleEnd = -180,
|
||||
radius = 0.072 / 4 * railHeight
|
||||
}, %)
|
||||
|> xLine(-0.06 * railHeight, %, $edge17)
|
||||
|> yLine(-0.087 * railHeight, %, $edge18)
|
||||
|> xLine(0.183 * railHeight, %, $edge19)
|
||||
|> angledLineToY({
|
||||
angle = 45,
|
||||
to = ((1 - 0.356) / 2 + 0.356) * railHeight + originStart[1]
|
||||
}, %, $edge20)
|
||||
|> xLine(-0.232 * railHeight, %, $edge21)
|
||||
|> angledLineToY({
|
||||
angle = 135,
|
||||
to = (1 - 0.087) * railHeight + originStart[1]
|
||||
}, %, $edge22)
|
||||
|> xLine(0.183 * railHeight, %, $edge23)
|
||||
|> yLine(0.087 * railHeight, %, $edge24)
|
||||
|> xLine(-0.06 * railHeight, %)
|
||||
|> arc({
|
||||
angleStart = 0,
|
||||
angleEnd = -180,
|
||||
radius = 0.072 / 4 * railHeight
|
||||
}, %)
|
||||
|> xLine(-0.1 * railHeight, %)
|
||||
|> arc({
|
||||
angleStart = 0,
|
||||
angleEnd = -180,
|
||||
radius = 0.072 / 4 * railHeight
|
||||
}, %)
|
||||
|> arc({
|
||||
angleStart = 90,
|
||||
angleEnd = 180,
|
||||
radius = 0.1 * railHeight
|
||||
}, %)
|
||||
|
||||
// Sketch side 4 of profile
|
||||
|> arc({
|
||||
angleStart = 90,
|
||||
angleEnd = -90,
|
||||
radius = 0.072 / 4 * railHeight
|
||||
}, %)
|
||||
|> yLine(-0.1 * railHeight, %)
|
||||
|> arc({
|
||||
angleStart = 90,
|
||||
angleEnd = -90,
|
||||
radius = 0.072 / 4 * railHeight
|
||||
}, %)
|
||||
|> yLine(-0.06 * railHeight, %, $edge25)
|
||||
|> xLine(0.087 * railHeight, %, $edge26)
|
||||
|> yLine(0.183 * railHeight, %, $edge27)
|
||||
|> angledLineToX({
|
||||
angle = 135,
|
||||
to = (1 - 0.356) / 2 * railHeight + originStart[0]
|
||||
}, %, $edge28)
|
||||
|> yLine(-0.232 * railHeight, %, $edge29)
|
||||
|> angledLineToX({
|
||||
angle = 45,
|
||||
to = 0.087 * railHeight + originStart[0]
|
||||
}, %, $edge30)
|
||||
|> yLine(0.183 * railHeight, %, $edge31)
|
||||
|> xLine(-0.087 * railHeight, %, $edge32)
|
||||
|> yLine(-0.06 * railHeight, %)
|
||||
|> arc({
|
||||
angleStart = 90,
|
||||
angleEnd = -90,
|
||||
radius = 0.072 / 4 * railHeight
|
||||
}, %)
|
||||
|> yLine(-0.1 * railHeight, %)
|
||||
|> arc({
|
||||
angleStart = 90,
|
||||
angleEnd = -90,
|
||||
radius = 0.072 / 4 * railHeight
|
||||
}, %)
|
||||
|> close()
|
||||
|
||||
// Sketch center hole of profile
|
||||
|> hole(circle(
|
||||
center = [
|
||||
.5 * railHeight + originStart[0],
|
||||
.5 * railHeight + originStart[1]
|
||||
],
|
||||
radius = .205 * railHeight / 2
|
||||
), %)
|
||||
|> extrude(length = railLength)
|
||||
|> fillet(
|
||||
radius = 0.06,
|
||||
tags = [
|
||||
getNextAdjacentEdge(edge3),
|
||||
getNextAdjacentEdge(edge4),
|
||||
getNextAdjacentEdge(edge5),
|
||||
getNextAdjacentEdge(edge6),
|
||||
getNextAdjacentEdge(edge11),
|
||||
getNextAdjacentEdge(edge12),
|
||||
getNextAdjacentEdge(edge13),
|
||||
getNextAdjacentEdge(edge14),
|
||||
getNextAdjacentEdge(edge19),
|
||||
getNextAdjacentEdge(edge20),
|
||||
getNextAdjacentEdge(edge21),
|
||||
getNextAdjacentEdge(edge22),
|
||||
getNextAdjacentEdge(edge27),
|
||||
getNextAdjacentEdge(edge28),
|
||||
getNextAdjacentEdge(edge29),
|
||||
getNextAdjacentEdge(edge30)
|
||||
]
|
||||
)
|
||||
|> fillet(
|
||||
radius = 0.03,
|
||||
tags = [
|
||||
getNextAdjacentEdge(edge1),
|
||||
getNextAdjacentEdge(edge2),
|
||||
getNextAdjacentEdge(edge7),
|
||||
getNextAdjacentEdge(edge8),
|
||||
getNextAdjacentEdge(edge9),
|
||||
getNextAdjacentEdge(edge10),
|
||||
getNextAdjacentEdge(edge15),
|
||||
getNextAdjacentEdge(edge16),
|
||||
getNextAdjacentEdge(edge17),
|
||||
getNextAdjacentEdge(edge18),
|
||||
getNextAdjacentEdge(edge23),
|
||||
getNextAdjacentEdge(edge24),
|
||||
getNextAdjacentEdge(edge25),
|
||||
getNextAdjacentEdge(edge26),
|
||||
getNextAdjacentEdge(edge31),
|
||||
getNextAdjacentEdge(edge32)
|
||||
]
|
||||
)
|
||||
return sketch001
|
||||
}
|
||||
|
||||
// Generate one adjustable rail of 80/20
|
||||
rail8020([0, 0], 1.5, 48)
|
103
public/kcl-samples/README.md
Normal file
103
public/kcl-samples/README.md
Normal file
@ -0,0 +1,103 @@
|
||||
# kcl-samples
|
||||
|
||||
KittyCAD Language (KCL) is our language for defining geometry and working with our Geometry Engine efficiently.
|
||||
|
||||
This repository includes a mixture of simple and complex models demonstrating the features and syntax of KCL.
|
||||
|
||||
The samples can be browsed in our documentation at <https://zoo.dev/docs/kcl-samples>.
|
||||
|
||||
## Guidelines for adding samples
|
||||
|
||||
Merge PRs to the `next` branch, not main. When we release Modeling App, we will merge this repo's `next` into `main`. This way, `main` is always compatible with the latest ZMA release.
|
||||
|
||||
KCL samples conform to a set of style guidelines to ensure consistency and readability.
|
||||
|
||||
1. **File Naming:** Name your KCL files descriptively and concisely, using hyphens to separate words (e.g., flange.kcl, ball-bearing.kcl).
|
||||
|
||||
2. **File Header:** Include a title comment at the top of each file, followed by a brief description explaining what the model is and its typical use cases.
|
||||
|
||||
3. **Inline Comments:** Use inline comments to explain non-obvious parts of the code. Each major section should have a comment describing its purpose.
|
||||
|
||||
4. **Constants:** Define constants at the beginning of your KCL files for any values that might change or need to be reused (e.g., dimensions, angles).
|
||||
|
||||
## Snapshot and export
|
||||
|
||||
When you submit a PR to add or modify KCL samples, images and STEP files will be generated and added to the repository automatically.
|
||||
|
||||
---
|
||||
#### [3d-boaty](3d-boaty/main.kcl) ([step](step/3d-boaty.step)) ([screenshot](screenshots/3d-boaty.png))
|
||||
[](3d-boaty/main.kcl)
|
||||
#### [80-20-rail](80-20-rail/main.kcl) ([step](step/80-20-rail.step)) ([screenshot](screenshots/80-20-rail.png))
|
||||
[](80-20-rail/main.kcl)
|
||||
#### [a-parametric-bearing-pillow-block](a-parametric-bearing-pillow-block/main.kcl) ([step](step/a-parametric-bearing-pillow-block.step)) ([screenshot](screenshots/a-parametric-bearing-pillow-block.png))
|
||||
[](a-parametric-bearing-pillow-block/main.kcl)
|
||||
#### [ball-bearing](ball-bearing/main.kcl) ([step](step/ball-bearing.step)) ([screenshot](screenshots/ball-bearing.png))
|
||||
[](ball-bearing/main.kcl)
|
||||
#### [bracket](bracket/main.kcl) ([step](step/bracket.step)) ([screenshot](screenshots/bracket.png))
|
||||
[](bracket/main.kcl)
|
||||
#### [car-wheel-assembly](car-wheel-assembly/main.kcl) ([step](step/car-wheel-assembly.step)) ([screenshot](screenshots/car-wheel-assembly.png))
|
||||
[](car-wheel-assembly/main.kcl)
|
||||
#### [color-cube](color-cube/main.kcl) ([step](step/color-cube.step)) ([screenshot](screenshots/color-cube.png))
|
||||
[](color-cube/main.kcl)
|
||||
#### [cycloidal-gear](cycloidal-gear/main.kcl) ([step](step/cycloidal-gear.step)) ([screenshot](screenshots/cycloidal-gear.png))
|
||||
[](cycloidal-gear/main.kcl)
|
||||
#### [dodecahedron](dodecahedron/main.kcl) ([step](step/dodecahedron.step)) ([screenshot](screenshots/dodecahedron.png))
|
||||
[](dodecahedron/main.kcl)
|
||||
#### [enclosure](enclosure/main.kcl) ([step](step/enclosure.step)) ([screenshot](screenshots/enclosure.png))
|
||||
[](enclosure/main.kcl)
|
||||
#### [exhaust-manifold](exhaust-manifold/main.kcl) ([step](step/exhaust-manifold.step)) ([screenshot](screenshots/exhaust-manifold.png))
|
||||
[](exhaust-manifold/main.kcl)
|
||||
#### [flange-with-patterns](flange-with-patterns/main.kcl) ([step](step/flange-with-patterns.step)) ([screenshot](screenshots/flange-with-patterns.png))
|
||||
[](flange-with-patterns/main.kcl)
|
||||
#### [flange-xy](flange-xy/main.kcl) ([step](step/flange-xy.step)) ([screenshot](screenshots/flange-xy.png))
|
||||
[](flange-xy/main.kcl)
|
||||
#### [focusrite-scarlett-mounting-bracket](focusrite-scarlett-mounting-bracket/main.kcl) ([step](step/focusrite-scarlett-mounting-bracket.step)) ([screenshot](screenshots/focusrite-scarlett-mounting-bracket.png))
|
||||
[](focusrite-scarlett-mounting-bracket/main.kcl)
|
||||
#### [food-service-spatula](food-service-spatula/main.kcl) ([step](step/food-service-spatula.step)) ([screenshot](screenshots/food-service-spatula.png))
|
||||
[](food-service-spatula/main.kcl)
|
||||
#### [french-press](french-press/main.kcl) ([step](step/french-press.step)) ([screenshot](screenshots/french-press.png))
|
||||
[](french-press/main.kcl)
|
||||
#### [gear-rack](gear-rack/main.kcl) ([step](step/gear-rack.step)) ([screenshot](screenshots/gear-rack.png))
|
||||
[](gear-rack/main.kcl)
|
||||
#### [gear](gear/main.kcl) ([step](step/gear.step)) ([screenshot](screenshots/gear.png))
|
||||
[](gear/main.kcl)
|
||||
#### [gridfinity-baseplate-magnets](gridfinity-baseplate-magnets/main.kcl) ([step](step/gridfinity-baseplate-magnets.step)) ([screenshot](screenshots/gridfinity-baseplate-magnets.png))
|
||||
[](gridfinity-baseplate-magnets/main.kcl)
|
||||
#### [gridfinity-baseplate](gridfinity-baseplate/main.kcl) ([step](step/gridfinity-baseplate.step)) ([screenshot](screenshots/gridfinity-baseplate.png))
|
||||
[](gridfinity-baseplate/main.kcl)
|
||||
#### [gridfinity-bins-stacking-lip](gridfinity-bins-stacking-lip/main.kcl) ([step](step/gridfinity-bins-stacking-lip.step)) ([screenshot](screenshots/gridfinity-bins-stacking-lip.png))
|
||||
[](gridfinity-bins-stacking-lip/main.kcl)
|
||||
#### [gridfinity-bins](gridfinity-bins/main.kcl) ([step](step/gridfinity-bins.step)) ([screenshot](screenshots/gridfinity-bins.png))
|
||||
[](gridfinity-bins/main.kcl)
|
||||
#### [hex-nut](hex-nut/main.kcl) ([step](step/hex-nut.step)) ([screenshot](screenshots/hex-nut.png))
|
||||
[](hex-nut/main.kcl)
|
||||
#### [i-beam](i-beam/main.kcl) ([step](step/i-beam.step)) ([screenshot](screenshots/i-beam.png))
|
||||
[](i-beam/main.kcl)
|
||||
#### [kitt](kitt/main.kcl) ([step](step/kitt.step)) ([screenshot](screenshots/kitt.png))
|
||||
[](kitt/main.kcl)
|
||||
#### [lego](lego/main.kcl) ([step](step/lego.step)) ([screenshot](screenshots/lego.png))
|
||||
[](lego/main.kcl)
|
||||
#### [mounting-plate](mounting-plate/main.kcl) ([step](step/mounting-plate.step)) ([screenshot](screenshots/mounting-plate.png))
|
||||
[](mounting-plate/main.kcl)
|
||||
#### [multi-axis-robot](multi-axis-robot/main.kcl) ([step](step/multi-axis-robot.step)) ([screenshot](screenshots/multi-axis-robot.png))
|
||||
[](multi-axis-robot/main.kcl)
|
||||
#### [pipe-flange-assembly](pipe-flange-assembly/main.kcl) ([step](step/pipe-flange-assembly.step)) ([screenshot](screenshots/pipe-flange-assembly.png))
|
||||
[](pipe-flange-assembly/main.kcl)
|
||||
#### [pipe-with-bend](pipe-with-bend/main.kcl) ([step](step/pipe-with-bend.step)) ([screenshot](screenshots/pipe-with-bend.png))
|
||||
[](pipe-with-bend/main.kcl)
|
||||
#### [pipe](pipe/main.kcl) ([step](step/pipe.step)) ([screenshot](screenshots/pipe.png))
|
||||
[](pipe/main.kcl)
|
||||
#### [poopy-shoe](poopy-shoe/main.kcl) ([step](step/poopy-shoe.step)) ([screenshot](screenshots/poopy-shoe.png))
|
||||
[](poopy-shoe/main.kcl)
|
||||
#### [router-template-cross-bar](router-template-cross-bar/main.kcl) ([step](step/router-template-cross-bar.step)) ([screenshot](screenshots/router-template-cross-bar.png))
|
||||
[](router-template-cross-bar/main.kcl)
|
||||
#### [router-template-slate](router-template-slate/main.kcl) ([step](step/router-template-slate.step)) ([screenshot](screenshots/router-template-slate.png))
|
||||
[](router-template-slate/main.kcl)
|
||||
#### [sheet-metal-bracket](sheet-metal-bracket/main.kcl) ([step](step/sheet-metal-bracket.step)) ([screenshot](screenshots/sheet-metal-bracket.png))
|
||||
[](sheet-metal-bracket/main.kcl)
|
||||
#### [socket-head-cap-screw](socket-head-cap-screw/main.kcl) ([step](step/socket-head-cap-screw.step)) ([screenshot](screenshots/socket-head-cap-screw.png))
|
||||
[](socket-head-cap-screw/main.kcl)
|
||||
#### [walkie-talkie](walkie-talkie/main.kcl) ([step](step/walkie-talkie.step)) ([screenshot](screenshots/walkie-talkie.png))
|
||||
[](walkie-talkie/main.kcl)
|
||||
#### [washer](washer/main.kcl) ([step](step/washer.step)) ([screenshot](screenshots/washer.png))
|
||||
[](washer/main.kcl)
|
104
public/kcl-samples/a-parametric-bearing-pillow-block/main.kcl
Normal file
104
public/kcl-samples/a-parametric-bearing-pillow-block/main.kcl
Normal file
@ -0,0 +1,104 @@
|
||||
// A Parametric Bearing Pillow Block
|
||||
// A bearing pillow block, also known as a plummer block or pillow block bearing, is a pedestal used to provide support for a rotating shaft with the help of compatible bearings and various accessories. Housing a bearing, the pillow block provides a secure and stable foundation that allows the shaft to rotate smoothly within its machinery setup. These components are essential in a wide range of mechanical systems and machinery, playing a key role in reducing friction and supporting radial and axial loads.
|
||||
|
||||
// Set units
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
// Define constants such as length, width, height, counter-bore depth and diameter, bearing diameter, hole location padding, and more
|
||||
length = 6
|
||||
width = 4
|
||||
height = 1
|
||||
cbDepth = .25
|
||||
cbDia = .7
|
||||
holeDia = .375
|
||||
padding = 1.5
|
||||
bearingDia = 3
|
||||
|
||||
// (Needs to be updated). Sketch the block and extrude up to where the counterbore diameter starts.
|
||||
block = startSketchOn('XY')
|
||||
|> startProfileAt([-width / 2, -length / 2], %)
|
||||
|> line(endAbsolute = [width / 2, -length / 2])
|
||||
|> line(endAbsolute = [width / 2, length / 2])
|
||||
|> line(endAbsolute = [-width / 2, length / 2])
|
||||
|> close()
|
||||
|> hole(circle(
|
||||
center = [
|
||||
-(width / 2 - (padding / 2)),
|
||||
-(length / 2 - (padding / 2))
|
||||
],
|
||||
radius = holeDia / 2
|
||||
), %)
|
||||
|> hole(circle(
|
||||
center = [
|
||||
-(width / 2 - (padding / 2)),
|
||||
length / 2 - (padding / 2)
|
||||
],
|
||||
radius = holeDia / 2
|
||||
), %)
|
||||
|> hole(circle(
|
||||
center = [
|
||||
width / 2 - (padding / 2),
|
||||
length / 2 - (padding / 2)
|
||||
],
|
||||
radius = holeDia / 2
|
||||
), %)
|
||||
|> hole(circle(
|
||||
center = [
|
||||
width / 2 - (padding / 2),
|
||||
-(length / 2 - (padding / 2))
|
||||
],
|
||||
radius = holeDia / 2
|
||||
), %)
|
||||
|> hole(circle(
|
||||
center = [0, 0],
|
||||
radius = bearingDia / 2
|
||||
), %)
|
||||
|> extrude(length = height - cbDepth)
|
||||
|
||||
// Create a second sketch that creates the counterbore diameters and extrude the rest of the way to get the total height. Note: You cannot use startSketchOn(block, 'end'). The extrude lives outside the bounds, and the engine will not execute. This is a known issue.
|
||||
secondHalf = startSketchOn({
|
||||
plane = {
|
||||
origin = { x = 0, y = 0, z = height - cbDepth },
|
||||
xAxis = { x = 1, y = 0, z = 0 },
|
||||
yAxis = { x = 0, y = 1, z = 0 },
|
||||
zAxis = { x = 0, y = 0, z = 1 }
|
||||
}
|
||||
})
|
||||
|> startProfileAt([-width / 2, -length / 2], %)
|
||||
|> line(endAbsolute = [width / 2, -length / 2])
|
||||
|> line(endAbsolute = [width / 2, length / 2])
|
||||
|> line(endAbsolute = [-width / 2, length / 2])
|
||||
|> close()
|
||||
|> hole(circle(
|
||||
center = [
|
||||
-(width / 2 - (padding / 2)),
|
||||
-(length / 2 - (padding / 2))
|
||||
],
|
||||
radius = cbDia / 2
|
||||
), %)
|
||||
|> hole(circle(
|
||||
center = [
|
||||
-(width / 2 - (padding / 2)),
|
||||
length / 2 - (padding / 2)
|
||||
],
|
||||
radius = cbDia / 2
|
||||
), %)
|
||||
|> hole(circle(
|
||||
center = [
|
||||
width / 2 - (padding / 2),
|
||||
length / 2 - (padding / 2)
|
||||
],
|
||||
radius = cbDia / 2
|
||||
), %)
|
||||
|> hole(circle(
|
||||
center = [
|
||||
width / 2 - (padding / 2),
|
||||
-(length / 2 - (padding / 2))
|
||||
],
|
||||
radius = cbDia / 2
|
||||
), %)
|
||||
|> hole(circle(
|
||||
center = [0, 0],
|
||||
radius = bearingDia / 2
|
||||
), %)
|
||||
|> extrude(length = cbDepth)
|
124
public/kcl-samples/ball-bearing/main.kcl
Normal file
124
public/kcl-samples/ball-bearing/main.kcl
Normal file
@ -0,0 +1,124 @@
|
||||
// Ball Bearing
|
||||
// A ball bearing is a type of rolling-element bearing that uses balls to maintain the separation between the bearing races. The primary purpose of a ball bearing is to reduce rotational friction and support radial and axial loads.
|
||||
|
||||
// Set units
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
// Define constants like ball diameter, inside diamter, overhange length, and thickness
|
||||
outsideDiameter = 1.625
|
||||
sphereDia = 0.25
|
||||
shaftDia = 0.75
|
||||
overallThickness = 0.313
|
||||
wallThickness = 0.100
|
||||
overHangLength = .3
|
||||
nBalls = 10
|
||||
chainWidth = sphereDia / 2
|
||||
chainThickness = sphereDia / 8
|
||||
linkDiameter = sphereDia / 4
|
||||
|
||||
customPlane = {
|
||||
plane = {
|
||||
origin = {
|
||||
x = 0,
|
||||
y = 0,
|
||||
z = -overallThickness / 2
|
||||
},
|
||||
xAxis = { x = 1, y = 0, z = 0 },
|
||||
yAxis = { x = 0, y = 1, z = 0 },
|
||||
zAxis = { x = 0, y = 0, z = 1 }
|
||||
}
|
||||
}
|
||||
|
||||
// Sketch the inside bearing piece
|
||||
insideWallSketch = startSketchOn(customPlane)
|
||||
|> circle(
|
||||
center = [0, 0],
|
||||
radius = shaftDia / 2 + wallThickness
|
||||
)
|
||||
|> hole(circle(
|
||||
center = [0, 0],
|
||||
radius = shaftDia / 2
|
||||
), %)
|
||||
|
||||
// Extrude the inside bearing piece
|
||||
insideWall = extrude(insideWallSketch, length = overallThickness)
|
||||
|
||||
// Create the sketch of one of the balls
|
||||
ballsSketch = startSketchOn("XY")
|
||||
|> startProfileAt([shaftDia / 2 + wallThickness, 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({ axis = "X" }, ballsSketch)
|
||||
|> patternCircular3d(
|
||||
arcDegrees = 360,
|
||||
axis = [0, 0, 1],
|
||||
center = [0, 0, 0],
|
||||
instances = nBalls,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
|
||||
// Create the sketch for the chain around the balls
|
||||
chainSketch = startSketchOn("XY")
|
||||
|> startProfileAt([
|
||||
shaftDia / 2 + wallThickness + sphereDia / 2 - (chainWidth / 2),
|
||||
0.125 * sin(toRadians(60))
|
||||
], %)
|
||||
|> arc({
|
||||
angleEnd = 60,
|
||||
angleStart = 120,
|
||||
radius = sphereDia / 2
|
||||
}, %)
|
||||
|> line(end = [0, chainThickness])
|
||||
|> line(end = [-chainWidth, 0])
|
||||
|> close()
|
||||
|
||||
// Revolve the chain sketch
|
||||
chainHead = revolve({ axis = "X" }, chainSketch)
|
||||
|> patternCircular3d(
|
||||
arcDegrees = 360,
|
||||
axis = [0, 0, 1],
|
||||
center = [0, 0, 0],
|
||||
instances = nBalls,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
|
||||
// Create the sketch for the links in between the chains
|
||||
linkSketch = startSketchOn("XZ")
|
||||
|> circle(
|
||||
center = [
|
||||
shaftDia / 2 + wallThickness + sphereDia / 2,
|
||||
0
|
||||
],
|
||||
radius = linkDiameter / 2
|
||||
)
|
||||
|
||||
// Revolve the link sketch
|
||||
linkRevolve = revolve({ axis = 'Y', angle = 360 / nBalls }, linkSketch)
|
||||
|> patternCircular3d(
|
||||
arcDegrees = 360,
|
||||
axis = [0, 0, 1],
|
||||
center = [0, 0, 0],
|
||||
instances = nBalls,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
|
||||
// Create the sketch for the outside walls
|
||||
outsideWallSketch = startSketchOn(customPlane)
|
||||
|> circle(
|
||||
center = [0, 0],
|
||||
radius = outsideDiameter / 2
|
||||
)
|
||||
|> hole(circle(
|
||||
center = [0, 0],
|
||||
radius = shaftDia / 2 + wallThickness + sphereDia
|
||||
), %)
|
||||
|
||||
outsideWall = extrude(outsideWallSketch, length = overallThickness)
|
||||
|
||||
// https://www.mcmaster.com/60355K185/
|
113
public/kcl-samples/bracket/main.kcl
Normal file
113
public/kcl-samples/bracket/main.kcl
Normal file
@ -0,0 +1,113 @@
|
||||
// Shelf Bracket
|
||||
// This is a bracket that holds a shelf. It is made of aluminum and is designed to hold a force of 300 lbs. The bracket is 6 inches wide and the force is applied at the end of the shelf, 12 inches from the wall. The bracket has a factor of safety of 1.2. The legs of the bracket are 5 inches and 2 inches long. The thickness of the bracket is calculated from the constraints provided.
|
||||
|
||||
// Set units
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
// Define constants
|
||||
sigmaAllow = 35000 // psi (6061-T6 aluminum)
|
||||
width = 6
|
||||
p = 300 // Force on shelf - lbs
|
||||
factorOfSafety = 1.2 // FOS of 1.2
|
||||
shelfMountL = 5
|
||||
wallMountL = 2
|
||||
shelfDepth = 12 // Shelf is 12 inches in depth from the wall
|
||||
moment = shelfDepth * p // assume the force is applied at the end of the shelf to be conservative (lb-in)
|
||||
|
||||
|
||||
filletRadius = .375
|
||||
extFilletRadius = .25
|
||||
mountingHoleDiameter = 0.5
|
||||
|
||||
// Calculate required thickness of bracket
|
||||
thickness = sqrt(moment * factorOfSafety * 6 / (sigmaAllow * width)) // this is the calculation of two brackets holding up the shelf (inches)
|
||||
|
||||
|
||||
// Sketch the bracket body and fillet the inner and outer edges of the bend
|
||||
bracketLeg1Sketch = startSketchOn('XY')
|
||||
|> startProfileAt([0, 0], %)
|
||||
|> line(end = [shelfMountL - filletRadius, 0], tag = $fillet1)
|
||||
|> line(end = [0, width], tag = $fillet2)
|
||||
|> line(end = [-shelfMountL + filletRadius, 0])
|
||||
|> close()
|
||||
|> hole(circle(
|
||||
center = [1, 1],
|
||||
radius = mountingHoleDiameter / 2
|
||||
), %)
|
||||
|> hole(circle(
|
||||
center = [shelfMountL - 1.5, width - 1],
|
||||
radius = mountingHoleDiameter / 2
|
||||
), %)
|
||||
|> hole(circle(
|
||||
center = [1, width - 1],
|
||||
radius = mountingHoleDiameter / 2
|
||||
), %)
|
||||
|> hole(circle(
|
||||
center = [shelfMountL - 1.5, 1],
|
||||
radius = mountingHoleDiameter / 2
|
||||
), %)
|
||||
|
||||
// Extrude the leg 2 bracket sketch
|
||||
bracketLeg1Extrude = extrude(bracketLeg1Sketch, length = thickness)
|
||||
|> fillet(
|
||||
radius = extFilletRadius,
|
||||
tags = [
|
||||
getNextAdjacentEdge(fillet1),
|
||||
getNextAdjacentEdge(fillet2)
|
||||
]
|
||||
)
|
||||
|
||||
// Sketch the fillet arc
|
||||
filletSketch = startSketchOn('XZ')
|
||||
|> startProfileAt([0, 0], %)
|
||||
|> line(end = [0, thickness])
|
||||
|> arc({
|
||||
angleEnd = 180,
|
||||
angleStart = 90,
|
||||
radius = filletRadius + thickness
|
||||
}, %)
|
||||
|> line(end = [thickness, 0])
|
||||
|> arc({
|
||||
angleEnd = 90,
|
||||
angleStart = 180,
|
||||
radius = filletRadius
|
||||
}, %)
|
||||
|
||||
// Sketch the bend
|
||||
filletExtrude = extrude(filletSketch, length = -width)
|
||||
|
||||
// Create a custom plane for the leg that sits on the wall
|
||||
customPlane = {
|
||||
plane = {
|
||||
origin = { x = -filletRadius, y = 0, z = 0 },
|
||||
xAxis = { x = 0, y = 1, z = 0 },
|
||||
yAxis = { x = 0, y = 0, z = 1 },
|
||||
zAxis = { x = 1, y = 0, z = 0 }
|
||||
}
|
||||
}
|
||||
|
||||
// Create a sketch for the second leg
|
||||
bracketLeg2Sketch = startSketchOn(customPlane)
|
||||
|> startProfileAt([0, -filletRadius], %)
|
||||
|> line(end = [width, 0])
|
||||
|> line(end = [0, -wallMountL], tag = $fillet3)
|
||||
|> line(end = [-width, 0], tag = $fillet4)
|
||||
|> close()
|
||||
|> hole(circle(
|
||||
center = [1, -1.5],
|
||||
radius = mountingHoleDiameter / 2
|
||||
), %)
|
||||
|> hole(circle(
|
||||
center = [5, -1.5],
|
||||
radius = mountingHoleDiameter / 2
|
||||
), %)
|
||||
|
||||
// Extrude the second leg
|
||||
bracketLeg2Extrude = extrude(bracketLeg2Sketch, length = -thickness)
|
||||
|> fillet(
|
||||
radius = extFilletRadius,
|
||||
tags = [
|
||||
getNextAdjacentEdge(fillet3),
|
||||
getNextAdjacentEdge(fillet4)
|
||||
]
|
||||
)
|
96
public/kcl-samples/car-wheel-assembly/brake-caliper.kcl
Normal file
96
public/kcl-samples/car-wheel-assembly/brake-caliper.kcl
Normal file
@ -0,0 +1,96 @@
|
||||
// Brake Caliper
|
||||
// Brake calipers are used to squeeze the brake pads against the rotor, causing larger and larger amounts of friction depending on how hard the brakes are pressed.
|
||||
|
||||
|
||||
// Set units
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
|
||||
// Import Constants
|
||||
import caliperTolerance, caliperPadLength, caliperThickness, caliperOuterEdgeRadius, caliperInnerEdgeRadius, rotorDiameter, rotorTotalThickness, yAxisOffset from "globals.kcl"
|
||||
|
||||
// Create the plane for the brake caliper. This is so it can match up with the rotor model.
|
||||
brakeCaliperPlane = {
|
||||
plane = {
|
||||
origin = { x = 0, y = yAxisOffset, z = 0 },
|
||||
xAxis = { x = 1, y = 0, z = 0 },
|
||||
yAxis = { x = 0, y = 1, z = 0 },
|
||||
zAxis = { x = 0, y = 0, z = 1 }
|
||||
}
|
||||
}
|
||||
|
||||
// Sketch the brake caliper profile
|
||||
brakeCaliperSketch = startSketchOn(brakeCaliperPlane)
|
||||
|> startProfileAt([
|
||||
rotorDiameter / 2 + caliperTolerance,
|
||||
0
|
||||
], %)
|
||||
|> line(end = [
|
||||
0,
|
||||
rotorTotalThickness + caliperTolerance - caliperInnerEdgeRadius
|
||||
])
|
||||
|> tangentialArc({
|
||||
offset = 90,
|
||||
radius = caliperInnerEdgeRadius
|
||||
}, %)
|
||||
|> line(end = [
|
||||
-caliperPadLength + 2 * caliperInnerEdgeRadius,
|
||||
0
|
||||
])
|
||||
|> tangentialArc({
|
||||
offset = -90,
|
||||
radius = caliperInnerEdgeRadius
|
||||
}, %)
|
||||
|> line(end = [
|
||||
0,
|
||||
caliperThickness - (caliperInnerEdgeRadius * 2)
|
||||
])
|
||||
|> tangentialArc({
|
||||
offset = -90,
|
||||
radius = caliperInnerEdgeRadius
|
||||
}, %)
|
||||
|> line(end = [
|
||||
caliperPadLength + caliperThickness - caliperOuterEdgeRadius - caliperInnerEdgeRadius,
|
||||
0
|
||||
])
|
||||
|> tangentialArc({
|
||||
offset = -90,
|
||||
radius = caliperOuterEdgeRadius
|
||||
}, %)
|
||||
|> line(end = [
|
||||
0,
|
||||
-2 * caliperTolerance - (2 * caliperThickness) - rotorTotalThickness + 2 * caliperOuterEdgeRadius
|
||||
])
|
||||
|> tangentialArc({
|
||||
offset = -90,
|
||||
radius = caliperOuterEdgeRadius
|
||||
}, %)
|
||||
|> line(end = [
|
||||
-caliperPadLength - caliperThickness + caliperOuterEdgeRadius + caliperInnerEdgeRadius,
|
||||
0
|
||||
])
|
||||
|> tangentialArc({
|
||||
offset = -90,
|
||||
radius = caliperInnerEdgeRadius
|
||||
}, %)
|
||||
|> line(end = [
|
||||
0,
|
||||
caliperThickness - (2 * caliperInnerEdgeRadius)
|
||||
])
|
||||
|> tangentialArc({
|
||||
offset = -90,
|
||||
radius = caliperInnerEdgeRadius
|
||||
}, %)
|
||||
|> line(end = [
|
||||
caliperPadLength - (2 * caliperInnerEdgeRadius),
|
||||
0
|
||||
])
|
||||
|> tangentialArc({
|
||||
offset = 90,
|
||||
radius = caliperInnerEdgeRadius
|
||||
}, %)
|
||||
|> close()
|
||||
|
||||
// Revolve the brake caliper sketch
|
||||
revolve({ axis = "Y", angle = -70 }, brakeCaliperSketch)
|
||||
|> appearance(color = "#c82d2d", metalness = 90, roughness = 90)
|
111
public/kcl-samples/car-wheel-assembly/car-rotor.kcl
Normal file
111
public/kcl-samples/car-wheel-assembly/car-rotor.kcl
Normal file
@ -0,0 +1,111 @@
|
||||
// Wheel rotor
|
||||
// A component of a disc brake system. It provides a surface for brake pads to press against, generating the friction needed to slow or stop the vehicle.
|
||||
|
||||
|
||||
// Set units
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
|
||||
// Import Constants
|
||||
import rotorDiameter, rotorInnerDiameter, rotorSinglePlateThickness, rotorInnerDiameterThickness, lugHolePatternDia, lugSpacing, rotorTotalThickness, spacerPatternDiameter, spacerDiameter, spacerLength, spacerCount, wheelDiameter, lugCount, yAxisOffset, drillAndSlotCount from "globals.kcl"
|
||||
|
||||
rotorPlane = {
|
||||
plane = {
|
||||
origin = { x = 0, y = yAxisOffset, z = 0 },
|
||||
xAxis = { x = -1, y = 0, z = 0 },
|
||||
yAxis = { x = 0, y = 0, z = 1 },
|
||||
zAxis = { x = 0, y = 1, z = 0 }
|
||||
}
|
||||
}
|
||||
fn lugPattern(plane) {
|
||||
lugHolePattern = circle(
|
||||
plane,
|
||||
center = [-lugSpacing / 2, 0],
|
||||
radius = 0.315
|
||||
)
|
||||
|> patternCircular2d(
|
||||
arcDegrees = 360,
|
||||
center = [0, 0],
|
||||
instances = lugCount,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
return lugHolePattern
|
||||
}
|
||||
rotorSketch = startSketchOn(rotorPlane)
|
||||
|> circle(
|
||||
center = [0, 0],
|
||||
radius = rotorDiameter / 2
|
||||
)
|
||||
|> hole(lugPattern(%), %)
|
||||
rotor = extrude(rotorSketch, length = rotorSinglePlateThickness)
|
||||
|> appearance(color = "#dbcd70", roughness = 90, metalness = 90)
|
||||
rotorBumpSketch = startSketchOn(rotorPlane)
|
||||
|> circle(
|
||||
center = [0, 0],
|
||||
radius = rotorInnerDiameter / 2
|
||||
)
|
||||
|> hole(lugPattern(%), %)
|
||||
rotorBump = extrude(rotorBumpSketch, length = -rotorInnerDiameterThickness)
|
||||
|> appearance(color = "#dbcd70", roughness = 90, metalness = 90)
|
||||
rotorSecondaryPlatePlane = {
|
||||
plane = {
|
||||
origin = {
|
||||
x = 0,
|
||||
y = yAxisOffset + rotorTotalThickness * 0.75,
|
||||
z = 0
|
||||
},
|
||||
xAxis = { x = -1, y = 0, z = 0 },
|
||||
yAxis = { x = 0, y = 0, z = 1 },
|
||||
zAxis = { x = 0, y = 1, z = 0 }
|
||||
}
|
||||
}
|
||||
secondaryRotorSketch = startSketchOn(rotorSecondaryPlatePlane)
|
||||
|> circle(
|
||||
center = [0, 0],
|
||||
radius = rotorDiameter / 2
|
||||
)
|
||||
|> hole(lugPattern(%), %)
|
||||
secondRotor = extrude(secondaryRotorSketch, length = rotorSinglePlateThickness)
|
||||
spacerSketch = startSketchOn(rotorSecondaryPlatePlane)
|
||||
|> circle(
|
||||
center = [spacerPatternDiameter / 2, 0],
|
||||
radius = spacerDiameter
|
||||
)
|
||||
|> patternCircular2d(
|
||||
arcDegrees = 360,
|
||||
center = [0, 0],
|
||||
instances = spacerCount,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
spacers = extrude(spacerSketch, length = -spacerLength)
|
||||
|> appearance(color = "#dbcd70", roughness = 90, metalness = 90)
|
||||
rotorSlottedSketch = startSketchOn(rotor, 'START')
|
||||
|> startProfileAt([2.17, 2.56], %)
|
||||
|> xLine(0.12, %)
|
||||
|> yLine(2.56, %)
|
||||
|> xLine(-0.12, %)
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
|> patternCircular2d(
|
||||
center = [0, 0],
|
||||
instances = drillAndSlotCount,
|
||||
arcDegrees = 360,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
rotorSlotted = extrude(rotorSlottedSketch, length = -rotorSinglePlateThickness / 2)
|
||||
|
||||
secondRotorSlottedSketch = startSketchOn(secondRotor, 'END')
|
||||
|> startProfileAt([-2.17, 2.56], %)
|
||||
|> xLine(-0.12, %)
|
||||
|> yLine(2.56, %)
|
||||
|> xLine(0.12, %)
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
|> patternCircular2d(
|
||||
center = [0, 0],
|
||||
instances = drillAndSlotCount,
|
||||
arcDegrees = 360,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
secondRotorSlotted = extrude(secondRotorSlottedSketch, length = -rotorSinglePlateThickness / 2)
|
||||
|> appearance(color = "#dbcd70", roughness = 90, metalness = 90)
|
44
public/kcl-samples/car-wheel-assembly/car-tire.kcl
Normal file
44
public/kcl-samples/car-wheel-assembly/car-tire.kcl
Normal file
@ -0,0 +1,44 @@
|
||||
// Tire
|
||||
// A tire is a critical component of a vehicle that provides the necessary traction and grip between the car and the road. It supports the vehicle's weight and absorbs shocks from road irregularities.
|
||||
|
||||
|
||||
// Set units
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
|
||||
// Import Constants
|
||||
import tireInnerDiameter, tireOuterDiameter, tireDepth, bendRadius, tireTreadWidth, tireTreadDepth, tireTreadOffset from "globals.kcl"
|
||||
|
||||
// Create the sketch of the tire
|
||||
tireSketch = startSketchOn("XY")
|
||||
|> startProfileAt([tireInnerDiameter / 2, tireDepth / 2], %)
|
||||
|> line(endAbsolute = [
|
||||
tireOuterDiameter / 2 - bendRadius,
|
||||
tireDepth / 2
|
||||
], tag = $edge1)
|
||||
|> tangentialArc({ offset = -90, radius = bendRadius }, %)
|
||||
|> line(endAbsolute = [
|
||||
tireOuterDiameter / 2,
|
||||
tireDepth / 2 - tireTreadOffset
|
||||
])
|
||||
|> line(end = [-tireTreadDepth, 0])
|
||||
|> line(end = [0, -tireTreadWidth])
|
||||
|> line(end = [tireTreadDepth, 0])
|
||||
|> line(endAbsolute = [
|
||||
tireOuterDiameter / 2,
|
||||
-tireDepth / 2 + tireTreadOffset + tireTreadWidth
|
||||
])
|
||||
|> line(end = [-tireTreadDepth, 0])
|
||||
|> line(end = [0, -tireTreadWidth])
|
||||
|> line(end = [tireTreadDepth, 0])
|
||||
|> line(endAbsolute = [
|
||||
tireOuterDiameter / 2,
|
||||
-tireDepth / 2 + bendRadius
|
||||
])
|
||||
|> tangentialArc({ offset = -90, radius = bendRadius }, %)
|
||||
|> line(endAbsolute = [tireInnerDiameter / 2, -tireDepth / 2], tag = $edge2)
|
||||
|> close()
|
||||
|
||||
// Revolve the sketch to create the tire
|
||||
revolve({ axis = "Y" }, tireSketch)
|
||||
|> appearance(color = "#0f0f0f", roughness = 80)
|
197
public/kcl-samples/car-wheel-assembly/car-wheel.kcl
Normal file
197
public/kcl-samples/car-wheel-assembly/car-wheel.kcl
Normal file
@ -0,0 +1,197 @@
|
||||
// Car Wheel
|
||||
// A sports car wheel with a circular lug pattern and spokes.
|
||||
|
||||
|
||||
// Set units
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
|
||||
// Import Constants
|
||||
import lugCount, lugSpacing, offset, backSpacing, wheelWidth, wheelDiameter, spokeCount, spokeGap, spokeAngle, spokeThickness from "globals.kcl"
|
||||
|
||||
// Create the wheel center
|
||||
lugBase = startSketchOn('XZ')
|
||||
|> circle(
|
||||
center = [0, 0],
|
||||
radius = (lugSpacing + 1.5) / 2
|
||||
)
|
||||
|> hole(circle(
|
||||
center = [0, 0],
|
||||
radius = (lugSpacing - 1.5) / 2
|
||||
), %)
|
||||
|> extrude(length = wheelWidth / 20)
|
||||
|
||||
// Extend the wheel center and bore holes to accomidate the lug heads
|
||||
lugExtrusion = startSketchOn(lugBase, 'END')
|
||||
|> circle(
|
||||
center = [0, 0],
|
||||
radius = (lugSpacing + 1.5) / 2
|
||||
)
|
||||
|> hole(circle(
|
||||
center = [0, 0],
|
||||
radius = (lugSpacing - 1.5) / 2
|
||||
), %)
|
||||
|> extrude(length = wheelWidth / 10)
|
||||
|
||||
// Create the circular pattern for the lugs
|
||||
lugClearance = startSketchOn(lugExtrusion, 'END')
|
||||
|> circle(
|
||||
center = [lugSpacing / 2, 0],
|
||||
radius = 1.2 / 2
|
||||
)
|
||||
|> patternCircular2d(
|
||||
arcDegrees = 360,
|
||||
center = [0, 0],
|
||||
instances = lugCount,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
|> extrude(length = -wheelWidth / 10)
|
||||
|
||||
// Create the circular pattern for the lug holes
|
||||
lugHoles = startSketchOn(lugBase, 'END')
|
||||
|> circle(
|
||||
center = [lugSpacing / 2, 0],
|
||||
radius = 16 * mm() / 2
|
||||
)
|
||||
|> patternCircular2d(
|
||||
arcDegrees = 360,
|
||||
center = [0, 0],
|
||||
instances = lugCount,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
|> extrude(length = -wheelWidth / 20)
|
||||
|> appearance(color = "#ffffff", metalness = 0, roughness = 0)
|
||||
|
||||
// Add detail to the wheel center by revolving curved edge profiles
|
||||
wheelCenterInner = startSketchOn('XY')
|
||||
|> startProfileAt([(lugSpacing - 1.5) / 2, 0], %)
|
||||
|> yLine(-wheelWidth / 10 - (wheelWidth / 20), %)
|
||||
|> bezierCurve({
|
||||
to = [-0.4, 0.3],
|
||||
control1 = [-0.3, 0],
|
||||
control2 = [0, 0.3]
|
||||
}, %)
|
||||
|> yLineTo(0, %)
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
|> revolve({ axis = 'y' }, %)
|
||||
|> appearance(color = "#ffffff", metalness = 0, roughness = 0)
|
||||
|
||||
wheelCenterOuter = startSketchOn('XY')
|
||||
|> startProfileAt([(lugSpacing + 1.5) / 2, 0], %)
|
||||
|> yLine(-wheelWidth / 10 - (wheelWidth / 20), %)
|
||||
|> bezierCurve({
|
||||
to = [0.4, -0.1],
|
||||
control1 = [0.3, 0],
|
||||
control2 = [0.2, -0.3]
|
||||
}, %)
|
||||
|> yLineTo(-wheelWidth / 20, %)
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
|> revolve({ axis = 'y' }, %)
|
||||
|> appearance(color = "#ffffff", metalness = 0, roughness = 0)
|
||||
|
||||
// Write a function that defines the spoke geometry, patterns and extrudes it
|
||||
fn spoke(spokeGap, spokeAngle, spokeThickness) {
|
||||
// Seperating the spoke base planes
|
||||
plane001 = {
|
||||
plane = {
|
||||
origin = [0.0, 0.0, spokeGap / 2],
|
||||
xAxis = [1.0, 0.0, spokeAngle],
|
||||
yAxis = [0.0, 1.0, 0.0],
|
||||
zAxis = [0.0, 0.0, 1.0]
|
||||
}
|
||||
}
|
||||
|
||||
// Spoke cross sections
|
||||
spokeProfile = startSketchOn(plane001)
|
||||
|> startProfileAt([(lugSpacing + 2) / 2, -0.7], %)
|
||||
|> bezierCurve({
|
||||
to = [
|
||||
(wheelDiameter - lugSpacing - 2.9) / 2,
|
||||
offset
|
||||
],
|
||||
control1 = [
|
||||
(wheelDiameter - lugSpacing - 2.9) / 3.5,
|
||||
offset / 7
|
||||
],
|
||||
control2 = [
|
||||
(wheelDiameter - lugSpacing - 2.9) / 4,
|
||||
offset / 1.5
|
||||
]
|
||||
}, %)
|
||||
|> yLine(-wheelWidth / 15, %)
|
||||
|> bezierCurve({
|
||||
to = [
|
||||
-(wheelDiameter - lugSpacing - 2.9) / 2,
|
||||
-offset
|
||||
],
|
||||
control1 = [
|
||||
-(wheelDiameter - lugSpacing - 2.9) / 5,
|
||||
-offset / 7
|
||||
],
|
||||
control2 = [
|
||||
-(wheelDiameter - lugSpacing - 2.9) / 5,
|
||||
-offset / 1.5
|
||||
]
|
||||
}, %)
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
|
||||
// Circular pattern spokes
|
||||
spokePattern = extrude(spokeProfile, length = spokeThickness)
|
||||
|> patternCircular3d(
|
||||
axis = [0, 1, 0],
|
||||
center = [0, -2000, 0],
|
||||
instances = spokeCount,
|
||||
arcDegrees = 360,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
|> appearance(color = "#ffffff", metalness = 0, roughness = 0)
|
||||
return spokePattern
|
||||
}
|
||||
|
||||
spoke(spokeGap, spokeAngle, spokeThickness)
|
||||
spoke(-spokeGap, -spokeAngle, -spokeThickness)
|
||||
|
||||
// Define and revolve wheel exterior
|
||||
startSketchOn('XY')
|
||||
|> startProfileAt([
|
||||
wheelDiameter / 2,
|
||||
-wheelWidth + backSpacing + offset
|
||||
], %)
|
||||
|> yLine(wheelWidth * 0.25, %)
|
||||
|> line(end = [-wheelWidth * 0.02, wheelWidth * 0.02])
|
||||
|> yLine(wheelWidth * 0.25, %)
|
||||
|> line(end = [wheelWidth * 0.02, wheelWidth * 0.02])
|
||||
|> yLineTo(backSpacing + offset, %)
|
||||
|> line(end = [wheelWidth * 0.05, wheelWidth * .01])
|
||||
|> yLine(wheelWidth * 0.05, %)
|
||||
|> xLine(-wheelWidth * 0.03, %)
|
||||
|> yLine(-wheelWidth * 0.02, %)
|
||||
|> line(end = [-wheelWidth * 0.05, -wheelWidth * 0.01])
|
||||
|> yLine(-backSpacing * 0.7, %)
|
||||
|> line(end = [
|
||||
-wheelDiameter * 0.01,
|
||||
-wheelWidth * 0.02
|
||||
])
|
||||
|> yLineTo(offset - 0.2, %)
|
||||
|> line(end = [
|
||||
-wheelDiameter * 0.03,
|
||||
-wheelWidth * 0.02
|
||||
])
|
||||
|> yLine(-wheelWidth * 0.02, %)
|
||||
|> line(end = [
|
||||
wheelDiameter * 0.03,
|
||||
-wheelWidth * 0.1
|
||||
])
|
||||
|> yLine(-wheelWidth * 0.05, %)
|
||||
|> line(end = [wheelWidth * 0.02, -wheelWidth * 0.02])
|
||||
|> yLineTo(-wheelWidth + backSpacing + offset - 0.28, %)
|
||||
|> line(end = [wheelWidth * 0.05, -wheelWidth * 0.01])
|
||||
|> yLine(-wheelWidth * 0.02, %)
|
||||
|> xLine(wheelWidth * 0.03, %)
|
||||
|> yLine(wheelWidth * 0.05, %)
|
||||
|> close()
|
||||
|> revolve({ axis = 'y' }, %)
|
||||
|> appearance(color = "#ffffff", metalness = 0, roughness = 0)
|
53
public/kcl-samples/car-wheel-assembly/globals.kcl
Normal file
53
public/kcl-samples/car-wheel-assembly/globals.kcl
Normal file
@ -0,0 +1,53 @@
|
||||
// Car wheel assembly global constants
|
||||
|
||||
// Set units
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
// Car Wheel
|
||||
export lugCount = 5
|
||||
export lugSpacing = 114.3 * mm()
|
||||
export offset = -35 * mm()
|
||||
export backSpacing = 6.38
|
||||
export wheelWidth = 9.5
|
||||
export wheelDiameter = 19
|
||||
export spokeCount = 6
|
||||
export spokeGap = 0.2
|
||||
export spokeAngle = 0.02
|
||||
export spokeThickness = 0.95
|
||||
|
||||
// Lug Nut
|
||||
export lugDiameter = 24 * mm()
|
||||
export lugHeadLength = lugDiameter * .5
|
||||
export lugThreadDiameter = lugDiameter / 2 * .85
|
||||
export lugLength = 30 * mm()
|
||||
export lugThreadDepth = lugLength - 12.7 * mm()
|
||||
|
||||
// Car Rotor
|
||||
export rotorDiameter = 12
|
||||
export rotorInnerDiameter = 6
|
||||
export rotorSinglePlateThickness = 0.25
|
||||
export rotorInnerDiameterThickness = 0.5
|
||||
export lugHolePatternDia = 3
|
||||
export rotorTotalThickness = 1
|
||||
export spacerPatternDiameter = 11
|
||||
export spacerDiameter = 0.25
|
||||
export spacerLength = rotorTotalThickness - (2 * rotorSinglePlateThickness)
|
||||
export spacerCount = 16
|
||||
export yAxisOffset = 0.5
|
||||
export drillAndSlotCount = 5
|
||||
|
||||
// Car Tire
|
||||
export tireInnerDiameter = 19
|
||||
export tireOuterDiameter = 24
|
||||
export tireDepth = 11.02
|
||||
export bendRadius = 1.6
|
||||
export tireTreadWidth = 0.39
|
||||
export tireTreadDepth = 0.39
|
||||
export tireTreadOffset = 3.15
|
||||
|
||||
// Brake Caliper
|
||||
export caliperTolerance = 0.050
|
||||
export caliperPadLength = 1.6
|
||||
export caliperThickness = 0.39
|
||||
export caliperOuterEdgeRadius = 0.39
|
||||
export caliperInnerEdgeRadius = 0.12
|
42
public/kcl-samples/car-wheel-assembly/lug-nut.kcl
Normal file
42
public/kcl-samples/car-wheel-assembly/lug-nut.kcl
Normal file
@ -0,0 +1,42 @@
|
||||
// Lug Nut
|
||||
// lug Nuts are essential components used to create secure connections, whether for electrical purposes, like terminating wires or grounding, or for mechanical purposes, such as providing mounting points or reinforcing structural joints.
|
||||
|
||||
|
||||
// Set units
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
|
||||
// Import Constants
|
||||
import lugDiameter, lugHeadLength, lugThreadDiameter, lugLength, lugThreadDepth, lugSpacing from "globals.kcl"
|
||||
|
||||
customPlane = {
|
||||
plane = {
|
||||
origin = {
|
||||
x = lugSpacing / 2,
|
||||
y = -30 * mm(),
|
||||
z = 0
|
||||
},
|
||||
xAxis = { x = 1, y = 0, z = 0 },
|
||||
yAxis = { x = 0, y = -1, z = 0 },
|
||||
zAxis = { x = 0, y = 0, z = 1 }
|
||||
}
|
||||
}
|
||||
|
||||
fn lug(plane, length, diameter) {
|
||||
lugSketch = startSketchOn(customPlane)
|
||||
|> startProfileAt([0 + diameter / 2, 0], %)
|
||||
|> angledLineOfYLength({ angle = 70, length = lugHeadLength }, %)
|
||||
|> xLineTo(lugDiameter / 2, %)
|
||||
|> yLineTo(lugLength, %)
|
||||
|> tangentialArc({ offset = 90, radius = 3 * mm() }, %)
|
||||
|> xLineTo(0 + .001, %, $c1)
|
||||
|> yLineTo(lugThreadDepth, %)
|
||||
|> xLineTo(lugThreadDiameter, %)
|
||||
|> yLineTo(0, %)
|
||||
|> close()
|
||||
|> revolve({ axis = "Y" }, %)
|
||||
|> appearance(color = "#dbcd70", roughness = 90, metalness = 90)
|
||||
return lugSketch
|
||||
}
|
||||
|
||||
lug(customPlane, lugLength, lugDiameter)
|
25
public/kcl-samples/car-wheel-assembly/main.kcl
Normal file
25
public/kcl-samples/car-wheel-assembly/main.kcl
Normal file
@ -0,0 +1,25 @@
|
||||
// Car Wheel Assembly
|
||||
// A car wheel assembly with a rotor, tire, and lug nuts.
|
||||
|
||||
// Set units
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
import 'car-wheel.kcl' as carWheel
|
||||
import 'car-rotor.kcl' as carRotor
|
||||
import "brake-caliper.kcl" as brakeCaliper
|
||||
import 'lug-nut.kcl' as lugNut
|
||||
import 'car-tire.kcl' as carTire
|
||||
import lugCount from 'globals.kcl'
|
||||
|
||||
carRotor
|
||||
carWheel
|
||||
lugNut
|
||||
|> patternCircular3d(
|
||||
arcDegrees = 360,
|
||||
axis = [0, 1, 0],
|
||||
center = [0, 0, 0],
|
||||
instances = lugCount,
|
||||
rotateDuplicates = false
|
||||
)
|
||||
brakeCaliper
|
||||
carTire
|
47
public/kcl-samples/color-cube/main.kcl
Normal file
47
public/kcl-samples/color-cube/main.kcl
Normal file
@ -0,0 +1,47 @@
|
||||
// Color Cube
|
||||
// This is a color cube centered about the origin. It is used to help determine orientation in the scene.
|
||||
|
||||
// Set unit
|
||||
@settings(defaultLengthUnit = mm)
|
||||
|
||||
// Globals referenced in drawRectangle
|
||||
size = 100
|
||||
halfSize = size/2
|
||||
extrudeLength = 1.0
|
||||
metalConstant = 50
|
||||
roughnessConstant = 50
|
||||
|
||||
// Create planes for 6 sides of a cube
|
||||
bluePlane = offsetPlane('XY', offset = halfSize)
|
||||
yellowPlane = offsetPlane('XY', offset = -halfSize)
|
||||
greenPlane = offsetPlane('XZ', offset = -halfSize)
|
||||
purplePlane = offsetPlane('-XZ', offset = -halfSize)
|
||||
redPlane = offsetPlane('YZ', offset = halfSize - extrudeLength)
|
||||
tealPlane = offsetPlane('YZ', offset = -halfSize)
|
||||
|
||||
// Sketch a rectangle centered at the origin of the profile
|
||||
fn sketchRectangle (profile, color) {
|
||||
return profile
|
||||
|> startProfileAt([-halfSize, halfSize], %)
|
||||
|> angledLine([0, size], %, $rectangleSegmentA001)
|
||||
|> angledLine([
|
||||
segAng(rectangleSegmentA001) - 90,
|
||||
size
|
||||
], %, $rectangleSegmentB001)
|
||||
|> angledLine([
|
||||
segAng(rectangleSegmentA001),
|
||||
-segLen(rectangleSegmentA001)
|
||||
], %, $rectangleSegmentC001)
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
|> extrude(%, length = extrudeLength)
|
||||
|> appearance(color = color, metalness = metalConstant, roughness = roughnessConstant)
|
||||
}
|
||||
|
||||
// Sketch each side of the cube
|
||||
sketchRectangle(bluePlane,'#0000FF')
|
||||
sketchRectangle(yellowPlane,'#FFFF00')
|
||||
sketchRectangle(greenPlane,'#00FF00')
|
||||
sketchRectangle(redPlane,'#FF0000')
|
||||
sketchRectangle(tealPlane,'#00FFFF')
|
||||
sketchRectangle(purplePlane,'#FF00FF')
|
51
public/kcl-samples/cycloidal-gear/main.kcl
Normal file
51
public/kcl-samples/cycloidal-gear/main.kcl
Normal file
@ -0,0 +1,51 @@
|
||||
// Cycloidal Gear
|
||||
// A cycloidal gear is a gear with a continuous, curved tooth profile. They are used in watchmaking and high precision robotics actuation
|
||||
|
||||
// Set Units
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
|
||||
fn cycloidalGear(gearPitch, gearHeight, holeDiameter, helixAngle) {
|
||||
// Create a function to draw the gear profile as a sketch. Rotate each profile about the gear's axis by an helix angle proportional to the total gear height
|
||||
fn gearSketch(gHeight) {
|
||||
helixAngleP = helixAngle * gHeight / gearHeight
|
||||
gearProfile = startSketchOn(offsetPlane("XY", offset = gHeight))
|
||||
|> startProfileAt([
|
||||
gearPitch * 1.55 * cos(toRadians(helixAngleP)) + gearPitch * sin(toRadians(-helixAngleP)),
|
||||
gearPitch * 1.55 * sin(toRadians(helixAngleP)) + gearPitch * cos(toRadians(-helixAngleP))
|
||||
], %)
|
||||
|> arc({
|
||||
angleStart = 90 + helixAngleP,
|
||||
angleEnd = -90 + helixAngleP,
|
||||
radius = gearPitch
|
||||
}, %)
|
||||
|> tangentialArc({
|
||||
radius = gearPitch * 1.67,
|
||||
offset = 60
|
||||
}, %)
|
||||
|> tangentialArc({ radius = gearPitch, offset = -180 }, %)
|
||||
|> tangentialArc({
|
||||
radius = gearPitch * 1.67,
|
||||
offset = 60
|
||||
}, %)
|
||||
|> tangentialArc({ radius = gearPitch, offset = -180 }, %)
|
||||
|> tangentialArcTo([profileStartX(%), profileStartY(%)], %)
|
||||
|> close(%)
|
||||
|> hole(circle(
|
||||
center = [0, 0],
|
||||
radius = holeDiameter / 2
|
||||
), %)
|
||||
return gearProfile
|
||||
}
|
||||
|
||||
// Draw sketches of the gear profile along the gear height and loft them together
|
||||
gearLoft = loft([
|
||||
gearSketch(0),
|
||||
gearSketch(gearHeight / 2),
|
||||
gearSketch(gearHeight)
|
||||
])
|
||||
|
||||
return gearLoft
|
||||
}
|
||||
|
||||
cycloidalGear(.3, 1.5, 0.297, -80)
|
90
public/kcl-samples/dodecahedron/main.kcl
Normal file
90
public/kcl-samples/dodecahedron/main.kcl
Normal file
@ -0,0 +1,90 @@
|
||||
// Hollow Dodecahedron
|
||||
// A regular dodecahedron or pentagonal dodecahedron is a dodecahedron composed of regular pentagonal faces, three meeting at each vertex. This example shows constructing the individual faces of the dodecahedron and extruding inwards.
|
||||
|
||||
// Set units
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
// Input parameters
|
||||
// circumscribed radius
|
||||
circR = 25
|
||||
|
||||
// Calculated parameters
|
||||
// thickness of the dodecahedron
|
||||
wallThickness = circR * 0.2
|
||||
|
||||
// angle between faces in radians
|
||||
dihedral = acos(-(sqrt(5) / 5))
|
||||
|
||||
// inscribed radius
|
||||
inscR = circR / 15 * sqrt(75 + 30 * sqrt(5))
|
||||
|
||||
// pentagon edge length
|
||||
edgeL = 4 * circR / (sqrt(3) * (1 + sqrt(5)))
|
||||
|
||||
// pentagon radius
|
||||
pentR = edgeL / 2 / sin(toRadians(36))
|
||||
|
||||
// Define a plane for the bottom angled face
|
||||
plane = {
|
||||
plane = {
|
||||
origin = [
|
||||
-inscR * cos(toRadians(toDegrees(dihedral) - 90)),
|
||||
0,
|
||||
inscR - (inscR * sin(toRadians(toDegrees(dihedral) - 90)))
|
||||
],
|
||||
xAxis = [cos(dihedral), 0.0, sin(dihedral)],
|
||||
yAxis = [0, 1, 0],
|
||||
zAxis = [sin(dihedral), 0, -cos(dihedral)]
|
||||
}
|
||||
}
|
||||
|
||||
// Create a regular pentagon inscribed in a circle of radius pentR
|
||||
bottomFace = startSketchOn('XY')
|
||||
|> polygon({
|
||||
radius = pentR,
|
||||
numSides = 5,
|
||||
center = [0, 0],
|
||||
inscribed = true
|
||||
}, %)
|
||||
|
||||
bottomSideFace = startSketchOn(plane)
|
||||
|> polygon({
|
||||
radius = pentR,
|
||||
numSides = 5,
|
||||
center = [0, 0],
|
||||
inscribed = true
|
||||
}, %)
|
||||
|
||||
// Extrude the faces in each plane
|
||||
bottom = extrude(bottomFace, length = wallThickness)
|
||||
bottomSide = extrude(bottomSideFace, length = wallThickness)
|
||||
|
||||
// Pattern the sides so we have a full dodecahedron
|
||||
bottomBowl = patternCircular3d(
|
||||
bottomSide,
|
||||
instances = 5,
|
||||
axis = [0, 0, 1],
|
||||
center = [0, 0, 0],
|
||||
arcDegrees = 360,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
|
||||
// pattern the bottom to create the top face
|
||||
patternCircular3d(
|
||||
bottom,
|
||||
instances = 2,
|
||||
axis = [0, 1, 0],
|
||||
center = [0, 0, inscR],
|
||||
arcDegrees = 360,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
|
||||
// pattern the bottom angled faces to create the top
|
||||
patternCircular3d(
|
||||
bottomBowl,
|
||||
instances = 2,
|
||||
axis = [0, 1, 0],
|
||||
center = [0, 0, inscR],
|
||||
arcDegrees = 360,
|
||||
rotateDuplicates = true
|
||||
)
|
196
public/kcl-samples/enclosure/main.kcl
Normal file
196
public/kcl-samples/enclosure/main.kcl
Normal file
@ -0,0 +1,196 @@
|
||||
// Enclosure
|
||||
// An enclosure body and sealing lid for storing items
|
||||
|
||||
// Set units
|
||||
@settings(defaultLengthUnit = mm)
|
||||
|
||||
length = 175
|
||||
width = 125
|
||||
height = 70
|
||||
wallThickness = 3
|
||||
holeDia = 4
|
||||
|
||||
// Model a box with base enclosure dimensions
|
||||
sketch001 = startSketchOn('XY')
|
||||
|> startProfileAt([0, 0], %)
|
||||
|> angledLine([0, width], %, $rectangleSegmentA001)
|
||||
|> angledLine([
|
||||
segAng(rectangleSegmentA001) + 90,
|
||||
length
|
||||
], %, $rectangleSegmentB001)
|
||||
|> angledLine([
|
||||
segAng(rectangleSegmentA001),
|
||||
-segLen(rectangleSegmentA001)
|
||||
], %, $rectangleSegmentC001)
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $rectangleSegmentD001)
|
||||
|> close()
|
||||
extrude001 = extrude(sketch001, length = height)
|
||||
|> fillet(
|
||||
radius = wallThickness * 4,
|
||||
tags = [
|
||||
getNextAdjacentEdge(rectangleSegmentA001),
|
||||
getNextAdjacentEdge(rectangleSegmentB001),
|
||||
getNextAdjacentEdge(rectangleSegmentC001),
|
||||
getNextAdjacentEdge(rectangleSegmentD001)
|
||||
]
|
||||
)
|
||||
|
||||
// Apply a shell to the enclosure base to create the internal storage
|
||||
|> shell(
|
||||
faces = ["end"],
|
||||
thickness = wallThickness
|
||||
)
|
||||
|
||||
// Define a function to create the internal structure to secure a fastener at each corner
|
||||
fn function001(originStart) {
|
||||
// Create a plane to sketch on shell interior
|
||||
plane001 = {
|
||||
plane = {
|
||||
origin = [0.0, 0.0, wallThickness],
|
||||
xAxis = [1.0, 0.0, 0.0],
|
||||
yAxis = [0.0, 1.0, 0.0],
|
||||
zAxis = [0.0, 0.0, 1.0]
|
||||
}
|
||||
}
|
||||
|
||||
// Create a pillar with a fasterner hole at the center
|
||||
sketch002 = startSketchOn(plane001)
|
||||
|> circle(
|
||||
center = [originStart[0], originStart[1]],
|
||||
radius = holeDia + wallThickness
|
||||
)
|
||||
|> hole(circle(
|
||||
center = [originStart[0], originStart[1]],
|
||||
radius = holeDia
|
||||
), %)
|
||||
extrude002 = extrude(sketch002, length = height - wallThickness)
|
||||
|
||||
return extrude002
|
||||
}
|
||||
|
||||
// Place the internal pillar at each corner
|
||||
function001([
|
||||
wallThickness * 3 + holeDia,
|
||||
wallThickness * 3 + holeDia
|
||||
])
|
||||
function001([
|
||||
wallThickness * 3 + holeDia,
|
||||
length - (wallThickness * 3 + holeDia)
|
||||
])
|
||||
function001([
|
||||
width - (wallThickness * 3 + holeDia),
|
||||
wallThickness * 3 + holeDia
|
||||
])
|
||||
function001([
|
||||
width - (wallThickness * 3 + holeDia),
|
||||
length - (wallThickness * 3 + holeDia)
|
||||
])
|
||||
|
||||
// Define lid position and outer surface
|
||||
sketch003 = startSketchOn('XY')
|
||||
|> startProfileAt([width * 1.2, 0], %)
|
||||
|> angledLine([0, width], %, $rectangleSegmentA002)
|
||||
|> angledLine([
|
||||
segAng(rectangleSegmentA001) + 90,
|
||||
length
|
||||
], %, $rectangleSegmentB002)
|
||||
|> angledLine([
|
||||
segAng(rectangleSegmentA001),
|
||||
-segLen(rectangleSegmentA001)
|
||||
], %, $rectangleSegmentC002)
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $rectangleSegmentD002)
|
||||
|> close()
|
||||
|> hole(circle(
|
||||
center = [
|
||||
width * 1.2 + wallThickness * 3 + holeDia,
|
||||
wallThickness * 3 + holeDia
|
||||
],
|
||||
radius = holeDia
|
||||
), %)
|
||||
|> hole(circle(
|
||||
center = [
|
||||
width * 1.2 + wallThickness * 3 + holeDia,
|
||||
length - (wallThickness * 3 + holeDia)
|
||||
],
|
||||
radius = holeDia
|
||||
), %)
|
||||
|> hole(circle(
|
||||
center = [
|
||||
width * 2.2 - (wallThickness * 3 + holeDia),
|
||||
wallThickness * 3 + holeDia
|
||||
],
|
||||
radius = holeDia
|
||||
), %)
|
||||
|> hole(circle(
|
||||
center = [
|
||||
width * 2.2 - (wallThickness * 3 + holeDia),
|
||||
length - (wallThickness * 3 + holeDia)
|
||||
],
|
||||
radius = holeDia
|
||||
), %)
|
||||
extrude003 = extrude(sketch003, length = wallThickness)
|
||||
|> fillet(
|
||||
radius = wallThickness * 4,
|
||||
tags = [
|
||||
getNextAdjacentEdge(rectangleSegmentA002),
|
||||
getNextAdjacentEdge(rectangleSegmentB002),
|
||||
getNextAdjacentEdge(rectangleSegmentC002),
|
||||
getNextAdjacentEdge(rectangleSegmentD002)
|
||||
]
|
||||
)
|
||||
|
||||
// Define lid inner and sealing surfaces
|
||||
sketch004 = startSketchOn(extrude003, 'END')
|
||||
|> startProfileAt([
|
||||
width * 1.2 + wallThickness,
|
||||
wallThickness
|
||||
], %)
|
||||
|> angledLine([0, width - (2 * wallThickness)], %, $rectangleSegmentA003)
|
||||
|> angledLine([
|
||||
segAng(rectangleSegmentA003) + 90,
|
||||
length - (2 * wallThickness)
|
||||
], %, $rectangleSegmentB003)
|
||||
|> angledLine([
|
||||
segAng(rectangleSegmentA003),
|
||||
-segLen(rectangleSegmentA003)
|
||||
], %, $rectangleSegmentC003)
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $rectangleSegmentD003)
|
||||
|> close()
|
||||
|> hole(circle(
|
||||
center = [
|
||||
width * 1.2 + wallThickness * 3 + holeDia,
|
||||
wallThickness * 3 + holeDia
|
||||
],
|
||||
radius = holeDia + wallThickness
|
||||
), %)
|
||||
|> hole(circle(
|
||||
center = [
|
||||
width * 1.2 + wallThickness * 3 + holeDia,
|
||||
length - (wallThickness * 3 + holeDia)
|
||||
],
|
||||
radius = holeDia + wallThickness
|
||||
), %)
|
||||
|> hole(circle(
|
||||
center = [
|
||||
width * 2.2 - (wallThickness * 3 + holeDia),
|
||||
wallThickness * 3 + holeDia
|
||||
],
|
||||
radius = holeDia + wallThickness
|
||||
), %)
|
||||
|> hole(circle(
|
||||
center = [
|
||||
width * 2.2 - (wallThickness * 3 + holeDia),
|
||||
length - (wallThickness * 3 + holeDia)
|
||||
],
|
||||
radius = holeDia + wallThickness
|
||||
), %)
|
||||
extrude004 = extrude(sketch004, length = wallThickness)
|
||||
|> fillet(
|
||||
radius = wallThickness * 3,
|
||||
tags = [
|
||||
getNextAdjacentEdge(rectangleSegmentA003),
|
||||
getNextAdjacentEdge(rectangleSegmentB003),
|
||||
getNextAdjacentEdge(rectangleSegmentC003),
|
||||
getNextAdjacentEdge(rectangleSegmentD003)
|
||||
]
|
||||
)
|
152
public/kcl-samples/exhaust-manifold/main.kcl
Normal file
152
public/kcl-samples/exhaust-manifold/main.kcl
Normal file
@ -0,0 +1,152 @@
|
||||
// Exhaust Manifold
|
||||
// A welded exhaust header for an inline 4-cylinder engine
|
||||
|
||||
// Set Units
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
// Define Constants
|
||||
primaryTubeDiameter = 1.625
|
||||
wallThickness = 0.080
|
||||
plateHeight = 0.125
|
||||
bendRadius = 3
|
||||
|
||||
// Create a function to draw each primary tube with specified lengths and angles
|
||||
fn primaryTube(n, angle001, length001, length002, length003) {
|
||||
// Create an index for the function
|
||||
pos001 = n * 2
|
||||
|
||||
// Define a plane for each sweep path defined by an angle
|
||||
sweepPlane = {
|
||||
plane = {
|
||||
origin = [pos001, 0.0, 0],
|
||||
xAxis = [
|
||||
sin(toRadians(-angle001)),
|
||||
cos(toRadians(-angle001)),
|
||||
0.0
|
||||
],
|
||||
yAxis = [0.0, 0.0, 1.0],
|
||||
zAxis = [1.0, 0.0, 0.0]
|
||||
}
|
||||
}
|
||||
|
||||
// Draw a path for each sweep
|
||||
sweepPath = startSketchOn(sweepPlane)
|
||||
|> startProfileAt([0, plateHeight], %)
|
||||
|> line(end = [0, length001])
|
||||
|> tangentialArc({ offset = -80, radius = bendRadius }, %, $arc01)
|
||||
|> angledLine({
|
||||
angle = tangentToEnd(arc01),
|
||||
length = length002
|
||||
}, %)
|
||||
|> tangentialArc({ offset = 85, radius = bendRadius }, %, $arc02)
|
||||
|> angledLine({
|
||||
angle = tangentToEnd(arc02),
|
||||
length = length003
|
||||
}, %)
|
||||
|
||||
// Create the cross section of each tube and sweep them
|
||||
sweepProfile = startSketchOn('XY')
|
||||
|> circle(
|
||||
center = [pos001, 0],
|
||||
radius = primaryTubeDiameter / 2
|
||||
)
|
||||
|> hole(circle(
|
||||
center = [pos001, 0],
|
||||
radius = primaryTubeDiameter / 2 - wallThickness
|
||||
), %)
|
||||
|> sweep(path = sweepPath)
|
||||
|
||||
return { }
|
||||
}
|
||||
|
||||
// Draw a primary tube for each cylinder with specified lengths and angles
|
||||
primaryTube(0, 0, 3, 6, 5)
|
||||
primaryTube(1, 1, 3, 6, 5)
|
||||
primaryTube(2, 24.3, 5, 5, 3)
|
||||
primaryTube(3, 25.2, 5, 5, 3)
|
||||
|
||||
// Create the mounting flange for the header
|
||||
flangeSketch = startSketchOn('XY')
|
||||
|> startProfileAt([3 + 1.3, -1.25], %)
|
||||
|> xLine(-2.6, %, $seg01)
|
||||
|> tangentialArc({ radius = .3, offset = -40 }, %)
|
||||
|> tangentialArc({ radius = .9, offset = 80 }, %)
|
||||
|> tangentialArc({ radius = .3, offset = -40 }, %)
|
||||
|> xLine(-1.4, %, $seg03)
|
||||
|> yLine(segLen(seg01), %, $seg04)
|
||||
|> xLine(3.1, %, $seg05)
|
||||
|> tangentialArc({ radius = .3, offset = -40 }, %)
|
||||
|> tangentialArc({ radius = 1.5, offset = 80 }, %)
|
||||
|> tangentialArc({ radius = .3, offset = -40 }, %)
|
||||
|> xLine(segLen(seg05), %, $seg07)
|
||||
|> yLineTo(profileStartY(%), %, $seg08)
|
||||
|> xLine(-segLen(seg03), %, $seg09)
|
||||
|> tangentialArc({ radius = .3, offset = -40 }, %)
|
||||
|> tangentialArc({ radius = .9, offset = 80 }, %)
|
||||
|> tangentialArcTo([profileStartX(%), profileStartY(%)], %)
|
||||
|> close()
|
||||
|
||||
// Create openings in the flange to accommodate each tube
|
||||
|> hole(circle(
|
||||
center = [0, 0],
|
||||
radius = primaryTubeDiameter / 2 - wallThickness
|
||||
), %)
|
||||
|> hole(circle(
|
||||
center = [2, 0],
|
||||
radius = primaryTubeDiameter / 2 - wallThickness
|
||||
), %)
|
||||
|> hole(circle(
|
||||
center = [4, 0],
|
||||
radius = primaryTubeDiameter / 2 - wallThickness
|
||||
), %)
|
||||
|> hole(circle(
|
||||
center = [6, 0],
|
||||
radius = primaryTubeDiameter / 2 - wallThickness
|
||||
), %)
|
||||
|
||||
// Add mounting holes to the flange
|
||||
|> hole(circle(
|
||||
center = [
|
||||
-primaryTubeDiameter * .6,
|
||||
-primaryTubeDiameter * .6
|
||||
],
|
||||
radius = 0.25 / 2
|
||||
), %)
|
||||
|> hole(circle(
|
||||
center = [
|
||||
primaryTubeDiameter * .6,
|
||||
primaryTubeDiameter * .6
|
||||
],
|
||||
radius = 0.25 / 2
|
||||
), %)
|
||||
|> hole(circle(
|
||||
center = [
|
||||
3 * 2 - (primaryTubeDiameter * .6),
|
||||
primaryTubeDiameter * .6
|
||||
],
|
||||
radius = 0.25 / 2
|
||||
), %)
|
||||
|> hole(circle(
|
||||
center = [
|
||||
3 * 2 + primaryTubeDiameter * .6,
|
||||
-primaryTubeDiameter * .6
|
||||
],
|
||||
radius = 0.25 / 2
|
||||
), %)
|
||||
|
||||
// Extrude the flange and fillet the edges
|
||||
|> extrude(length = plateHeight)
|
||||
|> fillet(
|
||||
radius = 1.5,
|
||||
tags = [
|
||||
getNextAdjacentEdge(seg04),
|
||||
getNextAdjacentEdge(seg07)
|
||||
]
|
||||
)
|
||||
|> fillet(
|
||||
radius = .25,
|
||||
tags = [
|
||||
getNextAdjacentEdge(seg03),
|
||||
getNextAdjacentEdge(seg08)
|
||||
]
|
||||
)
|
83
public/kcl-samples/flange-with-patterns/main.kcl
Normal file
83
public/kcl-samples/flange-with-patterns/main.kcl
Normal file
@ -0,0 +1,83 @@
|
||||
// Flange
|
||||
// A flange is a flat rim, collar, or rib, typically forged or cast, that is used to strengthen an object, guide it, or attach it to another object. Flanges are known for their use in various applications, including piping, plumbing, and mechanical engineering, among others.
|
||||
|
||||
// Set units
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
// Define constants
|
||||
mountingHoleDia = .625
|
||||
baseDia = 4.625
|
||||
pipeDia = 1.25
|
||||
thickness = .625
|
||||
totalThickness = 0.813
|
||||
topTotalDiameter = 2.313
|
||||
bottomThickness = 0.06
|
||||
bottomTotalDiameter = 2.5
|
||||
mountingHolePlacementDiameter = 3.5
|
||||
baseThickness = .625
|
||||
topTotalThickness = totalThickness - (bottomThickness + baseThickness)
|
||||
holeLocator = baseDia - 8
|
||||
nHoles = 4
|
||||
|
||||
// Add assertion so nHoles are always greater than 1
|
||||
assertGreaterThan(nHoles, 1, "nHoles must be greater than 1")
|
||||
|
||||
// Create the circular pattern for the mounting holes
|
||||
circles = startSketchOn('XY')
|
||||
|> circle(
|
||||
center = [mountingHolePlacementDiameter / 2, 0],
|
||||
radius = mountingHoleDia / 2
|
||||
)
|
||||
|> patternCircular2d(
|
||||
arcDegrees = 360,
|
||||
center = [0, 0],
|
||||
instances = nHoles,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
|
||||
// Create the base of the flange and add the mounting holes
|
||||
flangeBase = startSketchOn('XY')
|
||||
|> circle(
|
||||
center = [0, 0],
|
||||
radius = baseDia / 2
|
||||
)
|
||||
|> hole(circles, %)
|
||||
|> hole(circle(
|
||||
center = [0, 0],
|
||||
radius = pipeDia / 2
|
||||
), %)
|
||||
|> extrude(length = baseThickness)
|
||||
|
||||
// Plane for top face
|
||||
topFacePlane = {
|
||||
plane = {
|
||||
origin = { x = 0, y = 0, z = baseThickness },
|
||||
xAxis = { x = 1, y = 0, z = 0 },
|
||||
yAxis = { x = 0, y = 1, z = 0 },
|
||||
zAxis = { x = 0, y = 0, z = 1 }
|
||||
}
|
||||
}
|
||||
|
||||
// Create the extrusion on the top of the flange base
|
||||
topExtrusion = startSketchOn(topFacePlane)
|
||||
|> circle(
|
||||
center = [0, 0],
|
||||
radius = topTotalDiameter / 2
|
||||
)
|
||||
|> hole(circle(
|
||||
center = [0, 0],
|
||||
radius = pipeDia / 2
|
||||
), %)
|
||||
|> extrude(length = topTotalThickness)
|
||||
|
||||
// Create the extrusion on the bottom of the flange base
|
||||
bottomExtrusion = startSketchOn("XY")
|
||||
|> circle(
|
||||
center = [0, 0],
|
||||
radius = bottomTotalDiameter / 2
|
||||
)
|
||||
|> hole(circle(
|
||||
center = [0, 0],
|
||||
radius = pipeDia / 2
|
||||
), %)
|
||||
|> extrude(length = -bottomThickness)
|
87
public/kcl-samples/flange-xy/main.kcl
Normal file
87
public/kcl-samples/flange-xy/main.kcl
Normal file
@ -0,0 +1,87 @@
|
||||
// Flange with XY coordinates
|
||||
// A flange is a flat rim, collar, or rib, typically forged or cast, that is used to strengthen an object, guide it, or attach it to another object. Flanges are known for their use in various applications, including piping, plumbing, and mechanical engineering, among others.
|
||||
|
||||
// Set units
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
// Define constants
|
||||
mountingHoleDia = .625
|
||||
baseDia = 4.625
|
||||
pipeDia = 1.25
|
||||
thickness = .625
|
||||
totalThickness = 0.813
|
||||
topTotalDiameter = 2.313
|
||||
bottomThickness = 0.06
|
||||
bottomTotalDiameter = 2.5
|
||||
mountingHolePlacementDiameter = 3.5
|
||||
baseThickness = .625
|
||||
topTotalThickness = totalThickness - (bottomThickness + baseThickness)
|
||||
holeLocator = baseDia - 8
|
||||
nHoles = 4
|
||||
|
||||
// Add assertion so nHoles are always greater than 1
|
||||
assertGreaterThan(nHoles, 1, "nHoles must be greater than 1")
|
||||
|
||||
// Create the flange base and the six mounting holes
|
||||
flangeBase = startSketchOn('XY')
|
||||
|> circle(
|
||||
center = [0, 0],
|
||||
radius = baseDia / 2
|
||||
)
|
||||
|> hole(circle(
|
||||
center = [mountingHolePlacementDiameter / 2, 0],
|
||||
radius = mountingHoleDia / 2
|
||||
), %)
|
||||
|> hole(circle(
|
||||
center = [0, mountingHolePlacementDiameter / 2],
|
||||
radius = mountingHoleDia / 2
|
||||
), %)
|
||||
|> hole(circle(
|
||||
center = [-mountingHolePlacementDiameter / 2, 0],
|
||||
radius = mountingHoleDia / 2
|
||||
), %)
|
||||
|> hole(circle(
|
||||
center = [0, -mountingHolePlacementDiameter / 2],
|
||||
radius = mountingHoleDia / 2
|
||||
), %)
|
||||
|> hole(circle(
|
||||
center = [0, 0],
|
||||
radius = pipeDia / 2
|
||||
), %)
|
||||
|> extrude(length = baseThickness)
|
||||
|
||||
// Plane for top face
|
||||
topFacePlane = {
|
||||
plane = {
|
||||
origin = { x = 0, y = 0, z = baseThickness },
|
||||
xAxis = { x = 1, y = 0, z = 0 },
|
||||
yAxis = { x = 0, y = 1, z = 0 },
|
||||
zAxis = { x = 0, y = 0, z = 1 }
|
||||
}
|
||||
}
|
||||
|
||||
// Create the extrusion on the top of the flange base
|
||||
topExtrusion = startSketchOn(topFacePlane, 'end')
|
||||
|> circle(
|
||||
center = [0, 0],
|
||||
radius = topTotalDiameter / 2
|
||||
)
|
||||
|> hole(circle(
|
||||
center = [0, 0],
|
||||
radius = pipeDia / 2
|
||||
), %)
|
||||
|> extrude(length = topTotalThickness)
|
||||
|
||||
// Create the extrusion on the bottom of the flange base
|
||||
bottomExtrusion = startSketchOn("XY")
|
||||
|> circle(
|
||||
center = [0, 0],
|
||||
radius = bottomTotalDiameter / 2
|
||||
)
|
||||
|> hole(circle(
|
||||
center = [0, 0],
|
||||
radius = pipeDia / 2
|
||||
), %)
|
||||
|> extrude(length = -bottomThickness)
|
||||
|
||||
// https://www.mcmaster.com/44685K193/
|
159
public/kcl-samples/focusrite-scarlett-mounting-bracket/main.kcl
Normal file
159
public/kcl-samples/focusrite-scarlett-mounting-bracket/main.kcl
Normal file
@ -0,0 +1,159 @@
|
||||
// A mounting bracket for the Focusrite Scarlett Solo audio interface
|
||||
// This is a bracket that holds an audio device underneath a desk or shelf. The audio device has dimensions of 144mm wide, 80mm length and 45mm depth with fillets of 6mm. This mounting bracket is designed to be 3D printed with PLA material
|
||||
|
||||
// Set units
|
||||
@settings(defaultLengthUnit = mm)
|
||||
|
||||
// define constants in mm
|
||||
radius = 6.0
|
||||
width = 144.0
|
||||
length = 80.0
|
||||
depth = 45.0
|
||||
thk = 4
|
||||
holeDiam = 5
|
||||
tabLength = 25
|
||||
tabWidth = 12
|
||||
tabThk = 4
|
||||
|
||||
// define a rectangular shape func
|
||||
fn rectShape(pos, w, l) {
|
||||
rr = startSketchOn('xy')
|
||||
|> startProfileAt([pos[0] - (w / 2), pos[1] - (l / 2)], %)
|
||||
|> line(endAbsolute = [pos[0] + w / 2, pos[1] - (l / 2)], tag = $edge01)
|
||||
|> line(endAbsolute = [pos[0] + w / 2, pos[1] + l / 2], tag = $edge02)
|
||||
|> line(endAbsolute = [pos[0] - (w / 2), pos[1] + l / 2], tag = $edge03)
|
||||
|> close(tag = $edge04)
|
||||
return rr
|
||||
}
|
||||
|
||||
// define the bracket plane
|
||||
bracketPlane = {
|
||||
plane = {
|
||||
origin = { x = 0, y = length / 2 + thk, z = 0 },
|
||||
xAxis = { x = 1, y = 0, z = 0 },
|
||||
yAxis = { x = 0, y = 0, z = 1 },
|
||||
zAxis = { x = 0, y = -1, z = 0 }
|
||||
}
|
||||
}
|
||||
|
||||
// build the bracket sketch around the body
|
||||
fn bracketSketch(w, d, t) {
|
||||
s = startSketchOn(bracketPlane)
|
||||
|> startProfileAt([-w / 2 - t, d + t], %)
|
||||
|> line(endAbsolute = [-w / 2 - t, -t], tag = $edge1)
|
||||
|> line(endAbsolute = [w / 2 + t, -t], tag = $edge2)
|
||||
|> line(endAbsolute = [w / 2 + t, d + t], tag = $edge3)
|
||||
|> line(endAbsolute = [w / 2, d + t], tag = $edge4)
|
||||
|> line(endAbsolute = [w / 2, 0], tag = $edge5)
|
||||
|> line(endAbsolute = [-w / 2, 0], tag = $edge6)
|
||||
|> line(endAbsolute = [-w / 2, d + t], tag = $edge7)
|
||||
|> close(tag = $edge8)
|
||||
return s
|
||||
}
|
||||
|
||||
// build the body of the bracket
|
||||
bs = bracketSketch(width, depth, thk)
|
||||
bracketBody = bs
|
||||
|> extrude(length = length + 2 * thk)
|
||||
|> fillet(
|
||||
radius = radius,
|
||||
tags = [
|
||||
getPreviousAdjacentEdge(bs.tags.edge7),
|
||||
getPreviousAdjacentEdge(bs.tags.edge2),
|
||||
getPreviousAdjacentEdge(bs.tags.edge3),
|
||||
getPreviousAdjacentEdge(bs.tags.edge6)
|
||||
]
|
||||
)
|
||||
|
||||
// define the tab plane
|
||||
tabPlane = {
|
||||
plane = {
|
||||
origin = { x = 0, y = 0, z = depth + thk },
|
||||
xAxis = { x = 1, y = 0, z = 0 },
|
||||
yAxis = { x = 0, y = 1, z = 0 },
|
||||
zAxis = { x = 0, y = 0, z = 1 }
|
||||
}
|
||||
}
|
||||
|
||||
// build the tabs of the mounting bracket (right side)
|
||||
tabsR = startSketchOn(tabPlane)
|
||||
|> startProfileAt([width / 2 + thk, length / 2 + thk], %)
|
||||
|> line(end = [tabWidth, -tabLength / 3], tag = $edge11)
|
||||
|> line(end = [0, -tabLength / 3 * 2], tag = $edge12)
|
||||
|> line(end = [-tabWidth, -tabLength / 3], tag = $edge13)
|
||||
|> close(tag = $edge14)
|
||||
|> hole(circle(
|
||||
center = [
|
||||
width / 2 + thk + tabWidth / 2,
|
||||
length / 2 + thk - (tabLength / (3 / 2))
|
||||
],
|
||||
radius = holeDiam / 2
|
||||
), %)
|
||||
|> extrude(length = -tabThk)
|
||||
|> fillet(
|
||||
radius = holeDiam / 2,
|
||||
tags = [
|
||||
getNextAdjacentEdge(edge11),
|
||||
getNextAdjacentEdge(edge12)
|
||||
]
|
||||
)
|
||||
|> patternLinear3d(
|
||||
axis = [0, -1, 0],
|
||||
instances = 2,
|
||||
distance = length + 2 * thk - (tabLength * 4 / 3)
|
||||
)
|
||||
|
||||
// build the tabs of the mounting bracket (left side)
|
||||
tabsL = startSketchOn(tabPlane)
|
||||
|> startProfileAt([-width / 2 - thk, length / 2 + thk], %)
|
||||
|> line(end = [-tabWidth, -tabLength / 3], tag = $edge21)
|
||||
|> line(end = [0, -tabLength / 3 * 2], tag = $edge22)
|
||||
|> line(end = [tabWidth, -tabLength / 3], tag = $edge23)
|
||||
|> close(tag = $edge24)
|
||||
|> hole(circle(
|
||||
center = [
|
||||
-width / 2 - thk - (tabWidth / 2),
|
||||
length / 2 + thk - (tabLength / (3 / 2))
|
||||
],
|
||||
radius = holeDiam / 2
|
||||
), %)
|
||||
|> extrude(length = -tabThk)
|
||||
|> fillet(
|
||||
radius = holeDiam / 2,
|
||||
tags = [
|
||||
getNextAdjacentEdge(edge21),
|
||||
getNextAdjacentEdge(edge22)
|
||||
]
|
||||
)
|
||||
|> patternLinear3d(
|
||||
axis = [0, -1, 0],
|
||||
instances = 2,
|
||||
distance = length + 2 * thk - (tabLength * 4 / 3)
|
||||
)
|
||||
|
||||
// define a plane for retention bumps
|
||||
retPlane = {
|
||||
plane = {
|
||||
origin = { x = -width / 2 + 20, y = 0, z = 0 },
|
||||
xAxis = { x = 0, y = 1, z = 0 },
|
||||
yAxis = { x = 0, y = 0, z = 1 },
|
||||
zAxis = { x = 1, y = 0, z = 0 }
|
||||
}
|
||||
}
|
||||
|
||||
// build the retention bump in the front
|
||||
retFront = startSketchOn(retPlane)
|
||||
|> startProfileAt([-length / 2 - thk, 0], %)
|
||||
|> line(end = [0, thk])
|
||||
|> line(end = [thk, -thk])
|
||||
|> close()
|
||||
|> extrude(length = width - 40)
|
||||
|
||||
// build the retention bump in the back
|
||||
retBack = startSketchOn(retPlane)
|
||||
|> startProfileAt([length / 2 + thk, 0], %)
|
||||
|> line(end = [0, thk])
|
||||
|> line(end = [-thk, 0])
|
||||
|> line(end = [0, -thk])
|
||||
|> close()
|
||||
|> extrude(length = width - 40)
|
166
public/kcl-samples/food-service-spatula/main.kcl
Normal file
166
public/kcl-samples/food-service-spatula/main.kcl
Normal file
@ -0,0 +1,166 @@
|
||||
// Food Service Spatula
|
||||
// Use these spatulas for mixing, flipping, and scraping.
|
||||
|
||||
// Set units
|
||||
@settings(defaultLengthUnit = mm)
|
||||
|
||||
// Define constants in millimeters (mm)
|
||||
flipperThickness = 3.5
|
||||
flipperLength = 70.0
|
||||
handleWidth = 15.0
|
||||
gripLength = 150.0
|
||||
flipperFilletRadius = 5.0
|
||||
flipperSlotWidth = 10.0
|
||||
gripWidth = 10.0
|
||||
gripHeight = 20.0
|
||||
gripFilletRadius = 3.0
|
||||
gripSlotWidth = 8.0
|
||||
|
||||
// function for drawing slots on a sketch given the start and end points as well as a width
|
||||
fn slot(sketch1, start, end, width) {
|
||||
angle = if start[0] == end[0] {
|
||||
if end[1] > start[1] {
|
||||
90
|
||||
} else {
|
||||
270
|
||||
}
|
||||
} else {
|
||||
if end[0] < start[0] {
|
||||
toDegrees(atan((end[1] - start[1]) / (end[0] - start[0]))) + 180
|
||||
} else {
|
||||
toDegrees( atan((end[1] - start[1]) / (end[0] - start[0])))
|
||||
}
|
||||
}
|
||||
dist = sqrt(pow(end[1] - start[1], 2) + pow(end[0] - start[0], 2))
|
||||
xstart = width / 2 * cos(toRadians(angle - 90)) + start[0]
|
||||
ystart = width / 2 * sin(toRadians(angle - 90)) + start[1]
|
||||
slotSketch = startProfileAt([xstart, ystart], sketch1)
|
||||
|> angledLine({ angle = angle, length = dist }, %, $line000)
|
||||
|> tangentialArc({ radius = width / 2, offset = 180 }, %, $arc000)
|
||||
|> angledLine({ angle = angle, length = -dist }, %, $line001)
|
||||
|> tangentialArcTo([profileStartX(%), profileStartY(%)], %, $arc001)
|
||||
|> close()
|
||||
return slotSketch
|
||||
}
|
||||
|
||||
// create a sketch on the "XY" plane
|
||||
sketch000 = startSketchOn('XY')
|
||||
|
||||
// create a profile of the flipper
|
||||
flipperProfile = startProfileAt([-flipperLength, -32.0], sketch000)
|
||||
|> line(end = [flipperLength, 2.0])
|
||||
|> yLine(60.0, %, $backEdge)
|
||||
|> line(end = [-flipperLength, 2.0])
|
||||
|> arc({
|
||||
angleEnd = 196.912390,
|
||||
angleStart = 163.087610,
|
||||
radius = 110.0
|
||||
}, %)
|
||||
|> close()
|
||||
|
||||
// create a profile of the middle
|
||||
slotProfile000 = slot(sketch000, [-25, 0], [-55, 0], flipperSlotWidth)
|
||||
|
||||
// create a profile of the top slot
|
||||
slotProfile001 = slot(sketch000, [-25, 18], [-55, 19], flipperSlotWidth)
|
||||
|
||||
// create a profile of the bottom slot
|
||||
slotProfile002 = slot(sketch000, [-25, -18], [-55, -19], flipperSlotWidth)
|
||||
|
||||
// create a profile with slots for the spatula
|
||||
spatulaProfile = flipperProfile
|
||||
|> hole(slotProfile000, %)
|
||||
|> hole(slotProfile001, %)
|
||||
|> hole(slotProfile002, %)
|
||||
|
||||
// extrude the profile to create the spatula flipper
|
||||
flipper = extrude(spatulaProfile, length = flipperThickness)
|
||||
|
||||
// fillet the edges of the flipper
|
||||
fillet(
|
||||
flipper,
|
||||
radius = flipperFilletRadius,
|
||||
tags = [
|
||||
getNextAdjacentEdge(backEdge),
|
||||
getPreviousAdjacentEdge(backEdge)
|
||||
]
|
||||
)
|
||||
|
||||
// create a sketch on the "XZ" plane offset by half the thickness
|
||||
sketch001 = startSketchOn(offsetPlane("XZ", offset = -handleWidth / 2))
|
||||
|
||||
// create a profile of the spatula handle
|
||||
handleProfile = startProfileAt([0.0, flipperThickness], sketch001)
|
||||
|> line(end = [31.819805, 31.819805], tag = $handleBottomEdge)
|
||||
|> line(end = [140.953893, 51.303021])
|
||||
|> line(end = [-1.710101, 4.698463])
|
||||
|> line(end = [-141.995517, -51.682142], tag = $handleTopEdge)
|
||||
|> line(end = [-36.139148, -36.139148])
|
||||
|> xLine(7.071068, %)
|
||||
|> close()
|
||||
|
||||
// create an extrusion extrude001
|
||||
handle = extrude(handleProfile, length = handleWidth)
|
||||
|
||||
// fillet the bend of the spatula handle
|
||||
fillet(
|
||||
handle,
|
||||
radius = 4,
|
||||
tags = [
|
||||
getNextAdjacentEdge(handleBottomEdge),
|
||||
getNextAdjacentEdge(handleTopEdge)
|
||||
]
|
||||
)
|
||||
|
||||
// define a plane which is at the end of the handle
|
||||
handlePlane = {
|
||||
plane = {
|
||||
origin = [208.593833, 0.0, 75.921946],
|
||||
xAxis = [0.342020, -0.0, -0.939693],
|
||||
yAxis = [0.0, 1.0, 0.0],
|
||||
zAxis = [0.939693, -0.0, 0.342020]
|
||||
}
|
||||
}
|
||||
|
||||
// create a sketch on the handle plane
|
||||
sketch002 = startSketchOn(handlePlane)
|
||||
|
||||
// create a profile of the grip
|
||||
gripProfile = startProfileAt([-26.806746, -10.0], sketch002)
|
||||
|> xLine(gripWidth - (2 * gripFilletRadius), %)
|
||||
|> arc({
|
||||
angleStart = -90.0,
|
||||
angleEnd = 0.0,
|
||||
radius = gripFilletRadius
|
||||
}, %)
|
||||
|> yLine(gripHeight - (2 * gripFilletRadius), %)
|
||||
|> arc({
|
||||
angleStart = 0.0,
|
||||
angleEnd = 90.0,
|
||||
radius = gripFilletRadius
|
||||
}, %)
|
||||
|> xLine(-(gripWidth - (2 * gripFilletRadius)), %)
|
||||
|> arc({
|
||||
angleStart = 90.0,
|
||||
angleEnd = 180.0,
|
||||
radius = gripFilletRadius
|
||||
}, %)
|
||||
|> yLine(-(gripHeight - (2 * gripFilletRadius)), %, $gripEdgeTop)
|
||||
|> arc({
|
||||
angleStart = 180.0,
|
||||
angleEnd = 270.0,
|
||||
radius = gripFilletRadius
|
||||
}, %)
|
||||
|> close()
|
||||
|
||||
// extrude the grip profile to create the grip
|
||||
grip = extrude(gripProfile, length = -gripLength)
|
||||
|
||||
// create a sketch on the grip for the hole
|
||||
sketch003 = startSketchOn(grip, gripEdgeTop)
|
||||
|
||||
// create a profile for the grip hole
|
||||
gripHoleProfile = slot(sketch003, [0, 200], [0, 210], gripSlotWidth)
|
||||
|
||||
// cut a hole in the grip
|
||||
extrude(gripHoleProfile, length = -gripWidth-20)
|
231
public/kcl-samples/french-press/main.kcl
Normal file
231
public/kcl-samples/french-press/main.kcl
Normal file
@ -0,0 +1,231 @@
|
||||
// French Press
|
||||
// A french press immersion coffee maker
|
||||
|
||||
// Set units
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
// Define constants
|
||||
carafeDiameter = 4.41
|
||||
carafeHeight = 7.32
|
||||
handleThickness = 0.65
|
||||
|
||||
// Upper ring of the metal structure
|
||||
sketch001 = startSketchOn('XZ')
|
||||
|> startProfileAt([carafeDiameter / 2, 5.7], %)
|
||||
|> angledLine([0, 0.1], %, $rectangleSegmentA001)
|
||||
|> angledLine([
|
||||
segAng(rectangleSegmentA001) - 90,
|
||||
-0.75
|
||||
], %, $rectangleSegmentB001)
|
||||
|> angledLine([
|
||||
segAng(rectangleSegmentA001),
|
||||
-segLen(rectangleSegmentA001)
|
||||
], %, $rectangleSegmentC001)
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
|> revolve({ angle = 360, axis = 'Y' }, %)
|
||||
|
||||
// Create an angled plane to sketch the supports
|
||||
plane001 = {
|
||||
plane = {
|
||||
origin = [-0.26, 0.26, 0.0],
|
||||
xAxis = [1, 1, 0.0],
|
||||
yAxis = [0.0, 0.0, 1.0],
|
||||
zAxis = [1.0, 0.0, 0.0]
|
||||
}
|
||||
}
|
||||
|
||||
// Cross section of the metal supports
|
||||
sketch002 = startSketchOn(plane001)
|
||||
|> startProfileAt([carafeDiameter / 2, 5.7], %)
|
||||
|> xLine(0.1, %)
|
||||
|> yLine(-5.2, %, $edge1)
|
||||
|> arc({
|
||||
angleStart = 180,
|
||||
angleEnd = 205,
|
||||
radius = 0.3
|
||||
}, %)
|
||||
|> angledLine({ angle = -60, length = 0.6 }, %, $edge2)
|
||||
|> arc({
|
||||
angleStart = 30,
|
||||
angleEnd = -120,
|
||||
radius = 0.6
|
||||
}, %)
|
||||
|> angledLineToY({ angle = 150, to = -0.2 }, %, $edge3)
|
||||
|> arc({
|
||||
angleStart = 60,
|
||||
angleEnd = 90,
|
||||
radius = 0.5
|
||||
}, %)
|
||||
|> xLineTo(0.1, %, $edgeLen)
|
||||
|> yLine(0.1, %)
|
||||
|> xLine(segLen(edgeLen) + 0.035, %, $edge4)
|
||||
|> arc({
|
||||
angleStart = 90,
|
||||
angleEnd = 60,
|
||||
radius = 0.6
|
||||
}, %)
|
||||
|> angledLine({
|
||||
angle = 150,
|
||||
length = -segLen(edge3) + 0.035
|
||||
}, %, $edge5)
|
||||
|> arc({
|
||||
angleStart = -120,
|
||||
angleEnd = 30,
|
||||
radius = 0.5
|
||||
}, %)
|
||||
|> angledLine({
|
||||
angle = -60,
|
||||
length = -segLen(edge2) + 0.035
|
||||
}, %, $edge6)
|
||||
|> arc({
|
||||
angleStart = 205,
|
||||
angleEnd = 180,
|
||||
radius = 0.6
|
||||
}, %)
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
|> extrude(length = 0.75)
|
||||
|> patternCircular3d(
|
||||
axis = [0, 0, 1],
|
||||
center = [0, 0, 0],
|
||||
instances = 4,
|
||||
arcDegrees = 360,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
|
||||
// Cross plate
|
||||
sketch003 = startSketchOn(offsetPlane('XY', offset = 1))
|
||||
|> circle(
|
||||
center = [0, 0],
|
||||
radius = carafeDiameter / 2 - 0.15
|
||||
)
|
||||
|
||||
extrude001 = extrude(sketch003, length = 0.050)
|
||||
|
||||
sketch004 = startSketchOn(extrude001, 'END')
|
||||
|> startProfileAt([0.3, 0.17], %)
|
||||
|> yLine(1.2, %)
|
||||
|> arc({
|
||||
angleStart = 90,
|
||||
angleEnd = -30,
|
||||
radius = 1.2
|
||||
}, %)
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
|> patternCircular2d(
|
||||
center = [0, 0],
|
||||
instances = 3,
|
||||
arcDegrees = 360,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
|
||||
extrude002 = extrude(sketch004, length = -0.050)
|
||||
|
||||
// Filter screen
|
||||
sketch005 = startSketchOn('XZ')
|
||||
|> startProfileAt([0.15, 1.11], %)
|
||||
|> xLineTo(carafeDiameter / 2 - 0.2, %)
|
||||
|> angledLineToX({
|
||||
angle = 30,
|
||||
to = carafeDiameter / 2 - 0.07
|
||||
}, %, $seg1)
|
||||
|> angledLine({ angle = -60, length = 0.050 }, %)
|
||||
|> angledLine({ angle = 30, length = -segLen(seg1) }, %)
|
||||
|> xLineTo(0.15, %)
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
|> revolve({ axis = 'y' }, %)
|
||||
|
||||
// Plunger and stem
|
||||
sketch006 = startSketchOn('XZ')
|
||||
|> startProfileAt([0.1, 1], %)
|
||||
|> line(end = [0.1, 0])
|
||||
|> angledLineToX({ angle = 10, to = 0.05 }, %)
|
||||
|> yLine(10, %)
|
||||
|> line(end = [0.6, 0])
|
||||
|> yLine(-.05, %)
|
||||
|> tangentialArc({ radius = 0.6, offset = -90 }, %)
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
|> revolve({ axis = 'y' }, %)
|
||||
|
||||
// Spiral plate
|
||||
sketch007 = startSketchOn(offsetPlane('XY', offset = 1.12))
|
||||
|> circle(
|
||||
center = [0, 0],
|
||||
radius = carafeDiameter / 2 - 0.24
|
||||
)
|
||||
|> hole(circle(center = [0, 0], radius = .15), %)
|
||||
|
||||
extrude003 = extrude(sketch007, length = 0.050)
|
||||
|
||||
// Pattern holes in the spiral plate
|
||||
sketch008 = startSketchOn(extrude003, 'END')
|
||||
|> circle(center = [1.4, 0], radius = .3)
|
||||
|> patternCircular2d(
|
||||
center = [0, 0],
|
||||
instances = 8,
|
||||
arcDegrees = 360,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
|
||||
extrude004 = extrude(sketch008, length = -0.050)
|
||||
|
||||
// Pattern holes in the spiral plate
|
||||
sketch009 = startSketchOn(extrude003, 'END')
|
||||
|> circle(center = [0.6, 0], radius = .2)
|
||||
|> patternCircular2d(
|
||||
center = [0, 0],
|
||||
instances = 4,
|
||||
arcDegrees = 360,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
|
||||
extrude005 = extrude(sketch009, length = -0.050)
|
||||
|
||||
// Extrude a glass carafe body
|
||||
sketch010 = startSketchOn("XY")
|
||||
|> circle(
|
||||
center = [0, 0],
|
||||
radius = carafeDiameter / 2
|
||||
)
|
||||
|
||||
// Perform a shell operation to hollow the carafe body with the top face removed
|
||||
extrude006 = extrude(sketch010, length = carafeHeight)
|
||||
|> shell(faces = ["end"], thickness = .07)
|
||||
|
||||
// Draw and revolve the lid
|
||||
sketch011 = startSketchOn('XZ')
|
||||
|> startProfileAt([0.2, carafeHeight - 0.7], %)
|
||||
|> xLine(carafeDiameter / 2 - 0.3, %)
|
||||
|> yLine(0.7, %)
|
||||
|> xLine(0.3, %)
|
||||
|> yLine(0.4, %)
|
||||
|> line(end = [-0.02, 0.02])
|
||||
|> bezierCurve({
|
||||
to = [-carafeDiameter / 2 - 0.1, 1],
|
||||
control1 = [-0.3, 0],
|
||||
control2 = [carafeDiameter / 10, 1]
|
||||
}, %)
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
|> revolve({ axis = 'y' }, %)
|
||||
|
||||
// Draw and extrude handle
|
||||
sketch012 = startSketchOn(offsetPlane('XZ', offset = handleThickness / 2))
|
||||
|> startProfileAt([2.3, 6.4], %)
|
||||
|> line(end = [0.56, 0])
|
||||
|> tangentialArcTo([4.1, 5.26], %)
|
||||
|> tangentialArcTo([4.17, 1.6], %)
|
||||
|> tangentialArcTo([3.13, 0.61], %)
|
||||
|> line(end = [-1.09, 0])
|
||||
|> line(end = [0, 0.43])
|
||||
|> line(end = [0.99, -0.02])
|
||||
|> tangentialArcTo([3.63, 1.6], %)
|
||||
|> tangentialArcTo([3.56, 5.15], %)
|
||||
|> tangentialArcTo([2.72, 5.88], %)
|
||||
|> line(end = [-0.4, 0])
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
extrude007 = extrude(sketch012, length = -handleThickness)
|
63
public/kcl-samples/gear-rack/main.kcl
Normal file
63
public/kcl-samples/gear-rack/main.kcl
Normal file
@ -0,0 +1,63 @@
|
||||
// 100mm Gear Rack
|
||||
// A flat bar or rail that is engraved with teeth along its length. These teeth are designed to mesh with the teeth of a gear, known as a pinion. When the pinion, a small cylindrical gear, rotates, its teeth engage with the teeth on the rack, causing the rack to move linearly. Conversely, linear motion applied to the rack will cause the pinion to rotate.
|
||||
|
||||
// Set Units
|
||||
@settings(defaultLengthUnit = mm)
|
||||
|
||||
// Define constants
|
||||
length = 100
|
||||
pitchHeight = 11.5
|
||||
width = 5
|
||||
height = 12
|
||||
minHeight = 10.875
|
||||
|
||||
// Create the body of the rack
|
||||
rackBody = startSketchOn('XY')
|
||||
|> startProfileAt([-length / 2, 0], %)
|
||||
|> line(end = [length, 0])
|
||||
|> line(end = [0, minHeight])
|
||||
|> line(end = [-length, 0])
|
||||
|> close()
|
||||
|> extrude(length = width)
|
||||
|
||||
// Create a function for sketch of a single tooth
|
||||
fn tooth() {
|
||||
toothSketch = startSketchOn('XY')
|
||||
|> startProfileAt([-length / 2 + 0.567672, minHeight], %)
|
||||
|> tangentialArcToRelative([0.157636, 0.110378], %)
|
||||
|> line(end = [0.329118, 0.904244])
|
||||
|> tangentialArcToRelative([0.157636, 0.110378], %)
|
||||
|> line(end = [0.186505, 0])
|
||||
|> tangentialArcToRelative([0.157636, -0.110378], %)
|
||||
|> line(end = [0.329118, -0.904244])
|
||||
|> tangentialArcToRelative([0.157636, -0.110378], %)
|
||||
|> close()
|
||||
|> extrude(length = width)
|
||||
return toothSketch
|
||||
}
|
||||
|
||||
// Pattern the single tooth over the length of the rack body
|
||||
teeth = tooth()
|
||||
|> patternLinear3d(
|
||||
axis = [10, 0, 0],
|
||||
distance = 1.570796,
|
||||
instances = 63
|
||||
)
|
||||
|
||||
// Sketch and extrude the first end cap. This is a partial tooth
|
||||
endCapTooth = startSketchOn('XY')
|
||||
|> startProfileAt([-length / 2, 11.849525], %)
|
||||
|> line(end = [0.314524, -0.864147])
|
||||
|> tangentialArcToRelative([0.157636, -0.110378], %)
|
||||
|> line(endAbsolute = [-length / 2, minHeight])
|
||||
|> close()
|
||||
|> extrude(length = width)
|
||||
|
||||
// Sketch and extrude the second end cap. This is a partial tooth
|
||||
endCapTooth2 = startSketchOn('XY')
|
||||
|> startProfileAt([length / 2, 11.849525], %)
|
||||
|> line(end = [-0.314524, -0.864147])
|
||||
|> tangentialArcToRelative([-0.157636, -0.110378], %)
|
||||
|> line(endAbsolute = [length / 2, minHeight])
|
||||
|> close()
|
||||
|> extrude(length = width)
|
112
public/kcl-samples/gear/main.kcl
Normal file
112
public/kcl-samples/gear/main.kcl
Normal file
@ -0,0 +1,112 @@
|
||||
// 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)
|
||||
|
||||
// Define constants
|
||||
nTeeth = 21
|
||||
module = 0.5
|
||||
pitchDiameter = module * nTeeth
|
||||
pressureAngle = 20
|
||||
addendum = module
|
||||
deddendum = 1.25 * module
|
||||
baseDiameter = pitchDiameter * cos(toRadians(pressureAngle))
|
||||
tipDiameter = pitchDiameter + 2 * module
|
||||
gearHeight = 3
|
||||
|
||||
// Interpolate points along the involute curve
|
||||
cmo = 101
|
||||
rs = map([0..cmo], fn (i) {
|
||||
return baseDiameter / 2 + i / cmo * (tipDiameter - baseDiameter) / 2
|
||||
})
|
||||
|
||||
// Calculate operating pressure angle
|
||||
angles = map(rs, fn (r) {
|
||||
return toDegrees( acos(baseDiameter / 2 / r))
|
||||
})
|
||||
|
||||
// Calculate the involute function
|
||||
invas = map(angles, fn (a) {
|
||||
return tan(toRadians(a)) - toRadians(a)
|
||||
})
|
||||
|
||||
// Map the involute curve
|
||||
xs = map([0..cmo], fn (i) {
|
||||
return rs[i] * cos(invas[i])
|
||||
})
|
||||
|
||||
ys = map([0..cmo], fn (i) {
|
||||
return rs[i] * sin(invas[i])
|
||||
})
|
||||
|
||||
// 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, sg) {
|
||||
j = 100 - i // iterate backwards
|
||||
return line(sg, endAbsolute = [xs[j], ys[j]])
|
||||
}
|
||||
|
||||
fn rightInvolute(i, sg) {
|
||||
x = rs[i] * cos(toRadians(-toothAngle + toDegrees(atan(ys[i] / xs[i]))))
|
||||
y = -rs[i] * sin(toRadians(-toothAngle + toDegrees(atan(ys[i] / xs[i]))))
|
||||
return line(sg, endAbsolute = [x, y])
|
||||
}
|
||||
|
||||
// Draw gear teeth
|
||||
start = startSketchOn('XY')
|
||||
|> startProfileAt([xs[101], ys[101]], %)
|
||||
teeth = reduce([0..100], start, leftInvolute)
|
||||
|> arc({
|
||||
angleStart = 0,
|
||||
angleEnd = toothAngle,
|
||||
radius = baseDiameter / 2
|
||||
}, %)
|
||||
|> reduce([1..101], %, 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, 'END')
|
||||
|> startProfileAt([
|
||||
holeRadius * cos(startAngle),
|
||||
holeRadius * sin(startAngle)
|
||||
], %)
|
||||
|> xLine(keywayDepth, %)
|
||||
|> yLine(-keywayWidth, %)
|
||||
|> xLine(-keywayDepth, %)
|
||||
|> arc({
|
||||
angleEnd = 180,
|
||||
angleStart = -1 * 180 / PI * startAngle + 360,
|
||||
radius = holeRadius
|
||||
}, %)
|
||||
|> arc({
|
||||
angleEnd = 180 / PI * startAngle,
|
||||
angleStart = 180,
|
||||
radius = holeRadius
|
||||
}, %)
|
||||
|> close()
|
||||
|> extrude(length = -gearHeight)
|
66
public/kcl-samples/generate-manifest.js
Normal file
66
public/kcl-samples/generate-manifest.js
Normal file
@ -0,0 +1,66 @@
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
const FILE_EXTENSION = ".kcl";
|
||||
const MANIFEST_FILE = "manifest.json";
|
||||
const COMMENT_PREFIX = "//";
|
||||
|
||||
// Function to read and parse .kcl files
|
||||
const getKclMetadata = (projectPath, files) => {
|
||||
const primaryKclFile = files.find((file) => file.includes("main.kcl")) ?? files.sort()[0];
|
||||
const fullPathToPrimaryKcl = path.join(projectPath, primaryKclFile);
|
||||
|
||||
const content = fs.readFileSync(fullPathToPrimaryKcl, "utf-8");
|
||||
const lines = content.split("\n");
|
||||
|
||||
if (lines.length < 2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const title = lines[0].replace(COMMENT_PREFIX, "").trim();
|
||||
const description = lines[1].replace(COMMENT_PREFIX, "").trim();
|
||||
|
||||
return {
|
||||
file: primaryKclFile,
|
||||
// Assumed to ALWAYS be 1 level deep. That's the current practice.
|
||||
pathFromProjectDirectoryToFirstFile: fullPathToPrimaryKcl.split('/').splice(-2).join('/'),
|
||||
// This was added so that multiple file project samples do not load in
|
||||
// the web app through the manifest.
|
||||
multipleFiles: files.length > 1,
|
||||
title,
|
||||
description,
|
||||
};
|
||||
};
|
||||
|
||||
// Function to scan the directory and generate the manifest.json
|
||||
const generateManifest = (dir) => {
|
||||
const projectDirectories = fs.readdirSync(dir);
|
||||
const manifest = [];
|
||||
|
||||
projectDirectories.forEach((file) => {
|
||||
const projectPath = path.join(dir, file);
|
||||
const stattedDir = fs.statSync(projectPath);
|
||||
if (stattedDir.isDirectory()) {
|
||||
const files = fs
|
||||
.readdirSync(projectPath)
|
||||
.filter((f) => f.endsWith(FILE_EXTENSION));
|
||||
if (files.length === 0) {
|
||||
return;
|
||||
}
|
||||
const metadata = getKclMetadata(projectPath, files);
|
||||
if (metadata) {
|
||||
manifest.push(metadata);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Write the manifest.json
|
||||
const outputPath = path.join(dir, MANIFEST_FILE);
|
||||
fs.writeFileSync(outputPath, JSON.stringify(manifest, null, 2));
|
||||
console.log(`Manifest of ${manifest.length} items written to ${outputPath}`);
|
||||
};
|
||||
|
||||
// Run the script
|
||||
console.log(`Generating ${MANIFEST_FILE}...`);
|
||||
const projectDir = path.resolve(__dirname); // Set project root directory
|
||||
generateManifest(projectDir);
|
225
public/kcl-samples/gridfinity-baseplate-magnets/main.kcl
Normal file
225
public/kcl-samples/gridfinity-baseplate-magnets/main.kcl
Normal file
@ -0,0 +1,225 @@
|
||||
// Gridfinity Baseplate With Magnets
|
||||
// Gridfinity is a system to help you work more efficiently. This is a system invented by Zack Freedman. There are two main components the baseplate and the bins. The components are comprised of a matrix of squares. Allowing easy stacking and expansion. This baseplate version includes holes for magnet placement
|
||||
|
||||
// Set units in millimeters (mm)
|
||||
@settings(defaultLengthUnit = mm)
|
||||
|
||||
// Define constants
|
||||
binLength = 42.0
|
||||
cornerRadius = 4.0
|
||||
firstStep = 0.7
|
||||
secondStep = 1.8
|
||||
thirdStep = 2.15
|
||||
magOuterDiam = 6.5
|
||||
magOffset = 4.8
|
||||
magDepth = 2.4
|
||||
|
||||
// Number of bins in each direction
|
||||
countBinWidth = 2
|
||||
countBinLength = 3
|
||||
|
||||
// The total height of the baseplate is a summation of the vertical heights of the baseplate steps
|
||||
height = firstStep + secondStep + thirdStep
|
||||
|
||||
// define a function which builds the profile of the baseplate bin
|
||||
fn face(plane) {
|
||||
faceSketch = startSketchOn(plane)
|
||||
|> startProfileAt([0, 0], %)
|
||||
|> yLine(height, %)
|
||||
|> angledLineOfYLength({ angle = -45, length = thirdStep }, %)
|
||||
|> yLine(-secondStep, %)
|
||||
|> angledLineOfYLength({ angle = -45, length = firstStep }, %)
|
||||
|> close()
|
||||
return faceSketch
|
||||
}
|
||||
|
||||
// extrude a single side of the bin
|
||||
singleSide = extrude(face(offsetPlane("YZ", offset = cornerRadius)), length = binLength - (cornerRadius * 2), )
|
||||
|
||||
// create the other sides of the bin by using a circular pattern
|
||||
sides = patternCircular3d(
|
||||
singleSide,
|
||||
arcDegrees = 360,
|
||||
axis = [0, 0, 1],
|
||||
center = [binLength / 2, binLength / 2, 0],
|
||||
instances = 4,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
|
||||
// define an axis axis000
|
||||
axis000 = {
|
||||
custom = {
|
||||
axis = [0.0, 1.0],
|
||||
origin = [cornerRadius, cornerRadius]
|
||||
}
|
||||
}
|
||||
|
||||
// create a single corner of the bin
|
||||
singleCorner = revolve({ angle = -90, axis = axis000 }, face(offsetPlane("YZ", offset = cornerRadius)))
|
||||
|
||||
// create the corners of the bin
|
||||
corners = patternCircular3d(
|
||||
singleCorner,
|
||||
arcDegrees = 360,
|
||||
axis = [0, 0, 1],
|
||||
center = [binLength / 2, binLength / 2, 0],
|
||||
instances = 4,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
|
||||
// create the baseplate by patterning sides
|
||||
basePlateSides = patternLinear3d(
|
||||
sides,
|
||||
axis = [1.0, 0.0, 0.0],
|
||||
instances = countBinWidth,
|
||||
distance = binLength
|
||||
)
|
||||
|> patternLinear3d(
|
||||
axis = [0.0, 1.0, 0.0],
|
||||
instances = countBinLength,
|
||||
distance = binLength
|
||||
)
|
||||
|
||||
// create the corners of the baseplate by patterning the corners
|
||||
basePlateCorners = patternLinear3d(
|
||||
corners,
|
||||
axis = [1.0, 0.0, 0.0],
|
||||
instances = countBinWidth,
|
||||
distance = binLength
|
||||
)
|
||||
|> patternLinear3d(
|
||||
axis = [0.0, 1.0, 0.0],
|
||||
instances = countBinLength,
|
||||
distance = binLength
|
||||
)
|
||||
|
||||
// create the center cutout for the magnet profile
|
||||
fn magnetCenterCutout(plane) {
|
||||
magnetSketch = startSketchOn(plane)
|
||||
|> startProfileAt([
|
||||
firstStep + thirdStep,
|
||||
2 * magOuterDiam
|
||||
], %)
|
||||
|> xLine(2 * magOuterDiam - (firstStep + thirdStep) - (magOuterDiam / 2), %)
|
||||
|> arc({
|
||||
angleStart = 90.0,
|
||||
angleEnd = 0.0,
|
||||
radius = magOuterDiam / 2
|
||||
}, %)
|
||||
|> yLine(-(2 * magOuterDiam - (firstStep + thirdStep) - (magOuterDiam / 2)), %)
|
||||
|> xLine(binLength - (4 * magOuterDiam), %)
|
||||
|> yLine(2 * magOuterDiam - (firstStep + thirdStep) - (magOuterDiam / 2), %)
|
||||
|> arc({
|
||||
angleStart = 180.0,
|
||||
angleEnd = 90.0,
|
||||
radius = magOuterDiam / 2
|
||||
}, %)
|
||||
|> xLine(2 * magOuterDiam - (firstStep + thirdStep) - (magOuterDiam / 2), %)
|
||||
|> yLine(binLength - (4 * magOuterDiam), %)
|
||||
|> xLine(-(2 * magOuterDiam - (firstStep + thirdStep) - (magOuterDiam / 2)), %)
|
||||
|> arc({
|
||||
angleStart = 270.0,
|
||||
angleEnd = 180.0,
|
||||
radius = magOuterDiam / 2
|
||||
}, %)
|
||||
|> yLine(2 * magOuterDiam - (firstStep + thirdStep) - (magOuterDiam / 2), %)
|
||||
|> xLine(-(binLength - (4 * magOuterDiam)), %, $line012)
|
||||
|> yLine(-(2 * magOuterDiam - (firstStep + thirdStep) - (magOuterDiam / 2)), %)
|
||||
|> arc({
|
||||
angleStart = 360.0,
|
||||
angleEnd = 270.0,
|
||||
radius = magOuterDiam / 2
|
||||
}, %)
|
||||
|> xLine(-(2 * magOuterDiam - (firstStep + thirdStep) - (magOuterDiam / 2)), %)
|
||||
|> yLine(-(binLength - (4 * magOuterDiam)), %)
|
||||
|> close()
|
||||
return magnetSketch
|
||||
}
|
||||
|
||||
// create the outside profile of the magnets
|
||||
fn magnetBase(plane) {
|
||||
magnetBaseSketch = startSketchOn(plane)
|
||||
|> startProfileAt([0, 0], %)
|
||||
|> xLine(binLength, %, $line001)
|
||||
|> yLine(binLength, %, $line002)
|
||||
|> xLineTo(profileStartX(%), %, $line003)
|
||||
|> close(tag = $line004)
|
||||
|> hole(magnetCenterCutout(plane), %)
|
||||
return magnetBaseSketch
|
||||
}
|
||||
|
||||
// create sketch profile sketch000Profile002
|
||||
magnetsSketch = startSketchOn('XY')
|
||||
|> circle(
|
||||
center = [cornerRadius * 2, cornerRadius * 2],
|
||||
radius = magOuterDiam / 2
|
||||
)
|
||||
|> patternCircular2d(
|
||||
center = [binLength / 2, binLength / 2],
|
||||
instances = 4,
|
||||
arcDegrees = 360,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
|
||||
// create a profile with holes for the magnets
|
||||
magnetProfile = magnetBase("XY")
|
||||
|> hole(magnetsSketch, %)
|
||||
|
||||
// create an extrusion of the magnet cutout with holes
|
||||
magnetHolesExtrude = extrude(magnetProfile, length = -magDepth)
|
||||
|
||||
// add a fillet to the extrusion
|
||||
magnetHolesExtrudeFillets = fillet(
|
||||
magnetHolesExtrude,
|
||||
radius = cornerRadius,
|
||||
tags = [
|
||||
getNextAdjacentEdge(magnetHolesExtrude.sketch.tags.line001),
|
||||
getPreviousAdjacentEdge(magnetHolesExtrude.sketch.tags.line001),
|
||||
getNextAdjacentEdge(magnetHolesExtrude.sketch.tags.line003),
|
||||
getPreviousAdjacentEdge(magnetHolesExtrude.sketch.tags.line003)
|
||||
]
|
||||
)
|
||||
|
||||
// create a profile without the holes for the magnets
|
||||
magnetProfileNoMagnets = magnetBase(offsetPlane("XY", offset = -magDepth))
|
||||
|
||||
// create an extrusion of the magnet cutout without holes
|
||||
magnetCutoutExtrude = extrude(magnetProfileNoMagnets, length = -magDepth)
|
||||
|
||||
// add a fillet to the extrusion
|
||||
magnetCutoutExtrudeFillets = fillet(
|
||||
magnetCutoutExtrude,
|
||||
radius = cornerRadius,
|
||||
tags = [
|
||||
getNextAdjacentEdge(magnetCutoutExtrude.sketch.tags.line001),
|
||||
getPreviousAdjacentEdge(magnetCutoutExtrude.sketch.tags.line001),
|
||||
getNextAdjacentEdge(magnetCutoutExtrude.sketch.tags.line003),
|
||||
getPreviousAdjacentEdge(magnetCutoutExtrude.sketch.tags.line003)
|
||||
]
|
||||
)
|
||||
|
||||
// pattern the magnet cutouts with holes
|
||||
patternLinear3d(
|
||||
magnetHolesExtrudeFillets,
|
||||
axis = [1.0, 0.0, 0.0],
|
||||
instances = countBinWidth,
|
||||
distance = binLength
|
||||
)
|
||||
|> patternLinear3d(
|
||||
axis = [0.0, 1.0, 0.0],
|
||||
instances = countBinLength,
|
||||
distance = binLength
|
||||
)
|
||||
|
||||
// pattern the magnet cutouts without holes
|
||||
patternLinear3d(
|
||||
magnetCutoutExtrudeFillets,
|
||||
axis = [1.0, 0.0, 0.0],
|
||||
instances = countBinWidth,
|
||||
distance = binLength
|
||||
)
|
||||
|> patternLinear3d(
|
||||
axis = [0.0, 1.0, 0.0],
|
||||
instances = countBinLength,
|
||||
distance = binLength
|
||||
)
|
91
public/kcl-samples/gridfinity-baseplate/main.kcl
Normal file
91
public/kcl-samples/gridfinity-baseplate/main.kcl
Normal file
@ -0,0 +1,91 @@
|
||||
// Gridfinity Baseplate
|
||||
// Gridfinity is a system to help you work more efficiently. This is a system invented by Zack Freedman. There are two main components the baseplate and the bins. The components are comprised of a matrix of squares. Allowing easy stacking and expansion
|
||||
|
||||
// Set units in millimeters (mm)
|
||||
@settings(defaultLengthUnit = mm)
|
||||
|
||||
// Define constants
|
||||
binLength = 42.0
|
||||
cornerRadius = 4.0
|
||||
firstStep = 0.7
|
||||
secondStep = 1.8
|
||||
thirdStep = 2.15
|
||||
|
||||
// Number of bins in each direction
|
||||
countBinWidth = 2
|
||||
countBinLength = 3
|
||||
|
||||
// The total height of the baseplate is a summation of the vertical heights of the baseplate steps
|
||||
height = firstStep + secondStep + thirdStep
|
||||
|
||||
// define a function which builds the profile of the baseplate bin
|
||||
fn face(plane) {
|
||||
faceSketch = startSketchOn(plane)
|
||||
|> startProfileAt([0, 0], %)
|
||||
|> yLine(height, %)
|
||||
|> angledLineOfYLength({ angle = -45, length = thirdStep }, %)
|
||||
|> yLine(-secondStep, %)
|
||||
|> angledLineOfYLength({ angle = -45, length = firstStep }, %)
|
||||
|> close()
|
||||
return faceSketch
|
||||
}
|
||||
|
||||
// extrude a single side of the bin
|
||||
singleSide = extrude(face(offsetPlane("YZ", offset = cornerRadius)), length = binLength - (cornerRadius * 2))
|
||||
|
||||
// create the other sides of the bin by using a circular pattern
|
||||
sides = patternCircular3d(
|
||||
singleSide,
|
||||
arcDegrees = 360,
|
||||
axis = [0, 0, 1],
|
||||
center = [binLength / 2, binLength / 2, 0],
|
||||
instances = 4,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
|
||||
// define an axis axis000
|
||||
axis000 = {
|
||||
custom = {
|
||||
axis = [0.0, 1.0],
|
||||
origin = [cornerRadius, cornerRadius]
|
||||
}
|
||||
}
|
||||
|
||||
// create a single corner of the bin
|
||||
singleCorner = revolve({ angle = -90, axis = axis000 }, face(offsetPlane("YZ", offset = cornerRadius)))
|
||||
|
||||
// create the corners of the bin
|
||||
corners = patternCircular3d(
|
||||
singleCorner,
|
||||
arcDegrees = 360,
|
||||
axis = [0, 0, 1],
|
||||
center = [binLength / 2, binLength / 2, 0],
|
||||
instances = 4,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
|
||||
// create the baseplate by patterning sides
|
||||
basePlateSides = patternLinear3d(
|
||||
sides,
|
||||
axis = [1.0, 0.0, 0.0],
|
||||
instances = countBinWidth,
|
||||
distance = binLength
|
||||
)
|
||||
|> patternLinear3d(
|
||||
axis = [0.0, 1.0, 0.0],
|
||||
instances = countBinLength,
|
||||
distance = binLength
|
||||
)
|
||||
|
||||
// create the corners of the baseplate by patterning the corners
|
||||
basePlateCorners = patternLinear3d(
|
||||
corners,
|
||||
axis = [1.0, 0.0, 0.0],
|
||||
instances = countBinWidth,
|
||||
distance = binLength
|
||||
)
|
||||
|> patternLinear3d(
|
||||
axis = [0.0, 1.0, 0.0],
|
||||
instances = countBinLength,
|
||||
distance = binLength
|
||||
)
|
325
public/kcl-samples/gridfinity-bins-stacking-lip/main.kcl
Normal file
325
public/kcl-samples/gridfinity-bins-stacking-lip/main.kcl
Normal file
@ -0,0 +1,325 @@
|
||||
// Gridfinity Bins With A Stacking Lip
|
||||
// Gridfinity is a system to help you work more efficiently. This is a system invented by Zack Freedman. There are two main components the baseplate and the bins. The components are comprised of a matrix of squares. Allowing easy stacking and expansion. This Gridfinity bins version includes a lip to allowable stacking Gridfinity bins
|
||||
|
||||
// Set units in millimeters (mm)
|
||||
@settings(defaultLengthUnit = mm)
|
||||
|
||||
// Define constants
|
||||
binLength = 41.5
|
||||
binHeight = 7.0
|
||||
binBaseLength = 2.95
|
||||
binTol = 0.25
|
||||
binThk = 1.2
|
||||
cornerRadius = 3.75
|
||||
firstStep = 0.8
|
||||
secondStep = 1.8
|
||||
thirdStep = 2.15
|
||||
magOuterDiam = 6.5
|
||||
magOffset = 4.8
|
||||
magDepth = 2.4
|
||||
lipRadius = 0.5
|
||||
lipStep1 = 1.4
|
||||
lipStep2 = 1.2
|
||||
lipStep3 = 0.7
|
||||
lipStep4 = 1.8
|
||||
lipStep5 = 1.9
|
||||
|
||||
// Number of bins in each direction
|
||||
countBinWidth = 2
|
||||
countBinLength = 3
|
||||
countBinHeight = 1
|
||||
|
||||
// The total height of the baseplate is a summation of the vertical heights of the baseplate steps
|
||||
height = firstStep + secondStep + thirdStep
|
||||
lipHeight = lipStep1 + lipStep2 + lipStep3 + lipStep4 + lipStep5
|
||||
|
||||
// define a function which builds the profile of the baseplate bin
|
||||
fn face(plane) {
|
||||
faceSketch = startSketchOn(plane)
|
||||
|> startProfileAt([binBaseLength + binTol, 0], %)
|
||||
|> yLine(height, %)
|
||||
|> xLine(-binBaseLength, %)
|
||||
|> angledLineOfYLength({ angle = -45, length = thirdStep }, %)
|
||||
|> yLine(-secondStep, %)
|
||||
|> angledLineOfYLength({ angle = -45, length = firstStep }, %)
|
||||
|> close()
|
||||
return faceSketch
|
||||
}
|
||||
|
||||
// extrude a single side of the bin
|
||||
singleSide = extrude(face(offsetPlane("YZ", offset = cornerRadius + binTol)), length = binLength - (cornerRadius * 2))
|
||||
|
||||
// create the other sides of the bin by using a circular pattern
|
||||
sides = patternCircular3d(
|
||||
singleSide,
|
||||
arcDegrees = 360,
|
||||
axis = [0, 0, 1],
|
||||
center = [
|
||||
(binLength + 2 * binTol) / 2,
|
||||
(binLength + 2 * binTol) / 2,
|
||||
0
|
||||
],
|
||||
instances = 4,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
|
||||
// define an axis axis000
|
||||
axis000 = {
|
||||
custom = {
|
||||
axis = [0.0, 1.0],
|
||||
origin = [
|
||||
cornerRadius + binTol,
|
||||
cornerRadius + binTol
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
// create a single corner of the bin
|
||||
singleCorner = revolve({ angle = -90, axis = axis000 }, face(offsetPlane("YZ", offset = cornerRadius + binTol)))
|
||||
|
||||
// create the corners of the bin
|
||||
corners = patternCircular3d(
|
||||
singleCorner,
|
||||
arcDegrees = 360,
|
||||
axis = [0, 0, 1],
|
||||
center = [
|
||||
(binLength + 2 * binTol) / 2,
|
||||
(binLength + 2 * binTol) / 2,
|
||||
0
|
||||
],
|
||||
instances = 4,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
|
||||
singleBinFill = startSketchOn("XY")
|
||||
|> startProfileAt([
|
||||
binBaseLength + binTol,
|
||||
binBaseLength + binTol
|
||||
], %)
|
||||
|> line(end = [binLength - (binBaseLength * 2), 0], tag = $line000)
|
||||
|> line(end = [0, binLength - (binBaseLength * 2)], tag = $line001)
|
||||
|> xLineTo(profileStartX(%), %, $line002)
|
||||
|> close(tag = $line003)
|
||||
|> extrude(length = height)
|
||||
|> fillet(
|
||||
radius = firstStep,
|
||||
tags = [
|
||||
getNextAdjacentEdge(line000),
|
||||
getPreviousAdjacentEdge(line000),
|
||||
getNextAdjacentEdge(line002),
|
||||
getPreviousAdjacentEdge(line002)
|
||||
]
|
||||
)
|
||||
|
||||
magCutout000 = startSketchOn(singleBinFill, "start")
|
||||
|> circle(
|
||||
center = [
|
||||
-magOffset - binBaseLength - binTol,
|
||||
magOffset + binBaseLength + binTol
|
||||
],
|
||||
radius = magOuterDiam / 2
|
||||
)
|
||||
|> patternCircular2d(
|
||||
arcDegrees = 360,
|
||||
center = [
|
||||
(-binLength + 2 * binTol) / 2,
|
||||
(binLength + 2 * binTol) / 2
|
||||
],
|
||||
instances = 4,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
|> extrude(length = -magDepth)
|
||||
|
||||
// create the baseplate by patterning sides
|
||||
binSides = patternLinear3d(
|
||||
sides,
|
||||
axis = [1.0, 0.0, 0.0],
|
||||
instances = countBinWidth,
|
||||
distance = binLength + binTol * 2
|
||||
)
|
||||
|> patternLinear3d(
|
||||
axis = [0.0, 1.0, 0.0],
|
||||
instances = countBinLength,
|
||||
distance = binLength + binTol * 2
|
||||
)
|
||||
|
||||
// create the corners of the baseplate by patterning the corners
|
||||
binCorners = patternLinear3d(
|
||||
corners,
|
||||
axis = [1.0, 0.0, 0.0],
|
||||
instances = countBinWidth,
|
||||
distance = binLength + binTol * 2
|
||||
)
|
||||
|> patternLinear3d(
|
||||
axis = [0.0, 1.0, 0.0],
|
||||
instances = countBinLength,
|
||||
distance = binLength + binTol * 2
|
||||
)
|
||||
|
||||
// create the fill of the bin by patterning the corners
|
||||
binFill = patternLinear3d(
|
||||
singleBinFill,
|
||||
axis = [1.0, 0.0, 0.0],
|
||||
instances = countBinWidth,
|
||||
distance = binLength + binTol * 2
|
||||
)
|
||||
|> patternLinear3d(
|
||||
axis = [0.0, 1.0, 0.0],
|
||||
instances = countBinLength,
|
||||
distance = binLength + binTol * 2
|
||||
)
|
||||
|
||||
//
|
||||
binTop = startSketchOn(offsetPlane("XY", offset = height))
|
||||
|> startProfileAt([0, 0], %)
|
||||
|> xLine((binLength + 2 * binTol) * countBinWidth, %, $line010)
|
||||
|> yLine((binLength + 2 * binTol) * countBinLength, %, $line011)
|
||||
|> xLineTo(profileStartX(%), %, $line012)
|
||||
|> close(tag = $line013)
|
||||
|> extrude(length = binHeight * countBinHeight)
|
||||
|> fillet(
|
||||
radius = cornerRadius,
|
||||
tags = [
|
||||
getNextAdjacentEdge(line010),
|
||||
getPreviousAdjacentEdge(line010),
|
||||
getNextAdjacentEdge(line012),
|
||||
getPreviousAdjacentEdge(line012)
|
||||
]
|
||||
)
|
||||
|> shell(faces = ["end"], thickness = binThk)
|
||||
|
||||
// define a function which builds the profile of the baseplate bin
|
||||
fn lipFace(plane) {
|
||||
faceSketch = startSketchOn(plane)
|
||||
|> startProfileAt([0, 0], %)
|
||||
// |> yLine(lipHeight, %, $line100)
|
||||
|> line(end = [0.0, 5.792893], tag = $line000)
|
||||
|> arc({
|
||||
angleStart = 180.0,
|
||||
angleEnd = 45.0,
|
||||
radius = 0.500000
|
||||
}, %, $arc000)
|
||||
// |> angledLineOfYLength({ angle: -45, length: lipStep5 }, %)
|
||||
|> line(end = [1.046447, -1.046447], tag = $line001)
|
||||
|> yLine(-lipStep4, %)
|
||||
|> angledLineOfYLength({ angle = -45, length = lipStep3 }, %)
|
||||
|> yLine(-lipStep2, %)
|
||||
|> angledLineOfYLength({ angle = -135, length = lipStep1 }, %)
|
||||
|> close()
|
||||
return faceSketch
|
||||
}
|
||||
|
||||
plane000 = {
|
||||
plane = {
|
||||
origin = [
|
||||
cornerRadius,
|
||||
0.0,
|
||||
height + binHeight * countBinHeight
|
||||
],
|
||||
xAxis = [0.0, 1.0, 0.0],
|
||||
yAxis = [0.0, 0.0, 1.0],
|
||||
zAxis = [1.0, 0.0, 0.0]
|
||||
}
|
||||
}
|
||||
|
||||
plane001 = {
|
||||
plane = {
|
||||
origin = [
|
||||
0.0,
|
||||
cornerRadius,
|
||||
height + binHeight * countBinHeight
|
||||
],
|
||||
xAxis = [1.0, 0.0, 0.0],
|
||||
yAxis = [0.0, 0.0, 1.0],
|
||||
zAxis = [0.0, 1.0, 0.0]
|
||||
}
|
||||
}
|
||||
|
||||
plane002 = {
|
||||
plane = {
|
||||
origin = [
|
||||
countBinWidth * (binLength + 2 * binTol) - cornerRadius,
|
||||
0.0,
|
||||
height + binHeight * countBinHeight
|
||||
],
|
||||
xAxis = [0.0, 1.0, 0.0],
|
||||
yAxis = [0.0, 0.0, 1.0],
|
||||
zAxis = [1.0, 0.0, 0.0]
|
||||
}
|
||||
}
|
||||
|
||||
// extrude a single side of the lip of the bin
|
||||
lipSingleLength = extrude(lipFace(plane000), length = binLength * countBinWidth - (2 * cornerRadius) + 2 * binTol * countBinWidth)
|
||||
|
||||
// extrude a single side of the lip of the bin
|
||||
lipSingleWidth = extrude(lipFace(plane001), length = binLength * countBinLength - (2 * cornerRadius) + 2 * binTol * countBinLength)
|
||||
|
||||
// create the other sides of the lips by using a circular pattern
|
||||
lipLengths = patternCircular3d(
|
||||
lipSingleLength,
|
||||
arcDegrees = 360,
|
||||
axis = [0, 0, 1],
|
||||
center = [
|
||||
(binLength + 2 * binTol) / 2 * countBinWidth,
|
||||
(binLength + 2 * binTol) / 2 * countBinLength,
|
||||
0
|
||||
],
|
||||
instances = 2,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
|
||||
// create the other sides of the lips by using a circular pattern
|
||||
lipWidths = patternCircular3d(
|
||||
lipSingleWidth,
|
||||
arcDegrees = 360,
|
||||
axis = [0, 0, 1],
|
||||
center = [
|
||||
(binLength + 2 * binTol) / 2 * countBinWidth,
|
||||
(binLength + 2 * binTol) / 2 * countBinLength,
|
||||
0
|
||||
],
|
||||
instances = 2,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
|
||||
// define an axis axis000
|
||||
axis001 = {
|
||||
custom = {
|
||||
axis = [0.0, 1.0],
|
||||
origin = [cornerRadius, cornerRadius]
|
||||
}
|
||||
}
|
||||
|
||||
// create a single corner of the bin
|
||||
lipSingleLengthCorner = revolve({ angle = -90, axis = axis001 }, lipFace(plane000))
|
||||
|
||||
// create a single corner of the bin
|
||||
lipSingleWidthCorner = revolve({ angle = 90, axis = axis001 }, lipFace(plane002))
|
||||
|
||||
// create the corners of the bin
|
||||
lipCorners000 = patternCircular3d(
|
||||
lipSingleLengthCorner,
|
||||
arcDegrees = 360,
|
||||
axis = [0, 0, 1],
|
||||
center = [
|
||||
(binLength + 2 * binTol) / 2 * countBinWidth,
|
||||
(binLength + 2 * binTol) / 2 * countBinLength,
|
||||
0
|
||||
],
|
||||
instances = 2,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
|
||||
// create the corners of the bin
|
||||
lipCorners001 = patternCircular3d(
|
||||
lipSingleWidthCorner,
|
||||
arcDegrees = 360,
|
||||
axis = [0, 0, 1],
|
||||
center = [
|
||||
(binLength + 2 * binTol) / 2 * countBinWidth,
|
||||
(binLength + 2 * binTol) / 2 * countBinLength,
|
||||
0
|
||||
],
|
||||
instances = 2,
|
||||
rotateDuplicates = true
|
||||
)
|
182
public/kcl-samples/gridfinity-bins/main.kcl
Normal file
182
public/kcl-samples/gridfinity-bins/main.kcl
Normal file
@ -0,0 +1,182 @@
|
||||
// Gridfinity Bins
|
||||
// Gridfinity is a system to help you work more efficiently. This is a system invented by Zack Freedman. There are two main components the baseplate and the bins. The components are comprised of a matrix of squares. Allowing easy stacking and expansion
|
||||
|
||||
// Set units in millimeters (mm)
|
||||
@settings(defaultLengthUnit = mm)
|
||||
|
||||
// Define constants
|
||||
binLength = 41.5
|
||||
binHeight = 7.0
|
||||
binBaseLength = 2.95
|
||||
binTol = 0.25
|
||||
binThk = 1.2
|
||||
cornerRadius = 3.75
|
||||
firstStep = 0.8
|
||||
secondStep = 1.8
|
||||
thirdStep = 2.15
|
||||
magOuterDiam = 6.5
|
||||
magOffset = 4.8
|
||||
magDepth = 2.4
|
||||
|
||||
// Number of bins in each direction
|
||||
countBinWidth = 2
|
||||
countBinLength = 3
|
||||
countBinHeight = 2
|
||||
|
||||
// The total height of the baseplate is a summation of the vertical heights of the baseplate steps
|
||||
height = firstStep + secondStep + thirdStep
|
||||
|
||||
// define a function which builds the profile of the baseplate bin
|
||||
fn face(plane) {
|
||||
faceSketch = startSketchOn(plane)
|
||||
|> startProfileAt([binBaseLength + binTol, 0], %)
|
||||
|> yLine(height, %)
|
||||
|> xLine(-binBaseLength, %)
|
||||
|> angledLineOfYLength({ angle = -45, length = thirdStep }, %)
|
||||
|> yLine(-secondStep, %)
|
||||
|> angledLineOfYLength({ angle = -45, length = firstStep }, %)
|
||||
|> close()
|
||||
return faceSketch
|
||||
}
|
||||
|
||||
// extrude a single side of the bin
|
||||
singleSide = extrude(face(offsetPlane("YZ", offset = cornerRadius + binTol)), length = binLength - (cornerRadius * 2), )
|
||||
|
||||
// create the other sides of the bin by using a circular pattern
|
||||
sides = patternCircular3d(
|
||||
singleSide,
|
||||
arcDegrees = 360,
|
||||
axis = [0, 0, 1],
|
||||
center = [
|
||||
(binLength + 2 * binTol) / 2,
|
||||
(binLength + 2 * binTol) / 2,
|
||||
0
|
||||
],
|
||||
instances = 4,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
|
||||
// define an axis axis000
|
||||
axis000 = {
|
||||
custom = {
|
||||
axis = [0.0, 1.0],
|
||||
origin = [
|
||||
cornerRadius + binTol,
|
||||
cornerRadius + binTol
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
// create a single corner of the bin
|
||||
singleCorner = revolve({ angle = -90, axis = axis000 }, face(offsetPlane("YZ", offset = cornerRadius + binTol)))
|
||||
|
||||
// create the corners of the bin
|
||||
corners = patternCircular3d(
|
||||
singleCorner,
|
||||
arcDegrees = 360,
|
||||
axis = [0, 0, 1],
|
||||
center = [
|
||||
(binLength + 2 * binTol) / 2,
|
||||
(binLength + 2 * binTol) / 2,
|
||||
0
|
||||
],
|
||||
instances = 4,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
|
||||
singleBinFill = startSketchOn("XY")
|
||||
|> startProfileAt([
|
||||
binBaseLength + binTol,
|
||||
binBaseLength + binTol
|
||||
], %)
|
||||
|> line(end = [binLength - (binBaseLength * 2), 0], tag = $line000)
|
||||
|> line(end = [0, binLength - (binBaseLength * 2)], tag = $line001)
|
||||
|> xLineTo(profileStartX(%), %, $line002)
|
||||
|> close(tag = $line003)
|
||||
|> extrude(length = height)
|
||||
|> fillet(
|
||||
radius = firstStep,
|
||||
tags = [
|
||||
getNextAdjacentEdge(line000),
|
||||
getPreviousAdjacentEdge(line000),
|
||||
getNextAdjacentEdge(line002),
|
||||
getPreviousAdjacentEdge(line002)
|
||||
]
|
||||
)
|
||||
|
||||
magCutout000 = startSketchOn(singleBinFill, "start")
|
||||
|> circle(
|
||||
center = [
|
||||
-magOffset - binBaseLength - binTol,
|
||||
magOffset + binBaseLength + binTol
|
||||
],
|
||||
radius = magOuterDiam / 2
|
||||
)
|
||||
|> patternCircular2d(
|
||||
arcDegrees = 360,
|
||||
center = [
|
||||
(-binLength + 2 * binTol) / 2,
|
||||
(binLength + 2 * binTol) / 2
|
||||
],
|
||||
instances = 4,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
|> extrude(length = -magDepth)
|
||||
|
||||
// create the baseplate by patterning sides
|
||||
binSides = patternLinear3d(
|
||||
sides,
|
||||
axis = [1.0, 0.0, 0.0],
|
||||
instances = countBinWidth,
|
||||
distance = binLength + binTol * 2
|
||||
)
|
||||
|> patternLinear3d(
|
||||
axis = [0.0, 1.0, 0.0],
|
||||
instances = countBinLength,
|
||||
distance = binLength + binTol * 2
|
||||
)
|
||||
|
||||
// create the corners of the baseplate by patterning the corners
|
||||
binCorners = patternLinear3d(
|
||||
corners,
|
||||
axis = [1.0, 0.0, 0.0],
|
||||
instances = countBinWidth,
|
||||
distance = binLength + binTol * 2
|
||||
)
|
||||
|> patternLinear3d(
|
||||
axis = [0.0, 1.0, 0.0],
|
||||
instances = countBinLength,
|
||||
distance = binLength + binTol * 2
|
||||
)
|
||||
|
||||
// create the fill of the bin by patterning the corners
|
||||
binFill = patternLinear3d(
|
||||
singleBinFill,
|
||||
axis = [1.0, 0.0, 0.0],
|
||||
instances = countBinWidth,
|
||||
distance = binLength + binTol * 2
|
||||
)
|
||||
|> patternLinear3d(
|
||||
axis = [0.0, 1.0, 0.0],
|
||||
instances = countBinLength,
|
||||
distance = binLength + binTol * 2
|
||||
)
|
||||
|
||||
// create the top of the bin
|
||||
binTop = startSketchOn(offsetPlane("XY", offset = height))
|
||||
|> startProfileAt([0, 0], %)
|
||||
|> xLine((binLength + 2 * binTol) * countBinWidth, %, $line010)
|
||||
|> yLine((binLength + 2 * binTol) * countBinLength, %, $line011)
|
||||
|> xLineTo(profileStartX(%), %, $line012)
|
||||
|> close(tag = $line013)
|
||||
|> extrude(length = binHeight * countBinHeight)
|
||||
|> fillet(
|
||||
radius = cornerRadius,
|
||||
tags = [
|
||||
getNextAdjacentEdge(line010),
|
||||
getPreviousAdjacentEdge(line010),
|
||||
getNextAdjacentEdge(line012),
|
||||
getPreviousAdjacentEdge(line012)
|
||||
]
|
||||
)
|
||||
|> shell(faces = ["end"], thickness = binThk)
|
31
public/kcl-samples/hex-nut/main.kcl
Normal file
31
public/kcl-samples/hex-nut/main.kcl
Normal file
@ -0,0 +1,31 @@
|
||||
// Hex nut
|
||||
// A hex nut is a type of fastener with a threaded hole and a hexagonal outer shape, used in a wide variety of applications to secure parts together. The hexagonal shape allows for a greater torque to be applied with wrenches or tools, making it one of the most common nut types in hardware.
|
||||
|
||||
// Set Units
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
// Define constants (5/16" - 24 thread size)
|
||||
wallToWallLength = 0.5
|
||||
thickness = 0.266
|
||||
diameter = 0.3125
|
||||
|
||||
// Define a function for the hex nut
|
||||
fn hexNut(start, thk, innerDia) {
|
||||
hexNutSketch = startSketchOn('-XZ')
|
||||
|> startProfileAt([start[0] + innerDia, start[1]], %)
|
||||
|> angledLine({ angle = 240, length = innerDia }, %)
|
||||
|> angledLine({ angle = 180, length = innerDia }, %)
|
||||
|> angledLine({ angle = 120, length = innerDia }, %)
|
||||
|> angledLine({ angle = 60, length = innerDia }, %)
|
||||
|> angledLine({ angle = 0, length = innerDia * .90 }, %)
|
||||
|> close()
|
||||
|> hole(circle(
|
||||
center = [start[0], start[1]],
|
||||
radius = innerDia / 2
|
||||
), %)
|
||||
|> extrude(length = thk)
|
||||
return hexNutSketch
|
||||
}
|
||||
|
||||
// Create a hex nut
|
||||
hexNut([0, 0], thickness, diameter)
|
22
public/kcl-samples/i-beam/main.kcl
Normal file
22
public/kcl-samples/i-beam/main.kcl
Normal file
@ -0,0 +1,22 @@
|
||||
// I-beam
|
||||
// A structural metal beam with an I shaped cross section. Often used in construction
|
||||
|
||||
// Set Units
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
//Define Beam Dimensions
|
||||
beamLength = 24
|
||||
beamWidth = 2.663
|
||||
beamHeight = 4
|
||||
wallThickness = 0.293
|
||||
|
||||
// Sketch a quadrant of the beam cross section, then mirror for symmetry across each axis. Extrude to the appropriate length
|
||||
sketch001 = startSketchOn('-XZ')
|
||||
|> startProfileAt([0, beamHeight/2], %)
|
||||
|> xLine(beamWidth/2, %)
|
||||
|> yLine(-wallThickness, %)
|
||||
|> xLineTo(wallThickness/2, %)
|
||||
|> yLineTo(0, %)
|
||||
|> mirror2d({ axis = 'X' }, %)
|
||||
|> mirror2d({ axis = 'Y' }, %)
|
||||
|> extrude(length = beamLength)
|
256
public/kcl-samples/kitt/main.kcl
Normal file
256
public/kcl-samples/kitt/main.kcl
Normal file
@ -0,0 +1,256 @@
|
||||
// Kitt
|
||||
// The beloved KittyCAD mascot in a voxelized style.
|
||||
|
||||
// pixel box function
|
||||
fn pixelBox(kitExtrude, extrudeTag, positionY, positionZ, width, height, depth) {
|
||||
pixelBoxBody = startSketchOn(kitExtrude, extrudeTag)
|
||||
|> startProfileAt([positionY, positionZ], %)
|
||||
|> line(end = [0, height])
|
||||
|> line(end = [width, 0])
|
||||
|> line(end = [0, -height])
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
|> extrude(length = depth)
|
||||
return pixelBoxBody
|
||||
}
|
||||
|
||||
// 1. Kitty Body
|
||||
kitBodyElevation = 6
|
||||
kitBodyWidth = 26
|
||||
kitBodyHeight = 25
|
||||
kitBodyDepth = 18
|
||||
|
||||
kitBody = startSketchOn('XZ')
|
||||
|> startProfileAt([-kitBodyWidth / 2, kitBodyElevation], %)
|
||||
|> line(end = [0, kitBodyHeight])
|
||||
|> line(end = [kitBodyWidth, 0], tag = $seg01)
|
||||
|> line(end = [0, -kitBodyHeight], tag = $seg02)
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
|> extrude(length = kitBodyDepth)
|
||||
|
||||
// 2. Kitty Head (Frame of display)
|
||||
kitHeadOffset = 1
|
||||
kitHeadHeight = 16
|
||||
|
||||
kitHeadElevation = kitBodyElevation + kitBodyHeight - kitHeadOffset - kitHeadHeight
|
||||
|
||||
kitHeadWidth = kitBodyWidth - (kitHeadOffset * 2)
|
||||
kitHeadDepth = 3
|
||||
kitHead = pixelBox(kitBody, 'END', -kitHeadWidth / 2, kitHeadElevation, kitHeadWidth, kitHeadHeight, kitHeadDepth)
|
||||
kitFaceElevation = kitHeadElevation + 2
|
||||
|
||||
// 3. Kitty Face
|
||||
kitFaceWidth = kitHeadWidth - 4
|
||||
kitFaceHeight = kitHeadElevation + kitHeadHeight - kitFaceElevation - 3
|
||||
kitFaceDepth = 2
|
||||
|
||||
kitFace = startSketchOn(kitHead, 'END')
|
||||
|> startProfileAt([-kitFaceWidth / 2, kitFaceElevation], %)
|
||||
|> line(end = [0, 1]) // left lower corner up
|
||||
|> line(end = [-1, 0]) // left lower corner left
|
||||
|> line(end = [0, kitFaceHeight]) // left side up
|
||||
|> line(end = [1, 0]) // left upper corner right
|
||||
|> line(end = [0, 1]) // left upper corner up
|
||||
|> line(end = [kitFaceWidth, 0]) // upper side right
|
||||
|> line(end = [0, -1]) // right upper corner down
|
||||
|> line(end = [1, 0]) // right upper corner right
|
||||
|> line(end = [0, -kitFaceHeight]) // right side down
|
||||
|> line(end = [-1, 0]) // right lower corner left
|
||||
|> line(end = [0, -1]) // right lower corner down
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
|> extrude(length = -kitFaceDepth)
|
||||
|
||||
// Kitty Face Features:
|
||||
// 3.1 Kitty Eyes
|
||||
|
||||
// 3.1.1 Kitty Left Eye
|
||||
kitEyeDepth = 0.5
|
||||
kitEyeHeihgt = kitFaceElevation + 7
|
||||
kitEyeOffset = 7
|
||||
|
||||
// 3.1.2 Kitty Right Eye
|
||||
kitLeftEye1 = pixelBox(kitFace, 'START', -kitEyeOffset, kitEyeHeihgt, 1, 1, kitEyeDepth)
|
||||
|
||||
// 3.2 Kitty Nose
|
||||
kitLeftEye2 = pixelBox(kitFace, 'START', -kitEyeOffset + 1, kitEyeHeihgt + 1, 3, 1, kitEyeDepth)
|
||||
kitLeftEye3 = pixelBox(kitFace, 'START', -kitEyeOffset + 4, kitEyeHeihgt, 1, 1, kitEyeDepth)
|
||||
kitRightEye = pixelBox(kitFace, 'START', kitEyeOffset - 3, kitEyeHeihgt - 1, 2, 4, kitEyeDepth)
|
||||
kitNoseElevation = kitEyeHeihgt - 5
|
||||
kitNose = startSketchOn(kitFace, 'START')
|
||||
|> startProfileAt([-2, kitNoseElevation], %) // H V
|
||||
|> line(end = [0, 1]) // lower-left up
|
||||
|> line(end = [2, 0]) // lower-left right
|
||||
|> line(end = [0, 2]) // mid-left up
|
||||
|> line(end = [-1, 0]) // upper-left left
|
||||
|> line(end = [0, 1]) // upper-left up
|
||||
|> line(end = [3, 0]) // upper-mid right
|
||||
|> line(end = [0, -1]) // upper-right down
|
||||
|> line(end = [-1, 0]) // upper-right left
|
||||
|> line(end = [0, -2]) // mid-left down
|
||||
|> line(end = [2, 0]) // lower-right right
|
||||
|> line(end = [0, -1]) // lower-right down
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
|> extrude(length = kitEyeDepth)
|
||||
|
||||
// 3.3 Kitty Mouth
|
||||
kitMouthOffset = 4
|
||||
kitMouthHeight = kitEyeHeihgt - 3
|
||||
kitMouthUpLeft = pixelBox(kitFace, 'START', -kitMouthOffset, kitMouthHeight, 1, 1, kitEyeDepth)
|
||||
|
||||
// 4. Kitty Belly
|
||||
kitMouthDownLeft = pixelBox(kitFace, 'START', -kitMouthOffset + 1, kitMouthHeight - 1, 1, 1, kitEyeDepth)
|
||||
kitMouthUpRight = pixelBox(kitFace, 'START', kitMouthOffset, kitMouthHeight, 1, 1, kitEyeDepth)
|
||||
kitMouthDownRight = pixelBox(kitFace, 'START', kitMouthOffset - 1, kitMouthHeight - 1, 1, 1, kitEyeDepth)
|
||||
kitBellyElevation = kitBodyElevation + 1
|
||||
|
||||
kitBellyHeight = kitHeadElevation - kitBellyElevation - 1
|
||||
|
||||
// 4.1 Kitty VHS
|
||||
kitBellyWidth = kitHeadWidth
|
||||
kitBellyDepth = kitHeadDepth
|
||||
kitBelly = pixelBox(kitBody, 'END', -kitBellyWidth / 2, kitBellyElevation, kitBellyWidth, kitBellyHeight, kitBellyDepth)
|
||||
kitVHSelevation = kitBellyElevation + 1
|
||||
|
||||
kitVHSheight = 2
|
||||
|
||||
// 4.2 Kitty Floppy
|
||||
kitVHSwidth = 8
|
||||
kitVHSdepth = 1
|
||||
kitVHS = pixelBox(kitBelly, 'END', -kitVHSwidth / 2, kitVHSelevation, kitVHSwidth, kitVHSheight, kitVHSdepth)
|
||||
kitFloppyElevation = kitBellyElevation + 1
|
||||
kitFloppyHeight = 1
|
||||
|
||||
kitFloppyWidth = 5
|
||||
kitFloppyOffset = kitBellyWidth / 2 - 1
|
||||
kitFloppyDepth = 2
|
||||
|
||||
// 4.3 Kitty Belly Button
|
||||
kitFloppy1 = pixelBox(kitBelly, 'END', -kitFloppyOffset, kitFloppyElevation, kitFloppyWidth, kitFloppyHeight, -kitFloppyDepth)
|
||||
kitFloppy2 = pixelBox(kitBelly, 'END', -kitFloppyOffset, kitFloppyElevation + 2, kitFloppyWidth, kitFloppyHeight, -kitFloppyDepth)
|
||||
kitFloppy3 = pixelBox(kitBelly, 'END', kitFloppyOffset, kitFloppyElevation, -kitFloppyWidth, kitFloppyHeight, -kitFloppyDepth)
|
||||
kitBellyButtonOffset = kitHeadWidth / 2 - 3
|
||||
kitBellyButtonElevation = kitHeadElevation - 1
|
||||
|
||||
kitBellyButtonWidth = 2
|
||||
|
||||
// 4.4 Kitty Buttons
|
||||
kitBellyButtonHeight = 1
|
||||
kitBellyButtonDepth = kitHeadDepth + 1
|
||||
kitBellyButton = pixelBox(kitBody, 'END', -kitBellyButtonOffset, kitBellyButtonElevation, kitBellyButtonWidth, kitBellyButtonHeight, kitBellyButtonDepth)
|
||||
|
||||
kitButtonWidth = 1
|
||||
kitButtonHeight = 2
|
||||
kitButtonDepth = kitFloppyDepth
|
||||
kitButtonElevation = kitFloppyElevation + 2
|
||||
|
||||
kitButton1 = pixelBox(kitBelly, 'END', kitFloppyOffset, kitFloppyElevation + 2, -kitButtonWidth, kitButtonHeight, -kitButtonDepth)
|
||||
|
||||
// 5. Kitty Legs
|
||||
kitButton2 = pixelBox(kitBelly, 'END', kitFloppyOffset - kitButtonWidth - 1, kitFloppyElevation + 2, -kitButtonWidth, kitButtonHeight, -kitButtonDepth)
|
||||
kitButton3 = pixelBox(kitBelly, 'END', kitFloppyOffset - (2 * (kitButtonWidth + 1)), kitFloppyElevation + 2, -kitButtonWidth, kitButtonHeight, -kitButtonDepth)
|
||||
|
||||
kitShoeWidth = 7
|
||||
kitShoeLength = 10
|
||||
kitShoeHeight = 3
|
||||
|
||||
fn kitLeg(offsetFront, offsetSide) {
|
||||
kitShoeOffsetFront = kitShoeLength / 2 - (kitBodyDepth / 2) - offsetFront
|
||||
|
||||
kitFootPrint = startSketchOn('XY')
|
||||
|> startProfileAt([offsetSide, kitShoeOffsetFront], %)
|
||||
|> line(end = [kitShoeWidth, 0])
|
||||
|> line(end = [0, -kitShoeLength])
|
||||
|> line(end = [-kitShoeWidth, 0])
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
|
||||
kitShoe = extrude(kitFootPrint, length = kitShoeHeight)
|
||||
|
||||
kitPantsOffsetSide = offsetSide + 1
|
||||
kitPantsOffsetFront = 2 * kitShoeOffsetFront - 2
|
||||
kitPantsWidth = kitShoeWidth - 2
|
||||
kitPantsFrontWidth = kitPantsWidth
|
||||
kitPantsHeight = kitBodyElevation - kitShoeHeight
|
||||
|
||||
kitPants = pixelBox(kitShoe, 'END', kitPantsOffsetSide, kitPantsOffsetFront, kitPantsFrontWidth, kitPantsWidth, kitPantsHeight)
|
||||
|
||||
return kitShoe
|
||||
}
|
||||
kitLegOffset = 3
|
||||
|
||||
kitRightLeg = kitLeg(0, kitLegOffset)
|
||||
kitLeftLeg = kitLeg(0, -kitLegOffset - kitShoeWidth)
|
||||
|
||||
// 6. Kitty Ears
|
||||
kitEarWidth = 8
|
||||
kitEarDepth = 8
|
||||
kitEarHeight = 2
|
||||
|
||||
fn kitEar(earOffsetFront, earOffsetSide) {
|
||||
kitNewEarOffsetFront = kitBodyDepth - earOffsetFront
|
||||
kitNewEarOffsetSide = -(kitBodyWidth / 2 - earOffsetSide)
|
||||
baseVolume = pixelBox(kitBody, seg01, kitNewEarOffsetSide, kitNewEarOffsetFront, kitEarWidth, -kitEarDepth, kitEarHeight)
|
||||
|
||||
secondOffset = 1
|
||||
secondLevel = pixelBox(baseVolume, 'END', kitNewEarOffsetSide + secondOffset, kitNewEarOffsetFront - 0.01, kitEarWidth - (secondOffset * 2), -kitEarDepth + secondOffset * 2, kitEarHeight)
|
||||
|
||||
thirdOffset = 2
|
||||
thirdLevel = pixelBox(secondLevel, 'END', kitNewEarOffsetSide + thirdOffset, kitNewEarOffsetFront - 0.02, kitEarWidth - (thirdOffset * 2), -kitEarDepth + thirdOffset * 2, kitEarHeight)
|
||||
|
||||
fourthOffset = 3
|
||||
fourthLevel = pixelBox(thirdLevel, 'END', kitNewEarOffsetSide + fourthOffset, kitNewEarOffsetFront - 0.03, kitEarWidth - (fourthOffset * 2), -kitEarDepth + fourthOffset * 2, kitEarHeight)
|
||||
|
||||
return baseVolume
|
||||
}
|
||||
kitEarOffsetFront = 4
|
||||
kitEarOffsetSide = 1
|
||||
|
||||
kitRightEar = kitEar(kitEarOffsetFront, kitEarOffsetSide)
|
||||
kitLeftEar = kitEar(kitEarOffsetFront, kitBodyWidth - kitEarWidth - kitEarOffsetSide)
|
||||
|
||||
// 7. Kitty Side
|
||||
// 7.1 Grill
|
||||
grillOffset = 4
|
||||
|
||||
grillRowA = kitBodyElevation + kitBodyHeight - grillOffset
|
||||
grillRowB = grillRowA - 2
|
||||
grillRowC = grillRowA - 4
|
||||
|
||||
grillColumnA = kitBodyDepth - grillOffset
|
||||
grillColumnB = grillColumnA - 1
|
||||
grillColumnC = grillColumnA - 2
|
||||
grillColumnD = grillColumnA - 3
|
||||
grillColumnE = grillColumnA - 4
|
||||
|
||||
grillHoleSize = 1
|
||||
grillHoleDepth = -2
|
||||
|
||||
grillHoleAB = pixelBox(kitBody, seg02, grillRowA, grillColumnB, grillHoleSize, grillHoleSize, grillHoleDepth)
|
||||
|
||||
grillHoleAD = pixelBox(kitBody, seg02, grillRowA, grillColumnD, grillHoleSize, grillHoleSize, grillHoleDepth)
|
||||
|
||||
grillHoleBA = pixelBox(kitBody, seg02, grillRowB, grillColumnA, grillHoleSize, grillHoleSize, grillHoleDepth)
|
||||
|
||||
grillHoleBC = pixelBox(kitBody, seg02, grillRowB, grillColumnC, grillHoleSize, grillHoleSize, grillHoleDepth)
|
||||
|
||||
grillHoleBE = pixelBox(kitBody, seg02, grillRowB, grillColumnE, grillHoleSize, grillHoleSize, grillHoleDepth)
|
||||
|
||||
grillHoleCB = pixelBox(kitBody, seg02, grillRowC, grillColumnB, grillHoleSize, grillHoleSize, grillHoleDepth)
|
||||
|
||||
grillHoleCD = pixelBox(kitBody, seg02, grillRowC, grillColumnD, grillHoleSize, grillHoleSize, grillHoleDepth)
|
||||
|
||||
// 7.2 Kitty Vent
|
||||
kitVentElevation = kitBodyElevation + 1
|
||||
kitVentOffset = 1
|
||||
kitVentHoleWidth = 1
|
||||
kitVentHoleHeight = 4
|
||||
kitVentHoleDepth = grillHoleDepth
|
||||
|
||||
kitVentA = pixelBox(kitBody, seg02, kitVentElevation, kitVentOffset, kitVentHoleHeight, kitVentHoleWidth, kitVentHoleDepth)
|
||||
|
||||
kitVentB = pixelBox(kitBody, seg02, kitVentElevation, kitVentOffset + 2, kitVentHoleHeight, kitVentHoleWidth, kitVentHoleDepth)
|
||||
|
||||
kitVentC = pixelBox(kitBody, seg02, kitVentElevation, kitVentOffset + 4, kitVentHoleHeight, kitVentHoleWidth, kitVentHoleDepth)
|
109
public/kcl-samples/lego/main.kcl
Normal file
109
public/kcl-samples/lego/main.kcl
Normal file
@ -0,0 +1,109 @@
|
||||
// Lego Brick
|
||||
// A standard Lego brick. This is a small, plastic construction block toy that can be interlocked with other blocks to build various structures, models, and figures. There are a lot of hacks used in this code.
|
||||
|
||||
// Set Units
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
// Define constants
|
||||
lbumps = 5 // number of bumps long
|
||||
wbumps = 3 // number of bumps wide
|
||||
pitch = 8.0
|
||||
clearance = 0.1
|
||||
bumpDiam = 4.8
|
||||
bumpHeight = 1.8
|
||||
height = 3.2
|
||||
t = (pitch - (2 * clearance) - bumpDiam) / 2.0
|
||||
postDiam = pitch - t // works out to 6.5
|
||||
totalLength = lbumps * pitch - (2.0 * clearance)
|
||||
totalWidth = wbumps * pitch - (2.0 * clearance)
|
||||
|
||||
// Calculate the number of segments in the length and width
|
||||
lSegments = totalLength / lbumps
|
||||
wSegments = totalWidth / wbumps
|
||||
|
||||
// Add assertions to ensure that the number of bumps are greater than 1
|
||||
assertGreaterThan(lbumps, 1, "lbumps must be greater than 1")
|
||||
assertGreaterThan(wbumps, 1, "wbumps must be greater than 1")
|
||||
|
||||
// Create the plane for the pegs. This is a hack so that the pegs can be patterned along the face of the lego base.
|
||||
pegFace = {
|
||||
plane = {
|
||||
origin = { x = 0, y = 0, z = height },
|
||||
xAxis = { x = 1, y = 0, z = 0 },
|
||||
yAxis = { x = 0, y = 1, z = 0 },
|
||||
zAxis = { x = 0, y = 0, z = 1 }
|
||||
}
|
||||
}
|
||||
|
||||
// Create the plane for the tubes underneath the lego. This is a hack so that the tubes can be patterned underneath the lego.
|
||||
tubeFace = {
|
||||
plane = {
|
||||
origin = { x = 0, y = 0, z = height - t },
|
||||
xAxis = { x = 1, y = 0, z = 0 },
|
||||
yAxis = { x = 0, y = 1, z = 0 },
|
||||
zAxis = { x = 0, y = 0, z = 1 }
|
||||
}
|
||||
}
|
||||
|
||||
// Make the base
|
||||
s = startSketchOn('XY')
|
||||
|> startProfileAt([-totalWidth / 2, -totalLength / 2], %)
|
||||
|> line(end = [totalWidth, 0])
|
||||
|> line(end = [0, totalLength])
|
||||
|> line(end = [-totalWidth, 0])
|
||||
|> close()
|
||||
|> extrude(length = height)
|
||||
|
||||
// Sketch and extrude a rectangular shape to create the shell underneath the lego. This is a hack until we have a shell function.
|
||||
shellExtrude = startSketchOn(s, "start")
|
||||
|> startProfileAt([
|
||||
-(totalWidth / 2 - t),
|
||||
-(totalLength / 2 - t)
|
||||
], %)
|
||||
|> line(end = [totalWidth - (2 * t), 0])
|
||||
|> line(end = [0, totalLength - (2 * t)])
|
||||
|> line(end = [-(totalWidth - (2 * t)), 0])
|
||||
|> close()
|
||||
|> extrude(length = -(height - t))
|
||||
|
||||
// Create the pegs on the top of the base
|
||||
peg = startSketchOn(s, 'end')
|
||||
|> circle(
|
||||
center = [
|
||||
-(pitch * (wbumps - 1) / 2),
|
||||
-(pitch * (lbumps - 1) / 2)
|
||||
],
|
||||
radius = bumpDiam / 2
|
||||
)
|
||||
|> patternLinear2d(
|
||||
axis = [1, 0],
|
||||
instances = wbumps,
|
||||
distance = pitch
|
||||
)
|
||||
|> patternLinear2d(
|
||||
axis = [0, 1],
|
||||
instances = lbumps,
|
||||
distance = pitch
|
||||
)
|
||||
|> extrude(length = bumpHeight)
|
||||
|
||||
// Create the pegs on the bottom of the base
|
||||
tubePattern = startSketchOn(tubeFace)
|
||||
|> circle(
|
||||
center = [
|
||||
-(pitch * (wbumps - 1) / 2 - (pitch / 2)),
|
||||
-(pitch * (lbumps - 1) / 2 - (pitch / 2))
|
||||
],
|
||||
radius = bumpDiam / 2
|
||||
)
|
||||
|> patternLinear2d(
|
||||
axis = [1, 0],
|
||||
instances = wbumps - 1,
|
||||
distance = pitch
|
||||
)
|
||||
|> patternLinear2d(
|
||||
axis = [0, 1],
|
||||
instances = lbumps - 1,
|
||||
distance = pitch
|
||||
)
|
||||
|> extrude(length = -bumpHeight)
|
73
public/kcl-samples/mounting-plate/main.kcl
Normal file
73
public/kcl-samples/mounting-plate/main.kcl
Normal file
@ -0,0 +1,73 @@
|
||||
// Mounting Plate
|
||||
// A flat piece of material, often metal or plastic, that serves as a support or base for attaching, securing, or mounting various types of equipment, devices, or components.
|
||||
|
||||
// Set Units
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
// Define constants
|
||||
plateLength = 10
|
||||
plateWidth = 6
|
||||
filletRadius = 0.5
|
||||
plateThickness = .5
|
||||
centerHoleDiameter = 2
|
||||
|
||||
// Create a function that defines the body width and length of the mounting plate. Tag the corners so they can be passed through the fillet function.
|
||||
fn rectShape(pos, w, l) {
|
||||
rr = startSketchOn('XY')
|
||||
|> startProfileAt([pos[0] - (w / 2), pos[1] - (l / 2)], %)
|
||||
|> line(endAbsolute = [pos[0] + w / 2, pos[1] - (l / 2)], tag = $edge1)
|
||||
|> line(endAbsolute = [pos[0] + w / 2, pos[1] + l / 2], tag = $edge2)
|
||||
|> line(endAbsolute = [pos[0] - (w / 2), pos[1] + l / 2], tag = $edge3)
|
||||
|> close(tag = $edge4)
|
||||
return rr
|
||||
}
|
||||
|
||||
// Define the hole radius and x, y location constants
|
||||
holeRadius = .25
|
||||
holeIndex = .75
|
||||
|
||||
// Create the mounting plate extrusion, holes, and fillets
|
||||
rs = rectShape([0, 0], plateWidth, plateLength)
|
||||
part = rs
|
||||
|> hole(circle(
|
||||
center = [
|
||||
-plateWidth / 2 + holeIndex,
|
||||
plateLength / 2 - holeIndex
|
||||
],
|
||||
radius = holeRadius
|
||||
), %)
|
||||
|> hole(circle(
|
||||
center = [
|
||||
plateWidth / 2 - holeIndex,
|
||||
plateLength / 2 - holeIndex
|
||||
],
|
||||
radius = holeRadius
|
||||
), %)
|
||||
|> hole(circle(
|
||||
center = [
|
||||
-plateWidth / 2 + holeIndex,
|
||||
-plateLength / 2 + holeIndex
|
||||
],
|
||||
radius = holeRadius
|
||||
), %)
|
||||
|> hole(circle(
|
||||
center = [
|
||||
plateWidth / 2 - holeIndex,
|
||||
-plateLength / 2 + holeIndex
|
||||
],
|
||||
radius = holeRadius
|
||||
), %)
|
||||
|> hole(circle(
|
||||
center = [0, 0],
|
||||
radius = centerHoleDiameter
|
||||
), %)
|
||||
|> extrude(length = plateThickness)
|
||||
|> fillet(
|
||||
radius = filletRadius,
|
||||
tags = [
|
||||
getPreviousAdjacentEdge(rs.tags.edge1),
|
||||
getPreviousAdjacentEdge(rs.tags.edge2),
|
||||
getPreviousAdjacentEdge(rs.tags.edge3),
|
||||
getPreviousAdjacentEdge(rs.tags.edge4)
|
||||
]
|
||||
)
|
64
public/kcl-samples/multi-axis-robot/globals.kcl
Normal file
64
public/kcl-samples/multi-axis-robot/globals.kcl
Normal file
@ -0,0 +1,64 @@
|
||||
// Global constants for the multi-axis robot
|
||||
|
||||
// Set Units
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
// Axis Angles
|
||||
export axisJ4 = 25
|
||||
export axisJ3 = 60
|
||||
export axisJ2 = 110
|
||||
export axisJ1 = 80
|
||||
|
||||
// Robot Arm Base
|
||||
export basePlateRadius = 5
|
||||
export basePlateThickness = 0.5
|
||||
export baseChamfer = 2
|
||||
export baseHeight = 5
|
||||
|
||||
// J2 Axis for Robot Arm
|
||||
export axisJ2ArmLength = 31
|
||||
export axisJ2ArmWidth = 4
|
||||
export axisJ2ArmThickness = 2.5
|
||||
|
||||
// J3 Axis for Robot Arm
|
||||
export axisJ3C = axisJ3 - 180 + axisJ2
|
||||
export axisJ3CArmLength = 20
|
||||
export axisJ3CArmWidth = 3.75
|
||||
export axisJ3CArmThickness = 2.5
|
||||
|
||||
// Planes
|
||||
export plane001 = {
|
||||
plane = {
|
||||
origin = [0.0, 0.0, baseHeight - 1.5 + 0.1],
|
||||
xAxis = [1.0, 0.0, 0.0],
|
||||
yAxis = [0.0, 1.0, 0.0],
|
||||
zAxis = [0.0, 0.0, 1.0]
|
||||
}
|
||||
}
|
||||
|
||||
export plane002 = {
|
||||
plane = {
|
||||
origin = [0.0, 0.0, 0.0],
|
||||
xAxis = [
|
||||
sin(toRadians(axisJ1)),
|
||||
cos(toRadians(axisJ1)),
|
||||
0.0
|
||||
],
|
||||
yAxis = [0.0, 0.0, 1.0],
|
||||
zAxis = [1.0, 0.0, 0.0]
|
||||
}
|
||||
}
|
||||
|
||||
// Define Plane to Move J2 Axis Robot Arm
|
||||
export plane003 = {
|
||||
plane = {
|
||||
origin = [-0.1, 0.0, 0.0],
|
||||
xAxis = [
|
||||
sin(toRadians(axisJ1)),
|
||||
cos(toRadians(axisJ1)),
|
||||
0.0
|
||||
],
|
||||
yAxis = [0.0, 0.0, 1.0],
|
||||
zAxis = [1.0, 0.0, 0.0]
|
||||
}
|
||||
}
|
15
public/kcl-samples/multi-axis-robot/main.kcl
Normal file
15
public/kcl-samples/multi-axis-robot/main.kcl
Normal file
@ -0,0 +1,15 @@
|
||||
// Robot Arm
|
||||
// A 4 axis robotic arm for industrial use. These machines can be used for assembly, packaging, organization of goods, and quality inspection processes
|
||||
|
||||
// Set Units
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
import 'robot-arm-base.kcl' as robotArmBase
|
||||
import 'robot-rotating-base.kcl' as rotatingBase
|
||||
import 'robot-arm-j2.kcl' as j2RobotArm
|
||||
import 'robot-arm-j3.kcl' as j3RobotArm
|
||||
|
||||
robotArmBase
|
||||
rotatingBase
|
||||
j2RobotArm
|
||||
j3RobotArm
|
82
public/kcl-samples/multi-axis-robot/robot-arm-base.kcl
Normal file
82
public/kcl-samples/multi-axis-robot/robot-arm-base.kcl
Normal file
@ -0,0 +1,82 @@
|
||||
// Robot Arm Base
|
||||
|
||||
|
||||
// Set Units
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
|
||||
// Import Constants
|
||||
import basePlateRadius, basePlateThickness, baseChamfer, baseHeight from "globals.kcl"
|
||||
|
||||
// Base Plate
|
||||
sketch001 = startSketchOn('XY')
|
||||
|> startProfileAt([-basePlateRadius, -basePlateRadius], %)
|
||||
|> angledLine([0, 2 * basePlateRadius], %, $rectangleSegmentA001)
|
||||
|> angledLine([
|
||||
segAng(rectangleSegmentA001) + 90,
|
||||
2 * basePlateRadius
|
||||
], %, $rectangleSegmentB001)
|
||||
|> angledLine([
|
||||
segAng(rectangleSegmentA001),
|
||||
-segLen(rectangleSegmentA001)
|
||||
], %, $rectangleSegmentC001)
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $rectangleSegmentD001)
|
||||
|> close()
|
||||
extrude001 = extrude(sketch001, length = basePlateThickness)
|
||||
|> chamfer(
|
||||
length = baseChamfer,
|
||||
tags = [
|
||||
getNextAdjacentEdge(rectangleSegmentA001),
|
||||
getNextAdjacentEdge(rectangleSegmentB001),
|
||||
getNextAdjacentEdge(rectangleSegmentC001),
|
||||
getNextAdjacentEdge(rectangleSegmentD001)
|
||||
]
|
||||
)
|
||||
|
||||
// Base Motor for actuating first joint
|
||||
sketch002 = startSketchOn(extrude001, 'END')
|
||||
|> circle(center = [0, 0], radius = 4, tag = $referenceEdge)
|
||||
extrude002 = extrude(sketch002, length = baseHeight - basePlateThickness - 1.5)
|
||||
|> fillet(
|
||||
radius = 0.1,
|
||||
tags = [getOppositeEdge(referenceEdge)]
|
||||
)
|
||||
sketch003 = startSketchOn(extrude002, 'END')
|
||||
|> circle(center = [0, 0], radius = 0.5)
|
||||
extrude003 = extrude(sketch003, length = 1)
|
||||
|
||||
// Pattern M8 mounting bolts in base
|
||||
sketch4A = startSketchOn(extrude001, 'END')
|
||||
|> circle(
|
||||
center = [
|
||||
-basePlateRadius + 1,
|
||||
-basePlateRadius + baseChamfer + 0.5
|
||||
],
|
||||
radius = 0.4
|
||||
)
|
||||
|> patternCircular2d(
|
||||
arcDegrees = 360,
|
||||
center = [0, 0],
|
||||
instances = 4,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
|
||||
extrude4A = extrude(sketch4A, length = -basePlateThickness)
|
||||
|
||||
sketch4B = startSketchOn(extrude001, 'END')
|
||||
|> circle(
|
||||
center = [
|
||||
-basePlateRadius + 0.5 + baseChamfer,
|
||||
-basePlateRadius + 1
|
||||
],
|
||||
radius = 0.4
|
||||
)
|
||||
|> patternCircular2d(
|
||||
arcDegrees = 360,
|
||||
center = [0, 0],
|
||||
instances = 4,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
|
||||
extrude(sketch4B, length = -basePlateThickness)
|
||||
|> appearance(color = "#754110", roughness = 90, metalness = 90)
|
99
public/kcl-samples/multi-axis-robot/robot-arm-j2.kcl
Normal file
99
public/kcl-samples/multi-axis-robot/robot-arm-j2.kcl
Normal file
@ -0,0 +1,99 @@
|
||||
// J2 Axis for Robot Arm
|
||||
|
||||
|
||||
// Set Units
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
|
||||
import axisJ1, axisJ2, axisJ2ArmWidth, axisJ2ArmLength, axisJ2ArmThickness, plane003 from "globals.kcl"
|
||||
|
||||
// Create Body of J2 Robot Arm
|
||||
sketch011 = startSketchOn(plane003)
|
||||
|> startProfileAt([
|
||||
1.75 - (axisJ2ArmWidth / 2 * sin(toRadians(axisJ2))),
|
||||
8 + axisJ2ArmWidth / 2 * cos(toRadians(axisJ2))
|
||||
], %)
|
||||
|> arc({
|
||||
angleStart = 90 + axisJ2,
|
||||
angleEnd = 270 + axisJ2,
|
||||
radius = axisJ2ArmWidth / 2
|
||||
}, %)
|
||||
|> angledLine({
|
||||
angle = axisJ2,
|
||||
length = axisJ2ArmLength
|
||||
}, %)
|
||||
|> arc({
|
||||
angleStart = -90 + axisJ2,
|
||||
angleEnd = 90 + axisJ2,
|
||||
radius = axisJ2ArmWidth / 2
|
||||
}, %)
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
extrude011 = extrude(sketch011, length = -axisJ2ArmThickness)
|
||||
|
||||
sketch012 = startSketchOn(extrude011, 'START')
|
||||
|> circle(center = [-1.75, 8], radius = 1.9, tag = $referenceEdge4)
|
||||
|
||||
extrude012 = extrude(sketch012, length = 0.15)
|
||||
|> fillet(
|
||||
radius = 0.1,
|
||||
tags = [getOppositeEdge(referenceEdge4)]
|
||||
)
|
||||
sketch013 = startSketchOn(extrude011, 'START')
|
||||
|> circle(
|
||||
center = [
|
||||
-1.75 - (axisJ2ArmLength * cos(toRadians(axisJ2))),
|
||||
8 + axisJ2ArmLength * sin(toRadians(axisJ2))
|
||||
],
|
||||
radius = 1.9,
|
||||
tag = $referenceEdge5)
|
||||
|
||||
extrude013 = extrude(sketch013, length = 1)
|
||||
|> fillet(
|
||||
radius = 0.1,
|
||||
tags = [getOppositeEdge(referenceEdge5)]
|
||||
)
|
||||
|
||||
// Draw Bolt Patterns on J2 Robot Arm
|
||||
sketch014 = startSketchOn(extrude012, 'END')
|
||||
|> circle(center = [-1.75, 6.75], radius = 0.2)
|
||||
|> patternCircular2d(
|
||||
center = [-1.75, 8],
|
||||
instances = 8,
|
||||
arcDegrees = 360,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
|
||||
extrude014 = extrude(sketch014, length = 0.15)
|
||||
|
||||
sketch015 = startSketchOn(extrude013, 'END')
|
||||
|> circle(
|
||||
center = [
|
||||
-1.75 - ((axisJ2ArmLength - 1) * cos(toRadians(axisJ2))),
|
||||
8 + (axisJ2ArmLength - 1.5) * sin(toRadians(axisJ2))
|
||||
],
|
||||
radius = 0.2
|
||||
)
|
||||
|> patternCircular2d(
|
||||
center = [
|
||||
-1.75 - (axisJ2ArmLength * cos(toRadians(axisJ2))),
|
||||
8 + axisJ2ArmLength * sin(toRadians(axisJ2))
|
||||
],
|
||||
instances = 4,
|
||||
arcDegrees = 360,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
|
||||
extrude015 = extrude(sketch015, length = 0.15)
|
||||
|
||||
sketch016 = startSketchOn(extrude011, 'END')
|
||||
|> circle(
|
||||
center = [
|
||||
1.75 + axisJ2ArmLength * cos(toRadians(axisJ2)),
|
||||
8 + axisJ2ArmLength * sin(toRadians(axisJ2))
|
||||
],
|
||||
radius = 0.3
|
||||
)
|
||||
|
||||
extrude(sketch016, length = 1)
|
||||
|> appearance(color = "#454545", metalness = 90, roughness = 90)
|
171
public/kcl-samples/multi-axis-robot/robot-arm-j3.kcl
Normal file
171
public/kcl-samples/multi-axis-robot/robot-arm-j3.kcl
Normal file
@ -0,0 +1,171 @@
|
||||
// J3 Robot Arm
|
||||
|
||||
|
||||
// Set Units
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
|
||||
import plane002, axisJ2, axisJ3C, axisJ4, axisJ2ArmLength, axisJ3CArmLength, axisJ3CArmWidth, axisJ3CArmThickness from "globals.kcl"
|
||||
|
||||
// Create Body of J3 Robot Arm
|
||||
sketch017 = startSketchOn(plane002)
|
||||
|> startProfileAt([
|
||||
1.75 + axisJ2ArmLength * cos(toRadians(axisJ2)) - (axisJ3CArmWidth / 2 * sin(toRadians(axisJ3C))),
|
||||
8 + axisJ2ArmLength * sin(toRadians(axisJ2)) + axisJ3CArmWidth / 2 * cos(toRadians(axisJ3C))
|
||||
], %)
|
||||
|> arc({
|
||||
angleStart = 90 + axisJ3C,
|
||||
angleEnd = 270 + axisJ3C,
|
||||
radius = axisJ3CArmWidth / 2
|
||||
}, %)
|
||||
|> angledLine({
|
||||
angle = axisJ3C,
|
||||
length = axisJ3CArmLength
|
||||
}, %)
|
||||
|> arc({
|
||||
angleStart = 270 + axisJ3C,
|
||||
angleEnd = 90 + axisJ3C,
|
||||
radius = axisJ3CArmWidth / 2
|
||||
}, %)
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $seg01)
|
||||
|> close()
|
||||
extrude017 = extrude(sketch017, length = axisJ3CArmThickness)
|
||||
|
||||
sketch018 = startSketchOn(extrude017, 'END')
|
||||
|> circle(
|
||||
center = [
|
||||
1.75 + axisJ2ArmLength * cos(toRadians(axisJ2)),
|
||||
8 + axisJ2ArmLength * sin(toRadians(axisJ2))
|
||||
],
|
||||
radius = 3.7 / 2,
|
||||
tag = $referenceEdge6)
|
||||
|
||||
extrude018 = extrude(sketch018, length = 0.15)
|
||||
|> fillet(
|
||||
radius = 0.1,
|
||||
tags = [getOppositeEdge(referenceEdge6)]
|
||||
)
|
||||
|
||||
// Draw Bolt Pattern on J3 Robot Arm
|
||||
sketch019 = startSketchOn(extrude018, 'END')
|
||||
|> circle(
|
||||
center = [
|
||||
1.75 + (axisJ2ArmLength - 1) * cos(toRadians(axisJ2)),
|
||||
8 + (axisJ2ArmLength - 1.5) * sin(toRadians(axisJ2))
|
||||
],
|
||||
radius = 0.2
|
||||
)
|
||||
|> patternCircular2d(
|
||||
center = [
|
||||
1.75 + axisJ2ArmLength * cos(toRadians(axisJ2)),
|
||||
8 + axisJ2ArmLength * sin(toRadians(axisJ2))
|
||||
],
|
||||
instances = 8,
|
||||
arcDegrees = 360,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
|
||||
extrude019 = extrude(sketch019, length = 0.15)
|
||||
|
||||
// On the J3 Robot Arm Body, Create Mounting Clevis for Grabber Claw
|
||||
sketch020 = startSketchOn(extrude017, 'START')
|
||||
|> circle(
|
||||
center = [
|
||||
-1.75 - (axisJ2ArmLength * cos(toRadians(axisJ2))) - (axisJ3CArmLength * cos(toRadians(axisJ3C))),
|
||||
8 + axisJ2ArmLength * sin(toRadians(axisJ2)) + axisJ3CArmLength * sin(toRadians(axisJ3C))
|
||||
],
|
||||
radius = axisJ3CArmWidth / 2
|
||||
)
|
||||
extrude020 = extrude(sketch020, length = -0.5)
|
||||
|
||||
sketch021 = startSketchOn(extrude017, 'END')
|
||||
|> circle(
|
||||
center = [
|
||||
1.75 + axisJ2ArmLength * cos(toRadians(axisJ2)) + axisJ3CArmLength * cos(toRadians(axisJ3C)),
|
||||
8 + axisJ2ArmLength * sin(toRadians(axisJ2)) + axisJ3CArmLength * sin(toRadians(axisJ3C))
|
||||
],
|
||||
radius = axisJ3CArmWidth / 2.01
|
||||
)
|
||||
|
||||
extrude021 = extrude(sketch021, length = -0.5)
|
||||
|
||||
// Define Grabber Claw Constants
|
||||
grabberLength = 7
|
||||
|
||||
sketch022 = startSketchOn(extrude021, 'START')
|
||||
|> circle(center = [0, 0], radius = 0.10)
|
||||
|
||||
extrude022 = extrude(sketch022, length = -0.01)
|
||||
|
||||
// Build Upper Claw Finger
|
||||
sketch023 = startSketchOn(extrude022, 'START')
|
||||
|> startProfileAt([
|
||||
1.75 + axisJ2ArmLength * cos(toRadians(axisJ2)) + axisJ3CArmLength * cos(toRadians(axisJ3C)),
|
||||
8 + axisJ2ArmLength * sin(toRadians(axisJ2)) + axisJ3CArmLength * sin(toRadians(axisJ3C))
|
||||
], %)
|
||||
|> angledLine({
|
||||
angle = axisJ3C + axisJ4 / 2,
|
||||
length = grabberLength / 4
|
||||
}, %)
|
||||
|> arc({
|
||||
angleStart = 150 + axisJ3C + axisJ4 / 2,
|
||||
angleEnd = 30 + axisJ3C + axisJ4 / 2,
|
||||
radius = grabberLength / 3
|
||||
}, %)
|
||||
|> angledLine({
|
||||
angle = axisJ3C + axisJ4 / 2,
|
||||
length = grabberLength / 6
|
||||
}, %)
|
||||
|> angledLine({
|
||||
angle = axisJ3C + axisJ4 / 2 + 132,
|
||||
length = grabberLength / 3.5
|
||||
}, %)
|
||||
|> angledLine({
|
||||
angle = axisJ3C + axisJ4 / 2 + 160,
|
||||
length = grabberLength / 3.5
|
||||
}, %)
|
||||
|> angledLine({
|
||||
angle = axisJ3C + axisJ4 / 2 + 200,
|
||||
length = grabberLength / 3
|
||||
}, %)
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
|
||||
extrude023 = extrude(sketch023, length = -1.5)
|
||||
|
||||
// Build Lower Claw Finger
|
||||
sketch024 = startSketchOn(extrude022, 'START')
|
||||
|> startProfileAt([
|
||||
1.75 + axisJ2ArmLength * cos(toRadians(axisJ2)) + axisJ3CArmLength * cos(toRadians(axisJ3C)),
|
||||
8 + axisJ2ArmLength * sin(toRadians(axisJ2)) + axisJ3CArmLength * sin(toRadians(axisJ3C))
|
||||
], %)
|
||||
|> angledLine({
|
||||
angle = axisJ3C - (axisJ4 / 2),
|
||||
length = grabberLength / 4
|
||||
}, %)
|
||||
|> arc({
|
||||
angleStart = 210 + axisJ3C - (axisJ4 / 2),
|
||||
angleEnd = 330 + axisJ3C - (axisJ4 / 2),
|
||||
radius = grabberLength / 3
|
||||
}, %)
|
||||
|> angledLine({
|
||||
angle = axisJ3C - (axisJ4 / 2),
|
||||
length = grabberLength / 6
|
||||
}, %)
|
||||
|> angledLine({
|
||||
angle = axisJ3C - (axisJ4 / 2) - 132,
|
||||
length = grabberLength / 3.5
|
||||
}, %)
|
||||
|> angledLine({
|
||||
angle = axisJ3C - (axisJ4 / 2) - 160,
|
||||
length = grabberLength / 3.5
|
||||
}, %)
|
||||
|> angledLine({
|
||||
angle = axisJ3C - (axisJ4 / 2) - 200,
|
||||
length = grabberLength / 3
|
||||
}, %)
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
|
||||
extrude(sketch024, length = -1.5)
|
||||
|> appearance(color = "#6572b3", metalness = 90, roughness = 90)
|
86
public/kcl-samples/multi-axis-robot/robot-rotating-base.kcl
Normal file
86
public/kcl-samples/multi-axis-robot/robot-rotating-base.kcl
Normal file
@ -0,0 +1,86 @@
|
||||
// Robot Rotating Base
|
||||
|
||||
|
||||
// Set Units
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
|
||||
import axisJ1, baseHeight, plane001, plane002 from "globals.kcl"
|
||||
|
||||
// Create Rotating Base
|
||||
sketch005 = startSketchOn(plane001)
|
||||
|> circle(center = [0, 0], radius = 3.9, tag = $referenceEdge1)
|
||||
extrude005 = extrude(sketch005, length = 1.5 - 0.1)
|
||||
|> fillet(
|
||||
radius = 0.1,
|
||||
tags = [getOppositeEdge(referenceEdge1)]
|
||||
)
|
||||
|> appearance(color = "#4f7d54", metalness = 90, roughness = 90)
|
||||
|
||||
sketch006 = startSketchOn(plane002)
|
||||
|> startProfileAt([3.5, baseHeight], %)
|
||||
|> angledLine({ angle = 60, length = 1.75 }, %)
|
||||
|> arc({
|
||||
angleStart = -30,
|
||||
angleEnd = -30 + 180,
|
||||
radius = 3
|
||||
}, %)
|
||||
|> angledLineToY({ angle = 60, to = baseHeight }, %)
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
|
||||
extrude006 = extrude(sketch006, length = 1)
|
||||
|
||||
sketch007 = startSketchOn(extrude006, 'END')
|
||||
|> circle(
|
||||
center = [
|
||||
1.75 * cos(toRadians(axisJ1)) / abs(cos(toRadians(axisJ1))),
|
||||
8
|
||||
],
|
||||
radius = 2.75,
|
||||
tag = $referenceEdge2)
|
||||
extrude007 = extrude(sketch007, length = 1.5)
|
||||
|> fillet(
|
||||
radius = 0.1,
|
||||
tags = [getOppositeEdge(referenceEdge2)]
|
||||
)
|
||||
|
||||
// Draw Bolt Pattern on Rotating Base
|
||||
sketch008 = startSketchOn(extrude007, 'END')
|
||||
|> circle(
|
||||
center = [
|
||||
1.75 * cos(toRadians(axisJ1)) / abs(cos(toRadians(axisJ1))),
|
||||
6.75
|
||||
],
|
||||
radius = 0.2
|
||||
)
|
||||
|> patternCircular2d(
|
||||
center = [
|
||||
1.75 * cos(toRadians(axisJ1)) / abs(cos(toRadians(axisJ1))),
|
||||
8
|
||||
],
|
||||
instances = 4,
|
||||
arcDegrees = 360,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
extrude008 = extrude(sketch008, length = 0.2)
|
||||
|
||||
sketch009 = startSketchOn(extrude007, 'END')
|
||||
|> circle(
|
||||
center = [
|
||||
1.75 * cos(toRadians(axisJ1)) / abs(cos(toRadians(axisJ1))),
|
||||
8
|
||||
],
|
||||
radius = 0.5,
|
||||
tag = $referenceEdge3)
|
||||
extrude009 = extrude(sketch009, length = 0.15)
|
||||
|> fillet(
|
||||
radius = 0.1,
|
||||
tags = [getOppositeEdge(referenceEdge3)]
|
||||
)
|
||||
|> appearance(color = "#4f7d54", metalness = 90, roughness = 90)
|
||||
|
||||
sketch010 = startSketchOn(plane002)
|
||||
|> circle(center = [1.75, 8], radius = 0.3)
|
||||
|
||||
extrude(sketch010, length = -1)
|
196
public/kcl-samples/output_from_kcl.py
Normal file
196
public/kcl-samples/output_from_kcl.py
Normal file
@ -0,0 +1,196 @@
|
||||
import asyncio
|
||||
import os
|
||||
import re
|
||||
from concurrent.futures import ProcessPoolExecutor
|
||||
from io import BytesIO
|
||||
from operator import itemgetter
|
||||
from pathlib import Path
|
||||
|
||||
import kcl
|
||||
import requests
|
||||
from PIL import Image
|
||||
|
||||
RETRIES = 5
|
||||
|
||||
|
||||
def export_step(kcl_path: Path, save_path: Path) -> bool:
|
||||
# determine the current directory
|
||||
try:
|
||||
export_response = asyncio.run(
|
||||
kcl.execute_and_export(str(kcl_path.parent), kcl.FileExportFormat.Step)
|
||||
)
|
||||
|
||||
stl_path = save_path.with_suffix(".step")
|
||||
|
||||
with open(stl_path, "wb") as out:
|
||||
out.write(bytes(export_response[0].contents))
|
||||
|
||||
return True
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return False
|
||||
|
||||
|
||||
def find_files(
|
||||
path: str | Path, valid_suffixes: list[str], name_pattern: str | None = None
|
||||
) -> list[Path]:
|
||||
"""
|
||||
Recursively find files in a folder by a list of provided suffixes or file naming pattern
|
||||
|
||||
Args:
|
||||
path: str | Path
|
||||
Root folder to search
|
||||
valid_suffixes: Container[str]
|
||||
List of valid suffixes to find files by (e.g. ".stp", ".step")
|
||||
name_pattern: str
|
||||
Name pattern to additionally filter files by (e.g. "_component")
|
||||
|
||||
Returns:
|
||||
list[Path]
|
||||
"""
|
||||
path = Path(path)
|
||||
valid_suffixes = [i.lower() for i in valid_suffixes]
|
||||
return sorted(
|
||||
file for file in path.rglob("*")
|
||||
if file.suffix.lower() in valid_suffixes and
|
||||
(name_pattern is None or re.match(name_pattern, file.name))
|
||||
)
|
||||
|
||||
|
||||
def snapshot(kcl_path: Path, save_path: Path) -> bool:
|
||||
try:
|
||||
snapshot_response = asyncio.run(
|
||||
kcl.execute_and_snapshot(str(kcl_path.parent), kcl.ImageFormat.Png)
|
||||
)
|
||||
|
||||
image = Image.open(BytesIO(bytearray(snapshot_response)))
|
||||
|
||||
im_path = save_path.with_suffix(".png")
|
||||
|
||||
image.save(im_path)
|
||||
|
||||
return True
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return False
|
||||
|
||||
|
||||
def update_step_file_dates(step_file_path: Path) -> None:
|
||||
# https://github.com/KittyCAD/cli/blob/main/src/cmd_kcl.rs#L1092
|
||||
regex = r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+\+\d{2}:\d{2}"
|
||||
subst = r"1970-01-01T00:00:00.0+00:00"
|
||||
|
||||
with open(step_file_path, "r") as inp:
|
||||
contents = inp.read()
|
||||
|
||||
contents = re.sub(regex, subst, contents)
|
||||
|
||||
with open(step_file_path, "w") as out:
|
||||
out.write(contents)
|
||||
|
||||
|
||||
def process_single_kcl(kcl_path: Path) -> dict:
|
||||
# The part name is the parent folder since each file is main.kcl
|
||||
part_name = kcl_path.parent.name
|
||||
|
||||
print(f"Processing {part_name}")
|
||||
|
||||
# determine the root dir, which is where this python script
|
||||
root_dir = Path(__file__).parent
|
||||
# step and screenshots for the part are based on the root dir
|
||||
step_path = root_dir / "step" / part_name
|
||||
screenshots_path = root_dir / "screenshots" / part_name
|
||||
|
||||
# attempt step export
|
||||
export_status = export_step(kcl_path=kcl_path, save_path=step_path)
|
||||
count = 1
|
||||
while not export_status and count < RETRIES:
|
||||
export_status = export_step(kcl_path=kcl_path, save_path=step_path)
|
||||
count += 1
|
||||
|
||||
# attempt screenshot
|
||||
snapshot_status = snapshot(kcl_path=kcl_path, save_path=screenshots_path)
|
||||
count = 1
|
||||
while not snapshot_status and count < RETRIES:
|
||||
snapshot_status = snapshot(kcl_path=kcl_path, save_path=screenshots_path)
|
||||
count += 1
|
||||
|
||||
# find relative paths, used for building the README.md
|
||||
kcl_rel_path = kcl_path.relative_to(Path(__file__).parent)
|
||||
step_rel_path = step_path.relative_to(Path(__file__).parent).with_suffix(".step")
|
||||
screenshot_rel_path = screenshots_path.relative_to(Path(__file__).parent).with_suffix(".png")
|
||||
|
||||
# readme string for the part
|
||||
readme_entry = (
|
||||
f"#### [{part_name}]({kcl_rel_path}) ([step]({step_rel_path})) ([screenshot]({screenshot_rel_path}))\n"
|
||||
f"[]({kcl_rel_path})"
|
||||
)
|
||||
|
||||
return {"filename": f"{kcl_rel_path}", "export_status": export_status, "snapshot_status": snapshot_status,
|
||||
"readme_entry": readme_entry}
|
||||
|
||||
|
||||
def update_readme(new_content: str, search_string: str = '---\n') -> None:
|
||||
with open("README.md", 'r', encoding='utf-8') as file:
|
||||
lines = file.readlines()
|
||||
|
||||
# Find the line containing the search string
|
||||
found_index = -1
|
||||
for i, line in enumerate(lines):
|
||||
if search_string in line:
|
||||
found_index = i
|
||||
break
|
||||
|
||||
new_lines = lines[:found_index + 1]
|
||||
new_lines.append(new_content)
|
||||
|
||||
# Write the modified content back to the file
|
||||
with open("README.md", 'w', encoding='utf-8') as file:
|
||||
file.writelines(new_lines)
|
||||
file.write("\n")
|
||||
|
||||
|
||||
def main():
|
||||
kcl_files = find_files(path=Path(__file__).parent, valid_suffixes=[".kcl"], name_pattern="main")
|
||||
|
||||
# run concurrently
|
||||
with ProcessPoolExecutor(max_workers=5) as executor:
|
||||
futures = [executor.submit(process_single_kcl, kcl_file) for kcl_file in kcl_files]
|
||||
results = [future.result() for future in futures]
|
||||
|
||||
results = sorted(results, key=itemgetter('filename'))
|
||||
|
||||
step_files = find_files(path=Path(__file__).parent, valid_suffixes=[".step"])
|
||||
with ProcessPoolExecutor(max_workers=5) as executor:
|
||||
_ = [executor.submit(update_step_file_dates, step_file) for step_file in step_files]
|
||||
|
||||
if False in [i["export_status"] for i in results]:
|
||||
comment_body = "The following files failed to export to STEP format:\n"
|
||||
for i in results:
|
||||
if not i["export_status"]:
|
||||
comment_body += f"{i['filename']}\n"
|
||||
|
||||
url = f"https://api.github.com/repos/{os.getenv('GH_REPO')}/issues/{os.getenv('GH_PR')}/comments"
|
||||
|
||||
headers = {
|
||||
'Authorization': f'token {os.getenv("GH_TOKEN")}',
|
||||
}
|
||||
|
||||
json_data = {
|
||||
'body': comment_body,
|
||||
}
|
||||
|
||||
requests.post(url, headers=headers, json=json_data, timeout=60)
|
||||
|
||||
new_readme_links = []
|
||||
for result in results:
|
||||
if result["export_status"] and result["snapshot_status"]:
|
||||
new_readme_links.append(result["readme_entry"])
|
||||
|
||||
new_readme_str = "\n".join(new_readme_links)
|
||||
|
||||
update_readme(new_readme_str)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
304
public/kcl-samples/pipe-flange-assembly/main.kcl
Normal file
304
public/kcl-samples/pipe-flange-assembly/main.kcl
Normal file
@ -0,0 +1,304 @@
|
||||
// Pipe and Flange Assembly
|
||||
// A crucial component in various piping systems, designed to facilitate the connection, disconnection, and access to piping for inspection, cleaning, and modifications. This assembly combines pipes (long cylindrical conduits) with flanges (plate-like fittings) to create a secure yet detachable joint.
|
||||
|
||||
|
||||
// Set units
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
|
||||
// Define constants
|
||||
flangeThickness = .125
|
||||
flangeBaseDia = 2
|
||||
boreHeight = 1
|
||||
flangePipeDia = 1
|
||||
mountingHoleDia = 0.425
|
||||
screwDia = 0.375
|
||||
tol = 0.010
|
||||
hexNutScale = 0.90
|
||||
wallThickness = 0.5
|
||||
screwLength = 1.125
|
||||
washerThickness = 0.0625
|
||||
screwStart = [
|
||||
0,
|
||||
flangeThickness + washerThickness,
|
||||
1.375
|
||||
]
|
||||
capRatio = .190 / .313 // Ratio grabbed from another screw
|
||||
hexRatio = 5 / 32 / .190 // Ratio grabbed from another screw
|
||||
hexStartingAngle = 210 // first angle of hex pattern (degrees)
|
||||
hexInteriorAngle = 120 // degrees
|
||||
hexChangeAngle = 180 - hexInteriorAngle // degrees
|
||||
|
||||
|
||||
screwPlane = {
|
||||
plane = {
|
||||
origin = {
|
||||
x = screwStart[0],
|
||||
y = screwStart[1],
|
||||
z = screwStart[2]
|
||||
},
|
||||
xAxis = { x = 1, y = 0, z = 0 },
|
||||
yAxis = { x = 0, y = 0, z = 1 },
|
||||
zAxis = { x = 0, y = 1, z = 0 }
|
||||
}
|
||||
}
|
||||
|
||||
fn capScrew(start, length, dia) {
|
||||
headLength = dia // inch
|
||||
wallToWallLength = hexRatio * dia
|
||||
headDia = dia / capRatio
|
||||
hexWallLength = wallToWallLength / 2 * 1 / cos(toRadians(30)) // inch
|
||||
|
||||
|
||||
// Length of Cap Head is always equal to diameter
|
||||
capHeadLength = dia
|
||||
|
||||
// Create the head of the cap screw
|
||||
screwHeadSketch = startSketchOn(screwPlane)
|
||||
|> circle(
|
||||
center = [0, 0],
|
||||
radius = headDia / 2
|
||||
)
|
||||
|
||||
// Extrude the screw head sketch
|
||||
screwHead = extrude(screwHeadSketch, length = dia)
|
||||
|
||||
// Define the sketch of the hex pattern on the screw head
|
||||
hexPatternSketch = startSketchOn(screwHead, 'end')
|
||||
|> startProfileAt([
|
||||
-start[0] + wallToWallLength / 2,
|
||||
start[2]
|
||||
], %)
|
||||
|> yLine(-hexWallLength / 2, %)
|
||||
|> angledLine({
|
||||
angle = hexStartingAngle,
|
||||
length = hexWallLength
|
||||
}, %)
|
||||
|> angledLine({
|
||||
angle = hexStartingAngle - hexChangeAngle,
|
||||
length = hexWallLength
|
||||
}, %)
|
||||
|> angledLine({
|
||||
angle = hexStartingAngle - (2 * hexChangeAngle),
|
||||
length = hexWallLength
|
||||
}, %)
|
||||
|> angledLine({
|
||||
angle = hexStartingAngle - (3 * hexChangeAngle),
|
||||
length = hexWallLength
|
||||
}, %)
|
||||
|> angledLine({
|
||||
angle = hexStartingAngle - (4 * hexChangeAngle),
|
||||
length = hexWallLength
|
||||
}, %)
|
||||
|> close()
|
||||
hexPattern = extrude(hexPatternSketch, length = -headLength * 0.75)
|
||||
|
||||
return hexPattern
|
||||
}
|
||||
|
||||
workingPlane = {
|
||||
plane = {
|
||||
origin = { x = 0, y = flangeThickness, z = 0 },
|
||||
xAxis = { x = 0, y = 0, z = 1 },
|
||||
yAxis = { x = 1, y = 0, z = 0 },
|
||||
zAxis = { x = 0, y = 1, z = 0 }
|
||||
}
|
||||
}
|
||||
|
||||
// Washer function
|
||||
fn washer(plane, start, thk, innerDia, outerDia) {
|
||||
washerSketch = startSketchOn(plane)
|
||||
|> circle(
|
||||
center = [start[0], start[1]],
|
||||
radius = outerDia / 2
|
||||
)
|
||||
|> hole(circle(
|
||||
center = [start[0], start[1]],
|
||||
radius = innerDia / 2
|
||||
), %)
|
||||
|> extrude(length = thk)
|
||||
return washerSketch
|
||||
}
|
||||
|
||||
// Hex nut function
|
||||
fn hexNut(start, thk, innerDia) {
|
||||
hexNutSketch = startSketchOn({
|
||||
plane = {
|
||||
origin = {
|
||||
x = start[0],
|
||||
y = -wallThickness - washerThickness,
|
||||
z = start[2]
|
||||
},
|
||||
xAxis = { x = 1, y = 0, z = 0 },
|
||||
yAxis = { x = 0, y = 0, z = 1 },
|
||||
zAxis = { x = 0, y = 1, z = 0 }
|
||||
}
|
||||
})
|
||||
|> startProfileAt([0 + innerDia * hexNutScale, 0], %)
|
||||
|> angledLine({
|
||||
angle = 240,
|
||||
length = innerDia * hexNutScale
|
||||
}, %)
|
||||
|> angledLine({
|
||||
angle = 180,
|
||||
length = innerDia * hexNutScale
|
||||
}, %)
|
||||
|> angledLine({
|
||||
angle = 120,
|
||||
length = innerDia * hexNutScale
|
||||
}, %)
|
||||
|> angledLine({
|
||||
angle = 60,
|
||||
length = innerDia * hexNutScale
|
||||
}, %)
|
||||
|> angledLine({ angle = 0, length = innerDia * .90 }, %)
|
||||
|> close()
|
||||
|> hole(circle(
|
||||
center = [0, 0],
|
||||
radius = innerDia / 2
|
||||
), %)
|
||||
|> extrude(length = -thk)
|
||||
return hexNutSketch
|
||||
}
|
||||
|
||||
// Mounting holes pattern
|
||||
mountingHolePattern = startSketchOn('XZ')
|
||||
|> circle(
|
||||
center = [screwStart[0], screwStart[2]],
|
||||
radius = screwDia / 2 + tol
|
||||
)
|
||||
|> patternCircular2d(
|
||||
arcDegrees = 360,
|
||||
center = [0, 0],
|
||||
instances = 7,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
|
||||
// Sketch and revolve the pipe
|
||||
pipe = startSketchOn('XY')
|
||||
|> startProfileAt([flangePipeDia / 2 - tol, 0], %)
|
||||
|> line(end = [0, -2])
|
||||
|> angledLine({ angle = -60, length = .5 }, %)
|
||||
|> line(end = [0, -1])
|
||||
|> line(end = [-flangeThickness, 0])
|
||||
|> line(end = [0, 1])
|
||||
|> angledLine({ angle = -240, length = .5 }, %)
|
||||
|> line(end = [0, 5])
|
||||
|> angledLine({ angle = 60, length = .5 }, %)
|
||||
|> line(end = [0, 1])
|
||||
|> line(end = [flangeThickness, 0])
|
||||
|> line(end = [0, -1])
|
||||
|> angledLine({ angle = 240, length = .5 }, %)
|
||||
|> close()
|
||||
|> revolve({ axis = 'y' }, %)
|
||||
|> appearance(color = "#7b79d7")
|
||||
|
||||
// Sketch and extrude the wall
|
||||
wall = startSketchOn('XZ')
|
||||
|> startProfileAt([-4, -4], %)
|
||||
|> line(end = [0, 8])
|
||||
|> line(end = [8, 0])
|
||||
|> line(end = [0, -8])
|
||||
|> close()
|
||||
|> hole(mountingHolePattern, %)
|
||||
|> hole(circle(
|
||||
center = [0, 0],
|
||||
radius = flangePipeDia / 2
|
||||
), %)
|
||||
|> extrude(length = wallThickness)
|
||||
|> appearance(color = "#c7aa8f")
|
||||
|
||||
// Sketch and revolve the flange
|
||||
flangeBase = startSketchOn('XZ')
|
||||
|> circle(
|
||||
center = [0, 0],
|
||||
radius = flangeBaseDia
|
||||
)
|
||||
|> hole(mountingHolePattern, %)
|
||||
|> hole(circle(
|
||||
center = [0, 0],
|
||||
radius = flangePipeDia / 2
|
||||
), %)
|
||||
|> extrude(length = -flangeThickness)
|
||||
|> appearance(color = "#9b9797")
|
||||
|
||||
// Create the washer and pattern around the flange
|
||||
washer(workingPlane, [screwStart[2], screwStart[0]], 0.0625, screwDia + tol, 0.625)
|
||||
|> patternCircular3d(
|
||||
axis = [0, 1, 0],
|
||||
center = [0, 0, 0],
|
||||
instances = 7,
|
||||
arcDegrees = 360,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
|> appearance(color = "#d8da5d")
|
||||
|
||||
// Create the cap screw and pattern around the flange
|
||||
capScrew([
|
||||
0,
|
||||
flangeThickness + washerThickness,
|
||||
1.375
|
||||
], screwLength, screwDia)
|
||||
|> patternCircular3d(
|
||||
axis = [0, 1, 0],
|
||||
center = [0, 0, 0],
|
||||
instances = 7,
|
||||
arcDegrees = 360,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
|> appearance(color = "#4cd411")
|
||||
|
||||
screwBodySketch = startSketchOn(screwPlane)
|
||||
|> circle(
|
||||
center = [0, 0],
|
||||
radius = screwDia / 2
|
||||
)
|
||||
screwBody = extrude(screwBodySketch, length = -screwLength)
|
||||
|> patternCircular3d(
|
||||
axis = [0, 1, 0],
|
||||
center = [0, 0, 0],
|
||||
instances = 7,
|
||||
arcDegrees = 360,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
|> appearance(color = "#4cd411")
|
||||
|
||||
// Create a plane for the washers on the back side of the wall
|
||||
backSideWasherPlane = {
|
||||
plane = {
|
||||
origin = {
|
||||
x = 0,
|
||||
y = -wallThickness - washerThickness,
|
||||
z = 0
|
||||
},
|
||||
xAxis = { x = 0, y = 0, z = 1 },
|
||||
yAxis = { x = 1, y = 0, z = 0 },
|
||||
zAxis = { x = 0, y = 1, z = 0 }
|
||||
}
|
||||
}
|
||||
|
||||
// Create the washers on the backside of the wall
|
||||
washer(backSideWasherPlane, [screwStart[2], screwStart[0]], 0.0625, screwDia + tol, 0.625)
|
||||
|> patternCircular3d(
|
||||
axis = [0, 1, 0],
|
||||
center = [0, 0, 0],
|
||||
instances = 7,
|
||||
arcDegrees = 360,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
|> appearance(color = "#e8ec09")
|
||||
|
||||
// Create the hex nut and pattern around the flange
|
||||
hexNut([
|
||||
screwStart[0],
|
||||
screwStart[1],
|
||||
screwStart[2]
|
||||
], .25, screwDia + tol)
|
||||
|> patternCircular3d(
|
||||
axis = [0, 1, 0],
|
||||
center = [0, 0, 0],
|
||||
instances = 7,
|
||||
arcDegrees = 360,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
|> appearance(color = "#bc3434")
|
35
public/kcl-samples/pipe-with-bend/main.kcl
Normal file
35
public/kcl-samples/pipe-with-bend/main.kcl
Normal file
@ -0,0 +1,35 @@
|
||||
// Pipe with bend
|
||||
// A tubular section or hollow cylinder, usually but not necessarily of circular cross-section, used mainly to convey substances that can flow.
|
||||
|
||||
// Set units
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
// Define constants
|
||||
innerDiameter = 10
|
||||
outerDiameter = 20
|
||||
bendRadius = 30
|
||||
bendAngle = 90
|
||||
|
||||
// create a sketch in the 'XZ' plane
|
||||
sketch000 = startSketchOn("XZ")
|
||||
|
||||
// create a profile for the outer diameter
|
||||
outerProfile = circle(
|
||||
sketch000,
|
||||
center = [bendRadius, 0],
|
||||
radius = outerDiameter / 2
|
||||
)
|
||||
|
||||
// create a profile for the inner diameter
|
||||
innerProfile = circle(
|
||||
sketch000,
|
||||
center = [bendRadius, 0],
|
||||
radius = innerDiameter / 2
|
||||
)
|
||||
|
||||
// create the profile of the pipe
|
||||
pipeProfile = outerProfile
|
||||
|> hole(innerProfile, %)
|
||||
|
||||
// revolve the pipe profile at the desired angle
|
||||
pipe = revolve({ axis = "Y", angle = bendAngle }, pipeProfile)
|
36
public/kcl-samples/pipe/main.kcl
Normal file
36
public/kcl-samples/pipe/main.kcl
Normal file
@ -0,0 +1,36 @@
|
||||
// Pipe
|
||||
// A tubular section or hollow cylinder, usually but not necessarily of circular cross-section, used mainly to convey substances that can flow.
|
||||
|
||||
// Set Units
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
// Define constants
|
||||
pipeTotalLength = 20
|
||||
pipeLargeDiaLength = 1
|
||||
pipeLargeDia = 1
|
||||
pipeSmallDia = .75
|
||||
thickness = 0.125
|
||||
pipeTransitionAngle = 60
|
||||
pipeTransitionLength = 0.5
|
||||
pipeSmallDiaLength = pipeTotalLength - pipeTransitionLength - pipeLargeDiaLength
|
||||
|
||||
// Create the sketch to be revolved around the y-axis. Use the small diameter, large diameter, length, and thickness to define the sketch.
|
||||
pipeSketch = startSketchOn('XY')
|
||||
|> startProfileAt([pipeSmallDia - (thickness / 2), 38], %)
|
||||
|> line(end = [thickness, 0])
|
||||
|> line(end = [0, -pipeSmallDiaLength])
|
||||
|> angledLineOfYLength({
|
||||
angle = -60,
|
||||
length = pipeTransitionLength
|
||||
}, %)
|
||||
|> line(end = [0, -pipeLargeDiaLength])
|
||||
|> xLine(-thickness, %)
|
||||
|> line(end = [0, pipeLargeDiaLength])
|
||||
|> angledLineToX({
|
||||
angle = -pipeTransitionAngle + 180,
|
||||
to = pipeSmallDia - (thickness / 2)
|
||||
}, %)
|
||||
|> close()
|
||||
|
||||
// Revolve the sketch to create the pipe
|
||||
pipe = revolve({ axis = 'y' }, pipeSketch)
|
164
public/kcl-samples/poopy-shoe/main.kcl
Normal file
164
public/kcl-samples/poopy-shoe/main.kcl
Normal file
@ -0,0 +1,164 @@
|
||||
// Poopy Shoe
|
||||
// poop shute for bambu labs printer - optimized for printing.
|
||||
|
||||
// Set units
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
wallThickness = 0.125
|
||||
wallsWidth = 3
|
||||
height = 5.125
|
||||
filletRadius = 0.050
|
||||
backLength = 6
|
||||
exitHeight = 1
|
||||
frontLength = 7
|
||||
|
||||
sketch001 = startSketchOn("-YZ")
|
||||
|> startProfileAt([wallsWidth / 2, 0], %)
|
||||
|> xLine(wallThickness / 2, %)
|
||||
|> angledLineToX({ angle = 60, to = wallsWidth }, %, $seg01)
|
||||
|> yLineTo(height, %)
|
||||
|> xLine(-wallThickness, %)
|
||||
|> yLineTo(segEndY(seg01), %)
|
||||
|> angledLineToX({
|
||||
angle = 60,
|
||||
to = wallsWidth / 2 + wallThickness / 2
|
||||
}, %)
|
||||
|> xLine(-wallThickness, %)
|
||||
|> angledLineToX({ angle = 180 - 60, to = wallThickness }, %)
|
||||
|> yLineTo(height, %)
|
||||
|> xLineTo(0, %)
|
||||
|> yLineTo(segEndY(seg01), %)
|
||||
|> angledLineToY({ angle = 180 - 60, to = 0 }, %)
|
||||
|> close()
|
||||
part001 = revolve({
|
||||
angle = 90,
|
||||
axis = {
|
||||
custom = {
|
||||
axis = [1.0, 0.0],
|
||||
origin = [0.0, height + .0001]
|
||||
}
|
||||
}
|
||||
}, sketch001)
|
||||
|
||||
sketch002 = startSketchOn('-YZ')
|
||||
|> startProfileAt([wallsWidth / 2, 0], %)
|
||||
|> xLine(wallThickness / 2, %)
|
||||
|> angledLineToX({ angle = 60, to = wallsWidth }, %, $seg02)
|
||||
|> yLineTo(height, %)
|
||||
|> xLine(-wallThickness, %)
|
||||
|> yLineTo(segEndY(seg01), %)
|
||||
|> angledLineToX({
|
||||
angle = 60,
|
||||
to = wallsWidth / 2 + wallThickness / 2
|
||||
}, %)
|
||||
|> xLine(-wallThickness, %)
|
||||
|> angledLineToX({ angle = 180 - 60, to = wallThickness }, %)
|
||||
|> yLineTo(height, %)
|
||||
|> xLineTo(0, %)
|
||||
|> yLineTo(segEndY(seg02), %)
|
||||
|> angledLineToY({ angle = 180 - 60, to = 0 }, %)
|
||||
|> close()
|
||||
|> extrude(length = backLength - height)
|
||||
|
||||
customPlane = {
|
||||
plane = {
|
||||
origin = {
|
||||
x = 0,
|
||||
y = -(wallsWidth / 2 - (wallThickness / 2)),
|
||||
z = 0
|
||||
},
|
||||
xAxis = { x = 1, y = 0, z = 0 },
|
||||
yAxis = { x = 0, y = 0, z = 1 },
|
||||
zAxis = { x = 0, y = -1, z = 0 }
|
||||
}
|
||||
}
|
||||
sketch003 = startSketchOn(customPlane)
|
||||
|> startProfileAt([0, 0], %)
|
||||
|> tangentialArc({ offset = 60, radius = height }, %)
|
||||
|> angledLineToY({ angle = 60, to = 0 }, %)
|
||||
|> close()
|
||||
|> extrude(length = wallThickness)
|
||||
|
||||
sketch004 = startSketchOn(sketch002, 'END')
|
||||
|> startProfileAt([0, 0], %)
|
||||
|> yLineTo(height, %)
|
||||
|> xLineTo(wallThickness, %)
|
||||
|> yLineTo(segEndY(seg01), %)
|
||||
|> angledLineToX({
|
||||
angle = 180 - 60,
|
||||
to = wallsWidth / 2 - (wallThickness / 2)
|
||||
}, %)
|
||||
|> xLine(wallThickness, %)
|
||||
|> angledLineToY({ angle = 60, to = segEndY(seg01) }, %)
|
||||
|> yLineTo(height, %)
|
||||
|> xLine(wallThickness, %)
|
||||
|> tangentialArcTo([
|
||||
(frontLength - wallsWidth) / 2 + wallsWidth,
|
||||
height - ((height - exitHeight) / 2)
|
||||
], %)
|
||||
|> tangentialArcTo([frontLength, exitHeight], %)
|
||||
|> yLineTo(0, %)
|
||||
|> close(tag = $seg04)
|
||||
|> extrude(length = wallThickness)
|
||||
|
||||
customPlane2 = {
|
||||
plane = {
|
||||
origin = {
|
||||
x = -1 * (backLength - height + wallsWidth),
|
||||
y = 0,
|
||||
z = 0
|
||||
},
|
||||
xAxis = { x = 0, y = -1, z = 0 },
|
||||
yAxis = { x = 0, y = 0, z = 1 },
|
||||
zAxis = { x = 1, y = 0, z = 0 }
|
||||
}
|
||||
}
|
||||
sketch005 = startSketchOn(customPlane2)
|
||||
|> startProfileAt([0, 0], %)
|
||||
|> yLineTo(height, %)
|
||||
|> xLineTo(wallsWidth, %)
|
||||
|> tangentialArcTo([
|
||||
(frontLength - wallsWidth) / 2 + wallsWidth,
|
||||
height - ((height - exitHeight) / 2)
|
||||
], %)
|
||||
|> tangentialArcTo([frontLength, exitHeight], %)
|
||||
|> yLineTo(0, %, $seg03)
|
||||
|> close()
|
||||
|> extrude(length = wallThickness)
|
||||
|
||||
sketch006 = startSketchOn(sketch005, seg03)
|
||||
|> startProfileAt([0, -1 * (backLength - height)], %)
|
||||
|> xLineTo(-exitHeight, %)
|
||||
|> yLine(-wallsWidth, %)
|
||||
|> xLineTo(0, %)
|
||||
|> close()
|
||||
|> extrude(length = wallThickness)
|
||||
|
||||
sketch007 = startSketchOn(sketch004, 'END')
|
||||
|> startProfileAt([0, 0], %)
|
||||
|> xLineTo(wallThickness, %)
|
||||
|> yLineTo(height, %)
|
||||
|> xLineTo(0, %)
|
||||
|> close()
|
||||
|> extrude(length = wallsWidth - (2 * wallThickness))
|
||||
|
||||
customPlane3 = {
|
||||
plane = {
|
||||
origin = {
|
||||
x = -1 * (backLength - height + wallsWidth),
|
||||
y = 0,
|
||||
z = wallThickness
|
||||
},
|
||||
xAxis = { x = 0, y = -1, z = 0 },
|
||||
yAxis = { x = 1, y = 0, z = 0 },
|
||||
zAxis = { x = 0, y = 0, z = 1 }
|
||||
}
|
||||
}
|
||||
|
||||
sketch008 = startSketchOn(customPlane3)
|
||||
|> startProfileAt([wallThickness, wallThickness], %)
|
||||
|> xLineTo(frontLength, %)
|
||||
|> yLine(wallsWidth - (2 * wallThickness), %)
|
||||
|> xLineTo(wallThickness, %)
|
||||
|> close()
|
||||
|> extrude(length = -wallThickness)
|
2
public/kcl-samples/poopy-shoe/project.toml
Normal file
2
public/kcl-samples/poopy-shoe/project.toml
Normal file
@ -0,0 +1,2 @@
|
||||
[settings.app]
|
||||
themeColor = "255"
|
3
public/kcl-samples/requirements.txt
Normal file
3
public/kcl-samples/requirements.txt
Normal file
@ -0,0 +1,3 @@
|
||||
pillow==11.1.0
|
||||
requests==2.32.3
|
||||
zoo-kcl==0.3.45
|
93
public/kcl-samples/router-template-cross-bar/main.kcl
Normal file
93
public/kcl-samples/router-template-cross-bar/main.kcl
Normal file
@ -0,0 +1,93 @@
|
||||
// Router template for a cross bar
|
||||
// A guide for routing a notch into a cross bar.
|
||||
|
||||
// Set Units
|
||||
@settings(defaultLengthUnit = mm)
|
||||
|
||||
routerDiameter = 12.7
|
||||
templateDiameter = 11 / 16 * inch()
|
||||
templateGap = (templateDiameter - routerDiameter) / 2 - 0.5
|
||||
slateWidthHalf = 41.5 / 2
|
||||
minClampingDistance = 50 + 30
|
||||
templateThickness = 10
|
||||
radius = 10
|
||||
depth = 30
|
||||
distanceToInsideEdge = slateWidthHalf + templateThickness + templateGap
|
||||
sketch001 = startSketchOn('XZ')
|
||||
|> startProfileAt([ZERO, depth + templateGap], %)
|
||||
|> xLine(slateWidthHalf - radius, %, $seg01)
|
||||
|> arc({
|
||||
angleEnd = 0,
|
||||
angleStart = 90,
|
||||
radius = 10 + templateGap
|
||||
}, %, $seg09)
|
||||
|> yLineTo(-templateThickness, %, $seg03)
|
||||
|> xLine(templateThickness, %, $seg07)
|
||||
|> yLineTo((segEndY(seg01) + templateThickness) / 2 - templateThickness, %, $seg02)
|
||||
|> xLineTo(segEndX(seg03) + minClampingDistance, %, $seg06)
|
||||
|> yLine(templateThickness * 2, %, $seg08)
|
||||
|> xLineTo(segEndX(seg02) + 0, %, $seg05)
|
||||
|> yLineTo(segEndY(seg01) + templateThickness, %, $seg10)
|
||||
|> xLineTo(ZERO, %, $seg04)
|
||||
|> xLine(-segLen(seg04), %)
|
||||
|> yLine(-segLen(seg10), %)
|
||||
|> xLine(-segLen(seg05), %)
|
||||
|> yLine(-segLen(seg08), %)
|
||||
|> xLine(segLen(seg06), %)
|
||||
|> yLine(-segLen(seg02), %)
|
||||
|> xLine(segLen(seg07), %)
|
||||
|> yLine(segLen(seg03), %)
|
||||
|> arc({
|
||||
angleEnd = 90,
|
||||
angleStart = 180,
|
||||
radius = 10 + templateGap
|
||||
}, %)
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
extrude001 = extrude(sketch001, length = 5)
|
||||
|
||||
sketch003 = startSketchOn(extrude001, 'START')
|
||||
|> startProfileAt([distanceToInsideEdge, 0], %)
|
||||
|> angledLine([180, templateThickness], %, $rectangleSegmentA002)
|
||||
|> angledLine([
|
||||
segAng(rectangleSegmentA002) + 90,
|
||||
templateThickness
|
||||
], %, $rectangleSegmentB002)
|
||||
|> angledLine([
|
||||
segAng(rectangleSegmentA002),
|
||||
-segLen(rectangleSegmentA002)
|
||||
], %, $rectangleSegmentC002)
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
extrude003 = extrude(sketch003, length = 13)
|
||||
|
||||
sketch002 = startSketchOn(extrude001, 'START')
|
||||
|> startProfileAt([-distanceToInsideEdge, 0], %)
|
||||
|> angledLine([0, templateThickness], %, $rectangleSegmentA001)
|
||||
|> angledLine([
|
||||
segAng(rectangleSegmentA001) - 90,
|
||||
templateThickness
|
||||
], %, $rectangleSegmentB001)
|
||||
|> angledLine([
|
||||
segAng(rectangleSegmentA001),
|
||||
-segLen(rectangleSegmentA001)
|
||||
], %, $rectangleSegmentC001)
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
|
||||
extrude002 = extrude(sketch002, length = 13)
|
||||
|
||||
sketch004 = startSketchOn(extrude002, 'END')
|
||||
|> startProfileAt([-distanceToInsideEdge, 0], %)
|
||||
|> angledLine([0, distanceToInsideEdge * 2], %, $rectangleSegmentA003)
|
||||
|> angledLine([
|
||||
segAng(rectangleSegmentA003) - 90,
|
||||
templateThickness
|
||||
], %, $rectangleSegmentB003)
|
||||
|> angledLine([
|
||||
segAng(rectangleSegmentA003),
|
||||
-segLen(rectangleSegmentA003)
|
||||
], %, $rectangleSegmentC003)
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
extrude004 = extrude(sketch004, length = 4)
|
88
public/kcl-samples/router-template-slate/main.kcl
Normal file
88
public/kcl-samples/router-template-slate/main.kcl
Normal file
@ -0,0 +1,88 @@
|
||||
// Router template for a slate
|
||||
// A guide for routing a slate for a cross bar.
|
||||
|
||||
// Set Units
|
||||
@settings(defaultLengthUnit = mm)
|
||||
|
||||
// Define constants
|
||||
routerDiameter = 12.7
|
||||
templateDiameter = 11 / 16 * inch()
|
||||
templateGap = (templateDiameter - routerDiameter) / 2 - 0.5
|
||||
slateWidthHalf = 41.5 / 2
|
||||
minClampingDistance = 50 + 30
|
||||
templateThickness = 10
|
||||
radius = 10
|
||||
depth = 30
|
||||
length001 = slateWidthHalf - radius
|
||||
length002 = depth + minClampingDistance
|
||||
|
||||
// Create the first sketch
|
||||
sketch001 = startSketchOn('XZ')
|
||||
|> startProfileAt([0, depth - templateGap], %)
|
||||
|> xLine(length001, %, $seg01)
|
||||
|> arc({
|
||||
angleEnd = 0,
|
||||
angleStart = 90,
|
||||
radius = radius - templateGap
|
||||
}, %)
|
||||
|> yLineTo(-templateGap * 2 - (templateDiameter / 2), %, $seg05)
|
||||
|> xLineTo(slateWidthHalf + templateThickness, %, $seg04)
|
||||
|> yLine(-length002, %, $seg03)
|
||||
|> xLineTo(ZERO, %, $seg02)
|
||||
// |> line(end = [7.78, 11.16])
|
||||
|> xLine(-segLen(seg02), %)
|
||||
|> yLine(segLen(seg03), %)
|
||||
|> xLine(segLen(seg04), %)
|
||||
|> yLine(segLen(seg05), %)
|
||||
|> arc({
|
||||
angleEnd = 90,
|
||||
angleStart = 180,
|
||||
radius = radius - templateGap
|
||||
}, %)
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
|
||||
// Extrude the first sketch
|
||||
extrude001 = extrude(sketch001, length = 5)
|
||||
|
||||
// Create the second sketch
|
||||
sketch002 = startSketchOn(extrude001, 'START')
|
||||
|> startProfileAt([
|
||||
-slateWidthHalf,
|
||||
-templateGap * 2 - (templateDiameter / 2)
|
||||
], %)
|
||||
|> xLine(-7, %, $rectangleSegmentA001)
|
||||
|> angledLine([
|
||||
segAng(rectangleSegmentA001) + 90,
|
||||
minClampingDistance
|
||||
], %, $rectangleSegmentB001)
|
||||
|> angledLine([
|
||||
segAng(rectangleSegmentA001),
|
||||
-segLen(rectangleSegmentA001)
|
||||
], %, $rectangleSegmentC001)
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
|
||||
// Extrude the second sketch
|
||||
extrude002 = extrude(sketch002, length = 7.5)
|
||||
|
||||
// Create the third sketch
|
||||
sketch003 = startSketchOn(extrude001, 'START')
|
||||
|> startProfileAt([
|
||||
slateWidthHalf,
|
||||
-templateGap * 2 - (templateDiameter / 2)
|
||||
], %)
|
||||
|> xLine(7, %, $rectangleSegmentA002)
|
||||
|> angledLine([
|
||||
segAng(rectangleSegmentA002) - 90,
|
||||
minClampingDistance
|
||||
], %)
|
||||
|> angledLine([
|
||||
segAng(rectangleSegmentA002),
|
||||
-segLen(rectangleSegmentA002)
|
||||
], %)
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
|
||||
// Extrude the third Sketch
|
||||
extrude003 = extrude(sketch003, length = 7.5)
|
111
public/kcl-samples/sheet-metal-bracket/main.kcl
Normal file
111
public/kcl-samples/sheet-metal-bracket/main.kcl
Normal file
@ -0,0 +1,111 @@
|
||||
// Sheet Metal Bracket
|
||||
// A component typically made from flat sheet metal through various manufacturing processes such as bending, punching, cutting, and forming. These brackets are used to support, attach, or mount other hardware components, often providing a structural or functional base for assembly.
|
||||
|
||||
// Set Units
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
// Define constants such as sheet metal thickness, bend radius, flange length, bolt diameter size, etc.
|
||||
thickness = 0.090
|
||||
bendRad = 0.08
|
||||
outsideBendRad = bendRad + thickness
|
||||
flangeLength = 0.5
|
||||
hatHeight = 3
|
||||
hatWidth = 5
|
||||
boltSize = 0.25
|
||||
flangeWidth = 1.5
|
||||
|
||||
// Sketch and extrude the base shape and fillet the inside and outside edges.
|
||||
baseExtrusion = startSketchOn('-XZ')
|
||||
|> startProfileAt([0, 0], %)
|
||||
|> line(end = [0, thickness], tag = $e1)
|
||||
|> line(end = [flangeLength, 0], tag = $e2)
|
||||
|> line(end = [0, hatHeight], tag = $e3)
|
||||
|> line(end = [hatWidth, 0], tag = $e4)
|
||||
|> line(end = [0, -hatHeight], tag = $e5)
|
||||
|> line(end = [flangeLength, 0], tag = $e6)
|
||||
|> line(end = [0, -thickness], tag = $e7)
|
||||
|> line(end = [-flangeLength - thickness, 0], tag = $e8)
|
||||
|> line(end = [0, hatHeight], tag = $e9)
|
||||
|> line(end = [-hatWidth + 2 * thickness, 0], tag = $e10)
|
||||
|> line(end = [0, -hatHeight], tag = $e11)
|
||||
|> close(tag = $e12)
|
||||
|> extrude(length = hatWidth)
|
||||
|> fillet(
|
||||
radius = bendRad,
|
||||
tags = [getNextAdjacentEdge(e2)]
|
||||
)
|
||||
|> fillet(
|
||||
radius = outsideBendRad,
|
||||
tags = [getNextAdjacentEdge(e3)]
|
||||
)
|
||||
|> fillet(
|
||||
radius = outsideBendRad,
|
||||
tags = [getNextAdjacentEdge(e4)]
|
||||
)
|
||||
|> fillet(
|
||||
radius = bendRad,
|
||||
tags = [getNextAdjacentEdge(e5)]
|
||||
)
|
||||
|> fillet(
|
||||
radius = outsideBendRad,
|
||||
tags = [getNextAdjacentEdge(e8)]
|
||||
)
|
||||
|> fillet(
|
||||
radius = bendRad,
|
||||
tags = [getNextAdjacentEdge(e9)]
|
||||
)
|
||||
|> fillet(
|
||||
radius = bendRad,
|
||||
tags = [getNextAdjacentEdge(e10)]
|
||||
)
|
||||
|> fillet(
|
||||
radius = outsideBendRad,
|
||||
tags = [getNextAdjacentEdge(e11)]
|
||||
)
|
||||
|
||||
// Define the flanges and place the bolt holes
|
||||
flange1 = startSketchOn('XY')
|
||||
|> startProfileAt([0, 0], %)
|
||||
|> line(end = [0, hatWidth])
|
||||
|> line(end = [flangeWidth, 0], tag = $e13)
|
||||
|> line(end = [0, -hatWidth], tag = $e14)
|
||||
|> close()
|
||||
|> hole(circle(
|
||||
center = [0.75, 1],
|
||||
radius = boltSize
|
||||
), %)
|
||||
|> hole(circle(
|
||||
center = [0.75, 4],
|
||||
radius = boltSize
|
||||
), %)
|
||||
|> extrude(length = thickness)
|
||||
|> fillet(
|
||||
radius = 0.5,
|
||||
tags = [
|
||||
getNextAdjacentEdge(e13),
|
||||
getNextAdjacentEdge(e14)
|
||||
]
|
||||
)
|
||||
|
||||
flange2 = startSketchOn('XY')
|
||||
|> startProfileAt([-6, 0], %)
|
||||
|> line(end = [0, hatWidth])
|
||||
|> line(end = [-flangeWidth, 0], tag = $e15)
|
||||
|> line(end = [0, -hatWidth], tag = $e16)
|
||||
|> close()
|
||||
|> hole(circle(
|
||||
center = [-6.75, 1],
|
||||
radius = boltSize
|
||||
), %)
|
||||
|> hole(circle(
|
||||
center = [-6.75, 4],
|
||||
radius = boltSize
|
||||
), %)
|
||||
|> extrude(length = thickness)
|
||||
|> fillet(
|
||||
radius = 0.25,
|
||||
tags = [
|
||||
getNextAdjacentEdge(e15),
|
||||
getNextAdjacentEdge(e16)
|
||||
]
|
||||
)
|
68
public/kcl-samples/socket-head-cap-screw/main.kcl
Normal file
68
public/kcl-samples/socket-head-cap-screw/main.kcl
Normal file
@ -0,0 +1,68 @@
|
||||
// Socket Head Cap Screw
|
||||
// This is for a #10-24 screw that is 1.00 inches long. A socket head cap screw is a type of fastener that is widely used in a variety of applications requiring a high strength fastening solution. It is characterized by its cylindrical head and internal hexagonal drive, which allows for tightening with an Allen wrench or hex key.
|
||||
|
||||
// Set units
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
// Define constants
|
||||
screwLength = 1.0
|
||||
screwDiameter = .190
|
||||
headDiameter = .313
|
||||
headLength = screwDiameter
|
||||
hexWallToWall = 5 / 32
|
||||
capRatio = screwDiameter / headDiameter
|
||||
hexRatio = hexWallToWall / headDiameter
|
||||
hexWallLength = hexWallToWall / 2 * 1 / cos(toRadians(30))
|
||||
hexStartingAngle = 210 // first angle of hex pattern
|
||||
hexInteriorAngle = 120
|
||||
hexChangeAngle = 180 - hexInteriorAngle
|
||||
|
||||
// Write a function that defines the Socket Head Cap Screw
|
||||
fn capScrew(start, length, dia, capHeadLength) {
|
||||
// Create the head of the cap screw
|
||||
screwHeadSketch = startSketchOn('XZ')
|
||||
|> circle(
|
||||
center = [start[0], start[1]],
|
||||
radius = dia / capRatio / 2
|
||||
)
|
||||
|
||||
// Extrude the screw head sketch
|
||||
screwHead = extrude(screwHeadSketch, length = capHeadLength)
|
||||
|
||||
// Define the sketch of the hex pattern on the screw head
|
||||
hexPatternSketch = startSketchOn(screwHead, 'end')
|
||||
|> startProfileAt([hexWallToWall / 2, 0], %)
|
||||
|> yLine(-hexWallLength / 2, %)
|
||||
|> angledLine({
|
||||
angle = hexStartingAngle,
|
||||
length = hexWallLength
|
||||
}, %)
|
||||
|> angledLine({
|
||||
angle = hexStartingAngle - hexChangeAngle,
|
||||
length = hexWallLength
|
||||
}, %)
|
||||
|> angledLine({
|
||||
angle = hexStartingAngle - (2 * hexChangeAngle),
|
||||
length = hexWallLength
|
||||
}, %)
|
||||
|> angledLine({
|
||||
angle = hexStartingAngle - (3 * hexChangeAngle),
|
||||
length = hexWallLength
|
||||
}, %)
|
||||
|> angledLine({
|
||||
angle = hexStartingAngle - (4 * hexChangeAngle),
|
||||
length = hexWallLength
|
||||
}, %)
|
||||
|> close()
|
||||
hexPattern = extrude(hexPatternSketch, length = -headLength * 0.75)
|
||||
|
||||
screwBodySketch = startSketchOn(screwHead, "start")
|
||||
|> circle(
|
||||
center = [start[0], start[1]],
|
||||
radius = dia / 2
|
||||
)
|
||||
screwBody = extrude(screwBodySketch, length = length)
|
||||
return screwBody
|
||||
}
|
||||
|
||||
capScrew([0, 0], screwLength, screwDiameter, screwDiameter)
|
50
public/kcl-samples/walkie-talkie/antenna.kcl
Normal file
50
public/kcl-samples/walkie-talkie/antenna.kcl
Normal file
@ -0,0 +1,50 @@
|
||||
// Antenna
|
||||
|
||||
|
||||
// Set units
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
|
||||
// import constants
|
||||
import height, width, antennaBaseWidth, antennaBaseHeight, antennaTopWidth, antennaTopHeight from "globals.kcl"
|
||||
|
||||
// Calculate the origin
|
||||
origin = [-width / 2 + .45, -0.10]
|
||||
|
||||
// Create the antenna
|
||||
antennaX = origin[0]
|
||||
antennaY = origin[1]
|
||||
|
||||
antennaPlane = {
|
||||
plane = {
|
||||
origin = { x = 0, y = 0, z = height / 2 },
|
||||
xAxis = { x = 1, y = 0, z = 0 },
|
||||
yAxis = { x = 0, y = 1, z = 0 },
|
||||
zAxis = { x = 0, y = 0, z = 1 }
|
||||
}
|
||||
}
|
||||
|
||||
// Create the antenna base sketch
|
||||
sketch001 = startSketchOn(antennaPlane)
|
||||
|> startProfileAt([origin[0], origin[1]], %)
|
||||
|> line(end = [antennaBaseWidth, 0])
|
||||
|> line(end = [0, -antennaBaseHeight])
|
||||
|> line(end = [-antennaBaseWidth, 0])
|
||||
|> close()
|
||||
|
||||
// Create the antenna top sketch
|
||||
loftPlane = offsetPlane('XY', offset = height / 2 + 3)
|
||||
|
||||
sketch002 = startSketchOn(loftPlane)
|
||||
|> startProfileAt([
|
||||
origin[0] + (antennaBaseWidth - antennaTopWidth) / 2,
|
||||
origin[1] - ((antennaBaseHeight - antennaTopHeight) / 2)
|
||||
], %)
|
||||
|> xLine(antennaTopWidth, %)
|
||||
|> yLine(-antennaTopHeight, %)
|
||||
|> xLine(-antennaTopWidth, %)
|
||||
|> close()
|
||||
|
||||
// Create the antenna using a loft
|
||||
loft([sketch001, sketch002])
|
||||
|> appearance(color = "#000000")
|
80
public/kcl-samples/walkie-talkie/body.kcl
Normal file
80
public/kcl-samples/walkie-talkie/body.kcl
Normal file
@ -0,0 +1,80 @@
|
||||
// Walkie talkie body
|
||||
|
||||
|
||||
// Set units
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
|
||||
// Import constants
|
||||
import height, width, thickness, chamferLength, offset, screenWidth, screenHeight, screenYPosition, screenDepth, speakerBoxWidth, speakerBoxHeight from "globals.kcl"
|
||||
|
||||
bodySketch = startSketchOn('XZ')
|
||||
|> startProfileAt([-width / 2, height / 2], %)
|
||||
|> xLine(width, %, $chamfer1)
|
||||
|> yLine(-height, %, $chamfer2)
|
||||
|> xLine(-width, %, $chamfer3)
|
||||
|> close(tag = $chamfer4)
|
||||
bodyExtrude = extrude(bodySketch, length = thickness)
|
||||
|> chamfer(
|
||||
length = chamferLength,
|
||||
tags = [
|
||||
getNextAdjacentEdge(chamfer1),
|
||||
getNextAdjacentEdge(chamfer2),
|
||||
getNextAdjacentEdge(chamfer3),
|
||||
getNextAdjacentEdge(chamfer4)
|
||||
]
|
||||
)
|
||||
|
||||
// Define the offset for the indentation
|
||||
sketch002 = startSketchOn(bodyExtrude, 'END')
|
||||
|> startProfileAt([
|
||||
-width / 2 + offset,
|
||||
height / 2 - (chamferLength + offset / 2 * cos(toRadians(45)))
|
||||
], %)
|
||||
|> angledLineToY({ angle = 45, to = height / 2 - offset }, %)
|
||||
|> line(endAbsolute = [
|
||||
width / 2 - (chamferLength + offset / 2 * cos(toRadians(45))),
|
||||
height / 2 - offset
|
||||
])
|
||||
|> angledLineToX({ angle = -45, to = width / 2 - offset }, %)
|
||||
|> line(endAbsolute = [
|
||||
width / 2 - offset,
|
||||
-(height / 2 - (chamferLength + offset / 2 * cos(toRadians(45))))
|
||||
])
|
||||
|> angledLineToY({
|
||||
angle = -135,
|
||||
to = -height / 2 + offset
|
||||
}, %)
|
||||
|> line(endAbsolute = [
|
||||
-(width / 2 - (chamferLength + offset / 2 * cos(toRadians(45)))),
|
||||
-height / 2 + offset
|
||||
])
|
||||
|> angledLineToX({
|
||||
angle = -225,
|
||||
to = -width / 2 + offset
|
||||
}, %)
|
||||
|> close()
|
||||
extrude002 = extrude(sketch002, length = -0.0625)
|
||||
|
||||
// Create the pocket for the screen
|
||||
sketch003 = startSketchOn(extrude002, 'start')
|
||||
|> startProfileAt([-screenWidth / 2, screenYPosition], %)
|
||||
|> xLine(screenWidth, %, $seg01)
|
||||
|> yLine(-screenHeight, %)
|
||||
|> xLine(-segLen(seg01), %)
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
extrude003 = extrude(sketch003, length = screenDepth)
|
||||
|
||||
// Create the speaker box
|
||||
sketch004 = startSketchOn(extrude002, 'start')
|
||||
|> startProfileAt([-1.25 / 2, -.125], %)
|
||||
|> xLine(speakerBoxWidth, %)
|
||||
|> yLine(-speakerBoxHeight, %)
|
||||
|> xLine(-speakerBoxWidth, %)
|
||||
|> close()
|
||||
extrude(sketch004, length = -.5)
|
||||
|> appearance(
|
||||
color = "#277bb0",
|
||||
)
|
||||
|
38
public/kcl-samples/walkie-talkie/button.kcl
Normal file
38
public/kcl-samples/walkie-talkie/button.kcl
Normal file
@ -0,0 +1,38 @@
|
||||
// Walkie Talkie button
|
||||
|
||||
// Set units
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
// Import constants
|
||||
import screenHeight, buttonWidth, tolerance, buttonHeight, buttonThickness from 'globals.kcl'
|
||||
|
||||
|
||||
// Create a function for the button
|
||||
export fn button(origin, rotation, plane) {
|
||||
buttonSketch = startSketchOn(plane)
|
||||
|> startProfileAt([origin[0], origin[1]], %)
|
||||
|> angledLine({
|
||||
angle = 180 + rotation,
|
||||
length = buttonWidth
|
||||
}, %, $tag1)
|
||||
|> angledLine({
|
||||
angle = 270 + rotation,
|
||||
length = buttonHeight
|
||||
}, %, $tag2)
|
||||
|> angledLine({
|
||||
angle = 0 + rotation,
|
||||
length = buttonWidth
|
||||
}, %)
|
||||
|> close()
|
||||
buttonExtrude = extrude(buttonSketch, length = buttonThickness)
|
||||
|> chamfer(
|
||||
length = .050,
|
||||
tags = [
|
||||
getNextAdjacentEdge(tag1),
|
||||
getNextAdjacentEdge(tag2)
|
||||
]
|
||||
)
|
||||
|> appearance(color = "#ff0000")
|
||||
|
||||
return buttonExtrude
|
||||
}
|
85
public/kcl-samples/walkie-talkie/case.kcl
Normal file
85
public/kcl-samples/walkie-talkie/case.kcl
Normal file
@ -0,0 +1,85 @@
|
||||
// Walkie talkie case
|
||||
|
||||
|
||||
// Set units
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
|
||||
// Import constants and Zoo logo
|
||||
import width, height, chamferLength, offset, screenWidth, screenHeight, screenYPosition, screenDepth, speakerBoxWidth, speakerBoxHeight, squareHoleSideLength, caseTolerance from "globals.kcl"
|
||||
import zLogo, oLogo, oLogo2 from "zoo-logo.kcl"
|
||||
|
||||
plane = offsetPlane("XZ", offset = 1)
|
||||
|
||||
fn screenHole(sketchStart) {
|
||||
sketch006 = startSketchOn(sketchStart)
|
||||
|> startProfileAt([-screenWidth / 2, screenYPosition], %)
|
||||
|> xLine(screenWidth, %)
|
||||
|> yLine(-screenHeight, %)
|
||||
|> xLine(-screenWidth, %)
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
return sketch006
|
||||
}
|
||||
|
||||
fn squareHolePattern(plane, x, y) {
|
||||
fn transformX(i) {
|
||||
return { translate = [.125 * i, 0] }
|
||||
}
|
||||
fn transformY(i) {
|
||||
return { translate = [0, -.125 * i] }
|
||||
}
|
||||
squareHolePatternSketch = startSketchOn(plane)
|
||||
|> startProfileAt([-x, -y], %)
|
||||
|> line(end = [squareHoleSideLength / 2, 0])
|
||||
|> line(end = [0, -squareHoleSideLength / 2])
|
||||
|> line(end = [-squareHoleSideLength / 2, 0])
|
||||
|> close()
|
||||
|> patternTransform2d(instances = 13, transform = transformX)
|
||||
|> patternTransform2d(instances = 11, transform = transformY)
|
||||
return squareHolePatternSketch
|
||||
}
|
||||
sketch005 = startSketchOn(offsetPlane("XZ", offset = 1))
|
||||
|> startProfileAt([
|
||||
-width / 2 + offset + caseTolerance,
|
||||
height / 2 - (chamferLength + (offset + caseTolerance) / 2 * cos(toRadians(45)))
|
||||
], %)
|
||||
|> angledLineToY({
|
||||
angle = 45,
|
||||
to = height / 2 - (offset + caseTolerance)
|
||||
}, %)
|
||||
|> line(endAbsolute = [
|
||||
width / 2 - (chamferLength + (offset + caseTolerance) / 2 * cos(toRadians(45))),
|
||||
height / 2 - (offset + caseTolerance)
|
||||
])
|
||||
|> angledLineToX({
|
||||
angle = -45,
|
||||
to = width / 2 - (offset + caseTolerance)
|
||||
}, %)
|
||||
|> line(endAbsolute = [
|
||||
width / 2 - (offset + caseTolerance),
|
||||
-(height / 2 - (chamferLength + (offset + caseTolerance) / 2 * cos(toRadians(45))))
|
||||
])
|
||||
|> angledLineToY({
|
||||
angle = -135,
|
||||
to = -height / 2 + offset + caseTolerance
|
||||
}, %)
|
||||
|> line(endAbsolute = [
|
||||
-(width / 2 - (chamferLength + (offset + caseTolerance) / 2 * cos(toRadians(45)))),
|
||||
-height / 2 + offset + caseTolerance
|
||||
])
|
||||
|> angledLineToX({
|
||||
angle = -225,
|
||||
to = -width / 2 + offset + caseTolerance
|
||||
}, %)
|
||||
|> close()
|
||||
|> hole(screenHole(plane), %)
|
||||
|> hole(squareHolePattern(plane, .75, .125), %)
|
||||
|> hole(zLogo(plane, [-.30, -1.825], .20), %)
|
||||
|> hole(oLogo(plane, [-.075, -1.825], .20), %)
|
||||
|> hole(oLogo2(plane, [-.075, -1.825], .20), %)
|
||||
|> hole(oLogo(plane, [.175, -1.825], .20), %)
|
||||
|> hole(oLogo2(plane, [.175, -1.825], .20), %)
|
||||
|
||||
extrude(sketch005, length = -0.0625)
|
||||
|> appearance(color = '#D0FF01', metalness = 0, roughness = 50)
|
42
public/kcl-samples/walkie-talkie/globals.kcl
Normal file
42
public/kcl-samples/walkie-talkie/globals.kcl
Normal file
@ -0,0 +1,42 @@
|
||||
// Global constants for the walkie talkie
|
||||
|
||||
// Set units
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
// body
|
||||
export height = 4
|
||||
export width = 2.5
|
||||
export thickness = 1
|
||||
export chamferLength = .325
|
||||
export offset = .125
|
||||
export screenWidth = 1.75
|
||||
export screenHeight = 1
|
||||
export screenYPosition = height / 2 - 0.75
|
||||
export screenDepth = -.0625
|
||||
export speakerBoxWidth = 1.25
|
||||
export speakerBoxHeight = 1.25
|
||||
|
||||
// antenna
|
||||
export antennaBaseWidth = .5
|
||||
export antennaBaseHeight = .25
|
||||
export antennaTopWidth = .30
|
||||
export antennaTopHeight = .05
|
||||
|
||||
// button
|
||||
export buttonWidth = .15
|
||||
export tolerance = 0.020
|
||||
export buttonHeight = screenHeight / 2 - tolerance
|
||||
export buttonThickness = .040
|
||||
|
||||
// case
|
||||
export squareHoleSideLength = 0.0625
|
||||
export caseTolerance = 0.010
|
||||
|
||||
// knob
|
||||
export knobDiameter = .5
|
||||
export knobHeight = .25
|
||||
export knobRadius = 0.050
|
||||
|
||||
// talk-button
|
||||
export talkButtonSideLength = 0.5
|
||||
export talkButtonHeight = 0.050
|
38
public/kcl-samples/walkie-talkie/knob.kcl
Normal file
38
public/kcl-samples/walkie-talkie/knob.kcl
Normal file
@ -0,0 +1,38 @@
|
||||
// Walkie talkie knob
|
||||
|
||||
|
||||
// Set units
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
|
||||
// Import constants
|
||||
import width, thickness, height, knobDiameter, knobHeight, knobRadius from "globals.kcl"
|
||||
|
||||
// Define the plane for the knob
|
||||
knobPlane = {
|
||||
plane = {
|
||||
origin = {
|
||||
x = width / 2 - 0.70,
|
||||
y = -thickness / 2,
|
||||
z = height / 2
|
||||
},
|
||||
xAxis = { x = 1, y = 0, z = 0 },
|
||||
yAxis = { x = 0, y = 0, z = 1 },
|
||||
zAxis = { x = 0, y = 1, z = 0 }
|
||||
}
|
||||
}
|
||||
|
||||
// Create the knob sketch and revolve
|
||||
startSketchOn(knobPlane)
|
||||
|> startProfileAt([0.0001, 0], %)
|
||||
|> xLine(knobDiameter / 2, %)
|
||||
|> yLine(knobHeight - 0.05, %)
|
||||
|> arc({
|
||||
angleStart = 0,
|
||||
angleEnd = 90,
|
||||
radius = .05
|
||||
}, %)
|
||||
|> xLineTo(0.0001, %)
|
||||
|> close()
|
||||
|> revolve({ axis = "Y" }, %)
|
||||
|> appearance(color = '#D0FF01', metalness = 90, roughness = 50)
|
50
public/kcl-samples/walkie-talkie/main.kcl
Normal file
50
public/kcl-samples/walkie-talkie/main.kcl
Normal file
@ -0,0 +1,50 @@
|
||||
// Walkie Talkie
|
||||
// A portable, handheld two-way radio device that allows users to communicate wirelessly over short to medium distances. It operates on specific radio frequencies and features a push-to-talk button for transmitting messages, making it ideal for quick and reliable communication in outdoor, work, or emergency settings.
|
||||
|
||||
// Set units
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
// Import parts and constants
|
||||
import 'body.kcl'
|
||||
import 'antenna.kcl'
|
||||
import 'case.kcl'
|
||||
import 'talk-button.kcl' as talkButton
|
||||
import 'knob.kcl'
|
||||
import button from "button.kcl"
|
||||
import width, height, thickness, screenWidth, screenHeight, screenYPosition, tolerance from "globals.kcl"
|
||||
|
||||
// Import the body
|
||||
body
|
||||
|
||||
// Import the case
|
||||
case
|
||||
|
||||
// Import the antenna
|
||||
antenna
|
||||
|
||||
// Import the buttons
|
||||
button([
|
||||
-(screenWidth / 2 + tolerance),
|
||||
screenYPosition
|
||||
], 0, offsetPlane("XZ", offset = thickness))
|
||||
button([
|
||||
-(screenWidth / 2 + tolerance),
|
||||
screenYPosition - (screenHeight / 2)
|
||||
], 0, offsetPlane("XZ", offset = thickness))
|
||||
button([
|
||||
screenWidth / 2 + tolerance,
|
||||
screenYPosition - screenHeight
|
||||
], 180, offsetPlane("XZ", offset = thickness))
|
||||
button([
|
||||
screenWidth / 2 + tolerance,
|
||||
screenYPosition - (screenHeight / 2)
|
||||
], 180, offsetPlane("XZ", offset = thickness))
|
||||
|
||||
// Import the talk button
|
||||
talkButton
|
||||
|
||||
// Import the frequency knob
|
||||
knob
|
||||
|
||||
|
||||
|
46
public/kcl-samples/walkie-talkie/talk-button.kcl
Normal file
46
public/kcl-samples/walkie-talkie/talk-button.kcl
Normal file
@ -0,0 +1,46 @@
|
||||
// Walkie talkie talk button
|
||||
|
||||
|
||||
// Set units
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
|
||||
// Import constants
|
||||
import width, thickness, talkButtonSideLength, talkButtonHeight from "globals.kcl"
|
||||
|
||||
talkButtonPlane = {
|
||||
plane = {
|
||||
origin = {
|
||||
x = width / 2,
|
||||
y = -thickness / 2,
|
||||
z = .5
|
||||
},
|
||||
xAxis = { x = 0, y = 1, z = 0 },
|
||||
yAxis = { x = 0, y = 0, z = 1 },
|
||||
zAxis = { x = 1, y = 0, z = 0 }
|
||||
}
|
||||
}
|
||||
|
||||
// Create the talk button sketch
|
||||
talkButtonSketch = startSketchOn(talkButtonPlane)
|
||||
|> startProfileAt([
|
||||
-talkButtonSideLength / 2,
|
||||
talkButtonSideLength / 2
|
||||
], %)
|
||||
|> xLine(talkButtonSideLength, %, $tag1)
|
||||
|> yLine(-talkButtonSideLength, %, $tag2)
|
||||
|> xLine(-talkButtonSideLength, %, $tag3)
|
||||
|> close(tag = $tag4)
|
||||
|
||||
// Create the talk button and apply fillets
|
||||
extrude(talkButtonSketch, length = talkButtonHeight)
|
||||
|> fillet(
|
||||
radius = 0.050,
|
||||
tags = [
|
||||
getNextAdjacentEdge(tag1),
|
||||
getNextAdjacentEdge(tag2),
|
||||
getNextAdjacentEdge(tag3),
|
||||
getNextAdjacentEdge(tag4)
|
||||
]
|
||||
)
|
||||
|> appearance(color = '#D0FF01', metalness = 90, roughness = 90)
|
83
public/kcl-samples/walkie-talkie/zoo-logo.kcl
Normal file
83
public/kcl-samples/walkie-talkie/zoo-logo.kcl
Normal file
@ -0,0 +1,83 @@
|
||||
// Zoo logo
|
||||
|
||||
// Define a function to draw the ZOO "Z"
|
||||
export fn zLogo(surface, origin, scale) {
|
||||
zSketch = surface
|
||||
|> startProfileAt([
|
||||
0 + origin[0],
|
||||
0.15 * scale + origin[1]
|
||||
], %)
|
||||
|> yLine(-0.15 * scale, %)
|
||||
|> xLine(0.15 * scale, %)
|
||||
|> angledLineToX({
|
||||
angle = 47.15,
|
||||
to = 0.3 * scale + origin[0]
|
||||
}, %, $seg1)
|
||||
|> yLineTo(0 + origin[1], %, $seg3)
|
||||
|> xLine(0.63 * scale, %)
|
||||
|> yLine(0.225 * scale, %)
|
||||
|> xLine(-0.57 * scale, %)
|
||||
|> angledLineToX({
|
||||
angle = 47.15,
|
||||
to = 0.93 * scale + origin[0]
|
||||
}, %)
|
||||
|> yLine(0.15 * scale, %)
|
||||
|> xLine(-0.15 * scale, %)
|
||||
|> angledLine({
|
||||
angle = 47.15,
|
||||
length = -segLen(seg1)
|
||||
}, %, $seg2)
|
||||
|> yLine(segLen(seg3), %)
|
||||
|> xLineTo(0 + origin[0], %)
|
||||
|> yLine(-0.225 * scale, %)
|
||||
|> angledLineThatIntersects({
|
||||
angle = 0,
|
||||
intersectTag = seg2,
|
||||
offset = 0
|
||||
}, %)
|
||||
|> close()
|
||||
return zSketch
|
||||
}
|
||||
|
||||
// Define a function to draw the ZOO "O"
|
||||
export fn oLogo(surface, origin, scale) {
|
||||
oSketch001 = surface
|
||||
|> startProfileAt([
|
||||
.788 * scale + origin[0],
|
||||
.921 * scale + origin[1]
|
||||
], %)
|
||||
|> arc({
|
||||
angleStart = 47.15 + 6,
|
||||
angleEnd = 47.15 - 6 + 180,
|
||||
radius = .525 * scale
|
||||
}, %)
|
||||
|> angledLine({ angle = 47.15, length = .24 * scale }, %)
|
||||
|> arc({
|
||||
angleStart = 47.15 - 11 + 180,
|
||||
angleEnd = 47.15 + 11,
|
||||
radius = .288 * scale
|
||||
}, %)
|
||||
|> close()
|
||||
return oSketch001
|
||||
}
|
||||
|
||||
export fn oLogo2(surface, origin, scale) {
|
||||
oSketch002 = surface
|
||||
|> startProfileAt([
|
||||
.16 * scale + origin[0],
|
||||
.079 * scale + origin[1]
|
||||
], %)
|
||||
|> arc({
|
||||
angleStart = 47.15 + 6 - 180,
|
||||
angleEnd = 47.15 - 6,
|
||||
radius = .525 * scale
|
||||
}, %)
|
||||
|> angledLine({ angle = 47.15, length = -.24 * scale }, %)
|
||||
|> arc({
|
||||
angleStart = 47.15 - 11,
|
||||
angleEnd = 47.15 + 11 - 180,
|
||||
radius = .288 * scale
|
||||
}, %)
|
||||
|> close()
|
||||
return oSketch002
|
||||
}
|
30
public/kcl-samples/washer/main.kcl
Normal file
30
public/kcl-samples/washer/main.kcl
Normal file
@ -0,0 +1,30 @@
|
||||
// Washer
|
||||
// A small, typically disk-shaped component with a hole in the middle, used in a wide range of applications, primarily in conjunction with fasteners like bolts and screws. Washers distribute the load of a fastener across a broader area. This is especially important when the fastening surface is soft or uneven, as it helps to prevent damage to the surface and ensures the load is evenly distributed, reducing the risk of the fastener becoming loose over time.
|
||||
|
||||
// Set units
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
// Define constants in inches (in)
|
||||
innerDiameter = 0.203
|
||||
outerDiameter = 0.438
|
||||
thicknessMax = 0.038
|
||||
thicknessMin = 0.024
|
||||
|
||||
// Write a function that defines the washer and extrude it.
|
||||
fn washer(plane, innerDia, outerDia, thk) {
|
||||
// Define the sketch of the washer
|
||||
washerSketch = startSketchOn(plane)
|
||||
|> circle(
|
||||
center = [0, 0],
|
||||
radius = outerDia / 2
|
||||
)
|
||||
|> hole(circle(
|
||||
center = [0, 0],
|
||||
radius = innerDia / 2
|
||||
), %)
|
||||
|
||||
washer = extrude(washerSketch, length = thk)
|
||||
return washer
|
||||
}
|
||||
|
||||
washer('XY', innerDiameter, outerDiameter, thicknessMax)
|
@ -37,9 +37,9 @@ run-sim-test test_name:
|
||||
TWENTY_TWENTY=overwrite {{cita}} -p kcl-lib -- tests::{{test_name}}::kcl_test_execute
|
||||
|
||||
overwrite-sim-test test_name:
|
||||
EXPECTORATE=overwrite {{cita}} -p kcl-lib -- simulation_tests::{{test_name}}::parse
|
||||
EXPECTORATE=overwrite {{cita}} -p kcl-lib -- simulation_tests::{{test_name}}::unparse
|
||||
{{cita}} -p kcl-lib -- tests::{{test_name}}::kcl_test_execute
|
||||
EXPECTORATE=overwrite {{cita}} -p kcl-lib --no-quiet -- simulation_tests::{{test_name}}::parse
|
||||
EXPECTORATE=overwrite {{cita}} -p kcl-lib --no-quiet -- simulation_tests::{{test_name}}::unparse
|
||||
TWENTY_TWENTY=overwrite {{cita}} -p kcl-lib --no-quiet -- tests::{{test_name}}::kcl_test_execute
|
||||
|
||||
test:
|
||||
export RUST_BRACKTRACE="full" && cargo nextest run --workspace --no-fail-fast
|
||||
|
@ -1,4 +1,4 @@
|
||||
use std::path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use insta::rounded_redaction;
|
||||
|
||||
@ -10,6 +10,33 @@ use crate::{
|
||||
ModuleId,
|
||||
};
|
||||
|
||||
mod kcl_samples;
|
||||
|
||||
/// A simulation test.
|
||||
#[derive(Debug, Clone)]
|
||||
struct Test {
|
||||
/// The name of the test.
|
||||
name: String,
|
||||
/// The name of the KCL file that's the entry point, e.g. "main.kcl", in the
|
||||
/// `input_dir`.
|
||||
entry_point: String,
|
||||
/// Input KCL files are in this directory.
|
||||
input_dir: PathBuf,
|
||||
/// Expected snapshot output files are in this directory.
|
||||
output_dir: PathBuf,
|
||||
}
|
||||
|
||||
impl Test {
|
||||
fn new(name: &str) -> Self {
|
||||
Self {
|
||||
name: name.to_owned(),
|
||||
entry_point: "input.kcl".to_owned(),
|
||||
input_dir: Path::new("tests").join(name),
|
||||
output_dir: Path::new("tests").join(name),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Deserialize the data from a snapshot.
|
||||
fn get<T: serde::de::DeserializeOwned>(snapshot: &str) -> T {
|
||||
let mut parts = snapshot.split("---");
|
||||
@ -21,16 +48,16 @@ fn get<T: serde::de::DeserializeOwned>(snapshot: &str) -> T {
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn assert_snapshot<F, R>(test_name: &str, operation: &str, f: F)
|
||||
fn assert_snapshot<F, R>(test: &Test, operation: &str, f: F)
|
||||
where
|
||||
F: FnOnce() -> R,
|
||||
{
|
||||
let mut settings = insta::Settings::clone_current();
|
||||
// These make the snapshots more readable and match our dir structure.
|
||||
settings.set_omit_expression(true);
|
||||
settings.set_snapshot_path(format!("../tests/{test_name}"));
|
||||
settings.set_snapshot_path(Path::new("..").join(&test.output_dir));
|
||||
settings.set_prepend_module_to_snapshot(false);
|
||||
settings.set_description(format!("{operation} {test_name}.kcl"));
|
||||
settings.set_description(format!("{operation} {}.kcl", &test.name));
|
||||
// Sorting maps makes them easier to diff.
|
||||
settings.set_sort_maps(true);
|
||||
// Replace UUIDs with the string "[uuid]", because otherwise the tests would constantly
|
||||
@ -43,23 +70,34 @@ where
|
||||
settings.bind(f);
|
||||
}
|
||||
|
||||
fn read(filename: &'static str, test_name: &str) -> String {
|
||||
std::fs::read_to_string(format!("tests/{test_name}/{filename}")).unwrap()
|
||||
fn read<P>(filename: &str, dir: P) -> String
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
std::fs::read_to_string(dir.as_ref().join(filename)).unwrap()
|
||||
}
|
||||
|
||||
fn parse(test_name: &str) {
|
||||
let input = read("input.kcl", test_name);
|
||||
parse_test(&Test::new(test_name));
|
||||
}
|
||||
|
||||
fn parse_test(test: &Test) {
|
||||
let input = read(&test.entry_point, &test.input_dir);
|
||||
let tokens = crate::parsing::token::lex(&input, ModuleId::default()).unwrap();
|
||||
|
||||
// Parse the tokens into an AST.
|
||||
let parse_res = Result::<_, KclError>::Ok(crate::parsing::parse_tokens(tokens).unwrap());
|
||||
assert_snapshot(test_name, "Result of parsing", || {
|
||||
assert_snapshot(test, "Result of parsing", || {
|
||||
insta::assert_json_snapshot!("ast", parse_res);
|
||||
});
|
||||
}
|
||||
|
||||
fn unparse(test_name: &str) {
|
||||
let input = read("ast.snap", test_name);
|
||||
unparse_test(&Test::new(test_name));
|
||||
}
|
||||
|
||||
fn unparse_test(test: &Test) {
|
||||
let input = read("ast.snap", &test.output_dir);
|
||||
let ast_res: Result<Program, KclError> = get(&input);
|
||||
let Ok(ast) = ast_res else {
|
||||
return;
|
||||
@ -67,9 +105,9 @@ fn unparse(test_name: &str) {
|
||||
// Check recasting the AST produces the original string.
|
||||
let actual = ast.recast(&Default::default(), 0);
|
||||
if matches!(std::env::var("EXPECTORATE").as_deref(), Ok("overwrite")) {
|
||||
std::fs::write(format!("tests/{test_name}/input.kcl"), &actual).unwrap();
|
||||
std::fs::write(test.input_dir.join(&test.entry_point), &actual).unwrap();
|
||||
}
|
||||
let expected = read("input.kcl", test_name);
|
||||
let expected = read(&test.entry_point, &test.input_dir);
|
||||
pretty_assertions::assert_eq!(
|
||||
actual,
|
||||
expected,
|
||||
@ -78,42 +116,45 @@ fn unparse(test_name: &str) {
|
||||
}
|
||||
|
||||
async fn execute(test_name: &str, render_to_png: bool) {
|
||||
execute_test(&Test::new(test_name), render_to_png).await
|
||||
}
|
||||
|
||||
async fn execute_test(test: &Test, render_to_png: bool) {
|
||||
// Read the AST from disk.
|
||||
let input = read("ast.snap", test_name);
|
||||
let input = read("ast.snap", &test.output_dir);
|
||||
let ast_res: Result<Node<Program>, KclError> = get(&input);
|
||||
let Ok(ast) = ast_res else {
|
||||
return;
|
||||
};
|
||||
let ast = crate::Program {
|
||||
ast,
|
||||
original_file_contents: read("input.kcl", test_name),
|
||||
original_file_contents: read(&test.entry_point, &test.input_dir),
|
||||
};
|
||||
|
||||
// Run the program.
|
||||
let exec_res = crate::test_server::execute_and_snapshot_ast(
|
||||
ast,
|
||||
crate::settings::types::UnitLength::Mm,
|
||||
Some(Path::new("tests").join(test_name).join("input.kcl").to_owned()),
|
||||
Some(test.input_dir.join(&test.entry_point)),
|
||||
)
|
||||
.await;
|
||||
match exec_res {
|
||||
Ok((exec_state, env_ref, png)) => {
|
||||
let fail_path_str = format!("tests/{test_name}/execution_error.snap");
|
||||
let fail_path = Path::new(&fail_path_str);
|
||||
if std::fs::exists(fail_path).unwrap() {
|
||||
panic!("This test case is expected to fail, but it passed. If this is intended, and the test should actually be passing now, please delete kcl/{fail_path_str}")
|
||||
let fail_path = test.output_dir.join("execution_error.snap");
|
||||
if std::fs::exists(&fail_path).unwrap() {
|
||||
panic!("This test case is expected to fail, but it passed. If this is intended, and the test should actually be passing now, please delete kcl-lib/{}", fail_path.to_string_lossy())
|
||||
}
|
||||
if render_to_png {
|
||||
twenty_twenty::assert_image(format!("tests/{test_name}/rendered_model.png"), &png, 0.99);
|
||||
twenty_twenty::assert_image(test.output_dir.join("rendered_model.png"), &png, 0.99);
|
||||
}
|
||||
let outcome = exec_state.to_wasm_outcome(env_ref);
|
||||
assert_common_snapshots(
|
||||
test_name,
|
||||
test,
|
||||
outcome.operations,
|
||||
outcome.artifact_commands,
|
||||
outcome.artifact_graph,
|
||||
);
|
||||
assert_snapshot(test_name, "Variables in memory after executing", || {
|
||||
assert_snapshot(test, "Variables in memory after executing", || {
|
||||
insta::assert_json_snapshot!("program_memory", outcome.variables, {
|
||||
".**.value" => rounded_redaction(4),
|
||||
".**[].value" => rounded_redaction(4),
|
||||
@ -127,9 +168,8 @@ async fn execute(test_name: &str, render_to_png: bool) {
|
||||
});
|
||||
}
|
||||
Err(e) => {
|
||||
let ok_path_str = format!("tests/{test_name}/program_memory.snap");
|
||||
let ok_path = Path::new(&ok_path_str);
|
||||
let previously_passed = std::fs::exists(ok_path).unwrap();
|
||||
let ok_path = test.output_dir.join("program_memory.snap");
|
||||
let previously_passed = std::fs::exists(&ok_path).unwrap();
|
||||
match e.error {
|
||||
crate::errors::ExecError::Kcl(error) => {
|
||||
// Snapshot the KCL error with a fancy graphical report.
|
||||
@ -142,21 +182,16 @@ async fn execute(test_name: &str, render_to_png: bool) {
|
||||
let report = error.clone().into_miette_report_with_outputs().unwrap();
|
||||
let report = miette::Report::new(report);
|
||||
if previously_passed {
|
||||
eprintln!("This test case failed, but it previously passed. If this is intended, and the test should actually be failing now, please delete kcl/{ok_path_str} and other associated passing artifacts");
|
||||
eprintln!("This test case failed, but it previously passed. If this is intended, and the test should actually be failing now, please delete kcl-lib/{} and other associated passing artifacts", ok_path.to_string_lossy());
|
||||
panic!("{report:?}");
|
||||
}
|
||||
let report = format!("{:?}", report);
|
||||
|
||||
assert_snapshot(test_name, "Error from executing", || {
|
||||
assert_snapshot(test, "Error from executing", || {
|
||||
insta::assert_snapshot!("execution_error", report);
|
||||
});
|
||||
|
||||
assert_common_snapshots(
|
||||
test_name,
|
||||
error.operations,
|
||||
error.artifact_commands,
|
||||
error.artifact_graph,
|
||||
);
|
||||
assert_common_snapshots(test, error.operations, error.artifact_commands, error.artifact_graph);
|
||||
}
|
||||
e => {
|
||||
// These kinds of errors aren't expected to occur. We don't
|
||||
@ -172,12 +207,12 @@ async fn execute(test_name: &str, render_to_png: bool) {
|
||||
/// Assert snapshots that should happen both when KCL execution succeeds and
|
||||
/// when it results in an error.
|
||||
fn assert_common_snapshots(
|
||||
test_name: &str,
|
||||
test: &Test,
|
||||
operations: Vec<Operation>,
|
||||
artifact_commands: Vec<ArtifactCommand>,
|
||||
artifact_graph: ArtifactGraph,
|
||||
) {
|
||||
assert_snapshot(test_name, "Operations executed", || {
|
||||
assert_snapshot(test, "Operations executed", || {
|
||||
insta::assert_json_snapshot!("ops", operations, {
|
||||
"[].unlabeledArg.*.value.**[].from[]" => rounded_redaction(4),
|
||||
"[].unlabeledArg.*.value.**[].to[]" => rounded_redaction(4),
|
||||
@ -185,14 +220,14 @@ fn assert_common_snapshots(
|
||||
"[].labeledArgs.*.value.**[].to[]" => rounded_redaction(4),
|
||||
});
|
||||
});
|
||||
assert_snapshot(test_name, "Artifact commands", || {
|
||||
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),
|
||||
});
|
||||
});
|
||||
assert_snapshot(test_name, "Artifact graph flowchart", || {
|
||||
assert_snapshot(test, "Artifact graph flowchart", || {
|
||||
let flowchart = artifact_graph
|
||||
.to_mermaid_flowchart()
|
||||
.unwrap_or_else(|e| format!("Failed to convert artifact graph to flowchart: {e}"));
|
||||
|
186
rust/kcl-lib/src/simulation_tests/kcl_samples.rs
Normal file
186
rust/kcl-lib/src/simulation_tests/kcl_samples.rs
Normal file
@ -0,0 +1,186 @@
|
||||
//! Run all the KCL samples in the `kcl_samples` directory.
|
||||
//!
|
||||
//! Use the `KCL_SAMPLES_ONLY=gear` environment variable to run only a subset of
|
||||
//! the samples, in this case, all those that start with "gear".
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use fnv::FnvHashSet;
|
||||
use tokio::task::JoinSet;
|
||||
|
||||
use super::Test;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
/// The directory containing the KCL samples source.
|
||||
static ref INPUTS_DIR: PathBuf = Path::new("../../public/kcl-samples").to_path_buf();
|
||||
/// The directory containing the expected output. We keep them isolated in
|
||||
/// their own directory, separate from other simulation tests, so that we
|
||||
/// know whether we've checked them all.
|
||||
static ref OUTPUTS_DIR: PathBuf = Path::new("tests/kcl_samples").to_path_buf();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse() {
|
||||
let write_new = matches!(
|
||||
std::env::var("INSTA_UPDATE").as_deref(),
|
||||
Ok("auto" | "always" | "new" | "unseen")
|
||||
);
|
||||
let filter = filter_from_env();
|
||||
let tests = kcl_samples_inputs(filter.as_deref());
|
||||
let expected_outputs = kcl_samples_outputs(filter.as_deref());
|
||||
|
||||
assert!(!tests.is_empty(), "No KCL samples found");
|
||||
|
||||
let input_names = FnvHashSet::from_iter(tests.iter().map(|t| t.name.clone()));
|
||||
|
||||
for test in tests {
|
||||
if write_new {
|
||||
// Ensure the directory exists for new tests.
|
||||
std::fs::create_dir_all(test.output_dir.clone()).unwrap();
|
||||
}
|
||||
super::parse_test(&test);
|
||||
}
|
||||
|
||||
// Ensure that inputs aren't missing.
|
||||
let missing = expected_outputs
|
||||
.into_iter()
|
||||
.filter(|name| !input_names.contains(name))
|
||||
.collect::<Vec<_>>();
|
||||
assert!(missing.is_empty(), "Expected input kcl-samples for the following. If these are no longer tests, delete the expected output directories for them in {}: {missing:?}", OUTPUTS_DIR.to_string_lossy());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unparse() {
|
||||
// kcl-samples don't always use correct formatting. We don't ignore the
|
||||
// test because we want to allow the just command to work. It's actually
|
||||
// fine when no test runs.
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn kcl_test_execute() {
|
||||
let filter = filter_from_env();
|
||||
let tests = kcl_samples_inputs(filter.as_deref());
|
||||
let expected_outputs = kcl_samples_outputs(filter.as_deref());
|
||||
|
||||
assert!(!tests.is_empty(), "No KCL samples found");
|
||||
|
||||
// Note: This is unordered.
|
||||
let mut tasks = JoinSet::new();
|
||||
// Mapping from task ID to test index.
|
||||
let mut id_to_index = HashMap::new();
|
||||
// Spawn a task for each test.
|
||||
for (index, test) in tests.iter().cloned().enumerate() {
|
||||
let handle = tasks.spawn(async move {
|
||||
super::execute_test(&test, true).await;
|
||||
});
|
||||
id_to_index.insert(handle.id(), index);
|
||||
}
|
||||
|
||||
// Join all the tasks and collect the failures. We cannot just join_all
|
||||
// because insta's error messages don't clearly indicate which test failed.
|
||||
let mut failed = vec![None; tests.len()];
|
||||
while let Some(result) = tasks.join_next().await {
|
||||
let Err(err) = result else {
|
||||
continue;
|
||||
};
|
||||
// When there's an error, store the test name and error message.
|
||||
let index = *id_to_index.get(&err.id()).unwrap();
|
||||
failed[index] = Some(format!("{}: {err}", &tests[index].name));
|
||||
}
|
||||
let failed = failed.into_iter().flatten().collect::<Vec<_>>();
|
||||
assert!(failed.is_empty(), "Failed tests: {}", failed.join("\n"));
|
||||
|
||||
// Ensure that inputs aren't missing.
|
||||
let input_names = FnvHashSet::from_iter(tests.iter().map(|t| t.name.clone()));
|
||||
let missing = expected_outputs
|
||||
.into_iter()
|
||||
.filter(|name| !input_names.contains(name))
|
||||
.collect::<Vec<_>>();
|
||||
assert!(missing.is_empty(), "Expected input kcl-samples for the following. If these are no longer tests, delete the expected output directories for them in {}: {missing:?}", OUTPUTS_DIR.to_string_lossy());
|
||||
}
|
||||
|
||||
fn test(test_name: &str, entry_point: String) -> Test {
|
||||
Test {
|
||||
name: test_name.to_owned(),
|
||||
entry_point,
|
||||
input_dir: INPUTS_DIR.join(test_name),
|
||||
output_dir: OUTPUTS_DIR.join(test_name),
|
||||
}
|
||||
}
|
||||
|
||||
fn filter_from_env() -> Option<String> {
|
||||
std::env::var("KCL_SAMPLES_ONLY").ok().filter(|s| !s.is_empty())
|
||||
}
|
||||
|
||||
fn kcl_samples_inputs(filter: Option<&str>) -> Vec<Test> {
|
||||
let mut tests = Vec::new();
|
||||
for entry in INPUTS_DIR.read_dir().unwrap() {
|
||||
let entry = entry.unwrap();
|
||||
let path = entry.path();
|
||||
if !path.is_dir() {
|
||||
// We're looking for directories only.
|
||||
continue;
|
||||
}
|
||||
let Some(dir_name) = path.file_name() else {
|
||||
continue;
|
||||
};
|
||||
let dir_name_str = dir_name.to_string_lossy();
|
||||
if dir_name_str.starts_with('.') {
|
||||
// Skip hidden directories.
|
||||
continue;
|
||||
}
|
||||
if matches!(dir_name_str.as_ref(), "step" | "screenshots") {
|
||||
// Skip output directories.
|
||||
continue;
|
||||
}
|
||||
if let Some(filter) = &filter {
|
||||
if !dir_name_str.starts_with(filter) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
eprintln!("Found KCL sample: {:?}", dir_name.to_string_lossy());
|
||||
// Look for the entry point inside the directory.
|
||||
let sub_dir = INPUTS_DIR.join(dir_name);
|
||||
let entry_point = if sub_dir.join("main.kcl").exists() {
|
||||
"main.kcl".to_owned()
|
||||
} else {
|
||||
format!("{dir_name_str}.kcl")
|
||||
};
|
||||
tests.push(test(&dir_name_str, entry_point));
|
||||
}
|
||||
|
||||
tests
|
||||
}
|
||||
|
||||
fn kcl_samples_outputs(filter: Option<&str>) -> Vec<String> {
|
||||
let mut outputs = Vec::new();
|
||||
|
||||
for entry in OUTPUTS_DIR.read_dir().unwrap() {
|
||||
let entry = entry.unwrap();
|
||||
let path = entry.path();
|
||||
if !path.is_dir() {
|
||||
// We're looking for directories only.
|
||||
continue;
|
||||
}
|
||||
let Some(dir_name) = path.file_name() else {
|
||||
continue;
|
||||
};
|
||||
let dir_name_str = dir_name.to_string_lossy();
|
||||
if dir_name_str.starts_with('.') {
|
||||
// Skip hidden.
|
||||
continue;
|
||||
}
|
||||
if let Some(filter) = &filter {
|
||||
if !dir_name_str.starts_with(filter) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
eprintln!("Found expected KCL sample: {:?}", &dir_name_str);
|
||||
outputs.push(dir_name_str.into_owned());
|
||||
}
|
||||
|
||||
outputs
|
||||
}
|
11482
rust/kcl-lib/tests/kcl_samples/3d-boaty/artifact_commands.snap
Normal file
11482
rust/kcl-lib/tests/kcl_samples/3d-boaty/artifact_commands.snap
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,6 @@
|
||||
---
|
||||
source: kcl/src/simulation_tests.rs
|
||||
description: Artifact graph flowchart 3d-boaty.kcl
|
||||
extension: md
|
||||
snapshot_kind: binary
|
||||
---
|
File diff suppressed because it is too large
Load Diff
1025
rust/kcl-lib/tests/kcl_samples/3d-boaty/ast.snap
Normal file
1025
rust/kcl-lib/tests/kcl_samples/3d-boaty/ast.snap
Normal file
File diff suppressed because it is too large
Load Diff
1933
rust/kcl-lib/tests/kcl_samples/3d-boaty/ops.snap
Normal file
1933
rust/kcl-lib/tests/kcl_samples/3d-boaty/ops.snap
Normal file
File diff suppressed because it is too large
Load Diff
110
rust/kcl-lib/tests/kcl_samples/3d-boaty/program_memory.snap
Normal file
110
rust/kcl-lib/tests/kcl_samples/3d-boaty/program_memory.snap
Normal file
@ -0,0 +1,110 @@
|
||||
---
|
||||
source: kcl/src/simulation_tests.rs
|
||||
description: Variables in memory after executing 3d-boaty.kcl
|
||||
---
|
||||
{
|
||||
"armRest": {
|
||||
"type": "Function",
|
||||
"__meta": [
|
||||
{
|
||||
"sourceRange": [
|
||||
3641,
|
||||
3831,
|
||||
3
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"backSlats": {
|
||||
"type": "Function",
|
||||
"__meta": [
|
||||
{
|
||||
"sourceRange": [
|
||||
2981,
|
||||
3072,
|
||||
3
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"benchLength": {
|
||||
"type": "Number",
|
||||
"value": 56.0,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Mm"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
},
|
||||
"__meta": [
|
||||
{
|
||||
"sourceRange": [
|
||||
440,
|
||||
442,
|
||||
0
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"connector": {
|
||||
"type": "Function",
|
||||
"__meta": [
|
||||
{
|
||||
"sourceRange": [
|
||||
1877,
|
||||
2040,
|
||||
3
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"divider": {
|
||||
"type": "Function",
|
||||
"__meta": [
|
||||
{
|
||||
"sourceRange": [
|
||||
1319,
|
||||
1594,
|
||||
3
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"dividerThickness": {
|
||||
"type": "Number",
|
||||
"value": 4.0,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Mm"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
},
|
||||
"__meta": [
|
||||
{
|
||||
"sourceRange": [
|
||||
290,
|
||||
291,
|
||||
3
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"seatSlats": {
|
||||
"type": "Function",
|
||||
"__meta": [
|
||||
{
|
||||
"sourceRange": [
|
||||
2462,
|
||||
2548,
|
||||
3
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
BIN
rust/kcl-lib/tests/kcl_samples/3d-boaty/rendered_model.png
Normal file
BIN
rust/kcl-lib/tests/kcl_samples/3d-boaty/rendered_model.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 80 KiB |
4865
rust/kcl-lib/tests/kcl_samples/80-20-rail/artifact_commands.snap
Normal file
4865
rust/kcl-lib/tests/kcl_samples/80-20-rail/artifact_commands.snap
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,6 @@
|
||||
---
|
||||
source: kcl/src/simulation_tests.rs
|
||||
description: Artifact graph flowchart 80-20-rail.kcl
|
||||
extension: md
|
||||
snapshot_kind: binary
|
||||
---
|
@ -0,0 +1,794 @@
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph path2 [Path]
|
||||
2["Path<br>[326, 423, 0]"]
|
||||
3["Segment<br>[431, 536, 0]"]
|
||||
4["Segment<br>[544, 653, 0]"]
|
||||
5["Segment<br>[661, 687, 0]"]
|
||||
6["Segment<br>[695, 804, 0]"]
|
||||
7["Segment<br>[812, 847, 0]"]
|
||||
8["Segment<br>[855, 891, 0]"]
|
||||
9["Segment<br>[899, 936, 0]"]
|
||||
10["Segment<br>[944, 1061, 0]"]
|
||||
11["Segment<br>[1069, 1105, 0]"]
|
||||
12["Segment<br>[1113, 1221, 0]"]
|
||||
13["Segment<br>[1229, 1266, 0]"]
|
||||
14["Segment<br>[1274, 1311, 0]"]
|
||||
15["Segment<br>[1319, 1346, 0]"]
|
||||
16["Segment<br>[1354, 1463, 0]"]
|
||||
17["Segment<br>[1471, 1497, 0]"]
|
||||
18["Segment<br>[1505, 1614, 0]"]
|
||||
19["Segment<br>[1622, 1725, 0]"]
|
||||
20["Segment<br>[1766, 1876, 0]"]
|
||||
21["Segment<br>[1884, 1910, 0]"]
|
||||
22["Segment<br>[1918, 2028, 0]"]
|
||||
23["Segment<br>[2036, 2071, 0]"]
|
||||
24["Segment<br>[2079, 2117, 0]"]
|
||||
25["Segment<br>[2125, 2163, 0]"]
|
||||
26["Segment<br>[2181, 2310, 0]"]
|
||||
27["Segment<br>[2328, 2365, 0]"]
|
||||
28["Segment<br>[2379, 2493, 0]"]
|
||||
29["Segment<br>[2507, 2545, 0]"]
|
||||
30["Segment<br>[2559, 2596, 0]"]
|
||||
31["Segment<br>[2604, 2631, 0]"]
|
||||
32["Segment<br>[2639, 2749, 0]"]
|
||||
33["Segment<br>[2757, 2783, 0]"]
|
||||
34["Segment<br>[2791, 2901, 0]"]
|
||||
35["Segment<br>[2942, 3044, 0]"]
|
||||
36["Segment<br>[3052, 3162, 0]"]
|
||||
37["Segment<br>[3170, 3197, 0]"]
|
||||
38["Segment<br>[3205, 3315, 0]"]
|
||||
39["Segment<br>[3323, 3360, 0]"]
|
||||
40["Segment<br>[3368, 3406, 0]"]
|
||||
41["Segment<br>[3414, 3451, 0]"]
|
||||
42["Segment<br>[3459, 3587, 0]"]
|
||||
43["Segment<br>[3595, 3633, 0]"]
|
||||
44["Segment<br>[3641, 3756, 0]"]
|
||||
45["Segment<br>[3764, 3801, 0]"]
|
||||
46["Segment<br>[3809, 3846, 0]"]
|
||||
47["Segment<br>[3854, 3882, 0]"]
|
||||
48["Segment<br>[3890, 4000, 0]"]
|
||||
49["Segment<br>[4008, 4035, 0]"]
|
||||
50["Segment<br>[4043, 4153, 0]"]
|
||||
51["Segment<br>[4161, 4265, 0]"]
|
||||
52["Segment<br>[4306, 4416, 0]"]
|
||||
53["Segment<br>[4424, 4451, 0]"]
|
||||
54["Segment<br>[4459, 4569, 0]"]
|
||||
55["Segment<br>[4577, 4614, 0]"]
|
||||
56["Segment<br>[4622, 4659, 0]"]
|
||||
57["Segment<br>[4667, 4704, 0]"]
|
||||
58["Segment<br>[4712, 4831, 0]"]
|
||||
59["Segment<br>[4839, 4877, 0]"]
|
||||
60["Segment<br>[4885, 4993, 0]"]
|
||||
61["Segment<br>[5001, 5038, 0]"]
|
||||
62["Segment<br>[5046, 5084, 0]"]
|
||||
63["Segment<br>[5092, 5120, 0]"]
|
||||
64["Segment<br>[5128, 5238, 0]"]
|
||||
65["Segment<br>[5246, 5273, 0]"]
|
||||
66["Segment<br>[5281, 5391, 0]"]
|
||||
67["Segment<br>[5399, 5406, 0]"]
|
||||
68[Solid2d]
|
||||
end
|
||||
subgraph path69 [Path]
|
||||
69["Path<br>[5457, 5634, 0]"]
|
||||
70["Segment<br>[5457, 5634, 0]"]
|
||||
71[Solid2d]
|
||||
end
|
||||
1["Plane<br>[298, 318, 0]"]
|
||||
72["Sweep Extrusion<br>[5646, 5674, 0]"]
|
||||
73[Wall]
|
||||
74[Wall]
|
||||
75[Wall]
|
||||
76[Wall]
|
||||
77[Wall]
|
||||
78[Wall]
|
||||
79[Wall]
|
||||
80[Wall]
|
||||
81[Wall]
|
||||
82[Wall]
|
||||
83[Wall]
|
||||
84[Wall]
|
||||
85[Wall]
|
||||
86[Wall]
|
||||
87[Wall]
|
||||
88[Wall]
|
||||
89[Wall]
|
||||
90[Wall]
|
||||
91[Wall]
|
||||
92[Wall]
|
||||
93[Wall]
|
||||
94[Wall]
|
||||
95[Wall]
|
||||
96[Wall]
|
||||
97[Wall]
|
||||
98[Wall]
|
||||
99[Wall]
|
||||
100[Wall]
|
||||
101[Wall]
|
||||
102[Wall]
|
||||
103[Wall]
|
||||
104[Wall]
|
||||
105[Wall]
|
||||
106[Wall]
|
||||
107[Wall]
|
||||
108[Wall]
|
||||
109[Wall]
|
||||
110[Wall]
|
||||
111[Wall]
|
||||
112[Wall]
|
||||
113[Wall]
|
||||
114[Wall]
|
||||
115[Wall]
|
||||
116[Wall]
|
||||
117[Wall]
|
||||
118[Wall]
|
||||
119[Wall]
|
||||
120[Wall]
|
||||
121[Wall]
|
||||
122[Wall]
|
||||
123[Wall]
|
||||
124[Wall]
|
||||
125[Wall]
|
||||
126[Wall]
|
||||
127[Wall]
|
||||
128[Wall]
|
||||
129[Wall]
|
||||
130[Wall]
|
||||
131[Wall]
|
||||
132[Wall]
|
||||
133[Wall]
|
||||
134[Wall]
|
||||
135[Wall]
|
||||
136[Wall]
|
||||
137["Cap Start"]
|
||||
138["Cap End"]
|
||||
139["SweepEdge Opposite"]
|
||||
140["SweepEdge Adjacent"]
|
||||
141["SweepEdge Opposite"]
|
||||
142["SweepEdge Adjacent"]
|
||||
143["SweepEdge Opposite"]
|
||||
144["SweepEdge Adjacent"]
|
||||
145["SweepEdge Opposite"]
|
||||
146["SweepEdge Adjacent"]
|
||||
147["SweepEdge Opposite"]
|
||||
148["SweepEdge Adjacent"]
|
||||
149["SweepEdge Opposite"]
|
||||
150["SweepEdge Adjacent"]
|
||||
151["SweepEdge Opposite"]
|
||||
152["SweepEdge Adjacent"]
|
||||
153["SweepEdge Opposite"]
|
||||
154["SweepEdge Adjacent"]
|
||||
155["SweepEdge Opposite"]
|
||||
156["SweepEdge Adjacent"]
|
||||
157["SweepEdge Opposite"]
|
||||
158["SweepEdge Adjacent"]
|
||||
159["SweepEdge Opposite"]
|
||||
160["SweepEdge Adjacent"]
|
||||
161["SweepEdge Opposite"]
|
||||
162["SweepEdge Adjacent"]
|
||||
163["SweepEdge Opposite"]
|
||||
164["SweepEdge Adjacent"]
|
||||
165["SweepEdge Opposite"]
|
||||
166["SweepEdge Adjacent"]
|
||||
167["SweepEdge Opposite"]
|
||||
168["SweepEdge Adjacent"]
|
||||
169["SweepEdge Opposite"]
|
||||
170["SweepEdge Adjacent"]
|
||||
171["SweepEdge Opposite"]
|
||||
172["SweepEdge Adjacent"]
|
||||
173["SweepEdge Opposite"]
|
||||
174["SweepEdge Adjacent"]
|
||||
175["SweepEdge Opposite"]
|
||||
176["SweepEdge Adjacent"]
|
||||
177["SweepEdge Opposite"]
|
||||
178["SweepEdge Adjacent"]
|
||||
179["SweepEdge Opposite"]
|
||||
180["SweepEdge Adjacent"]
|
||||
181["SweepEdge Opposite"]
|
||||
182["SweepEdge Adjacent"]
|
||||
183["SweepEdge Opposite"]
|
||||
184["SweepEdge Adjacent"]
|
||||
185["SweepEdge Opposite"]
|
||||
186["SweepEdge Adjacent"]
|
||||
187["SweepEdge Opposite"]
|
||||
188["SweepEdge Adjacent"]
|
||||
189["SweepEdge Opposite"]
|
||||
190["SweepEdge Adjacent"]
|
||||
191["SweepEdge Opposite"]
|
||||
192["SweepEdge Adjacent"]
|
||||
193["SweepEdge Opposite"]
|
||||
194["SweepEdge Adjacent"]
|
||||
195["SweepEdge Opposite"]
|
||||
196["SweepEdge Adjacent"]
|
||||
197["SweepEdge Opposite"]
|
||||
198["SweepEdge Adjacent"]
|
||||
199["SweepEdge Opposite"]
|
||||
200["SweepEdge Adjacent"]
|
||||
201["SweepEdge Opposite"]
|
||||
202["SweepEdge Adjacent"]
|
||||
203["SweepEdge Opposite"]
|
||||
204["SweepEdge Adjacent"]
|
||||
205["SweepEdge Opposite"]
|
||||
206["SweepEdge Adjacent"]
|
||||
207["SweepEdge Opposite"]
|
||||
208["SweepEdge Adjacent"]
|
||||
209["SweepEdge Opposite"]
|
||||
210["SweepEdge Adjacent"]
|
||||
211["SweepEdge Opposite"]
|
||||
212["SweepEdge Adjacent"]
|
||||
213["SweepEdge Opposite"]
|
||||
214["SweepEdge Adjacent"]
|
||||
215["SweepEdge Opposite"]
|
||||
216["SweepEdge Adjacent"]
|
||||
217["SweepEdge Opposite"]
|
||||
218["SweepEdge Adjacent"]
|
||||
219["SweepEdge Opposite"]
|
||||
220["SweepEdge Adjacent"]
|
||||
221["SweepEdge Opposite"]
|
||||
222["SweepEdge Adjacent"]
|
||||
223["SweepEdge Opposite"]
|
||||
224["SweepEdge Adjacent"]
|
||||
225["SweepEdge Opposite"]
|
||||
226["SweepEdge Adjacent"]
|
||||
227["SweepEdge Opposite"]
|
||||
228["SweepEdge Adjacent"]
|
||||
229["SweepEdge Opposite"]
|
||||
230["SweepEdge Adjacent"]
|
||||
231["SweepEdge Opposite"]
|
||||
232["SweepEdge Adjacent"]
|
||||
233["SweepEdge Opposite"]
|
||||
234["SweepEdge Adjacent"]
|
||||
235["SweepEdge Opposite"]
|
||||
236["SweepEdge Adjacent"]
|
||||
237["SweepEdge Opposite"]
|
||||
238["SweepEdge Adjacent"]
|
||||
239["SweepEdge Opposite"]
|
||||
240["SweepEdge Adjacent"]
|
||||
241["SweepEdge Opposite"]
|
||||
242["SweepEdge Adjacent"]
|
||||
243["SweepEdge Opposite"]
|
||||
244["SweepEdge Adjacent"]
|
||||
245["SweepEdge Opposite"]
|
||||
246["SweepEdge Adjacent"]
|
||||
247["SweepEdge Opposite"]
|
||||
248["SweepEdge Adjacent"]
|
||||
249["SweepEdge Opposite"]
|
||||
250["SweepEdge Adjacent"]
|
||||
251["SweepEdge Opposite"]
|
||||
252["SweepEdge Adjacent"]
|
||||
253["SweepEdge Opposite"]
|
||||
254["SweepEdge Adjacent"]
|
||||
255["SweepEdge Opposite"]
|
||||
256["SweepEdge Adjacent"]
|
||||
257["SweepEdge Opposite"]
|
||||
258["SweepEdge Adjacent"]
|
||||
259["SweepEdge Opposite"]
|
||||
260["SweepEdge Adjacent"]
|
||||
261["SweepEdge Opposite"]
|
||||
262["SweepEdge Adjacent"]
|
||||
263["SweepEdge Opposite"]
|
||||
264["SweepEdge Adjacent"]
|
||||
265["SweepEdge Opposite"]
|
||||
266["SweepEdge Adjacent"]
|
||||
267["EdgeCut Fillet<br>[5682, 6386, 0]"]
|
||||
268["EdgeCut Fillet<br>[5682, 6386, 0]"]
|
||||
269["EdgeCut Fillet<br>[5682, 6386, 0]"]
|
||||
270["EdgeCut Fillet<br>[5682, 6386, 0]"]
|
||||
271["EdgeCut Fillet<br>[5682, 6386, 0]"]
|
||||
272["EdgeCut Fillet<br>[5682, 6386, 0]"]
|
||||
273["EdgeCut Fillet<br>[5682, 6386, 0]"]
|
||||
274["EdgeCut Fillet<br>[5682, 6386, 0]"]
|
||||
275["EdgeCut Fillet<br>[5682, 6386, 0]"]
|
||||
276["EdgeCut Fillet<br>[5682, 6386, 0]"]
|
||||
277["EdgeCut Fillet<br>[5682, 6386, 0]"]
|
||||
278["EdgeCut Fillet<br>[5682, 6386, 0]"]
|
||||
279["EdgeCut Fillet<br>[5682, 6386, 0]"]
|
||||
280["EdgeCut Fillet<br>[5682, 6386, 0]"]
|
||||
281["EdgeCut Fillet<br>[5682, 6386, 0]"]
|
||||
282["EdgeCut Fillet<br>[5682, 6386, 0]"]
|
||||
283["EdgeCut Fillet<br>[6394, 7097, 0]"]
|
||||
284["EdgeCut Fillet<br>[6394, 7097, 0]"]
|
||||
285["EdgeCut Fillet<br>[6394, 7097, 0]"]
|
||||
286["EdgeCut Fillet<br>[6394, 7097, 0]"]
|
||||
287["EdgeCut Fillet<br>[6394, 7097, 0]"]
|
||||
288["EdgeCut Fillet<br>[6394, 7097, 0]"]
|
||||
289["EdgeCut Fillet<br>[6394, 7097, 0]"]
|
||||
290["EdgeCut Fillet<br>[6394, 7097, 0]"]
|
||||
291["EdgeCut Fillet<br>[6394, 7097, 0]"]
|
||||
292["EdgeCut Fillet<br>[6394, 7097, 0]"]
|
||||
293["EdgeCut Fillet<br>[6394, 7097, 0]"]
|
||||
294["EdgeCut Fillet<br>[6394, 7097, 0]"]
|
||||
295["EdgeCut Fillet<br>[6394, 7097, 0]"]
|
||||
296["EdgeCut Fillet<br>[6394, 7097, 0]"]
|
||||
297["EdgeCut Fillet<br>[6394, 7097, 0]"]
|
||||
298["EdgeCut Fillet<br>[6394, 7097, 0]"]
|
||||
1 --- 2
|
||||
1 --- 69
|
||||
2 --- 3
|
||||
2 --- 4
|
||||
2 --- 5
|
||||
2 --- 6
|
||||
2 --- 7
|
||||
2 --- 8
|
||||
2 --- 9
|
||||
2 --- 10
|
||||
2 --- 11
|
||||
2 --- 12
|
||||
2 --- 13
|
||||
2 --- 14
|
||||
2 --- 15
|
||||
2 --- 16
|
||||
2 --- 17
|
||||
2 --- 18
|
||||
2 --- 19
|
||||
2 --- 20
|
||||
2 --- 21
|
||||
2 --- 22
|
||||
2 --- 23
|
||||
2 --- 24
|
||||
2 --- 25
|
||||
2 --- 26
|
||||
2 --- 27
|
||||
2 --- 28
|
||||
2 --- 29
|
||||
2 --- 30
|
||||
2 --- 31
|
||||
2 --- 32
|
||||
2 --- 33
|
||||
2 --- 34
|
||||
2 --- 35
|
||||
2 --- 36
|
||||
2 --- 37
|
||||
2 --- 38
|
||||
2 --- 39
|
||||
2 --- 40
|
||||
2 --- 41
|
||||
2 --- 42
|
||||
2 --- 43
|
||||
2 --- 44
|
||||
2 --- 45
|
||||
2 --- 46
|
||||
2 --- 47
|
||||
2 --- 48
|
||||
2 --- 49
|
||||
2 --- 50
|
||||
2 --- 51
|
||||
2 --- 52
|
||||
2 --- 53
|
||||
2 --- 54
|
||||
2 --- 55
|
||||
2 --- 56
|
||||
2 --- 57
|
||||
2 --- 58
|
||||
2 --- 59
|
||||
2 --- 60
|
||||
2 --- 61
|
||||
2 --- 62
|
||||
2 --- 63
|
||||
2 --- 64
|
||||
2 --- 65
|
||||
2 --- 66
|
||||
2 --- 67
|
||||
2 ---- 72
|
||||
2 --- 68
|
||||
3 --- 73
|
||||
3 --- 139
|
||||
3 --- 140
|
||||
4 --- 74
|
||||
4 --- 141
|
||||
4 --- 142
|
||||
5 --- 75
|
||||
5 --- 143
|
||||
5 --- 144
|
||||
6 --- 76
|
||||
6 --- 145
|
||||
6 --- 146
|
||||
7 --- 77
|
||||
7 --- 147
|
||||
7 --- 148
|
||||
8 --- 78
|
||||
8 --- 149
|
||||
8 --- 150
|
||||
9 --- 79
|
||||
9 --- 151
|
||||
9 --- 152
|
||||
10 --- 80
|
||||
10 --- 153
|
||||
10 --- 154
|
||||
11 --- 81
|
||||
11 --- 155
|
||||
11 --- 156
|
||||
12 --- 82
|
||||
12 --- 157
|
||||
12 --- 158
|
||||
13 --- 83
|
||||
13 --- 159
|
||||
13 --- 160
|
||||
14 --- 84
|
||||
14 --- 161
|
||||
14 --- 162
|
||||
15 --- 85
|
||||
15 --- 163
|
||||
15 --- 164
|
||||
16 --- 86
|
||||
16 --- 165
|
||||
16 --- 166
|
||||
17 --- 87
|
||||
17 --- 167
|
||||
17 --- 168
|
||||
18 --- 88
|
||||
18 --- 169
|
||||
18 --- 170
|
||||
19 --- 89
|
||||
19 --- 171
|
||||
19 --- 172
|
||||
20 --- 90
|
||||
20 --- 173
|
||||
20 --- 174
|
||||
21 --- 91
|
||||
21 --- 175
|
||||
21 --- 176
|
||||
22 --- 92
|
||||
22 --- 177
|
||||
22 --- 178
|
||||
23 --- 93
|
||||
23 --- 179
|
||||
23 --- 180
|
||||
24 --- 94
|
||||
24 --- 181
|
||||
24 --- 182
|
||||
25 --- 95
|
||||
25 --- 183
|
||||
25 --- 184
|
||||
26 --- 96
|
||||
26 --- 185
|
||||
26 --- 186
|
||||
27 --- 97
|
||||
27 --- 187
|
||||
27 --- 188
|
||||
28 --- 98
|
||||
28 --- 189
|
||||
28 --- 190
|
||||
29 --- 99
|
||||
29 --- 191
|
||||
29 --- 192
|
||||
30 --- 100
|
||||
30 --- 193
|
||||
30 --- 194
|
||||
31 --- 101
|
||||
31 --- 195
|
||||
31 --- 196
|
||||
32 --- 102
|
||||
32 --- 197
|
||||
32 --- 198
|
||||
33 --- 103
|
||||
33 --- 199
|
||||
33 --- 200
|
||||
34 --- 104
|
||||
34 --- 201
|
||||
34 --- 202
|
||||
35 --- 105
|
||||
35 --- 203
|
||||
35 --- 204
|
||||
36 --- 106
|
||||
36 --- 205
|
||||
36 --- 206
|
||||
37 --- 107
|
||||
37 --- 207
|
||||
37 --- 208
|
||||
38 --- 108
|
||||
38 --- 209
|
||||
38 --- 210
|
||||
39 --- 109
|
||||
39 --- 211
|
||||
39 --- 212
|
||||
40 --- 110
|
||||
40 --- 213
|
||||
40 --- 214
|
||||
41 --- 111
|
||||
41 --- 215
|
||||
41 --- 216
|
||||
42 --- 112
|
||||
42 --- 217
|
||||
42 --- 218
|
||||
43 --- 113
|
||||
43 --- 219
|
||||
43 --- 220
|
||||
44 --- 114
|
||||
44 --- 221
|
||||
44 --- 222
|
||||
45 --- 115
|
||||
45 --- 223
|
||||
45 --- 224
|
||||
46 --- 116
|
||||
46 --- 225
|
||||
46 --- 226
|
||||
47 --- 117
|
||||
47 --- 227
|
||||
47 --- 228
|
||||
48 --- 118
|
||||
48 --- 229
|
||||
48 --- 230
|
||||
49 --- 119
|
||||
49 --- 231
|
||||
49 --- 232
|
||||
50 --- 120
|
||||
50 --- 233
|
||||
50 --- 234
|
||||
51 --- 121
|
||||
51 --- 235
|
||||
51 --- 236
|
||||
52 --- 122
|
||||
52 --- 237
|
||||
52 --- 238
|
||||
53 --- 123
|
||||
53 --- 239
|
||||
53 --- 240
|
||||
54 --- 124
|
||||
54 --- 241
|
||||
54 --- 242
|
||||
55 --- 125
|
||||
55 --- 243
|
||||
55 --- 244
|
||||
56 --- 126
|
||||
56 --- 245
|
||||
56 --- 246
|
||||
57 --- 127
|
||||
57 --- 247
|
||||
57 --- 248
|
||||
58 --- 128
|
||||
58 --- 249
|
||||
58 --- 250
|
||||
59 --- 129
|
||||
59 --- 251
|
||||
59 --- 252
|
||||
60 --- 130
|
||||
60 --- 253
|
||||
60 --- 254
|
||||
61 --- 131
|
||||
61 --- 255
|
||||
61 --- 256
|
||||
62 --- 132
|
||||
62 --- 257
|
||||
62 --- 258
|
||||
63 --- 133
|
||||
63 --- 259
|
||||
63 --- 260
|
||||
64 --- 134
|
||||
64 --- 261
|
||||
64 --- 262
|
||||
65 --- 135
|
||||
65 --- 263
|
||||
65 --- 264
|
||||
66 --- 136
|
||||
66 --- 265
|
||||
66 --- 266
|
||||
69 --- 70
|
||||
69 --- 71
|
||||
72 --- 73
|
||||
72 --- 74
|
||||
72 --- 75
|
||||
72 --- 76
|
||||
72 --- 77
|
||||
72 --- 78
|
||||
72 --- 79
|
||||
72 --- 80
|
||||
72 --- 81
|
||||
72 --- 82
|
||||
72 --- 83
|
||||
72 --- 84
|
||||
72 --- 85
|
||||
72 --- 86
|
||||
72 --- 87
|
||||
72 --- 88
|
||||
72 --- 89
|
||||
72 --- 90
|
||||
72 --- 91
|
||||
72 --- 92
|
||||
72 --- 93
|
||||
72 --- 94
|
||||
72 --- 95
|
||||
72 --- 96
|
||||
72 --- 97
|
||||
72 --- 98
|
||||
72 --- 99
|
||||
72 --- 100
|
||||
72 --- 101
|
||||
72 --- 102
|
||||
72 --- 103
|
||||
72 --- 104
|
||||
72 --- 105
|
||||
72 --- 106
|
||||
72 --- 107
|
||||
72 --- 108
|
||||
72 --- 109
|
||||
72 --- 110
|
||||
72 --- 111
|
||||
72 --- 112
|
||||
72 --- 113
|
||||
72 --- 114
|
||||
72 --- 115
|
||||
72 --- 116
|
||||
72 --- 117
|
||||
72 --- 118
|
||||
72 --- 119
|
||||
72 --- 120
|
||||
72 --- 121
|
||||
72 --- 122
|
||||
72 --- 123
|
||||
72 --- 124
|
||||
72 --- 125
|
||||
72 --- 126
|
||||
72 --- 127
|
||||
72 --- 128
|
||||
72 --- 129
|
||||
72 --- 130
|
||||
72 --- 131
|
||||
72 --- 132
|
||||
72 --- 133
|
||||
72 --- 134
|
||||
72 --- 135
|
||||
72 --- 136
|
||||
72 --- 137
|
||||
72 --- 138
|
||||
72 --- 139
|
||||
72 --- 140
|
||||
72 --- 141
|
||||
72 --- 142
|
||||
72 --- 143
|
||||
72 --- 144
|
||||
72 --- 145
|
||||
72 --- 146
|
||||
72 --- 147
|
||||
72 --- 148
|
||||
72 --- 149
|
||||
72 --- 150
|
||||
72 --- 151
|
||||
72 --- 152
|
||||
72 --- 153
|
||||
72 --- 154
|
||||
72 --- 155
|
||||
72 --- 156
|
||||
72 --- 157
|
||||
72 --- 158
|
||||
72 --- 159
|
||||
72 --- 160
|
||||
72 --- 161
|
||||
72 --- 162
|
||||
72 --- 163
|
||||
72 --- 164
|
||||
72 --- 165
|
||||
72 --- 166
|
||||
72 --- 167
|
||||
72 --- 168
|
||||
72 --- 169
|
||||
72 --- 170
|
||||
72 --- 171
|
||||
72 --- 172
|
||||
72 --- 173
|
||||
72 --- 174
|
||||
72 --- 175
|
||||
72 --- 176
|
||||
72 --- 177
|
||||
72 --- 178
|
||||
72 --- 179
|
||||
72 --- 180
|
||||
72 --- 181
|
||||
72 --- 182
|
||||
72 --- 183
|
||||
72 --- 184
|
||||
72 --- 185
|
||||
72 --- 186
|
||||
72 --- 187
|
||||
72 --- 188
|
||||
72 --- 189
|
||||
72 --- 190
|
||||
72 --- 191
|
||||
72 --- 192
|
||||
72 --- 193
|
||||
72 --- 194
|
||||
72 --- 195
|
||||
72 --- 196
|
||||
72 --- 197
|
||||
72 --- 198
|
||||
72 --- 199
|
||||
72 --- 200
|
||||
72 --- 201
|
||||
72 --- 202
|
||||
72 --- 203
|
||||
72 --- 204
|
||||
72 --- 205
|
||||
72 --- 206
|
||||
72 --- 207
|
||||
72 --- 208
|
||||
72 --- 209
|
||||
72 --- 210
|
||||
72 --- 211
|
||||
72 --- 212
|
||||
72 --- 213
|
||||
72 --- 214
|
||||
72 --- 215
|
||||
72 --- 216
|
||||
72 --- 217
|
||||
72 --- 218
|
||||
72 --- 219
|
||||
72 --- 220
|
||||
72 --- 221
|
||||
72 --- 222
|
||||
72 --- 223
|
||||
72 --- 224
|
||||
72 --- 225
|
||||
72 --- 226
|
||||
72 --- 227
|
||||
72 --- 228
|
||||
72 --- 229
|
||||
72 --- 230
|
||||
72 --- 231
|
||||
72 --- 232
|
||||
72 --- 233
|
||||
72 --- 234
|
||||
72 --- 235
|
||||
72 --- 236
|
||||
72 --- 237
|
||||
72 --- 238
|
||||
72 --- 239
|
||||
72 --- 240
|
||||
72 --- 241
|
||||
72 --- 242
|
||||
72 --- 243
|
||||
72 --- 244
|
||||
72 --- 245
|
||||
72 --- 246
|
||||
72 --- 247
|
||||
72 --- 248
|
||||
72 --- 249
|
||||
72 --- 250
|
||||
72 --- 251
|
||||
72 --- 252
|
||||
72 --- 253
|
||||
72 --- 254
|
||||
72 --- 255
|
||||
72 --- 256
|
||||
72 --- 257
|
||||
72 --- 258
|
||||
72 --- 259
|
||||
72 --- 260
|
||||
72 --- 261
|
||||
72 --- 262
|
||||
72 --- 263
|
||||
72 --- 264
|
||||
72 --- 265
|
||||
72 --- 266
|
||||
152 <--x 267
|
||||
154 <--x 268
|
||||
156 <--x 269
|
||||
158 <--x 270
|
||||
184 <--x 271
|
||||
186 <--x 272
|
||||
188 <--x 273
|
||||
190 <--x 274
|
||||
216 <--x 275
|
||||
218 <--x 276
|
||||
220 <--x 277
|
||||
222 <--x 278
|
||||
248 <--x 279
|
||||
250 <--x 280
|
||||
252 <--x 281
|
||||
254 <--x 282
|
||||
148 <--x 283
|
||||
150 <--x 284
|
||||
160 <--x 285
|
||||
162 <--x 286
|
||||
180 <--x 287
|
||||
182 <--x 288
|
||||
192 <--x 289
|
||||
194 <--x 290
|
||||
212 <--x 291
|
||||
214 <--x 292
|
||||
224 <--x 293
|
||||
226 <--x 294
|
||||
244 <--x 295
|
||||
246 <--x 296
|
||||
256 <--x 297
|
||||
258 <--x 298
|
||||
```
|
7235
rust/kcl-lib/tests/kcl_samples/80-20-rail/ast.snap
Normal file
7235
rust/kcl-lib/tests/kcl_samples/80-20-rail/ast.snap
Normal file
File diff suppressed because it is too large
Load Diff
370
rust/kcl-lib/tests/kcl_samples/80-20-rail/ops.snap
Normal file
370
rust/kcl-lib/tests/kcl_samples/80-20-rail/ops.snap
Normal file
@ -0,0 +1,370 @@
|
||||
---
|
||||
source: kcl/src/simulation_tests.rs
|
||||
description: Operations executed 80-20-rail.kcl
|
||||
---
|
||||
[
|
||||
{
|
||||
"type": "UserDefinedFunctionCall",
|
||||
"name": "rail8020",
|
||||
"functionSourceRange": [
|
||||
214,
|
||||
7118,
|
||||
0
|
||||
],
|
||||
"unlabeledArg": null,
|
||||
"labeledArgs": {},
|
||||
"sourceRange": [
|
||||
7161,
|
||||
7186,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"labeledArgs": {
|
||||
"data": {
|
||||
"value": {
|
||||
"type": "String",
|
||||
"value": "-XZ"
|
||||
},
|
||||
"sourceRange": [
|
||||
312,
|
||||
317,
|
||||
0
|
||||
]
|
||||
}
|
||||
},
|
||||
"name": "startSketchOn",
|
||||
"sourceRange": [
|
||||
298,
|
||||
318,
|
||||
0
|
||||
],
|
||||
"type": "StdLibCall",
|
||||
"unlabeledArg": null
|
||||
},
|
||||
{
|
||||
"labeledArgs": {
|
||||
"holeSketch": {
|
||||
"value": {
|
||||
"type": "Sketch",
|
||||
"value": {
|
||||
"artifactId": "[uuid]"
|
||||
}
|
||||
},
|
||||
"sourceRange": [
|
||||
5457,
|
||||
5634,
|
||||
0
|
||||
]
|
||||
},
|
||||
"sketch": {
|
||||
"value": {
|
||||
"type": "Sketch",
|
||||
"value": {
|
||||
"artifactId": "[uuid]"
|
||||
}
|
||||
},
|
||||
"sourceRange": [
|
||||
5636,
|
||||
5637,
|
||||
0
|
||||
]
|
||||
}
|
||||
},
|
||||
"name": "hole",
|
||||
"sourceRange": [
|
||||
5452,
|
||||
5638,
|
||||
0
|
||||
],
|
||||
"type": "StdLibCall",
|
||||
"unlabeledArg": null
|
||||
},
|
||||
{
|
||||
"labeledArgs": {
|
||||
"length": {
|
||||
"value": {
|
||||
"type": "Number",
|
||||
"value": 48.0,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Inches"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sourceRange": [
|
||||
5663,
|
||||
5673,
|
||||
0
|
||||
]
|
||||
}
|
||||
},
|
||||
"name": "extrude",
|
||||
"sourceRange": [
|
||||
5646,
|
||||
5674,
|
||||
0
|
||||
],
|
||||
"type": "StdLibCall",
|
||||
"unlabeledArg": {
|
||||
"value": {
|
||||
"type": "Sketch",
|
||||
"value": {
|
||||
"artifactId": "[uuid]"
|
||||
}
|
||||
},
|
||||
"sourceRange": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"labeledArgs": {
|
||||
"radius": {
|
||||
"value": {
|
||||
"type": "Number",
|
||||
"value": 0.06,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Inches"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sourceRange": [
|
||||
5708,
|
||||
5712,
|
||||
0
|
||||
]
|
||||
},
|
||||
"tags": {
|
||||
"value": {
|
||||
"type": "Array",
|
||||
"value": [
|
||||
{
|
||||
"type": "Uuid",
|
||||
"value": "[uuid]"
|
||||
},
|
||||
{
|
||||
"type": "Uuid",
|
||||
"value": "[uuid]"
|
||||
},
|
||||
{
|
||||
"type": "Uuid",
|
||||
"value": "[uuid]"
|
||||
},
|
||||
{
|
||||
"type": "Uuid",
|
||||
"value": "[uuid]"
|
||||
},
|
||||
{
|
||||
"type": "Uuid",
|
||||
"value": "[uuid]"
|
||||
},
|
||||
{
|
||||
"type": "Uuid",
|
||||
"value": "[uuid]"
|
||||
},
|
||||
{
|
||||
"type": "Uuid",
|
||||
"value": "[uuid]"
|
||||
},
|
||||
{
|
||||
"type": "Uuid",
|
||||
"value": "[uuid]"
|
||||
},
|
||||
{
|
||||
"type": "Uuid",
|
||||
"value": "[uuid]"
|
||||
},
|
||||
{
|
||||
"type": "Uuid",
|
||||
"value": "[uuid]"
|
||||
},
|
||||
{
|
||||
"type": "Uuid",
|
||||
"value": "[uuid]"
|
||||
},
|
||||
{
|
||||
"type": "Uuid",
|
||||
"value": "[uuid]"
|
||||
},
|
||||
{
|
||||
"type": "Uuid",
|
||||
"value": "[uuid]"
|
||||
},
|
||||
{
|
||||
"type": "Uuid",
|
||||
"value": "[uuid]"
|
||||
},
|
||||
{
|
||||
"type": "Uuid",
|
||||
"value": "[uuid]"
|
||||
},
|
||||
{
|
||||
"type": "Uuid",
|
||||
"value": "[uuid]"
|
||||
}
|
||||
]
|
||||
},
|
||||
"sourceRange": [
|
||||
5730,
|
||||
6377,
|
||||
0
|
||||
]
|
||||
}
|
||||
},
|
||||
"name": "fillet",
|
||||
"sourceRange": [
|
||||
5682,
|
||||
6386,
|
||||
0
|
||||
],
|
||||
"type": "StdLibCall",
|
||||
"unlabeledArg": {
|
||||
"value": {
|
||||
"type": "Solid",
|
||||
"value": {
|
||||
"artifactId": "[uuid]"
|
||||
}
|
||||
},
|
||||
"sourceRange": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"labeledArgs": {
|
||||
"radius": {
|
||||
"value": {
|
||||
"type": "Number",
|
||||
"value": 0.03,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Inches"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sourceRange": [
|
||||
6420,
|
||||
6424,
|
||||
0
|
||||
]
|
||||
},
|
||||
"tags": {
|
||||
"value": {
|
||||
"type": "Array",
|
||||
"value": [
|
||||
{
|
||||
"type": "Uuid",
|
||||
"value": "[uuid]"
|
||||
},
|
||||
{
|
||||
"type": "Uuid",
|
||||
"value": "[uuid]"
|
||||
},
|
||||
{
|
||||
"type": "Uuid",
|
||||
"value": "[uuid]"
|
||||
},
|
||||
{
|
||||
"type": "Uuid",
|
||||
"value": "[uuid]"
|
||||
},
|
||||
{
|
||||
"type": "Uuid",
|
||||
"value": "[uuid]"
|
||||
},
|
||||
{
|
||||
"type": "Uuid",
|
||||
"value": "[uuid]"
|
||||
},
|
||||
{
|
||||
"type": "Uuid",
|
||||
"value": "[uuid]"
|
||||
},
|
||||
{
|
||||
"type": "Uuid",
|
||||
"value": "[uuid]"
|
||||
},
|
||||
{
|
||||
"type": "Uuid",
|
||||
"value": "[uuid]"
|
||||
},
|
||||
{
|
||||
"type": "Uuid",
|
||||
"value": "[uuid]"
|
||||
},
|
||||
{
|
||||
"type": "Uuid",
|
||||
"value": "[uuid]"
|
||||
},
|
||||
{
|
||||
"type": "Uuid",
|
||||
"value": "[uuid]"
|
||||
},
|
||||
{
|
||||
"type": "Uuid",
|
||||
"value": "[uuid]"
|
||||
},
|
||||
{
|
||||
"type": "Uuid",
|
||||
"value": "[uuid]"
|
||||
},
|
||||
{
|
||||
"type": "Uuid",
|
||||
"value": "[uuid]"
|
||||
},
|
||||
{
|
||||
"type": "Uuid",
|
||||
"value": "[uuid]"
|
||||
}
|
||||
]
|
||||
},
|
||||
"sourceRange": [
|
||||
6442,
|
||||
7088,
|
||||
0
|
||||
]
|
||||
}
|
||||
},
|
||||
"name": "fillet",
|
||||
"sourceRange": [
|
||||
6394,
|
||||
7097,
|
||||
0
|
||||
],
|
||||
"type": "StdLibCall",
|
||||
"unlabeledArg": {
|
||||
"value": {
|
||||
"type": "Solid",
|
||||
"value": {
|
||||
"artifactId": "[uuid]"
|
||||
}
|
||||
},
|
||||
"sourceRange": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "UserDefinedFunctionReturn"
|
||||
}
|
||||
]
|
@ -0,0 +1,18 @@
|
||||
---
|
||||
source: kcl/src/simulation_tests.rs
|
||||
description: Variables in memory after executing 80-20-rail.kcl
|
||||
---
|
||||
{
|
||||
"rail8020": {
|
||||
"type": "Function",
|
||||
"__meta": [
|
||||
{
|
||||
"sourceRange": [
|
||||
214,
|
||||
7118,
|
||||
0
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
BIN
rust/kcl-lib/tests/kcl_samples/80-20-rail/rendered_model.png
Normal file
BIN
rust/kcl-lib/tests/kcl_samples/80-20-rail/rendered_model.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,6 @@
|
||||
---
|
||||
source: kcl/src/simulation_tests.rs
|
||||
description: Artifact graph flowchart a-parametric-bearing-pillow-block.kcl
|
||||
extension: md
|
||||
snapshot_kind: binary
|
||||
---
|
@ -0,0 +1,197 @@
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph path2 [Path]
|
||||
2["Path<br>[966, 1010, 0]"]
|
||||
3["Segment<br>[1016, 1060, 0]"]
|
||||
4["Segment<br>[1066, 1109, 0]"]
|
||||
5["Segment<br>[1115, 1159, 0]"]
|
||||
6["Segment<br>[1165, 1172, 0]"]
|
||||
7[Solid2d]
|
||||
end
|
||||
subgraph path8 [Path]
|
||||
8["Path<br>[1183, 1331, 0]"]
|
||||
9["Segment<br>[1183, 1331, 0]"]
|
||||
10[Solid2d]
|
||||
end
|
||||
subgraph path11 [Path]
|
||||
11["Path<br>[1346, 1491, 0]"]
|
||||
12["Segment<br>[1346, 1491, 0]"]
|
||||
13[Solid2d]
|
||||
end
|
||||
subgraph path14 [Path]
|
||||
14["Path<br>[1506, 1648, 0]"]
|
||||
15["Segment<br>[1506, 1648, 0]"]
|
||||
16[Solid2d]
|
||||
end
|
||||
subgraph path17 [Path]
|
||||
17["Path<br>[1663, 1808, 0]"]
|
||||
18["Segment<br>[1663, 1808, 0]"]
|
||||
19[Solid2d]
|
||||
end
|
||||
subgraph path20 [Path]
|
||||
20["Path<br>[1823, 1892, 0]"]
|
||||
21["Segment<br>[1823, 1892, 0]"]
|
||||
22[Solid2d]
|
||||
end
|
||||
subgraph path39 [Path]
|
||||
39["Path<br>[2455, 2499, 0]"]
|
||||
40["Segment<br>[2505, 2549, 0]"]
|
||||
41["Segment<br>[2555, 2598, 0]"]
|
||||
42["Segment<br>[2604, 2648, 0]"]
|
||||
43["Segment<br>[2654, 2661, 0]"]
|
||||
44[Solid2d]
|
||||
end
|
||||
subgraph path45 [Path]
|
||||
45["Path<br>[2672, 2818, 0]"]
|
||||
46["Segment<br>[2672, 2818, 0]"]
|
||||
47[Solid2d]
|
||||
end
|
||||
subgraph path48 [Path]
|
||||
48["Path<br>[2833, 2976, 0]"]
|
||||
49["Segment<br>[2833, 2976, 0]"]
|
||||
50[Solid2d]
|
||||
end
|
||||
subgraph path51 [Path]
|
||||
51["Path<br>[2991, 3131, 0]"]
|
||||
52["Segment<br>[2991, 3131, 0]"]
|
||||
53[Solid2d]
|
||||
end
|
||||
subgraph path54 [Path]
|
||||
54["Path<br>[3146, 3289, 0]"]
|
||||
55["Segment<br>[3146, 3289, 0]"]
|
||||
56[Solid2d]
|
||||
end
|
||||
subgraph path57 [Path]
|
||||
57["Path<br>[3304, 3373, 0]"]
|
||||
58["Segment<br>[3304, 3373, 0]"]
|
||||
59[Solid2d]
|
||||
end
|
||||
1["Plane<br>[941, 960, 0]"]
|
||||
23["Sweep Extrusion<br>[1902, 1936, 0]"]
|
||||
24[Wall]
|
||||
25[Wall]
|
||||
26[Wall]
|
||||
27[Wall]
|
||||
28["Cap Start"]
|
||||
29["Cap End"]
|
||||
30["SweepEdge Opposite"]
|
||||
31["SweepEdge Adjacent"]
|
||||
32["SweepEdge Opposite"]
|
||||
33["SweepEdge Adjacent"]
|
||||
34["SweepEdge Opposite"]
|
||||
35["SweepEdge Adjacent"]
|
||||
36["SweepEdge Opposite"]
|
||||
37["SweepEdge Adjacent"]
|
||||
38["Plane<br>[2217, 2449, 0]"]
|
||||
60["Sweep Extrusion<br>[3383, 3408, 0]"]
|
||||
61[Wall]
|
||||
62[Wall]
|
||||
63[Wall]
|
||||
64[Wall]
|
||||
65["Cap Start"]
|
||||
66["Cap End"]
|
||||
67["SweepEdge Opposite"]
|
||||
68["SweepEdge Adjacent"]
|
||||
69["SweepEdge Opposite"]
|
||||
70["SweepEdge Adjacent"]
|
||||
71["SweepEdge Opposite"]
|
||||
72["SweepEdge Adjacent"]
|
||||
73["SweepEdge Opposite"]
|
||||
74["SweepEdge Adjacent"]
|
||||
1 --- 2
|
||||
1 --- 8
|
||||
1 --- 11
|
||||
1 --- 14
|
||||
1 --- 17
|
||||
1 --- 20
|
||||
2 --- 3
|
||||
2 --- 4
|
||||
2 --- 5
|
||||
2 --- 6
|
||||
2 ---- 23
|
||||
2 --- 7
|
||||
3 --- 24
|
||||
3 --- 30
|
||||
3 --- 31
|
||||
4 --- 25
|
||||
4 --- 32
|
||||
4 --- 33
|
||||
5 --- 26
|
||||
5 --- 34
|
||||
5 --- 35
|
||||
6 --- 27
|
||||
6 --- 36
|
||||
6 --- 37
|
||||
8 --- 9
|
||||
8 --- 10
|
||||
11 --- 12
|
||||
11 --- 13
|
||||
14 --- 15
|
||||
14 --- 16
|
||||
17 --- 18
|
||||
17 --- 19
|
||||
20 --- 21
|
||||
20 --- 22
|
||||
23 --- 24
|
||||
23 --- 25
|
||||
23 --- 26
|
||||
23 --- 27
|
||||
23 --- 28
|
||||
23 --- 29
|
||||
23 --- 30
|
||||
23 --- 31
|
||||
23 --- 32
|
||||
23 --- 33
|
||||
23 --- 34
|
||||
23 --- 35
|
||||
23 --- 36
|
||||
23 --- 37
|
||||
38 --- 39
|
||||
38 --- 45
|
||||
38 --- 48
|
||||
38 --- 51
|
||||
38 --- 54
|
||||
38 --- 57
|
||||
39 --- 40
|
||||
39 --- 41
|
||||
39 --- 42
|
||||
39 --- 43
|
||||
39 ---- 60
|
||||
39 --- 44
|
||||
40 --- 61
|
||||
40 --- 67
|
||||
40 --- 68
|
||||
41 --- 62
|
||||
41 --- 69
|
||||
41 --- 70
|
||||
42 --- 63
|
||||
42 --- 71
|
||||
42 --- 72
|
||||
43 --- 64
|
||||
43 --- 73
|
||||
43 --- 74
|
||||
45 --- 46
|
||||
45 --- 47
|
||||
48 --- 49
|
||||
48 --- 50
|
||||
51 --- 52
|
||||
51 --- 53
|
||||
54 --- 55
|
||||
54 --- 56
|
||||
57 --- 58
|
||||
57 --- 59
|
||||
60 --- 61
|
||||
60 --- 62
|
||||
60 --- 63
|
||||
60 --- 64
|
||||
60 --- 65
|
||||
60 --- 66
|
||||
60 --- 67
|
||||
60 --- 68
|
||||
60 --- 69
|
||||
60 --- 70
|
||||
60 --- 71
|
||||
60 --- 72
|
||||
60 --- 73
|
||||
60 --- 74
|
||||
```
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,702 @@
|
||||
---
|
||||
source: kcl/src/simulation_tests.rs
|
||||
description: Operations executed a-parametric-bearing-pillow-block.kcl
|
||||
---
|
||||
[
|
||||
{
|
||||
"labeledArgs": {
|
||||
"data": {
|
||||
"value": {
|
||||
"type": "String",
|
||||
"value": "XY"
|
||||
},
|
||||
"sourceRange": [
|
||||
955,
|
||||
959,
|
||||
0
|
||||
]
|
||||
}
|
||||
},
|
||||
"name": "startSketchOn",
|
||||
"sourceRange": [
|
||||
941,
|
||||
960,
|
||||
0
|
||||
],
|
||||
"type": "StdLibCall",
|
||||
"unlabeledArg": null
|
||||
},
|
||||
{
|
||||
"labeledArgs": {
|
||||
"holeSketch": {
|
||||
"value": {
|
||||
"type": "Sketch",
|
||||
"value": {
|
||||
"artifactId": "[uuid]"
|
||||
}
|
||||
},
|
||||
"sourceRange": [
|
||||
1183,
|
||||
1331,
|
||||
0
|
||||
]
|
||||
},
|
||||
"sketch": {
|
||||
"value": {
|
||||
"type": "Sketch",
|
||||
"value": {
|
||||
"artifactId": "[uuid]"
|
||||
}
|
||||
},
|
||||
"sourceRange": [
|
||||
1333,
|
||||
1334,
|
||||
0
|
||||
]
|
||||
}
|
||||
},
|
||||
"name": "hole",
|
||||
"sourceRange": [
|
||||
1178,
|
||||
1335,
|
||||
0
|
||||
],
|
||||
"type": "StdLibCall",
|
||||
"unlabeledArg": null
|
||||
},
|
||||
{
|
||||
"labeledArgs": {
|
||||
"holeSketch": {
|
||||
"value": {
|
||||
"type": "Sketch",
|
||||
"value": {
|
||||
"artifactId": "[uuid]"
|
||||
}
|
||||
},
|
||||
"sourceRange": [
|
||||
1346,
|
||||
1491,
|
||||
0
|
||||
]
|
||||
},
|
||||
"sketch": {
|
||||
"value": {
|
||||
"type": "Sketch",
|
||||
"value": {
|
||||
"artifactId": "[uuid]"
|
||||
}
|
||||
},
|
||||
"sourceRange": [
|
||||
1493,
|
||||
1494,
|
||||
0
|
||||
]
|
||||
}
|
||||
},
|
||||
"name": "hole",
|
||||
"sourceRange": [
|
||||
1341,
|
||||
1495,
|
||||
0
|
||||
],
|
||||
"type": "StdLibCall",
|
||||
"unlabeledArg": null
|
||||
},
|
||||
{
|
||||
"labeledArgs": {
|
||||
"holeSketch": {
|
||||
"value": {
|
||||
"type": "Sketch",
|
||||
"value": {
|
||||
"artifactId": "[uuid]"
|
||||
}
|
||||
},
|
||||
"sourceRange": [
|
||||
1506,
|
||||
1648,
|
||||
0
|
||||
]
|
||||
},
|
||||
"sketch": {
|
||||
"value": {
|
||||
"type": "Sketch",
|
||||
"value": {
|
||||
"artifactId": "[uuid]"
|
||||
}
|
||||
},
|
||||
"sourceRange": [
|
||||
1650,
|
||||
1651,
|
||||
0
|
||||
]
|
||||
}
|
||||
},
|
||||
"name": "hole",
|
||||
"sourceRange": [
|
||||
1501,
|
||||
1652,
|
||||
0
|
||||
],
|
||||
"type": "StdLibCall",
|
||||
"unlabeledArg": null
|
||||
},
|
||||
{
|
||||
"labeledArgs": {
|
||||
"holeSketch": {
|
||||
"value": {
|
||||
"type": "Sketch",
|
||||
"value": {
|
||||
"artifactId": "[uuid]"
|
||||
}
|
||||
},
|
||||
"sourceRange": [
|
||||
1663,
|
||||
1808,
|
||||
0
|
||||
]
|
||||
},
|
||||
"sketch": {
|
||||
"value": {
|
||||
"type": "Sketch",
|
||||
"value": {
|
||||
"artifactId": "[uuid]"
|
||||
}
|
||||
},
|
||||
"sourceRange": [
|
||||
1810,
|
||||
1811,
|
||||
0
|
||||
]
|
||||
}
|
||||
},
|
||||
"name": "hole",
|
||||
"sourceRange": [
|
||||
1658,
|
||||
1812,
|
||||
0
|
||||
],
|
||||
"type": "StdLibCall",
|
||||
"unlabeledArg": null
|
||||
},
|
||||
{
|
||||
"labeledArgs": {
|
||||
"holeSketch": {
|
||||
"value": {
|
||||
"type": "Sketch",
|
||||
"value": {
|
||||
"artifactId": "[uuid]"
|
||||
}
|
||||
},
|
||||
"sourceRange": [
|
||||
1823,
|
||||
1892,
|
||||
0
|
||||
]
|
||||
},
|
||||
"sketch": {
|
||||
"value": {
|
||||
"type": "Sketch",
|
||||
"value": {
|
||||
"artifactId": "[uuid]"
|
||||
}
|
||||
},
|
||||
"sourceRange": [
|
||||
1894,
|
||||
1895,
|
||||
0
|
||||
]
|
||||
}
|
||||
},
|
||||
"name": "hole",
|
||||
"sourceRange": [
|
||||
1818,
|
||||
1896,
|
||||
0
|
||||
],
|
||||
"type": "StdLibCall",
|
||||
"unlabeledArg": null
|
||||
},
|
||||
{
|
||||
"labeledArgs": {
|
||||
"length": {
|
||||
"value": {
|
||||
"type": "Number",
|
||||
"value": 0.75,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Inches"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sourceRange": [
|
||||
1919,
|
||||
1935,
|
||||
0
|
||||
]
|
||||
}
|
||||
},
|
||||
"name": "extrude",
|
||||
"sourceRange": [
|
||||
1902,
|
||||
1936,
|
||||
0
|
||||
],
|
||||
"type": "StdLibCall",
|
||||
"unlabeledArg": {
|
||||
"value": {
|
||||
"type": "Sketch",
|
||||
"value": {
|
||||
"artifactId": "[uuid]"
|
||||
}
|
||||
},
|
||||
"sourceRange": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"labeledArgs": {
|
||||
"data": {
|
||||
"value": {
|
||||
"type": "Object",
|
||||
"value": {
|
||||
"plane": {
|
||||
"type": "Object",
|
||||
"value": {
|
||||
"origin": {
|
||||
"type": "Object",
|
||||
"value": {
|
||||
"x": {
|
||||
"type": "Number",
|
||||
"value": 0.0,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Inches"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
}
|
||||
},
|
||||
"y": {
|
||||
"type": "Number",
|
||||
"value": 0.0,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Inches"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
}
|
||||
},
|
||||
"z": {
|
||||
"type": "Number",
|
||||
"value": 0.75,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Inches"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"xAxis": {
|
||||
"type": "Object",
|
||||
"value": {
|
||||
"x": {
|
||||
"type": "Number",
|
||||
"value": 1.0,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Inches"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
}
|
||||
},
|
||||
"y": {
|
||||
"type": "Number",
|
||||
"value": 0.0,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Inches"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
}
|
||||
},
|
||||
"z": {
|
||||
"type": "Number",
|
||||
"value": 0.0,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Inches"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"yAxis": {
|
||||
"type": "Object",
|
||||
"value": {
|
||||
"x": {
|
||||
"type": "Number",
|
||||
"value": 0.0,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Inches"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
}
|
||||
},
|
||||
"y": {
|
||||
"type": "Number",
|
||||
"value": 1.0,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Inches"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
}
|
||||
},
|
||||
"z": {
|
||||
"type": "Number",
|
||||
"value": 0.0,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Inches"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"zAxis": {
|
||||
"type": "Object",
|
||||
"value": {
|
||||
"x": {
|
||||
"type": "Number",
|
||||
"value": 0.0,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Inches"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
}
|
||||
},
|
||||
"y": {
|
||||
"type": "Number",
|
||||
"value": 0.0,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Inches"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
}
|
||||
},
|
||||
"z": {
|
||||
"type": "Number",
|
||||
"value": 1.0,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Inches"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"sourceRange": [
|
||||
2231,
|
||||
2448,
|
||||
0
|
||||
]
|
||||
}
|
||||
},
|
||||
"name": "startSketchOn",
|
||||
"sourceRange": [
|
||||
2217,
|
||||
2449,
|
||||
0
|
||||
],
|
||||
"type": "StdLibCall",
|
||||
"unlabeledArg": null
|
||||
},
|
||||
{
|
||||
"labeledArgs": {
|
||||
"holeSketch": {
|
||||
"value": {
|
||||
"type": "Sketch",
|
||||
"value": {
|
||||
"artifactId": "[uuid]"
|
||||
}
|
||||
},
|
||||
"sourceRange": [
|
||||
2672,
|
||||
2818,
|
||||
0
|
||||
]
|
||||
},
|
||||
"sketch": {
|
||||
"value": {
|
||||
"type": "Sketch",
|
||||
"value": {
|
||||
"artifactId": "[uuid]"
|
||||
}
|
||||
},
|
||||
"sourceRange": [
|
||||
2820,
|
||||
2821,
|
||||
0
|
||||
]
|
||||
}
|
||||
},
|
||||
"name": "hole",
|
||||
"sourceRange": [
|
||||
2667,
|
||||
2822,
|
||||
0
|
||||
],
|
||||
"type": "StdLibCall",
|
||||
"unlabeledArg": null
|
||||
},
|
||||
{
|
||||
"labeledArgs": {
|
||||
"holeSketch": {
|
||||
"value": {
|
||||
"type": "Sketch",
|
||||
"value": {
|
||||
"artifactId": "[uuid]"
|
||||
}
|
||||
},
|
||||
"sourceRange": [
|
||||
2833,
|
||||
2976,
|
||||
0
|
||||
]
|
||||
},
|
||||
"sketch": {
|
||||
"value": {
|
||||
"type": "Sketch",
|
||||
"value": {
|
||||
"artifactId": "[uuid]"
|
||||
}
|
||||
},
|
||||
"sourceRange": [
|
||||
2978,
|
||||
2979,
|
||||
0
|
||||
]
|
||||
}
|
||||
},
|
||||
"name": "hole",
|
||||
"sourceRange": [
|
||||
2828,
|
||||
2980,
|
||||
0
|
||||
],
|
||||
"type": "StdLibCall",
|
||||
"unlabeledArg": null
|
||||
},
|
||||
{
|
||||
"labeledArgs": {
|
||||
"holeSketch": {
|
||||
"value": {
|
||||
"type": "Sketch",
|
||||
"value": {
|
||||
"artifactId": "[uuid]"
|
||||
}
|
||||
},
|
||||
"sourceRange": [
|
||||
2991,
|
||||
3131,
|
||||
0
|
||||
]
|
||||
},
|
||||
"sketch": {
|
||||
"value": {
|
||||
"type": "Sketch",
|
||||
"value": {
|
||||
"artifactId": "[uuid]"
|
||||
}
|
||||
},
|
||||
"sourceRange": [
|
||||
3133,
|
||||
3134,
|
||||
0
|
||||
]
|
||||
}
|
||||
},
|
||||
"name": "hole",
|
||||
"sourceRange": [
|
||||
2986,
|
||||
3135,
|
||||
0
|
||||
],
|
||||
"type": "StdLibCall",
|
||||
"unlabeledArg": null
|
||||
},
|
||||
{
|
||||
"labeledArgs": {
|
||||
"holeSketch": {
|
||||
"value": {
|
||||
"type": "Sketch",
|
||||
"value": {
|
||||
"artifactId": "[uuid]"
|
||||
}
|
||||
},
|
||||
"sourceRange": [
|
||||
3146,
|
||||
3289,
|
||||
0
|
||||
]
|
||||
},
|
||||
"sketch": {
|
||||
"value": {
|
||||
"type": "Sketch",
|
||||
"value": {
|
||||
"artifactId": "[uuid]"
|
||||
}
|
||||
},
|
||||
"sourceRange": [
|
||||
3291,
|
||||
3292,
|
||||
0
|
||||
]
|
||||
}
|
||||
},
|
||||
"name": "hole",
|
||||
"sourceRange": [
|
||||
3141,
|
||||
3293,
|
||||
0
|
||||
],
|
||||
"type": "StdLibCall",
|
||||
"unlabeledArg": null
|
||||
},
|
||||
{
|
||||
"labeledArgs": {
|
||||
"holeSketch": {
|
||||
"value": {
|
||||
"type": "Sketch",
|
||||
"value": {
|
||||
"artifactId": "[uuid]"
|
||||
}
|
||||
},
|
||||
"sourceRange": [
|
||||
3304,
|
||||
3373,
|
||||
0
|
||||
]
|
||||
},
|
||||
"sketch": {
|
||||
"value": {
|
||||
"type": "Sketch",
|
||||
"value": {
|
||||
"artifactId": "[uuid]"
|
||||
}
|
||||
},
|
||||
"sourceRange": [
|
||||
3375,
|
||||
3376,
|
||||
0
|
||||
]
|
||||
}
|
||||
},
|
||||
"name": "hole",
|
||||
"sourceRange": [
|
||||
3299,
|
||||
3377,
|
||||
0
|
||||
],
|
||||
"type": "StdLibCall",
|
||||
"unlabeledArg": null
|
||||
},
|
||||
{
|
||||
"labeledArgs": {
|
||||
"length": {
|
||||
"value": {
|
||||
"type": "Number",
|
||||
"value": 0.25,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Inches"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sourceRange": [
|
||||
3400,
|
||||
3407,
|
||||
0
|
||||
]
|
||||
}
|
||||
},
|
||||
"name": "extrude",
|
||||
"sourceRange": [
|
||||
3383,
|
||||
3408,
|
||||
0
|
||||
],
|
||||
"type": "StdLibCall",
|
||||
"unlabeledArg": {
|
||||
"value": {
|
||||
"type": "Sketch",
|
||||
"value": {
|
||||
"artifactId": "[uuid]"
|
||||
}
|
||||
},
|
||||
"sourceRange": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
@ -0,0 +1,648 @@
|
||||
---
|
||||
source: kcl/src/simulation_tests.rs
|
||||
description: Variables in memory after executing a-parametric-bearing-pillow-block.kcl
|
||||
---
|
||||
{
|
||||
"bearingDia": {
|
||||
"type": "Number",
|
||||
"value": 3.0,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Inches"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
},
|
||||
"__meta": [
|
||||
{
|
||||
"sourceRange": [
|
||||
830,
|
||||
831,
|
||||
0
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"block": {
|
||||
"type": "Solid",
|
||||
"value": {
|
||||
"type": "Solid",
|
||||
"id": "[uuid]",
|
||||
"artifactId": "[uuid]",
|
||||
"value": [
|
||||
{
|
||||
"faceId": "[uuid]",
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
1016,
|
||||
1060,
|
||||
0
|
||||
],
|
||||
"tag": null,
|
||||
"type": "extrudePlane"
|
||||
},
|
||||
{
|
||||
"faceId": "[uuid]",
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
1066,
|
||||
1109,
|
||||
0
|
||||
],
|
||||
"tag": null,
|
||||
"type": "extrudePlane"
|
||||
},
|
||||
{
|
||||
"faceId": "[uuid]",
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
1115,
|
||||
1159,
|
||||
0
|
||||
],
|
||||
"tag": null,
|
||||
"type": "extrudePlane"
|
||||
},
|
||||
{
|
||||
"faceId": "[uuid]",
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
1165,
|
||||
1172,
|
||||
0
|
||||
],
|
||||
"tag": null,
|
||||
"type": "extrudePlane"
|
||||
}
|
||||
],
|
||||
"sketch": {
|
||||
"type": "Sketch",
|
||||
"id": "[uuid]",
|
||||
"paths": [
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
1016,
|
||||
1060,
|
||||
0
|
||||
]
|
||||
},
|
||||
"from": [
|
||||
-2.0,
|
||||
-3.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
2.0,
|
||||
-3.0
|
||||
],
|
||||
"type": "ToPoint",
|
||||
"units": {
|
||||
"type": "Inches"
|
||||
}
|
||||
},
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
1066,
|
||||
1109,
|
||||
0
|
||||
]
|
||||
},
|
||||
"from": [
|
||||
2.0,
|
||||
-3.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
2.0,
|
||||
3.0
|
||||
],
|
||||
"type": "ToPoint",
|
||||
"units": {
|
||||
"type": "Inches"
|
||||
}
|
||||
},
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
1115,
|
||||
1159,
|
||||
0
|
||||
]
|
||||
},
|
||||
"from": [
|
||||
2.0,
|
||||
3.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
-2.0,
|
||||
3.0
|
||||
],
|
||||
"type": "ToPoint",
|
||||
"units": {
|
||||
"type": "Inches"
|
||||
}
|
||||
},
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
1165,
|
||||
1172,
|
||||
0
|
||||
]
|
||||
},
|
||||
"from": [
|
||||
-2.0,
|
||||
3.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
-2.0,
|
||||
-3.0
|
||||
],
|
||||
"type": "ToPoint",
|
||||
"units": {
|
||||
"type": "Inches"
|
||||
}
|
||||
}
|
||||
],
|
||||
"on": {
|
||||
"type": "plane",
|
||||
"id": "[uuid]",
|
||||
"artifactId": "[uuid]",
|
||||
"value": "XY",
|
||||
"origin": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"xAxis": {
|
||||
"x": 1.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"yAxis": {
|
||||
"x": 0.0,
|
||||
"y": 1.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"zAxis": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 1.0
|
||||
},
|
||||
"units": {
|
||||
"type": "Inches"
|
||||
},
|
||||
"__meta": []
|
||||
},
|
||||
"start": {
|
||||
"from": [
|
||||
-2.0,
|
||||
-3.0
|
||||
],
|
||||
"to": [
|
||||
-2.0,
|
||||
-3.0
|
||||
],
|
||||
"units": {
|
||||
"type": "Inches"
|
||||
},
|
||||
"tag": null,
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
966,
|
||||
1010,
|
||||
0
|
||||
]
|
||||
}
|
||||
},
|
||||
"artifactId": "[uuid]",
|
||||
"originalId": "[uuid]",
|
||||
"units": {
|
||||
"type": "Inches"
|
||||
},
|
||||
"__meta": [
|
||||
{
|
||||
"sourceRange": [
|
||||
966,
|
||||
1010,
|
||||
0
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"height": 0.75,
|
||||
"startCapId": "[uuid]",
|
||||
"endCapId": "[uuid]",
|
||||
"units": {
|
||||
"type": "Inches"
|
||||
},
|
||||
"__meta": [
|
||||
{
|
||||
"sourceRange": [
|
||||
966,
|
||||
1010,
|
||||
0
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"cbDepth": {
|
||||
"type": "Number",
|
||||
"value": 0.25,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Inches"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
},
|
||||
"__meta": [
|
||||
{
|
||||
"sourceRange": [
|
||||
773,
|
||||
776,
|
||||
0
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"cbDia": {
|
||||
"type": "Number",
|
||||
"value": 0.7,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Inches"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
},
|
||||
"__meta": [
|
||||
{
|
||||
"sourceRange": [
|
||||
785,
|
||||
787,
|
||||
0
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"height": {
|
||||
"type": "Number",
|
||||
"value": 1.0,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Inches"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
},
|
||||
"__meta": [
|
||||
{
|
||||
"sourceRange": [
|
||||
761,
|
||||
762,
|
||||
0
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"holeDia": {
|
||||
"type": "Number",
|
||||
"value": 0.375,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Inches"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
},
|
||||
"__meta": [
|
||||
{
|
||||
"sourceRange": [
|
||||
798,
|
||||
802,
|
||||
0
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"length": {
|
||||
"type": "Number",
|
||||
"value": 6.0,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Inches"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
},
|
||||
"__meta": [
|
||||
{
|
||||
"sourceRange": [
|
||||
740,
|
||||
741,
|
||||
0
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"padding": {
|
||||
"type": "Number",
|
||||
"value": 1.5,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Inches"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
},
|
||||
"__meta": [
|
||||
{
|
||||
"sourceRange": [
|
||||
813,
|
||||
816,
|
||||
0
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"secondHalf": {
|
||||
"type": "Solid",
|
||||
"value": {
|
||||
"type": "Solid",
|
||||
"id": "[uuid]",
|
||||
"artifactId": "[uuid]",
|
||||
"value": [
|
||||
{
|
||||
"faceId": "[uuid]",
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
2505,
|
||||
2549,
|
||||
0
|
||||
],
|
||||
"tag": null,
|
||||
"type": "extrudePlane"
|
||||
},
|
||||
{
|
||||
"faceId": "[uuid]",
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
2555,
|
||||
2598,
|
||||
0
|
||||
],
|
||||
"tag": null,
|
||||
"type": "extrudePlane"
|
||||
},
|
||||
{
|
||||
"faceId": "[uuid]",
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
2604,
|
||||
2648,
|
||||
0
|
||||
],
|
||||
"tag": null,
|
||||
"type": "extrudePlane"
|
||||
},
|
||||
{
|
||||
"faceId": "[uuid]",
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
2654,
|
||||
2661,
|
||||
0
|
||||
],
|
||||
"tag": null,
|
||||
"type": "extrudePlane"
|
||||
}
|
||||
],
|
||||
"sketch": {
|
||||
"type": "Sketch",
|
||||
"id": "[uuid]",
|
||||
"paths": [
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
2505,
|
||||
2549,
|
||||
0
|
||||
]
|
||||
},
|
||||
"from": [
|
||||
-2.0,
|
||||
-3.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
2.0,
|
||||
-3.0
|
||||
],
|
||||
"type": "ToPoint",
|
||||
"units": {
|
||||
"type": "Inches"
|
||||
}
|
||||
},
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
2555,
|
||||
2598,
|
||||
0
|
||||
]
|
||||
},
|
||||
"from": [
|
||||
2.0,
|
||||
-3.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
2.0,
|
||||
3.0
|
||||
],
|
||||
"type": "ToPoint",
|
||||
"units": {
|
||||
"type": "Inches"
|
||||
}
|
||||
},
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
2604,
|
||||
2648,
|
||||
0
|
||||
]
|
||||
},
|
||||
"from": [
|
||||
2.0,
|
||||
3.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
-2.0,
|
||||
3.0
|
||||
],
|
||||
"type": "ToPoint",
|
||||
"units": {
|
||||
"type": "Inches"
|
||||
}
|
||||
},
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
2654,
|
||||
2661,
|
||||
0
|
||||
]
|
||||
},
|
||||
"from": [
|
||||
-2.0,
|
||||
3.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
-2.0,
|
||||
-3.0
|
||||
],
|
||||
"type": "ToPoint",
|
||||
"units": {
|
||||
"type": "Inches"
|
||||
}
|
||||
}
|
||||
],
|
||||
"on": {
|
||||
"type": "plane",
|
||||
"id": "[uuid]",
|
||||
"artifactId": "[uuid]",
|
||||
"value": "Custom",
|
||||
"origin": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.75
|
||||
},
|
||||
"xAxis": {
|
||||
"x": 1.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"yAxis": {
|
||||
"x": 0.0,
|
||||
"y": 1.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"zAxis": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 1.0
|
||||
},
|
||||
"units": {
|
||||
"type": "Inches"
|
||||
},
|
||||
"__meta": []
|
||||
},
|
||||
"start": {
|
||||
"from": [
|
||||
-2.0,
|
||||
-3.0
|
||||
],
|
||||
"to": [
|
||||
-2.0,
|
||||
-3.0
|
||||
],
|
||||
"units": {
|
||||
"type": "Inches"
|
||||
},
|
||||
"tag": null,
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
2455,
|
||||
2499,
|
||||
0
|
||||
]
|
||||
}
|
||||
},
|
||||
"artifactId": "[uuid]",
|
||||
"originalId": "[uuid]",
|
||||
"units": {
|
||||
"type": "Inches"
|
||||
},
|
||||
"__meta": [
|
||||
{
|
||||
"sourceRange": [
|
||||
2455,
|
||||
2499,
|
||||
0
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"height": 0.25,
|
||||
"startCapId": "[uuid]",
|
||||
"endCapId": "[uuid]",
|
||||
"units": {
|
||||
"type": "Inches"
|
||||
},
|
||||
"__meta": [
|
||||
{
|
||||
"sourceRange": [
|
||||
2455,
|
||||
2499,
|
||||
0
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"width": {
|
||||
"type": "Number",
|
||||
"value": 4.0,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Inches"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
},
|
||||
"__meta": [
|
||||
{
|
||||
"sourceRange": [
|
||||
750,
|
||||
751,
|
||||
0
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 73 KiB |
1914
rust/kcl-lib/tests/kcl_samples/ball-bearing/artifact_commands.snap
Normal file
1914
rust/kcl-lib/tests/kcl_samples/ball-bearing/artifact_commands.snap
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,6 @@
|
||||
---
|
||||
source: kcl/src/simulation_tests.rs
|
||||
description: Artifact graph flowchart ball-bearing.kcl
|
||||
extension: md
|
||||
snapshot_kind: binary
|
||||
---
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user