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.
Files changed (216) hide show
  1. package/LICENSE +6 -4
  2. package/README.md +8 -4
  3. package/dist/assets/{AdminPage-DramHHDf.js → AdminPage-CDyGUinA.js} +2 -2
  4. package/dist/assets/{BenchmarkPage-Bjgkh5m9.js → BenchmarkPage-DfPMY_-d.js} +4 -15
  5. package/dist/assets/{BlogPage-n_HGP3Qm.js → BlogPage-kF0fkdJT.js} +2 -2
  6. package/dist/assets/{DocsPage-WCIkPmzC.js → DocsPage-B954L3YN.js} +9 -3
  7. package/dist/assets/EditorApp-Beb-IZ0y.js +14014 -0
  8. package/dist/assets/{EditorApp-BAnckbsk.css → EditorApp-CuDLxKqL.css} +698 -0
  9. package/dist/assets/{EmbedViewer-DEZKqdfW.js → EmbedViewer-C77B-TrF.js} +3 -3
  10. package/dist/assets/{LandingPageProofDriven-CeRIctuj.js → LandingPageProofDriven-Cr6fXMDj.js} +35 -37
  11. package/dist/assets/LegalPage-BRlScr9A.css +91 -0
  12. package/dist/assets/LegalPage-Dzklqmmg.js +39 -0
  13. package/dist/assets/{PricingPage-BMedqFef.css → PricingPage-BPF6HKyO.css} +25 -0
  14. package/dist/assets/{PricingPage-rIRa8p4Y.js → PricingPage-zWXkvlwl.js} +19 -19
  15. package/dist/assets/{SettingsPage-BqCUvEXM.js → SettingsPage-Bz0of4KQ.js} +2 -2
  16. package/dist/assets/app-CE3sYcV7.css +3890 -0
  17. package/dist/assets/{app-BUZqJvSO.js → app-D3kDkggg.js} +2305 -960
  18. package/dist/assets/cli/{render-lhGxj50Y.js → render-DSY3mMQa.js} +423 -30
  19. package/dist/assets/{constructionHistoryWorker-ipD1jcIv.js → constructionHistoryWorker-gpDo-uH2.js} +927 -243
  20. package/dist/assets/{evalWorker-CHXSe_-u.js → evalWorker-CU0Ke6DP.js} +7799 -4163
  21. package/dist/assets/{forgecad_geometry-BVnIeXMG.js → forgecad_geometry-Dgceylq9.js} +43 -1
  22. package/dist/assets/{forgecad_geometry_bg-DufhhCBV.wasm → forgecad_geometry_bg-dD4RNQF1.wasm} +0 -0
  23. package/dist/assets/{inspectWorker-DeRnMVv1.js → inspectWorker-COyp8XXA.js} +927 -243
  24. package/dist/assets/{javascript-70-4uGcz.js → javascript-1kQXfVaz.js} +1 -1
  25. package/dist/assets/landing-proof-driven-DiGqdtWa.js +18 -0
  26. package/dist/assets/{landing-proof-driven-oFYW6mjz.css → landing-proof-driven-ORyigZ6p.css} +13 -7
  27. package/dist/assets/legalContent-ZfFGMmi4.js +251 -0
  28. package/dist/assets/{manifold-D1LZIHqn.js → manifold-BRI5prcH.js} +1 -1
  29. package/dist/assets/{manifold-C2fwoTgd.js → manifold-C-3h2M7p.js} +2 -2
  30. package/dist/assets/{manifold-BTkzxi9V.js → manifold-DNkrUWpA.js} +1 -1
  31. package/dist/assets/{reportWorker-Cq1qGmg0.js → reportWorker-CdBz5bNg.js} +7537 -10856
  32. package/dist/assets/{scalar-sampling-budget-D9Qv_UlJ.js → scalar-sampling-budget-wJF98aY9.js} +6943 -4345
  33. package/dist/assets/{scanProxyWorker-Bs2TDgLw.js → scanProxyWorker-B-9VbLIs.js} +32 -1
  34. package/dist/assets/{renderSceneState-Dr0xPq1A.js → targets-B9sGB5nB.js} +27 -1
  35. package/dist/assets/{vendor-react-Da3A2QmU.js → vendor-react-6j1Kke-Y.js} +6 -5
  36. package/dist/cli/render.html +1 -1
  37. package/dist/docs/index.html +2 -2
  38. package/dist/docs-raw/AI/ai-native-cad.md +50 -0
  39. package/dist/docs-raw/AI/usage.md +9 -17
  40. package/dist/docs-raw/CLI.md +71 -21
  41. package/dist/docs-raw/component-model.md +27 -11
  42. package/dist/docs-raw/generated/assembly.md +301 -212
  43. package/dist/docs-raw/generated/concepts.md +238 -240
  44. package/dist/docs-raw/generated/core.md +283 -6
  45. package/dist/docs-raw/generated/curves.md +274 -361
  46. package/dist/docs-raw/generated/lib.md +7 -1
  47. package/dist/docs-raw/generated/output.md +19 -4
  48. package/dist/docs-raw/generated/runtime-names.md +41 -0
  49. package/dist/docs-raw/generated/sdf.md +31 -0
  50. package/dist/docs-raw/generated/sheet-metal.md +9 -0
  51. package/dist/docs-raw/generated/sketch.md +44 -1
  52. package/dist/docs-raw/generated/viewport.md +14 -6
  53. package/dist/docs-raw/guides/coordinate-system.md +20 -16
  54. package/dist/docs-raw/guides/geometry-conventions.md +2 -2
  55. package/dist/docs-raw/guides/inspection-bundles.md +2 -1
  56. package/dist/docs-raw/guides/joint-design.md +24 -0
  57. package/dist/docs-raw/guides/positioning.md +13 -3
  58. package/dist/docs-raw/legal/privacy.md +63 -0
  59. package/dist/docs-raw/legal/software-license.md +55 -0
  60. package/dist/docs-raw/legal/terms.md +87 -0
  61. package/dist/docs-raw/skills/forgecad-3d-reconstruction.md +3 -3
  62. package/dist/docs-raw/skills/forgecad-blockout-model.md +1 -1
  63. package/dist/docs-raw/skills/forgecad-component-model.md +11 -2
  64. package/dist/docs-raw/skills/forgecad-high-level-spec.md +1 -1
  65. package/dist/docs-raw/skills/forgecad-image-replicator.md +8 -8
  66. package/dist/docs-raw/skills/forgecad-lld.md +1 -1
  67. package/dist/docs-raw/skills/forgecad-make-a-model.md +4 -4
  68. package/dist/docs-raw/skills/forgecad-model-grader.md +2 -2
  69. package/dist/docs-raw/skills/forgecad-prepare-prompt.md +2 -2
  70. package/dist/docs-raw/skills/forgecad-project.md +1 -1
  71. package/dist/docs-raw/skills/forgecad-reconstruction-benchmark.md +4 -4
  72. package/dist/docs-raw/skills/forgecad-render-inspect.md +4 -2
  73. package/dist/docs-raw/skills/forgecad-visual-spec.md +1 -1
  74. package/dist/docs-raw/skills/forgecad.md +4 -3
  75. package/dist/index.html +40 -12
  76. package/dist/llms.txt +8 -0
  77. package/dist/site.webmanifest +1 -1
  78. package/dist/sitemap.xml +49 -13
  79. package/dist-cli/{check-compiler-LOXCPEOI.js → check-compiler-SDX5QIXI.js} +1 -2
  80. package/dist-cli/{check-query-propagation-BAKNVWXR.js → check-query-propagation-EAYEFT77.js} +1 -2
  81. package/dist-cli/{chunk-RY43WF46.js → chunk-N4O47JLF.js} +13772 -9938
  82. package/dist-cli/forgecad.js +2387 -899
  83. package/dist-cli/{forgecad_geometry-GYVNKPIE.js → forgecad_geometry-QOQIIP53.js} +42 -1
  84. package/dist-cli/forgecad_geometry_bg.wasm +0 -0
  85. package/dist-cli/{solver-46FFSK2U.js → solver-OK4HECRH.js} +0 -1
  86. package/dist-skill/CONTEXT.md +1120 -724
  87. package/dist-skill/SKILL.md +3 -2
  88. package/dist-skill/docs/API/core/concepts.md +64 -1
  89. package/dist-skill/docs/CLI.md +71 -21
  90. package/dist-skill/docs/generated/assembly.md +277 -229
  91. package/dist-skill/docs/generated/core.md +283 -6
  92. package/dist-skill/docs/generated/curves.md +272 -362
  93. package/dist-skill/docs/generated/lib.md +7 -1
  94. package/dist-skill/docs/generated/output.md +19 -4
  95. package/dist-skill/docs/generated/runtime-names.md +41 -0
  96. package/dist-skill/docs/generated/sdf.md +31 -0
  97. package/dist-skill/docs/generated/sheet-metal.md +9 -0
  98. package/dist-skill/docs/generated/sketch.md +44 -2
  99. package/dist-skill/docs/generated/viewport.md +5 -90
  100. package/dist-skill/docs/guides/coordinate-system.md +20 -16
  101. package/dist-skill/docs/guides/geometry-conventions.md +2 -2
  102. package/dist-skill/docs/guides/inspection-bundles.md +2 -1
  103. package/dist-skill/docs/guides/joint-design.md +24 -0
  104. package/dist-skill/docs/guides/positioning.md +13 -3
  105. package/dist-skill/library/forgecad-3d-reconstruction/SKILL.md +2 -2
  106. package/dist-skill/library/forgecad-component-model/SKILL.md +10 -1
  107. package/dist-skill/library/forgecad-image-replicator/SKILL.md +6 -6
  108. package/dist-skill/library/forgecad-image-replicator/scripts/compare_images.py +166 -0
  109. package/dist-skill/library/forgecad-make-a-model/SKILL.md +3 -3
  110. package/dist-skill/library/forgecad-model-grader/SKILL.md +1 -1
  111. package/dist-skill/library/forgecad-prepare-prompt/SKILL.md +1 -1
  112. package/dist-skill/library/forgecad-reconstruction-benchmark/SKILL.md +3 -3
  113. package/dist-skill/library/forgecad-render-inspect/SKILL.md +3 -1
  114. package/examples/api/assembly-kinematics-foundation.forge.js +65 -0
  115. package/examples/api/assembly-kinematics-four-bar.forge.js +115 -0
  116. package/examples/api/assembly-kinematics-limb.forge.js +116 -0
  117. package/examples/api/connector-frame-rig-chain.forge.js +102 -0
  118. package/examples/api/exact-sheet-shell-assembly.forge.js +0 -2
  119. package/examples/api/exact-surface-studio.forge.js +6 -8
  120. package/examples/api/helix-basics.forge.js +6 -6
  121. package/examples/api/lean-foundations/README.md +12 -0
  122. package/examples/api/lean-foundations/curve-blend-exact.forge.js +22 -0
  123. package/examples/api/lean-foundations/curve-fit-interpolation.forge.js +18 -0
  124. package/examples/api/lean-foundations/curve-helix-canonicalization.forge.js +27 -0
  125. package/examples/api/lean-foundations/curve-route-canonicalization.forge.js +16 -0
  126. package/examples/api/lean-foundations/curve-trim-reverse.forge.js +24 -0
  127. package/examples/api/lean-foundations/exact-curve-arc.forge.js +36 -0
  128. package/examples/api/mixed-edge-finishes-proof.forge.js +8 -11
  129. package/examples/api/route3d-elbow.forge.js +68 -0
  130. package/examples/api/transition-curves.forge.js +44 -15
  131. package/examples/api/y-blend-corner-showcase.forge.js +0 -2
  132. package/examples/generative/coral-vase.forge.js +1 -1
  133. package/examples/nurbs-tube.forge.js +1 -1
  134. package/package.json +14 -18
  135. package/dist/assets/EditorApp-CP9Za6tm.js +0 -13630
  136. package/dist/assets/app-CsHnaBWt.css +0 -1789
  137. package/dist/docs-raw/API/README.md +0 -16
  138. package/dist/docs-raw/API/core/concepts.md +0 -118
  139. package/dist/docs-raw/INDEX.md +0 -138
  140. package/dist/docs-raw/RELEASING.md +0 -87
  141. package/dist/docs-raw/agent-native-api.md +0 -27
  142. package/dist/docs-raw/beta-deployment.md +0 -304
  143. package/dist/docs-raw/beta-operations.md +0 -325
  144. package/dist/docs-raw/blueprint-first.md +0 -145
  145. package/dist/docs-raw/cli-monetization.md +0 -112
  146. package/dist/docs-raw/coding-best-practices.md +0 -120
  147. package/dist/docs-raw/coding.md +0 -340
  148. package/dist/docs-raw/deployment.md +0 -374
  149. package/dist/docs-raw/guides/skill-maintenance.md +0 -161
  150. package/dist/docs-raw/guides/surface-members.md +0 -82
  151. package/dist/docs-raw/internals/backend-vocabulary.md +0 -35
  152. package/dist/docs-raw/internals/compiler.md +0 -307
  153. package/dist/docs-raw/internals/constraint-solver-quality.md +0 -161
  154. package/dist/docs-raw/internals/constraint-solver.md +0 -176
  155. package/dist/docs-raw/internals/shape-from-slices.md +0 -152
  156. package/dist/docs-raw/internals/sketch-2d-pipeline.md +0 -108
  157. package/dist/docs-raw/platform/admin.md +0 -45
  158. package/dist/docs-raw/platform/architecture.md +0 -82
  159. package/dist/docs-raw/platform/auth.md +0 -139
  160. package/dist/docs-raw/platform/email.md +0 -67
  161. package/dist/docs-raw/platform/google-oauth-setup.md +0 -88
  162. package/dist/docs-raw/platform/observability.md +0 -197
  163. package/dist/docs-raw/platform/projects.md +0 -111
  164. package/dist/docs-raw/platform/sharing.md +0 -90
  165. package/dist/docs-raw/product/README.md +0 -39
  166. package/dist/docs-raw/product/api-as-product-language.md +0 -13
  167. package/dist/docs-raw/product/business-model.md +0 -15
  168. package/dist/docs-raw/product/competitive-positioning.md +0 -17
  169. package/dist/docs-raw/product/creative-manufacturing.md +0 -15
  170. package/dist/docs-raw/product/founder-story.md +0 -11
  171. package/dist/docs-raw/product/manufacturing-workflows.md +0 -15
  172. package/dist/docs-raw/product/onboarding-first-experience.md +0 -256
  173. package/dist/docs-raw/product/product-loop.md +0 -17
  174. package/dist/docs-raw/product/strategic-decisions.md +0 -22
  175. package/dist/docs-raw/product/user-outreach-email-templates.md +0 -161
  176. package/dist/docs-raw/product/user-segments.md +0 -15
  177. package/dist/docs-raw/product/vision.md +0 -26
  178. package/dist/docs-raw/rl-environments.md +0 -508
  179. package/dist/docs-raw/runbook.md +0 -611
  180. package/dist-cli/check-compiler-LOXCPEOI.js.map +0 -1
  181. package/dist-cli/check-query-propagation-BAKNVWXR.js.map +0 -1
  182. package/dist-cli/chunk-RY43WF46.js.map +0 -1
  183. package/dist-cli/forgecad.js.map +0 -1
  184. package/dist-cli/forgecad_geometry-GYVNKPIE.js.map +0 -1
  185. package/dist-cli/solver-46FFSK2U.js.map +0 -1
  186. package/dist-skill/SKILL-dev.md +0 -145
  187. package/dist-skill/docs-dev/API/core/concepts.md +0 -118
  188. package/dist-skill/docs-dev/CLI.md +0 -647
  189. package/dist-skill/docs-dev/agent-native-api.md +0 -27
  190. package/dist-skill/docs-dev/blueprint-first.md +0 -145
  191. package/dist-skill/docs-dev/coding-best-practices.md +0 -120
  192. package/dist-skill/docs-dev/coding.md +0 -340
  193. package/dist-skill/docs-dev/component-model.md +0 -164
  194. package/dist-skill/docs-dev/generated/assembly.md +0 -794
  195. package/dist-skill/docs-dev/generated/core.md +0 -2117
  196. package/dist-skill/docs-dev/generated/curves.md +0 -2583
  197. package/dist-skill/docs-dev/generated/lib.md +0 -169
  198. package/dist-skill/docs-dev/generated/output.md +0 -247
  199. package/dist-skill/docs-dev/generated/sdf.md +0 -446
  200. package/dist-skill/docs-dev/generated/sheet-metal.md +0 -504
  201. package/dist-skill/docs-dev/generated/sketch.md +0 -1811
  202. package/dist-skill/docs-dev/generated/viewport.md +0 -585
  203. package/dist-skill/docs-dev/generated/wood.md +0 -108
  204. package/dist-skill/docs-dev/guides/coordinate-system.md +0 -46
  205. package/dist-skill/docs-dev/guides/geometry-conventions.md +0 -52
  206. package/dist-skill/docs-dev/guides/inspection-bundles.md +0 -485
  207. package/dist-skill/docs-dev/guides/joint-design.md +0 -78
  208. package/dist-skill/docs-dev/guides/modeling-recipes.md +0 -78
  209. package/dist-skill/docs-dev/guides/positioning.md +0 -161
  210. package/dist-skill/docs-dev/guides/skill-maintenance.md +0 -161
  211. package/dist-skill/docs-dev/internals/backend-vocabulary.md +0 -35
  212. package/dist-skill/docs-dev/internals/compiler.md +0 -307
  213. package/dist-skill/docs-dev/internals/constraint-solver-quality.md +0 -161
  214. package/dist-skill/docs-dev/internals/constraint-solver.md +0 -176
  215. package/dist-skill/docs-dev/internals/sketch-2d-pipeline.md +0 -108
  216. package/dist-skill/library/forgecad-image-replicator/scripts/compare_images.mjs +0 -289
@@ -1,585 +0,0 @@
1
- ---
2
- skill-group: viewport
3
- skill-order: 100
4
- ---
5
-
6
- # Viewport & Runtime
7
-
8
- Cut planes, exploded views, joint animations, and scene configuration.
9
-
10
- ## Contents
11
-
12
- - [Viewport & Runtime](#viewport-runtime) — `Viewport.label`, `scene`, `viewConfig`, `explodeView`, `jointsView`, `compareWith`, `cutPlane`, `mock`, `showLabels`, `highlight`
13
- - [RouteBuilder](#routebuilder)
14
- - [route](#route)
15
-
16
- ## Functions
17
-
18
- ### Viewport & Runtime
19
-
20
- #### `Viewport.label()` — Add a render-only viewport label at a world-space point.
21
-
22
- `Viewport.label()` is for temporary review, debug, tutorial, or explicitly requested presentation overlays. It does not create sketches, meshes, B-rep topology, exported text, or face labels, so it stays off the OCCT path. Default production models should be understandable from physical geometry, materials, part boundaries, and named objects, not viewport annotations.
23
-
24
- Use [`text2d()`](/docs/sketch#text2d) only when the letters should become manufactured geometry, such as raised lettering, engraved serial numbers, or exported nameplates.
25
-
26
- Labels are collected during script execution and rendered by the viewport as lightweight overlay annotations. They are ignored by exports and do not appear in `objects`.
27
-
28
- ```js
29
- Viewport.label('Bearing bore', [0, 0, 18], {
30
- color: '#f8fafc',
31
- background: '#0f172acc',
32
- offset: [0, 0, 8],
33
- anchor: 'bottom',
34
- });
35
-
36
- return box(40, 30, 12);
37
- ```
38
-
39
- ```ts
40
- Viewport.label(text: string, at: [ number, number, number ], options?: RenderLabelOptions): void
41
- ```
42
-
43
- **`RenderLabelOptions`**
44
-
45
- | Option | Type | Description |
46
- |--------|------|-------------|
47
- | `color?` | `string` | Text color as any CSS color string. |
48
- | `background?` | `string` | Background color as any CSS color string. Use `'transparent'` for no pill background. |
49
- | `size?` | `number` | Font size in CSS pixels. Defaults to 12. |
50
- | `offset?` | `[ number, number, number ]` | Additional world-space offset from `at`. |
51
- | `anchor?` | `RenderLabelAnchor` | Which point of the label box is anchored to `at`. Defaults to `'center'`. |
52
- | `alwaysOnTop?` | `boolean` | When false, the label is hidden when occluded by scene geometry. Defaults to true. |
53
-
54
- #### `scene()` — Configure the scene environment for the current script execution.
55
-
56
- Controls camera position, named render views, optional model journeys, lighting rig, background color or gradient, atmospheric fog, environment maps, post-processing effects, and capture parameters for the `forgecad capture` command. Multiple calls merge — later values override earlier ones on a per-key basis, so you can split configuration across multiple `scene()` calls.
57
-
58
- When `lights` is specified, **all** default lights are removed. You must include your own ambient light or the scene will be fully dark.
59
-
60
- Setting `camera.position` overrides auto-framing — the viewport will no longer auto-fit the geometry on script reload.
61
-
62
- Named render views let scripts check in repeatable cameras next to the model code. The canonical shape is `{ camera: { position, target } }`, and a direct camera shorthand `{ position, target }` is also accepted. Use the canonical shape when you may add view metadata later. Use it from the CLI with `--view hero` on `forgecad render 3d`, `forgecad render hq`, or `forgecad capture`.
63
-
64
- Model journeys let scripts check in a compact guided path through named objects. Each journey has ordered `steps`; each step can name a `focus` target by object name/tree path, provide a caption, and optionally provide an explicit camera. In the viewer, journeys are opt-in: they appear as a small Explore control and do not move the camera until the user starts them. Use `forgecad run model.forge.js --journeys` or `--journeys-json` to inspect resolved targets.
65
-
66
- Post-processing effects (`bloom`, `vignette`, `grain`) work in the browser viewport only. The CLI applies camera, lights, background, fog, and `toneMappingExposure` but skips shader effects.
67
-
68
- All numeric values accept `param()` expressions.
69
-
70
- ```js
71
- scene({
72
- background: { top: '#000814', bottom: '#001d3d' },
73
- camera: { position: [160, -120, 100], target: [0, 0, 50], fov: 52 },
74
- views: {
75
- hero: {
76
- camera: { position: [180, -140, 90], target: [0, 0, 25], up: [0, 0, 1], fov: 38 },
77
- },
78
- side: { position: [240, 0, 70], target: [0, 0, 25], fov: 34 },
79
- },
80
- journeys: {
81
- grandTour: {
82
- title: 'Grand Tour',
83
- startsAt: 'overview',
84
- steps: [
85
- { id: 'overview', focus: 'Solar System', caption: 'Start with the whole model.' },
86
- { id: 'earth', focus: 'Earth', caption: 'Fit and inspect Earth.' },
87
- ],
88
- },
89
- },
90
- lights: [
91
- { type: 'ambient', color: '#001233', intensity: 0.08 },
92
- { type: 'point', position: [120, -80, 130], color: '#00f5d4', intensity: 4, distance: 400, decay: 1 },
93
- { type: 'point', position: [-100, 60, 20], color: '#f72585', intensity: 3, distance: 350 },
94
- { type: 'directional', position: [50, -30, 200], color: '#ffd60a', intensity: 1.2 },
95
- { type: 'hemisphere', skyColor: '#003566', groundColor: '#000814', intensity: 0.2 },
96
- ],
97
- fog: { color: '#000814', near: 100, far: 450 },
98
- postProcessing: {
99
- bloom: { intensity: param('bloom', 1.5, 0, 4), threshold: 0.5, radius: 0.7 },
100
- vignette: { darkness: 0.8, offset: 0.25 },
101
- grain: { intensity: 0.08 },
102
- toneMappingExposure: param('exposure', 1.5, 0.5, 4),
103
- },
104
- });
105
- ```
106
-
107
- ```ts
108
- scene(options: SceneOptions): void
109
- ```
110
-
111
- **`SceneOptions`**
112
-
113
- | Option | Type | Description |
114
- |--------|------|-------------|
115
- | `capture?` | `SceneCaptureConfig` | Default capture parameters for `forgecad capture` — CLI flags override these. |
116
- | `background?`, `camera?`, `views?`, `journeys?`, `lights?`, `environment?`, `fog?`, `postProcessing?`, `ground?` | | — |
117
-
118
- `SceneBackgroundGradient`: `{ top: string, bottom: string }`
119
-
120
- **`SceneCameraConfig`**: `position?: [ number, number, number ]`, `target?: [ number, number, number ]`, `up?: [ number, number, number ]`, `fov?: number`, `type?: "perspective" | "orthographic"`
121
-
122
- **`SceneJourneyConfig`**
123
-
124
- | Option | Type | Description |
125
- |--------|------|-------------|
126
- | `title?` | `string` | Viewer-facing journey title. Defaults to the journey id. |
127
- | `startsAt?` | `string` | Optional starting step id. Defaults to the first step. |
128
- | `behavior?` | `"opt-in" \| "auto"` | Whether the viewer should offer or auto-open the journey. First slice supports opt-in. |
129
- | `steps` | `SceneJourneyStepConfig[]` | Ordered journey spine. Branches can be added later without changing this core contract. |
130
- | `valid?` | `boolean` | True unless any journey or step diagnostic has level "error". |
131
-
132
- **`SceneJourneyStepConfig`**
133
-
134
- | Option | Type | Description |
135
- |--------|------|-------------|
136
- | `id` | `string` | Stable step id used by viewer links and Next/Back state. |
137
- | `title?` | `string` | Viewer-facing title. Defaults to the step id. |
138
- | `focus?` | `string` | Object name or slash-separated tree path to focus. |
139
- | `caption?` | `string` | Short optional viewer caption. |
140
- | `camera?` | `SceneViewCameraConfig` | Optional explicit camera for this step. When omitted, the viewer fits `focus`. |
141
- | `resolvedFocusId?` | `string \| null` | Resolved object id after script execution, when `focus` matched exactly one object. |
142
- | `resolvedFocusPath?` | `string \| null` | Resolved object tree path or name after script execution. |
143
-
144
- **`SceneLightConfig`**
145
-
146
- | Option | Type | Description |
147
- |--------|------|-------------|
148
- | `target?` | `[ number, number, number ]` | Target for directional/spot lights |
149
- | `groundColor?` | `string` | Ground color for hemisphere lights |
150
- | `skyColor?` | `string` | Sky color alias for hemisphere lights (same as color) |
151
- | `angle?` | `number` | Spot light cone angle in radians |
152
- | `penumbra?` | `number` | Spot light penumbra (0–1) |
153
- | `decay?` | `number` | Point/spot light decay |
154
- | `distance?` | `number` | Point/spot light distance (0 = infinite) |
155
- | `castShadow?` | `boolean` | Whether this light casts shadows |
156
- | `type`, `color?`, `intensity?`, `position?` | | — |
157
-
158
- **`SceneEnvironmentConfig`**
159
- - `preset?: "studio" | "sunset" | "dawn" | "warehouse" | "forest" | "apartment" | "lobby" | "city" | "park" | "night" | "none"` — Built-in preset name or 'none' to disable
160
- - `intensity?: number` — Environment map intensity
161
- - `background?: boolean` — Use environment map as scene background
162
-
163
- **`SceneFogConfig`**
164
- - `near?: number` — Linear fog near distance
165
- - `far?: number` — Linear fog far distance
166
- - `density?: number` — Exponential fog density (if set, uses FogExp2 instead of linear Fog)
167
- - Also: `color?: string`
168
-
169
- `ScenePostProcessingConfig`: `{ bloom?: SceneBloomConfig, vignette?: SceneVignetteConfig, grain?: SceneGrainConfig, toneMappingExposure?: number }`
170
-
171
- `SceneBloomConfig`: `{ intensity?: number, threshold?: number, radius?: number }`
172
-
173
- `SceneVignetteConfig`: `{ darkness?: number, offset?: number }`
174
-
175
- `SceneGrainConfig`: `{ intensity?: number }`
176
-
177
- **`SceneGroundConfig`**
178
-
179
- | Option | Type | Description |
180
- |--------|------|-------------|
181
- | `visible?` | `boolean` | Show a ground plane |
182
- | `color?` | `string` | Ground color |
183
- | `offset?` | `number` | Offset below the model's bounding box minimum Z. Default 0 (flush with model bottom). |
184
- | `receiveShadow?` | `boolean` | Receive shadows on the ground |
185
-
186
- **`SceneCaptureConfig`**
187
-
188
- | Option | Type | Description |
189
- |--------|------|-------------|
190
- | `framesPerTurn?` | `number` | Frames for one full orbit rotation (default: 72) |
191
- | `holdFrames?` | `number` | Frozen frames before motion starts (default: 6) |
192
- | `pitchDeg?` | `number` | Orbit pitch angle in degrees (default: auto from camera) |
193
- | `fps?` | `number` | Output frame rate (default: 24) |
194
- | `size?` | `number` | Output frame size in pixels (default: 960) |
195
- | `background?` | `string` | Canvas background color for capture (default: '#252526') |
196
-
197
- #### `viewConfig()` — Configure viewport helper visuals for the current script execution.
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 `jointsView` is active. Multiple calls merge — later values override earlier ones per key.
200
-
201
- This does **not** trigger a geometry recompute; it only affects the visual helpers drawn on top of the 3D scene.
202
-
203
- ```js
204
- viewConfig({
205
- jointOverlay: {
206
- axisColor: '#13dfff',
207
- arcColor: '#ff7a1a',
208
- axisLineRadiusScale: 0.03,
209
- arcLineRadiusScale: 0.022,
210
- },
211
- });
212
- ```
213
-
214
- ```ts
215
- viewConfig(options?: ViewConfigOptions): void
216
- ```
217
-
218
- #### `explodeView()` — Configure how the viewport explode slider offsets returned objects.
219
-
220
- Offsets are resolved from the returned object tree, not a flat list. In `radial` mode each node follows its parent branch direction, then fans locally from the immediate parent center — nested assemblies peel apart level by level. In fixed-axis or fixed-vector modes, the branch follows that axis/vector but nested descendants fan out perpendicular by default.
221
-
222
- Multiple calls merge — later values override earlier ones on a per-key basis. `byName` and `byPath` maps are merged entry-by-entry.
223
-
224
- For programmatic explode applied before returning (without the slider), use `lib.explode()` instead.
225
-
226
- ```js
227
- explodeView({
228
- amountScale: 1.2,
229
- stages: [0.35, 0.8],
230
- mode: 'radial',
231
- byPath: { 'Drive/Shaft': { direction: [1, 0, 0], stage: 1.6 } },
232
- });
233
- ```
234
-
235
- ```ts
236
- explodeView(options?: ExplodeViewOptions): void
237
- ```
238
-
239
- **`ExplodeViewOptions`**
240
-
241
- | Option | Type | Description |
242
- |--------|------|-------------|
243
- | `enabled?` | `boolean` | Set false to disable viewport explode offsets for this script output. |
244
- | `amountScale?` | `number` | Scales the UI explode amount. Default: 1 |
245
- | `stages?` | `number[]` | Per-depth stage multipliers (depth 1 = first level). If depth exceeds this array, the last value is reused. Default when omitted: reciprocal depth (1, 1/2, 1/3, ...) |
246
- | `mode?` | `ExplodeViewDirection` | Global direction mode fallback. Default: 'radial' |
247
- | `axisLock?` | `ExplodeAxis` | Global axis lock fallback. |
248
- | `byName?` | `Record<string, ExplodeViewDirective>` | Per-object overrides by final object name. |
249
- | `byPath?` | `Record<string, ExplodeViewDirective>` | Per-tree-path overrides using slash-separated object tree segments. |
250
-
251
- **`ExplodeDirective`**
252
- - `stage?: number` — Multiplier applied to `amount` for this node
253
- - `direction?: ExplodeDirection` — Direction mode for this node
254
- - `axisLock?: ExplodeAxis` — Optional axis lock after direction is resolved
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
- #### `compareWith()` — Declare a reference model for comparison inspection.
342
-
343
- `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`.
344
-
345
- The path is resolved relative to the file that calls `compareWith()`. It may point to another `.forge.js` file or an imported CAD asset such as `.stl`, `.obj`, `.3mf`, `.step`, or `.stp`.
346
-
347
- ```js
348
- compareWith('./reference.3mf', { align: 'center', toleranceMm: 0.25, samples: 3000 });
349
- return rebuiltBearing;
350
- ```
351
-
352
- ```ts
353
- compareWith(path: string, options?: CompareWithOptions): void
354
- ```
355
-
356
- **`CompareWithOptions`**
357
-
358
- | Option | Type | Description |
359
- |--------|------|-------------|
360
- | `align?` | `CompareAlignMode` | Candidate alignment before scoring. Defaults to no automatic alignment. |
361
- | `toleranceMm?` | `number` | Distance tolerance in model units for coverage scoring. Defaults to the comparison scorer's auto tolerance. |
362
- | `samples?` | `number` | Surface samples per direction for numeric scoring. Defaults to the comparison scorer's standard sample count. |
363
- | `label?` | `string` | Human label for the reference model in inspection manifests. |
364
-
365
- #### `cutPlane()` — Define a named section plane for inspecting internal geometry.
366
-
367
- Registers a cut plane that appears as a toggle in the viewport View Panel. When enabled, geometry on the positive side of the plane (the side the normal points toward) is clipped away, revealing the internal cross-section. The newly exposed section faces render with a hatched overlay; pre-existing coplanar boundary faces are left unhatched.
368
-
369
- Planes are registered once per script run. The viewport toggle state (on/off) persists across parameter changes without re-running the script. The `exclude` option only works correctly when the excluded object names are stable across parameter changes.
370
-
371
- Accepts two overloads: `cutPlane(name, normal, offset?, options?)` or `cutPlane(name, normal, options?)` where options may include `offset`.
372
-
373
- ```js
374
- const cutZ = param('Cut Height', 10, { min: -50, max: 50, unit: 'mm' });
375
- cutPlane('Inspection', [0, 0, 1], cutZ, { exclude: ['Probe', 'Fasteners'] });
376
- ```
377
-
378
- Overloads:
379
-
380
- - `cutPlane(name: string, normal: [ number, number, number ], offset?: number, options?: CutPlaneOptions): void`
381
- - `cutPlane(name: string, normal: [ number, number, number ], options?: CutPlaneOptions): void`
382
-
383
- **`CutPlaneOptions`**
384
- - `offset?: number` — Optional offset along the plane normal (primarily for object-form overload).
385
- - `exclude?: CutPlaneExcludeInput` — Object names to keep uncut for this plane.
386
-
387
- #### `mock()` — Register a mock (context) object for visualization and collision checking.
388
-
389
- Mock objects appear in the viewport and spatial 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
-
391
- The shape is returned unchanged, so you can reference it for alignment, dimensioning, and `verify` checks.
392
-
393
- Mock objects participate in `forgecad run --spatial bounded|exact` collision detection and spatial analysis. Their names appear with a `(mock)` suffix in reports.
394
-
395
- In the viewport, mock objects render at reduced opacity so they are visually distinct from real geometry.
396
-
397
- ```ts
398
- // bracket.forge.js
399
- const wall = mock(box(100, 200, 10).translate(0, 0, -5), "wall");
400
- const bolt = mock(cylinder(3, 15).translate(10, 15, 0), "bolt");
401
-
402
- const bracket = box(20, 30, 5);
403
- verify.notColliding("bracket vs wall", bracket, wall);
404
-
405
- return bracket;
406
- // When imported: only bracket is exported
407
- // When run directly: bracket + wall + bolt all visible
408
- ```
409
-
410
- ```ts
411
- mock<T extends Shape>(shape: T, name?: string): T
412
- ```
413
-
414
- #### `showLabels()` — Highlight all user-labeled faces on a shape for visual debugging.
415
-
416
- Shows each user-authored label name in the viewport for visual debugging. Returns the shape unchanged for chaining: `return showLabels(myShape)`.
417
-
418
- ```ts
419
- showLabels(shape: Shape): Shape
420
- ```
421
-
422
- #### `highlight()` — Highlight any geometry for visual debugging in the viewport.
423
-
424
- Supported inputs:
425
-
426
- - `string` — sketch entity ID (e.g. `'L0'`, `'P0'`, `'C0'`)
427
- - `[x, y, z]` — 3D point
428
- - `[[x1,y1,z1], [x2,y2,z2]]` — edge (line segment)
429
- - `{ normal: [x,y,z], offset: number }` — plane by normal + distance from origin
430
- - `{ normal: [x,y,z], point: [x,y,z] }` — plane by normal + point on plane
431
- - [`Shape`](/docs/core#shape) — highlight entire 3D shape
432
- - `FaceRef` (from `shape.face('top')`) — highlight as plane at face center
433
- - `EdgeRef` (from `shape.edge('left')`) — highlight as edge segment
434
-
435
- Overloads:
436
-
437
- - `highlight(entityId: string, opts?: HighlightOptions): void`
438
- - `highlight(point: [ number, number, number ], opts?: HighlightOptions): void`
439
- - `highlight(edge: [ [ number, number, number ], [ number, number, number ] ], opts?: HighlightOptions): void`
440
- - `highlight(plane: { normal: [ number, number, number ]; offset: number; }, opts?: HighlightOptions): void`
441
- - `highlight(plane: { normal: [ number, number, number ]; point: [ number, number, number ]; }, opts?: HighlightOptions): void`
442
- - `highlight(shape: Shape, opts?: HighlightOptions): void`
443
- - `highlight(face: FaceRef, opts?: HighlightOptions): void`
444
- - `highlight(edge: EdgeRef, opts?: HighlightOptions): void`
445
-
446
- **`HighlightOptions`**
447
- - `size?: number` — Size hint for points (radius in mm) or planes (disc radius in mm).
448
- - Also: `color?: string, label?: string, pulse?: boolean`
449
-
450
- **`FaceRef`**
451
-
452
- | Option | Type | Description |
453
- |--------|------|-------------|
454
- | `normal` | `[ number, number, number ]` | Normal direction of the face |
455
- | `center` | `[ number, number, number ]` | Center point of the face |
456
- | `query?` | `FaceQueryRef` | Compiler-owned face query when available. |
457
- | `planar?` | `boolean` | True when the face can host a 2D sketch placement frame |
458
- | `uAxis?` | `[ number, number, number ]` | Face-local horizontal axis for planar faces |
459
- | `vAxis?` | `[ number, number, number ]` | Face-local vertical axis for planar faces |
460
- | `surface?` | `FaceSurface` | Analytic surface family when the backend can identify one. |
461
- | `descendant?` | `FaceDescendantMetadata` | Shared descendant-resolution metadata when this face is a semantic region/set. |
462
- | `name` | | — |
463
-
464
- **`FaceDescendantMetadata`**: `kind: "single" | "face-set"`, `semantic: FaceDescendantSemantic`, `memberCount: number`, `memberNames: string[]`, `coplanar: boolean`
465
-
466
- **`EdgeRef`**
467
-
468
- | Option | Type | Description |
469
- |--------|------|-------------|
470
- | `start` | `[ number, number, number ]` | Start point |
471
- | `end` | `[ number, number, number ]` | End point |
472
- | `query?` | `EdgeQueryRef` | Compiler-owned edge query when available. |
473
- | `curve?` | `EdgeCurve` | Exact or parametric curve family when the backend/source can identify one. |
474
- | `faceName?` | `string` | Owning face name when the edge is associated with one face in a larger topology. |
475
- | `name` | | — |
476
-
477
- ---
478
-
479
- ## Classes
480
-
481
- ### `RouteBuilder`
482
-
483
- #### `up()` — Vertical line going +Y. Length is optional (solver determines it from constraints).
484
-
485
- ```ts
486
- up(length?: number): LineId
487
- ```
488
-
489
- #### `down()` — Vertical line going -Y. Length is optional.
490
-
491
- ```ts
492
- down(length?: number): LineId
493
- ```
494
-
495
- #### `right()` — Horizontal line going +X. Length is optional.
496
-
497
- ```ts
498
- right(length?: number): LineId
499
- ```
500
-
501
- #### `left()` — Horizontal line going -X. Length is optional.
502
-
503
- ```ts
504
- left(length?: number): LineId
505
- ```
506
-
507
- #### `lineAt()` — Line at an arbitrary angle (degrees from +X). Length is optional.
508
-
509
- ```ts
510
- lineAt(angleDeg: number, length?: number): LineId
511
- ```
512
-
513
- #### [`line()`](/docs/sketch#line) — Line with solver-determined direction. Length is optional. Direction comes from tangency to previous arc or from constraints.
514
-
515
- ```ts
516
- line(length?: number): LineId
517
- ```
518
-
519
- #### `toward()` — Line toward a specific point. Length defaults to the distance to that point.
520
-
521
- ```ts
522
- toward(x: number, y: number): LineId
523
- ```
524
-
525
- #### `arcLeft()` — Tangent arc turning left relative to travel direction.
526
-
527
- or `{ minSweep: degrees }` to seed the geometry without constraining. `minSweep` guides the solver to the correct branch for arcs that sweep more than the default 90° seed.
528
-
529
- ```ts
530
- arcLeft(radius?: number, sweepDegOrOpts?: number | { minSweep: number; }): ArcId
531
- ```
532
-
533
- #### `arcRight()` — Tangent arc turning right relative to travel direction.
534
-
535
- or `{ minSweep: degrees }` to seed without constraining.
536
-
537
- ```ts
538
- arcRight(radius?: number, sweepDegOrOpts?: number | { minSweep: number; }): ArcId
539
- ```
540
-
541
- #### `close()` — Close the route with a straight line back to the start point.
542
-
543
- ```ts
544
- close(): void
545
- ```
546
-
547
- #### `done()` — Close the route back to its start point and register as a profile loop.
548
-
549
- No extra line segment is added. A coincident constraint connects the last point to the start, and tangency is added for G1 smoothness when arcs are at the junction. The session's incremental solver processes these constraints, keeping seed positions accurate for the final solve.
550
-
551
- ```ts
552
- done(): void
553
- ```
554
-
555
- #### `start()` — PointId of the route's start point.
556
-
557
- ```ts
558
- get start(): PointId
559
- ```
560
-
561
- #### `end()` — PointId of the current cursor (route's end).
562
-
563
- ```ts
564
- get end(): PointId
565
- ```
566
-
567
- #### `startOf()` — Get the start point of a segment.
568
-
569
- ```ts
570
- startOf(segId: LineId | ArcId): PointId
571
- ```
572
-
573
- #### `endOf()` — Get the end point of a segment.
574
-
575
- ```ts
576
- endOf(segId: LineId | ArcId): PointId
577
- ```
578
-
579
- ---
580
-
581
- ## Constants
582
-
583
- ### `route`
584
-
585
- Route step factories. Access via `route.line()`, `route.fillet()`, etc.
@@ -1,108 +0,0 @@
1
- ---
2
- skill-group: toolbox
3
- skill-order: 100
4
- ---
5
-
6
- # Woodworking
7
-
8
- Wood boards with grain/species metadata, and joinery operations: dado, rabbet, mortise & tenon. Access via `Wood.*`.
9
-
10
- ## Contents
11
-
12
- - [WoodBoard](#woodboard)
13
- - [Wood](#wood)
14
-
15
- ---
16
-
17
- ## Classes
18
-
19
- ### `WoodBoard`
20
-
21
- A board of wood with metadata for manufacturing: grain direction, species, and dimensions. The underlying geometry is a simple box.
22
-
23
- WoodBoard operations are immutable. Joint operations return new boards instead of carving the original in-place, and transform methods preserve all metadata.
24
-
25
- **Properties:**
26
-
27
- | Property | Type | Description |
28
- |----------|------|-------------|
29
- | `shape` | `Shape` | The underlying 3D shape. |
30
- | `width` | `number` | Board width (mm) — the longer flat dimension |
31
- | `height` | `number` | Board height (mm) — the shorter flat dimension |
32
- | `thickness` | `number` | Board thickness (mm) |
33
- | `grain` | `string` | Grain direction: "long" or "cross" |
34
- | `species` | `string` | Wood species, e.g. "birch", "oak" |
35
- | `material` | `string` | Material label for BOM |
36
-
37
- **Methods:**
38
-
39
- #### `cut()` — Subtract a cutter from this board, returning a new board. Used by joint functions (dado, rabbet, mortiseAndTenon).
40
-
41
- ```ts
42
- cut(cutter: Shape): WoodBoard
43
- ```
44
-
45
- #### `translate()` — Translate the board in 3D space.
46
-
47
- ```ts
48
- translate(x: number, y: number, z: number): WoodBoard
49
- ```
50
-
51
- #### `rotate()` — Rotate the board around an axis by a given angle in degrees.
52
-
53
- ```ts
54
- rotate(axis: [ number, number, number ], angleDeg: number, options?: { pivot?: [ number, number, number ]; }): WoodBoard
55
- ```
56
-
57
- #### `rotateX()` — Rotate the board around the X axis by a given angle in degrees.
58
-
59
- ```ts
60
- rotateX(angleDeg: number): WoodBoard
61
- ```
62
-
63
- #### `rotateY()` — Rotate the board around the Y axis by a given angle in degrees.
64
-
65
- ```ts
66
- rotateY(angleDeg: number): WoodBoard
67
- ```
68
-
69
- #### `rotateZ()` — Rotate the board around the Z axis by a given angle in degrees.
70
-
71
- ```ts
72
- rotateZ(angleDeg: number): WoodBoard
73
- ```
74
-
75
- #### `mirror()` — Mirror the board across a plane defined by its normal.
76
-
77
- ```ts
78
- mirror(normal: [ number, number, number ]): WoodBoard
79
- ```
80
-
81
- #### `color()` — Set the board's display color.
82
-
83
- ```ts
84
- color(value: string): WoodBoard
85
- ```
86
-
87
- #### `clone()` — Clone the board (creates an independent copy of the underlying shape).
88
-
89
- ```ts
90
- clone(): WoodBoard
91
- ```
92
-
93
- ---
94
-
95
- ## Constants
96
-
97
- ### `Wood`
98
-
99
- Woodworking namespace — create boards and cut joints.
100
-
101
- **Boards:** `Wood.board()` creates a WoodBoard with grain, species, and BOM metadata.
102
-
103
- **Joints:** `Wood.dado()`, `Wood.rabbet()`, and `Wood.mortiseAndTenon()` are immutable — they return new board value(s) with the joint cut applied.
104
-
105
- - `readonly board: (width: number, height: number, thickness: number, opts?: WoodBoardOptions) => WoodBoard` — Create a wood board with metadata for manufacturing. The board is a box(width, height, thickness) centered on XY, base at Z=0. Width along X, height along Y, thickness along Z (0 to thickness).
106
- - `dado(host: WoodBoard, guest: WoodBoard, opts: DadoOptions): WoodBoard` — Cut a dado (channel) across the face of a host board for a guest board to sit in. Returns a new host board with the dado cut applied.
107
- - `rabbet(board: WoodBoard, opts: RabbetOptions): WoodBoard` — Cut a rabbet (L-shaped step) along an edge of a board. Returns a new board with the rabbet cut applied.
108
- - `mortiseAndTenon(mortiseBoard: WoodBoard, tenonBoard: WoodBoard, opts?: MortiseAndTenonOptions): MortiseAndTenonResult` — Cut a mortise in one board and shape a tenon on another. Returns new boards with the mortise pocket and tenon cuts applied.