forgecad 0.9.14 → 0.9.16

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 (239) hide show
  1. package/LICENSE +6 -4
  2. package/README.md +8 -4
  3. package/dist/assets/{AdminPage-eWGs2K6H.js → AdminPage-CXvls4-J.js} +2 -2
  4. package/dist/assets/{BenchmarkPage-CTrLKfpo.js → BenchmarkPage-B27zk8xL.js} +4 -15
  5. package/dist/assets/{BlogPage-5nPesyds.js → BlogPage-CMAVvgQL.js} +2 -2
  6. package/dist/assets/{DocsPage-C4Y3nbYc.js → DocsPage-knf4I4h7.js} +9 -3
  7. package/dist/assets/EditorApp-BHMQlJ-D.js +14686 -0
  8. package/dist/assets/{EditorApp-BAnckbsk.css → EditorApp-BpjZgzk0.css} +846 -0
  9. package/dist/assets/{EmbedViewer-C8fB4n5U.js → EmbedViewer-D7ZGlFjx.js} +3 -3
  10. package/dist/assets/{LandingPageProofDriven-jSz0LaMM.js → LandingPageProofDriven-CnevhTE8.js} +36 -38
  11. package/dist/assets/LegalPage-BPTUmqeg.js +39 -0
  12. package/dist/assets/LegalPage-BRlScr9A.css +91 -0
  13. package/dist/assets/{PricingPage-B83B90zh.js → PricingPage-B0D4goG_.js} +19 -19
  14. package/dist/assets/{PricingPage-BMedqFef.css → PricingPage-BPF6HKyO.css} +25 -0
  15. package/dist/assets/{SettingsPage-DY889pcu.js → SettingsPage-CFF-UgjI.js} +2 -2
  16. package/dist/assets/app-CE3sYcV7.css +3890 -0
  17. package/dist/assets/{app-bEww1ic4.js → app-T0pDcSX4.js} +3382 -1069
  18. package/dist/assets/cli/{render-Cho2uKG_.js → render-C5pcIISc.js} +477 -29
  19. package/dist/assets/{constructionHistoryWorker-HYwzJY4m.js → constructionHistoryWorker-Ba2Hm58b.js} +928 -243
  20. package/dist/assets/{evalWorker-CjQwJSE-.js → evalWorker-vkx310U2.js} +8883 -6040
  21. package/dist/assets/{forgecad_geometry-CH2nvuLA.js → forgecad_geometry-Dgceylq9.js} +43 -1
  22. package/dist/assets/forgecad_geometry_bg-dD4RNQF1.wasm +0 -0
  23. package/dist/assets/{inspectWorker-DeRnMVv1.js → inspectWorker-BuTJDVX6.js} +1179 -273
  24. package/dist/assets/{javascript-70-4uGcz.js → javascript-1kQXfVaz.js} +1 -1
  25. package/dist/assets/{targets-D6PWsv6X.js → jointPose-B_Cgedn9.js} +71 -3
  26. package/dist/assets/landing-proof-driven-DiGqdtWa.js +18 -0
  27. package/dist/assets/{landing-proof-driven-oFYW6mjz.css → landing-proof-driven-ORyigZ6p.css} +13 -7
  28. package/dist/assets/legalContent-ZfFGMmi4.js +251 -0
  29. package/dist/assets/{manifold-rmfAcdwF.js → manifold-BWgsjmAM.js} +1 -1
  30. package/dist/assets/{manifold-uRzgk5O8.js → manifold-D6IFSkhH.js} +2 -2
  31. package/dist/assets/{manifold-CG9Fokx-.js → manifold-rZexZI0G.js} +1 -1
  32. package/dist/assets/{reportWorker-4cW_ZpoS.js → reportWorker-0AGij1Ru.js} +8659 -12771
  33. package/dist/assets/{scalar-sampling-budget-CfDiFvh7.js → scalar-sampling-budget-J5cuzxT1.js} +8050 -6203
  34. package/dist/assets/{scanProxyWorker-Bs2TDgLw.js → scanProxyWorker-Vl4Wxa1y.js} +50 -6
  35. package/dist/assets/{solver-DuJAO8S6.js → solver-BZ9LPTHs.js} +1 -1
  36. package/dist/assets/solver_bg-DAHZJ_rw.wasm +0 -0
  37. package/dist/assets/{vendor-react-Da3A2QmU.js → vendor-react-6j1Kke-Y.js} +6 -5
  38. package/dist/cli/render.html +1 -1
  39. package/dist/docs/index.html +2 -2
  40. package/dist/docs-raw/AI/ai-native-cad.md +50 -0
  41. package/dist/docs-raw/AI/usage.md +5 -12
  42. package/dist/docs-raw/CLI.md +34 -10
  43. package/dist/docs-raw/component-model.md +27 -11
  44. package/dist/docs-raw/generated/assembly.md +374 -187
  45. package/dist/docs-raw/generated/concepts.md +245 -237
  46. package/dist/docs-raw/generated/core.md +283 -6
  47. package/dist/docs-raw/generated/curves.md +274 -361
  48. package/dist/docs-raw/generated/lib.md +9 -19
  49. package/dist/docs-raw/generated/output.md +29 -4
  50. package/dist/docs-raw/generated/runtime-names.md +49 -0
  51. package/dist/docs-raw/generated/sdf.md +31 -0
  52. package/dist/docs-raw/generated/sheet-metal.md +9 -0
  53. package/dist/docs-raw/generated/sketch.md +44 -1
  54. package/dist/docs-raw/generated/viewport.md +11 -3
  55. package/dist/docs-raw/guides/coordinate-system.md +20 -16
  56. package/dist/docs-raw/guides/geometry-conventions.md +2 -2
  57. package/dist/docs-raw/guides/inspection-bundles.md +2 -1
  58. package/dist/docs-raw/guides/joint-design.md +24 -0
  59. package/dist/docs-raw/guides/positioning.md +13 -3
  60. package/dist/docs-raw/legal/privacy.md +63 -0
  61. package/dist/docs-raw/legal/software-license.md +55 -0
  62. package/dist/docs-raw/legal/terms.md +87 -0
  63. package/dist/docs-raw/skills/forgecad-3d-reconstruction.md +1 -1
  64. package/dist/docs-raw/skills/forgecad-blockout-model.md +1 -1
  65. package/dist/docs-raw/skills/forgecad-component-model.md +11 -2
  66. package/dist/docs-raw/skills/forgecad-high-level-spec.md +1 -1
  67. package/dist/docs-raw/skills/forgecad-image-replicator.md +8 -8
  68. package/dist/docs-raw/skills/forgecad-lld.md +1 -1
  69. package/dist/docs-raw/skills/forgecad-make-a-model.md +40 -39
  70. package/dist/docs-raw/skills/forgecad-model-grader.md +2 -2
  71. package/dist/docs-raw/skills/forgecad-prepare-prompt.md +2 -2
  72. package/dist/docs-raw/skills/forgecad-project.md +3 -1
  73. package/dist/docs-raw/skills/forgecad-reconstruction-benchmark.md +1 -1
  74. package/dist/docs-raw/skills/forgecad-render-inspect.md +4 -2
  75. package/dist/docs-raw/skills/forgecad-visual-spec.md +1 -1
  76. package/dist/docs-raw/skills/forgecad.md +4 -3
  77. package/dist/docs-raw/welcome.md +2 -0
  78. package/dist/index.html +40 -12
  79. package/dist/llms.txt +8 -0
  80. package/dist/site.webmanifest +1 -1
  81. package/dist/sitemap.xml +49 -13
  82. package/dist-cli/{check-compiler-U5SOPN7X.js → check-compiler-SYQ2PWOB.js} +1 -2
  83. package/dist-cli/{check-query-propagation-XOKNSSYU.js → check-query-propagation-HIAGV62W.js} +1 -2
  84. package/dist-cli/{chunk-EXWGNL6K.js → chunk-SPZE3DUY.js} +20659 -17930
  85. package/dist-cli/forgecad.js +3568 -1250
  86. package/dist-cli/{forgecad_geometry-GYVNKPIE.js → forgecad_geometry-QOQIIP53.js} +42 -1
  87. package/dist-cli/forgecad_geometry_bg.wasm +0 -0
  88. package/dist-cli/{solver-46FFSK2U.js → solver-OK4HECRH.js} +0 -1
  89. package/dist-cli/solver_bg.wasm +0 -0
  90. package/dist-skill/CONTEXT.md +1192 -725
  91. package/dist-skill/SKILL.md +3 -2
  92. package/dist-skill/docs/API/core/concepts.md +64 -1
  93. package/dist-skill/docs/CLI.md +34 -10
  94. package/dist-skill/docs/generated/assembly.md +339 -213
  95. package/dist-skill/docs/generated/core.md +283 -6
  96. package/dist-skill/docs/generated/curves.md +272 -362
  97. package/dist-skill/docs/generated/lib.md +9 -19
  98. package/dist-skill/docs/generated/output.md +29 -4
  99. package/dist-skill/docs/generated/runtime-names.md +40 -0
  100. package/dist-skill/docs/generated/sdf.md +31 -0
  101. package/dist-skill/docs/generated/sheet-metal.md +9 -0
  102. package/dist-skill/docs/generated/sketch.md +44 -2
  103. package/dist-skill/docs/generated/viewport.md +2 -87
  104. package/dist-skill/docs/guides/coordinate-system.md +20 -16
  105. package/dist-skill/docs/guides/geometry-conventions.md +2 -2
  106. package/dist-skill/docs/guides/inspection-bundles.md +2 -1
  107. package/dist-skill/docs/guides/joint-design.md +24 -0
  108. package/dist-skill/docs/guides/positioning.md +13 -3
  109. package/dist-skill/library/forgecad-component-model/SKILL.md +10 -1
  110. package/dist-skill/library/forgecad-image-replicator/SKILL.md +6 -6
  111. package/dist-skill/library/forgecad-image-replicator/scripts/compare_images.py +166 -0
  112. package/dist-skill/library/forgecad-make-a-model/SKILL.md +39 -38
  113. package/dist-skill/library/forgecad-model-grader/SKILL.md +1 -1
  114. package/dist-skill/library/forgecad-prepare-prompt/SKILL.md +1 -1
  115. package/dist-skill/library/forgecad-project/SKILL.md +2 -0
  116. package/dist-skill/library/forgecad-render-inspect/SKILL.md +3 -1
  117. package/examples/api/assembly-kinematics-foundation.forge.js +65 -0
  118. package/examples/api/assembly-kinematics-four-bar.forge.js +115 -0
  119. package/examples/api/assembly-kinematics-limb.forge.js +116 -0
  120. package/examples/api/connector-frame-rig-chain.forge.js +102 -0
  121. package/examples/api/exact-sheet-shell-assembly.forge.js +0 -2
  122. package/examples/api/exact-surface-studio.forge.js +6 -8
  123. package/examples/api/helix-basics.forge.js +8 -8
  124. package/examples/api/lean-foundations/README.md +12 -0
  125. package/examples/api/lean-foundations/curve-blend-exact.forge.js +22 -0
  126. package/examples/api/lean-foundations/curve-fit-interpolation.forge.js +18 -0
  127. package/examples/api/lean-foundations/curve-helix-canonicalization.forge.js +27 -0
  128. package/examples/api/lean-foundations/curve-route-canonicalization.forge.js +16 -0
  129. package/examples/api/lean-foundations/curve-trim-reverse.forge.js +24 -0
  130. package/examples/api/lean-foundations/exact-curve-arc.forge.js +36 -0
  131. package/examples/api/mixed-edge-finishes-proof.forge.js +8 -11
  132. package/examples/api/route3d-elbow.forge.js +71 -0
  133. package/examples/api/transition-curves.forge.js +44 -15
  134. package/examples/api/variable-sweep-test.forge.js +3 -1
  135. package/examples/api/y-blend-corner-showcase.forge.js +0 -2
  136. package/examples/generative/coral-vase.forge.js +1 -1
  137. package/examples/nurbs-tube.forge.js +1 -1
  138. package/package.json +17 -13
  139. package/dist/assets/EditorApp-lXv53A1m.js +0 -13610
  140. package/dist/assets/app-CsHnaBWt.css +0 -1789
  141. package/dist/assets/forgecad_geometry_bg-C5_E9Oa9.wasm +0 -0
  142. package/dist/assets/solver_bg-CWvv4lnN.wasm +0 -0
  143. package/dist/docs-raw/API/README.md +0 -16
  144. package/dist/docs-raw/API/core/concepts.md +0 -118
  145. package/dist/docs-raw/INDEX.md +0 -138
  146. package/dist/docs-raw/RELEASING.md +0 -87
  147. package/dist/docs-raw/agent-native-api.md +0 -27
  148. package/dist/docs-raw/beta-deployment.md +0 -304
  149. package/dist/docs-raw/beta-operations.md +0 -325
  150. package/dist/docs-raw/blueprint-first.md +0 -145
  151. package/dist/docs-raw/cli-monetization.md +0 -112
  152. package/dist/docs-raw/coding-best-practices.md +0 -120
  153. package/dist/docs-raw/coding.md +0 -340
  154. package/dist/docs-raw/deployment.md +0 -374
  155. package/dist/docs-raw/guides/skill-maintenance.md +0 -161
  156. package/dist/docs-raw/guides/surface-members.md +0 -82
  157. package/dist/docs-raw/harbor-cli.md +0 -854
  158. package/dist/docs-raw/internals/backend-vocabulary.md +0 -35
  159. package/dist/docs-raw/internals/compiler.md +0 -307
  160. package/dist/docs-raw/internals/constraint-solver-quality.md +0 -161
  161. package/dist/docs-raw/internals/constraint-solver.md +0 -176
  162. package/dist/docs-raw/internals/shape-from-slices.md +0 -152
  163. package/dist/docs-raw/internals/sketch-2d-pipeline.md +0 -108
  164. package/dist/docs-raw/platform/admin.md +0 -45
  165. package/dist/docs-raw/platform/architecture.md +0 -82
  166. package/dist/docs-raw/platform/auth.md +0 -139
  167. package/dist/docs-raw/platform/email.md +0 -67
  168. package/dist/docs-raw/platform/google-oauth-setup.md +0 -88
  169. package/dist/docs-raw/platform/observability.md +0 -197
  170. package/dist/docs-raw/platform/projects.md +0 -111
  171. package/dist/docs-raw/platform/sharing.md +0 -90
  172. package/dist/docs-raw/product/README.md +0 -39
  173. package/dist/docs-raw/product/api-as-product-language.md +0 -13
  174. package/dist/docs-raw/product/business-model.md +0 -15
  175. package/dist/docs-raw/product/competitive-positioning.md +0 -17
  176. package/dist/docs-raw/product/creative-manufacturing.md +0 -15
  177. package/dist/docs-raw/product/founder-story.md +0 -11
  178. package/dist/docs-raw/product/manufacturing-workflows.md +0 -15
  179. package/dist/docs-raw/product/onboarding-first-experience.md +0 -256
  180. package/dist/docs-raw/product/product-loop.md +0 -17
  181. package/dist/docs-raw/product/strategic-decisions.md +0 -22
  182. package/dist/docs-raw/product/user-outreach-email-templates.md +0 -161
  183. package/dist/docs-raw/product/user-segments.md +0 -15
  184. package/dist/docs-raw/product/vision.md +0 -26
  185. package/dist/docs-raw/rl-environments.md +0 -350
  186. package/dist/docs-raw/runbook.md +0 -611
  187. package/dist-cli/check-compiler-U5SOPN7X.js.map +0 -1
  188. package/dist-cli/check-query-propagation-XOKNSSYU.js.map +0 -1
  189. package/dist-cli/chunk-EXWGNL6K.js.map +0 -1
  190. package/dist-cli/forgecad.js.map +0 -1
  191. package/dist-cli/forgecad_geometry-GYVNKPIE.js.map +0 -1
  192. package/dist-cli/solver-46FFSK2U.js.map +0 -1
  193. package/dist-skill/SKILL-dev.md +0 -145
  194. package/dist-skill/docs-dev/API/core/concepts.md +0 -118
  195. package/dist-skill/docs-dev/CLI.md +0 -677
  196. package/dist-skill/docs-dev/agent-native-api.md +0 -27
  197. package/dist-skill/docs-dev/blueprint-first.md +0 -145
  198. package/dist-skill/docs-dev/coding-best-practices.md +0 -120
  199. package/dist-skill/docs-dev/coding.md +0 -340
  200. package/dist-skill/docs-dev/component-model.md +0 -164
  201. package/dist-skill/docs-dev/generated/assembly.md +0 -794
  202. package/dist-skill/docs-dev/generated/core.md +0 -2117
  203. package/dist-skill/docs-dev/generated/curves.md +0 -2583
  204. package/dist-skill/docs-dev/generated/lib.md +0 -169
  205. package/dist-skill/docs-dev/generated/output.md +0 -247
  206. package/dist-skill/docs-dev/generated/sdf.md +0 -446
  207. package/dist-skill/docs-dev/generated/sheet-metal.md +0 -504
  208. package/dist-skill/docs-dev/generated/sketch.md +0 -1811
  209. package/dist-skill/docs-dev/generated/viewport.md +0 -585
  210. package/dist-skill/docs-dev/generated/wood.md +0 -108
  211. package/dist-skill/docs-dev/guides/coordinate-system.md +0 -46
  212. package/dist-skill/docs-dev/guides/geometry-conventions.md +0 -52
  213. package/dist-skill/docs-dev/guides/inspection-bundles.md +0 -485
  214. package/dist-skill/docs-dev/guides/joint-design.md +0 -78
  215. package/dist-skill/docs-dev/guides/modeling-recipes.md +0 -78
  216. package/dist-skill/docs-dev/guides/positioning.md +0 -161
  217. package/dist-skill/docs-dev/guides/skill-maintenance.md +0 -161
  218. package/dist-skill/docs-dev/internals/backend-vocabulary.md +0 -35
  219. package/dist-skill/docs-dev/internals/compiler.md +0 -307
  220. package/dist-skill/docs-dev/internals/constraint-solver-quality.md +0 -161
  221. package/dist-skill/docs-dev/internals/constraint-solver.md +0 -176
  222. package/dist-skill/docs-dev/internals/sketch-2d-pipeline.md +0 -108
  223. package/dist-skill/library/forgecad-image-replicator/scripts/compare_images.mjs +0 -289
  224. package/examples/api/bolted-service-cover.forge.js +0 -17
  225. package/examples/api/cable-gland-anchor.forge.js +0 -14
  226. package/examples/api/captured-cartridge-guide.forge.js +0 -14
  227. package/examples/api/captured-linear-slide.forge.js +0 -13
  228. package/examples/api/clevis-pin-joint.forge.js +0 -13
  229. package/examples/api/datum-enclosure.forge.js +0 -16
  230. package/examples/api/hose-barb-port.forge.js +0 -14
  231. package/examples/api/knuckled-hinge-assembly.forge.js +0 -15
  232. package/examples/api/living-hinge-cover.forge.js +0 -14
  233. package/examples/api/pcb-terminal-block.forge.js +0 -22
  234. package/examples/api/pinned-lever-pivot-stack.forge.js +0 -14
  235. package/examples/api/retained-shaft-knob-stack.forge.js +0 -15
  236. package/examples/api/routed-tube-clip.forge.js +0 -15
  237. package/examples/api/seated-bearing-stack.forge.js +0 -30
  238. package/examples/api/snap-latch-cover.forge.js +0 -14
  239. package/examples/api/thumb-screw-clamp.forge.js +0 -15
@@ -1,504 +0,0 @@
1
- ---
2
- skill-group: sheet-metal
3
- skill-order: 100
4
- ---
5
-
6
- # Sheet Metal
7
-
8
- Folded sheet metal parts with flanges, bends, and flat pattern unfolding.
9
-
10
- ## Contents
11
-
12
- - [Sheet Metal](#sheet-metal) — `sheetMetal`
13
- - [Laser Cutting](#laser-cutting) — `kerfCompensateOutline`, `kerfCompensateTabs`, `kerfCompensateSlots`, `kerfCompensatePart`, `lookupKerf`, `flatPanel`, `flatPart`, `fingerJoint`, `tabSlot`, `assemblyPreview`, `assemblyInstructions`, `formatInstructions`, `laserKit`
14
- - [SheetMetalPart](#sheetmetalpart)
15
- - [FlatPart](#flatpart)
16
- - [LaserKit](#laserkit)
17
- - [SHEET_METAL_EDGES](#sheet-metal-edges)
18
- - [COMMON_KERFS](#common-kerfs)
19
-
20
- ## Functions
21
-
22
- ### Sheet Metal
23
-
24
- #### `sheetMetal()` — Create a parametric sheet metal part with flanges, bend allowances, and flat-pattern unfolding.
25
-
26
- `sheetMetal()` keeps one semantic model and derives both a folded 3D solid and an accurate flat pattern from it. The K-factor bend allowance is applied during unfolding. This is a strict v1 subset — it does not infer sheet metal from arbitrary solids.
27
-
28
- **Recommended authoring order:**
29
-
30
- 1. Define the base panel + thickness + bend parameters.
31
- 2. Chain `.flange()` calls for each edge. Validate with `.folded()` and `.flatPattern()` before adding cutouts.
32
- 3. Add panel cutouts, then flange cutouts one region at a time.
33
- 4. Validate after each new cutout region.
34
-
35
- **v1 limitations:** one base panel, up to four 90° edge flanges, constant thickness, explicit K-factor, rectangular corner reliefs, planar cutouts only. No hems, jogs, lofted bends, non-90° flanges, or bend-region cutouts.
36
-
37
- ```ts
38
- const cover = sheetMetal({
39
- panel: { width: 180, height: 110 },
40
- thickness: 1.5,
41
- bendRadius: 2,
42
- bendAllowance: { kFactor: 0.42 },
43
- cornerRelief: { size: 4 },
44
- })
45
- .flange('top', { length: 18 })
46
- .flange('right', { length: 18 })
47
- .flange('bottom', { length: 18 })
48
- .flange('left', { length: 18 })
49
- .cutout('panel', rect(72, 36), { selfAnchor: 'center' })
50
- .cutout('flange-right', roundedRect(26, 10, 5), { selfAnchor: 'center' });
51
-
52
- const folded = cover.folded();
53
- const flat = cover.flatPattern();
54
- ```
55
-
56
- ```ts
57
- sheetMetal(options: SheetMetalOptions): SheetMetalPart
58
- ```
59
-
60
- **`SheetMetalOptions`**
61
-
62
- | Option | Type | Description |
63
- |--------|------|-------------|
64
- | `panel` | `{ width: number; height: number; }` | Base panel dimensions. This is the flat blank before flanges are applied. |
65
- | `thickness` | `number` | Sheet thickness in mm. Applied uniformly across the panel and all flanges. |
66
- | `bendRadius` | `number` | Inside bend radius in mm. Must be ≥ 0. Typically 0.5–2× the sheet thickness. |
67
- | `bendAllowance` | `{ kFactor: number; }` | Bend allowance model used when computing the flat-pattern developed length. Currently only K-factor is supported. The K-factor (0–1) describes how far the neutral axis sits from the inner bend surface. Typical values: - Soft materials / large radius: 0.50 - General sheet steel: 0.42–0.44 - Hard materials / tight radius: 0.30–0.38 |
68
- | `cornerRelief?` | `{ kind?: "rect"; size: number; }` | Corner relief cut at each bend intersection. Prevents material overlap when two flanges meet at a corner. Defaults to a rectangular relief sized to `bendRadius + thickness` if omitted. |
69
-
70
- ### Laser Cutting
71
-
72
- #### `kerfCompensateOutline()` — Apply kerf compensation to a complete part outline (outer boundary + holes).
73
-
74
- Offsets inward by half-kerf: the outer boundary shrinks and inner holes grow. This is correct because the laser beam removes material on both sides of the cut line.
75
-
76
- ```ts
77
- kerfCompensateOutline(sketch: Sketch, kerf: number): Sketch
78
- ```
79
-
80
- #### `kerfCompensateTabs()` — Apply kerf compensation to joint protrusions (tabs, fingers).
81
-
82
- These grow by half-kerf so they are slightly oversized and fit tightly in their mating slots after the laser removes material.
83
-
84
- ```ts
85
- kerfCompensateTabs(sketch: Sketch, kerf: number): Sketch
86
- ```
87
-
88
- #### `kerfCompensateSlots()` — Apply kerf compensation to joint cutouts (slots, holes that receive tabs).
89
-
90
- These grow by half-kerf so tabs can fit into them after the laser removes material from both sides of the slot walls.
91
-
92
- ```ts
93
- kerfCompensateSlots(sketch: Sketch, kerf: number): Sketch
94
- ```
95
-
96
- #### `kerfCompensatePart()` — Build a kerf-compensated part profile.
97
-
98
- 1. Start with the base profile.
99
- 2. Kerf-compensate each tab addition (grow by kerf/2), then union with base.
100
- 3. Kerf-compensate each slot subtraction (grow by kerf/2), then subtract from base.
101
- 4. Kerf-compensate the resulting outline (shrink by kerf/2).
102
-
103
- Order matters: joints modify geometry BEFORE outline compensation so the final inward offset applies uniformly to the assembled profile.
104
-
105
- ```ts
106
- kerfCompensatePart(baseProfile: Sketch, joints: PartJoints, kerf: number): Sketch
107
- ```
108
-
109
- **`PartJoints`**
110
- - `additions?: Sketch[]` — Geometry to ADD to the base profile (tabs, fingers protruding from edges).
111
- - `subtractions?: Sketch[]` — Geometry to SUBTRACT from the base profile (slots, holes for mating tabs).
112
-
113
- #### `lookupKerf()` — Look up kerf for a material + thickness + laser combo.
114
-
115
- If `laserType` is omitted, returns the first matching material + thickness entry. Returns `undefined` when no match is found.
116
-
117
- ```ts
118
- lookupKerf(material: string, thickness: number, laserType?: string): number | undefined
119
- ```
120
-
121
- #### `flatPanel()` — Create a rectangular flat panel with 4 named edges.
122
-
123
- Profile origin at bottom-left corner. Edges: bottom (y=0), right (x=width), top (y=height), left (x=0). Edge traversal follows CCW winding order.
124
-
125
- ```ts
126
- flatPanel(name: string, width: number, height: number, thickness: number, options?: FlatPartOptions): FlatPart
127
- ```
128
-
129
- `FlatPartOptions`: `{ material?: string, qty?: number, color?: string }`
130
-
131
- #### `flatPart()` — Create a flat part from an arbitrary profile with user-named edges.
132
-
133
- Edge normals are computed automatically (perpendicular to direction, rotated 90deg CW).
134
-
135
- ```ts
136
- flatPart(name: string, profile: Sketch, thickness: number, edges?: Record<string, { start: [ number, number ]; end: [ number, number ]; }>, options?: FlatPartOptions): FlatPart
137
- ```
138
-
139
- #### `fingerJoint()` — Connect two parts with finger joints along specified edges.
140
-
141
- Adds finger geometry to partA's edge, cuts matching slots from partB's edge. The joint profiles are positioned along each edge using rotation + translation.
142
-
143
- ```ts
144
- fingerJoint(partA: FlatPart, edgeNameA: string, partB: FlatPart, edgeNameB: string, options?: FingerJointOptions & { foldAngle?: number; }): void
145
- ```
146
-
147
- **`FingerJointOptions`**
148
-
149
- | Option | Type | Description |
150
- |--------|------|-------------|
151
- | `fingers?` | `number` | Explicit finger count (must be odd, >= 3). Default: auto from length/thickness. |
152
- | `fingerWidth?` | `number` | Explicit finger width. Default: auto. |
153
- | `clearance?` | `number` | Extra clearance per side (mm). Default: 0. |
154
- | `kerf?` | `number` | Laser kerf (mm). Default: 0. |
155
- | `endStyle?` | `"full" \| "half"` | Whether edge starts with full finger or half. Default: 'full'. |
156
-
157
- #### `tabSlot()` — Connect two parts with tab-and-slot joints along specified edges.
158
-
159
- Adds tab geometry to partA's edge, cuts matching slots from partB's edge.
160
-
161
- ```ts
162
- tabSlot(partA: FlatPart, edgeNameA: string, partB: FlatPart, edgeNameB: string, options?: TabSlotOptions & { foldAngle?: number; }): void
163
- ```
164
-
165
- **`TabSlotOptions`**
166
-
167
- | Option | Type | Description |
168
- |--------|------|-------------|
169
- | `tabCount?` | `number` | Number of tabs. Default: auto (length / (4 * thickness)). |
170
- | `tabWidth?` | `number` | Tab width. Default: 2 * thickness. |
171
- | `clearance?` | `number` | Extra clearance per side (mm). Default: 0. |
172
- | `kerf?` | `number` | Laser kerf (mm). Default: 0. |
173
- | `inset?` | `number` | Distance from panel edges to first/last tab center. Default: thickness. |
174
-
175
- #### `assemblyPreview()` — Generate a 3D assembly preview from flat parts and their joint records.
176
-
177
- The preview can fold joints partially or fully and optionally apply exploded spacing so part relationships are easier to inspect visually.
178
-
179
- ```ts
180
- assemblyPreview(parts: FlatPart[], joints: JointRecord[], options?: AssemblyPreviewOptions): AssemblyPreviewResult
181
- ```
182
-
183
- **`JointRecord`**
184
- - `foldAngle: number` — Fold angle in degrees. Default: 90.
185
- - Also: `type: "finger" | "tabSlot" | "snapFit", partA: string, partB: string, edgeA: string, edgeB: string`
186
-
187
- **`AssemblyPreviewOptions`**
188
- - `kerf?: number` — Kerf compensation passed to each part's solid(). Default: 0
189
- - `fold?: number` — Fold amount: 0 = flat layout, 1 = fully assembled. Default: 1
190
- - `explode?: number` — Explode distance: 0 = assembled, >0 = parts spread outward. Default: 0
191
-
192
- **`AssemblyPreviewResult`**
193
- - `shapes: ShapeGroup` — All part shapes grouped for display.
194
- - `partShapes: Map<string, Shape>` — Individual transformed shapes keyed by part name.
195
-
196
- #### `assemblyInstructions()` — Generate step-by-step assembly instructions from flat parts and joints.
197
-
198
- Algorithm:
199
-
200
- 1. Build adjacency graph from joints
201
- 2. Pick root part (most connections, or user-specified)
202
- 3. BFS from root, creating one step per part addition
203
- 4. Each step describes: which part to add, where it connects, how to orient it
204
-
205
- Heuristics for step ordering:
206
-
207
- - Start with the part that has the most connections (the base)
208
- - Add parts that connect to already-assembled parts first (BFS order)
209
- - Among candidates at the same BFS depth, prefer parts with more connections to already-assembled parts (structurally stable)
210
-
211
- ```ts
212
- assemblyInstructions(parts: FlatPart[], joints: JointRecord[], options?: AssemblyInstructionsOptions): AssemblyInstructionsResult
213
- ```
214
-
215
- **`AssemblyInstructionsOptions`**
216
- - `rootPart?: string` — Part to start from. Default: part with most joint connections.
217
-
218
- **`AssemblyInstructionsResult`**
219
- - `totalParts: number` — Total number of parts in the assembly.
220
- - `orphanParts: string[]` — Parts not connected to the joint graph (orphans).
221
- - Also: `steps: AssemblyStep[]`
222
-
223
- **`AssemblyStep`**
224
-
225
- | Option | Type | Description |
226
- |--------|------|-------------|
227
- | `stepNumber` | `number` | 1-based step number. |
228
- | `description` | `string` | Human-readable instruction. |
229
- | `partName` | `string` | The part being added in this step. |
230
- | `partNumber` | `number` | Part number (for cross-ref with cut sheets). |
231
- | `connectsTo` | `string` | Which existing part it connects to. |
232
- | `jointType` | `"finger" \| "tabSlot" \| "snapFit"` | Joint type used. |
233
- | `newPartEdge` | `string` | The edge on the new part. |
234
- | `existingPartEdge` | `string` | The edge on the existing part. |
235
- | `foldAngle` | `number` | Fold angle in degrees. |
236
- | `assembledParts` | `string[]` | Part names in the assembly so far (after this step). |
237
-
238
- #### `formatInstructions()` — Format assembly instructions as a human-readable text document.
239
-
240
- Includes a "Step 0" preamble identifying the base part, followed by numbered steps, and a note about any orphan parts.
241
-
242
- ```ts
243
- formatInstructions(result: AssemblyInstructionsResult): string
244
- ```
245
-
246
- #### `laserKit()` — Top-level factory for creating a LaserKit container.
247
-
248
- ```ts
249
- laserKit(options?: LaserKitOptions): LaserKit
250
- ```
251
-
252
- **`LaserKitOptions`**
253
-
254
- | Option | Type | Description |
255
- |--------|------|-------------|
256
- | `material?` | `string` | Default material label for parts that don't specify one. |
257
- | `sheetWidth?` | `number` | Stock sheet width in mm (default 600). |
258
- | `sheetHeight?` | `number` | Stock sheet height in mm (default 400). |
259
- | `kerf?` | `number` | Laser kerf in mm (default 0.2). |
260
-
261
- ---
262
-
263
- ## Classes
264
-
265
- ### `SheetMetalPart`
266
-
267
- An immutable sheet metal part that accumulates flanges and cutouts.
268
-
269
- Each mutating method returns a **new** `SheetMetalPart`; the original is unchanged. The part does not produce geometry until you call `.folded()` or `.flatPattern()`.
270
-
271
- #### `flange()` — Add a 90° flange along one edge of the base panel.
272
-
273
- Each of the four edges (`'top'`, `'right'`, `'bottom'`, `'left'`) may carry at most one flange. Calling `.flange()` twice for the same edge throws.
274
-
275
- Corner reliefs are automatically inserted at the intersections of adjacent flanges. Build flanges before cutouts — validate with `.folded()` and `.flatPattern()` after each addition.
276
-
277
- ```ts
278
- const part = sheetMetal({ panel: { width: 100, height: 60 }, thickness: 1.5, bendRadius: 2, bendAllowance: { kFactor: 0.42 } })
279
- .flange('top', { length: 15 })
280
- .flange('bottom', { length: 15 });
281
- ```
282
-
283
- ```ts
284
- flange(edge: SheetMetalEdge, options: SheetMetalFlangeOptions): SheetMetalPart
285
- ```
286
-
287
- #### `cutout()` — Subtract a 2D sketch cutout from a planar region of the sheet metal part.
288
-
289
- `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.
290
-
291
- `sketch` must be an **unplaced** compile-covered 2D profile (e.g. the result of [`circle2d()`](/docs/sketch#circle2d), [`rect()`](/docs/sketch#rect), [`roundedRect()`](/docs/sketch#roundedrect)). Passing an already-placed sketch (one that has had `.onFace(...)` called on it) will throw.
292
-
293
- **Authoring order:** Add all flanges before adding cutouts. Add panel cutouts before flange cutouts. Add one region at a time and validate with `.folded()` / `.flatPattern()` after each step.
294
-
295
- ```ts
296
- const part = sheetMetal({ panel: { width: 180, height: 110 }, thickness: 1.5, bendRadius: 2, bendAllowance: { kFactor: 0.42 } })
297
- .flange('top', { length: 18 })
298
- .cutout('panel', rect(72, 36), { selfAnchor: 'center' })
299
- .cutout('flange-top', roundedRect(26, 10, 5), { selfAnchor: 'center' });
300
- ```
301
-
302
- ```ts
303
- cutout(region: SheetMetalPlanarRegionName, sketch: Sketch, options?: SheetMetalCutoutOptions): SheetMetalPart
304
- ```
305
-
306
- #### `regionNames()` — Return all semantic region names currently available on this part.
307
-
308
- 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.
309
-
310
- Use this to discover valid targets for `.cutout()` or for querying faces by region after materializing with `.folded()`.
311
-
312
- Defended region names: `panel` | `flange-top` | `flange-right` | `flange-bottom` | `flange-left` | `bend-top` | `bend-right` | `bend-bottom` | `bend-left`
313
-
314
- ```ts
315
- regionNames(): SheetMetalRegionName[]
316
- ```
317
-
318
- #### `folded()` — Materialize the 3D folded solid.
319
-
320
- Applies all flanges (bent up at their configured angles) and all registered cutouts, then returns the resulting [`Shape`](/docs/core#shape). The shape is compiler-owned and exact-exportable (STEP, IGES, etc.).
321
-
322
- Prefer calling `.folded()` to validate each build step before proceeding to the final model.
323
-
324
- ```ts
325
- folded(): Shape
326
- ```
327
-
328
- #### `flatPattern()` — Materialize the flat-pattern (unfolded blank) for fabrication.
329
-
330
- Unfolds all flanges using the K-factor bend allowance and lays the result flat in the XY plane. Cutouts are projected into the flat geometry. The returned shape is exact-exportable and ready for laser / waterjet / CNC nesting workflows.
331
-
332
- The developed length of each bend zone is: `BA = (bendRadius + kFactor × thickness) × angleDeg × π / 180`
333
-
334
- ```ts
335
- flatPattern(): Shape
336
- ```
337
-
338
- ### `FlatPart`
339
-
340
- **Properties:**
341
-
342
- | Property | Type | Description |
343
- |----------|------|-------------|
344
- | `name` | `string` | — |
345
- | `thickness` | `number` | — |
346
- | `options` | `FlatPartOptions` | — |
347
-
348
- **Methods:**
349
-
350
- #### `edges()` — All edges as a read-only map.
351
-
352
- ```ts
353
- get edges(): ReadonlyMap<string, EdgeInfo>
354
- ```
355
-
356
- #### `edge()` — Look up a named edge. Throws if the edge does not exist.
357
-
358
- ```ts
359
- edge(name: string): EdgeInfo
360
- ```
361
-
362
- #### `edgeNames()` — All edge names on this part.
363
-
364
- ```ts
365
- edgeNames(): string[]
366
- ```
367
-
368
- #### `partNumber()` — BOM part number assigned to this flat part.
369
-
370
- ```ts
371
- get partNumber(): number
372
- ```
373
-
374
- #### `joints()` — Joint records that attach this part to other parts in the kit.
375
-
376
- ```ts
377
- get joints(): readonly JointRecord[]
378
- ```
379
-
380
- #### `quantity()` — Requested quantity of this part in the kit. Defaults to `1`.
381
-
382
- ```ts
383
- get quantity(): number
384
- ```
385
-
386
- #### `addGeometry()` — Add geometry (e.g. protruding tabs) to the part profile.
387
-
388
- ```ts
389
- addGeometry(sketch: Sketch): void
390
- ```
391
-
392
- #### `subtractGeometry()` — Subtract geometry (e.g. slot cuts) from the part profile.
393
-
394
- ```ts
395
- subtractGeometry(sketch: Sketch): void
396
- ```
397
-
398
- #### `addJoint()` — Record a joint connection for assembly preview.
399
-
400
- ```ts
401
- addJoint(record: JointRecord): void
402
- ```
403
-
404
- #### `profile()` — Final 2D profile with joints and optional kerf compensation.
405
-
406
- ```ts
407
- profile(kerf?: number): Sketch
408
- ```
409
-
410
- #### `solid()` — 3D solid — extrude the profile by material thickness.
411
-
412
- ```ts
413
- solid(kerf?: number): Shape
414
- ```
415
-
416
- ### `LaserKit`
417
-
418
- #### `kerf()` — Laser kerf in mm.
419
-
420
- ```ts
421
- get kerf(): number
422
- ```
423
-
424
- #### `parts()` — All registered parts (flat, in insertion order).
425
-
426
- ```ts
427
- get parts(): readonly FlatPart[]
428
- ```
429
-
430
- #### `material()` — Default material label.
431
-
432
- ```ts
433
- get material(): string
434
- ```
435
-
436
- #### `sheetWidth()` — Stock sheet width in mm.
437
-
438
- ```ts
439
- get sheetWidth(): number
440
- ```
441
-
442
- #### `sheetHeight()` — Stock sheet height in mm.
443
-
444
- ```ts
445
- get sheetHeight(): number
446
- ```
447
-
448
- #### `addPart()` — Register a flat part with this kit. Assigns a sequential part number and records the quantity.
449
-
450
- ```ts
451
- addPart(part: FlatPart, overrides?: { qty?: number; }): this
452
- ```
453
-
454
- #### `cutSheets()` — Generate nested cut sheets using guillotine bin-packing.
455
-
456
- ```ts
457
- cutSheets(): CuttingLayoutResult
458
- ```
459
-
460
- #### [`bom()`](/docs/output#bom) — Bill of materials listing every part with dimensions.
461
-
462
- ```ts
463
- bom(): LaserKitBomEntry[]
464
- ```
465
-
466
- #### `partSvgs()` — Individual SVG string for each part profile, keyed by part name.
467
-
468
- ```ts
469
- partSvgs(): Map<string, string>
470
- ```
471
-
472
- #### `inventorySvg()` — Combined inventory SVG showing all parts in a labeled grid.
473
-
474
- ```ts
475
- inventorySvg(): string
476
- ```
477
-
478
- #### `assemblyPreview()` — 3D fold-up preview of the assembled kit.
479
-
480
- ```ts
481
- assemblyPreview(options?: Omit<AssemblyPreviewOptions, "kerf">): AssemblyPreviewResult
482
- ```
483
-
484
- #### `assemblyInstructions()` — Step-by-step assembly instructions.
485
-
486
- ```ts
487
- assemblyInstructions(options?: AssemblyInstructionsOptions): AssemblyInstructionsResult
488
- ```
489
-
490
- #### `formatInstructions()` — Human-readable assembly instructions text.
491
-
492
- ```ts
493
- formatInstructions(options?: AssemblyInstructionsOptions): string
494
- ```
495
-
496
- ---
497
-
498
- ## Constants
499
-
500
- ### `SHEET_METAL_EDGES`
501
-
502
- ### `COMMON_KERFS`
503
-
504
- Common kerf values. Users should always test-cut to verify for their specific setup.