@mylasertools/kerfscript 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.0 (2026-10-30)
4
+
5
+ - Assembly: `part()` takes `at` and `rotate` to place a part in 3D, rotated
6
+ first and then moved, like OpenSCAD. `render()` returns the placed parts as
7
+ `assembly` (outline, thickness and a 4 × 4 matrix per copy) so apps can show
8
+ the design put together, and warns when two placed parts collide, which is
9
+ how a wrong finger edge shows up. Overlaps under about 1 mm³ are ignored.
10
+ Parts without a placement lie flat beside the assembly, marked
11
+ `placed: false`, so a divider added to a `box()` still shows.
12
+ `box()` from `kerf/box` places its own panels.
13
+ - Copies of a part that share one placement are drawn in the same place and
14
+ get one warning that says so, instead of a collision warning for every pair.
15
+ - The collision check stops after `maxCollisionPairs` pairs of touching parts
16
+ (20,000 by default) with a warning, so a program that places thousands of
17
+ parts cannot hold up the render. It also skips parts far apart on x before
18
+ comparing them, so large assemblies check faster.
19
+ - `kerfscript.wasm` returns `assembly` in its render response.
20
+
3
21
  ## 0.3.0 (2026-10-30)
4
22
 
5
23
  - `kerfscript.wasm`: a WASI module that runs KerfScript from Python, Rust,
package/LANGUAGE.md CHANGED
@@ -198,8 +198,12 @@ material(thickness = 4, kerf = 0.12, name = "birch") {
198
198
  }
199
199
  ```
200
200
 
201
- - `part(name, qty = 1) { ... }` makes a named part. It records `$thickness`,
202
- `$kerf` and `$material` where it is called.
201
+ - `part(name, qty = 1, at, rotate) { ... }` makes a named part. It records
202
+ `$thickness`, `$kerf` and `$material` where it is called. `at = [x, y, z]`
203
+ and `rotate = [x, y, z]` (degrees) place the part in the assembled view:
204
+ rotated first, then moved, with its thickness along +Z. A part with copies
205
+ takes one placement or a list with one per copy. `render()` returns the
206
+ placed parts as `assembly` and warns when two of them collide.
203
207
  - Shapes outside any part form one part named `part`.
204
208
  - `material(thickness, kerf, name) { ... }` sets those special variables for
205
209
  its children.
@@ -407,16 +411,17 @@ Exceeding a limit stops evaluation with an error.
407
411
 
408
412
  Programs are also limited in how much memory they can ask for:
409
413
 
410
- | Limit | Default | What it counts |
411
- | ----------------- | --------- | -------------------------------------------------------------------------------------------------------------------------- |
412
- | `maxParts` | 10,000 | copies of all parts, adding up every `qty` |
413
- | `maxSegments` | 10,000 | segments in one circle, ellipse or arc, and corners in one polygon |
414
- | `maxListLength` | 1,000,000 | items in one list or range, or characters in one string, including the text `echo()` writes in one call |
415
- | `maxListItems` | 3,000,000 | items in all lists the program builds, plus 4 for each list, one for every 8 characters of the strings it builds or echoes |
416
- | `maxTextLength` | 2,000 | characters in one `text()` |
417
- | `maxPoints` | 2,000,000 | points in all shapes the modules make, plus 100 for each shape |
418
- | `maxOutputPoints` | 1,000,000 | points in the exported files, counting every copy |
419
- | `maxSheets` | 200 | sheets in the layout |
414
+ | Limit | Default | What it counts |
415
+ | ------------------- | --------- | -------------------------------------------------------------------------------------------------------------------------- |
416
+ | `maxParts` | 10,000 | copies of all parts, adding up every `qty` |
417
+ | `maxSegments` | 10,000 | segments in one circle, ellipse or arc, and corners in one polygon |
418
+ | `maxListLength` | 1,000,000 | items in one list or range, or characters in one string, including the text `echo()` writes in one call |
419
+ | `maxListItems` | 3,000,000 | items in all lists the program builds, plus 4 for each list, one for every 8 characters of the strings it builds or echoes |
420
+ | `maxTextLength` | 2,000 | characters in one `text()` |
421
+ | `maxPoints` | 2,000,000 | points in all shapes the modules make, plus 100 for each shape |
422
+ | `maxOutputPoints` | 1,000,000 | points in the exported files, counting every copy |
423
+ | `maxSheets` | 200 | sheets in the layout |
424
+ | `maxCollisionPairs` | 20,000 | pairs of touching placed parts checked for collisions; past it the check stops with a warning |
420
425
 
421
426
  Applications can change them with the `limits` render option.
422
427
 
@@ -0,0 +1,20 @@
1
+ import type { Poly } from './geometry.cjs';
2
+ export type Vec3 = [number, number, number];
3
+ export interface Placement {
4
+ at: Vec3;
5
+ rotate: Vec3;
6
+ }
7
+ export interface AssemblyPart {
8
+ name: string;
9
+ copy: number;
10
+ thickness: number;
11
+ matrix: number[];
12
+ outline: Poly[];
13
+ placed: boolean;
14
+ }
15
+ export declare function placementMatrix(p: Placement): number[];
16
+ export declare function besideAssembly(placed: AssemblyPart[], loose: AssemblyPart[], gap?: number): AssemblyPart[];
17
+ export declare function collisions(parts: AssemblyPart[], maxPairs?: number, eps?: number, pitch?: number, volume?: number): {
18
+ found: [AssemblyPart, AssemblyPart][];
19
+ complete: boolean;
20
+ };
@@ -0,0 +1,20 @@
1
+ import type { Poly } from './geometry.js';
2
+ export type Vec3 = [number, number, number];
3
+ export interface Placement {
4
+ at: Vec3;
5
+ rotate: Vec3;
6
+ }
7
+ export interface AssemblyPart {
8
+ name: string;
9
+ copy: number;
10
+ thickness: number;
11
+ matrix: number[];
12
+ outline: Poly[];
13
+ placed: boolean;
14
+ }
15
+ export declare function placementMatrix(p: Placement): number[];
16
+ export declare function besideAssembly(placed: AssemblyPart[], loose: AssemblyPart[], gap?: number): AssemblyPart[];
17
+ export declare function collisions(parts: AssemblyPart[], maxPairs?: number, eps?: number, pitch?: number, volume?: number): {
18
+ found: [AssemblyPart, AssemblyPart][];
19
+ complete: boolean;
20
+ };