forgecad 0.9.13 → 0.9.15
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/LICENSE +6 -4
- package/README.md +8 -4
- package/dist/assets/{AdminPage-DramHHDf.js → AdminPage-CDyGUinA.js} +2 -2
- package/dist/assets/{BenchmarkPage-Bjgkh5m9.js → BenchmarkPage-DfPMY_-d.js} +4 -15
- package/dist/assets/{BlogPage-n_HGP3Qm.js → BlogPage-kF0fkdJT.js} +2 -2
- package/dist/assets/{DocsPage-WCIkPmzC.js → DocsPage-B954L3YN.js} +9 -3
- package/dist/assets/EditorApp-Beb-IZ0y.js +14014 -0
- package/dist/assets/{EditorApp-BAnckbsk.css → EditorApp-CuDLxKqL.css} +698 -0
- package/dist/assets/{EmbedViewer-DEZKqdfW.js → EmbedViewer-C77B-TrF.js} +3 -3
- package/dist/assets/{LandingPageProofDriven-CeRIctuj.js → LandingPageProofDriven-Cr6fXMDj.js} +35 -37
- package/dist/assets/LegalPage-BRlScr9A.css +91 -0
- package/dist/assets/LegalPage-Dzklqmmg.js +39 -0
- package/dist/assets/{PricingPage-BMedqFef.css → PricingPage-BPF6HKyO.css} +25 -0
- package/dist/assets/{PricingPage-rIRa8p4Y.js → PricingPage-zWXkvlwl.js} +19 -19
- package/dist/assets/{SettingsPage-BqCUvEXM.js → SettingsPage-Bz0of4KQ.js} +2 -2
- package/dist/assets/app-CE3sYcV7.css +3890 -0
- package/dist/assets/{app-BUZqJvSO.js → app-D3kDkggg.js} +2305 -960
- package/dist/assets/cli/{render-lhGxj50Y.js → render-DSY3mMQa.js} +423 -30
- package/dist/assets/{constructionHistoryWorker-ipD1jcIv.js → constructionHistoryWorker-gpDo-uH2.js} +927 -243
- package/dist/assets/{evalWorker-CHXSe_-u.js → evalWorker-CU0Ke6DP.js} +7799 -4163
- package/dist/assets/{forgecad_geometry-BVnIeXMG.js → forgecad_geometry-Dgceylq9.js} +43 -1
- package/dist/assets/{forgecad_geometry_bg-DufhhCBV.wasm → forgecad_geometry_bg-dD4RNQF1.wasm} +0 -0
- package/dist/assets/{inspectWorker-DeRnMVv1.js → inspectWorker-COyp8XXA.js} +927 -243
- package/dist/assets/{javascript-70-4uGcz.js → javascript-1kQXfVaz.js} +1 -1
- package/dist/assets/landing-proof-driven-DiGqdtWa.js +18 -0
- package/dist/assets/{landing-proof-driven-oFYW6mjz.css → landing-proof-driven-ORyigZ6p.css} +13 -7
- package/dist/assets/legalContent-ZfFGMmi4.js +251 -0
- package/dist/assets/{manifold-D1LZIHqn.js → manifold-BRI5prcH.js} +1 -1
- package/dist/assets/{manifold-C2fwoTgd.js → manifold-C-3h2M7p.js} +2 -2
- package/dist/assets/{manifold-BTkzxi9V.js → manifold-DNkrUWpA.js} +1 -1
- package/dist/assets/{reportWorker-Cq1qGmg0.js → reportWorker-CdBz5bNg.js} +7537 -10856
- package/dist/assets/{scalar-sampling-budget-D9Qv_UlJ.js → scalar-sampling-budget-wJF98aY9.js} +6943 -4345
- package/dist/assets/{scanProxyWorker-Bs2TDgLw.js → scanProxyWorker-B-9VbLIs.js} +32 -1
- package/dist/assets/{renderSceneState-Dr0xPq1A.js → targets-B9sGB5nB.js} +27 -1
- package/dist/assets/{vendor-react-Da3A2QmU.js → vendor-react-6j1Kke-Y.js} +6 -5
- package/dist/cli/render.html +1 -1
- package/dist/docs/index.html +2 -2
- package/dist/docs-raw/AI/ai-native-cad.md +50 -0
- package/dist/docs-raw/AI/usage.md +9 -17
- package/dist/docs-raw/CLI.md +71 -21
- package/dist/docs-raw/component-model.md +27 -11
- package/dist/docs-raw/generated/assembly.md +301 -212
- package/dist/docs-raw/generated/concepts.md +238 -240
- package/dist/docs-raw/generated/core.md +283 -6
- package/dist/docs-raw/generated/curves.md +274 -361
- package/dist/docs-raw/generated/lib.md +7 -1
- package/dist/docs-raw/generated/output.md +19 -4
- package/dist/docs-raw/generated/runtime-names.md +41 -0
- package/dist/docs-raw/generated/sdf.md +31 -0
- package/dist/docs-raw/generated/sheet-metal.md +9 -0
- package/dist/docs-raw/generated/sketch.md +44 -1
- package/dist/docs-raw/generated/viewport.md +14 -6
- package/dist/docs-raw/guides/coordinate-system.md +20 -16
- package/dist/docs-raw/guides/geometry-conventions.md +2 -2
- package/dist/docs-raw/guides/inspection-bundles.md +2 -1
- package/dist/docs-raw/guides/joint-design.md +24 -0
- package/dist/docs-raw/guides/positioning.md +13 -3
- package/dist/docs-raw/legal/privacy.md +63 -0
- package/dist/docs-raw/legal/software-license.md +55 -0
- package/dist/docs-raw/legal/terms.md +87 -0
- package/dist/docs-raw/skills/forgecad-3d-reconstruction.md +3 -3
- package/dist/docs-raw/skills/forgecad-blockout-model.md +1 -1
- package/dist/docs-raw/skills/forgecad-component-model.md +11 -2
- package/dist/docs-raw/skills/forgecad-high-level-spec.md +1 -1
- package/dist/docs-raw/skills/forgecad-image-replicator.md +8 -8
- package/dist/docs-raw/skills/forgecad-lld.md +1 -1
- package/dist/docs-raw/skills/forgecad-make-a-model.md +4 -4
- package/dist/docs-raw/skills/forgecad-model-grader.md +2 -2
- package/dist/docs-raw/skills/forgecad-prepare-prompt.md +2 -2
- package/dist/docs-raw/skills/forgecad-project.md +1 -1
- package/dist/docs-raw/skills/forgecad-reconstruction-benchmark.md +4 -4
- package/dist/docs-raw/skills/forgecad-render-inspect.md +4 -2
- package/dist/docs-raw/skills/forgecad-visual-spec.md +1 -1
- package/dist/docs-raw/skills/forgecad.md +4 -3
- package/dist/index.html +40 -12
- package/dist/llms.txt +8 -0
- package/dist/site.webmanifest +1 -1
- package/dist/sitemap.xml +49 -13
- package/dist-cli/{check-compiler-LOXCPEOI.js → check-compiler-SDX5QIXI.js} +1 -2
- package/dist-cli/{check-query-propagation-BAKNVWXR.js → check-query-propagation-EAYEFT77.js} +1 -2
- package/dist-cli/{chunk-RY43WF46.js → chunk-N4O47JLF.js} +13772 -9938
- package/dist-cli/forgecad.js +2387 -899
- package/dist-cli/{forgecad_geometry-GYVNKPIE.js → forgecad_geometry-QOQIIP53.js} +42 -1
- package/dist-cli/forgecad_geometry_bg.wasm +0 -0
- package/dist-cli/{solver-46FFSK2U.js → solver-OK4HECRH.js} +0 -1
- package/dist-skill/CONTEXT.md +1120 -724
- package/dist-skill/SKILL.md +3 -2
- package/dist-skill/docs/API/core/concepts.md +64 -1
- package/dist-skill/docs/CLI.md +71 -21
- package/dist-skill/docs/generated/assembly.md +277 -229
- package/dist-skill/docs/generated/core.md +283 -6
- package/dist-skill/docs/generated/curves.md +272 -362
- package/dist-skill/docs/generated/lib.md +7 -1
- package/dist-skill/docs/generated/output.md +19 -4
- package/dist-skill/docs/generated/runtime-names.md +41 -0
- package/dist-skill/docs/generated/sdf.md +31 -0
- package/dist-skill/docs/generated/sheet-metal.md +9 -0
- package/dist-skill/docs/generated/sketch.md +44 -2
- package/dist-skill/docs/generated/viewport.md +5 -90
- package/dist-skill/docs/guides/coordinate-system.md +20 -16
- package/dist-skill/docs/guides/geometry-conventions.md +2 -2
- package/dist-skill/docs/guides/inspection-bundles.md +2 -1
- package/dist-skill/docs/guides/joint-design.md +24 -0
- package/dist-skill/docs/guides/positioning.md +13 -3
- package/dist-skill/library/forgecad-3d-reconstruction/SKILL.md +2 -2
- package/dist-skill/library/forgecad-component-model/SKILL.md +10 -1
- package/dist-skill/library/forgecad-image-replicator/SKILL.md +6 -6
- package/dist-skill/library/forgecad-image-replicator/scripts/compare_images.py +166 -0
- package/dist-skill/library/forgecad-make-a-model/SKILL.md +3 -3
- package/dist-skill/library/forgecad-model-grader/SKILL.md +1 -1
- package/dist-skill/library/forgecad-prepare-prompt/SKILL.md +1 -1
- package/dist-skill/library/forgecad-reconstruction-benchmark/SKILL.md +3 -3
- package/dist-skill/library/forgecad-render-inspect/SKILL.md +3 -1
- package/examples/api/assembly-kinematics-foundation.forge.js +65 -0
- package/examples/api/assembly-kinematics-four-bar.forge.js +115 -0
- package/examples/api/assembly-kinematics-limb.forge.js +116 -0
- package/examples/api/connector-frame-rig-chain.forge.js +102 -0
- package/examples/api/exact-sheet-shell-assembly.forge.js +0 -2
- package/examples/api/exact-surface-studio.forge.js +6 -8
- package/examples/api/helix-basics.forge.js +6 -6
- package/examples/api/lean-foundations/README.md +12 -0
- package/examples/api/lean-foundations/curve-blend-exact.forge.js +22 -0
- package/examples/api/lean-foundations/curve-fit-interpolation.forge.js +18 -0
- package/examples/api/lean-foundations/curve-helix-canonicalization.forge.js +27 -0
- package/examples/api/lean-foundations/curve-route-canonicalization.forge.js +16 -0
- package/examples/api/lean-foundations/curve-trim-reverse.forge.js +24 -0
- package/examples/api/lean-foundations/exact-curve-arc.forge.js +36 -0
- package/examples/api/mixed-edge-finishes-proof.forge.js +8 -11
- package/examples/api/route3d-elbow.forge.js +68 -0
- package/examples/api/transition-curves.forge.js +44 -15
- package/examples/api/y-blend-corner-showcase.forge.js +0 -2
- package/examples/generative/coral-vase.forge.js +1 -1
- package/examples/nurbs-tube.forge.js +1 -1
- package/package.json +14 -18
- package/dist/assets/EditorApp-CP9Za6tm.js +0 -13630
- package/dist/assets/app-CsHnaBWt.css +0 -1789
- package/dist/docs-raw/API/README.md +0 -16
- package/dist/docs-raw/API/core/concepts.md +0 -118
- package/dist/docs-raw/INDEX.md +0 -138
- package/dist/docs-raw/RELEASING.md +0 -87
- package/dist/docs-raw/agent-native-api.md +0 -27
- package/dist/docs-raw/beta-deployment.md +0 -304
- package/dist/docs-raw/beta-operations.md +0 -325
- package/dist/docs-raw/blueprint-first.md +0 -145
- package/dist/docs-raw/cli-monetization.md +0 -112
- package/dist/docs-raw/coding-best-practices.md +0 -120
- package/dist/docs-raw/coding.md +0 -340
- package/dist/docs-raw/deployment.md +0 -374
- package/dist/docs-raw/guides/skill-maintenance.md +0 -161
- package/dist/docs-raw/guides/surface-members.md +0 -82
- package/dist/docs-raw/internals/backend-vocabulary.md +0 -35
- package/dist/docs-raw/internals/compiler.md +0 -307
- package/dist/docs-raw/internals/constraint-solver-quality.md +0 -161
- package/dist/docs-raw/internals/constraint-solver.md +0 -176
- package/dist/docs-raw/internals/shape-from-slices.md +0 -152
- package/dist/docs-raw/internals/sketch-2d-pipeline.md +0 -108
- package/dist/docs-raw/platform/admin.md +0 -45
- package/dist/docs-raw/platform/architecture.md +0 -82
- package/dist/docs-raw/platform/auth.md +0 -139
- package/dist/docs-raw/platform/email.md +0 -67
- package/dist/docs-raw/platform/google-oauth-setup.md +0 -88
- package/dist/docs-raw/platform/observability.md +0 -197
- package/dist/docs-raw/platform/projects.md +0 -111
- package/dist/docs-raw/platform/sharing.md +0 -90
- package/dist/docs-raw/product/README.md +0 -39
- package/dist/docs-raw/product/api-as-product-language.md +0 -13
- package/dist/docs-raw/product/business-model.md +0 -15
- package/dist/docs-raw/product/competitive-positioning.md +0 -17
- package/dist/docs-raw/product/creative-manufacturing.md +0 -15
- package/dist/docs-raw/product/founder-story.md +0 -11
- package/dist/docs-raw/product/manufacturing-workflows.md +0 -15
- package/dist/docs-raw/product/onboarding-first-experience.md +0 -256
- package/dist/docs-raw/product/product-loop.md +0 -17
- package/dist/docs-raw/product/strategic-decisions.md +0 -22
- package/dist/docs-raw/product/user-outreach-email-templates.md +0 -161
- package/dist/docs-raw/product/user-segments.md +0 -15
- package/dist/docs-raw/product/vision.md +0 -26
- package/dist/docs-raw/rl-environments.md +0 -508
- package/dist/docs-raw/runbook.md +0 -611
- package/dist-cli/check-compiler-LOXCPEOI.js.map +0 -1
- package/dist-cli/check-query-propagation-BAKNVWXR.js.map +0 -1
- package/dist-cli/chunk-RY43WF46.js.map +0 -1
- package/dist-cli/forgecad.js.map +0 -1
- package/dist-cli/forgecad_geometry-GYVNKPIE.js.map +0 -1
- package/dist-cli/solver-46FFSK2U.js.map +0 -1
- package/dist-skill/SKILL-dev.md +0 -145
- package/dist-skill/docs-dev/API/core/concepts.md +0 -118
- package/dist-skill/docs-dev/CLI.md +0 -647
- package/dist-skill/docs-dev/agent-native-api.md +0 -27
- package/dist-skill/docs-dev/blueprint-first.md +0 -145
- package/dist-skill/docs-dev/coding-best-practices.md +0 -120
- package/dist-skill/docs-dev/coding.md +0 -340
- package/dist-skill/docs-dev/component-model.md +0 -164
- package/dist-skill/docs-dev/generated/assembly.md +0 -794
- package/dist-skill/docs-dev/generated/core.md +0 -2117
- package/dist-skill/docs-dev/generated/curves.md +0 -2583
- package/dist-skill/docs-dev/generated/lib.md +0 -169
- package/dist-skill/docs-dev/generated/output.md +0 -247
- package/dist-skill/docs-dev/generated/sdf.md +0 -446
- package/dist-skill/docs-dev/generated/sheet-metal.md +0 -504
- package/dist-skill/docs-dev/generated/sketch.md +0 -1811
- package/dist-skill/docs-dev/generated/viewport.md +0 -585
- package/dist-skill/docs-dev/generated/wood.md +0 -108
- package/dist-skill/docs-dev/guides/coordinate-system.md +0 -46
- package/dist-skill/docs-dev/guides/geometry-conventions.md +0 -52
- package/dist-skill/docs-dev/guides/inspection-bundles.md +0 -485
- package/dist-skill/docs-dev/guides/joint-design.md +0 -78
- package/dist-skill/docs-dev/guides/modeling-recipes.md +0 -78
- package/dist-skill/docs-dev/guides/positioning.md +0 -161
- package/dist-skill/docs-dev/guides/skill-maintenance.md +0 -161
- package/dist-skill/docs-dev/internals/backend-vocabulary.md +0 -35
- package/dist-skill/docs-dev/internals/compiler.md +0 -307
- package/dist-skill/docs-dev/internals/constraint-solver-quality.md +0 -161
- package/dist-skill/docs-dev/internals/constraint-solver.md +0 -176
- package/dist-skill/docs-dev/internals/sketch-2d-pipeline.md +0 -108
- package/dist-skill/library/forgecad-image-replicator/scripts/compare_images.mjs +0 -289
|
@@ -59,18 +59,24 @@ offsetBand(thickness: number): Sketch
|
|
|
59
59
|
addSpurTeethBetween(options: DriveWheelSpurTeethRegionOptions): this
|
|
60
60
|
```
|
|
61
61
|
|
|
62
|
+
`DriveWheelSpurTeethRegionOptions`: `{ name?: string, teethOnFullCircle: number, toothCount: number, firstTooth?: number, faceWidth?: number }`
|
|
63
|
+
|
|
62
64
|
#### `addSolidArcBetween()` — Add a constant-radius solid arc region such as a dwell, stop, or pusher.
|
|
63
65
|
|
|
64
66
|
```ts
|
|
65
67
|
addSolidArcBetween(options: DriveWheelSolidArcRegionOptions): this
|
|
66
68
|
```
|
|
67
69
|
|
|
70
|
+
**`DriveWheelSolidArcRegionOptions`**: `name?: string`, `fromAngleDeg: number`, `toAngleDeg: number`, `innerRadius?: number`, `outerRadius: number`, `faceWidth?: number`, `segments?: number`
|
|
71
|
+
|
|
68
72
|
#### `addShapeRegion()` — Add a fully custom region shape while preserving region metadata.
|
|
69
73
|
|
|
70
74
|
```ts
|
|
71
75
|
addShapeRegion(name: string, shape: Shape, options?: DriveWheelShapeRegionOptions): this
|
|
72
76
|
```
|
|
73
77
|
|
|
78
|
+
`DriveWheelShapeRegionOptions`: `{ fromAngleDeg?: number, toAngleDeg?: number, innerRadius?: number, outerRadius?: number }`
|
|
79
|
+
|
|
74
80
|
#### `build()` — Build the final wheel shape with a bore connector and region metadata.
|
|
75
81
|
|
|
76
82
|
```ts
|
|
@@ -137,7 +143,7 @@ Sizes outside the supported ranges will throw at runtime with a descriptive erro
|
|
|
137
143
|
- `routedTubeClipAssembly(options: RoutedTubeClipAssemblyOptions): RoutedTubeClipAssemblyResult` — Routed tube or cable retained by saddle clips with real bores, screw holes, and installed screws. **Details** This pattern is for hoses, wires, pump tubes, sensor leads, and appliance cable runs where generated models often draw a cylinder near a wall without clips or strain relief. The base panel has receiving screw envelopes, each saddle clip has a real through-bore around the tube and vertical screw clearances, and the installed screws share those positions. Coordinate convention: the routed tube runs along +X through the world origin. The base panel starts at `z=0`; clips sit on top of the panel, and the tube passes through their bores. **Example** ```ts const route = lib.routedTubeClipAssembly({ tubeDiameter: 6, clipCount: 3, }); verify.notColliding('tube clears clip bores', route.tube, union(...route.clips)); verify.notColliding('clip screws clear retained stack', union(...route.screws), union(route.panel, ...route.clips)); return route.parts; ```
|
|
138
144
|
- `pcbTerminalBlockAssembly(options?: PcbTerminalBlockAssemblyOptions): PcbTerminalBlockAssemblyResult` — PCB terminal-block stack with a backplate, standoffs, mounting screws, pin holes, and a seated terminal block. **Details** This pattern is for thermostat backplates, appliance control panels, sensor boards, and small electronics where generated models often place a terminal block, screw heads, and holes as independent decorations. The PCB mounting holes, fused standoffs, installed screws, terminal pins, and PCB pin clearances all come from one shared datum system so the purchased block is mechanically seated and the board is actually mounted. Coordinate convention: X/Y are the board footprint, Z is up. The backplate starts at `z=0`, standoffs rise from the plate, the PCB rests on the standoffs, and the terminal block sits on top of the PCB near the front edge. **Example** ```ts const terminalStack = lib.pcbTerminalBlockAssembly({ terminalCount: 5, screwSize: 'M3', }); verify.notColliding('terminal pins clear PCB holes', terminalStack.terminalBlock, terminalStack.pcb); verify.notColliding('mounting screws clear PCB and standoff holes', union(...terminalStack.screws), union(terminalStack.pcb, terminalStack.backplate)); return terminalStack.parts; ```
|
|
139
145
|
- `thumbScrewClampAssembly(options?: ThumbScrewClampAssemblyOptions): ThumbScrewClampAssemblyResult` — Thumb-screw clamp with a C-frame, threaded boss, captive pressure pad, knob, and clamped workpiece. **Details** This pattern is for bench clamps, monitor-arm desk clamps, small vise screws, capo pressure screws, fixture hold-downs, and service brackets where generated models often place a loose screw, knob, or pressure pad near a bracket. The helper creates a one-piece clamp frame with a fixed anvil pad, a bored threaded support and boss, an installed screw with a captive pressure pad and hand knob, and a representative clamped workpiece seated between the pads. Coordinate convention: the clamp screw runs along +X. The fixed anvil is on the -X side, the threaded support and knob are on the +X side, and Z is up from the base bridge. **Example** ```ts const clamp = lib.thumbScrewClampAssembly({ screwSize: 'M6', workpieceThickness: 20, }); verify.notColliding('thumb screw clears threaded boss', clamp.clampScrew, clamp.frame); verify.clearanceBetween('pressure pad is seated on workpiece', clamp.clampScrew, clamp.workpiece, -0.01, 0.05); return clamp.parts; ```
|
|
140
|
-
- `pipeRoute(points: [ number, number, number ][], radius: number, options?: { bendRadius?: number; wall?: number; segments?: number; }): Shape` — Route a pipe (solid or hollow) through 3D waypoints with smooth bends.
|
|
146
|
+
- `pipeRoute(points: [ number, number, number ][], radius: number, options?: { bendRadius?: number; wall?: number; segments?: number; }): Shape` — Route a pipe (solid or hollow) through 3D waypoints with smooth bends. This is a convenience recipe over `Curve.Route.fromPolyline()` and [`sweep()`](/docs/curves#sweep). Use `Curve.Route` directly when you need route metadata, named ports, or custom swept profiles.
|
|
141
147
|
- `elbow(pipeRadius: number, bendRadius: number, angle?: number | { ... }, options?: { ... }): Shape` — Pipe elbow — a curved pipe section (torus arc) for connecting two pipe directions. By default creates a bend in the XZ plane: incoming along +Z, outgoing rotated by `angle`. The bend starts at the origin, curving away from it.
|
|
142
148
|
- `beltDrive(options: BeltDriveOptions): BeltDriveResult` — Create a flat open-belt body around two pulley pitch circles. The belt is generated as a tangent loop in the XY plane and extruded along +Z by `beltWidth`. The result includes the solid belt, the 2D belt profile, a thin pitch-path sketch for visualization, total belt length, tangent spans, and wrap metadata for each pulley. For more than two pulleys, the API intentionally asks for route intent before geometry is created. Use `route: "outer"` for the future outside-envelope mode, or an ordered route for future serpentine/idler layouts. ```ts const drive = lib.beltDrive({ pulleys: [ { name: "motor", center: [0, 0], pitchRadius: 12 }, { name: "output", center: [80, 0], pitchRadius: 28 }, ], beltWidth: 8, beltThickness: 2, }); return drive.belt; ```
|
|
143
149
|
- `tangentLoop2d(circles: TangentCircle2D[], options?: TangentLoop2DOptions): TangentLoop2D` — Build a closed 2D route made from common tangent spans and pulley wrap arcs. Use this when you need reusable belt/chain route geometry before creating a solid body. The first implementation supports two circles. `mode: "open"` uses external tangents; `mode: "crossed"` uses internal tangents. ```ts const route = lib.tangentLoop2d([ { center: [0, 0], radius: 12 }, { center: [80, 0], radius: 28 }, ]); const belt = route.offsetBand(2).extrude(8); ```
|
|
@@ -68,7 +68,7 @@ Call `robotExport()` alongside your assembly definition. The CLI commands `forge
|
|
|
68
68
|
|
|
69
69
|
- Mesh-based inertia tensors (full 6-component, not bounding-box approximations)
|
|
70
70
|
- Separate collision meshes (convex hull by default — ~50–80% smaller)
|
|
71
|
-
- Joint
|
|
71
|
+
- Joint limits, effort/velocity/damping/friction metadata from assembly joints
|
|
72
72
|
|
|
73
73
|
**Collision mesh modes** (set per-link via `links["PartName"].collision`):
|
|
74
74
|
|
|
@@ -84,7 +84,7 @@ Call `robotExport()` alongside your assembly definition. The CLI commands `forge
|
|
|
84
84
|
- Revolute `velocity` is in degrees/second in Forge; exporters convert to rad/s.
|
|
85
85
|
- Prismatic distances are in mm in Forge; exported in meters.
|
|
86
86
|
- `massKg` is preferred; `densityKgM3` is used when mass is unknown.
|
|
87
|
-
-
|
|
87
|
+
- Compatibility coupling metadata, when present, maps only the primary term (largest ratio) to `<mimic>` — SDF/URDF support single-leader mimic only. Dropped terms emit a warning.
|
|
88
88
|
|
|
89
89
|
```ts
|
|
90
90
|
const rover = assembly("Scout")
|
|
@@ -140,9 +140,9 @@ robotExport(options: RobotExportOptions): CollectedRobotExport
|
|
|
140
140
|
|
|
141
141
|
**`CollectedRobotExport`**: `modelName: string`, `assembly: AssemblyDefinition`, `state: JointState`, `static: boolean`, `selfCollide: boolean`, `allowAutoDisable: boolean`, `links: Record<string, RobotLinkExportOptions>`, `joints: Record<string, RobotJointExportOptions>`, `plugins: { diffDrive?: RobotDiffDrivePluginOptions; jointStatePublisher?: RobotJointStatePublisherOptions; }`, `world: RobotWorldOptions | null`
|
|
142
142
|
|
|
143
|
-
|
|
143
|
+
**`AssemblyDefinition`**: `name: string`, `parts: AssemblyPartDef[]`, `joints: AssemblyJointDef[]`, `jointCouplings: AssemblyJointCouplingDef[]`, `kinematics: AssemblyKinematicGraphDef`
|
|
144
144
|
|
|
145
|
-
`AssemblyPartDef`: `{ name: string, part: AssemblyPart, base: Transform, metadata?: PartMetadata }`
|
|
145
|
+
`AssemblyPartDef`: `{ name: string, part: AssemblyPart, base: Transform, metadata?: PartMetadata, mates: AssemblyPartMateInput[] }`
|
|
146
146
|
|
|
147
147
|
**`PartMetadata`**
|
|
148
148
|
|
|
@@ -151,6 +151,11 @@ robotExport(options: RobotExportOptions): CollectedRobotExport
|
|
|
151
151
|
| `tags?` | `string \| readonly string[]` | Viewport organization tags applied to scene objects produced from this part. |
|
|
152
152
|
| `material?`, `process?`, `tolerance?`, `qty?`, `notes?`, `densityKgM3?`, `massKg?` | | — |
|
|
153
153
|
|
|
154
|
+
**`AssemblyPartMateInput`**
|
|
155
|
+
- `connector: string` — Name of a connector declared on the part (via `withConnectors()`).
|
|
156
|
+
- `toLink: string` — Name of the link this connector's origin is pinned to.
|
|
157
|
+
- `aimLink?: string` — Optional second link to orient toward. When set, the part is rotated so the connector's **axis** aims from `toLink` toward `aimLink`, posing an oriented bone instead of only translating it. For full pose without relying on a connector axis, declare a second mate (two connectors → two links).
|
|
158
|
+
|
|
154
159
|
**`AssemblyJointDef`**: `name: string`, `type: JointType`, `parent: string`, `child: string`, `frame: Transform`, `axis: Vec3`, `min?: number`, `max?: number`, `defaultValue: number`, `unit?: string`, `effort?: number`, `velocity?: number`, `damping?: number`, `friction?: number`, `connectorRefs?: JointConnectorRefs`
|
|
155
160
|
|
|
156
161
|
`JointConnectorRefs`: `{ parent: string, child: string, parentAlign?: PortAlign, childAlign?: PortAlign }`
|
|
@@ -159,6 +164,16 @@ robotExport(options: RobotExportOptions): CollectedRobotExport
|
|
|
159
164
|
|
|
160
165
|
`JointCouplingTermRecord`: `{ joint: string, ratio: number }`
|
|
161
166
|
|
|
167
|
+
`AssemblyKinematicGraphDef`: `{ links: AssemblyLinkDef[], edges: AssemblyEdgeBetweenLinksDef[], angles: AssemblyAngleBetweenLinksDef[] }`
|
|
168
|
+
|
|
169
|
+
`AssemblyLinkDef`: `{ name: string, at: Vec3, fixed: boolean, metadata?: Record<string, unknown> }`
|
|
170
|
+
|
|
171
|
+
**`AssemblyEdgeBetweenLinksDef`**: `name: string`, `a: string`, `b: string`, `length: number | null`, `min?: number`, `max?: number`, `visualOnly: boolean`, `control?: AssemblyKinematicControlOptions`, `metadata?: Record<string, unknown>`
|
|
172
|
+
|
|
173
|
+
`AssemblyKinematicControlOptions`: `{ min?: number, max?: number, default?: number, unit?: string }`
|
|
174
|
+
|
|
175
|
+
**`AssemblyAngleBetweenLinksDef`**: `name: string`, `a: string`, `b: string`, `c: string`, `target?: number`, `min?: number`, `max?: number`, `control?: AssemblyKinematicControlOptions`, `metadata?: Record<string, unknown>`
|
|
176
|
+
|
|
162
177
|
#### `dim()` — Add a dimension annotation between two points.
|
|
163
178
|
|
|
164
179
|
Dimension annotations are purely visual callouts rendered in the viewport and report export. They do not affect geometry or constrain the model.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
skill-group: core
|
|
3
|
+
skill-order: 2
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Runtime Names
|
|
7
|
+
|
|
8
|
+
Generated by `scripts/gen-api-docs.mjs` from `src/forge/script-runtime/runScript.ts`. Do not edit by hand.
|
|
9
|
+
|
|
10
|
+
ForgeCAD injects API functions, classes, namespaces, and sandbox guard names into every `.forge.js` script. Top-level lexical declarations using these names collide with the injected runtime bindings when the script runs.
|
|
11
|
+
|
|
12
|
+
Agents should avoid declaring these names with top-level `const`, `let`, destructured imports, or `class` declarations. Use project-specific local names such as `wheelLib`, `axleSlotSketch`, `driveJointConfig`, or `labelTextSketch` instead.
|
|
13
|
+
|
|
14
|
+
These collision-reserved names are case-sensitive:
|
|
15
|
+
|
|
16
|
+
```text
|
|
17
|
+
activateBackend, Analysis, arcSlot, assembly, Assembly, assemblyInstructions, assemblyPreview, Blend
|
|
18
|
+
bom, bomToCsv, boolParam, box, cameraTrajectory, Carrier, chamfer, chamferTrackedEdge
|
|
19
|
+
choiceParam, circle, circle2d, Circle2D, circularLayout, circularPattern, circularPattern2d, coalesceEdges
|
|
20
|
+
combine, COMMON_KERFS, compareWith, composeChain, connectEdges, connector, console, constrainedSketch
|
|
21
|
+
Constraint, Counterbore, Curve, Curve3D, cutPlane, cylinder, degrees, difference
|
|
22
|
+
difference2d, dim, dimLine, draft, ellipse, explodeView, faceProfile, fillet
|
|
23
|
+
filletCorners, filletTrackedEdge, fingerJoint, flatPanel, flatPart, formatInstructions, Function, gcode
|
|
24
|
+
GCodeBuilder, getActiveBackend, global, globalThis, group, Helix, HelixCurve, hermiteTransitionG2
|
|
25
|
+
highlight, Import, ImportedAssembly, importMesh, importStep, importSvgSketch, initKernel, intersection
|
|
26
|
+
intersection2d, intersectWithPlane, joint, jointsView, laserKit, lib, line, Line2D
|
|
27
|
+
linearPattern, linearPattern2d, listParam, loadFont, loft, Loft, loftAlongSpine, lookupKerf
|
|
28
|
+
mirrorCopy, mock, ngon, nurbs3d, NurbsCurve3D, nurbsSurface, NurbsSurface, offsetSolid
|
|
29
|
+
param, Param, path, point, Point2D, Points, polygon, polygonVertices
|
|
30
|
+
port, Product, ProductHandleBuilder, ProductHandleFeature, ProductPanelBuilder, ProductRibbonBuilder, ProductSkin, ProductSkinBuilder
|
|
31
|
+
ProductSpoutBuilder, ProductStationBuilder, ProductSurfaceBuilder, ProductSurfaceRef, projectToPlane, queueMicrotask, radians, rect
|
|
32
|
+
Rectangle2D, Ribs, robotExport, roundedRect, Route3D, scene, Sculpt, sdf
|
|
33
|
+
SdfShape, selectEdge, selectEdges, self, setActiveBackend, setImmediate, setInterval, setTimeout
|
|
34
|
+
Shape, ShapeGroup, sheetMetal, SheetMetalPart, sheetStock, Sketch, sketchToDxf, sketchToSvg
|
|
35
|
+
slot, Slot, SolvedAssembly, spec, sphere, spline2d, spline3d, star
|
|
36
|
+
stroke, Surface, SurfaceBody, SurfaceMembers, surfacePatch, sweep, tabSlot, text2d
|
|
37
|
+
textWidth, torus, toShape, Transform, transitionCurve, transitionSurface, union, union2d
|
|
38
|
+
variableSweep, verify, viewConfig, Viewport, window, Wood
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
`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.
|
|
@@ -101,12 +101,33 @@ color(value: string | undefined): SdfShape
|
|
|
101
101
|
material(props: ShapeMaterialProps): SdfShape
|
|
102
102
|
```
|
|
103
103
|
|
|
104
|
+
**`ShapeMaterialProps`**
|
|
105
|
+
|
|
106
|
+
| Option | Type | Description |
|
|
107
|
+
|--------|------|-------------|
|
|
108
|
+
| `metalness?` | `number` | Metalness factor (0 = dielectric, 1 = metal). Default: 0.05 |
|
|
109
|
+
| `roughness?` | `number` | Roughness factor (0 = mirror, 1 = fully diffuse). Default: 0.35 |
|
|
110
|
+
| `emissive?` | `string` | Emissive glow color (hex string, e.g. "#ff6b35"). |
|
|
111
|
+
| `emissiveIntensity?` | `number` | Emissive intensity multiplier. Default: 1 |
|
|
112
|
+
| `opacity?` | `number` | Opacity (0 = fully transparent, 1 = fully opaque). Default: 1 |
|
|
113
|
+
| `wireframe?` | `boolean` | Render as wireframe. Default: false |
|
|
114
|
+
| `clearcoat?` | `number` | Clearcoat intensity (0–1). Default: 0.1 |
|
|
115
|
+
| `clearcoatRoughness?` | `number` | Clearcoat roughness (0–1). Default: 0.4 |
|
|
116
|
+
| `transmission?` | `number` | Glass/translucency transmission factor (0–1). Renderer support depends on target. |
|
|
117
|
+
| `ior?` | `number` | Index of refraction for transmissive materials. Typical glass is ~1.45. |
|
|
118
|
+
| `thickness?` | `number` | Approximate transmissive volume thickness in model units. |
|
|
119
|
+
| `specularIntensity?` | `number` | Specular highlight intensity (0–1). |
|
|
120
|
+
| `specularColor?` | `string` | Specular highlight tint. |
|
|
121
|
+
| `reflectivity?` | `number` | Reflection strength for supported renderers (0–1). |
|
|
122
|
+
|
|
104
123
|
#### `bounds()` — Set explicit preview/meshing bounds for this implicit leaf.
|
|
105
124
|
|
|
106
125
|
```ts
|
|
107
126
|
bounds(bounds: SdfBounds | [ Vec3, Vec3 ]): SdfShape
|
|
108
127
|
```
|
|
109
128
|
|
|
129
|
+
`SdfBounds`: `{ min: Vec3, max: Vec3 }`
|
|
130
|
+
|
|
110
131
|
#### `at()` — Sculpt-style alias for translate().
|
|
111
132
|
|
|
112
133
|
```ts
|
|
@@ -203,6 +224,12 @@ fillWith(pattern: SdfShape): SdfShape
|
|
|
203
224
|
fillWithGyroid(options: TpmsOptions): SdfShape
|
|
204
225
|
```
|
|
205
226
|
|
|
227
|
+
**`TpmsOptions`**
|
|
228
|
+
- `thickness?: number` — Dimensionless field threshold kept for compatibility. Prefer `wallThickness` for approximate millimeter units.
|
|
229
|
+
- `wallThickness?: number` — Approximate physical wall thickness in millimeters.
|
|
230
|
+
- `tpmsThicknessMode?: TpmsThicknessMode` — Override TPMS thickness interpretation. Defaults to metric when `wallThickness` is used, field-threshold when `thickness` is used.
|
|
231
|
+
- Also: `cellSize: number`
|
|
232
|
+
|
|
206
233
|
#### `fillWithSchwarzP()` — Keep only the Schwarz-P lattice inside this shape.
|
|
207
234
|
|
|
208
235
|
```ts
|
|
@@ -353,6 +380,10 @@ shape.surfaceDisplace((u, v) => -Math.sin(u * 2) * 0.3)
|
|
|
353
380
|
surfaceDisplace(pattern: SurfacePattern | ((u: number, v: number) => number), options?: SurfaceDisplaceOptions): SdfShape
|
|
354
381
|
```
|
|
355
382
|
|
|
383
|
+
**`SurfaceDisplaceOptions`**
|
|
384
|
+
- `uv?: "auto" | "sphere" | "cylinder" | "torus" | "triplanar"` — Override auto-detected UV mode. Default: 'auto' (detects from SDF tree).
|
|
385
|
+
- `triplanarSharpness?: number` — Triplanar blend sharpness — higher = crisper transitions. Default: 4. Only used in triplanar mode.
|
|
386
|
+
|
|
356
387
|
#### `onion()` — Create concentric onion layers.
|
|
357
388
|
|
|
358
389
|
```ts
|
|
@@ -284,6 +284,10 @@ const part = sheetMetal({ panel: { width: 100, height: 60 }, thickness: 1.5, ben
|
|
|
284
284
|
flange(edge: SheetMetalEdge, options: SheetMetalFlangeOptions): SheetMetalPart
|
|
285
285
|
```
|
|
286
286
|
|
|
287
|
+
**`SheetMetalFlangeOptions`**
|
|
288
|
+
- `length: number` — Flange leg length in mm, measured from the outside of the bend to the tip.
|
|
289
|
+
- `angleDeg?: number` — Bend angle in degrees (default: `90`). Only `90°` is supported in v1. Values other than 90 will be rejected at build time.
|
|
290
|
+
|
|
287
291
|
#### `cutout()` — Subtract a 2D sketch cutout from a planar region of the sheet metal part.
|
|
288
292
|
|
|
289
293
|
`region` must be `'panel'` or one of `'flange-top'`, `'flange-right'`, `'flange-bottom'`, `'flange-left'` (only available once the corresponding flange has been added). Cutouts inside bend regions are **not** supported in v1.
|
|
@@ -303,6 +307,11 @@ const part = sheetMetal({ panel: { width: 180, height: 110 }, thickness: 1.5, be
|
|
|
303
307
|
cutout(region: SheetMetalPlanarRegionName, sketch: Sketch, options?: SheetMetalCutoutOptions): SheetMetalPart
|
|
304
308
|
```
|
|
305
309
|
|
|
310
|
+
**`SheetMetalCutoutOptions`**
|
|
311
|
+
- `u?: number` — Horizontal offset within the region, measured from the region centre (mm). Default: `0`.
|
|
312
|
+
- `v?: number` — Vertical offset within the region, measured from the region centre (mm). Default: `0`.
|
|
313
|
+
- `selfAnchor?: Anchor` — Anchor point on the sketch that aligns to `(u, v)`. Use `'center'` for most cases. For asymmetric profiles, verify orientation by placing one test cutout before committing to the final position. Default: `'center'`.
|
|
314
|
+
|
|
306
315
|
#### `regionNames()` — Return all semantic region names currently available on this part.
|
|
307
316
|
|
|
308
317
|
The returned list always includes `'panel'`. For every flange that has been added, the list also includes the corresponding `'flange-<edge>'` and `'bend-<edge>'` entries.
|
|
@@ -500,7 +500,6 @@ addRegularPolygon(sk: ConstrainedSketchBuilder, options: RegularPolygonOptions):
|
|
|
500
500
|
| `startAngle?` | `number` | Angle (in degrees) of vertex[0] measured from the +X axis (CCW positive). Default: 0 (rightmost vertex). |
|
|
501
501
|
| `blockRotation?` | `boolean` | Prevent 180° rotation (ensures first edge maintains its initial direction). Default: false. |
|
|
502
502
|
|
|
503
|
-
|
|
504
503
|
**`ConstrainedRegularPolygon`** extends ConstrainedPolygon
|
|
505
504
|
- `center: PointId` — Center point. Use `sk.fix(poly.center, x, y)` to pin location, or `sk.coincident(poly.center, other)` to align with other geometry.
|
|
506
505
|
|
|
@@ -740,7 +739,7 @@ region(seed: [ number, number ]): Sketch
|
|
|
740
739
|
extrude(height: number, opts?: { twist?: number; divisions?: number; scaleTop?: number | [ number, number ]; }): Shape
|
|
741
740
|
```
|
|
742
741
|
|
|
743
|
-
#### `revolve()` — Revolve this 2D sketch around the
|
|
742
|
+
#### `revolve()` — Revolve this 2D sketch around the world Z axis. Sketch X is radius; sketch Y becomes world Z height.
|
|
744
743
|
|
|
745
744
|
```ts
|
|
746
745
|
revolve(degrees?: number, segments?: number): Shape
|
|
@@ -771,6 +770,22 @@ Use this when a 2D profile should be oriented onto a 3D face before extrusion or
|
|
|
771
770
|
onFace(parentOrFace: Shape | { toShape(): Shape; } | { _bbox(): { min: number[]; max: number[]; }; } | FaceRef, faceOrOpts?: "front" | "back" | "left" | "right" | "top" | "bottom" | string | FaceRef | { u?: number; v?: number; protrude?: number; selfAnchor?: Anchor; }, opts?: { u?: number; v?: number; protrude?: number; selfAnchor?: Anchor; }): Sketch
|
|
772
771
|
```
|
|
773
772
|
|
|
773
|
+
**`FaceRef`**
|
|
774
|
+
|
|
775
|
+
| Option | Type | Description |
|
|
776
|
+
|--------|------|-------------|
|
|
777
|
+
| `normal` | `[ number, number, number ]` | Normal direction of the face |
|
|
778
|
+
| `center` | `[ number, number, number ]` | Center point of the face |
|
|
779
|
+
| `query?` | `FaceQueryRef` | Compiler-owned face query when available. |
|
|
780
|
+
| `planar?` | `boolean` | True when the face can host a 2D sketch placement frame |
|
|
781
|
+
| `uAxis?` | `[ number, number, number ]` | Face-local horizontal axis for planar faces |
|
|
782
|
+
| `vAxis?` | `[ number, number, number ]` | Face-local vertical axis for planar faces |
|
|
783
|
+
| `surface?` | `FaceSurface` | Analytic surface family when the backend can identify one. |
|
|
784
|
+
| `descendant?` | `FaceDescendantMetadata` | Shared descendant-resolution metadata when this face is a semantic region/set. |
|
|
785
|
+
| `name` | | — |
|
|
786
|
+
|
|
787
|
+
**`FaceDescendantMetadata`**: `kind: "single" | "face-set"`, `semantic: FaceDescendantSemantic`, `memberCount: number`, `memberNames: string[]`, `coplanar: boolean`
|
|
788
|
+
|
|
774
789
|
**Labels**
|
|
775
790
|
|
|
776
791
|
#### `labelEdge()` — Label the single boundary edge (for circles, single-loop profiles). Returns a new sketch.
|
|
@@ -1069,6 +1084,16 @@ regularPolygon(options: RegularPolygonOptions): ConstrainedRegularPolygon
|
|
|
1069
1084
|
groupRect(options: GroupRectOptions): ConstrainedGroupRect
|
|
1070
1085
|
```
|
|
1071
1086
|
|
|
1087
|
+
**`GroupRectOptions`**
|
|
1088
|
+
|
|
1089
|
+
| Option | Type | Description |
|
|
1090
|
+
|--------|------|-------------|
|
|
1091
|
+
| `x?` | `number` | Bottom-left x coordinate (world). Default: 0. |
|
|
1092
|
+
| `y?` | `number` | Bottom-left y coordinate (world). Default: 0. |
|
|
1093
|
+
| `width` | `number` | Width (along x in local coords). Required. |
|
|
1094
|
+
| `height` | `number` | Height (along y in local coords). Required. |
|
|
1095
|
+
| `allowRotation?` | `boolean` | Allow the solver to rotate this rectangle. Default: false. |
|
|
1096
|
+
|
|
1072
1097
|
**Geometric Constraints**
|
|
1073
1098
|
|
|
1074
1099
|
#### `horizontal()` — Constrain a line to be horizontal (parallel to the X axis).
|
|
@@ -1412,6 +1437,23 @@ result.withUpdatedConstraint('cst-5', 120); // update a dimension without rebuil
|
|
|
1412
1437
|
solve(options?: SolveOptions): ConstraintSketch | Sketch
|
|
1413
1438
|
```
|
|
1414
1439
|
|
|
1440
|
+
**`SolveOptions`**
|
|
1441
|
+
|
|
1442
|
+
| Option | Type | Description |
|
|
1443
|
+
|--------|------|-------------|
|
|
1444
|
+
| `iterations?` | `number` | Maximum number of LM outer iterations per restart. |
|
|
1445
|
+
| `tolerance?` | `number` | Infinity-norm residual tolerance for declaring convergence. |
|
|
1446
|
+
| `restarts?` | `number` | Number of deterministic restart seeds used by the global solver. |
|
|
1447
|
+
| `warmStartIterations?` | `number` | Optional projector iterations used only for initialisation, not as the main solver. |
|
|
1448
|
+
| `maxScaledStep?` | `number` | Maximum LM step length in scaled variable space. Larger = bolder, smaller = safer. |
|
|
1449
|
+
| `skipRedundancyCheck?` | `boolean` | Skip redundancy detection (safe when topology is unchanged and previous DOF >= 0). |
|
|
1450
|
+
| `presolveConstraintId?` | `string` | Run the targeted presolve hook for this constraint before the main solve. |
|
|
1451
|
+
| `fallbackRestarts?` | `number` | When set and the first solve exceeds tolerance*5, retry with this many restarts. |
|
|
1452
|
+
| `progressive?` | `boolean` | Add constraints progressively with short LM solves, all in one WASM call. |
|
|
1453
|
+
| `timeBudgetMs?` | `number` | Wall-clock time budget in ms for the entire solve. 0 = no limit. |
|
|
1454
|
+
| `debugConstructiveTranscript?` | `boolean` | Capture a readable constructive transcript in `constraintMeta.debug`. |
|
|
1455
|
+
| `debugSvgSnapshots?` | `boolean` | Capture SVG snapshots for constructive steps in `constraintMeta.debug`. |
|
|
1456
|
+
|
|
1415
1457
|
#### `solveConstraintsOnly()` — Run the solver without building a full `ConstraintSketch`.
|
|
1416
1458
|
|
|
1417
1459
|
Lighter than `solve()` — skips profile and DOF analysis. Useful for lightweight constraint validation or progress monitoring mid-construction.
|
|
@@ -9,7 +9,7 @@ Cut planes, exploded views, joint animations, and scene configuration.
|
|
|
9
9
|
|
|
10
10
|
## Contents
|
|
11
11
|
|
|
12
|
-
- [Viewport & Runtime](#viewport-runtime) — `Viewport.label`, `scene`, `viewConfig`, `explodeView`, `
|
|
12
|
+
- [Viewport & Runtime](#viewport-runtime) — `Viewport.label`, `scene`, `viewConfig`, `explodeView`, `compareWith`, `cutPlane`, `mock`, `showLabels`, `highlight`
|
|
13
13
|
- [RouteBuilder](#routebuilder)
|
|
14
14
|
- [route](#route)
|
|
15
15
|
|
|
@@ -196,7 +196,7 @@ scene(options: SceneOptions): void
|
|
|
196
196
|
|
|
197
197
|
#### `viewConfig()` — Configure viewport helper visuals for the current script execution.
|
|
198
198
|
|
|
199
|
-
Controls renderer-only overlays that appear in the viewport but are not part of the geometry. Currently supports the joint overlay that renders axis arrows and arc indicators when
|
|
199
|
+
Controls renderer-only overlays that appear in the viewport but are not part of the geometry. Currently supports the joint overlay that renders axis arrows and arc indicators when joint controls are active. Multiple calls merge — later values override earlier ones per key.
|
|
200
200
|
|
|
201
201
|
This does **not** trigger a geometry recompute; it only affects the visual helpers drawn on top of the 3D scene.
|
|
202
202
|
|
|
@@ -253,91 +253,6 @@ explodeView(options?: ExplodeViewOptions): void
|
|
|
253
253
|
- `direction?: ExplodeDirection` — Direction mode for this node
|
|
254
254
|
- `axisLock?: ExplodeAxis` — Optional axis lock after direction is resolved
|
|
255
255
|
|
|
256
|
-
#### `jointsView()` — Register viewport-only mechanism controls that animate returned objects without re-running the script.
|
|
257
|
-
|
|
258
|
-
Defines joints (revolute or prismatic), optional gear/rack couplings, and named animations. The viewport resolves transforms through the joint chain at display time — the script geometry is computed only once at rest pose.
|
|
259
|
-
|
|
260
|
-
**Critical:** Solve the assembly at **rest pose** (all animated joints = 0). The viewport applies `jointsView` transforms on top of the returned scene. If geometry is already solved at non-zero angles, animation will double-rotate everything.
|
|
261
|
-
|
|
262
|
-
```js
|
|
263
|
-
// BAD — double rotation
|
|
264
|
-
const solved = mech.solve({ shoulder: 45, elbow: 30 });
|
|
265
|
-
jointsView({ joints: [{ name: 'shoulder', ... }] });
|
|
266
|
-
return solved;
|
|
267
|
-
|
|
268
|
-
// GOOD — rest pose, jointsView controls all posing
|
|
269
|
-
const solved = mech.solve({ shoulder: 0, elbow: 0 });
|
|
270
|
-
jointsView({
|
|
271
|
-
joints: [
|
|
272
|
-
{ name: 'shoulder', child: 'Upper Arm', default: 45, ... },
|
|
273
|
-
{ name: 'elbow', child: 'Forearm', parent: 'Upper Arm', default: 30, ... },
|
|
274
|
-
],
|
|
275
|
-
});
|
|
276
|
-
return solved;
|
|
277
|
-
```
|
|
278
|
-
|
|
279
|
-
**Pivot coordinates** are world-space positions of each joint origin at rest pose. For `addRevolute('shoulder', 'Base', 'Link', { frame: Transform.identity().translate(0, 0, 20) })` where "Base" is at world origin, the pivot is `[0, 0, 20]`.
|
|
280
|
-
|
|
281
|
-
**Fixed attachments** that must follow a parent during animation need a zero-angle revolute joint in the chain:
|
|
282
|
-
|
|
283
|
-
```js
|
|
284
|
-
{ name: 'EE_Follow', child: 'End Effector', parent: 'Last Link',
|
|
285
|
-
type: 'revolute', axis: [0, 0, 1], pivot: [linkLength, 0, 0],
|
|
286
|
-
min: 0, max: 0, default: 0 }
|
|
287
|
-
```
|
|
288
|
-
|
|
289
|
-
Animation values are interpolated linearly between keyframes. ForgeCAD does **not** auto-wrap revolute values across `-180/180`. Keep keyframe values continuous — a `-180 -> 171` jump spins the part the long way around. Use `-180 -> -189` instead. Author high-speed multi-turn joints as accumulating angles (`0, 360, 720, ...`) with `continuous: true`.
|
|
290
|
-
|
|
291
|
-
**Tick-based keyframes:** Omit `at` from all keyframes to auto-distribute by tick weight:
|
|
292
|
-
|
|
293
|
-
```js
|
|
294
|
-
keyframes: [
|
|
295
|
-
{ ticks: 3, values: { Shoulder: 20 } }, // slow segment (3x weight)
|
|
296
|
-
{ ticks: 1, values: { Shoulder: -10 } }, // fast segment (1x weight)
|
|
297
|
-
{ values: { Shoulder: 20 } }, // last keyframe; ticks ignored
|
|
298
|
-
]
|
|
299
|
-
// positions: 0, 0.75, 1.0
|
|
300
|
-
```
|
|
301
|
-
|
|
302
|
-
Mixing explicit `at` and omitted `at` in the same animation is not allowed.
|
|
303
|
-
|
|
304
|
-
```js
|
|
305
|
-
jointsView({
|
|
306
|
-
joints: [{
|
|
307
|
-
name: 'Shoulder', child: 'Upper Arm', parent: 'Base',
|
|
308
|
-
type: 'revolute', axis: [0, -1, 0], pivot: [0, 0, 46],
|
|
309
|
-
min: -30, max: 110, default: 15,
|
|
310
|
-
}],
|
|
311
|
-
animations: [{
|
|
312
|
-
name: 'Walk Cycle', duration: 1.6, loop: true,
|
|
313
|
-
keyframes: [
|
|
314
|
-
{ values: { Shoulder: 20 } },
|
|
315
|
-
{ values: { Shoulder: -10 } },
|
|
316
|
-
{ values: { Shoulder: 20 } },
|
|
317
|
-
],
|
|
318
|
-
}],
|
|
319
|
-
});
|
|
320
|
-
```
|
|
321
|
-
|
|
322
|
-
```ts
|
|
323
|
-
jointsView(options?: JointsViewOptions): void
|
|
324
|
-
```
|
|
325
|
-
|
|
326
|
-
**`JointsViewOptions`**: `enabled?: boolean`, `joints?: JointViewInput[]`, `couplings?: JointViewCouplingInput[]`, `animations?: JointViewAnimationInput[]`, `defaultAnimation?: string`
|
|
327
|
-
|
|
328
|
-
**`JointViewInput`**: `name: string`, `child: string`, `parent?: string`, `type?: JointViewType`, `axis?: JointViewAxis`, `pivot?: [ number, number, number ]`, `min?: number`, `max?: number`, `default?: number`, `unit?: string`, `hidden?: boolean`
|
|
329
|
-
|
|
330
|
-
`JointViewCouplingInput`: `{ joint: string, terms: JointViewCouplingTermInput[], offset?: number }`
|
|
331
|
-
|
|
332
|
-
`JointViewCouplingTermInput`: `{ joint: string, ratio?: number }`
|
|
333
|
-
|
|
334
|
-
`JointViewAnimationInput`: `{ name: string, duration?: number, loop?: boolean, continuous?: boolean, keyframes: JointViewAnimationKeyframeInput[] }`
|
|
335
|
-
|
|
336
|
-
**`JointViewAnimationKeyframeInput`**
|
|
337
|
-
- `at?: number` — Timeline position [0, 1]. If omitted from ALL keyframes, positions are auto-computed from tick weights.
|
|
338
|
-
- `ticks?: number` — Relative weight of the segment from this keyframe to the next (default 1). Only used in tick-based mode (when `at` is omitted). Last keyframe's ticks value is ignored.
|
|
339
|
-
- Also: `values: Record<string, number>`
|
|
340
|
-
|
|
341
256
|
#### `compareWith()` — Declare a reference model for comparison inspection.
|
|
342
257
|
|
|
343
258
|
`compareWith()` lets a model carry its own comparison target for inspection workflows. `forgecad inspect compare overlay model.forge.js` uses this reference to render the same Difference Only comparison overlay as the live viewport. Amber marks candidate mismatch evidence, cyan marks reference mismatch evidence, and faint model context keeps the overlay readable. When the CLI can resolve the referenced file, the manifest also includes the same geometric score produced by `forgecad compare 3d`.
|
|
@@ -384,13 +299,13 @@ Overloads:
|
|
|
384
299
|
- `offset?: number` — Optional offset along the plane normal (primarily for object-form overload).
|
|
385
300
|
- `exclude?: CutPlaneExcludeInput` — Object names to keep uncut for this plane.
|
|
386
301
|
|
|
387
|
-
#### `mock()` — Register a mock (context) object for visualization and
|
|
302
|
+
#### `mock()` — Register a mock (context) object for visualization and inspection.
|
|
388
303
|
|
|
389
|
-
Mock objects appear in the viewport and
|
|
304
|
+
Mock objects appear in the viewport and inspection analysis when you run a file directly, but are excluded when the file is imported via [`require()`](/docs/core#require). This lets you model the surrounding context — walls, bolts, mating parts — without polluting the module's exports.
|
|
390
305
|
|
|
391
306
|
The shape is returned unchanged, so you can reference it for alignment, dimensioning, and `verify` checks.
|
|
392
307
|
|
|
393
|
-
Mock objects participate in `forgecad
|
|
308
|
+
Mock objects participate in focused inspection commands such as `forgecad inspect fit interference` and `forgecad inspect physical gaps`. Their names appear with a `(mock)` suffix in reports.
|
|
394
309
|
|
|
395
310
|
In the viewport, mock objects render at reduced opacity so they are visually distinct from real geometry.
|
|
396
311
|
|
|
@@ -7,39 +7,43 @@ skill-order: 1
|
|
|
7
7
|
|
|
8
8
|
ForgeCAD uses a **Z-up** right-handed coordinate system.
|
|
9
9
|
|
|
10
|
+
For objects with a clear facing direction, model the front/face/nose/camera side toward **-Y**. The rear/back side is **+Y**. In code, a forward/fore direction vector is `[0, -1, 0]`.
|
|
11
|
+
|
|
10
12
|
## Axes
|
|
11
13
|
|
|
12
14
|
| Axis | Direction | Positive |
|
|
13
15
|
|------|-----------------|----------|
|
|
14
16
|
| X | Left / Right | Right |
|
|
15
|
-
| Y |
|
|
17
|
+
| Y | Front / Back | Back |
|
|
16
18
|
| Z | Up / Down | Up |
|
|
17
19
|
|
|
18
20
|
## Standard Views
|
|
19
21
|
|
|
22
|
+
The camera position direction says where the camera sits relative to the model. A front view camera sits at `-Y` and looks toward `+Y`, so it sees the model's `-Y` front face.
|
|
23
|
+
|
|
20
24
|
| View | Camera position direction | Sees plane |
|
|
21
|
-
|
|
22
|
-
| Front |
|
|
23
|
-
| Back | +Y
|
|
25
|
+
|--------|---------------------------|------------|
|
|
26
|
+
| Front | -Y | XZ |
|
|
27
|
+
| Back | +Y | XZ |
|
|
24
28
|
| Right | +X | YZ |
|
|
25
|
-
| Left |
|
|
29
|
+
| Left | -X | YZ |
|
|
26
30
|
| Top | +Z | XY |
|
|
27
|
-
| Bottom |
|
|
31
|
+
| Bottom | -Z | XY |
|
|
28
32
|
|
|
29
33
|
## GizmoViewcube Face Mapping
|
|
30
34
|
|
|
31
|
-
|
|
35
|
+
Renderer/view-cube internals may have their own material ordering. Map any view-cube labels to the ForgeCAD directions below:
|
|
32
36
|
|
|
33
|
-
|
|
|
34
|
-
|
|
35
|
-
|
|
|
36
|
-
|
|
|
37
|
-
|
|
|
38
|
-
|
|
|
39
|
-
|
|
|
40
|
-
|
|
|
37
|
+
| Direction | ForgeCAD label |
|
|
38
|
+
|-----------|----------------|
|
|
39
|
+
| +X | Right |
|
|
40
|
+
| -X | Left |
|
|
41
|
+
| +Y | Back |
|
|
42
|
+
| -Y | Front |
|
|
43
|
+
| +Z | Top |
|
|
44
|
+
| -Z | Bottom |
|
|
41
45
|
|
|
42
|
-
|
|
46
|
+
The face/anchor API is the source of truth: `front` resolves to the minimum-Y side and `back` resolves to the maximum-Y side.
|
|
43
47
|
|
|
44
48
|
## Grid
|
|
45
49
|
|
|
@@ -21,7 +21,7 @@ Three.js is Y-up; ForgeCAD is Z-up. Fix applied at camera level (`camera.up = (0
|
|
|
21
21
|
|
|
22
22
|
## Revolution Axis
|
|
23
23
|
|
|
24
|
-
`
|
|
24
|
+
`Sketch.revolve()` produces a world Z-axis solid of revolution. Profile X = radial distance from the Z axis, Profile Y = world Z height after revolution. Profile should stay at X > 0 unless intentionally touching the axis.
|
|
25
25
|
|
|
26
26
|
## Boolean Winding (3D)
|
|
27
27
|
|
|
@@ -47,6 +47,6 @@ Prefer `composeChain(...)` over manual `.mul(...).mul(...)` in kinematics code t
|
|
|
47
47
|
|---|---|---|---|
|
|
48
48
|
| Winding | Any point order | CCW | `polygon()`, `path().close()` |
|
|
49
49
|
| Up axis | Z-up | Y-up (Three.js) | `camera.up`, gizmo labels |
|
|
50
|
-
| Revolution | "revolve this profile" | Profile
|
|
50
|
+
| Revolution | "revolve this profile" | Profile X = radius, Profile Y = world Z height | Documented and regression-tested |
|
|
51
51
|
| Face normals | Doesn't think about it | Outward-pointing | Manifold constructors |
|
|
52
52
|
| Transform order | Left-to-right chain | Post-multiply | Native match |
|
|
@@ -60,7 +60,7 @@ stable; named scene views are still available through `--view`.
|
|
|
60
60
|
The command tree is intentionally job-shaped:
|
|
61
61
|
|
|
62
62
|
```text
|
|
63
|
-
inspect visual image|cutaway|depth|normals|objects
|
|
63
|
+
inspect visual image|cutaway|depth|normals|rig|objects
|
|
64
64
|
inspect surface zebra|roughness
|
|
65
65
|
inspect physical components|floating|gaps
|
|
66
66
|
inspect fit interference
|
|
@@ -101,6 +101,7 @@ Use targeted evidence commands for expensive analyses:
|
|
|
101
101
|
```bash
|
|
102
102
|
forgecad inspect visual depth model.forge.js --camera iso
|
|
103
103
|
forgecad inspect visual normals model.forge.js --camera iso
|
|
104
|
+
forgecad inspect visual rig model.forge.js --camera iso
|
|
104
105
|
forgecad inspect surface zebra model.forge.js --camera iso
|
|
105
106
|
forgecad inspect surface roughness model.forge.js --camera iso
|
|
106
107
|
forgecad inspect visual objects model.forge.js --camera iso
|
|
@@ -7,6 +7,30 @@ skill-order: 5
|
|
|
7
7
|
|
|
8
8
|
How to build mechanical joints — clevis-tongue hinges, ball-and-socket, dovetails — that actually rotate without binding and stop where they should.
|
|
9
9
|
|
|
10
|
+
## Frame-Aware Connectors First
|
|
11
|
+
|
|
12
|
+
If a part must rotate, slide, or point in a specific physical direction, define connectors and use `assembly().connect()`. A connector is a small coordinate frame on the part:
|
|
13
|
+
|
|
14
|
+
- `origin` is the pivot, pin center, socket center, or contact point.
|
|
15
|
+
- `axis` is the hinge line or slide direction.
|
|
16
|
+
- `up` is the secondary direction that fixes the part's zero-angle twist.
|
|
17
|
+
|
|
18
|
+
For a hip -> knee -> wheel chain, the upper leg should be a real part with a hip connector and a knee connector. The hip connector frame defines how the upper leg sits on the hip drum at rest; the knee connector frame defines where the next part attaches. `connect()` aligns those frames and derives the joint axis.
|
|
19
|
+
|
|
20
|
+
Do not treat `up` as optional on hinges, wheels, levers, or keyed sliders. If `up` is omitted, ForgeCAD chooses a deterministic perpendicular vector, which keeps the model stable but may not match the intended mechanical rest pose.
|
|
21
|
+
|
|
22
|
+
Use `link()`, `edgeBetweenLinks()`, and `addAngleBetweenLinks()` for solved point skeletons and closed-loop relationships. A link is a point, not a bone frame. `addPart(..., { mate: { connector, toLink } })` only moves a connector origin onto a solved link point; it does not rotate the part to aim along an edge.
|
|
23
|
+
|
|
24
|
+
## Mirrored Revolute Axes
|
|
25
|
+
|
|
26
|
+
Revolute joint values are physical values signed by the right-hand rule around the joint axis. If a bilateral mechanism mirrors a hinge axis, the same numeric joint value does not mean "same pose" on both sides.
|
|
27
|
+
|
|
28
|
+
Example: a right ankle hinge with `axis: [1, 0, 0]` and a left ankle hinge with `axis: [-1, 0, 0]` are exact geometric mirrors at rest. But `+20` degrees around those two axes rotates the feet in opposite fore/aft senses. The mirrored pose uses `RightAnkle: 20` and `LeftAnkle: -20`.
|
|
29
|
+
|
|
30
|
+
When you expose physical joint limits directly, mirror revolute limits as `[min, max] -> [-max, -min]`. Prismatic joints do not have this angle-handedness flip because their scalar value translates along the mirrored axis.
|
|
31
|
+
|
|
32
|
+
For bilateral robots, legs, grippers, and suspension mechanisms, prefer a side-neutral control layer when possible: solve mirrored link positions with `link()`, `edgeBetweenLinks()`, and `addAngleBetweenLinks()`, then attach real parts to the solved skeleton. If you use connector-frame joints directly, make the sign mapping explicit in defaults, keyframes, and verification.
|
|
33
|
+
|
|
10
34
|
## The Cavity Rule
|
|
11
35
|
|
|
12
36
|
Every mechanical joint has a **cavity** in one part and a **tenon** in the other. The cavity must be a real empty volume — not a gap implied by the absence of two separate solids.
|
|
@@ -11,6 +11,16 @@ For any fixed assembly where parts are meant to stay in contact in the final mod
|
|
|
11
11
|
|
|
12
12
|
Use raw `translate()` and `rotate()` when parts are intentionally free-floating or when you are doing quick exploratory layout. Use `attachTo()` for rough bounding-box placement. But if the relationship is a real interface, make it explicit with connectors.
|
|
13
13
|
|
|
14
|
+
## Mechanisms: connector frames vs link points
|
|
15
|
+
|
|
16
|
+
For serial articulated parts (hinges, hips, knees, levers, wheels), use `assembly().connect()` with connectors. `connect()` aligns the full connector frame: `origin` is the pivot/contact point, `axis` is the hinge line or slide direction, and `up` locks the zero-angle twist of the child part. `up` is a local roll reference, not world up; author it explicitly whenever the rest pose matters.
|
|
17
|
+
|
|
18
|
+
Do not use `addPart(..., { mate: { connector, toLink } })` when the part must point along a bone or inherit orientation from a link edge. Link mates are point attachments only: they translate the connector origin onto the solved link position and preserve the part's existing rotation. That is good for markers, sensors, labels, and debug handles. It is not a bone-frame API.
|
|
19
|
+
|
|
20
|
+
Use link graphs (`link()`, `edgeBetweenLinks()`, `addAngleBetweenLinks()`) when the hard part is solving point positions, especially closed loops. Use connector-frame joints when the hard part is orienting real physical parts.
|
|
21
|
+
|
|
22
|
+
For bilateral mechanisms, remember that connector-frame revolute values are physical axis-local values. Mirrored hinge axes need negated physical revolute values for the same mirrored pose, and physical limits mirror as `[min, max] -> [-max, -min]`. If you want `HipR: 10` and `HipL: 10` to mean the same semantic pose, drive a mirrored link graph or write an explicit state mapping instead of assuming equal connector-joint values are symmetric.
|
|
23
|
+
|
|
14
24
|
## Primitive origin convention
|
|
15
25
|
|
|
16
26
|
All 3D primitives are **centered on XY, base at Z=0**:
|
|
@@ -34,14 +44,14 @@ Most positioning bugs come from manual coordinate arithmetic. Use these methods
|
|
|
34
44
|
|
|
35
45
|
## 1. Connectors + `matchTo()` — default for mating interfaces
|
|
36
46
|
|
|
37
|
-
Define connectors on parts; `matchTo()` provides automatic
|
|
47
|
+
Define connectors on parts; `matchTo()` provides automatic alignment. With one connector pair, the child translates and rotates so its connector aligns with the target's — origins coincide, axes oppose (plug-in model), and `up` pins the roll reference. With multiple connector pairs, the connector origins define the rigid transform; still author meaningful `axis` and `up` values so the same connectors remain useful for `connect()`, audits, and future matching.
|
|
38
48
|
|
|
39
49
|
```javascript
|
|
40
50
|
const shelf = box(200, 120, 10).translate(0, 0, -5).withConnectors({
|
|
41
|
-
left_tab: connector.male("dovetail", { origin: [-100, 0, 0], axis: [-1, 0, 0] }),
|
|
51
|
+
left_tab: connector.male("dovetail", { origin: [-100, 0, 0], axis: [-1, 0, 0], up: [0, 0, 1] }),
|
|
42
52
|
});
|
|
43
53
|
const panel = box(12, 120, 200).translate(0, 0, -100).withConnectors({
|
|
44
|
-
shelf_0: connector.female("dovetail", { origin: [6, 0, -50], axis: [1, 0, 0] }),
|
|
54
|
+
shelf_0: connector.female("dovetail", { origin: [6, 0, -50], axis: [1, 0, 0], up: [0, 0, 1] }),
|
|
45
55
|
});
|
|
46
56
|
const placed = shelf.matchTo(panel, "left_tab", "shelf_0");
|
|
47
57
|
// Dictionary form for multiple pairs on same target:
|
|
@@ -31,13 +31,13 @@ Do not solve reconstruction by returning `importMesh("reference.stl")` or `impor
|
|
|
31
31
|
No wrapper script is needed. Use the local checkout CLI:
|
|
32
32
|
|
|
33
33
|
```bash
|
|
34
|
-
node dist-cli/forgecad.js
|
|
34
|
+
node dist-cli/forgecad.js ls path/to/source.stl --quality live --long
|
|
35
35
|
node dist-cli/forgecad.js render 3d path/to/source.stl /tmp/<slug>-source.png --camera iso --edges thin --size 900
|
|
36
36
|
node dist-cli/forgecad.js inspect visual objects path/to/source.stl /tmp/<slug>-source-objects --camera iso --size 700 --force
|
|
37
37
|
node dist-cli/forgecad.js inspect sections sample path/to/source.stl /tmp/<slug>-source-sections --count 5 --size 700 --force
|
|
38
38
|
```
|
|
39
39
|
|
|
40
|
-
For 3MF sources, `run
|
|
40
|
+
For 3MF sources, `forgecad run` prints the source archive's build
|
|
41
41
|
items/resource objects with stable refs such as
|
|
42
42
|
`3mf:build:001:object:2`, automatic names, per-item bounding boxes, and
|
|
43
43
|
triangle counts. Use that item table to avoid missing hidden multi-part
|