forgecad 0.10.5 → 0.11.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/dist/assets/{AdminPage-raksfnNA.js → AdminPage-B1nIvqLS.js} +1 -1
- package/dist/assets/{BenchmarkPage-DP3RxhPs.js → BenchmarkPage-YZJbw5nd.js} +1 -1
- package/dist/assets/{BlogPage-D7Dos-vl.js → BlogPage-DIWRApKS.js} +1 -1
- package/dist/assets/{DocsPage-DO1kvBns.js → DocsPage-ClL6X1hR.js} +2 -22
- package/dist/assets/{EditorApp-DQJmcmRT.js → EditorApp-CYBDvSyT.js} +575 -119
- package/dist/assets/{EmbedViewer-DFDUhOma.js → EmbedViewer-Dmfu_LIw.js} +2 -2
- package/dist/assets/{LandingPageProofDriven-DbE_tp8-.js → LandingPageProofDriven-XYTiYxfM.js} +1 -1
- package/dist/assets/{LegalPage-CominSso.js → LegalPage-D5Z3CscF.js} +1 -1
- package/dist/assets/{PricingPage-CcVIN9yj.js → PricingPage-BP4lIGio.js} +1 -1
- package/dist/assets/{SettingsPage-DLWcP289.js → SettingsPage-D3bcPBsC.js} +1 -1
- package/dist/assets/{app-xW3hOdq9.js → app-BKjogwIZ.js} +2192 -231
- package/dist/assets/{backendInit-mDHk97u7.js → backendInit-6a9-ilom.js} +76448 -75066
- package/dist/assets/cli/{render--SIU27W_.js → render-CMNudGb0.js} +3 -3
- package/dist/assets/{constructionHistoryWorker-uEe_Q7Kg.js → constructionHistoryWorker-BuZgc606.js} +6985 -6706
- package/dist/assets/{evalWorker-BqyDHDcI.js → evalWorker-DQ82ueGu.js} +40862 -39497
- package/dist/assets/{inspectWorker-UXMxlcR8.js → inspectWorker-Cuby2qfT.js} +2078 -478
- package/dist/assets/{jointPose-bYMlwU3v.js → jointPose-CFql5I-u.js} +1 -1
- package/dist/assets/{manifold-CyOV5B9S.js → manifold-02pmr7O7.js} +2 -2
- package/dist/assets/{manifold-BR7UYI4P.js → manifold-C6KU0oII.js} +1 -1
- package/dist/assets/{manifold-D4d5NQst.js → manifold-P1yF3GKn.js} +1 -1
- package/dist/assets/{reportWorker-DsaICZsn.js → reportWorker-kg065BVL.js} +85183 -78309
- package/dist/cli/render.html +1 -1
- package/dist/docs/index.html +2 -2
- package/dist/docs-raw/AI/usage.md +6 -8
- package/dist/docs-raw/CLI.md +10 -10
- package/dist/docs-raw/component-model.md +28 -9
- package/dist/docs-raw/generated/concepts.md +13 -4
- package/dist/docs-raw/generated/core.md +244 -56
- package/dist/docs-raw/generated/curves.md +13 -0
- package/dist/docs-raw/generated/runtime-names.md +2 -2
- package/dist/docs-raw/guides/inspection-bundles.md +1 -1
- package/dist/docs-raw/guides/structural-fea.md +11 -0
- package/dist/docs-raw/skills/forgecad-build-model.md +70 -147
- package/dist/docs-raw/skills/forgecad-image-prompt.md +1 -1
- package/dist/docs-raw/skills/forgecad-project-sync.md +3 -3
- package/dist/docs-raw/skills/forgecad-reconstruct-cad-file.md +2 -2
- package/dist/docs-raw/skills/forgecad-reconstruct-from-images.md +4 -5
- package/dist/docs-raw/skills/forgecad.md +3 -1
- package/dist/docs-raw/skills/index.md +1 -5
- package/dist/docs-raw/welcome.md +3 -4
- package/dist/index.html +1 -1
- package/dist/llms.txt +1 -2
- package/dist/sitemap.xml +15 -15
- package/dist-cli/{check-compiler-7YAHVXYM.js → check-compiler-UJWUEIDC.js} +1 -1
- package/dist-cli/{check-query-propagation-ZRR6IOJW.js → check-query-propagation-O2EPDJSY.js} +1 -1
- package/dist-cli/{chunk-VNM67DIV.js → chunk-MNDROM7T.js} +77145 -75767
- package/dist-cli/forgecad.js +1145 -441
- package/dist-skill/CONTEXT.md +429 -64
- package/dist-skill/SKILL.md +3 -1
- package/dist-skill/docs/API/core/concepts.md +31 -4
- package/dist-skill/docs/CLI.md +10 -10
- package/dist-skill/docs/generated/core.md +240 -57
- package/dist-skill/docs/generated/curves.md +13 -0
- package/dist-skill/docs/generated/runtime-names.md +2 -2
- package/dist-skill/docs/guides/inspection-bundles.md +1 -1
- package/dist-skill/docs/guides/manual-parameters.md +130 -0
- package/dist-skill/docs/guides/structural-fea.md +11 -0
- package/dist-skill/library/README.md +0 -4
- package/dist-skill/library/forgecad-build-model/SKILL.md +57 -150
- package/dist-skill/library/forgecad-build-model/references/inspection-feedback.md +58 -0
- package/dist-skill/library/forgecad-build-model/references/module-contracts.md +53 -0
- package/dist-skill/library/forgecad-build-model/references/parameter-controls.md +22 -0
- package/dist-skill/library/forgecad-build-model/references/readiness-review.md +43 -0
- package/dist-skill/library/forgecad-build-model/references/simulation-feedback.md +49 -0
- package/dist-skill/library/forgecad-build-model/references/stage-1-design-intent.md +21 -0
- package/dist-skill/library/forgecad-build-model/references/stage-2-architecture-plan.md +23 -0
- package/dist-skill/library/forgecad-build-model/references/stage-3-build-slices.md +39 -0
- package/dist-skill/library/forgecad-build-model/references/stage-4-feedback-iteration.md +24 -0
- package/dist-skill/library/forgecad-build-model/references/stage-5-readiness-package.md +34 -0
- package/dist-skill/library/forgecad-image-prompt/SKILL.md +1 -1
- package/dist-skill/library/forgecad-project-sync/SKILL.md +3 -3
- package/dist-skill/library/forgecad-reconstruct-cad-file/SKILL.md +2 -2
- package/dist-skill/library/forgecad-reconstruct-from-images/SKILL.md +4 -5
- package/dist-skill/website/skills/forgecad-build-model.md +70 -147
- package/dist-skill/website/skills/forgecad-image-prompt.md +1 -1
- package/dist-skill/website/skills/forgecad-project-sync.md +3 -3
- package/dist-skill/website/skills/forgecad-reconstruct-cad-file.md +2 -2
- package/dist-skill/website/skills/forgecad-reconstruct-from-images.md +4 -5
- package/dist-skill/website/skills/forgecad.md +3 -1
- package/dist-skill/website/skills/index.md +1 -5
- package/examples/api/param-path2d.forge.js +65 -0
- package/examples/api/param-placement2d.forge.js +80 -0
- package/examples/api/param-spline2d-g-continuity.forge.js +57 -0
- package/examples/api/spoon-full-tang-handle.forge.js +57 -17
- package/examples/api/surface-variable-thickness-panel.forge.js +62 -0
- package/examples/mechanical/airplane-propeller.forge.js +81 -28
- package/package.json +2 -2
- package/dist/docs-raw/skills/forgecad-design-spec.md +0 -145
- package/dist/docs-raw/skills/forgecad-grade-model.md +0 -84
- package/dist/docs-raw/skills/forgecad-inspect-model.md +0 -80
- package/dist/docs-raw/skills/forgecad-verify-mujoco.md +0 -78
- package/dist-skill/library/forgecad-design-spec/SKILL.md +0 -132
- package/dist-skill/library/forgecad-design-spec/references/default-profiles.md +0 -99
- package/dist-skill/library/forgecad-design-spec/references/master-prompt.md +0 -73
- package/dist-skill/library/forgecad-grade-model/SKILL.md +0 -72
- package/dist-skill/library/forgecad-grade-model/agents/openai.yaml +0 -4
- package/dist-skill/library/forgecad-inspect-model/SKILL.md +0 -68
- package/dist-skill/library/forgecad-verify-mujoco/SKILL.md +0 -66
- package/dist-skill/website/skills/forgecad-design-spec.md +0 -145
- package/dist-skill/website/skills/forgecad-grade-model.md +0 -84
- package/dist-skill/website/skills/forgecad-inspect-model.md +0 -80
- package/dist-skill/website/skills/forgecad-verify-mujoco.md +0 -78
- /package/dist-skill/library/{forgecad-verify-mujoco → forgecad-build-model}/scripts/mujoco_verify.py +0 -0
- /package/dist-skill/library/{forgecad-inspect-model → forgecad-build-model/scripts}/summarize_manifest.py +0 -0
package/dist-skill/SKILL.md
CHANGED
|
@@ -23,7 +23,8 @@ Author or modify ForgeCAD models, sketches, assemblies, and CLI workflows. Prefe
|
|
|
23
23
|
|
|
24
24
|
### Import and Composition
|
|
25
25
|
|
|
26
|
-
- Always include the extension in relative imports: `require("./file.forge.js"
|
|
26
|
+
- Always include the extension in relative imports: `require("./file.forge.js")` for model files, `require("./helpers.js")` for plain helper modules. Extensionless imports such as `require("./file")` do not resolve; ForgeCAD resolves project imports by exact path.
|
|
27
|
+
- Reusable `.forge.js` part files should return builder functions such as `return { buildPart }`; direct-run preview params belong inside `if (require.main === module)`.
|
|
27
28
|
- ForgeCAD APIs are injected globals in `.forge.js` files. Use `bom()`, `box()`, `scene()`, `Shape`, etc. directly; never destructure those names from helpers (`const { bom } = require("./bom.js")`). Import helper files under a project-specific name such as `const bomHelpers = require("./bom.js")`.
|
|
28
29
|
- For static multi-part models, connectors + `matchTo()` are the default way to assemble touching parts.
|
|
29
30
|
- Top-level scripts can return `Assembly` or `SolvedAssembly` directly. Do not call `.toGroup()` just to render an assembly; use it only when you need `ShapeGroup` composition, transforms, or named-child lookup.
|
|
@@ -41,6 +42,7 @@ Execution model, colors, coordinate system, primitives, booleans, patterns, impo
|
|
|
41
42
|
|
|
42
43
|
- `{{SKILL_DIR}}/docs/API/core/concepts.md`
|
|
43
44
|
- `{{SKILL_DIR}}/docs/generated/runtime-names.md`
|
|
45
|
+
- `{{SKILL_DIR}}/docs/guides/manual-parameters.md`
|
|
44
46
|
- `{{SKILL_DIR}}/docs/generated/core.md`
|
|
45
47
|
|
|
46
48
|
### 2. Static Assembly and Positioning (for any multi-part model)
|
|
@@ -11,10 +11,10 @@ A `.forge.js` script is plain JavaScript that returns geometry. The entire forge
|
|
|
11
11
|
|
|
12
12
|
All geometry operations are **immutable** — shapes, sketches, groups, assemblies, and boards return new values, never mutate in place.
|
|
13
13
|
|
|
14
|
-
A script
|
|
14
|
+
A script should return one of three shapes:
|
|
15
15
|
|
|
16
16
|
1. **A single renderable** — `Shape`, `Sketch`, `ShapeGroup`, `Assembly`, `SolvedAssembly`, or `SdfShape`.
|
|
17
|
-
2. **An array** of renderables or named descriptors `{ name, tags?, shape | sketch | group, color? }
|
|
17
|
+
2. **An array** of renderables or named descriptors `{ name, tags?, shape | sketch | group, color? }`, usually for direct-run previews and multi-object display:
|
|
18
18
|
|
|
19
19
|
```javascript
|
|
20
20
|
return [
|
|
@@ -23,11 +23,38 @@ A script must return one of three shapes:
|
|
|
23
23
|
];
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
3. **A
|
|
26
|
+
3. **A module interface object** — usually builder functions, optionally a built shape plus interface data:
|
|
27
|
+
|
|
28
|
+
```javascript
|
|
29
|
+
return { buildBracket };
|
|
30
|
+
// or, when the file's useful output is already built:
|
|
31
|
+
return { shape, connectors, boltPattern };
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
For reusable part files, prefer a builder export and keep direct-run preview controls inside the entry guard:
|
|
35
|
+
|
|
36
|
+
```javascript
|
|
37
|
+
function buildThing(props) {
|
|
38
|
+
return box(props.width, props.depth, props.height);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (require.main === module) {
|
|
42
|
+
const previewProps = {
|
|
43
|
+
width: param("Width", 80),
|
|
44
|
+
depth: param("Depth", 40),
|
|
45
|
+
height: param("Height", 12),
|
|
46
|
+
};
|
|
47
|
+
return buildThing(previewProps);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return { buildThing };
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
When a plain object is returned directly, renderable values are shown in the viewport and non-renderable values are available to importers through `require()`.
|
|
27
54
|
|
|
28
55
|
Return an unsolved `Assembly` directly — ForgeCAD solves it at default joint values for display. Use `assembly.solve(state)` for a specific pose. Never call `.toGroup()` just to make an assembly render; use it only when you need `ShapeGroup` composition or named-child lookup.
|
|
29
56
|
|
|
30
|
-
For multi-file projects
|
|
57
|
+
For multi-file projects, import path rules, and reusable builder modules, see the [`require()` docs](../../generated/core.md).
|
|
31
58
|
|
|
32
59
|
## Identity
|
|
33
60
|
|
package/dist-skill/docs/CLI.md
CHANGED
|
@@ -13,8 +13,7 @@ Create projects, open local studios, run, inspect, export, publish, and sync `.f
|
|
|
13
13
|
# 1. Install
|
|
14
14
|
npm install -g forgecad
|
|
15
15
|
|
|
16
|
-
# 2.
|
|
17
|
-
forgecad login
|
|
16
|
+
# 2. Create a dedicated local project folder
|
|
18
17
|
mkdir spool-adapter
|
|
19
18
|
cd spool-adapter
|
|
20
19
|
forgecad project init "Spool Adapter" --visibility private
|
|
@@ -25,14 +24,15 @@ forgecad new adapter --template part
|
|
|
25
24
|
# 4. Open the local editor
|
|
26
25
|
forgecad studio .
|
|
27
26
|
|
|
28
|
-
# 5. Validate, export, and push to the browser
|
|
27
|
+
# 5. Validate, export, sign in, and push to the browser
|
|
29
28
|
forgecad run adapter.forge.js
|
|
30
29
|
forgecad export stl adapter.forge.js
|
|
30
|
+
forgecad login
|
|
31
31
|
forgecad project push
|
|
32
32
|
forgecad project open
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
-
Local modeling, inspection, export, and skill-install commands do not require a ForgeCAD account. Hosted project sync, publishing, token management, and license activation require sign-in: run `forgecad login` and choose email/password or API token (for GitHub/Google accounts, create a token in Settings > API Tokens first). Use `FORGECAD_TOKEN=fc_pat_... forgecad <hosted-command>` only for CI/CD and one-off automation. `forgecad studio` always requires an explicit project path; use `.` for the current project.
|
|
35
|
+
Local modeling, project initialization, inspection, export, and skill-install commands do not require a ForgeCAD account. Hosted project sync, publishing, token management, and license activation require sign-in: run `forgecad login` and choose email/password or API token (for GitHub/Google accounts, create a token in Settings > API Tokens first). Use `FORGECAD_TOKEN=fc_pat_... forgecad <hosted-command>` only for CI/CD and one-off automation. `forgecad studio` always requires an explicit project path; use `.` for the current project.
|
|
36
36
|
|
|
37
37
|
You can also start from the hosted starter project with `forgecad project clone start-here`, then `cd start-here` and `forgecad studio .`.
|
|
38
38
|
|
|
@@ -74,7 +74,7 @@ The fast validation command: runs the script with the real geometry kernel (no b
|
|
|
74
74
|
|
|
75
75
|
A bare `forgecad run` skips expensive diagnostics. Opt in with `--details` (volumes/bounds), `--history` (construction tree), `--features` (feature tallies), `--solver-profile` (constraint solver timing), or `--connectivity` (physical connected components — bbox contact is evidence, exact geometry is checked by default). `--quality live|default|high` selects the same geometry quality profile as the editor and export tools; `live` is fastest for large models.
|
|
76
76
|
|
|
77
|
-
Direct `.stl`/`.obj`/`.3mf`/`.step`/`.stp` inputs are imported automatically; STEP/STP auto-selects OCCT unless you pass `--backend`. For deeper confidence gates, prefer `inspect mechanical-integrity`, `check print`, or `inspect fit interference` instead of turning `run` into a catch-all audit command.
|
|
77
|
+
Direct `.stl`/`.obj`/`.3mf`/`.step`/`.stp` inputs are imported automatically; STEP/STP auto-selects OCCT unless you pass `--backend`. Use `--project-root <dir>` when running a file inside a larger uninitialized folder and you intentionally want relative imports to resolve against that root. For deeper confidence gates, prefer `inspect mechanical-integrity`, `check print`, or `inspect fit interference` instead of turning `run` into a catch-all audit command.
|
|
78
78
|
|
|
79
79
|
```bash
|
|
80
80
|
forgecad run model.forge.js
|
|
@@ -358,16 +358,16 @@ Script-backed exports accept repeatable `--param Key=Value` overrides before the
|
|
|
358
358
|
|
|
359
359
|
ForgeCAD has a hosted platform at [forgecad.io](https://forgecad.io). The CLI connects a dedicated local project folder to it.
|
|
360
360
|
|
|
361
|
-
A project is a local folder
|
|
361
|
+
A project is a local folder marked by `forgecad.json`; after the first push, that same file also links it to the hosted app. Use `forgecad project clone <slug>` to download an existing hosted project into a local folder, or run `forgecad project init` inside a folder that should become a new ForgeCAD project. Open local projects with `forgecad studio <project-path>`.
|
|
362
362
|
|
|
363
363
|
Keep the project root small and intentional. Do not run the editor from `~`, downloads, desktop, or a huge source tree. ForgeCAD scans project files such as `.forge.js`, `.js`, `.svg`, and `.dxf`; broad roots make local workflows and AI-agent context slow and confusing.
|
|
364
364
|
|
|
365
|
-
First-time setup (
|
|
365
|
+
First-time setup (init, studio, login, push) is the [Quick Start](#quick-start) sequence above. `forgecad project init` writes a local `forgecad.json` with the project name, slug, server, and visibility. It does not contact the server. The first `forgecad project push` creates the hosted project if `forgecad.json` has no project ID yet, uploads local source files, and records server file IDs. Later pushes sync the already linked hosted project. `forgecad project push` still requires `forgecad.json`; it does not initialize a random folder.
|
|
366
366
|
|
|
367
367
|
### Sync
|
|
368
368
|
|
|
369
369
|
```bash
|
|
370
|
-
forgecad project push #
|
|
370
|
+
forgecad project push # Create hosted project if needed; upload changes
|
|
371
371
|
forgecad project pull # Download remote changes
|
|
372
372
|
forgecad project status # See what's different
|
|
373
373
|
```
|
|
@@ -395,10 +395,10 @@ Shares are live references — always the current version, not a snapshot.
|
|
|
395
395
|
|
|
396
396
|
| Command | Description |
|
|
397
397
|
|---------|-------------|
|
|
398
|
-
| `project init` | Initialize the current directory as a ForgeCAD project
|
|
398
|
+
| `project init` | Initialize the current directory as a local ForgeCAD project. |
|
|
399
399
|
| `project clone` | Download a remote project into a new local directory. |
|
|
400
400
|
| `project pull` | Download remote changes into the current project. |
|
|
401
|
-
| `project push` |
|
|
401
|
+
| `project push` | Create the hosted project if needed, then upload local changes. |
|
|
402
402
|
| `project status` | Show differences between local and remote project files. |
|
|
403
403
|
| `project list` | List your remote projects. |
|
|
404
404
|
| `project open` | Open the current project in the browser. |
|
|
@@ -24,6 +24,9 @@ skill-order: 100
|
|
|
24
24
|
- [SurfacePattern](#surfacepattern)
|
|
25
25
|
- [Pattern2D](#pattern2d)
|
|
26
26
|
- [Pattern2DBuilder](#pattern2dbuilder)
|
|
27
|
+
- [Path2DParamValue](#path2dparamvalue)
|
|
28
|
+
- [Spline2DParamValue](#spline2dparamvalue)
|
|
29
|
+
- [Placement2DParamValue](#placement2dparamvalue)
|
|
27
30
|
- [CurveNetBuilder](#curvenetbuilder)
|
|
28
31
|
- [MatchEdgeBuilder](#matchedgebuilder)
|
|
29
32
|
- [BridgeBuilder](#bridgebuilder)
|
|
@@ -352,11 +355,11 @@ for (const edge of coalesceEdges(topEdges)) {
|
|
|
352
355
|
|
|
353
356
|
### Imports & Composition
|
|
354
357
|
|
|
355
|
-
#### `require(path: string
|
|
358
|
+
#### `require(path: string): any` — Import a ForgeCAD or helper module. Returns the file's returned value.
|
|
356
359
|
|
|
357
|
-
When importing a `.forge.js` file,
|
|
360
|
+
When importing a `.forge.js` file, return values are passed through exactly as the script returns them, except for unsolved assemblies: a returned [`Assembly`](/docs/assembly#assembly) is wrapped as an [`ImportedAssembly`](/docs/assembly#importedassembly), preserving `solve(state)` and `mergeInto()` across file boundaries. A returned [`SolvedAssembly`](/docs/assembly#solvedassembly) stays a [`SolvedAssembly`](/docs/assembly#solvedassembly).
|
|
358
361
|
|
|
359
|
-
**Script return contract:** a `.forge.js` script
|
|
362
|
+
**Script return contract:** a `.forge.js` script should return one of three shapes: a single renderable (Shape, ShapeGroup, Sketch, SdfShape, Assembly), an array of renderables or named descriptors (`{ name, shape|sketch|group }`) for previews and multi-object display, or a module interface object. Reusable part files should return builders such as `return { buildBracket }`; files that already build useful geometry may return `{ shape, connectors, boltPattern }`. When a script runs directly, renderable entries of a plain object are rendered under their key names and non-renderable entries are skipped.
|
|
360
363
|
|
|
361
364
|
**Assembly return contract**
|
|
362
365
|
|
|
@@ -369,52 +372,56 @@ When importing a `.forge.js` file, most return values are passed through exactly
|
|
|
369
372
|
|
|
370
373
|
**Path rule:** Always include the file extension in relative imports: use `require("./part.forge.js")` for model files and `require("./helpers.js")` for plain helper modules. ForgeCAD does not apply Node-style extension inference, so `require("./part")` will not find `part.forge.js` or `part.js`.
|
|
371
374
|
|
|
372
|
-
**
|
|
373
|
-
|
|
374
|
-
**Parameter overrides:** When passing overrides, use the bare param name (not the scoped name). Overrides are type-checked — unrecognized keys throw an error with typo suggestions.
|
|
375
|
-
|
|
376
|
-
**Multi-file assembly pattern** — pass cross-cutting design values from the assembly to parts:
|
|
375
|
+
**Multi-file assembly pattern** — the assembly owns params and passes ordinary props to child builders:
|
|
377
376
|
|
|
378
377
|
```js
|
|
379
378
|
// assembly.forge.js — owns cross-cutting params, passes to parts
|
|
380
379
|
const wall = param("Wall", 3);
|
|
381
380
|
const baseH = param("Base Height", 20);
|
|
382
381
|
|
|
383
|
-
const
|
|
384
|
-
const
|
|
382
|
+
const mountModule = require('./motor-mount.forge.js');
|
|
383
|
+
const baseModule = require('./base-body.forge.js');
|
|
384
|
+
|
|
385
|
+
const mount = mountModule.buildMount({ wall });
|
|
386
|
+
const base = baseModule.buildBase({ wall, height: baseH });
|
|
385
387
|
```
|
|
386
388
|
|
|
387
|
-
**
|
|
389
|
+
**Builder result pattern** — parts publish interface data alongside geometry:
|
|
388
390
|
|
|
389
391
|
```js
|
|
390
392
|
// motor-mount.forge.js
|
|
391
|
-
|
|
393
|
+
function buildMount({ wall }) {
|
|
394
|
+
const shape = box(80, 40, wall);
|
|
395
|
+
return { shape, boltPattern: { dia: 5.3, positions: [[-25, 0], [25, 0]] } };
|
|
396
|
+
}
|
|
392
397
|
|
|
393
398
|
// base-body.forge.js
|
|
394
399
|
const mount = require('./motor-mount.forge.js');
|
|
395
|
-
mount.
|
|
396
|
-
|
|
400
|
+
const built = mount.buildMount({ wall: 3 });
|
|
401
|
+
built.boltPattern // access interface data
|
|
402
|
+
built.shape // access geometry
|
|
397
403
|
```
|
|
398
404
|
|
|
399
405
|
**Forge-aware builder module pattern** — use `.forge.js` modules for reusable sketch, profile, shape, or assembly builders that need ForgeCAD runtime APIs:
|
|
400
406
|
|
|
401
407
|
```js
|
|
402
|
-
// profiles.forge.js
|
|
408
|
+
// profiles.forge.js
|
|
403
409
|
function wheelProfile() {
|
|
404
410
|
return circle2d(40).subtract(circle2d(18));
|
|
405
411
|
}
|
|
406
412
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
413
|
+
if (require.main === module) {
|
|
414
|
+
return [{ name: 'Wheel profile', sketch: wheelProfile() }];
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
return { wheelProfile };
|
|
411
418
|
|
|
412
419
|
// main.forge.js
|
|
413
420
|
const profiles = require('./profiles.forge.js');
|
|
414
|
-
const wheel = profiles.
|
|
421
|
+
const wheel = profiles.wheelProfile().extrude(8);
|
|
415
422
|
```
|
|
416
423
|
|
|
417
|
-
Keep
|
|
424
|
+
Keep returned builders pure over top-level constants or explicit function arguments. Put preview-only `param()` values inside `if (require.main === module)` so parent assemblies stay in charge of design parameters. Use plain `.js` modules only for pure constants, tables, math helpers, and formatting code that does not construct ForgeCAD geometry.
|
|
418
425
|
|
|
419
426
|
**Entry detection (Node semantics):** `require.main` is the entry script's module object, so `require.main === module` is true only in the file being run directly. Part files use it to build standalone preview geometry only when opened directly — importers then skip that work entirely:
|
|
420
427
|
|
|
@@ -422,16 +429,30 @@ Keep exported builders pure over top-level constants, top-level `param()` values
|
|
|
422
429
|
// part.forge.js
|
|
423
430
|
function bracket() { ... }
|
|
424
431
|
if (require.main === module) {
|
|
425
|
-
return {
|
|
432
|
+
return bracket({ width: param('Width', 80), height: param('Height', 40) });
|
|
426
433
|
}
|
|
427
|
-
return {
|
|
434
|
+
return { bracket };
|
|
428
435
|
```
|
|
429
436
|
|
|
430
437
|
### Parameters
|
|
431
438
|
|
|
432
|
-
#### `Param.
|
|
439
|
+
#### `Param.anchor: { ... }` — Viewport anchor builders for spatial parameter editing.
|
|
440
|
+
|
|
441
|
+
Anchors are metadata only: they do not change geometry. The editor uses them to show clickable parameter pins and manual-editing sheets in the 3D viewport. Use point anchors for scalar/text/list parameters and sheet anchors for `path2d`, [`spline2d`](/docs/curves#spline2d), and `placement2d` editors.
|
|
433
442
|
|
|
434
|
-
|
|
443
|
+
A sheet anchor's origin is a world/model-space point. Its plane selects how the 2D editor coordinates map into the viewport:
|
|
444
|
+
|
|
445
|
+
- `sheetOnXY([x, y, z])`: editor x/y map to world X/Y at fixed Z.
|
|
446
|
+
- `sheetOnXZ([x, y, z])`: editor x/y map to world X/Z at fixed Y.
|
|
447
|
+
- `sheetOnYZ([x, y, z])`: editor x/y map to world Y/Z at fixed X.
|
|
448
|
+
|
|
449
|
+
Omitting `anchor` still registers the parameter in the parameter panel; it just will not create a viewport pin/sheet.
|
|
450
|
+
|
|
451
|
+
`ParamAnchorOptions`: `{ label?: string, color?: string }`
|
|
452
|
+
|
|
453
|
+
#### `Param.number(name: string, defaultValue: number, opts?: NumberParamOptions): number` — Declare a numeric parameter that renders as a slider in the UI.
|
|
454
|
+
|
|
455
|
+
Each call registers a slider control. When the user moves the slider the entire script re-executes with the new value. The `name` string is the UI label and the CLI `--param` key.
|
|
435
456
|
|
|
436
457
|
Default range rules when options are omitted:
|
|
437
458
|
|
|
@@ -447,38 +468,34 @@ const angle = Param.number("Angle", 45, { min: 0, max: 180, unit: "°" });
|
|
|
447
468
|
const sides = Param.number("Sides", 6, { min: 3, max: 12, integer: true });
|
|
448
469
|
```
|
|
449
470
|
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
```ts
|
|
453
|
-
// Via require()
|
|
454
|
-
const bracket = require("./bracket.forge.js", { Width: 80 });
|
|
471
|
+
CLI overrides use the parameter name:
|
|
455
472
|
|
|
456
|
-
|
|
457
|
-
|
|
473
|
+
```bash
|
|
474
|
+
forgecad run model.forge.js --param "Wall Thickness=3"
|
|
458
475
|
```
|
|
459
476
|
|
|
460
477
|
Also available as the shorthand alias `param()`.
|
|
461
478
|
|
|
462
|
-
|
|
479
|
+
`ParamAnchorableOptions`: `{ anchor?: ParamAnchorDef }`
|
|
463
480
|
|
|
464
|
-
|
|
481
|
+
`NumberParamOptions`: `{ min?: number, max?: number, step?: number, unit?: string, integer?: boolean, reverse?: boolean }`
|
|
465
482
|
|
|
466
|
-
|
|
467
|
-
const label = Param.string("Label", "Hello World");
|
|
468
|
-
const name = Param.string("Name", "Part-001", { maxLength: 20 });
|
|
469
|
-
```
|
|
483
|
+
#### `Param.string(name: string, defaultValue: string, opts?: StringParamOptions): string` — Declare a string parameter that renders as a text input in the UI.
|
|
470
484
|
|
|
471
|
-
|
|
485
|
+
String parameters let users type free-form text — labels, names, inscriptions, file paths, etc.
|
|
472
486
|
|
|
473
487
|
```ts
|
|
474
|
-
const
|
|
488
|
+
const label = Param.string("Label", "Hello World");
|
|
489
|
+
const name = Param.string("Name", "Part-001", { maxLength: 20 });
|
|
475
490
|
```
|
|
476
491
|
|
|
477
492
|
Only available as `Param.string()` — no standalone alias.
|
|
478
493
|
|
|
479
|
-
|
|
494
|
+
`StringParamOptions`: `{ maxLength?: number }`
|
|
495
|
+
|
|
496
|
+
#### `Param.bool(name: string, defaultValue: boolean, opts?: ParamAnchorableOptions): boolean` — Declare a boolean parameter that renders as a checkbox in the UI.
|
|
480
497
|
|
|
481
|
-
Internally stored as `0`/`1
|
|
498
|
+
Internally stored as `0`/`1` for CLI overrides. Pass `1` for true and `0` for false.
|
|
482
499
|
|
|
483
500
|
```ts
|
|
484
501
|
const showHoles = Param.bool("Show Holes", true);
|
|
@@ -486,29 +503,17 @@ if (showHoles) return difference(plate, cylinder(10, 5).translate(50, 30, 0));
|
|
|
486
503
|
return plate;
|
|
487
504
|
```
|
|
488
505
|
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
```ts
|
|
492
|
-
const pan = require("./pan.forge.js", { "Show Lid": 0 });
|
|
493
|
-
```
|
|
494
|
-
|
|
495
|
-
#### `Param.choice(name: string, defaultValue: string, choices: string[]): string` — Declare a choice parameter that renders as a dropdown in the UI.
|
|
506
|
+
#### `Param.choice(name: string, defaultValue: string, choices: string[], opts?: ParamAnchorableOptions): string` — Declare a choice parameter that renders as a dropdown in the UI.
|
|
496
507
|
|
|
497
508
|
`defaultValue` must exactly match one entry in `choices`. Returns the selected string label. Prefer `Param.choice` over `Param.number` when a slider would hide intent — named choices like `"wok"` are self-describing.
|
|
498
509
|
|
|
499
|
-
|
|
510
|
+
CLI overrides may be passed as the choice label string (preferred) or as a numeric index.
|
|
500
511
|
|
|
501
512
|
```ts
|
|
502
513
|
const panStyle = Param.choice("Pan Style", "frying-pan", ["frying-pan", "saute-pan", "wok"]);
|
|
503
514
|
if (panStyle === "wok") return buildWok();
|
|
504
515
|
```
|
|
505
516
|
|
|
506
|
-
Override via import:
|
|
507
|
-
|
|
508
|
-
```ts
|
|
509
|
-
const pan = require("./pan.forge.js", { "Pan Style": "wok" });
|
|
510
|
-
```
|
|
511
|
-
|
|
512
517
|
Override via CLI:
|
|
513
518
|
|
|
514
519
|
```bash
|
|
@@ -527,6 +532,90 @@ Field types:
|
|
|
527
532
|
|
|
528
533
|
`ListParamFieldDef`: `{ min?: number, max?: number, step?: number, unit?: string, integer?: boolean, boolean?: boolean, choices?: string[] }`
|
|
529
534
|
|
|
535
|
+
#### `Param.path2d(name: string, defaultPoints: Path2DPointInput[], opts?: Path2DParamOptions): Path2DParamValue` — Declare an editable 2D path parameter.
|
|
536
|
+
|
|
537
|
+
Use this for hand-shaped 2D profile data: plate outlines, slice profiles, stroke centerlines, and sweep rails. The returned value keeps the model code deterministic while the editor can render a drag-handle path UI.
|
|
538
|
+
|
|
539
|
+
Override keys use the same explicit row-field form as list params: `Path Name[0].x`, `Path Name[0].y`, and `Path Name.__count__`.
|
|
540
|
+
|
|
541
|
+
```ts
|
|
542
|
+
const outline = Param.path2d("Bracket Outline", [
|
|
543
|
+
[-40, -20],
|
|
544
|
+
[40, -20],
|
|
545
|
+
[36, 24],
|
|
546
|
+
[-30, 28],
|
|
547
|
+
], {
|
|
548
|
+
closed: true,
|
|
549
|
+
anchor: Param.anchor.sheetOnXY([0, 0, 8], { label: "Bracket outline" }),
|
|
550
|
+
});
|
|
551
|
+
|
|
552
|
+
return outline.toSketch().filletCorners(4).extrude(5);
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
**`Path2DParamOptions`** extends ParamAnchorableOptions: `closed?: boolean`, `minPoints?: number`, `maxPoints?: number`, `x?: Partial<Path2DParamAxisDef>`, `y?: Partial<Path2DParamAxisDef>`, `unit?: string`
|
|
556
|
+
|
|
557
|
+
**`Path2DParamAxisDef`**
|
|
558
|
+
- `min: number` — Initial editor-frame minimum. Points may move outside this range on the infinite canvas.
|
|
559
|
+
- `max: number` — Initial editor-frame maximum. Points may move outside this range on the infinite canvas.
|
|
560
|
+
- Also: `step: number`.
|
|
561
|
+
|
|
562
|
+
#### `Param.spline2d(name: string, defaultPoints: Spline2DPointInput[], opts?: Spline2DParamOptions): Spline2DParamValue` — Declare an editable 2D spline parameter.
|
|
563
|
+
|
|
564
|
+
Use this when the model wants hand-shaped smooth curve data instead of a numeric table: handle spines, bowl station curves, sweep rails, and class-A guide profiles. Each node stores `g`, a continuity intent:
|
|
565
|
+
|
|
566
|
+
- `"G0"` starts/ends a hard curve segment at that point
|
|
567
|
+
- `"G1"` keeps the point in a tangent-smooth run
|
|
568
|
+
- `"G2"` keeps the point in a curvature-smooth cubic run
|
|
569
|
+
|
|
570
|
+
Override keys use explicit row-field form: `Curve Name[0].x`, `Curve Name[0].y`, `Curve Name[0].g`, and `Curve Name.__count__`.
|
|
571
|
+
|
|
572
|
+
```ts
|
|
573
|
+
const spine = Param.spline2d("Handle Spine", [
|
|
574
|
+
{ x: 0, y: 0, g: "G2" },
|
|
575
|
+
{ x: 35, y: 8, g: "G2" },
|
|
576
|
+
{ x: 80, y: 2, g: "G1" },
|
|
577
|
+
], {
|
|
578
|
+
anchor: Param.anchor.sheetOnXZ([0, -18, 0], { label: "Side-view spine" }),
|
|
579
|
+
});
|
|
580
|
+
|
|
581
|
+
return sweep(circle2d(2), spine.toCurveOnXZ());
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
**`Spline2DParamOptions`** extends ParamAnchorableOptions: `closed?: boolean`, `degree?: number`, `defaultContinuity?: Spline2DContinuity`, `minPoints?: number`, `maxPoints?: number`, `x?: Partial<Path2DParamAxisDef>`, `y?: Partial<Path2DParamAxisDef>`, `unit?: string`
|
|
585
|
+
|
|
586
|
+
#### `Param.placement2d(name: string, spec: Placement2DParamOptions): Placement2DParamValue` — Declare an editable 2D placement sheet parameter.
|
|
587
|
+
|
|
588
|
+
Use this when the user should arrange named model roles rather than draw geometry: batteries inside an enclosure, rooms across floors, controls on a panel, robot modules on a chassis, or other semantic blockouts.
|
|
589
|
+
|
|
590
|
+
The script declares stable item IDs, footprints, optional rectangular zones, and interaction rules. The returned value exposes named placements as data; the model code decides what those placements mean geometrically.
|
|
591
|
+
|
|
592
|
+
Override keys are item-ID based: `Layout.battery.x`, `Layout.battery.y`, `Layout.battery.angle`, and `Layout.battery.zone`.
|
|
593
|
+
|
|
594
|
+
```ts
|
|
595
|
+
const layout = Param.placement2d("Internal Layout", {
|
|
596
|
+
frame: { size: [120, 80] },
|
|
597
|
+
items: [
|
|
598
|
+
{ id: "battery", footprint: { type: "rect", size: [42, 24] }, at: [-25, 0] },
|
|
599
|
+
{ id: "speaker", footprint: { type: "circle", radius: 12 }, at: [32, 8] },
|
|
600
|
+
],
|
|
601
|
+
rules: { bounds: "prevent", collisions: "warn", snap: 1 },
|
|
602
|
+
anchor: Param.anchor.sheetOnXY([0, 0, 12], { label: "Internal layout" }),
|
|
603
|
+
});
|
|
604
|
+
|
|
605
|
+
const battery = layout.item("battery");
|
|
606
|
+
const batteryPocket = box(42, 24, 6).translate(battery.x, battery.y, 3);
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
**`Placement2DParamOptions`** extends ParamAnchorableOptions: `frame?: Placement2DFrameInput`, `zones?: Placement2DZoneInput[]`, `items: Placement2DItemInput[]`, `rules?: Partial<Placement2DRulesDef>`, `unit?: string`
|
|
610
|
+
|
|
611
|
+
`Placement2DFrameInput`: `{ width?: number, height?: number, size?: Vec2, center?: Placement2DPointInput, at?: Placement2DPointInput }`
|
|
612
|
+
|
|
613
|
+
`Placement2DZoneInput`: `{ id: string, label?: string, frame?: Placement2DFrameInput }`
|
|
614
|
+
|
|
615
|
+
**`Placement2DItemInput`**: `id: string`, `label?: string`, `footprint: Placement2DFootprintInput`, `at?: Placement2DPointInput`, `center?: Placement2DPointInput`, `angle?: number`, `zone?: string`, `locked?: boolean`
|
|
616
|
+
|
|
617
|
+
`Placement2DRulesDef`: `{ bounds: Placement2DRuleMode, collisions: Placement2DRuleMode, snap: number }`
|
|
618
|
+
|
|
530
619
|
### Grouping & Local Coordinates
|
|
531
620
|
|
|
532
621
|
#### `group(...items: GroupInput[]): ShapeGroup` — Group multiple shapes/sketches for joint transforms without merging into a single mesh.
|
|
@@ -1204,7 +1293,7 @@ cylinder(60, 20).wrapTexture(label, Wrap.aroundCylinder({ axis: 'z' })); // wra
|
|
|
1204
1293
|
|
|
1205
1294
|
#### `ref(path: string): ShapeRef` — Resolve a semantic reference path like `lid`, `lid/back`, or a midpoint selector on `lid/back`.
|
|
1206
1295
|
|
|
1207
|
-
#### `thicken(thickness:
|
|
1296
|
+
#### `thicken(thickness: ThicknessInput): Shape` — Offset-thicken an exact open surface or shell into a solid.
|
|
1208
1297
|
|
|
1209
1298
|
#### `getMesh(): ShapeRuntimeMesh` — Extract triangle mesh for Three.js rendering
|
|
1210
1299
|
|
|
@@ -1444,6 +1533,99 @@ const bracket = group(
|
|
|
1444
1533
|
| `depth?` | `number` | Thread groove depth in millimeters. Default: 0.8. |
|
|
1445
1534
|
| `underScale?` | `number` | Relative height of the under-crossing thread. Default: 0.15. |
|
|
1446
1535
|
|
|
1536
|
+
### `Path2DParamValue`
|
|
1537
|
+
|
|
1538
|
+
Runtime value returned by `Param.path2d()`.
|
|
1539
|
+
|
|
1540
|
+
Use closed paths as editable profile outlines via `toSketch()`. Use open paths as editable centerlines via `toStroke(width)`.
|
|
1541
|
+
|
|
1542
|
+
**Properties:**
|
|
1543
|
+
|
|
1544
|
+
| Property | Type | Description |
|
|
1545
|
+
|----------|------|-------------|
|
|
1546
|
+
| `closed` | `boolean` | True when this path is intended to close back to its first point. |
|
|
1547
|
+
|
|
1548
|
+
**Methods:**
|
|
1549
|
+
|
|
1550
|
+
#### `points(): Vec2[]` — Return the current points as `[x, y]` pairs in the editor coordinate system.
|
|
1551
|
+
|
|
1552
|
+
#### `toSketch(): Sketch` — Convert a closed editable path into a sketch profile.
|
|
1553
|
+
|
|
1554
|
+
This is the common path for hand-edited plates, outlines, and 2D section profiles that will be extruded, subtracted, or used in sketch booleans. Throws for open paths; use `toStroke(width)` for editable centerlines.
|
|
1555
|
+
|
|
1556
|
+
#### `toStroke(width: number, join?: "Round" | "Square"): Sketch` — Convert an editable path into a stroked sketch with physical width.
|
|
1557
|
+
|
|
1558
|
+
Use this for rails, ribs, cable routes, gasket paths, and other open centerlines. Closed paths can also be stroked when the intent is a looped band rather than a filled profile.
|
|
1559
|
+
|
|
1560
|
+
### `Spline2DParamValue`
|
|
1561
|
+
|
|
1562
|
+
Runtime value returned by `Param.spline2d()`.
|
|
1563
|
+
|
|
1564
|
+
Spline params preserve both editable point coordinates and each point's continuity intent (`G0`, `G1`, or `G2`). Convert them to curves for sweeps and loft rails, or to sampled paths when an API expects plain points.
|
|
1565
|
+
|
|
1566
|
+
**Properties:**
|
|
1567
|
+
|
|
1568
|
+
| Property | Type | Description |
|
|
1569
|
+
|----------|------|-------------|
|
|
1570
|
+
| `closed` | `boolean` | True when this spline is intended to close back to its first point. |
|
|
1571
|
+
| `degree` | `number` | Requested fitting degree before any automatic reduction for short spans. |
|
|
1572
|
+
|
|
1573
|
+
**Methods:**
|
|
1574
|
+
|
|
1575
|
+
#### `points(): Vec2[]` — Return the current control nodes as `[x, y]` pairs without continuity metadata.
|
|
1576
|
+
|
|
1577
|
+
#### `nodes(): Spline2DPointDef[]` — Return the current editable nodes, including per-point `g` continuity values.
|
|
1578
|
+
|
|
1579
|
+
#### `continuities(): Spline2DContinuity[]` — Return only the per-node continuity intents in point order.
|
|
1580
|
+
|
|
1581
|
+
#### `toPolyline(samples?: number): Vec2[]` — Sample the spline into 2D `[x, y]` points.
|
|
1582
|
+
|
|
1583
|
+
Use this when downstream code needs a polyline instead of a curve object.
|
|
1584
|
+
|
|
1585
|
+
#### `toCurveOnXY(z?: number, options?: Spline2DCurveOptions): NurbsCurve3D` — Fit the editable spline as a 3D curve on the XY plane at constant `z`.
|
|
1586
|
+
|
|
1587
|
+
The point's `x` maps to world X and `y` maps to world Y.
|
|
1588
|
+
|
|
1589
|
+
`Spline2DCurveOptions`: `{ degree?: number, tolerance?: number, samples?: number }`
|
|
1590
|
+
|
|
1591
|
+
#### `toCurveOnXZ(y?: number, options?: Spline2DCurveOptions): NurbsCurve3D` — Fit the editable spline as a 3D curve on the XZ plane at constant `y`.
|
|
1592
|
+
|
|
1593
|
+
The point's `x` maps to world X and `y` maps to world Z. This is useful for side-view height/depth profiles such as spoon bowls, handles, and rails.
|
|
1594
|
+
|
|
1595
|
+
#### `toCurveOnYZ(x?: number, options?: Spline2DCurveOptions): NurbsCurve3D` — Fit the editable spline as a 3D curve on the YZ plane at constant `x`.
|
|
1596
|
+
|
|
1597
|
+
The point's `x` maps to world Y and `y` maps to world Z.
|
|
1598
|
+
|
|
1599
|
+
#### `toCurveSegmentsOnXY(z?: number, options?: Spline2DCurveOptions): NurbsCurve3D[]` — Fit the spline on XY and return separate curve segments split at `G0` nodes.
|
|
1600
|
+
|
|
1601
|
+
Use segment output when a hard break should remain visible to downstream code instead of being joined into one continuous curve.
|
|
1602
|
+
|
|
1603
|
+
#### `toCurveSegmentsOnXZ(y?: number, options?: Spline2DCurveOptions): NurbsCurve3D[]` — Fit the spline on XZ and return separate curve segments split at `G0` nodes.
|
|
1604
|
+
|
|
1605
|
+
#### `toCurveSegmentsOnYZ(x?: number, options?: Spline2DCurveOptions): NurbsCurve3D[]` — Fit the spline on YZ and return separate curve segments split at `G0` nodes.
|
|
1606
|
+
|
|
1607
|
+
#### `toPathOnXY(z?: number, options?: Spline2DCurveOptions): Vec3[]` — Sample the spline as 3D points on the XY plane at constant `z`.
|
|
1608
|
+
|
|
1609
|
+
This is useful for sweeps and surface helpers that accept point paths.
|
|
1610
|
+
|
|
1611
|
+
#### `toPathOnXZ(y?: number, options?: Spline2DCurveOptions): Vec3[]` — Sample the spline as 3D points on the XZ plane at constant `y`.
|
|
1612
|
+
|
|
1613
|
+
#### `toPathOnYZ(x?: number, options?: Spline2DCurveOptions): Vec3[]` — Sample the spline as 3D points on the YZ plane at constant `x`.
|
|
1614
|
+
|
|
1615
|
+
### `Placement2DParamValue`
|
|
1616
|
+
|
|
1617
|
+
Runtime value returned by `Param.placement2d()`.
|
|
1618
|
+
|
|
1619
|
+
Placement sheets return semantic item positions. The model decides what each item means geometrically, so users can drag named blocks without editing the construction code.
|
|
1620
|
+
|
|
1621
|
+
#### `items(): Placement2DItemPlacement[]` — Return all current item placements as immutable copies.
|
|
1622
|
+
|
|
1623
|
+
#### `positions(): Record<string, Placement2DItemPlacement>` — Return current placements keyed by item id for table-style lookup.
|
|
1624
|
+
|
|
1625
|
+
#### `item(id: string): Placement2DItemPlacement` — Return one named item placement.
|
|
1626
|
+
|
|
1627
|
+
Throws if `id` was not declared in the sheet, which keeps model code tied to stable semantic item IDs rather than fragile list indices.
|
|
1628
|
+
|
|
1447
1629
|
### `CurveNetBuilder`
|
|
1448
1630
|
|
|
1449
1631
|
#### `alongRails(railA: CurveInput, railB: CurveInput): this` — Use two lengthwise boundary curves as guide rails.
|
|
@@ -1515,6 +1697,7 @@ Pass `{ edge }` to match an adjacent sheet's tangent (G1) or curvature (G2), or
|
|
|
1515
1697
|
- `pathAlongU(v: number, options?: SheetPathAlongOptions): Vec3[]`
|
|
1516
1698
|
- `pathAlongV(u: number, options?: SheetPathAlongOptions): Vec3[]`
|
|
1517
1699
|
- `thicken(wall: number, options?: { resolution?: number; }): Shape`
|
|
1700
|
+
- `thickenInsideBy(thickness: ThicknessInput, options?: { resolution?: number; }): Shape`
|
|
1518
1701
|
- `matchEdge(edge: SheetEdge): MatchEdgeBuilder`
|
|
1519
1702
|
|
|
1520
1703
|
**`SheetFrameOptions`**
|
|
@@ -39,6 +39,7 @@ Smooth curves, lofted surfaces, swept solids, splines, and high-level product sk
|
|
|
39
39
|
- [Surface](#surface)
|
|
40
40
|
- [Blend](#blend)
|
|
41
41
|
- [Analysis](#analysis)
|
|
42
|
+
- [Thickness](#thickness)
|
|
42
43
|
- [Product](#product)
|
|
43
44
|
- [Carrier](#carrier)
|
|
44
45
|
- [SurfaceMembers](#surfacemembers)
|
|
@@ -648,6 +649,10 @@ Use this when the guide path runs in the surface V direction and the sketch prof
|
|
|
648
649
|
|
|
649
650
|
#### `thicken(wall: number, options?: { resolution?: number; }): Shape` — Offset the sheet along its analytic normals into a watertight solid shell of the given wall thickness. Throws if the wall would self-intersect on a concave region (no silent degenerate solid).
|
|
650
651
|
|
|
652
|
+
#### `thickenInsideBy(thickness: ThicknessInput, options?: { resolution?: number; }): Shape` — Thicken this sheet inward by a scalar UV thickness field.
|
|
653
|
+
|
|
654
|
+
Numeric input delegates to `Sheet.thicken()`. `Thickness.*` fields produce a sampled solid because a variable normal offset is not generally an exact NURBS surface.
|
|
655
|
+
|
|
651
656
|
#### `matchEdge(edge: SheetEdge): MatchEdgeBuilder` — Per-edge continuity match against a neighbor (returns a NEW Sheet).
|
|
652
657
|
|
|
653
658
|
- `get rearEdge(): SheetEdge`
|
|
@@ -1523,6 +1528,14 @@ Members (full entries under [Curves & Surfacing](#curves-surfacing)): `Curve.Ble
|
|
|
1523
1528
|
- `SurfaceHealth(shape: Shape, options?: { tinyEdgeThreshold?: number; sliverThreshold?: number; }): SurfaceHealthReport`
|
|
1524
1529
|
- `BRepValidity(shape: Shape, options?: BRepValidityOptions): BRepValidityReport` — Validate B-rep/shell/solid structure and return closedness, manifoldness, orientation, and issue diagnostics.
|
|
1525
1530
|
|
|
1531
|
+
### `Thickness`
|
|
1532
|
+
|
|
1533
|
+
- `constant: (thickness: number) => ThicknessField` — Use the same wall thickness everywhere on the sheet.
|
|
1534
|
+
- `alongU: (profile: ThicknessStation[] | ThicknessStationProfile) => ThicknessField` — Vary wall thickness across the sheet U direction.
|
|
1535
|
+
- `alongV: (profile: ThicknessStation[] | ThicknessStationProfile) => ThicknessField` — Vary wall thickness across the sheet V direction.
|
|
1536
|
+
- `grid: (values: number[][], options?: ThicknessGridOptions) => ThicknessField` — Bilinearly interpolate wall thickness from a rectangular UV grid.
|
|
1537
|
+
- `nurbs: (values: number[][], options?: ThicknessNurbsOptions) => ThicknessField` — Interpolate wall thickness from a scalar tensor-product B-spline over sheet UV.
|
|
1538
|
+
|
|
1526
1539
|
### `Product`
|
|
1527
1540
|
|
|
1528
1541
|
- `skin(name: string): ProductSkinBuilder` — Start a named product skin builder.
|
|
@@ -28,8 +28,8 @@ rect, Rectangle2D, roundedRect, Route3D, scene, Sculpt, sdf, SdfShape
|
|
|
28
28
|
selectEdge, selectEdges, self, setActiveBackend, setImmediate, setInterval, setTimeout, Shape
|
|
29
29
|
ShapeGroup, sheetMetal, SheetMetalPart, sheetStock, Sim, Sketch, sketchToDxf, sketchToSvg
|
|
30
30
|
slot, SolvedAssembly, spec, sphere, spline2d, stroke, Surface, SurfaceBody
|
|
31
|
-
SurfaceMembers, sweep, text2d, textWidth, torus, toShape, Transform
|
|
32
|
-
union2d, variableSweep, verify, Viewport, window, Wood, Wrap
|
|
31
|
+
SurfaceMembers, sweep, text2d, textWidth, Thickness, torus, toShape, Transform
|
|
32
|
+
union, union2d, variableSweep, verify, Viewport, window, Wood, Wrap
|
|
33
33
|
```
|
|
34
34
|
|
|
35
35
|
`showLabels` is also a runtime global, but it is not part of the top-level collision check. Avoid reusing it unless you intentionally want a local value with that name.
|
|
@@ -5,7 +5,7 @@ skill-order: 2
|
|
|
5
5
|
|
|
6
6
|
# Inspection Bundles — Evidence Contract
|
|
7
7
|
|
|
8
|
-
`forgecad inspect <family> <mode>` writes a deterministic bundle: evidence PNGs under `evidence/<type>/` plus a root `manifest.json`. **The manifest is the authoritative contract** — take file paths, encodings, per-view ranges, thresholds, tolerances, and identity maps from it; never hard-code bundle layout or infer object identity from object order. The PNGs are a visual index for locating findings, not standalone artifacts. Command tree, flags, and `--focus`/`--hide` filtering live in `docs/skill/CLI.md` and `forgecad inspect evidence`; the inspection workflow lives in
|
|
8
|
+
`forgecad inspect <family> <mode>` writes a deterministic bundle: evidence PNGs under `evidence/<type>/` plus a root `manifest.json`. **The manifest is the authoritative contract** — take file paths, encodings, per-view ranges, thresholds, tolerances, and identity maps from it; never hard-code bundle layout or infer object identity from object order. The PNGs are a visual index for locating findings, not standalone artifacts. Command tree, flags, and `--focus`/`--hide` filtering live in `docs/skill/CLI.md` and `forgecad inspect evidence`; the model-building inspection workflow lives in `forgecad-build-model/references/inspection-feedback.md`. Model-authored `scene()` background, lights, fog, and exposure are ignored for inspection captures so evidence stays stable; named scene views remain available via `--view`.
|
|
9
9
|
|
|
10
10
|
Manifest evidence keys are evidence-oriented and stable for bundle readers: e.g. `fit interference` writes `manifest.evidence.collisions`, `physical components` writes `manifest.evidence.connectivity`.
|
|
11
11
|
|