forgecad 0.6.3 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (234) hide show
  1. package/README.md +3 -12
  2. package/dist/assets/{AdminPage-CeqCUUgu.js → AdminPage-D4bocK4E.js} +250 -151
  3. package/dist/assets/{BlogPage-P_AJP0v9.js → BlogPage-CJEXL_zJ.js} +94 -70
  4. package/dist/assets/{DocsPage-CKRV2iq2.js → DocsPage-D3A_g8V3.js} +329 -163
  5. package/dist/assets/{EditorApp-CnC2k4cW.css → EditorApp-BWYUSpUN.css} +590 -136
  6. package/dist/assets/EditorApp-Cihhqcsq.js +11692 -0
  7. package/dist/assets/{EmbedViewer-DBlzmQ5i.js → EmbedViewer-kWjKaC_t.js} +2 -4
  8. package/dist/assets/LandingPageProofDriven-Bg2IUc3l.css +856 -0
  9. package/dist/assets/LandingPageProofDriven-DXkKlyhI.js +601 -0
  10. package/dist/assets/PricingPage-BsU5vzEx.js +232 -0
  11. package/dist/assets/{SettingsPage-BqCh9JcC.js → SettingsPage-PqvpAKIs.js} +129 -5
  12. package/dist/assets/{evalWorker-Ql-aKwLA.js → evalWorker-C-hzNUMy.js} +8949 -3161
  13. package/dist/assets/{Viewport-CoB46f5R.js → index-Pz321YAt.js} +38382 -7501
  14. package/dist/assets/{index-2hfs_ub0.css → index-ay13WNfa.css} +726 -53
  15. package/dist/assets/{javascript-DCxGoE5Y.js → javascript-DAl8Gmyo.js} +1 -1
  16. package/dist/assets/{manifold-CqNMHHKO.js → manifold-BcbjWLIo.js} +4 -3
  17. package/dist/assets/{manifold-Cce9wRFz.js → manifold-DBckbFgx.js} +1 -1
  18. package/dist/assets/{manifold-D6BeHIOo.js → manifold-O2AAGXyj.js} +1 -1
  19. package/dist/assets/{reportWorker-sFEFonXf.js → reportWorker-Dxr-5A7w.js} +8760 -3559
  20. package/dist/assets/{vendor-react-Dt7-aaJH.js → vendor-react-CG3i_wp0.js} +65 -8
  21. package/dist/docs/index.html +2 -2
  22. package/dist/docs-raw/CLI.md +341 -718
  23. package/dist/docs-raw/generated/assembly.md +699 -112
  24. package/dist/docs-raw/generated/concepts.md +1834 -1346
  25. package/dist/docs-raw/generated/core.md +1012 -1059
  26. package/dist/docs-raw/generated/curves.md +759 -116
  27. package/dist/docs-raw/generated/lib.md +43 -748
  28. package/dist/docs-raw/generated/output.md +139 -245
  29. package/dist/docs-raw/generated/sdf.md +208 -0
  30. package/dist/docs-raw/generated/sheet-metal.md +473 -21
  31. package/dist/docs-raw/generated/sketch.md +1518 -362
  32. package/dist/docs-raw/generated/viewport.md +368 -299
  33. package/dist/docs-raw/generated/wood.md +104 -0
  34. package/dist/index.html +2 -2
  35. package/dist/landing/proof-ams-adapter.png +0 -0
  36. package/dist/landing/proof-bolt-and-nut.png +0 -0
  37. package/dist/landing/proof-fillet-enclosure.png +0 -0
  38. package/dist/landing/proof-glasses.png +0 -0
  39. package/dist/landing/proof-gyroid.png +0 -0
  40. package/dist/sitemap.xml +6 -6
  41. package/dist-cli/forgecad.js +12321 -5700
  42. package/dist-cli/forgecad.js.map +1 -0
  43. package/dist-cli/solver-46FFSK2U.js +363 -0
  44. package/dist-cli/solver-46FFSK2U.js.map +1 -0
  45. package/dist-skill/CONTEXT.md +4890 -6302
  46. package/dist-skill/SKILL-dev.md +22 -66
  47. package/dist-skill/SKILL.md +20 -59
  48. package/dist-skill/docs/API/core/concepts.md +37 -92
  49. package/dist-skill/docs/CLI.md +341 -718
  50. package/dist-skill/docs/generated/assembly.md +699 -112
  51. package/dist-skill/docs/generated/core.md +1012 -1059
  52. package/dist-skill/docs/generated/curves.md +759 -116
  53. package/dist-skill/docs/generated/lib.md +43 -748
  54. package/dist-skill/docs/generated/output.md +139 -245
  55. package/dist-skill/docs/generated/sdf.md +208 -0
  56. package/dist-skill/docs/generated/sheet-metal.md +473 -21
  57. package/dist-skill/docs/generated/sketch.md +1518 -362
  58. package/dist-skill/docs/generated/viewport.md +368 -299
  59. package/dist-skill/docs/generated/wood.md +104 -0
  60. package/dist-skill/docs/guides/coordinate-system.md +11 -17
  61. package/dist-skill/docs/guides/geometry-conventions.md +13 -70
  62. package/dist-skill/docs/guides/joint-design.md +78 -0
  63. package/dist-skill/docs/guides/modeling-recipes.md +22 -195
  64. package/dist-skill/docs/guides/positioning.md +88 -147
  65. package/dist-skill/docs-dev/API/core/concepts.md +78 -0
  66. package/dist-skill/docs-dev/CLI.md +488 -0
  67. package/dist-skill/{docs → docs-dev}/blueprint-first.md +5 -0
  68. package/dist-skill/{docs → docs-dev}/coding-best-practices.md +6 -8
  69. package/dist-skill/{docs → docs-dev}/coding.md +2 -4
  70. package/dist-skill/docs-dev/component-model.md +164 -0
  71. package/dist-skill/docs-dev/generated/assembly.md +779 -0
  72. package/dist-skill/docs-dev/generated/core.md +1676 -0
  73. package/dist-skill/docs-dev/generated/curves.md +855 -0
  74. package/dist-skill/docs-dev/generated/lib.md +55 -0
  75. package/dist-skill/docs-dev/generated/output.md +234 -0
  76. package/dist-skill/docs-dev/generated/sdf.md +208 -0
  77. package/dist-skill/docs-dev/generated/sheet-metal.md +506 -0
  78. package/dist-skill/docs-dev/generated/sketch.md +1753 -0
  79. package/dist-skill/docs-dev/generated/viewport.md +513 -0
  80. package/dist-skill/docs-dev/generated/wood.md +104 -0
  81. package/dist-skill/docs-dev/guides/coordinate-system.md +46 -0
  82. package/dist-skill/docs-dev/guides/geometry-conventions.md +52 -0
  83. package/dist-skill/docs-dev/guides/joint-design.md +78 -0
  84. package/dist-skill/docs-dev/guides/modeling-recipes.md +77 -0
  85. package/dist-skill/docs-dev/guides/positioning.md +151 -0
  86. package/dist-skill/{docs → docs-dev}/guides/skill-maintenance.md +21 -10
  87. package/dist-skill/{docs → docs-dev}/internals/compiler.md +5 -6
  88. package/dist-skill/{docs → docs-dev}/internals/constraint-solver-quality.md +0 -1
  89. package/dist-skill/{docs → docs-dev}/internals/constraint-solver.md +0 -1
  90. package/dist-skill/{docs → docs-dev}/internals/sketch-2d-pipeline.md +2 -3
  91. package/examples/api/attachTo-basics.forge.js +8 -8
  92. package/examples/api/bill-of-materials.forge.js +9 -9
  93. package/examples/api/bolt-pattern.forge.js +5 -5
  94. package/examples/api/boolean-operations.forge.js +5 -5
  95. package/examples/api/bounding-box-visualizer.forge.js +3 -3
  96. package/examples/api/clone-duplicate.forge.js +2 -2
  97. package/examples/api/colors-union-vs-array.forge.js +6 -6
  98. package/examples/api/connector-assembly.forge.js +8 -6
  99. package/examples/api/connector-basics.forge.js +7 -7
  100. package/examples/api/constrained-sketch-mechanical.forge.js +4 -4
  101. package/examples/api/elbow-test.forge.js +3 -3
  102. package/examples/api/extrude-options.forge.js +8 -14
  103. package/examples/api/feature-created-faces.forge.js +6 -10
  104. package/examples/api/fillet-showcase.forge.js +2 -2
  105. package/examples/api/folded-service-panel-cover.forge.js +2 -2
  106. package/examples/api/gears-tier1.forge.js +5 -5
  107. package/examples/api/group-test.forge.js +3 -3
  108. package/examples/api/group-vs-union.forge.js +1 -1
  109. package/examples/api/highlight-debug.forge.js +4 -0
  110. package/examples/api/js-module-pillars.js +1 -1
  111. package/examples/api/js-module-scene.js +2 -2
  112. package/examples/api/mesh-import-slats.forge.js +4 -4
  113. package/examples/api/patterns.forge.js +3 -3
  114. package/examples/api/pointAlong-orientation.forge.js +3 -3
  115. package/examples/api/profile-2020-b-slot6.forge.js +4 -5
  116. package/examples/api/route-perimeter-flange.forge.js +1 -1
  117. package/examples/api/sdf-rover-demo.forge.js +10 -10
  118. package/examples/api/sketch-on-face-demo.forge.js +2 -2
  119. package/examples/api/sketch-regions.forge.js +4 -4
  120. package/examples/api/sketch-rounding-strategies.forge.js +1 -1
  121. package/examples/api/smooth-curve-connections.forge.js +1 -1
  122. package/examples/api/transition-curves.forge.js +4 -4
  123. package/examples/api/variable-sweep-pure-sdf-test.forge.js +162 -0
  124. package/examples/api/variable-sweep-test.forge.js +2 -2
  125. package/examples/api/wood-joinery.forge.js +60 -0
  126. package/examples/compiler-corpus/enclosure-shell-cuts.forge.js +3 -3
  127. package/examples/compiler-corpus/fastener-plate-variants.forge.js +2 -2
  128. package/examples/constraints/01-fully-constrained-rect.forge.js +2 -2
  129. package/examples/constraints/02-underconstrained-triangle.forge.js +1 -1
  130. package/examples/constraints/03-redundant-constraints.forge.js +2 -2
  131. package/examples/constraints/05-parallel-with-linedistance.forge.js +2 -2
  132. package/examples/constraints/06-complex-spectrogram.forge.js +1 -1
  133. package/examples/constraints/07-perpendicular-chain.forge.js +4 -4
  134. package/examples/constraints/08-symmetric-bracket.forge.js +4 -4
  135. package/examples/constraints/09-stress-spiral.forge.js +1 -1
  136. package/examples/constraints/10-stress-honeycomb.forge.js +1 -1
  137. package/examples/constraints/11-surface-grid.forge.js +2 -2
  138. package/examples/constraints/12-surface-nested.forge.js +4 -4
  139. package/examples/constraints/13-surface-complex.forge.js +1 -1
  140. package/examples/exact-arc-housing.forge.js +12 -0
  141. package/examples/experiments/drone-arm.forge.js +53 -0
  142. package/examples/furniture/adjustable-table.forge.js +15 -15
  143. package/examples/furniture/bathroom.forge.js +26 -26
  144. package/examples/furniture/chair.forge.js +13 -13
  145. package/examples/furniture/picture-frame.forge.js +6 -6
  146. package/examples/furniture/shoe-rack-doors.forge.js +8 -8
  147. package/examples/furniture/shoe-rack.forge.js +7 -7
  148. package/examples/furniture/table-lamp.forge.js +8 -8
  149. package/examples/gcode/lissajous-vase.forge.js +4 -4
  150. package/examples/gcode/math-surface.forge.js +3 -3
  151. package/examples/gcode/parametric-vase.forge.js +4 -4
  152. package/examples/gcode/spiral-tower.forge.js +4 -4
  153. package/examples/generative/crystal-growth.forge.js +9 -9
  154. package/examples/generative/frost-spires.forge.js +9 -9
  155. package/examples/generative/golden-spiral-tower.forge.js +11 -11
  156. package/examples/generative/molten-forge.forge.js +6 -6
  157. package/examples/generative/neon-coral.forge.js +7 -7
  158. package/examples/mechanical/3d-printer.forge.js +37 -37
  159. package/examples/mechanical/5-finger-robot-hand.forge.js +19 -19
  160. package/examples/mechanical/airplane-propeller.forge.js +9 -9
  161. package/examples/mechanical/bolt-and-nut.forge.js +10 -10
  162. package/examples/mechanical/door-with-hinges.forge.js +7 -7
  163. package/examples/mechanical/fillet-enclosure.forge.js +15 -11
  164. package/examples/mechanical/headphone-hanger-v2.forge.js +11 -11
  165. package/examples/mechanical/robot_hand.forge.js +24 -24
  166. package/examples/mechanical/robot_hand_2.forge.js +26 -26
  167. package/examples/nurbs-surface.forge.js +8 -0
  168. package/examples/nurbs-tube.forge.js +7 -0
  169. package/examples/products/bottle.forge.js +8 -8
  170. package/examples/products/chess-set.forge.js +25 -25
  171. package/examples/products/classical-piano.forge.js +20 -20
  172. package/examples/products/clock.forge.js +33 -33
  173. package/examples/products/cup.forge.js +5 -5
  174. package/examples/products/iphone.forge.js +20 -20
  175. package/examples/products/laptop.forge.js +24 -24
  176. package/examples/products/laser-cut-box.forge.js +6 -6
  177. package/examples/products/laser-cut-tray.forge.js +6 -6
  178. package/examples/products/liquid-soap-dispenser.forge.js +23 -23
  179. package/examples/products/origami-fish.forge.js +14 -12
  180. package/examples/products/spiderman-cake.forge.js +6 -6
  181. package/examples/shelf/container.forge.js +5 -5
  182. package/examples/shelf/shelf-unit.forge.js +6 -6
  183. package/examples/toolbox/bolted-joint.forge.js +7 -7
  184. package/package.json +9 -4
  185. package/dist/assets/EditorApp-B-vQvgam.js +0 -9888
  186. package/dist/assets/LandingPage-C5n9hDXI.js +0 -322
  187. package/dist/assets/PublishedModelPage-Dt7PCVBj.js +0 -146
  188. package/dist/assets/__vite-browser-external-CURh0WXD.js +0 -8
  189. package/dist/assets/deserializeRunResult-BLAFoiE0.js +0 -19365
  190. package/dist/assets/index-1CYp3zUp.js +0 -1455
  191. package/dist-skill/docs/API/API.md +0 -1666
  192. package/dist-skill/docs/API/README.md +0 -37
  193. package/dist-skill/docs/API/assembly/assembly.md +0 -617
  194. package/dist-skill/docs/API/core/edge-queries.md +0 -130
  195. package/dist-skill/docs/API/core/parameters.md +0 -122
  196. package/dist-skill/docs/API/core/reserved-terms.md +0 -137
  197. package/dist-skill/docs/API/core/sdf.md +0 -326
  198. package/dist-skill/docs/API/core/skill-cli.md +0 -194
  199. package/dist-skill/docs/API/core/skill-guide.md +0 -205
  200. package/dist-skill/docs/API/core/specs.md +0 -186
  201. package/dist-skill/docs/API/core/topology.md +0 -372
  202. package/dist-skill/docs/API/entities.md +0 -268
  203. package/dist-skill/docs/API/output/bom.md +0 -58
  204. package/dist-skill/docs/API/output/brep-export.md +0 -87
  205. package/dist-skill/docs/API/output/dimensions.md +0 -67
  206. package/dist-skill/docs/API/output/export.md +0 -110
  207. package/dist-skill/docs/API/output/gcode.md +0 -195
  208. package/dist-skill/docs/API/runtime/viewport.md +0 -420
  209. package/dist-skill/docs/API/sheet-metal/sheet-metal.md +0 -185
  210. package/dist-skill/docs/API/sketch/anchor.md +0 -37
  211. package/dist-skill/docs/API/sketch/booleans.md +0 -91
  212. package/dist-skill/docs/API/sketch/core.md +0 -73
  213. package/dist-skill/docs/API/sketch/extrude.md +0 -62
  214. package/dist-skill/docs/API/sketch/on-face.md +0 -104
  215. package/dist-skill/docs/API/sketch/operations.md +0 -78
  216. package/dist-skill/docs/API/sketch/path.md +0 -75
  217. package/dist-skill/docs/API/sketch/primitives.md +0 -146
  218. package/dist-skill/docs/API/sketch/regions.md +0 -80
  219. package/dist-skill/docs/API/sketch/text.md +0 -108
  220. package/dist-skill/docs/API/sketch/transforms.md +0 -65
  221. package/dist-skill/docs/API/toolbox/fasteners.md +0 -129
  222. package/dist-skill/docs/INDEX.md +0 -94
  223. package/dist-skill/docs/RELEASING.md +0 -55
  224. package/dist-skill/docs/cli-monetization.md +0 -111
  225. package/dist-skill/docs/deployment.md +0 -281
  226. package/dist-skill/docs/generated/concepts.md +0 -2112
  227. package/dist-skill/docs/internals/shape-from-slices.md +0 -152
  228. package/dist-skill/docs/platform/admin.md +0 -45
  229. package/dist-skill/docs/platform/architecture.md +0 -79
  230. package/dist-skill/docs/platform/auth.md +0 -110
  231. package/dist-skill/docs/platform/email.md +0 -67
  232. package/dist-skill/docs/platform/projects.md +0 -111
  233. package/dist-skill/docs/platform/sharing.md +0 -90
  234. package/dist-skill/docs/runbook.md +0 -345
@@ -1,420 +0,0 @@
1
- ---
2
- skill-group: viewport
3
- skill-order: 1
4
- ---
5
-
6
- # Viewport Runtime APIs
7
-
8
- These APIs affect the viewer and scene presentation. They do not change the underlying model geometry contract, so they are not part of the required model-building reading set.
9
-
10
- ## `scene(options)`
11
-
12
- Control the full visual environment — camera, lighting, background, fog, and post-processing. Essential for generative art, presentations, and dramatic renders.
13
-
14
- When `scene()` is called, it **replaces** the default viewer settings for the specified properties. Properties not specified keep their defaults. Multiple calls merge (later overrides earlier).
15
-
16
- **Parameters:**
17
- - `background` (string or `{ top, bottom }`) — solid color (`'#0a0a0a'`) or vertical gradient
18
- - `camera` (object):
19
- - `position` (`[x, y, z]`) — camera world position (overrides auto-framing)
20
- - `target` (`[x, y, z]`) — look-at point
21
- - `fov` (number) — field of view in degrees (1–179)
22
- - `up` (`[x, y, z]`) — up vector (default `[0, 0, 1]`)
23
- - `type` (`'perspective' | 'orthographic'`)
24
- - `lights` (array) — **replaces** all default lights. Each entry:
25
- - `type` (`'ambient' | 'directional' | 'point' | 'spot' | 'hemisphere'`) — required
26
- - `color` (string) — CSS color
27
- - `intensity` (number)
28
- - `position` (`[x, y, z]`) — for directional, point, spot
29
- - `target` (`[x, y, z]`) — for directional, spot
30
- - `groundColor` / `skyColor` (string) — for hemisphere
31
- - `angle` (number) — spot cone angle in radians
32
- - `penumbra` (number, 0–1) — spot penumbra
33
- - `decay` (number) — point/spot light decay
34
- - `distance` (number) — point/spot max range (0 = infinite)
35
- - `castShadow` (boolean)
36
- - `environment` (object):
37
- - `preset` (`'studio' | 'sunset' | 'dawn' | 'warehouse' | 'forest' | 'apartment' | 'lobby' | 'city' | 'park' | 'night' | 'none'`)
38
- - `intensity` (number) — environment map intensity
39
- - `background` (boolean) — use environment map as scene background
40
- - `fog` (object):
41
- - `color` (string)
42
- - `near` / `far` (number) — linear fog
43
- - `density` (number) — if set, uses exponential fog instead of linear
44
- - `postProcessing` (object):
45
- - `bloom` — `{ intensity?, threshold?, radius? }`
46
- - `vignette` — `{ darkness?, offset? }`
47
- - `grain` — `{ intensity? }`
48
- - `toneMappingExposure` (number)
49
- - `ground` (object):
50
- - `visible` (boolean)
51
- - `color` (string)
52
- - `height` (number) — Z offset
53
- - `receiveShadow` (boolean)
54
- - `capture` (object) — default capture parameters for `forgecad capture`; CLI flags override these:
55
- - `framesPerTurn` (number, 12–720) — frames for one orbit rotation (default: 72)
56
- - `holdFrames` (number, 0–300) — frozen frames before motion (default: 6)
57
- - `pitchDeg` (number, -80–80) — orbit pitch angle (default: auto from camera)
58
- - `fps` (number, 1–60) — output frame rate (default: 24)
59
- - `size` (number) — output frame size in pixels (default: 960)
60
- - `background` (string) — canvas background color (default: '#252526')
61
-
62
- **Returns:** `void`
63
-
64
- ```javascript
65
- scene({
66
- background: { top: '#000814', bottom: '#001d3d' },
67
-
68
- camera: {
69
- position: [160, -120, 100],
70
- target: [0, 0, 50],
71
- fov: 52,
72
- },
73
-
74
- lights: [
75
- { type: 'ambient', color: '#001233', intensity: 0.08 },
76
- { type: 'point', position: [120, -80, 130], color: '#00f5d4', intensity: 4, distance: 400, decay: 1 },
77
- { type: 'point', position: [-100, 60, 20], color: '#f72585', intensity: 3, distance: 350 },
78
- { type: 'directional', position: [50, -30, 200], color: '#ffd60a', intensity: 1.2 },
79
- { type: 'hemisphere', skyColor: '#003566', groundColor: '#000814', intensity: 0.2 },
80
- ],
81
-
82
- fog: { color: '#000814', near: 100, far: 450 },
83
-
84
- postProcessing: {
85
- bloom: { intensity: param('bloom', 1.5, 0, 4), threshold: 0.5, radius: 0.7 },
86
- vignette: { darkness: 0.8, offset: 0.25 },
87
- grain: { intensity: 0.08 },
88
- toneMappingExposure: param('exposure', 1.5, 0.5, 4),
89
- },
90
- });
91
- ```
92
-
93
- Notes:
94
- - All values work with `param()` for real-time slider control
95
- - When `lights` is specified, **all** default lights are removed — you must provide your own ambient light or the scene will be very dark
96
- - Post-processing (bloom, vignette, grain) works in the browser viewport only — CLI renders apply camera, lights, background, fog, and exposure but not shader-based effects
97
- - Camera `position` overrides the auto-frame behavior — the viewport will not auto-fit the geometry to view
98
- - See `examples/generative-art/` for full demos
99
-
100
- ## `shape.material(props)`
101
-
102
- Set per-object material properties for controlling visual appearance. Returns a new Shape with the specified material properties. Material properties survive transforms (translate, rotate, scale, etc.) and boolean operations.
103
-
104
- **Parameters (all optional):**
105
- - `metalness` (number, 0–1) — metallic vs. dielectric appearance. Default: 0.05
106
- - `roughness` (number, 0–1) — surface roughness (0 = mirror, 1 = matte). Default: 0.35
107
- - `emissive` (string) — glow color (hex string, e.g. `'#ff6b35'`)
108
- - `emissiveIntensity` (number) — glow multiplier. Default: 1
109
- - `opacity` (number, 0–1) — transparency. Default: 1
110
- - `wireframe` (boolean) — render as wireframe. Default: false
111
- - `clearcoat` (number, 0–1) — clearcoat layer intensity. Default: 0.1
112
- - `clearcoatRoughness` (number, 0–1) — clearcoat roughness. Default: 0.4
113
-
114
- **Returns:** `Shape`
115
-
116
- ```javascript
117
- // Polished metal
118
- box(50, 50, 50).material({ metalness: 0.9, roughness: 0.1 });
119
-
120
- // Glowing emissive
121
- sphere(30).material({ emissive: '#ff6b35', emissiveIntensity: 2 });
122
-
123
- // Translucent ice
124
- cylinder(40, 20).material({ opacity: 0.4, clearcoat: 1.0, clearcoatRoughness: 0.02 });
125
-
126
- // Chainable with other methods
127
- box(100, 100, 10)
128
- .color('#gold')
129
- .material({ metalness: 0.95, roughness: 0.05 })
130
- .translate(0, 0, 50);
131
- ```
132
-
133
- Notes:
134
- - Material properties are per-shape — each returned object can have different materials
135
- - Works in both the browser viewport and CLI renderer
136
- - `.color()` sets the base diffuse color; `.material()` controls how that color behaves under light
137
- - Emissive color glows independently of lighting — great for generative art effects like bloom
138
- - See `examples/generative-art/molten-forge.forge.js` and `frost-spires.forge.js` for full demos
139
-
140
- ## `cutPlane(name, normal, offsetOrOptions?, options?)`
141
-
142
- Define a named section plane for inspection.
143
-
144
- **Parameters:**
145
- - `name` (string) - label shown in the viewport controls
146
- - `normal` (`[number, number, number]`) - direction toward the clipped side
147
- - `offsetOrOptions` (number or object, optional):
148
- - number: plane offset from origin along `normal`
149
- - object: `{ offset?: number, exclude?: string | string[] }`
150
- - `options` (object, optional; used with numeric offset):
151
- - `exclude` (`string | string[]`) - returned object `name` values to keep uncut
152
-
153
- **Returns:** `void`
154
-
155
- ```javascript
156
- const cutZ = param("Cut Height", 10, { min: -50, max: 50, unit: "mm" });
157
-
158
- cutPlane("Inspection", [0, 0, 1], cutZ, {
159
- exclude: ["Probe", "Fasteners"],
160
- });
161
- ```
162
-
163
- Notes:
164
- - planes are registered per script run
165
- - viewport toggle state persists across parameter changes
166
- - clipping is applied to returned named objects, so `exclude` only works when names are stable
167
- - newly exposed section faces render with a hatched overlay; pre-existing coplanar boundary faces are left unhatched
168
-
169
- ## `explodeView(options?)`
170
-
171
- Override how the viewport explode slider offsets returned objects.
172
-
173
- Explode offsets are resolved from the returned object tree, not from a flat list.
174
- In `radial` mode each node follows its parent branch direction, then adds a smaller
175
- local fan from the immediate parent/subassembly center, so nested assemblies peel
176
- apart level by level without losing their branch structure.
177
-
178
- In fixed-axis or fixed-vector modes, the branch itself follows that axis/vector, but
179
- nested descendants fan out perpendicular to the branch by default so deep trees do
180
- not keep stacking farther along the same axis.
181
-
182
- By default this is container-oriented: named groups/subassemblies advance along the
183
- tree, while plain leaves inside a group stay much closer and mostly fan locally
184
- around their parent cluster unless you override them explicitly.
185
-
186
- **Parameters:**
187
- - `enabled` (boolean) - disable explode offsets for this script when `false`
188
- - `amountScale` (number) - multiply the UI explode amount
189
- - `stages` (number[]) - per-depth multipliers (depth 1 = first level, defaults to `1, 1/2, 1/3, ...`)
190
- - `mode` (`'radial' | 'x' | 'y' | 'z' | [x, y, z]`) - default explode direction
191
- - `axisLock` (`'x' | 'y' | 'z'`) - optional global axis lock
192
- - `byName` (`Record<string, { stage?, direction?, axisLock? }>`)- per-object overrides keyed by returned object `name`
193
- - `byPath` (`Record<string, { stage?, direction?, axisLock? }>`)- per-tree-path overrides using slash-separated object tree paths such as `"Drive/Shaft"`
194
-
195
- **Returns:** `void`
196
-
197
- ```javascript
198
- explodeView({
199
- amountScale: 1.2,
200
- stages: [0.35, 0.8],
201
- mode: 'radial',
202
- byPath: {
203
- "Drive/Shaft": { direction: [1, 0, 0], stage: 1.6 },
204
- },
205
- });
206
- ```
207
-
208
- ## `jointsView(options?)`
209
-
210
- Register viewport-only mechanism controls that animate returned objects without rerunning the script.
211
-
212
- Use this when you want interactive articulation in the viewer but the geometry itself stays fixed.
213
-
214
- Animation values are interpolated linearly between keyframes. Forge does **not**
215
- auto-wrap revolute values across `-180/180` or `0/360` for you, because doing
216
- that globally would break intentional multi-turn tracks.
217
-
218
- **Key options:**
219
- - `enabled`
220
- - `joints`: `{ name, child, parent?, type?, axis?, pivot?, min?, max?, default?, unit? }[]` — `min`/`max` control the slider range in the UI; they do **not** clamp animation keyframe values
221
- - `couplings`: `{ joint, terms, offset? }[]`
222
- - `animations`: `{ name, duration?, loop?, continuous?, keyframes }[]`
223
- - `defaultAnimation`
224
-
225
- **Keyframe `at` is optional (tick-based mode):** If you omit `at` from all
226
- keyframes, they are spaced across the timeline as sequential ticks. By default
227
- all ticks are equal, but you can use `ticks` to weight individual segments:
228
-
229
- ```javascript
230
- keyframes: [
231
- { ticks: 3, values: { "Shoulder": 20 } }, // slow move (3× weight)
232
- { ticks: 1, values: { "Shoulder": -10 } }, // fast snap (1× weight)
233
- { values: { "Shoulder": 20 } }, // last keyframe's ticks is ignored
234
- ]
235
- // Positions: 0, 0.75, 1.0 (weights 3,1 → total 4 → at 0/4, 3/4, 4/4)
236
- ```
237
-
238
- You can still use explicit `at` values when you need precise non-uniform
239
- spacing, but mixing explicit and omitted `at` within the same animation is not
240
- allowed. `ticks` is only valid in tick-based mode.
241
-
242
- ```javascript
243
- jointsView({
244
- joints: [
245
- {
246
- name: "Shoulder",
247
- child: "Upper Arm",
248
- parent: "Base",
249
- type: "revolute",
250
- axis: [0, -1, 0],
251
- pivot: [0, 0, 46],
252
- min: -30,
253
- max: 110,
254
- default: 15,
255
- },
256
- ],
257
- animations: [
258
- {
259
- name: "Walk Cycle",
260
- duration: 1.6,
261
- loop: true,
262
- keyframes: [
263
- { values: { "Shoulder": 20 } },
264
- { values: { "Shoulder": -10 } },
265
- { values: { "Shoulder": 20 } },
266
- ],
267
- },
268
- ],
269
- });
270
- ```
271
-
272
- ### Using `jointsView` with assemblies
273
-
274
- When combining `jointsView` animations with an `assembly().solve()` pipeline, the assembly must be solved at **rest pose** (all animated joints = 0). The viewport applies `jointsView` transforms on top of the scene objects' existing positions — if the assembly is already solved at non-zero joint angles, the animation will double-rotate everything.
275
-
276
- ```javascript
277
- // BAD — assembly bakes in slider angles, then jointsView rotates again
278
- const solved = mech.solve({ shoulder: 45, elbow: 30 });
279
- jointsView({
280
- joints: [{ name: "shoulder", child: "Upper Arm", ... }],
281
- animations: [{ ... keyframes with shoulder values ... }],
282
- });
283
- return solved; // double-rotated mess
284
-
285
- // GOOD — assembly at rest, jointsView controls all posing
286
- const solved = mech.solve({ shoulder: 0, elbow: 0 });
287
- jointsView({
288
- joints: [
289
- { name: "shoulder", child: "Upper Arm", default: 45, ... },
290
- { name: "elbow", child: "Forearm", parent: "Upper Arm", default: 30, ... },
291
- ],
292
- animations: [{ ... }],
293
- });
294
- return solved; // jointsView handles static pose via defaults AND animation
295
- ```
296
-
297
- **Pivot coordinates** are the world-space position of each joint origin at rest pose. For an assembly with `addRevolute("shoulder", "Base", "Link", { frame: Transform.identity().translate(0, 0, 20) })` where "Base" is at the world origin, the pivot is `[0, 0, 20]`.
298
-
299
- For kinematic chains, child joint pivots are specified in the parent joint's rest-pose space — the viewport resolves them through the parent chain automatically.
300
-
301
- **Fixed attachments** (e.g. an end effector bolted to the last link) need a zero-angle revolute joint in the `jointsView` chain so they follow the parent during animation:
302
-
303
- ```javascript
304
- { name: "EE_Follow", child: "End Effector", parent: "Last Link",
305
- type: "revolute", axis: [0, 0, 1], pivot: [linkLength, 0, 0],
306
- min: 0, max: 0, default: 0 }
307
- ```
308
-
309
- **Slider-driven posing** still works: use `param()` for interactive angles, compute dependent joint values (FK/IK), and pass them as `default` values on the `jointsView` joints. When an animation plays it overrides the defaults; when stopped the slider defaults take over.
310
-
311
- `continuous: true` is for looping tracks that should keep accumulating across
312
- cycles instead of snapping back to the first keyframe each time. Use it for
313
- monotonic multi-turn drives such as `0 -> 360 -> 720`.
314
-
315
- ### Animation continuity for revolute joints
316
-
317
- If an animation channel comes from `atan2(...)`, `normalizeAngleDeg(...)`, or
318
- any other wrapped angle source, keep the sampled keyframes continuous before
319
- passing them to `jointsView()`.
320
-
321
- Bad branch-cut sample stream:
322
-
323
- ```javascript
324
- keyframes: [
325
- { at: 0.48, values: { "Power Rod": -171 } },
326
- { at: 0.50, values: { "Power Rod": -180 } },
327
- { at: 0.52, values: { "Power Rod": 171 } },
328
- ]
329
- ```
330
-
331
- That `-180 -> 171` jump is interpreted literally and the viewer will spin the
332
- part the long way around.
333
-
334
- Good continuous sample stream:
335
-
336
- ```javascript
337
- keyframes: [
338
- { at: 0.48, values: { "Power Rod": -171 } },
339
- { at: 0.50, values: { "Power Rod": -180 } },
340
- { at: 0.52, values: { "Power Rod": -189 } },
341
- ]
342
- ```
343
-
344
- Guidelines:
345
- - Keep high-speed multi-turn joints authored as continuous angles (`0`, `360`,
346
- `720`, etc.).
347
- - Only unwrap channels that represent cyclic angles. Do not apply angle
348
- unwrapping blindly to prismatic or other scalar values.
349
- - If you build sampled helper utilities, let them unwrap a named set of joints
350
- instead of guessing from every numeric channel.
351
-
352
- ## `viewConfig(options?)`
353
-
354
- Configure viewport helper visuals for the current script.
355
-
356
- Current support:
357
- - `jointOverlay.enabled`
358
- - joint overlay colors such as `axisColor`, `axisCoreColor`, `arcColor`, `zeroColor`
359
- - joint overlay sizing and tessellation controls such as `axisLengthScale`, `arcVisualLimitDeg`, `arcStepDeg`
360
-
361
- **Returns:** `void`
362
-
363
- ```javascript
364
- viewConfig({
365
- jointOverlay: {
366
- axisColor: "#13dfff",
367
- arcColor: "#ff7a1a",
368
- axisLineRadiusScale: 0.03,
369
- arcLineRadiusScale: 0.022,
370
- },
371
- });
372
- ```
373
-
374
- ## `lib.explode(items, options?)`
375
-
376
- Apply deterministic exploded-view offsets to an assembly tree while preserving names, colors, and nesting.
377
-
378
- `radial` separation is branch-aware and parent-relative: each child follows the
379
- direction of its parent branch, then fans out locally inside that branch. This keeps
380
- subassemblies visually grouped while still letting their internals break apart.
381
-
382
- For non-radial fixed-axis or fixed-vector modes, nested descendants keep the branch
383
- offset but spread perpendicular to it by default.
384
-
385
- Default behavior is tree-like rather than flat: containers separate recursively,
386
- while unconfigured leaves inside a container use a smaller local fan so sibling parts
387
- stay visually associated with their parent group.
388
-
389
- Works with:
390
- - arrays of shapes/sketches/named items
391
- - nested `{ name, group: [...] }` structures
392
- - `ShapeGroup` outputs
393
-
394
- **Parameters:**
395
- - `items` (`ExplodeItem[] | ShapeGroup`)
396
- - `options`:
397
- - `amount` (number)
398
- - `stages` (number[])
399
- - `mode` (`'radial' | 'x' | 'y' | 'z' | [x, y, z]`)
400
- - `axisLock` (`'x' | 'y' | 'z'`)
401
- - `byName`
402
- - `byPath`
403
-
404
- Named items may also include:
405
- - `explode: { stage?, direction?, axisLock? }`
406
-
407
- **Returns:** same structure type as input, with translated geometry
408
-
409
- ```javascript
410
- const explodeAmt = param("Explode", 0, { min: 0, max: 40, unit: "mm" });
411
-
412
- return lib.explode(assembly, {
413
- amount: explodeAmt,
414
- stages: [0.4, 0.8],
415
- mode: 'radial',
416
- byName: {
417
- "Shaft": { direction: [1, 0, 0], stage: 1.4 },
418
- },
419
- });
420
- ```
@@ -1,185 +0,0 @@
1
- ---
2
- skill-group: sheet-metal
3
- skill-order: 1
4
- ---
5
-
6
- # Sheet Metal
7
-
8
- `sheetMetal()` is ForgeCAD's first dedicated compiler-owned sheet-metal family.
9
-
10
- It keeps one semantic model, then derives both:
11
-
12
- - a folded solid
13
- - a flat pattern
14
-
15
- This is a strict v1 subset. Forge does not try to infer sheet metal from arbitrary solids.
16
-
17
- ## Quick Start
18
-
19
- ```javascript
20
- const cover = sheetMetal({
21
- panel: { width: 180, height: 110 },
22
- thickness: 1.5,
23
- bendRadius: 2,
24
- bendAllowance: { kFactor: 0.42 },
25
- cornerRelief: { size: 4 },
26
- })
27
- .flange('top', { length: 18 })
28
- .flange('right', { length: 18 })
29
- .flange('bottom', { length: 18 })
30
- .flange('left', { length: 18 })
31
- .cutout('panel', rect(72, 36, true), { selfAnchor: 'center' })
32
- .cutout('flange-right', roundedRect(26, 10, 5, true), { selfAnchor: 'center' });
33
-
34
- const folded = cover.folded();
35
- const flat = cover.flatPattern();
36
- ```
37
-
38
- The maintained proof artifact is [`examples/api/folded-service-panel-cover.forge.js`](../../../../examples/api/folded-service-panel-cover.forge.js).
39
-
40
- ## Practical First Pass
41
-
42
- If the goal is "open docs and make a cover/bracket quickly," the most reliable current workflow is:
43
-
44
- 1. Build the base panel plus flanges first.
45
- 2. Validate `folded()` and `flatPattern()` before adding any cutouts.
46
- 3. Add panel cutouts before flange cutouts.
47
- 4. Add flange cutouts one region at a time instead of decorating every flange at once.
48
- 5. Re-run validation after each new region so cutout complexity stays easy to localize.
49
-
50
- This keeps failures narrow and makes it obvious whether the issue is:
51
-
52
- - the sheet-metal setup itself
53
- - one specific region
54
- - one specific cutout pattern
55
-
56
- ## Current Practical Cutout Lane
57
-
58
- The defended API surface is wider than the current "fast to author" lane.
59
-
60
- For quick, low-drama iteration, prefer:
61
-
62
- - `circle2d(...)`
63
- - `rect(...)`
64
- - `roundedRect(...)`
65
-
66
- These simple compile-covered sketches are the current safest first choice for panel and flange cutouts.
67
-
68
- Decorative language still works best when expressed as several individually placed simple cutouts rather than one heavily composed art sketch. In practice, fewer larger apertures are more reliable than many tiny details when you are still exploring the part.
69
-
70
- If runtime spikes or validation stops feeling immediate, simplify first by:
71
-
72
- - reducing cutout count
73
- - replacing composed motifs with simple repeated cutouts
74
- - validating one region before mirroring the same detail to other flanges
75
-
76
- ## Placement Tips
77
-
78
- - `selfAnchor: 'center'` is the easiest default for early iterations because it keeps panel and flange placement intent readable.
79
- - Flange-local placement is easy to misread, especially on side flanges. Place one obvious asymmetric test cutout on one flange first, validate it, then mirror or repeat once the orientation is confirmed.
80
- - Keep cutouts off bend regions for v1. The defended cutout lane is planar panel and flange regions only.
81
-
82
- ## API Surface
83
-
84
- ### `sheetMetal(options)`
85
-
86
- Creates a `SheetMetalPart`.
87
-
88
- Required options:
89
-
90
- - `panel: { width, height }`
91
- - `thickness`
92
- - `bendRadius`
93
- - `bendAllowance: { kFactor }`
94
-
95
- Optional:
96
-
97
- - `cornerRelief: { kind?: 'rect', size }`
98
-
99
- ### `part.flange(edge, options)`
100
-
101
- Adds one edge flange.
102
-
103
- - `edge`: `'top' | 'right' | 'bottom' | 'left'`
104
- - `options.length`
105
- - `options.angleDeg` defaults to `90`
106
-
107
- Current v1 support is only `90°` flanges.
108
-
109
- ### `part.cutout(region, sketch, options?)`
110
-
111
- Adds a planar cutout on a supported sheet-metal region.
112
-
113
- - `region`: `'panel' | 'flange-top' | 'flange-right' | 'flange-bottom' | 'flange-left'`
114
- - `sketch` must be an unplaced compile-covered 2D sketch
115
- - `options.u` / `options.v` place the sketch in region-local coordinates
116
- - `options.selfAnchor` works like other planar placement APIs
117
-
118
- For exploratory authoring, prefer a loop like:
119
-
120
- ```javascript
121
- let part = sheetMetal({
122
- panel: { width: 180, height: 110 },
123
- thickness: 1.5,
124
- bendRadius: 2,
125
- bendAllowance: { kFactor: 0.42 },
126
- cornerRelief: { size: 4 },
127
- })
128
- .flange('top', { length: 18 })
129
- .flange('right', { length: 18 });
130
-
131
- part = part.cutout('panel', roundedRect(40, 10, 5, true), { selfAnchor: 'center' });
132
- part = part.cutout('flange-right', circle2d(3), { u: 0, v: 0, selfAnchor: 'center' });
133
- ```
134
-
135
- That authoring style keeps each downstream cutout step explicit and easy to debug.
136
-
137
- ### `part.regionNames()`
138
-
139
- Returns the semantic region names currently available from the model.
140
-
141
- ### `part.folded()` / `part.flatPattern()`
142
-
143
- Materialize the folded solid or flat pattern from the same semantic model.
144
-
145
- Both outputs stay compiler-owned and exact-exportable inside the defended subset.
146
-
147
- ## Defended Region Names
148
-
149
- Forge exposes the following semantic family where the corresponding flange exists:
150
-
151
- - `panel`
152
- - `flange-top`, `flange-right`, `flange-bottom`, `flange-left`
153
- - `bend-top`, `bend-right`, `bend-bottom`, `bend-left`
154
-
155
- Important behavior:
156
-
157
- - planar panel/flange faces can resolve as descendant `region`s after downstream cutouts
158
- - folded bend regions resolve explicitly as descendant `set`s because one bend can honestly span multiple surfaces
159
- - flat-pattern bend regions stay explicit too, but as planar band descendants instead of guessed folded topology
160
-
161
- ## Supported V1 Subset
162
-
163
- - one base panel
164
- - up to four edge flanges
165
- - constant thickness
166
- - explicit bend radius
167
- - explicit K-factor bend allowance input
168
- - rectangular corner reliefs
169
- - planar cutouts on the panel and existing flange regions
170
- - folded preview and exact folded/flat lowering from the same semantic model
171
-
172
- ## Explicit Non-Goals
173
-
174
- Not supported in v1:
175
-
176
- - arbitrary solid-to-sheet-metal conversion
177
- - hems
178
- - jogs or offset bends
179
- - lofted bends
180
- - miter corner logic beyond the defended rectangular-relief subset
181
- - nonuniform thickness
182
- - bend-region cutouts
183
- - non-`90°` flanges
184
-
185
- If Forge cannot defend a requested operation inside that subset, it should fail with a targeted error instead of guessing.
@@ -1,37 +0,0 @@
1
- ---
2
- skill-group: sketch
3
- skill-order: 9
4
- ---
5
-
6
- # Sketch Anchor Positioning
7
-
8
- Position sketches relative to each other using named anchor points.
9
-
10
- ## Methods
11
-
12
- ### `.attachTo(target, targetAnchor, selfAnchor?, offset?)`
13
- Position a sketch relative to another using named anchor points.
14
-
15
- **Parameters:**
16
- - `target` (Sketch) — The sketch to attach to
17
- - `targetAnchor` (Anchor) — Point on target: 'center', 'top-left', 'top-right', 'bottom-left', 'bottom-right', 'top', 'bottom', 'left', 'right'
18
- - `selfAnchor` (Anchor, optional) — Point on this sketch to align. Default: 'center'
19
- - `offset` ([number, number], optional) — Additional offset after alignment
20
-
21
- **Returns:** `Sketch`
22
-
23
- ```javascript
24
- const plate = rect(50, 4);
25
- const arm = rect(4, 70).attachTo(plate, 'bottom-left', 'top-left');
26
- return union2d(plate, arm);
27
-
28
- // With offset: attach then shift 5mm right
29
- const shifted = rect(4, 70).attachTo(plate, 'bottom-left', 'top-left', [5, 0]);
30
- ```
31
-
32
- ## Anchor Points
33
-
34
- Available anchor positions:
35
- - `'center'` — geometric center
36
- - `'top-left'`, `'top-right'`, `'bottom-left'`, `'bottom-right'` — corners
37
- - `'top'`, `'bottom'`, `'left'`, `'right'` — edge midpoints