forgecad 0.6.3 → 0.7.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/README.md +2 -11
- package/dist/assets/{AdminPage-CeqCUUgu.js → AdminPage-DAu1C1ST.js} +250 -151
- package/dist/assets/{BlogPage-P_AJP0v9.js → BlogPage-CJEXL_zJ.js} +94 -70
- package/dist/assets/{DocsPage-CKRV2iq2.js → DocsPage-Gc_BCdqC.js} +269 -143
- package/dist/assets/EditorApp-D9bJvtf7.js +11338 -0
- package/dist/assets/{EditorApp-CnC2k4cW.css → EditorApp-DG1-oUSV.css} +459 -87
- package/dist/assets/{EmbedViewer-DBlzmQ5i.js → EmbedViewer-CEO8XbV8.js} +2 -4
- package/dist/assets/LandingPage-CdCuEOdC.js +451 -0
- package/dist/assets/PricingPage-BSrxu6d7.js +232 -0
- package/dist/assets/{SettingsPage-BqCh9JcC.js → SettingsPage-FUCSIRq6.js} +129 -5
- package/dist/assets/{evalWorker-Ql-aKwLA.js → evalWorker-KoR0SNKq.js} +6770 -2914
- package/dist/assets/{index-2hfs_ub0.css → index-CyVd1D4D.css} +227 -53
- package/dist/assets/{Viewport-CoB46f5R.js → index-wTEK39at.js} +31385 -6439
- package/dist/assets/{javascript-DCxGoE5Y.js → javascript-DAl8Gmyo.js} +1 -1
- package/dist/assets/{manifold-CqNMHHKO.js → manifold-B1sGWdYk.js} +4 -3
- package/dist/assets/{manifold-Cce9wRFz.js → manifold-D7o0N50J.js} +1 -1
- package/dist/assets/{manifold-D6BeHIOo.js → manifold-G5sBaXzi.js} +1 -1
- package/dist/assets/{reportWorker-sFEFonXf.js → reportWorker-DYcRHhv9.js} +6798 -3341
- package/dist/assets/{vendor-react-Dt7-aaJH.js → vendor-react-CG3i_wp0.js} +65 -8
- package/dist/docs-raw/generated/assembly.md +691 -112
- package/dist/docs-raw/generated/concepts.md +1225 -1400
- package/dist/docs-raw/generated/core.md +464 -1412
- package/dist/docs-raw/generated/curves.md +593 -117
- package/dist/docs-raw/generated/lib.md +38 -748
- package/dist/docs-raw/generated/output.md +139 -245
- package/dist/docs-raw/generated/sheet-metal.md +473 -21
- package/dist/docs-raw/generated/sketch.md +553 -349
- package/dist/docs-raw/generated/viewport.md +345 -303
- package/dist/docs-raw/generated/wood.md +104 -0
- package/dist/index.html +2 -2
- package/dist/sitemap.xml +6 -6
- package/dist-cli/chunk-PZ5AY32C.js +10 -0
- package/dist-cli/chunk-PZ5AY32C.js.map +1 -0
- package/dist-cli/forgecad.js +9435 -5407
- package/dist-cli/forgecad.js.map +1 -0
- package/dist-cli/solver-FV7TJZGI.js +365 -0
- package/dist-cli/solver-FV7TJZGI.js.map +1 -0
- package/dist-skill/CONTEXT.md +3186 -7145
- package/dist-skill/SKILL-dev.md +21 -63
- package/dist-skill/SKILL.md +12 -56
- package/dist-skill/docs/API/core/concepts.md +16 -98
- package/dist-skill/docs/CLI/export.md +91 -0
- package/dist-skill/docs/CLI/projects.md +107 -0
- package/dist-skill/docs/CLI/studio_publishing.md +52 -0
- package/dist-skill/docs/CLI/validation.md +66 -0
- package/dist-skill/docs/generated/assembly.md +691 -112
- package/dist-skill/docs/generated/core.md +464 -1412
- package/dist-skill/docs/generated/curves.md +593 -117
- package/dist-skill/docs/generated/lib.md +38 -748
- package/dist-skill/docs/generated/output.md +139 -245
- package/dist-skill/docs/generated/sheet-metal.md +473 -21
- package/dist-skill/docs/generated/sketch.md +553 -349
- package/dist-skill/docs/generated/viewport.md +345 -303
- package/dist-skill/docs/generated/wood.md +104 -0
- package/dist-skill/docs/guides/coordinate-system.md +11 -17
- package/dist-skill/docs/guides/geometry-conventions.md +13 -70
- package/dist-skill/docs/guides/modeling-recipes.md +22 -195
- package/dist-skill/docs/guides/positioning.md +88 -147
- package/dist-skill/docs-dev/API/core/concepts.md +51 -0
- package/dist-skill/docs-dev/API/core/sdf-advanced.md +92 -0
- package/dist-skill/docs-dev/API/core/sdf-primitives.md +58 -0
- package/dist-skill/docs-dev/API/core/sdf-workflow.md +42 -0
- package/dist-skill/docs-dev/CLI/export.md +91 -0
- package/dist-skill/docs-dev/CLI/projects.md +107 -0
- package/dist-skill/docs-dev/CLI/studio_publishing.md +52 -0
- package/dist-skill/docs-dev/CLI/validation.md +66 -0
- package/dist-skill/{docs → docs-dev}/blueprint-first.md +5 -0
- package/dist-skill/{docs → docs-dev}/coding-best-practices.md +6 -8
- package/dist-skill/{docs → docs-dev}/coding.md +1 -3
- package/dist-skill/docs-dev/generated/assembly.md +771 -0
- package/dist-skill/docs-dev/generated/core.md +775 -0
- package/dist-skill/docs-dev/generated/curves.md +688 -0
- package/dist-skill/docs-dev/generated/lib.md +50 -0
- package/dist-skill/docs-dev/generated/output.md +234 -0
- package/dist-skill/docs-dev/generated/sheet-metal.md +506 -0
- package/dist-skill/docs-dev/generated/sketch.md +801 -0
- package/dist-skill/docs-dev/generated/viewport.md +486 -0
- package/dist-skill/docs-dev/generated/wood.md +104 -0
- package/dist-skill/docs-dev/guides/coordinate-system.md +46 -0
- package/dist-skill/docs-dev/guides/geometry-conventions.md +52 -0
- package/dist-skill/docs-dev/guides/modeling-recipes.md +77 -0
- package/dist-skill/docs-dev/guides/positioning.md +151 -0
- package/dist-skill/{docs → docs-dev}/guides/skill-maintenance.md +21 -10
- package/dist-skill/{docs → docs-dev}/internals/compiler.md +5 -6
- package/dist-skill/{docs → docs-dev}/internals/constraint-solver-quality.md +0 -1
- package/dist-skill/{docs → docs-dev}/internals/constraint-solver.md +0 -1
- package/dist-skill/{docs → docs-dev}/internals/sketch-2d-pipeline.md +2 -3
- package/examples/api/attachTo-basics.forge.js +5 -5
- package/examples/api/boolean-operations.forge.js +3 -3
- package/examples/api/bounding-box-visualizer.forge.js +2 -2
- package/examples/api/clone-duplicate.forge.js +1 -1
- package/examples/api/colors-union-vs-array.forge.js +6 -6
- package/examples/api/connector-assembly.forge.js +4 -4
- package/examples/api/connector-basics.forge.js +2 -2
- package/examples/api/extrude-options.forge.js +4 -10
- package/examples/api/feature-created-faces.forge.js +6 -10
- package/examples/api/fillet-showcase.forge.js +1 -1
- package/examples/api/folded-service-panel-cover.forge.js +2 -2
- package/examples/api/group-test.forge.js +1 -1
- package/examples/api/group-vs-union.forge.js +1 -1
- package/examples/api/highlight-debug.forge.js +4 -0
- package/examples/api/js-module-pillars.js +1 -1
- package/examples/api/js-module-scene.js +2 -2
- package/examples/api/mesh-import-slats.forge.js +1 -1
- package/examples/api/pointAlong-orientation.forge.js +1 -1
- package/examples/api/profile-2020-b-slot6.forge.js +0 -1
- package/examples/api/route-perimeter-flange.forge.js +1 -1
- package/examples/api/sdf-rover-demo.forge.js +10 -10
- package/examples/api/sketch-on-face-demo.forge.js +2 -2
- package/examples/api/sketch-regions.forge.js +4 -4
- package/examples/api/transition-curves.forge.js +1 -1
- package/examples/api/variable-sweep-pure-sdf-test.forge.js +162 -0
- package/examples/api/variable-sweep-test.forge.js +2 -2
- package/examples/api/wood-joinery.forge.js +60 -0
- package/examples/compiler-corpus/enclosure-shell-cuts.forge.js +3 -3
- package/examples/compiler-corpus/fastener-plate-variants.forge.js +2 -2
- package/examples/experiments/drone-arm.forge.js +53 -0
- package/examples/furniture/adjustable-table.forge.js +2 -2
- package/examples/furniture/bathroom.forge.js +11 -11
- package/examples/furniture/chair.forge.js +1 -1
- package/examples/generative/crystal-growth.forge.js +2 -2
- package/examples/generative/frost-spires.forge.js +3 -3
- package/examples/generative/golden-spiral-tower.forge.js +3 -3
- package/examples/mechanical/3d-printer.forge.js +28 -28
- package/examples/mechanical/5-finger-robot-hand.forge.js +15 -15
- package/examples/mechanical/airplane-propeller.forge.js +2 -2
- package/examples/mechanical/fillet-enclosure.forge.js +1 -1
- package/examples/mechanical/headphone-hanger-v2.forge.js +2 -2
- package/examples/mechanical/robot_hand.forge.js +15 -15
- package/examples/mechanical/robot_hand_2.forge.js +9 -9
- package/examples/products/bottle.forge.js +1 -1
- package/examples/products/chess-set.forge.js +19 -19
- package/examples/products/classical-piano.forge.js +11 -11
- package/examples/products/clock.forge.js +12 -12
- package/examples/products/iphone.forge.js +8 -8
- package/examples/products/laptop.forge.js +15 -15
- package/examples/products/liquid-soap-dispenser.forge.js +18 -18
- package/examples/products/origami-fish.forge.js +8 -6
- package/examples/products/spiderman-cake.forge.js +4 -4
- package/examples/toolbox/bolted-joint.forge.js +2 -2
- package/package.json +7 -4
- package/dist/assets/EditorApp-B-vQvgam.js +0 -9888
- package/dist/assets/LandingPage-C5n9hDXI.js +0 -322
- package/dist/assets/PublishedModelPage-Dt7PCVBj.js +0 -146
- package/dist/assets/__vite-browser-external-CURh0WXD.js +0 -8
- package/dist/assets/deserializeRunResult-BLAFoiE0.js +0 -19365
- package/dist/assets/index-1CYp3zUp.js +0 -1455
- package/dist/docs-raw/CLI.md +0 -865
- package/dist-skill/docs/API/API.md +0 -1666
- package/dist-skill/docs/API/README.md +0 -37
- package/dist-skill/docs/API/assembly/assembly.md +0 -617
- package/dist-skill/docs/API/core/edge-queries.md +0 -130
- package/dist-skill/docs/API/core/parameters.md +0 -122
- package/dist-skill/docs/API/core/reserved-terms.md +0 -137
- package/dist-skill/docs/API/core/sdf.md +0 -326
- package/dist-skill/docs/API/core/skill-cli.md +0 -194
- package/dist-skill/docs/API/core/skill-guide.md +0 -205
- package/dist-skill/docs/API/core/specs.md +0 -186
- package/dist-skill/docs/API/core/topology.md +0 -372
- package/dist-skill/docs/API/entities.md +0 -268
- package/dist-skill/docs/API/output/bom.md +0 -58
- package/dist-skill/docs/API/output/brep-export.md +0 -87
- package/dist-skill/docs/API/output/dimensions.md +0 -67
- package/dist-skill/docs/API/output/export.md +0 -110
- package/dist-skill/docs/API/output/gcode.md +0 -195
- package/dist-skill/docs/API/runtime/viewport.md +0 -420
- package/dist-skill/docs/API/sheet-metal/sheet-metal.md +0 -185
- package/dist-skill/docs/API/sketch/anchor.md +0 -37
- package/dist-skill/docs/API/sketch/booleans.md +0 -91
- package/dist-skill/docs/API/sketch/core.md +0 -73
- package/dist-skill/docs/API/sketch/extrude.md +0 -62
- package/dist-skill/docs/API/sketch/on-face.md +0 -104
- package/dist-skill/docs/API/sketch/operations.md +0 -78
- package/dist-skill/docs/API/sketch/path.md +0 -75
- package/dist-skill/docs/API/sketch/primitives.md +0 -146
- package/dist-skill/docs/API/sketch/regions.md +0 -80
- package/dist-skill/docs/API/sketch/text.md +0 -108
- package/dist-skill/docs/API/sketch/transforms.md +0 -65
- package/dist-skill/docs/API/toolbox/fasteners.md +0 -129
- package/dist-skill/docs/CLI.md +0 -865
- package/dist-skill/docs/INDEX.md +0 -94
- package/dist-skill/docs/RELEASING.md +0 -55
- package/dist-skill/docs/cli-monetization.md +0 -111
- package/dist-skill/docs/deployment.md +0 -281
- package/dist-skill/docs/generated/concepts.md +0 -2112
- package/dist-skill/docs/internals/shape-from-slices.md +0 -152
- package/dist-skill/docs/platform/admin.md +0 -45
- package/dist-skill/docs/platform/architecture.md +0 -79
- package/dist-skill/docs/platform/auth.md +0 -110
- package/dist-skill/docs/platform/email.md +0 -67
- package/dist-skill/docs/platform/projects.md +0 -111
- package/dist-skill/docs/platform/sharing.md +0 -90
- package/dist-skill/docs/runbook.md +0 -345
|
@@ -1,205 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
skill-group: core
|
|
3
|
-
skill-order: 0
|
|
4
|
-
skill-tiers: [one-file]
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# ForgeCAD Skill Guide — Concepts & Patterns
|
|
8
|
-
|
|
9
|
-
Conceptual knowledge that complements the auto-generated API index. The API index covers every function signature; this file covers the patterns, gotchas, and composition strategies that signatures alone cannot convey.
|
|
10
|
-
|
|
11
|
-
## Core Concepts
|
|
12
|
-
|
|
13
|
-
ForgeCAD scripts are JavaScript code that returns geometry. The forge API is globally available — no imports needed.
|
|
14
|
-
|
|
15
|
-
### Basic Structure
|
|
16
|
-
```javascript
|
|
17
|
-
const width = param("Width", 50, { min: 20, max: 100, unit: "mm" });
|
|
18
|
-
const shape = box(width, 30, 10);
|
|
19
|
-
return shape;
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
### Execution Model
|
|
23
|
-
- Scripts execute on every parameter change (400ms debounce)
|
|
24
|
-
- All operations are **immutable** — they return new shapes, never modify in place
|
|
25
|
-
- Must return one of:
|
|
26
|
-
- A `Shape` (3D solid)
|
|
27
|
-
- A `Sketch` (2D profile — rendered flat on XY plane)
|
|
28
|
-
- A `TrackedShape` (3D solid with named faces/edges — auto-unwrapped)
|
|
29
|
-
- A `ShapeGroup` (multiple shapes/sketches grouped for joint transforms)
|
|
30
|
-
- An `Array` of shapes/sketches/groups (multi-object scene)
|
|
31
|
-
- An `Array` of `{ name, shape?, sketch?, color? }` objects (named multi-object scene)
|
|
32
|
-
|
|
33
|
-
### Unions Remove Colors
|
|
34
|
-
|
|
35
|
-
`union()` merges into a single solid — individual colors are lost. Return an array of named objects instead:
|
|
36
|
-
|
|
37
|
-
```javascript
|
|
38
|
-
// BAD: colors lost after union
|
|
39
|
-
return union(red, blue);
|
|
40
|
-
|
|
41
|
-
// GOOD: each object keeps its color
|
|
42
|
-
return [
|
|
43
|
-
{ name: "Red Box", shape: red, color: '#ff0000' },
|
|
44
|
-
{ name: "Blue Box", shape: blue, color: '#0066ff' },
|
|
45
|
-
];
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
### Coordinate System
|
|
49
|
-
Z-up right-handed: X = left/right, Y = forward/back, Z = up/down.
|
|
50
|
-
|
|
51
|
-
## Returning Multiple Objects
|
|
52
|
-
|
|
53
|
-
```javascript
|
|
54
|
-
return [
|
|
55
|
-
{ name: "Base", shape: box(100, 100, 5), color: "#888888" },
|
|
56
|
-
{ name: "Column", shape: cylinder(50, 10).translate(50, 50, 5), color: "#4488cc" },
|
|
57
|
-
];
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
Each object must have `name` (string) and `shape` or `sketch`. Optional `color` sets display color.
|
|
61
|
-
|
|
62
|
-
## Positioning & Connectors
|
|
63
|
-
|
|
64
|
-
### Connectors + `.matchTo()` — Primary positioning method
|
|
65
|
-
|
|
66
|
-
Define named connectors on parts, then use `matchTo()` for automatic alignment. Connectors are stable (don't shift with geometry changes), semantic (typed and gendered), and oriented (full coordinate frame).
|
|
67
|
-
|
|
68
|
-
```javascript
|
|
69
|
-
const bracket = box(40, 10, 60, true).withConnectors({
|
|
70
|
-
mount: connector.male("bolt", { origin: [0, -5, 0], axis: [0, -1, 0] }),
|
|
71
|
-
});
|
|
72
|
-
const wall = box(200, 5, 200, true).withConnectors({
|
|
73
|
-
slot: connector.female("bolt", { origin: [50, 2.5, 30], axis: [0, 1, 0] }),
|
|
74
|
-
});
|
|
75
|
-
const placed = bracket.matchTo(wall, "mount", "slot");
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
Query connector distances to derive dimensions:
|
|
79
|
-
```javascript
|
|
80
|
-
const pipeLen = frame.connectorDistance('inlet', 'outlet');
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
### `.attachTo()` — Quick bounding-box positioning
|
|
84
|
-
|
|
85
|
-
For simple stacking where connectors aren't needed. Uses bounding-box anchors — fast but fragile.
|
|
86
|
-
|
|
87
|
-
```javascript
|
|
88
|
-
const column = cylinder(50, 8).attachTo(base, 'top', 'bottom');
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
### `.onFace(parent, face, opts?)`
|
|
92
|
-
|
|
93
|
-
Place a shape on a specific face of a parent. Face-local coordinates: `u`/`v` offset from center, `protrude` outward.
|
|
94
|
-
|
|
95
|
-
```javascript
|
|
96
|
-
const vent = box(80, 2, 12, true)
|
|
97
|
-
.onFace(body, 'front', { v: -15, protrude: 2 });
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
**When to use:** `onFace()` for surface details (vents, displays). Connectors for assembly interfaces. `attachTo()` for quick prototyping.
|
|
101
|
-
|
|
102
|
-
## Multi-File Projects
|
|
103
|
-
|
|
104
|
-
### File Types
|
|
105
|
-
- `.forge.js` — parametric part/assembly script
|
|
106
|
-
- `.forge-notebook.json` — multi-cell notebook
|
|
107
|
-
- `.svg` — vector artwork, imported as sketch geometry
|
|
108
|
-
|
|
109
|
-
### Import Function
|
|
110
|
-
|
|
111
|
-
Use `require(path, paramOverrides?)` to import any `.forge.js` file. The second argument is optional param overrides.
|
|
112
|
-
|
|
113
|
-
```javascript
|
|
114
|
-
const bracket = require("./bracket.forge.js");
|
|
115
|
-
const bracket2 = require("./bracket.forge.js", { Width: 100, Thickness: 3 });
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
The return value matches what the imported file exports:
|
|
119
|
-
- File `return`s a `Shape` → you get a `Shape`
|
|
120
|
-
- File `return`s an `Assembly` → you get an `ImportedAssembly`
|
|
121
|
-
- File `return`s a `ShapeGroup` → you get a `ShapeGroup`
|
|
122
|
-
- File uses `exports.name = value` → you get an object with named properties
|
|
123
|
-
|
|
124
|
-
Use `importSvgSketch()` for SVG files (separate function — SVG is a file format loader, not a module import).
|
|
125
|
-
|
|
126
|
-
### Import Rules
|
|
127
|
-
- Paths: `./file.forge.js` resolves relative to caller; bare paths resolve from project root
|
|
128
|
-
- Param overrides only affect that import call
|
|
129
|
-
- Circular imports throw an error
|
|
130
|
-
- Each import call is a fresh execution
|
|
131
|
-
|
|
132
|
-
### Placement References
|
|
133
|
-
|
|
134
|
-
Attach named reference points/edges/surfaces to shapes for precise cross-file positioning:
|
|
135
|
-
|
|
136
|
-
```javascript
|
|
137
|
-
// In part file:
|
|
138
|
-
return union(base, post).withReferences({
|
|
139
|
-
points: { mount: [0, -16, -4] },
|
|
140
|
-
surfaces: { mountingFace: { center: [0, -16, 0], normal: [0, -1, 0] } },
|
|
141
|
-
objects: { base, post },
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
// In assembly file:
|
|
145
|
-
const widget = require("./widget.forge.js")
|
|
146
|
-
.placeReference("mount", [120, 40, 0]);
|
|
147
|
-
const cap = box(18, 18, 8, true)
|
|
148
|
-
.attachTo(widget, "objects.post.top", "bottom");
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
References survive transforms and import round-trips.
|
|
152
|
-
|
|
153
|
-
### Plain JS Module Imports
|
|
154
|
-
|
|
155
|
-
Regular `import`/`require()` works for utility modules. Don't mix explicit exports with top-level `return` in the same module.
|
|
156
|
-
|
|
157
|
-
### Typical Project Structure
|
|
158
|
-
```
|
|
159
|
-
my-project/
|
|
160
|
-
├── base-profile.forge.js ← 2D cross-section (returns Sketch)
|
|
161
|
-
├── bracket.forge.js ← extrudes the sketch, adds holes
|
|
162
|
-
└── assembly.forge.js ← imports multiple parts, positions them
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
## Compiler-Owned Operations
|
|
166
|
-
|
|
167
|
-
### `shape.shell(thickness, options?)`
|
|
168
|
-
Hollows out a solid. Supports `box()`, `cylinder()`, straight `extrude()`. Optional `openFaces: ['top' | 'bottom']`.
|
|
169
|
-
|
|
170
|
-
```javascript
|
|
171
|
-
const cup = roundedRect(80, 50, 6, true)
|
|
172
|
-
.extrude(30).shell(2.5, { openFaces: ['top'] });
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
### `shape.hole(face, options)`
|
|
176
|
-
Circular hole anchored to a face. `depth` omitted = through-hole. Supports `counterbore`/`countersink`, `upToFace`, two-sided `extent`.
|
|
177
|
-
|
|
178
|
-
```javascript
|
|
179
|
-
const body = block
|
|
180
|
-
.hole('front', { diameter: 8, u: 0, v: 2 })
|
|
181
|
-
.hole('top', { diameter: 6, u: -18, v: 10, depth: 10 })
|
|
182
|
-
.hole('top', { diameter: 5, u: 18, v: 10, upToFace: exitFace,
|
|
183
|
-
counterbore: { diameter: 9, depth: 4 } });
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
### `shape.cutout(sketch, options?)`
|
|
187
|
-
Cut-extrude using a sketch placed with `Sketch.onFace(...)`. Same extent options as `hole()`. Supports `taperScale` on circle/rect/roundedRect profiles.
|
|
188
|
-
|
|
189
|
-
### `sheetMetal(options)`
|
|
190
|
-
Sheet-metal builder: base panel → `.flange()` → `.cutout()` → `.folded()` or `.flatPattern()`.
|
|
191
|
-
|
|
192
|
-
## Group Patterns
|
|
193
|
-
|
|
194
|
-
`group()` combines shapes without merging — colors and identities preserved.
|
|
195
|
-
|
|
196
|
-
```javascript
|
|
197
|
-
const housing = group(
|
|
198
|
-
{ name: 'Shell', shape: shell },
|
|
199
|
-
{ name: 'Lid', shape: lid },
|
|
200
|
-
).withReferences({
|
|
201
|
-
points: { mountCenter: [0, 30, 20] },
|
|
202
|
-
});
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
ShapeGroup supports all transforms, placement references, and child access (`.child("Name")`).
|
|
@@ -1,186 +0,0 @@
|
|
|
1
|
-
# Specs — Named Requirement Bundles
|
|
2
|
-
|
|
3
|
-
A **Spec** is a named, reusable group of `verify.*` checks. When you call `spec.check(shape)`, every `verify` call inside the check function is tagged with the spec name and displayed as a collapsible section in the Checks panel.
|
|
4
|
-
|
|
5
|
-
## Why Specs
|
|
6
|
-
|
|
7
|
-
Bare `verify.*` calls produce a flat list. With 15 checks across 3 different concerns, the panel becomes hard to scan. Specs add structure:
|
|
8
|
-
|
|
9
|
-
- **Grouping** — related checks appear under a named, collapsible header
|
|
10
|
-
- **Reusability** — one spec, applied to many shapes: `printable.check(bracket); printable.check(standoff);`
|
|
11
|
-
- **Composability** — combine independent specs: check fit, strength, and printability separately
|
|
12
|
-
- **Separation** — define what "good" looks like before building geometry (spec-first / TDD workflow)
|
|
13
|
-
|
|
14
|
-
## Quick Start
|
|
15
|
-
|
|
16
|
-
```javascript
|
|
17
|
-
// Define a spec
|
|
18
|
-
const printable = spec("Fits printer bed", (shape) => {
|
|
19
|
-
verify.notEmpty("Has geometry", shape);
|
|
20
|
-
const bb = shape.boundingBox();
|
|
21
|
-
const size = [bb.max[0] - bb.min[0], bb.max[1] - bb.min[1], bb.max[2] - bb.min[2]];
|
|
22
|
-
verify.lessThan("Width < 220mm", size[0], 220);
|
|
23
|
-
verify.lessThan("Depth < 220mm", size[1], 220);
|
|
24
|
-
verify.lessThan("Height < 250mm", size[2], 250);
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
// Build something
|
|
28
|
-
const part = box(100, 80, 40);
|
|
29
|
-
|
|
30
|
-
// Check it
|
|
31
|
-
printable.check(part);
|
|
32
|
-
|
|
33
|
-
return part;
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
The Checks panel shows:
|
|
37
|
-
|
|
38
|
-
```
|
|
39
|
-
▼ ✓ Fits printer bed — 4/4
|
|
40
|
-
✓ Has geometry
|
|
41
|
-
✓ Width < 220mm
|
|
42
|
-
✓ Depth < 220mm
|
|
43
|
-
✓ Height < 250mm
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
## API
|
|
47
|
-
|
|
48
|
-
### `spec(name, checkFn)`
|
|
49
|
-
|
|
50
|
-
Create a named spec.
|
|
51
|
-
|
|
52
|
-
| Parameter | Type | Description |
|
|
53
|
-
|-----------|------|-------------|
|
|
54
|
-
| `name` | `string` | Display name in the Checks panel |
|
|
55
|
-
| `checkFn` | `(...args) => void` | Function that calls `verify.*` methods |
|
|
56
|
-
|
|
57
|
-
Returns a `Spec` object with a `.check()` method.
|
|
58
|
-
|
|
59
|
-
### `Spec.check(...args)`
|
|
60
|
-
|
|
61
|
-
Run the spec's check function. Any `verify.*` calls inside are grouped under the spec name.
|
|
62
|
-
|
|
63
|
-
Returns a `SpecResult`:
|
|
64
|
-
|
|
65
|
-
```typescript
|
|
66
|
-
interface SpecResult {
|
|
67
|
-
name: string; // Spec name
|
|
68
|
-
passed: number; // Checks that passed
|
|
69
|
-
total: number; // Total checks
|
|
70
|
-
results: VerificationResult[];
|
|
71
|
-
}
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
The return value is optional — you can ignore it and just let the Checks panel show the results.
|
|
75
|
-
|
|
76
|
-
## Patterns
|
|
77
|
-
|
|
78
|
-
### Reusable Spec — Apply to Multiple Shapes
|
|
79
|
-
|
|
80
|
-
```javascript
|
|
81
|
-
const structural = spec("Structural", (shape) => {
|
|
82
|
-
verify.greaterThan("Min volume", shape.volume(), 500);
|
|
83
|
-
verify.notEmpty("Not degenerate", shape);
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
structural.check(bracket);
|
|
87
|
-
structural.check(plate);
|
|
88
|
-
structural.check(standoff);
|
|
89
|
-
// Each call adds a "Structural" group to the panel
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
### Multi-Shape Spec — Check Relationships
|
|
93
|
-
|
|
94
|
-
Specs can accept multiple arguments for checking relationships between parts:
|
|
95
|
-
|
|
96
|
-
```javascript
|
|
97
|
-
const fitSpec = spec("Assembly fit", (partA, partB) => {
|
|
98
|
-
verify.notColliding("No interference", partA, partB, 10);
|
|
99
|
-
verify.minClearance("Min gap 0.3mm", partA, partB, 0.3, 10);
|
|
100
|
-
verify.parallel("Mating faces aligned",
|
|
101
|
-
partA.face('top'), partB.face('bottom'));
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
fitSpec.check(bracket, standoff);
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
### Importable Spec Library
|
|
108
|
-
|
|
109
|
-
Specs can live in separate `.forge.js` files and be imported via `require()`:
|
|
110
|
-
|
|
111
|
-
```javascript
|
|
112
|
-
// specs/printers.forge.js
|
|
113
|
-
const prusaMK3S = spec("Prusa MK3S", (shape) => {
|
|
114
|
-
const bb = shape.boundingBox();
|
|
115
|
-
const size = [bb.max[0]-bb.min[0], bb.max[1]-bb.min[1], bb.max[2]-bb.min[2]];
|
|
116
|
-
verify.lessThan("X", size[0], 220);
|
|
117
|
-
verify.lessThan("Y", size[1], 220);
|
|
118
|
-
verify.lessThan("Z", size[2], 250);
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
return { prusaMK3S };
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
```javascript
|
|
125
|
-
// my-part.forge.js
|
|
126
|
-
const { prusaMK3S } = require("./specs/printers.forge.js");
|
|
127
|
-
const part = box(100, 80, 40);
|
|
128
|
-
prusaMK3S.check(part);
|
|
129
|
-
return part;
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
### Reference Geometry in Specs
|
|
133
|
-
|
|
134
|
-
Specs can create shapes internally as test fixtures — these are used only for checking and never rendered:
|
|
135
|
-
|
|
136
|
-
```javascript
|
|
137
|
-
const fitsInEnclosure = spec("Fits in enclosure", (shape) => {
|
|
138
|
-
// Reference geometry — not returned, not rendered
|
|
139
|
-
const enclosure = box(200, 150, 100);
|
|
140
|
-
const overlap = shape.intersect(enclosure);
|
|
141
|
-
|
|
142
|
-
verify.that("Fully contained", () =>
|
|
143
|
-
Math.abs(overlap.volume() - shape.volume()) < 1
|
|
144
|
-
);
|
|
145
|
-
verify.minClearance("2mm clearance", shape, enclosure, 2.0, 20);
|
|
146
|
-
});
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
### Spec-First Workflow (TDD for CAD)
|
|
150
|
-
|
|
151
|
-
Write specs before geometry. Watch checks go from red to green as you build:
|
|
152
|
-
|
|
153
|
-
```javascript
|
|
154
|
-
// Step 1: Define what we need
|
|
155
|
-
const caseSpec = spec("Phone case", (shape) => {
|
|
156
|
-
verify.notEmpty("Has geometry", shape);
|
|
157
|
-
verify.that("Is hollow (< 40% fill)", () => {
|
|
158
|
-
const bb = shape.boundingBox();
|
|
159
|
-
const bboxVol = (bb.max[0]-bb.min[0]) * (bb.max[1]-bb.min[1]) * (bb.max[2]-bb.min[2]);
|
|
160
|
-
return shape.volume() < bboxVol * 0.4;
|
|
161
|
-
});
|
|
162
|
-
verify.greaterThan("Weighs under 30g (PLA)", 30, shape.volume() * 0.00124);
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
// Step 2: Build iteratively — specs tell you when you're done
|
|
166
|
-
const myCase = box(75, 150, 12).shell(2, { openFaces: ['top'] });
|
|
167
|
-
caseSpec.check(myCase);
|
|
168
|
-
return myCase;
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
## Mixing Specs and Plain Verify Calls
|
|
172
|
-
|
|
173
|
-
Plain `verify.*` calls (outside any spec) still work. They appear ungrouped below the spec sections:
|
|
174
|
-
|
|
175
|
-
```javascript
|
|
176
|
-
// Grouped under spec name
|
|
177
|
-
printable.check(part);
|
|
178
|
-
|
|
179
|
-
// Ungrouped — shown separately
|
|
180
|
-
verify.greaterThan("Custom check", someValue, 10);
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
## See Also
|
|
184
|
-
|
|
185
|
-
- **[Verification demo](../../../examples/api/verification-demo.forge.js)** — all `verify.*` methods
|
|
186
|
-
- **[Spec demo](../../../examples/api/spec-demo.forge.js)** — `spec()` in action
|