forgecad 0.10.4 → 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-B3L3W1Uo.js → AdminPage-B1nIvqLS.js} +1 -1
- package/dist/assets/{BenchmarkPage-DXKVXMrJ.js → BenchmarkPage-YZJbw5nd.js} +2 -2
- package/dist/assets/{BlogPage-B7BWxOCg.js → BlogPage-DIWRApKS.js} +1 -1
- package/dist/assets/{DocsPage-BPGGwht1.js → DocsPage-ClL6X1hR.js} +8 -22
- package/dist/assets/EditorApp-CYBDvSyT.js +17067 -0
- package/dist/assets/{EmbedViewer-DygByZS2.js → EmbedViewer-Dmfu_LIw.js} +2 -2
- package/dist/assets/{LandingPageProofDriven-BoVE7JGY.js → LandingPageProofDriven-XYTiYxfM.js} +2 -2
- package/dist/assets/{LegalPage-Din8wv8d.js → LegalPage-D5Z3CscF.js} +2 -2
- package/dist/assets/{PricingPage-C2PMzmDc.js → PricingPage-BP4lIGio.js} +2 -2
- package/dist/assets/{SettingsPage-BlJDCRe8.js → SettingsPage-D3bcPBsC.js} +1 -1
- package/dist/assets/{app-BsRYSfxY.js → app-BKjogwIZ.js} +3288 -512
- package/dist/assets/{backendInit-6C0DLgH0.js → backendInit-6a9-ilom.js} +80498 -74979
- package/dist/assets/cli/{render-XXol_ET7.js → render-CMNudGb0.js} +1264 -113
- package/dist/assets/{constructionHistoryWorker-cTHWRJEi.js → constructionHistoryWorker-BuZgc606.js} +8369 -6839
- package/dist/assets/{evalWorker-BssDYW9u.js → evalWorker-DQ82ueGu.js} +45438 -39996
- package/dist/assets/{forgecad_geometry-CZ_IfuvA.js → forgecad_geometry-D8rWX7nQ.js} +1 -1
- package/dist/assets/{forgecad_geometry_bg-C3rQHfwg.wasm → forgecad_geometry_bg-ObqfqjJT.wasm} +0 -0
- package/dist/assets/{inspectWorker-ymhBV4Ll.js → inspectWorker-Cuby2qfT.js} +4899 -1303
- package/dist/assets/{jointPose-B0blBj9A.js → jointPose-CFql5I-u.js} +1 -1
- package/dist/assets/{landing-proof-driven-Cpf-MIbI.css → landing-proof-driven-_u4v_xQb.css} +2 -2
- package/dist/assets/{manifold-CYlIm-M6.js → manifold-02pmr7O7.js} +2 -2
- package/dist/assets/{manifold-B_7QXpGB.js → manifold-C6KU0oII.js} +1 -1
- package/dist/assets/{manifold-CNShmpEJ.js → manifold-P1yF3GKn.js} +1 -1
- package/dist/assets/{reportWorker-Cb5eyM7D.js → reportWorker-kg065BVL.js} +76583 -65731
- 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 +14 -12
- package/dist/docs-raw/component-model.md +28 -9
- package/dist/docs-raw/generated/assembly.md +76 -3
- package/dist/docs-raw/generated/concepts.md +43 -7
- package/dist/docs-raw/generated/core.md +399 -73
- package/dist/docs-raw/generated/curves.md +357 -6
- package/dist/docs-raw/generated/runtime-names.md +12 -12
- package/dist/docs-raw/generated/sketch.md +16 -3
- package/dist/docs-raw/guides/inspection-bundles.md +5 -3
- package/dist/docs-raw/guides/structural-fea.md +235 -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 +4 -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-4RPB6SB5.js → check-compiler-UJWUEIDC.js} +1 -1
- package/dist-cli/{check-query-propagation-KN3DFQTX.js → check-query-propagation-O2EPDJSY.js} +1 -1
- package/dist-cli/{chunk-UHBRMYA6.js → chunk-MNDROM7T.js} +78926 -73392
- package/dist-cli/forgecad.js +6306 -1061
- package/dist-cli/forgecad_geometry_bg.wasm +0 -0
- package/dist-skill/CONTEXT.md +1257 -110
- package/dist-skill/SKILL.md +4 -1
- package/dist-skill/docs/API/core/concepts.md +31 -4
- package/dist-skill/docs/CLI.md +14 -12
- package/dist-skill/docs/generated/assembly.md +73 -3
- package/dist-skill/docs/generated/core.md +395 -74
- package/dist-skill/docs/generated/curves.md +356 -6
- package/dist-skill/docs/generated/runtime-names.md +12 -12
- package/dist-skill/docs/generated/sketch.md +16 -3
- package/dist-skill/docs/guides/inspection-bundles.md +5 -3
- package/dist-skill/docs/guides/manual-parameters.md +130 -0
- package/dist-skill/docs/guides/structural-fea.md +235 -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 +4 -1
- package/dist-skill/website/skills/index.md +1 -5
- package/examples/analysis/structural-stress-fea.forge.js +19 -0
- package/examples/api/blend-full-round.forge.js +37 -0
- package/examples/api/blend-variable-radius.forge.js +51 -0
- package/examples/api/curve-project-and-intersect.forge.js +59 -0
- package/examples/api/extrude-up-to-face.forge.js +47 -0
- 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 +188 -0
- package/examples/api/surface-boundarynet-dished-bowl.forge.js +63 -0
- package/examples/api/surface-fill-interior-constraints.forge.js +59 -0
- package/examples/api/surface-variable-thickness-panel.forge.js +62 -0
- package/examples/mechanical/airplane-propeller.forge.js +81 -28
- package/package.json +5 -2
- package/dist/assets/EditorApp-BWUGCdD5.js +0 -16610
- 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/assets/{landing-proof-driven-BxZZh5r5.js → landing-proof-driven-DNPRKL_p.js} +0 -0
- /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
|
@@ -18,13 +18,15 @@ skill-order: 100
|
|
|
18
18
|
- [Grouping & Local Coordinates](#grouping-local-coordinates)
|
|
19
19
|
- [Section & Projection](#section-projection)
|
|
20
20
|
- [Verification](#verification)
|
|
21
|
-
- [Shape](#shape) — Appearance, Face Topology, Edge Topology, Transforms, Booleans & Cutting, Features, Placement, Connectors, References, Measurement
|
|
21
|
+
- [Shape](#shape) — Freeform Construction, Appearance, Face Topology, Edge Topology, Transforms, Booleans & Cutting, Features, Placement, Connectors, References, Measurement
|
|
22
22
|
- [Transform](#transform)
|
|
23
23
|
- [ShapeGroup](#shapegroup) — Children, Transforms, Placement, Connectors, References
|
|
24
24
|
- [SurfacePattern](#surfacepattern)
|
|
25
25
|
- [Pattern2D](#pattern2d)
|
|
26
26
|
- [Pattern2DBuilder](#pattern2dbuilder)
|
|
27
|
-
- [
|
|
27
|
+
- [Path2DParamValue](#path2dparamvalue)
|
|
28
|
+
- [Spline2DParamValue](#spline2dparamvalue)
|
|
29
|
+
- [Placement2DParamValue](#placement2dparamvalue)
|
|
28
30
|
- [CurveNetBuilder](#curvenetbuilder)
|
|
29
31
|
- [MatchEdgeBuilder](#matchedgebuilder)
|
|
30
32
|
- [BridgeBuilder](#bridgebuilder)
|
|
@@ -353,11 +355,11 @@ for (const edge of coalesceEdges(topEdges)) {
|
|
|
353
355
|
|
|
354
356
|
### Imports & Composition
|
|
355
357
|
|
|
356
|
-
#### `require(path: string
|
|
358
|
+
#### `require(path: string): any` — Import a ForgeCAD or helper module. Returns the file's returned value.
|
|
357
359
|
|
|
358
|
-
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).
|
|
359
361
|
|
|
360
|
-
**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.
|
|
361
363
|
|
|
362
364
|
**Assembly return contract**
|
|
363
365
|
|
|
@@ -370,52 +372,56 @@ When importing a `.forge.js` file, most return values are passed through exactly
|
|
|
370
372
|
|
|
371
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`.
|
|
372
374
|
|
|
373
|
-
**
|
|
374
|
-
|
|
375
|
-
**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.
|
|
376
|
-
|
|
377
|
-
**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:
|
|
378
376
|
|
|
379
377
|
```js
|
|
380
378
|
// assembly.forge.js — owns cross-cutting params, passes to parts
|
|
381
379
|
const wall = param("Wall", 3);
|
|
382
380
|
const baseH = param("Base Height", 20);
|
|
383
381
|
|
|
384
|
-
const
|
|
385
|
-
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 });
|
|
386
387
|
```
|
|
387
388
|
|
|
388
|
-
**
|
|
389
|
+
**Builder result pattern** — parts publish interface data alongside geometry:
|
|
389
390
|
|
|
390
391
|
```js
|
|
391
392
|
// motor-mount.forge.js
|
|
392
|
-
|
|
393
|
+
function buildMount({ wall }) {
|
|
394
|
+
const shape = box(80, 40, wall);
|
|
395
|
+
return { shape, boltPattern: { dia: 5.3, positions: [[-25, 0], [25, 0]] } };
|
|
396
|
+
}
|
|
393
397
|
|
|
394
398
|
// base-body.forge.js
|
|
395
399
|
const mount = require('./motor-mount.forge.js');
|
|
396
|
-
mount.
|
|
397
|
-
|
|
400
|
+
const built = mount.buildMount({ wall: 3 });
|
|
401
|
+
built.boltPattern // access interface data
|
|
402
|
+
built.shape // access geometry
|
|
398
403
|
```
|
|
399
404
|
|
|
400
405
|
**Forge-aware builder module pattern** — use `.forge.js` modules for reusable sketch, profile, shape, or assembly builders that need ForgeCAD runtime APIs:
|
|
401
406
|
|
|
402
407
|
```js
|
|
403
|
-
// profiles.forge.js
|
|
408
|
+
// profiles.forge.js
|
|
404
409
|
function wheelProfile() {
|
|
405
410
|
return circle2d(40).subtract(circle2d(18));
|
|
406
411
|
}
|
|
407
412
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
413
|
+
if (require.main === module) {
|
|
414
|
+
return [{ name: 'Wheel profile', sketch: wheelProfile() }];
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
return { wheelProfile };
|
|
412
418
|
|
|
413
419
|
// main.forge.js
|
|
414
420
|
const profiles = require('./profiles.forge.js');
|
|
415
|
-
const wheel = profiles.
|
|
421
|
+
const wheel = profiles.wheelProfile().extrude(8);
|
|
416
422
|
```
|
|
417
423
|
|
|
418
|
-
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.
|
|
419
425
|
|
|
420
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:
|
|
421
427
|
|
|
@@ -423,16 +429,30 @@ Keep exported builders pure over top-level constants, top-level `param()` values
|
|
|
423
429
|
// part.forge.js
|
|
424
430
|
function bracket() { ... }
|
|
425
431
|
if (require.main === module) {
|
|
426
|
-
return {
|
|
432
|
+
return bracket({ width: param('Width', 80), height: param('Height', 40) });
|
|
427
433
|
}
|
|
428
|
-
return {
|
|
434
|
+
return { bracket };
|
|
429
435
|
```
|
|
430
436
|
|
|
431
437
|
### Parameters
|
|
432
438
|
|
|
433
|
-
#### `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.
|
|
442
|
+
|
|
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 }`
|
|
434
452
|
|
|
435
|
-
|
|
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.
|
|
436
456
|
|
|
437
457
|
Default range rules when options are omitted:
|
|
438
458
|
|
|
@@ -448,38 +468,35 @@ const angle = Param.number("Angle", 45, { min: 0, max: 180, unit: "°" });
|
|
|
448
468
|
const sides = Param.number("Sides", 6, { min: 3, max: 12, integer: true });
|
|
449
469
|
```
|
|
450
470
|
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
```ts
|
|
454
|
-
// Via require()
|
|
455
|
-
const bracket = require("./bracket.forge.js", { Width: 80 });
|
|
471
|
+
CLI overrides use the parameter name:
|
|
456
472
|
|
|
457
|
-
|
|
458
|
-
|
|
473
|
+
```bash
|
|
474
|
+
forgecad run model.forge.js --param "Wall Thickness=3"
|
|
459
475
|
```
|
|
460
476
|
|
|
461
477
|
Also available as the shorthand alias `param()`.
|
|
462
478
|
|
|
463
|
-
|
|
479
|
+
`ParamAnchorableOptions`: `{ anchor?: ParamAnchorDef }`
|
|
480
|
+
|
|
481
|
+
`NumberParamOptions`: `{ min?: number, max?: number, step?: number, unit?: string, integer?: boolean, reverse?: boolean }`
|
|
482
|
+
|
|
483
|
+
#### `Param.string(name: string, defaultValue: string, opts?: StringParamOptions): string` — Declare a string parameter that renders as a text input in the UI.
|
|
464
484
|
|
|
465
|
-
String parameters let users type free-form text — labels, names, inscriptions, file paths, etc.
|
|
485
|
+
String parameters let users type free-form text — labels, names, inscriptions, file paths, etc.
|
|
466
486
|
|
|
467
487
|
```ts
|
|
468
488
|
const label = Param.string("Label", "Hello World");
|
|
469
489
|
const name = Param.string("Name", "Part-001", { maxLength: 20 });
|
|
470
490
|
```
|
|
471
491
|
|
|
472
|
-
|
|
492
|
+
Only available as `Param.string()` — no standalone alias.
|
|
473
493
|
|
|
474
|
-
```ts
|
|
475
|
-
const tag = require("./tag.forge.js", { Label: "Custom Text" });
|
|
476
|
-
```
|
|
477
494
|
|
|
478
|
-
|
|
495
|
+
`StringParamOptions`: `{ maxLength?: number }`
|
|
479
496
|
|
|
480
|
-
#### `Param.bool(name: string, defaultValue: boolean): boolean` — Declare a boolean parameter that renders as a checkbox in the UI.
|
|
497
|
+
#### `Param.bool(name: string, defaultValue: boolean, opts?: ParamAnchorableOptions): boolean` — Declare a boolean parameter that renders as a checkbox in the UI.
|
|
481
498
|
|
|
482
|
-
Internally stored as `0`/`1
|
|
499
|
+
Internally stored as `0`/`1` for CLI overrides. Pass `1` for true and `0` for false.
|
|
483
500
|
|
|
484
501
|
```ts
|
|
485
502
|
const showHoles = Param.bool("Show Holes", true);
|
|
@@ -487,29 +504,17 @@ if (showHoles) return difference(plate, cylinder(10, 5).translate(50, 30, 0));
|
|
|
487
504
|
return plate;
|
|
488
505
|
```
|
|
489
506
|
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
```ts
|
|
493
|
-
const pan = require("./pan.forge.js", { "Show Lid": 0 });
|
|
494
|
-
```
|
|
495
|
-
|
|
496
|
-
#### `Param.choice(name: string, defaultValue: string, choices: string[]): string` — Declare a choice parameter that renders as a dropdown in the UI.
|
|
507
|
+
#### `Param.choice(name: string, defaultValue: string, choices: string[], opts?: ParamAnchorableOptions): string` — Declare a choice parameter that renders as a dropdown in the UI.
|
|
497
508
|
|
|
498
509
|
`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.
|
|
499
510
|
|
|
500
|
-
|
|
511
|
+
CLI overrides may be passed as the choice label string (preferred) or as a numeric index.
|
|
501
512
|
|
|
502
513
|
```ts
|
|
503
514
|
const panStyle = Param.choice("Pan Style", "frying-pan", ["frying-pan", "saute-pan", "wok"]);
|
|
504
515
|
if (panStyle === "wok") return buildWok();
|
|
505
516
|
```
|
|
506
517
|
|
|
507
|
-
Override via import:
|
|
508
|
-
|
|
509
|
-
```ts
|
|
510
|
-
const pan = require("./pan.forge.js", { "Pan Style": "wok" });
|
|
511
|
-
```
|
|
512
|
-
|
|
513
518
|
Override via CLI:
|
|
514
519
|
|
|
515
520
|
```bash
|
|
@@ -528,6 +533,94 @@ Field types:
|
|
|
528
533
|
|
|
529
534
|
`ListParamFieldDef`: `{ min?: number, max?: number, step?: number, unit?: string, integer?: boolean, boolean?: boolean, choices?: string[] }`
|
|
530
535
|
|
|
536
|
+
#### `Param.path2d(name: string, defaultPoints: Path2DPointInput[], opts?: Path2DParamOptions): Path2DParamValue` — Declare an editable 2D path parameter.
|
|
537
|
+
|
|
538
|
+
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.
|
|
539
|
+
|
|
540
|
+
Override keys use the same explicit row-field form as list params: `Path Name[0].x`, `Path Name[0].y`, and `Path Name.__count__`.
|
|
541
|
+
|
|
542
|
+
```ts
|
|
543
|
+
const outline = Param.path2d("Bracket Outline", [
|
|
544
|
+
[-40, -20],
|
|
545
|
+
[40, -20],
|
|
546
|
+
[36, 24],
|
|
547
|
+
[-30, 28],
|
|
548
|
+
], {
|
|
549
|
+
closed: true,
|
|
550
|
+
anchor: Param.anchor.sheetOnXY([0, 0, 8], { label: "Bracket outline" }),
|
|
551
|
+
});
|
|
552
|
+
|
|
553
|
+
return outline.toSketch().filletCorners(4).extrude(5);
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
|
|
557
|
+
**`Path2DParamOptions`** extends ParamAnchorableOptions: `closed?: boolean`, `minPoints?: number`, `maxPoints?: number`, `x?: Partial<Path2DParamAxisDef>`, `y?: Partial<Path2DParamAxisDef>`, `unit?: string`
|
|
558
|
+
|
|
559
|
+
**`Path2DParamAxisDef`**
|
|
560
|
+
- `min: number` — Initial editor-frame minimum. Points may move outside this range on the infinite canvas.
|
|
561
|
+
- `max: number` — Initial editor-frame maximum. Points may move outside this range on the infinite canvas.
|
|
562
|
+
- Also: `step: number`.
|
|
563
|
+
|
|
564
|
+
#### `Param.spline2d(name: string, defaultPoints: Spline2DPointInput[], opts?: Spline2DParamOptions): Spline2DParamValue` — Declare an editable 2D spline parameter.
|
|
565
|
+
|
|
566
|
+
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:
|
|
567
|
+
|
|
568
|
+
- `"G0"` starts/ends a hard curve segment at that point
|
|
569
|
+
- `"G1"` keeps the point in a tangent-smooth run
|
|
570
|
+
- `"G2"` keeps the point in a curvature-smooth cubic run
|
|
571
|
+
|
|
572
|
+
Override keys use explicit row-field form: `Curve Name[0].x`, `Curve Name[0].y`, `Curve Name[0].g`, and `Curve Name.__count__`.
|
|
573
|
+
|
|
574
|
+
```ts
|
|
575
|
+
const spine = Param.spline2d("Handle Spine", [
|
|
576
|
+
{ x: 0, y: 0, g: "G2" },
|
|
577
|
+
{ x: 35, y: 8, g: "G2" },
|
|
578
|
+
{ x: 80, y: 2, g: "G1" },
|
|
579
|
+
], {
|
|
580
|
+
anchor: Param.anchor.sheetOnXZ([0, -18, 0], { label: "Side-view spine" }),
|
|
581
|
+
});
|
|
582
|
+
|
|
583
|
+
return sweep(circle2d(2), spine.toCurveOnXZ());
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
|
|
587
|
+
**`Spline2DParamOptions`** extends ParamAnchorableOptions: `closed?: boolean`, `degree?: number`, `defaultContinuity?: Spline2DContinuity`, `minPoints?: number`, `maxPoints?: number`, `x?: Partial<Path2DParamAxisDef>`, `y?: Partial<Path2DParamAxisDef>`, `unit?: string`
|
|
588
|
+
|
|
589
|
+
#### `Param.placement2d(name: string, spec: Placement2DParamOptions): Placement2DParamValue` — Declare an editable 2D placement sheet parameter.
|
|
590
|
+
|
|
591
|
+
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.
|
|
592
|
+
|
|
593
|
+
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.
|
|
594
|
+
|
|
595
|
+
Override keys are item-ID based: `Layout.battery.x`, `Layout.battery.y`, `Layout.battery.angle`, and `Layout.battery.zone`.
|
|
596
|
+
|
|
597
|
+
```ts
|
|
598
|
+
const layout = Param.placement2d("Internal Layout", {
|
|
599
|
+
frame: { size: [120, 80] },
|
|
600
|
+
items: [
|
|
601
|
+
{ id: "battery", footprint: { type: "rect", size: [42, 24] }, at: [-25, 0] },
|
|
602
|
+
{ id: "speaker", footprint: { type: "circle", radius: 12 }, at: [32, 8] },
|
|
603
|
+
],
|
|
604
|
+
rules: { bounds: "prevent", collisions: "warn", snap: 1 },
|
|
605
|
+
anchor: Param.anchor.sheetOnXY([0, 0, 12], { label: "Internal layout" }),
|
|
606
|
+
});
|
|
607
|
+
|
|
608
|
+
const battery = layout.item("battery");
|
|
609
|
+
const batteryPocket = box(42, 24, 6).translate(battery.x, battery.y, 3);
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
|
|
613
|
+
**`Placement2DParamOptions`** extends ParamAnchorableOptions: `frame?: Placement2DFrameInput`, `zones?: Placement2DZoneInput[]`, `items: Placement2DItemInput[]`, `rules?: Partial<Placement2DRulesDef>`, `unit?: string`
|
|
614
|
+
|
|
615
|
+
`Placement2DFrameInput`: `{ width?: number, height?: number, size?: Vec2, center?: Placement2DPointInput, at?: Placement2DPointInput }`
|
|
616
|
+
|
|
617
|
+
|
|
618
|
+
`Placement2DZoneInput`: `{ id: string, label?: string, frame?: Placement2DFrameInput }`
|
|
619
|
+
|
|
620
|
+
**`Placement2DItemInput`**: `id: string`, `label?: string`, `footprint: Placement2DFootprintInput`, `at?: Placement2DPointInput`, `center?: Placement2DPointInput`, `angle?: number`, `zone?: string`, `locked?: boolean`
|
|
621
|
+
|
|
622
|
+
`Placement2DRulesDef`: `{ bounds: Placement2DRuleMode, collisions: Placement2DRuleMode, snap: number }`
|
|
623
|
+
|
|
531
624
|
### Grouping & Local Coordinates
|
|
532
625
|
|
|
533
626
|
#### `group(...items: GroupInput[]): ShapeGroup` — Group multiple shapes/sketches for joint transforms without merging into a single mesh.
|
|
@@ -705,6 +798,96 @@ Supports transforms (translate, rotate, scale, mirror, transform, rotateAround,
|
|
|
705
798
|
|----------|------|-------------|
|
|
706
799
|
| `materialProps` | `ShapeMaterialProps \| undefined` | — |
|
|
707
800
|
|
|
801
|
+
**Freeform Construction**
|
|
802
|
+
|
|
803
|
+
#### `slicePerpendicularToX(x: number, profile: Sketch, options?: FromSlicesAxisSliceOptions): FromSlicesSlice` — Create a slice descriptor perpendicular to the X axis.
|
|
804
|
+
|
|
805
|
+
The profile is drawn in the YZ plane. `options.center` is `[y, z]`, so authors can place changing section centers without manually translating sketches in ForgeCAD's internal plane axes.
|
|
806
|
+
|
|
807
|
+
```js
|
|
808
|
+
Shape.fromSlices([
|
|
809
|
+
Shape.slicePerpendicularToX(-20, ellipse(10, 2), { center: [0, 3] }),
|
|
810
|
+
Shape.slicePerpendicularToX(20, ellipse(8, 1.5), { center: [0, 6] }),
|
|
811
|
+
]);
|
|
812
|
+
```
|
|
813
|
+
|
|
814
|
+
**`FromSlicesAxisSliceOptions`**
|
|
815
|
+
- `center?: FromSlicesVec2` — Plane-local profile center. XY uses [x, y], XZ uses [x, z], YZ uses [y, z].
|
|
816
|
+
|
|
817
|
+
#### `slicePerpendicularToY(y: number, profile: Sketch, options?: FromSlicesAxisSliceOptions): FromSlicesSlice` — Create a slice descriptor perpendicular to the Y axis.
|
|
818
|
+
|
|
819
|
+
The profile is drawn in the XZ plane. `options.center` is `[x, z]`.
|
|
820
|
+
|
|
821
|
+
#### `slicePerpendicularToZ(z: number, profile: Sketch, options?: FromSlicesAxisSliceOptions): FromSlicesSlice` — Create a slice descriptor perpendicular to the Z axis.
|
|
822
|
+
|
|
823
|
+
The profile is drawn in the XY plane. `options.center` is `[x, y]`.
|
|
824
|
+
|
|
825
|
+
#### `sliceThrough(center: FromSlicesVec3, normal: FromSlicesVec3, profile: Sketch): FromSlicesSlice` — Create a slice descriptor through a world point with an arbitrary plane normal.
|
|
826
|
+
|
|
827
|
+
The profile origin lands at `center`. Use this when the section plane is not one of the world XY/XZ/YZ planes.
|
|
828
|
+
|
|
829
|
+
#### `sliceOnFrame(frame: FromSlicesFrameInput, profile: Sketch): FromSlicesSlice` — Create a slice descriptor on a full 3D work frame.
|
|
830
|
+
|
|
831
|
+
Sheet frame helpers return the right shape for `frame`. Use `Sheet.frameAt()` for tangent construction planes, or `Sheet.framePerpendicularToU()` / `Sheet.framePerpendicularToV()` for cross-sections normal to a surface path. On the Manifold backend, framed slices are lofted in input order when every slice comes from a frame.
|
|
832
|
+
|
|
833
|
+
**`FromSlicesFrameInput`**
|
|
834
|
+
|
|
835
|
+
| Option | Type | Description |
|
|
836
|
+
|--------|------|-------------|
|
|
837
|
+
| `point?` | `FromSlicesVec3` | World-space frame origin. Sheet frame helpers return this as `point`. |
|
|
838
|
+
| `origin?` | `FromSlicesVec3` | Alias for `point` when using generic CAD frame terminology. |
|
|
839
|
+
| `normal` | `FromSlicesVec3` | World-space frame normal. |
|
|
840
|
+
| `tangentU?` | `FromSlicesVec3` | World-space direction for the profile's local X axis. Sheet frame helpers return this as `tangentU`. |
|
|
841
|
+
| `tangentV?` | `FromSlicesVec3` | Optional world-space direction for the profile's local Y axis. Sheet frame helpers return this as `tangentV`. |
|
|
842
|
+
| `xAxis?` | `FromSlicesVec3` | Alias for `tangentU`. |
|
|
843
|
+
| `yAxis?` | `FromSlicesVec3` | Alias for `tangentV`. |
|
|
844
|
+
|
|
845
|
+
#### `fromSlices(slices: FromSlicesSlice[], options?: FromSlicesOptions): Shape` — Construct a 3D shape from cross-section slices on one or more planes.
|
|
846
|
+
|
|
847
|
+
On the Manifold backend, slices created with `Shape.sliceOnFrame()` are lofted in their input order while preserving each full 3D frame. Other slices with the same normal direction are lofted together. Slices with different normals are combined via smooth radial blending — each silhouette constrains the shape's extent, producing smooth ellipsoidal cross-sections.
|
|
848
|
+
|
|
849
|
+
```js
|
|
850
|
+
// Egg from two orthogonal silhouettes
|
|
851
|
+
const eggProfile = ellipse(15, 25);
|
|
852
|
+
return Shape.fromSlices([
|
|
853
|
+
{ on: 'xz', at: 0, profile: eggProfile },
|
|
854
|
+
{ on: 'yz', at: 0, profile: eggProfile },
|
|
855
|
+
]);
|
|
856
|
+
```
|
|
857
|
+
|
|
858
|
+
```js
|
|
859
|
+
// Vase with cross-section transitions
|
|
860
|
+
return Shape.fromSlices([
|
|
861
|
+
Shape.slicePerpendicularToZ(0, circle2d(20)),
|
|
862
|
+
Shape.slicePerpendicularToZ(40, rect(25, 25)),
|
|
863
|
+
Shape.slicePerpendicularToZ(80, circle2d(8)),
|
|
864
|
+
Shape.slicePerpendicularToY(0, vaseOutline),
|
|
865
|
+
]);
|
|
866
|
+
```
|
|
867
|
+
|
|
868
|
+
**`FromSlicesSlice`**
|
|
869
|
+
|
|
870
|
+
| Option | Type | Description |
|
|
871
|
+
|--------|------|-------------|
|
|
872
|
+
| `on` | `SlicePlane` | Plane normal: axis name or arbitrary unit vector. |
|
|
873
|
+
| `at?` | `number` | Signed offset along the normal from the origin. Omit when `center` defines the plane. |
|
|
874
|
+
| `center?` | `FromSlicesVec3` | World-space point where the 2D profile origin should land on the slice plane. |
|
|
875
|
+
| `profile` | `Sketch` | 2D cross-section profile on that plane. |
|
|
876
|
+
| `frame?` | `FromSlicesFramePlacement` | Full 3D section frame, preserved for ordered lofts through rotating planes. |
|
|
877
|
+
|
|
878
|
+
**`FromSlicesFramePlacement`**
|
|
879
|
+
|
|
880
|
+
| Option | Type | Description |
|
|
881
|
+
|--------|------|-------------|
|
|
882
|
+
| `point` | `FromSlicesVec3` | World-space frame origin. |
|
|
883
|
+
| `normal` | `FromSlicesVec3` | World-space section normal. |
|
|
884
|
+
| `tangentU` | `FromSlicesVec3` | World-space direction for the profile's local X axis. |
|
|
885
|
+
| `tangentV` | `FromSlicesVec3` | World-space direction for the profile's local Y axis. |
|
|
886
|
+
|
|
887
|
+
**`FromSlicesOptions`**
|
|
888
|
+
- `edgeLength?: number` — Marching-grid edge length for level-set meshing (Manifold only).
|
|
889
|
+
- `boundsPadding?: number` — Extra bounding-box padding (Manifold only).
|
|
890
|
+
|
|
708
891
|
**Appearance**
|
|
709
892
|
|
|
710
893
|
#### `color(value: string | undefined): Shape` — Set the color of this shape (hex string, e.g. "#ff0000"). Returns a new Shape with the color applied.
|
|
@@ -1115,7 +1298,7 @@ cylinder(60, 20).wrapTexture(label, Wrap.aroundCylinder({ axis: 'z' })); // wra
|
|
|
1115
1298
|
|
|
1116
1299
|
#### `ref(path: string): ShapeRef` — Resolve a semantic reference path like `lid`, `lid/back`, or a midpoint selector on `lid/back`.
|
|
1117
1300
|
|
|
1118
|
-
#### `thicken(thickness:
|
|
1301
|
+
#### `thicken(thickness: ThicknessInput): Shape` — Offset-thicken an exact open surface or shell into a solid.
|
|
1119
1302
|
|
|
1120
1303
|
#### `getMesh(): ShapeRuntimeMesh` — Extract triangle mesh for Three.js rendering
|
|
1121
1304
|
|
|
@@ -1355,57 +1538,200 @@ const bracket = group(
|
|
|
1355
1538
|
| `depth?` | `number` | Thread groove depth in millimeters. Default: 0.8. |
|
|
1356
1539
|
| `underScale?` | `number` | Relative height of the under-crossing thread. Default: 0.15. |
|
|
1357
1540
|
|
|
1358
|
-
### `
|
|
1541
|
+
### `Path2DParamValue`
|
|
1542
|
+
|
|
1543
|
+
Runtime value returned by `Param.path2d()`.
|
|
1544
|
+
|
|
1545
|
+
Use closed paths as editable profile outlines via `toSketch()`. Use open paths as editable centerlines via `toStroke(width)`.
|
|
1546
|
+
|
|
1547
|
+
**Properties:**
|
|
1548
|
+
|
|
1549
|
+
| Property | Type | Description |
|
|
1550
|
+
|----------|------|-------------|
|
|
1551
|
+
| `closed` | `boolean` | True when this path is intended to close back to its first point. |
|
|
1552
|
+
|
|
1553
|
+
**Methods:**
|
|
1554
|
+
|
|
1555
|
+
#### `points(): Vec2[]` — Return the current points as `[x, y]` pairs in the editor coordinate system.
|
|
1556
|
+
|
|
1557
|
+
#### `toSketch(): Sketch` — Convert a closed editable path into a sketch profile.
|
|
1558
|
+
|
|
1559
|
+
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.
|
|
1560
|
+
|
|
1561
|
+
#### `toStroke(width: number, join?: "Round" | "Square"): Sketch` — Convert an editable path into a stroked sketch with physical width.
|
|
1359
1562
|
|
|
1360
|
-
|
|
1563
|
+
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.
|
|
1564
|
+
|
|
1565
|
+
### `Spline2DParamValue`
|
|
1566
|
+
|
|
1567
|
+
Runtime value returned by `Param.spline2d()`.
|
|
1568
|
+
|
|
1569
|
+
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.
|
|
1361
1570
|
|
|
1362
1571
|
**Properties:**
|
|
1363
1572
|
|
|
1364
1573
|
| Property | Type | Description |
|
|
1365
1574
|
|----------|------|-------------|
|
|
1366
|
-
| `
|
|
1575
|
+
| `closed` | `boolean` | True when this spline is intended to close back to its first point. |
|
|
1576
|
+
| `degree` | `number` | Requested fitting degree before any automatic reduction for short spans. |
|
|
1367
1577
|
|
|
1368
1578
|
**Methods:**
|
|
1369
1579
|
|
|
1370
|
-
#### `
|
|
1580
|
+
#### `points(): Vec2[]` — Return the current control nodes as `[x, y]` pairs without continuity metadata.
|
|
1581
|
+
|
|
1582
|
+
#### `nodes(): Spline2DPointDef[]` — Return the current editable nodes, including per-point `g` continuity values.
|
|
1583
|
+
|
|
1584
|
+
#### `continuities(): Spline2DContinuity[]` — Return only the per-node continuity intents in point order.
|
|
1585
|
+
|
|
1586
|
+
#### `toPolyline(samples?: number): Vec2[]` — Sample the spline into 2D `[x, y]` points.
|
|
1587
|
+
|
|
1588
|
+
Use this when downstream code needs a polyline instead of a curve object.
|
|
1589
|
+
|
|
1590
|
+
#### `toCurveOnXY(z?: number, options?: Spline2DCurveOptions): NurbsCurve3D` — Fit the editable spline as a 3D curve on the XY plane at constant `z`.
|
|
1591
|
+
|
|
1592
|
+
The point's `x` maps to world X and `y` maps to world Y.
|
|
1593
|
+
|
|
1594
|
+
`Spline2DCurveOptions`: `{ degree?: number, tolerance?: number, samples?: number }`
|
|
1595
|
+
|
|
1596
|
+
#### `toCurveOnXZ(y?: number, options?: Spline2DCurveOptions): NurbsCurve3D` — Fit the editable spline as a 3D curve on the XZ plane at constant `y`.
|
|
1597
|
+
|
|
1598
|
+
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.
|
|
1599
|
+
|
|
1600
|
+
#### `toCurveOnYZ(x?: number, options?: Spline2DCurveOptions): NurbsCurve3D` — Fit the editable spline as a 3D curve on the YZ plane at constant `x`.
|
|
1601
|
+
|
|
1602
|
+
The point's `x` maps to world Y and `y` maps to world Z.
|
|
1603
|
+
|
|
1604
|
+
#### `toCurveSegmentsOnXY(z?: number, options?: Spline2DCurveOptions): NurbsCurve3D[]` — Fit the spline on XY and return separate curve segments split at `G0` nodes.
|
|
1605
|
+
|
|
1606
|
+
Use segment output when a hard break should remain visible to downstream code instead of being joined into one continuous curve.
|
|
1371
1607
|
|
|
1372
|
-
#### `
|
|
1608
|
+
#### `toCurveSegmentsOnXZ(y?: number, options?: Spline2DCurveOptions): NurbsCurve3D[]` — Fit the spline on XZ and return separate curve segments split at `G0` nodes.
|
|
1373
1609
|
|
|
1374
|
-
#### `
|
|
1610
|
+
#### `toCurveSegmentsOnYZ(x?: number, options?: Spline2DCurveOptions): NurbsCurve3D[]` — Fit the spline on YZ and return separate curve segments split at `G0` nodes.
|
|
1611
|
+
|
|
1612
|
+
#### `toPathOnXY(z?: number, options?: Spline2DCurveOptions): Vec3[]` — Sample the spline as 3D points on the XY plane at constant `z`.
|
|
1613
|
+
|
|
1614
|
+
This is useful for sweeps and surface helpers that accept point paths.
|
|
1615
|
+
|
|
1616
|
+
#### `toPathOnXZ(y?: number, options?: Spline2DCurveOptions): Vec3[]` — Sample the spline as 3D points on the XZ plane at constant `y`.
|
|
1617
|
+
|
|
1618
|
+
#### `toPathOnYZ(x?: number, options?: Spline2DCurveOptions): Vec3[]` — Sample the spline as 3D points on the YZ plane at constant `x`.
|
|
1619
|
+
|
|
1620
|
+
### `Placement2DParamValue`
|
|
1621
|
+
|
|
1622
|
+
Runtime value returned by `Param.placement2d()`.
|
|
1623
|
+
|
|
1624
|
+
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.
|
|
1625
|
+
|
|
1626
|
+
#### `items(): Placement2DItemPlacement[]` — Return all current item placements as immutable copies.
|
|
1627
|
+
|
|
1628
|
+
#### `positions(): Record<string, Placement2DItemPlacement>` — Return current placements keyed by item id for table-style lookup.
|
|
1629
|
+
|
|
1630
|
+
#### `item(id: string): Placement2DItemPlacement` — Return one named item placement.
|
|
1631
|
+
|
|
1632
|
+
Throws if `id` was not declared in the sheet, which keeps model code tied to stable semantic item IDs rather than fragile list indices.
|
|
1633
|
+
|
|
1634
|
+
### `CurveNetBuilder`
|
|
1635
|
+
|
|
1636
|
+
#### `alongRails(railA: CurveInput, railB: CurveInput): this` — Use two lengthwise boundary curves as guide rails.
|
|
1637
|
+
|
|
1638
|
+
Chain `.sections(...)` to create a bi-rail surface: the rails define the sheet edges while each section curve shapes the cross-span at its station.
|
|
1639
|
+
|
|
1640
|
+
#### `sections(...curves: CurveInput[]): this` — Add crosswise section curves.
|
|
1641
|
+
|
|
1642
|
+
By itself this skins the sections into a surface. After `.alongRails(...)`, the sections are fitted between the two rails so the surface follows both the boundary guide curves and the section profiles.
|
|
1643
|
+
|
|
1644
|
+
#### `resolution(samples: number): this` — Set the sampling resolution used to build curve-family surface grids.
|
|
1645
|
+
|
|
1646
|
+
This affects `.lengthwise(...)`, `.crosswise(...)`, and `.alongRails(...).sections(...)` surfaces. It does not resample explicit `.cage(grid)` input because the cage already is the authored control net.
|
|
1647
|
+
|
|
1648
|
+
#### `matchStartU(condition: BoundaryCondition): this` — Enforce a continuity condition on the `u = 0` (left) boundary.
|
|
1649
|
+
|
|
1650
|
+
Pass `{ edge }` to match an adjacent sheet's tangent (G1) or curvature (G2), or `{ tangent }` to impose an explicit cross-boundary direction. See `BoundaryCondition`.
|
|
1651
|
+
|
|
1652
|
+
**`BoundaryCondition`**
|
|
1653
|
+
|
|
1654
|
+
| Option | Type | Description |
|
|
1655
|
+
|--------|------|-------------|
|
|
1656
|
+
| `edge?` | `SheetEdge` | Match the tangent (G1) and curvature (G2) of an existing sheet edge across this boundary. |
|
|
1657
|
+
| `tangent?` | `Vec3` | Or impose an explicit cross-boundary tangent direction in world space (auto-normalized). |
|
|
1658
|
+
| `tangentScale?` | `number` | Scalar magnitude for the imposed `tangent` ramp, in model units. Ignored when `edge` is given. Default: the local cross-boundary control-span length (chord-scaled), so the imposed tangent has the same strength as the surface already carries — no magic number. |
|
|
1659
|
+
| `continuity?` | `0 \| 1 \| 2` | Continuity order to enforce on this side. Default inferred: 1 if a tangent or edge is given, else 0. G2 (curvature) requires an `edge` to copy the neighbor's second difference. |
|
|
1375
1660
|
|
|
1376
1661
|
**`SheetEdge`**
|
|
1377
1662
|
- `fixed: "u" | "v"` — Which parameter is held fixed along this edge.
|
|
1378
1663
|
- `value: 0 | 1` — The fixed value (0 or 1).
|
|
1379
1664
|
- Also: `sheet: Sheet`.
|
|
1380
1665
|
|
|
1381
|
-
|
|
1382
|
-
- `get leftEdge(): SheetEdge`
|
|
1383
|
-
- `get rightEdge(): SheetEdge`
|
|
1384
|
-
- `pointAt(u: number, v: number): Vec3`
|
|
1385
|
-
- `normalAt(u: number, v: number): Vec3`
|
|
1386
|
-
- `curvatureAt(u: number, v: number): SurfaceCurvature`
|
|
1666
|
+
#### `matchEndU(condition: BoundaryCondition): this` — Enforce a continuity condition on the `u = 1` (right) boundary. See `matchStartU`.
|
|
1387
1667
|
|
|
1388
|
-
|
|
1668
|
+
#### `matchStartV(condition: BoundaryCondition): this` — Enforce a continuity condition on the `v = 0` (front) boundary. See `matchStartU`.
|
|
1669
|
+
|
|
1670
|
+
#### `matchEndV(condition: BoundaryCondition): this` — Enforce a continuity condition on the `v = 1` (rear) boundary. See `matchStartU`.
|
|
1671
|
+
|
|
1672
|
+
#### `closedU(): this` — Weld the two ends of the U direction into a tangent-continuous periodic loop, so the `u = 0` and `u = 1` boundaries coincide with NO G0 kink (a closed tube/ring in U — e.g. a bowl's around-rim seam). The cage's first and last U rows must already be coincident (the loop must close in position).
|
|
1673
|
+
|
|
1674
|
+
#### `closedV(): this` — Weld the two ends of the V direction into a tangent-continuous periodic loop. See `closedU`.
|
|
1389
1675
|
|
|
1390
1676
|
#### `toSheet(): Sheet` — Build (once) and return the Sheet.
|
|
1391
1677
|
|
|
1392
1678
|
- `lengthwise(...curves: CurveInput[]): this`
|
|
1393
1679
|
- `crosswise(...curves: CurveInput[]): this`
|
|
1394
|
-
- `alongRails(railA: CurveInput, railB: CurveInput): this`
|
|
1395
|
-
- `sections(...curves: CurveInput[]): this`
|
|
1396
1680
|
- `cage(grid: Vec3[][]): this`
|
|
1397
1681
|
- `degree(u: number, v: number): this`
|
|
1398
1682
|
- `get frontEdge(): SheetEdge`
|
|
1399
1683
|
- `get rearEdge(): SheetEdge`
|
|
1400
1684
|
- `get leftEdge(): SheetEdge`
|
|
1401
1685
|
- `get rightEdge(): SheetEdge`
|
|
1686
|
+
- `get frontCurve(): NurbsCurve3D`
|
|
1687
|
+
- `get rearCurve(): NurbsCurve3D`
|
|
1688
|
+
- `get leftCurve(): NurbsCurve3D`
|
|
1689
|
+
- `get rightCurve(): NurbsCurve3D`
|
|
1402
1690
|
- `get surface(): BSplineSurface`
|
|
1403
1691
|
- `pointAt(u: number, v: number): Vec3`
|
|
1404
1692
|
- `normalAt(u: number, v: number): Vec3`
|
|
1693
|
+
- `frameAt(u: number, v: number, options?: SheetFrameOptions): SheetFrame`
|
|
1694
|
+
- `framePerpendicularToU(u: number, v: number, options?: SheetFrameOptions): SheetFrame`
|
|
1695
|
+
- `framePerpendicularToV(u: number, v: number, options?: SheetFrameOptions): SheetFrame`
|
|
1405
1696
|
- `curvatureAt(u: number, v: number): SurfaceCurvature`
|
|
1697
|
+
- `curveAlong(edge: SheetEdge): NurbsCurve3D`
|
|
1698
|
+
- `curveAlongU(v: number): NurbsCurve3D`
|
|
1699
|
+
- `curveAlongV(u: number): NurbsCurve3D`
|
|
1700
|
+
- `pathAlong(edge: SheetEdge, options?: SheetPathAlongOptions): Vec3[]`
|
|
1701
|
+
- `pathAlongBoundary(spans: SheetBoundaryPathSpan[], options?: SheetBoundaryPathOptions): Vec3[]`
|
|
1702
|
+
- `pathAlongU(v: number, options?: SheetPathAlongOptions): Vec3[]`
|
|
1703
|
+
- `pathAlongV(u: number, options?: SheetPathAlongOptions): Vec3[]`
|
|
1406
1704
|
- `thicken(wall: number, options?: { resolution?: number; }): Shape`
|
|
1705
|
+
- `thickenInsideBy(thickness: ThicknessInput, options?: { resolution?: number; }): Shape`
|
|
1407
1706
|
- `matchEdge(edge: SheetEdge): MatchEdgeBuilder`
|
|
1408
1707
|
|
|
1708
|
+
**`SheetFrameOptions`**
|
|
1709
|
+
- `normalOffset?: number` — Offset the frame origin along the analytic surface normal. Default 0.
|
|
1710
|
+
|
|
1711
|
+
**`SheetPathAlongOptions`**
|
|
1712
|
+
|
|
1713
|
+
| Option | Type | Description |
|
|
1714
|
+
|--------|------|-------------|
|
|
1715
|
+
| `samples?` | `number` | Samples along the path span. Default 32. |
|
|
1716
|
+
| `start?` | `number` | Normalized start parameter along the path. Default 0. |
|
|
1717
|
+
| `end?` | `number` | Normalized end parameter along the path. Default 1. |
|
|
1718
|
+
| `reverse?` | `boolean` | Return points from end to start after sampling the span. Default false. |
|
|
1719
|
+
| `normalOffset?` | `number` | Offset each path point along the analytic surface normal. Default 0. |
|
|
1720
|
+
|
|
1721
|
+
**`SheetBoundaryPathSpan`**
|
|
1722
|
+
|
|
1723
|
+
| Option | Type | Description |
|
|
1724
|
+
|--------|------|-------------|
|
|
1725
|
+
| `edge` | `SheetEdge` | Boundary edge to sample for this span. |
|
|
1726
|
+
| `start?` | `SheetPathParameter` | Normalized edge parameter or world point projected to the closest edge parameter. Default 0. |
|
|
1727
|
+
| `end?` | `SheetPathParameter` | Normalized edge parameter or world point projected to the closest edge parameter. Default 1. |
|
|
1728
|
+
| `samples?` | `number` | Samples along this edge span. Defaults to options.samplesPerEdge or 32. |
|
|
1729
|
+
|
|
1730
|
+
**`SheetBoundaryPathOptions`**
|
|
1731
|
+
- `samplesPerEdge?: number` — Samples for spans that do not specify their own count. Default 32.
|
|
1732
|
+
- `normalOffset?: number` — Offset each path point along the analytic surface normal. Default 0.
|
|
1733
|
+
- `tolerance?: number` — Maximum allowed gap between adjacent sampled spans. Default 1e-6.
|
|
1734
|
+
|
|
1409
1735
|
### `MatchEdgeBuilder`
|
|
1410
1736
|
|
|
1411
1737
|
- `toG0(neighbor: SheetEdge): Sheet`
|