Compare commits
11 Commits
delete-net
...
achalmers/
Author | SHA1 | Date | |
---|---|---|---|
5bc6e76d7b | |||
556396acf3 | |||
56c25cd1f7 | |||
3cd9454268 | |||
55d27ee391 | |||
f35485751d | |||
2b7e924eb9 | |||
63f2756182 | |||
1a1c2c038b | |||
7e2a75509b | |||
4b7537356f |
@ -1,4 +0,0 @@
|
||||
[codespell]
|
||||
ignore-words-list: crate,everytime,inout,co-ordinate,ot,nwo,atleast,ue,afterall,ser,fromM,FromM
|
||||
skip: **/target,node_modules,build,dist,./out,**/Cargo.lock,./docs/**/*.md,./e2e/playwright/lib/console-error-whitelist.ts,.package-lock.json,**/package-lock.json,./openapi/*.json,./packages/codemirror-lang-kcl/test/all.test.ts,./public/kcl-samples,./rust/kcl-lib/tests/kcl_samples,tsconfig.tsbuildinfo,./src/lib/machine-api.d.ts,./test-results,./playwright-report,./kcl-book/book
|
||||
|
5
.github/workflows/build-apps.yml
vendored
@ -96,7 +96,8 @@ jobs:
|
||||
run: |
|
||||
COMMIT=$(git rev-parse --short HEAD)
|
||||
DATE=$(date +'%-y.%-m.%-d')
|
||||
export VERSION=$DATE-main.$COMMIT
|
||||
OFFSET=$(date +'%H%M')
|
||||
export VERSION=$DATE-staging.$OFFSET+$COMMIT
|
||||
npm run files:set-version
|
||||
npm run files:flip-to-nightly
|
||||
|
||||
@ -118,7 +119,7 @@ jobs:
|
||||
assets/icon.png
|
||||
|
||||
- id: export_version
|
||||
run: echo "version=`cat package.json | jq -r '.version'`" >> "$GITHUB_OUTPUT"
|
||||
run: echo "version=`cat package.json | jq -r '.version' | cut -f1 -d"+"`" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- id: export_notes
|
||||
run: echo "notes=`cat release-notes.md`" >> "$GITHUB_OUTPUT"
|
||||
|
8
.github/workflows/static-analysis.yml
vendored
@ -213,13 +213,7 @@ jobs:
|
||||
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
|
||||
run: npm run playwright install chromium --with-deps
|
||||
|
||||
- name: Download internal KCL samples
|
||||
run: git clone --depth=1 https://x-access-token:${{ secrets.GH_PAT_KCL_SAMPLES_INTERNAL }}@github.com/KittyCAD/kcl-samples-internal public/kcl-samples/internal
|
||||
|
||||
- name: Regenerate KCL samples manifest
|
||||
run: cd rust/kcl-lib && EXPECTORATE=overwrite cargo test generate_manifest
|
||||
|
||||
- name: Check public and internal KCL samples
|
||||
- name: run unit tests for kcl samples
|
||||
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
|
||||
run: npm run test:unit:kcl-samples
|
||||
env:
|
||||
|
5
.gitignore
vendored
@ -86,3 +86,8 @@ venv
|
||||
.vscode-test
|
||||
.biome/
|
||||
.million
|
||||
|
||||
# KCL book
|
||||
kcl-book/book
|
||||
kcl-book/src/images/dynamic/foo.png
|
||||
|
||||
|
7
Makefile
@ -44,15 +44,15 @@ endif
|
||||
# BUILD
|
||||
|
||||
CARGO_SOURCES := rust/.cargo/config.toml $(wildcard rust/Cargo.*) $(wildcard rust/**/Cargo.*)
|
||||
KCL_SOURCES := $(wildcard public/kcl-samples/**/*.kcl)
|
||||
RUST_SOURCES := $(wildcard rust/**/*.rs)
|
||||
|
||||
REACT_SOURCES := $(wildcard src/*.tsx) $(wildcard src/**/*.tsx)
|
||||
TYPESCRIPT_SOURCES := tsconfig.* $(wildcard src/*.ts) $(wildcard src/**/*.ts)
|
||||
VITE_SOURCES := $(wildcard vite.*) $(wildcard vite/**/*.tsx)
|
||||
|
||||
|
||||
.PHONY: build
|
||||
build: install public/kcl_wasm_lib_bg.wasm public/kcl-samples/manifest.json .vite/build/main.js
|
||||
build: install public/kcl_wasm_lib_bg.wasm .vite/build/main.js
|
||||
|
||||
public/kcl_wasm_lib_bg.wasm: $(CARGO_SOURCES) $(RUST_SOURCES)
|
||||
ifdef WINDOWS
|
||||
@ -61,9 +61,6 @@ else
|
||||
npm run build:wasm:dev
|
||||
endif
|
||||
|
||||
public/kcl-samples/manifest.json: $(KCL_SOURCES)
|
||||
cd rust/kcl-lib && EXPECTORATE=overwrite cargo test generate_manifest
|
||||
|
||||
.vite/build/main.js: $(REACT_SOURCES) $(TYPESCRIPT_SOURCES) $(VITE_SOURCES)
|
||||
npm run tronb:vite:dev
|
||||
|
||||
|
@ -1,32 +0,0 @@
|
||||
---
|
||||
title: "Arrays and ranges"
|
||||
excerpt: "Documentation of the KCL language for the Zoo Design Studio."
|
||||
layout: manual
|
||||
---
|
||||
|
||||
Arrays are sequences of values.
|
||||
|
||||
Arrays can be written out as *array literals* using a sequence of expressions surrounded by square brackets, e.g., `['hello', 'world']` is an array of strings, `[x, x + 1, x + 2]` is an array of numbers (assuming `x` is a number), `[]` is an empty array, and `['hello', 42, true]` is a mixed array.
|
||||
|
||||
A value in an array can be accessed by indexing using square brackets where the index is a number, for example, `arr[0]`, `arr[42]`, `arr[i]` (where `arr` is an array and `i` is a (whole) number).
|
||||
|
||||
There are some useful functions for working with arrays in the standard library, see [std::array](/docs/kcl-std/modules/std-array) for details.
|
||||
|
||||
## Array types
|
||||
|
||||
Arrays have their own types: `[T]` where `T` is the type of the elements of the array, for example, `[string]` means an array of `string`s and `[any]` means an array of any values.
|
||||
|
||||
Array types can also include length information: `[T; n]` denotes an array of length `n` (where `n` is a number literal) and `[T; 1+]` denotes an array whose length is at least one (i.e., a non-empty array). E.g., `[string; 1+]` and `[number(mm); 3]` are valid array types.
|
||||
|
||||
## Ranges
|
||||
|
||||
Ranges are a succinct way to create an array of sequential numbers. The syntax is `[start .. end]` where `start` and `end` evaluate to whole numbers (integers). Ranges are inclusive of the start and end. The end must be greater than the start. Examples:
|
||||
|
||||
```kcl,norun
|
||||
[0..3] // [0, 1, 2, 3]
|
||||
[3..10] // [3, 4, 5, 6, 7, 8, 9, 10]
|
||||
x = 2
|
||||
[x..x+1] // [2, 3]
|
||||
```
|
||||
|
||||
The units of the start and end numbers must be the same and the result inherits those units.
|
@ -14,7 +14,6 @@ things in a more tutorial fashion. See also our documentation of the [standard l
|
||||
* [Values and types](/docs/kcl-lang/types)
|
||||
* [Numeric types and units](/docs/kcl-lang/numeric)
|
||||
* [Functions](/docs/kcl-lang/functions)
|
||||
* [Arrays and ranges](/docs/kcl-lang/arrays)
|
||||
* [Projects and modules](/docs/kcl-lang/modules)
|
||||
* [Attributes](/docs/kcl-lang/attributes)
|
||||
* [Importing geometry from other CAD systems](/docs/kcl-lang/foreign-imports)
|
||||
|
@ -19,6 +19,18 @@ myBool = false
|
||||
|
||||
Currently you cannot redeclare a constant.
|
||||
|
||||
## Arrays
|
||||
|
||||
An array is defined with `[]` braces. What is inside the brackets can
|
||||
be of any type. For example, the following is completely valid:
|
||||
|
||||
```
|
||||
myArray = ["thing", 2, false]
|
||||
```
|
||||
|
||||
If you want to get a value from an array you can use the index like so:
|
||||
`myArray[0]`.
|
||||
|
||||
|
||||
## Objects
|
||||
|
||||
@ -28,8 +40,8 @@ An object is defined with `{}` braces. Here is an example object:
|
||||
myObj = { a = 0, b = "thing" }
|
||||
```
|
||||
|
||||
To get the property of an object, you can call `myObj.a`, which in the above
|
||||
example returns 0.
|
||||
We support two different ways of getting properties from objects, you can call
|
||||
`myObj.a` or `myObj["a"]` both work.
|
||||
|
||||
## `ImportedGeometry`
|
||||
|
||||
|
@ -22,14 +22,14 @@ This will work on any solid, including extruded solids, revolved solids, and she
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `solids` | [`[Solid]`](/docs/kcl-std/types/std-types-Solid) or [`ImportedGeometry`](/docs/kcl-std/types/std-types-ImportedGeometry) | The solid(s) whose appearance is being set | Yes |
|
||||
| `solids` | [`[Solid]`](/docs/kcl-std/types/std-types-Solid) or [`ImportedGeometry`](/docs/kcl-lang/types#ImportedGeometry) | The solid(s) whose appearance is being set | Yes |
|
||||
| `color` | [`string`](/docs/kcl-std/types/std-types-string) | Color of the new material, a hex string like '#ff0000' | Yes |
|
||||
| `metalness` | [`number`](/docs/kcl-std/types/std-types-number) | Metalness of the new material, a percentage like 95.7. | No |
|
||||
| `roughness` | [`number`](/docs/kcl-std/types/std-types-number) | Roughness of the new material, a percentage like 95.7. | No |
|
||||
|
||||
### Returns
|
||||
|
||||
[`[Solid]`](/docs/kcl-std/types/std-types-Solid) or [`ImportedGeometry`](/docs/kcl-std/types/std-types-ImportedGeometry) - Data for a solid or an imported geometry.
|
||||
[`[Solid]`](/docs/kcl-std/types/std-types-Solid) or [`ImportedGeometry`](/docs/kcl-lang/types#ImportedGeometry) - Data for a solid or an imported geometry.
|
||||
|
||||
|
||||
### Examples
|
||||
|
@ -1,38 +0,0 @@
|
||||
---
|
||||
title: "legAngX"
|
||||
subtitle: "Function in std::math"
|
||||
excerpt: "Compute the angle of the given leg for x."
|
||||
layout: manual
|
||||
---
|
||||
|
||||
Compute the angle of the given leg for x.
|
||||
|
||||
```kcl
|
||||
legAngX(
|
||||
hypotenuse: number(Length),
|
||||
leg: number(Length),
|
||||
): number(deg)
|
||||
```
|
||||
|
||||
|
||||
|
||||
### Arguments
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `hypotenuse` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The length of the triangle's hypotenuse. | Yes |
|
||||
| `leg` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The length of one of the triangle's legs (i.e. non-hypotenuse side). | Yes |
|
||||
|
||||
### Returns
|
||||
|
||||
[`number(deg)`](/docs/kcl-std/types/std-types-number) - A number.
|
||||
|
||||
|
||||
### Examples
|
||||
|
||||
```kcl
|
||||
legAngX(hypotenuse = 5, leg = 3)
|
||||
```
|
||||
|
||||
|
||||
|
@ -1,38 +0,0 @@
|
||||
---
|
||||
title: "legAngY"
|
||||
subtitle: "Function in std::math"
|
||||
excerpt: "Compute the angle of the given leg for y."
|
||||
layout: manual
|
||||
---
|
||||
|
||||
Compute the angle of the given leg for y.
|
||||
|
||||
```kcl
|
||||
legAngY(
|
||||
hypotenuse: number(Length),
|
||||
leg: number(Length),
|
||||
): number(deg)
|
||||
```
|
||||
|
||||
|
||||
|
||||
### Arguments
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `hypotenuse` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The length of the triangle's hypotenuse. | Yes |
|
||||
| `leg` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The length of one of the triangle's legs (i.e. non-hypotenuse side). | Yes |
|
||||
|
||||
### Returns
|
||||
|
||||
[`number(deg)`](/docs/kcl-std/types/std-types-number) - A number.
|
||||
|
||||
|
||||
### Examples
|
||||
|
||||
```kcl
|
||||
legAngY(hypotenuse = 5, leg = 3)
|
||||
```
|
||||
|
||||
|
||||
|
@ -1,38 +0,0 @@
|
||||
---
|
||||
title: "legLen"
|
||||
subtitle: "Function in std::math"
|
||||
excerpt: "Compute the length of the given leg."
|
||||
layout: manual
|
||||
---
|
||||
|
||||
Compute the length of the given leg.
|
||||
|
||||
```kcl
|
||||
legLen(
|
||||
hypotenuse: number(Length),
|
||||
leg: number(Length),
|
||||
): number(deg)
|
||||
```
|
||||
|
||||
|
||||
|
||||
### Arguments
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `hypotenuse` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The length of the triangle's hypotenuse. | Yes |
|
||||
| `leg` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The length of one of the triangle's legs (i.e. non-hypotenuse side). | Yes |
|
||||
|
||||
### Returns
|
||||
|
||||
[`number(deg)`](/docs/kcl-std/types/std-types-number) - A number.
|
||||
|
||||
|
||||
### Examples
|
||||
|
||||
```kcl
|
||||
legLen(hypotenuse = 5, leg = 3)
|
||||
```
|
||||
|
||||
|
||||
|
@ -12,15 +12,15 @@ layout: manual
|
||||
* [`appearance`](/docs/kcl-std/appearance)
|
||||
* [`assert`](/docs/kcl-std/assert)
|
||||
* [`assertIs`](/docs/kcl-std/assertIs)
|
||||
* [`clone`](/docs/kcl-std/functions/std-clone)
|
||||
* [`clone`](/docs/kcl-std/clone)
|
||||
* [`helix`](/docs/kcl-std/functions/std-helix)
|
||||
* [`offsetPlane`](/docs/kcl-std/functions/std-offsetPlane)
|
||||
* [`patternLinear2d`](/docs/kcl-std/patternLinear2d)
|
||||
* [**std::array**](/docs/kcl-std/modules/std-array)
|
||||
* [`map`](/docs/kcl-std/functions/std-array-map)
|
||||
* [`pop`](/docs/kcl-std/functions/std-array-pop)
|
||||
* [`push`](/docs/kcl-std/functions/std-array-push)
|
||||
* [`reduce`](/docs/kcl-std/functions/std-array-reduce)
|
||||
* [`map`](/docs/kcl-std/map)
|
||||
* [`pop`](/docs/kcl-std/pop)
|
||||
* [`push`](/docs/kcl-std/push)
|
||||
* [`reduce`](/docs/kcl-std/reduce)
|
||||
* [**std::math**](/docs/kcl-std/modules/std-math)
|
||||
* [`abs`](/docs/kcl-std/functions/std-math-abs)
|
||||
* [`acos`](/docs/kcl-std/functions/std-math-acos)
|
||||
@ -30,9 +30,9 @@ layout: manual
|
||||
* [`ceil`](/docs/kcl-std/functions/std-math-ceil)
|
||||
* [`cos`](/docs/kcl-std/functions/std-math-cos)
|
||||
* [`floor`](/docs/kcl-std/functions/std-math-floor)
|
||||
* [`legAngX`](/docs/kcl-std/functions/std-math-legAngX)
|
||||
* [`legAngY`](/docs/kcl-std/functions/std-math-legAngY)
|
||||
* [`legLen`](/docs/kcl-std/functions/std-math-legLen)
|
||||
* [`legAngX`](/docs/kcl-std/legAngX)
|
||||
* [`legAngY`](/docs/kcl-std/legAngY)
|
||||
* [`legLen`](/docs/kcl-std/legLen)
|
||||
* [`ln`](/docs/kcl-std/functions/std-math-ln)
|
||||
* [`log`](/docs/kcl-std/functions/std-math-log)
|
||||
* [`log10`](/docs/kcl-std/functions/std-math-log10)
|
||||
@ -140,13 +140,12 @@ See also the [types overview](/docs/kcl-lang/types)
|
||||
|
||||
* [**Primitive types**](/docs/kcl-lang/types)
|
||||
* [`End`](/docs/kcl-lang/types#End)
|
||||
* [`ImportedGeometry`](/docs/kcl-std/types/std-types-ImportedGeometry)
|
||||
* [`ImportedGeometry`](/docs/kcl-lang/types#ImportedGeometry)
|
||||
* [`Start`](/docs/kcl-lang/types#Start)
|
||||
* [`TagDeclarator`](/docs/kcl-lang/types#TagDeclarator)
|
||||
* [`TagIdentifier`](/docs/kcl-lang/types#TagIdentifier)
|
||||
* [`any`](/docs/kcl-std/types/std-types-any)
|
||||
* [`bool`](/docs/kcl-std/types/std-types-bool)
|
||||
* [`fn`](/docs/kcl-std/types/std-types-fn)
|
||||
* [`number`](/docs/kcl-std/types/std-types-number)
|
||||
* [`string`](/docs/kcl-std/types/std-types-string)
|
||||
* [`tag`](/docs/kcl-std/types/std-types-tag)
|
||||
|
38
docs/kcl-std/legAngX.md
Normal file
@ -0,0 +1,38 @@
|
||||
---
|
||||
title: "legAngX"
|
||||
subtitle: "Function in std::math"
|
||||
excerpt: "Compute the angle of the given leg for x."
|
||||
layout: manual
|
||||
---
|
||||
|
||||
Compute the angle of the given leg for x.
|
||||
|
||||
```kcl
|
||||
legAngX(
|
||||
hypotenuse: number,
|
||||
leg: number,
|
||||
): number
|
||||
```
|
||||
|
||||
|
||||
|
||||
### Arguments
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `hypotenuse` | [`number`](/docs/kcl-std/types/std-types-number) | The length of the triangle's hypotenuse | Yes |
|
||||
| `leg` | [`number`](/docs/kcl-std/types/std-types-number) | The length of one of the triangle's legs (i.e. non-hypotenuse side) | Yes |
|
||||
|
||||
### Returns
|
||||
|
||||
[`number`](/docs/kcl-std/types/std-types-number) - A number.
|
||||
|
||||
|
||||
### Examples
|
||||
|
||||
```kcl
|
||||
legAngX(hypotenuse = 5, leg = 3)
|
||||
```
|
||||
|
||||
|
||||
|
38
docs/kcl-std/legAngY.md
Normal file
@ -0,0 +1,38 @@
|
||||
---
|
||||
title: "legAngY"
|
||||
subtitle: "Function in std::math"
|
||||
excerpt: "Compute the angle of the given leg for y."
|
||||
layout: manual
|
||||
---
|
||||
|
||||
Compute the angle of the given leg for y.
|
||||
|
||||
```kcl
|
||||
legAngY(
|
||||
hypotenuse: number,
|
||||
leg: number,
|
||||
): number
|
||||
```
|
||||
|
||||
|
||||
|
||||
### Arguments
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `hypotenuse` | [`number`](/docs/kcl-std/types/std-types-number) | The length of the triangle's hypotenuse | Yes |
|
||||
| `leg` | [`number`](/docs/kcl-std/types/std-types-number) | The length of one of the triangle's legs (i.e. non-hypotenuse side) | Yes |
|
||||
|
||||
### Returns
|
||||
|
||||
[`number`](/docs/kcl-std/types/std-types-number) - A number.
|
||||
|
||||
|
||||
### Examples
|
||||
|
||||
```kcl
|
||||
legAngY(hypotenuse = 5, leg = 3)
|
||||
```
|
||||
|
||||
|
||||
|
38
docs/kcl-std/legLen.md
Normal file
@ -0,0 +1,38 @@
|
||||
---
|
||||
title: "legLen"
|
||||
subtitle: "Function in std::math"
|
||||
excerpt: "Compute the length of the given leg."
|
||||
layout: manual
|
||||
---
|
||||
|
||||
Compute the length of the given leg.
|
||||
|
||||
```kcl
|
||||
legLen(
|
||||
hypotenuse: number,
|
||||
leg: number,
|
||||
): number
|
||||
```
|
||||
|
||||
|
||||
|
||||
### Arguments
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `hypotenuse` | [`number`](/docs/kcl-std/types/std-types-number) | The length of the triangle's hypotenuse | Yes |
|
||||
| `leg` | [`number`](/docs/kcl-std/types/std-types-number) | The length of one of the triangle's legs (i.e. non-hypotenuse side) | Yes |
|
||||
|
||||
### Returns
|
||||
|
||||
[`number`](/docs/kcl-std/types/std-types-number) - A number.
|
||||
|
||||
|
||||
### Examples
|
||||
|
||||
```kcl
|
||||
legLen(hypotenuse = 5, leg = 3)
|
||||
```
|
||||
|
||||
|
||||
|
@ -12,8 +12,8 @@ Functions for manipulating arrays of values.
|
||||
|
||||
## Functions and constants
|
||||
|
||||
* [`map`](/docs/kcl-std/functions/std-array-map)
|
||||
* [`pop`](/docs/kcl-std/functions/std-array-pop)
|
||||
* [`push`](/docs/kcl-std/functions/std-array-push)
|
||||
* [`reduce`](/docs/kcl-std/functions/std-array-reduce)
|
||||
* [`map`](/docs/kcl-std/map)
|
||||
* [`pop`](/docs/kcl-std/pop)
|
||||
* [`push`](/docs/kcl-std/push)
|
||||
* [`reduce`](/docs/kcl-std/reduce)
|
||||
|
||||
|
@ -23,9 +23,9 @@ Functions for mathematical operations and some useful constants.
|
||||
* [`ceil`](/docs/kcl-std/functions/std-math-ceil)
|
||||
* [`cos`](/docs/kcl-std/functions/std-math-cos)
|
||||
* [`floor`](/docs/kcl-std/functions/std-math-floor)
|
||||
* [`legAngX`](/docs/kcl-std/functions/std-math-legAngX)
|
||||
* [`legAngY`](/docs/kcl-std/functions/std-math-legAngY)
|
||||
* [`legLen`](/docs/kcl-std/functions/std-math-legLen)
|
||||
* [`legAngX`](/docs/kcl-std/legAngX)
|
||||
* [`legAngY`](/docs/kcl-std/legAngY)
|
||||
* [`legLen`](/docs/kcl-std/legLen)
|
||||
* [`ln`](/docs/kcl-std/functions/std-math-ln)
|
||||
* [`log`](/docs/kcl-std/functions/std-math-log)
|
||||
* [`log10`](/docs/kcl-std/functions/std-math-log10)
|
||||
|
@ -18,7 +18,6 @@ Types can (optionally) be used to describe a function's arguments and returned v
|
||||
* [`Edge`](/docs/kcl-std/types/std-types-Edge)
|
||||
* [`Face`](/docs/kcl-std/types/std-types-Face)
|
||||
* [`Helix`](/docs/kcl-std/types/std-types-Helix)
|
||||
* [`ImportedGeometry`](/docs/kcl-std/types/std-types-ImportedGeometry)
|
||||
* [`Plane`](/docs/kcl-std/types/std-types-Plane)
|
||||
* [`Point2d`](/docs/kcl-std/types/std-types-Point2d)
|
||||
* [`Point3d`](/docs/kcl-std/types/std-types-Point3d)
|
||||
@ -26,7 +25,6 @@ Types can (optionally) be used to describe a function's arguments and returned v
|
||||
* [`Solid`](/docs/kcl-std/types/std-types-Solid)
|
||||
* [`any`](/docs/kcl-std/types/std-types-any)
|
||||
* [`bool`](/docs/kcl-std/types/std-types-bool)
|
||||
* [`fn`](/docs/kcl-std/types/std-types-fn)
|
||||
* [`number`](/docs/kcl-std/types/std-types-number)
|
||||
* [`string`](/docs/kcl-std/types/std-types-string)
|
||||
* [`tag`](/docs/kcl-std/types/std-types-tag)
|
||||
|
@ -37,7 +37,7 @@ You might also want the [KCL language reference](/docs/kcl-lang) or the [KCL gui
|
||||
* [`appearance`](/docs/kcl-std/appearance)
|
||||
* [`assert`](/docs/kcl-std/assert)
|
||||
* [`assertIs`](/docs/kcl-std/assertIs)
|
||||
* [`clone`](/docs/kcl-std/functions/std-clone)
|
||||
* [`clone`](/docs/kcl-std/clone)
|
||||
* [`helix`](/docs/kcl-std/functions/std-helix)
|
||||
* [`offsetPlane`](/docs/kcl-std/functions/std-offsetPlane)
|
||||
* [`patternLinear2d`](/docs/kcl-std/patternLinear2d)
|
||||
|
@ -43,7 +43,7 @@ When rotating a part around an axis, you specify the axis of rotation and the an
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `objects` | [`[Solid]`](/docs/kcl-std/types/std-types-Solid) or [`[Sketch]`](/docs/kcl-std/types/std-types-Sketch) or [`ImportedGeometry`](/docs/kcl-std/types/std-types-ImportedGeometry) | The solid, sketch, or set of solids or sketches to rotate. | Yes |
|
||||
| `objects` | [`[Solid]`](/docs/kcl-std/types/std-types-Solid) or [`[Sketch]`](/docs/kcl-std/types/std-types-Sketch) or [`ImportedGeometry`](/docs/kcl-lang/types#ImportedGeometry) | The solid, sketch, or set of solids or sketches to rotate. | Yes |
|
||||
| `roll` | [`number`](/docs/kcl-std/types/std-types-number) | The roll angle in degrees. Must be between -360 and 360. Default is 0 if not given. | No |
|
||||
| `pitch` | [`number`](/docs/kcl-std/types/std-types-number) | The pitch angle in degrees. Must be between -360 and 360. Default is 0 if not given. | No |
|
||||
| `yaw` | [`number`](/docs/kcl-std/types/std-types-number) | The yaw angle in degrees. Must be between -360 and 360. Default is 0 if not given. | No |
|
||||
@ -53,7 +53,7 @@ When rotating a part around an axis, you specify the axis of rotation and the an
|
||||
|
||||
### Returns
|
||||
|
||||
[`[Solid]`](/docs/kcl-std/types/std-types-Solid) or [`[Sketch]`](/docs/kcl-std/types/std-types-Sketch) or [`ImportedGeometry`](/docs/kcl-std/types/std-types-ImportedGeometry) - Data for a solid, sketch, or an imported geometry.
|
||||
[`[Solid]`](/docs/kcl-std/types/std-types-Solid) or [`[Sketch]`](/docs/kcl-std/types/std-types-Sketch) or [`ImportedGeometry`](/docs/kcl-lang/types#ImportedGeometry) - Data for a solid, sketch, or an imported geometry.
|
||||
|
||||
|
||||
### Examples
|
||||
|
@ -29,7 +29,7 @@ If you want to apply the transform in global space, set `global` to `true`. The
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `objects` | [`[Solid]`](/docs/kcl-std/types/std-types-Solid) or [`[Sketch]`](/docs/kcl-std/types/std-types-Sketch) or [`ImportedGeometry`](/docs/kcl-std/types/std-types-ImportedGeometry) | The solid, sketch, or set of solids or sketches to scale. | Yes |
|
||||
| `objects` | [`[Solid]`](/docs/kcl-std/types/std-types-Solid) or [`[Sketch]`](/docs/kcl-std/types/std-types-Sketch) or [`ImportedGeometry`](/docs/kcl-lang/types#ImportedGeometry) | The solid, sketch, or set of solids or sketches to scale. | Yes |
|
||||
| `x` | [`number`](/docs/kcl-std/types/std-types-number) | The scale factor for the x axis. Default is 1 if not provided. | No |
|
||||
| `y` | [`number`](/docs/kcl-std/types/std-types-number) | The scale factor for the y axis. Default is 1 if not provided. | No |
|
||||
| `z` | [`number`](/docs/kcl-std/types/std-types-number) | The scale factor for the z axis. Default is 1 if not provided. | No |
|
||||
@ -37,7 +37,7 @@ If you want to apply the transform in global space, set `global` to `true`. The
|
||||
|
||||
### Returns
|
||||
|
||||
[`[Solid]`](/docs/kcl-std/types/std-types-Solid) or [`[Sketch]`](/docs/kcl-std/types/std-types-Sketch) or [`ImportedGeometry`](/docs/kcl-std/types/std-types-ImportedGeometry) - Data for a solid, sketch, or an imported geometry.
|
||||
[`[Solid]`](/docs/kcl-std/types/std-types-Solid) or [`[Sketch]`](/docs/kcl-std/types/std-types-Sketch) or [`ImportedGeometry`](/docs/kcl-lang/types#ImportedGeometry) - Data for a solid, sketch, or an imported geometry.
|
||||
|
||||
|
||||
### Examples
|
||||
|
34924
docs/kcl-std/std.json
@ -25,7 +25,7 @@ Translate is really useful for sketches if you want to move a sketch and then ro
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `objects` | [`[Solid]`](/docs/kcl-std/types/std-types-Solid) or [`[Sketch]`](/docs/kcl-std/types/std-types-Sketch) or [`ImportedGeometry`](/docs/kcl-std/types/std-types-ImportedGeometry) | The solid, sketch, or set of solids or sketches to move. | Yes |
|
||||
| `objects` | [`[Solid]`](/docs/kcl-std/types/std-types-Solid) or [`[Sketch]`](/docs/kcl-std/types/std-types-Sketch) or [`ImportedGeometry`](/docs/kcl-lang/types#ImportedGeometry) | The solid, sketch, or set of solids or sketches to move. | Yes |
|
||||
| `x` | [`number`](/docs/kcl-std/types/std-types-number) | The amount to move the solid or sketch along the x axis. Defaults to 0 if not provided. | No |
|
||||
| `y` | [`number`](/docs/kcl-std/types/std-types-number) | The amount to move the solid or sketch along the y axis. Defaults to 0 if not provided. | No |
|
||||
| `z` | [`number`](/docs/kcl-std/types/std-types-number) | The amount to move the solid or sketch along the z axis. Defaults to 0 if not provided. | No |
|
||||
@ -33,7 +33,7 @@ Translate is really useful for sketches if you want to move a sketch and then ro
|
||||
|
||||
### Returns
|
||||
|
||||
[`[Solid]`](/docs/kcl-std/types/std-types-Solid) or [`[Sketch]`](/docs/kcl-std/types/std-types-Sketch) or [`ImportedGeometry`](/docs/kcl-std/types/std-types-ImportedGeometry) - Data for a solid, sketch, or an imported geometry.
|
||||
[`[Solid]`](/docs/kcl-std/types/std-types-Solid) or [`[Sketch]`](/docs/kcl-std/types/std-types-Sketch) or [`ImportedGeometry`](/docs/kcl-lang/types#ImportedGeometry) - Data for a solid, sketch, or an imported geometry.
|
||||
|
||||
|
||||
### Examples
|
||||
|
@ -1,13 +0,0 @@
|
||||
---
|
||||
title: "ImportedGeometry"
|
||||
subtitle: "Type in std::types"
|
||||
excerpt: "Represents geometry which is defined using some other CAD system and imported into KCL."
|
||||
layout: manual
|
||||
---
|
||||
|
||||
Represents geometry which is defined using some other CAD system and imported into KCL.
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,13 +0,0 @@
|
||||
---
|
||||
title: "fn"
|
||||
subtitle: "Type in std::types"
|
||||
excerpt: "The type of any function in KCL."
|
||||
layout: manual
|
||||
---
|
||||
|
||||
The type of any function in KCL.
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -549,6 +549,48 @@ extrude002 = extrude(profile002, length = 150)
|
||||
})
|
||||
})
|
||||
|
||||
test(
|
||||
`Network health indicator only appears in modeling view`,
|
||||
{ tag: '@electron' },
|
||||
async ({ context, page }, testInfo) => {
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
const bracketDir = path.join(dir, 'bracket')
|
||||
await fsp.mkdir(bracketDir, { recursive: true })
|
||||
await fsp.copyFile(
|
||||
executorInputPath('cylinder-inches.kcl'),
|
||||
path.join(bracketDir, 'main.kcl')
|
||||
)
|
||||
})
|
||||
|
||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||
const u = await getUtils(page)
|
||||
|
||||
// Locators
|
||||
const projectsHeading = page.getByRole('heading', {
|
||||
name: 'Projects',
|
||||
})
|
||||
const projectLink = page.getByRole('link', { name: 'bracket' })
|
||||
const networkHealthIndicator = page.getByTestId('network-toggle')
|
||||
|
||||
await test.step('Check the home page', async () => {
|
||||
await expect(projectsHeading).toBeVisible()
|
||||
await expect(projectLink).toBeVisible()
|
||||
await expect(networkHealthIndicator).not.toBeVisible()
|
||||
})
|
||||
|
||||
await test.step('Open the project', async () => {
|
||||
await projectLink.click()
|
||||
})
|
||||
|
||||
await test.step('Check the modeling view', async () => {
|
||||
await expect(networkHealthIndicator).toBeVisible()
|
||||
await expect(networkHealthIndicator).toContainText('Problem')
|
||||
await u.waitForPageLoad()
|
||||
await expect(networkHealthIndicator).toContainText('Connected')
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
test(`View gizmo stays visible even when zoomed out all the way`, async ({
|
||||
page,
|
||||
homePage,
|
||||
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 43 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 74 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 132 KiB After Width: | Height: | Size: 132 KiB |
Before Width: | Height: | Size: 116 KiB After Width: | Height: | Size: 116 KiB |
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 65 KiB |
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 68 KiB |
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 64 KiB |
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 67 KiB |
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 67 KiB |
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 63 KiB |
@ -905,7 +905,7 @@ test.describe('Mocked Text-to-CAD API tests', { tag: ['@skipWin'] }, () => {
|
||||
await page.keyboard.press('Enter')
|
||||
|
||||
// Go into the project that was created from Text to CAD
|
||||
await homePage.openProject(projectName)
|
||||
await page.getByText(projectName).click()
|
||||
|
||||
await expect(page.getByTestId('app-header-project-name')).toBeVisible()
|
||||
await expect(page.getByTestId('app-header-project-name')).toContainText(
|
||||
@ -951,7 +951,7 @@ test.describe('Mocked Text-to-CAD API tests', { tag: ['@skipWin'] }, () => {
|
||||
await page.keyboard.press('Enter')
|
||||
|
||||
// Go into the project that was created from Text to CAD
|
||||
await homePage.openProject(projectName)
|
||||
await page.getByText(projectName).click()
|
||||
|
||||
await page.getByRole('button', { name: 'Accept' }).click()
|
||||
|
||||
|
1
kcl-book/TODO.md
Normal file
@ -0,0 +1 @@
|
||||
|
15
kcl-book/book.toml
Normal file
@ -0,0 +1,15 @@
|
||||
[book]
|
||||
authors = ["Adam Chalmers"]
|
||||
language = "en"
|
||||
multilingual = false
|
||||
src = "src"
|
||||
title = "Modeling with KCL"
|
||||
|
||||
[preprocessor.toc]
|
||||
command = "mdbook-toc"
|
||||
renderer = ["html"]
|
||||
|
||||
# [output.pdf]
|
||||
|
||||
# [output.html.print]
|
||||
# enable = true
|
BIN
kcl-book/program1_in_editor.png
Normal file
After Width: | Height: | Size: 738 KiB |
31
kcl-book/src/SUMMARY.md
Normal file
@ -0,0 +1,31 @@
|
||||
# Contents
|
||||
|
||||
[Introduction](./intro.md)
|
||||
|
||||
# Language basics
|
||||
|
||||
- [Calculations and variables](./variables.md)
|
||||
- [Calling functions](./calling_functions.md)
|
||||
- [Pipeline syntax](./pipelines.md)
|
||||
|
||||
# Modeling with KCL
|
||||
|
||||
- [Sketching 2D shapes](./sketch2d.md)
|
||||
- [Sketching curved lines](./sketch2d_curves.md)
|
||||
- [Creating 3D shapes](./sketch3d.md)
|
||||
- [Tags, Fillets and Chamfers](./tags.md)
|
||||
- [Sketch on face](./sketch_on_face.md)
|
||||
- [Transforming 3D solids](./transform_3d.md)
|
||||
- [Combining 3D solids](./csg.md)
|
||||
- [Patterns](./patterns.md)
|
||||
|
||||
# Advanced modeling
|
||||
|
||||
- [Functions and parametric design](./declaring_functions.md)
|
||||
- [Iterating with map and reduce](./map_reduce.md)
|
||||
- [Reduce and geometry](./reduce_geometry.md)
|
||||
|
||||
# KCL projects
|
||||
- [Units of measurement](./units_of_measurement.md)
|
||||
- [Modules](./modules.md)
|
||||
|
110
kcl-book/src/calling_functions.md
Normal file
@ -0,0 +1,110 @@
|
||||
# Calling functions
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
In the last chapter, we looked at different data types that KCL can store. Now let's look at how to actually use them for more complex calculations. We use KCL functions for nearly everything, including all our mechanical engineering tools, so they're very important.
|
||||
|
||||
## Data in, data out
|
||||
|
||||
Let's look at a really simple function call.
|
||||
|
||||
```kcl
|
||||
smallest = min([1, 2, 3, 0, 4])
|
||||
```
|
||||
|
||||
This is a variable declaration, just like the variables we declared in the previous chapter. But the right-hand side -- the value the variable is defined as -- looks different. This is a _function call_. The function's name is `min`, as in "minimum".
|
||||
|
||||
Functions have _inputs_ and _outputs_. This function has just one input, an array of numbers. When you _call_ a function, you pass it inputs in between the parentheses/round brackets. Then KCL calculates its output. You can check its output by looking up `smallest` in the Variables panel. Spoiler: it's 0. Which is, as you'd expect, the minimum value in that array.
|
||||
|
||||
If you hover your mouse cursor over the function name `min`, you'll find some helpful documentation about the function. You can also look up all the possible functions at <https://docs.zoo.dev>. That page shows every function, and if you click it, you can see the function's name, inputs, outputs and some helpful examples of how to use it.
|
||||
|
||||
All functions take some data inputs and return an output. The inputs can be variables, just like you used in the previous chapter:
|
||||
|
||||
```kcl
|
||||
myNumbers = [1, 2, 3, 0, 4]
|
||||
smallest = min(myNumbers)
|
||||
```
|
||||
|
||||
A function's inputs are also called its _arguments_. A function's output is also called its _return value_.
|
||||
|
||||
Here are some other simple functions you can call:
|
||||
|
||||
```kcl
|
||||
absoluteValue = abs(-3)
|
||||
roundedUp = ceil(12.5)
|
||||
shouldBe2 = log10(100)
|
||||
```
|
||||
|
||||
## Labeled arguments
|
||||
|
||||
The `min` function takes just one argument: an array of numbers. But most KCL functions take in multiple arguments. When there's many different arguments, it can be confusing to tell which argument means what. For example, what does this function do?
|
||||
|
||||
```kcl
|
||||
x = pow(4, 2)
|
||||
```
|
||||
|
||||
If you mouse over the docs for `pow` (or look them up at the KCL website) you'll see it's short for `power`, as in raising a number to some power (like squaring it, or cubing it). But, does `pow(4, 2)` mean 4 to the power of 2, or 2 to the power of 4? You could look up the docs, but that gets annoying quickly. Instead, KCL uses _labels_ for the parameters. The real `pow` call looks like this:
|
||||
|
||||
```kcl
|
||||
x = pow(4, exp = 2)
|
||||
```
|
||||
|
||||
Now you can tell that 2 is the _exponent_ (i.e. the power), not the base. If a KCL function has multiple arguments, only the first argument can be unlabeled. All the following arguments need a label. Here are some other examples.
|
||||
|
||||
```kcl
|
||||
oldArray = [1, 2, 3]
|
||||
newArray = push(oldArray, item = 4)
|
||||
```
|
||||
|
||||
Here, we make a new array by pushing a new item onto the end of the old array. The old array is the first argument, so it doesn't need a label. The second argument, `item`, does need a label.
|
||||
|
||||
## Combining functions
|
||||
|
||||
Functions take inputs and produce an output. The real power of functions is: that output can become the input to another function! For example:
|
||||
|
||||
```kcl
|
||||
x = 2
|
||||
xSquared = pow(x, exp = 2)
|
||||
xPow4 = pow(xSquared, exp = 2)
|
||||
```
|
||||
|
||||
That's a very simple example, but it shows that you can assign the output of a function call to a variable (like `xSquared`) and then use it as the input to another function. Here's a more realistic example, where we use several functions to calculate the roots x0 and x1 of a quadratic equation.
|
||||
|
||||
```kcl
|
||||
a = 2
|
||||
b = 3
|
||||
c = 1
|
||||
|
||||
delta = pow(b, exp = 2) - (4 * a * c)
|
||||
x0 = ((-b) + sqrt(delta)) / (2 * a)
|
||||
x1 = ((-b) - sqrt(delta)) / (2 * a)
|
||||
```
|
||||
|
||||
If you open up the Variables panel, you'll see this gives two roots -0.5 and -1. Combining functions like this lets you break complicated equations into several small, simple steps. Each step can have its own variable, with a sensible name that explains how it's being used.
|
||||
|
||||
## Comments
|
||||
|
||||
This is a good point to introduce comments. When you start writing more complex code, with lots of function calls and variables, it might be hard for your colleagues (or your future self) to understand what you're trying to do. That's why KCL lets you leave comments to anyone reading your code. Let's add some comments to the quadratic equation code above:
|
||||
|
||||
```kcl
|
||||
// Coefficients that define the quadratic
|
||||
a = 2
|
||||
b = 3
|
||||
c = 1
|
||||
|
||||
// The quadratic equation's discriminant
|
||||
delta = pow(b, exp = 2) - (4 * a * c)
|
||||
|
||||
// The two roots of the equation
|
||||
x0 = ((-b) + sqrt(delta)) / (2 * a)
|
||||
x1 = ((-b) - sqrt(delta)) / (2 * a)
|
||||
```
|
||||
|
||||
If you type `//`, any subsequent text on that line is a comment. It doesn't get executed like the rest of the code! It's just for other humans to read.
|
||||
|
||||
## The standard library
|
||||
|
||||
KCL comes built-in with functions for all sorts of common engineering problems -- functions to calculate equations, sketch 2D shapes, combine and manipulate 3D shapes, etc. The built-in KCL functions are called the _standard library_, because it's like a big library of code you can always use.
|
||||
|
||||
You can create your own functions too, but we'll save that for a future chapter. You can get pretty far just using the built-in KCL functions! We're nearly ready to do some actual CAD work, but we've got to learn one more essential KCL feature first.
|
||||
|
108
kcl-book/src/csg.md
Normal file
@ -0,0 +1,108 @@
|
||||
# Combining 3D solids
|
||||
|
||||
We've seen how to make a lot of different solids. You could transform a 2D shape into a 3D solid. From there, you can copy and transform that 3D solid by rotating, translating or rotating it. Now it's time to learn a third way to build 3D solids: by combining other 3D solids. This is sometimes called _constructive solid geometry_ and it's a very powerful tool for any serious mechanical engineering work.
|
||||
|
||||
## Constructive solid geometry
|
||||
|
||||
Remember in school, when you learned about Venn diagrams? How you can take the _union_, the _intersection_ or the _difference_ of two shapes? If you need a quick recap, here's a screenshot from [Wikipedia's article on boolean operations].
|
||||
|
||||

|
||||
|
||||
We can perform similar operations on 3D solids in KCL. Let's see how. Here's two cubes.
|
||||
|
||||
```kcl=two_cubes
|
||||
length = 20
|
||||
cubeGreen = startSketchOn(XY)
|
||||
|> polygon(radius = length, numSides = 4, center = [0, 0])
|
||||
|> extrude(length = length)
|
||||
|> appearance(color = "#229922")
|
||||
|
||||
cubeBlue = startSketchOn(XY)
|
||||
|> polygon(radius = length, numSides = 4, center = [0, 0])
|
||||
|> translate(x = 10, z = 10)
|
||||
|> extrude(length = length)
|
||||
|> appearance(color = "#222299")
|
||||
```
|
||||
|
||||

|
||||
|
||||
That's what it looks like _before_ we apply any CSG operations. Now let's see what happens when we use KCL's [`union`], [`intersect`] and [`subtract`] functions on these. Firstly, let's do a union. This should create a new solid which combines both input solids.
|
||||
|
||||
```kcl=two_cubes_union
|
||||
length = 20
|
||||
cubeGreen = startSketchOn(XY)
|
||||
|> polygon(radius = length, numSides = 4, center = [0, 0])
|
||||
|> extrude(length = length)
|
||||
|> appearance(color = "#229922")
|
||||
|
||||
cubeBlue = startSketchOn(XY)
|
||||
|> polygon(radius = length, numSides = 4, center = [0, 0])
|
||||
|> translate(x = 10, z = 10)
|
||||
|> extrude(length = length)
|
||||
|> appearance(color = "#222299")
|
||||
|
||||
// Boolean operations on the two cubes
|
||||
both = union([cubeGreen, cubeBlue])
|
||||
```
|
||||
|
||||

|
||||
|
||||
Of course, this [`union`] of our two cubes has the exact same dimensions and position as the two cubes. So it looks the exact same. What's the point of doing this? Well, for a start, we can use transforms like `appearance` or `rotate` on the single unified shape. Previously we needed to transform each part separately, which can get annoying. Now that it's a single shape, transformations will apply to the whole thing -- both the first cube's volume, and the second cube's.
|
||||
|
||||
**Note**: Instead of writing `union([cubeGreen, cubeBlue])` you can use the shorthand `cubeGreen + cubeBlue` or `cubeGreen | cubeBlue`. This is a nice little shorthand you can use if you want to.
|
||||
|
||||
Let's try an intersection. This combines both cubes, but leaves only the volume from where they overlapped.
|
||||
|
||||
|
||||
```kcl=two_cubes_intersection
|
||||
length = 20
|
||||
cubeGreen = startSketchOn(XY)
|
||||
|> polygon(radius = length, numSides = 4, center = [0, 0])
|
||||
|> extrude(length = length)
|
||||
|> appearance(color = "#229922")
|
||||
|
||||
cubeBlue = startSketchOn(XY)
|
||||
|> polygon(radius = length, numSides = 4, center = [0, 0])
|
||||
|> translate(x = 10, z = 10)
|
||||
|> extrude(length = length)
|
||||
|> appearance(color = "#222299")
|
||||
|
||||
// Boolean operations on the two cubes
|
||||
both = intersect([cubeGreen, cubeBlue])
|
||||
```
|
||||
|
||||

|
||||
|
||||
This keeps only the small cube shape from where the previous two intersected. This is a new solid, so it can be transformed just like any other solid.
|
||||
|
||||
**Note**: Instead of writing `intersect([cubeGreen, cubeBlue])` you can use the shorthand `cubeGreen & cubeBlue`. This is a nice little shorthand you can use if you want to.
|
||||
|
||||
Lastly, let's try a `subtract` call:
|
||||
|
||||
```kcl=two_cubes_subtraction
|
||||
length = 20
|
||||
cubeGreen = startSketchOn(XY)
|
||||
|> polygon(radius = length, numSides = 4, center = [0, 0])
|
||||
|> extrude(length = length)
|
||||
|> appearance(color = "#229922")
|
||||
|
||||
cubeBlue = startSketchOn(XY)
|
||||
|> polygon(radius = length, numSides = 4, center = [0, 0])
|
||||
|> translate(x = 10, z = 10)
|
||||
|> extrude(length = length)
|
||||
|> appearance(color = "#222299")
|
||||
|
||||
// Boolean operations on the two cubes
|
||||
both = subtract(cubeGreen, tools=[cubeBlue])
|
||||
```
|
||||
|
||||

|
||||
|
||||
Note that the syntax for `subtract` is a little different. The first argument is the solid which will have some volume carved out. The second argument is a list of solids to cut out. You can think of these as "tools" -- you're basically passing tools of various shapes which can carve out special volumes.
|
||||
|
||||
**NOTE**: Currently only one tool can be passed in, but we're nearly finished supporting multiple tools here.
|
||||
|
||||
[Wikipedia's article on boolean operations]: https://en.wikipedia.org/wiki/Set_(mathematics)#Basic_operations
|
||||
[`intersect`]: https://zoo.dev/docs/kcl-std/intersect
|
||||
[`subtract`]: https://zoo.dev/docs/kcl-std/subtract
|
||||
[`union`]: https://zoo.dev/docs/kcl-std/union
|
208
kcl-book/src/declaring_functions.md
Normal file
@ -0,0 +1,208 @@
|
||||
# Functions and parametric design
|
||||
|
||||
+In mechanical engineering, _parametric design_ is a key tool that helps you avoid redundant work when you're designing the same object over and over again with slight tweaks. In software engineering, _functions_ are a key tool that help you avoid redundant work when you're designing the same software over and over again with slight tweaks.
|
||||
|
||||
That's right -- breaking a mechanical engineering project into several key parametric designs is basically the same as breaking a software engineering project into several key functions. KCL makes parametric design easy and convenient with functions. You'll declare functions to represent parametric designs, and you'll call those functions with specific arguments to produce specific designs with the right parameters. Let's see how.
|
||||
|
||||
## Function declaration
|
||||
|
||||
We briefly looked at function declarations when we covered pattern transforms. Let's write an example function declaration and analyze its parts.
|
||||
|
||||
```kcl
|
||||
fn add(a, b) {
|
||||
sum = a + b
|
||||
return sum
|
||||
}
|
||||
```
|
||||
|
||||
A function declaration has a few key parts. Let's look at each one, in the order they appear:
|
||||
|
||||
- The `fn` keyword
|
||||
- The function's _name_
|
||||
- Round parentheses `(` and `)`
|
||||
- Within those parentheses, a list of argument names
|
||||
- Curly brackets `{` and `}`
|
||||
- Within those brackets, KCL code, which may end with a `return` statement.
|
||||
|
||||
This function takes two arguments, `a` and `b`, adds them, and returns their sum as the function's output. When a function executes the `return` statement, it evaluates the expression after `return`, stops executing, and outputs that value. You can call our example function like this:
|
||||
|
||||
```kcl
|
||||
sum = add(a = 1, b = 2)
|
||||
```
|
||||
|
||||
Functions can also declare one *unlabeled* arg. If you do want to declare an unlabeled arg, it must be the first arg declared. When declaring an unlabeled arg, prefix it with `@`, like here:
|
||||
|
||||
```kcl
|
||||
// The @ indicates an argument can be used without a label.
|
||||
// Note that only the first argument can use @.
|
||||
fn increment(@x) {
|
||||
return x + 1
|
||||
}
|
||||
|
||||
fn add(@x, delta) {
|
||||
return x + delta
|
||||
}
|
||||
|
||||
two = increment(1)
|
||||
three = add(1, delta = 2)
|
||||
```
|
||||
|
||||
## Mechanical engineering with functions
|
||||
|
||||
Let's use functions to build a parametric pipe flange. We can start with a specific design, with specific direct measurements. Then we'll learn how to parameterize it. Then we can easily make a lot of similar pipe flanges with different parameters.
|
||||
|
||||
Here's a specific model. It's got 8 unthreaded holes, each with a radius of 4, and the overall model has a radius of 60. It's 10mm thick.
|
||||
|
||||
```kcl=specific_flange
|
||||
holes = startSketchOn(XZ)
|
||||
|> circle(radius = 4, center = [50, 0])
|
||||
|> patternCircular2d(
|
||||
center = [0, 0],
|
||||
instances = 8,
|
||||
arcDegrees = 360,
|
||||
rotateDuplicates = true,
|
||||
)
|
||||
|
||||
base = startSketchOn(XZ)
|
||||
|> circle(radius = 60, center = [0, 0])
|
||||
|> subtract2d(tool = holes)
|
||||
|> extrude(length = 10)
|
||||
```
|
||||
|
||||

|
||||
|
||||
Its specific measurements, like number of holes, radius, thickness etc were chosen somewhat arbitrarily. What if we want to make another pipe flange in the future, with different measurements? We can turn this specific flange model into a parametric design by making it into a function. We'll define a function `pipe_flange` which takes in several parameters. Let's see:
|
||||
|
||||
```kcl=parametric_flange
|
||||
// Define a parametric flange
|
||||
fn flange(numHoles, holeRadius, radius, thickness) {
|
||||
holes = startSketchOn(XZ)
|
||||
|> circle(radius = holeRadius, center = [radius - holeEdgeGap, 0])
|
||||
|> patternCircular2d(
|
||||
center = [0, 0],
|
||||
instances = numHoles,
|
||||
arcDegrees = 360,
|
||||
rotateDuplicates = true,
|
||||
)
|
||||
|
||||
return startSketchOn(XZ)
|
||||
|> circle(radius = radius, center = [0, 0])
|
||||
|> subtract2d(tool = holes)
|
||||
|> extrude(length = thickness)
|
||||
}
|
||||
```
|
||||
|
||||
We can get our original flange by calling the parametric flange with the right parameters:
|
||||
```kcl
|
||||
// Call our parametric flange function, passing in specific parameter values, to make a specific flange.
|
||||
flange(
|
||||
numHoles = 8,
|
||||
holeRadius = 5,
|
||||
radius = 60,
|
||||
thickness = 10,
|
||||
holeEdgeGap = 10,
|
||||
)
|
||||
```
|
||||
|
||||
But we can also make a range of other flanges! Here's one:
|
||||
|
||||
```kcl
|
||||
flange(
|
||||
numHoles = 4,
|
||||
holeRadius = 15,
|
||||
radius = 60,
|
||||
thickness = 20,
|
||||
holeEdgeGap = 20,
|
||||
)
|
||||
```
|
||||
|
||||

|
||||
|
||||
And let's try one more:
|
||||
|
||||
```kcl
|
||||
flange(
|
||||
numHoles = 20,
|
||||
holeRadius = 3,
|
||||
radius = 90,
|
||||
thickness = 20,
|
||||
holeEdgeGap = 15,
|
||||
)
|
||||
```
|
||||
|
||||

|
||||
|
||||
Replacing specific KCL code for a specific design with a parametric function gives you the flexibility to generate a lot of very similar designs, varying their parameters by passing in different arguments to suit whatever your project's requirements are.
|
||||
|
||||
## Repeating geometry with functions
|
||||
|
||||
Functions can also be used to avoid writing the same code over and over again, in a single model. In an earlier chapter we modeled three cubes in one scene, like this:
|
||||
|
||||
```kcl=cube_textures
|
||||
offset = 25
|
||||
|
||||
greyCube = startSketchOn(XY)
|
||||
|> startProfile(at = [0, 0])
|
||||
|> polygon(radius = 10, numSides = 4, center = [0, 0])
|
||||
|> extrude(length = 10)
|
||||
|
||||
greenCube = startSketchOn(XY)
|
||||
|> startProfile(at = [0, 0])
|
||||
|> polygon(radius = 10, numSides = 4, center = [0, offset])
|
||||
|> extrude(length = 10)
|
||||
// The appearance call lets you set a color using hexadecimal notation.
|
||||
|> appearance(color = "#00ff00")
|
||||
|
||||
greenCubeShiny = startSketchOn(XY)
|
||||
|> startProfile(at = [0, 0])
|
||||
|> polygon(radius = 10, numSides = 4, center = [0, offset * 2])
|
||||
|> extrude(length = 10)
|
||||
// You can also set the metalness and roughness, as percentages between 0 and 100.
|
||||
|> appearance(color = "#00ff00", metalness = 90, roughness = 10)
|
||||
```
|
||||
|
||||

|
||||
|
||||
This code works fine, but it's got one small problem. We're repeating the code for "sketch a cube" three times. This makes it a bit annoying to read, and also, if we want to tweak the cubes (making them larger, or rotating them), we'd have to update them in three different places. We could improve this code by making a function for the cube, and calling that function three times.
|
||||
|
||||
```kcl
|
||||
fn cube(offset) {
|
||||
return startSketchOn(XY)
|
||||
|> startProfile(at = [0, 0])
|
||||
|> polygon(radius = 10, numSides = 4, center = [0, offset])
|
||||
|> extrude(length = 10)
|
||||
}
|
||||
|
||||
greyCube = cube(offset = 0)
|
||||
|
||||
greenCube = cube(offset = 25)
|
||||
|> appearance(color = "#00ff00")
|
||||
|
||||
greenCubeShiny = cube(offset = 50)
|
||||
|> appearance(color = "#00ff00", metalness = 90, roughness = 10)
|
||||
```
|
||||
|
||||
This code produces the exact same model as the above code, but it's shorter and easier to read. It's also more maintainable! If we wanted to change the cubes to be flatter, we only have to change one part of our code, instead of changing all three.
|
||||
|
||||
```kcl=three_short_cubes
|
||||
fn cube(offset) {
|
||||
return startSketchOn(XY)
|
||||
|> startProfile(at = [0, 0])
|
||||
|> polygon(radius = 10, numSides = 4, center = [0, offset])
|
||||
// Change the extrude length from 10 to 2, shortening the cubes.
|
||||
|> extrude(length = 2)
|
||||
}
|
||||
|
||||
greyCube = cube(offset = 0)
|
||||
|
||||
greenCube = cube(offset = 25)
|
||||
|> appearance(color = "#00ff00")
|
||||
|
||||
greenCubeShiny = cube(offset = 50)
|
||||
|> appearance(color = "#00ff00", metalness = 90, roughness = 10)
|
||||
```
|
||||
|
||||

|
||||
|
||||
If we hadn't made the cube into a function, we would have had to change every extrude call separately. By putting the details of "what does a cube look like" in a single function, we make our code both more readable, and easier to change in the future.
|
||||
|
BIN
kcl-book/src/images/dynamic/basic_circle.png
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
kcl-book/src/images/dynamic/chamfered_cube.png
Normal file
After Width: | Height: | Size: 65 KiB |
BIN
kcl-book/src/images/dynamic/circle.png
Normal file
After Width: | Height: | Size: 33 KiB |
BIN
kcl-book/src/images/dynamic/circular_cubes_false.png
Normal file
After Width: | Height: | Size: 111 KiB |
BIN
kcl-book/src/images/dynamic/circular_cubes_partway.png
Normal file
After Width: | Height: | Size: 76 KiB |
BIN
kcl-book/src/images/dynamic/circular_cubes_true.png
Normal file
After Width: | Height: | Size: 93 KiB |
BIN
kcl-book/src/images/dynamic/cube_eight_fillets.png
Normal file
After Width: | Height: | Size: 86 KiB |
BIN
kcl-book/src/images/dynamic/cube_four_fillets.png
Normal file
After Width: | Height: | Size: 65 KiB |
BIN
kcl-book/src/images/dynamic/cube_next_prev_fillets.png
Normal file
After Width: | Height: | Size: 73 KiB |
BIN
kcl-book/src/images/dynamic/cube_next_prev_fillets_all_sides.png
Normal file
After Width: | Height: | Size: 81 KiB |
BIN
kcl-book/src/images/dynamic/cube_no_fillets.png
Normal file
After Width: | Height: | Size: 71 KiB |
BIN
kcl-book/src/images/dynamic/cube_one_fillet.png
Normal file
After Width: | Height: | Size: 69 KiB |
BIN
kcl-book/src/images/dynamic/cube_spiral.png
Normal file
After Width: | Height: | Size: 60 KiB |
BIN
kcl-book/src/images/dynamic/cube_textures.png
Normal file
After Width: | Height: | Size: 56 KiB |
BIN
kcl-book/src/images/dynamic/cube_two_opposite_fillets.png
Normal file
After Width: | Height: | Size: 86 KiB |
BIN
kcl-book/src/images/dynamic/custom_plane.png
Normal file
After Width: | Height: | Size: 35 KiB |
BIN
kcl-book/src/images/dynamic/donut.png
Normal file
After Width: | Height: | Size: 107 KiB |
BIN
kcl-book/src/images/dynamic/donut240.png
Normal file
After Width: | Height: | Size: 87 KiB |
BIN
kcl-book/src/images/dynamic/donut_angle_units.png
Normal file
After Width: | Height: | Size: 79 KiB |
BIN
kcl-book/src/images/dynamic/linear_pattern.png
Normal file
After Width: | Height: | Size: 87 KiB |
BIN
kcl-book/src/images/dynamic/lines_units.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
kcl-book/src/images/dynamic/loft_basic.png
Normal file
After Width: | Height: | Size: 88 KiB |
BIN
kcl-book/src/images/dynamic/loft_vd1.png
Normal file
After Width: | Height: | Size: 101 KiB |
BIN
kcl-book/src/images/dynamic/loft_vd2.png
Normal file
After Width: | Height: | Size: 76 KiB |
BIN
kcl-book/src/images/dynamic/parametric_flange.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
kcl-book/src/images/dynamic/path_for_sweep.png
Normal file
After Width: | Height: | Size: 33 KiB |
BIN
kcl-book/src/images/dynamic/pattern2d.png
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
kcl-book/src/images/dynamic/pattern_sof.png
Normal file
After Width: | Height: | Size: 57 KiB |
BIN
kcl-book/src/images/dynamic/reduce_comb.png
Normal file
After Width: | Height: | Size: 38 KiB |
BIN
kcl-book/src/images/dynamic/reduce_polygon.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
kcl-book/src/images/dynamic/reduce_square.png
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
kcl-book/src/images/dynamic/rotated_cubes.png
Normal file
After Width: | Height: | Size: 55 KiB |
BIN
kcl-book/src/images/dynamic/rotated_cubes_axis.png
Normal file
After Width: | Height: | Size: 92 KiB |
BIN
kcl-book/src/images/dynamic/scaled_cubes.png
Normal file
After Width: | Height: | Size: 37 KiB |
BIN
kcl-book/src/images/dynamic/semicircle.png
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
kcl-book/src/images/dynamic/sketch_on_chamfered_cube.png
Normal file
After Width: | Height: | Size: 34 KiB |