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,794 +0,0 @@
1
- ---
2
- skill-group: assembly
3
- skill-order: 100
4
- ---
5
-
6
- # Assembly API
7
-
8
- Kinematic assemblies, joints, couplings, and robot export.
9
-
10
- ## Contents
11
-
12
- - [Assembly & Joints](#assembly-joints) — `bomToCsv`, `assembly`, `joint`
13
- - [Assembly](#assembly) — Structure, Connectors, References, Joints, Solving
14
- - [ImportedAssembly](#importedassembly)
15
- - [SolvedAssembly](#solvedassembly)
16
- - [MateBuilder](#matebuilder)
17
-
18
- ## Functions
19
-
20
- ### Assembly & Joints
21
-
22
- #### `bomToCsv()` — Convert an array of BOM rows into a CSV string.
23
-
24
- Produces a CSV with columns: `part`, `qty`, `material`, `process`, `tolerance`, `notes`. String values are quoted and internal double-quotes are escaped. Prefer calling `solvedAssembly.bomCsv()` directly — this function is exposed for custom BOM processing.
25
-
26
- ```ts
27
- bomToCsv(rows: BomRow[]): string
28
- ```
29
-
30
- **`BomRow`**: `part: string`, `qty: number`, `material?: string`, `process?: string`, `tolerance?: string`, `notes?: string`, `metadata?: PartMetadata`
31
-
32
- **`PartMetadata`**
33
-
34
- | Option | Type | Description |
35
- |--------|------|-------------|
36
- | `tags?` | `string \| readonly string[]` | Viewport organization tags applied to scene objects produced from this part. |
37
- | `material?`, `process?`, `tolerance?`, `qty?`, `notes?`, `densityKgM3?`, `massKg?` | | — |
38
-
39
- #### `assembly()` — Create an assembly container with named parts and joints for kinematic mechanisms.
40
-
41
- **Use this from iteration 1 for any model with moving parts.** Hinges, sliders, gears, articulated fingers, doors — all start with `assembly()`, not with manual rotation math. Don't build a static "extended pose" first and refactor to an assembly later: joint sliders, animations, sweeps, collision detection, and robot export all flow from the kinematic graph.
42
-
43
- An assembly models a mechanism as a directed graph of parts connected by joints. Parts are the nodes; joints are directed edges from parent to child. The graph must be a forest (no cycles). Root parts (those with no incoming joint) are anchored to world space.
44
-
45
- Three joint types are supported: `'revolute'` (hinge), `'prismatic'` (slider), and `'fixed'` (rigid attachment). Use `addPart()` to add geometry, `addJoint()` (or the shorthands `addRevolute()`, `addPrismatic()`, `addFixed()`) to connect parts, and `solve()` to compute world-space positions at a given joint state.
46
-
47
- The higher-level `connect()` API uses declared **connectors** to compute joint frames automatically. The `match()` API uses typed connectors (with gender and type metadata) for automatic compatibility validation and joint creation.
48
-
49
- For multi-file assemblies, a file that returns an `Assembly` is importable via [`require()`](/docs/core#require) and yields an `ImportedAssembly`. Use `mergeInto()` to flatten a sub-assembly into a parent assembly.
50
-
51
- ```ts
52
- const mech = assembly("Arm")
53
- .addPart("base", box(80, 80, 20).translate(0, 0, -10), {
54
- metadata: { material: "PETG", process: "FDM", qty: 1 },
55
- })
56
- .addPart("link", box(140, 24, 24).translate(0, -12, -12))
57
- .addRevolute("shoulder", "base", "link", {
58
- axis: [0, 1, 0],
59
- min: -30, max: 120, default: 25,
60
- frame: Transform.identity().translate(0, 0, 20),
61
- });
62
-
63
- return mech; // auto-solved at defaults, renders all parts
64
- ```
65
-
66
- ```ts
67
- assembly(name?: string): Assembly
68
- ```
69
-
70
- #### `joint()` — Create a revolute joint that auto-generates a parameter slider and rotates the shape.
71
-
72
- This is a convenience wrapper for single-shape, single-joint use cases. It calls `param()` to create a named angle slider, then applies `rotateAroundAxis()` to the shape. Use the full `Assembly` API for mechanisms with multiple parts and joints.
73
-
74
- ```ts
75
- const arm = joint("Shoulder", armShape, [0, 0, 20], {
76
- axis: [0, 1, 0],
77
- min: -30, max: 120, default: 25,
78
- });
79
- return arm;
80
- ```
81
-
82
- ```ts
83
- joint(name: string, shape: Shape, pivot: [ number, number, number ], opts?: RevoluteJointOpts): Shape
84
- ```
85
-
86
- `RevoluteJointOpts`: `{ axis?: [ number, number, number ], min?: number, max?: number, default?: number, unit?: string, reverse?: boolean }`
87
-
88
- ---
89
-
90
- ## Classes
91
-
92
- ### `Assembly`
93
-
94
- Container for a kinematic mechanism made up of named parts and joints.
95
-
96
- An assembly is a directed graph where **parts** are nodes and **joints** are directed edges from parent to child. The graph must be a forest (one or more trees with no cycles). Root parts (no incoming joint) are fixed to world space.
97
-
98
- Each joint carries a `frame` transform (from the parent part frame to the joint's zero-state frame) and a motion formula:
99
-
100
- ```
101
- childWorld = parentWorld × frame × motion(value) × childBase
102
- ```
103
-
104
- Three joint types are supported:
105
-
106
- - **revolute** — rotates the child around an axis by `value` degrees
107
- - **prismatic** — translates the child along an axis by `value` mm
108
- - **fixed** — no motion; rigidly attaches the child at `frame`
109
-
110
- **Quick start**
111
-
112
- ```ts
113
- const mech = assembly("Arm")
114
- .addPart("base", box(80, 80, 20).translate(0, 0, -10))
115
- .addPart("link", box(140, 24, 24).translate(0, -12, -12))
116
- .addJoint("shoulder", "revolute", "base", "link", {
117
- axis: [0, 1, 0],
118
- min: -30, max: 120, default: 25,
119
- frame: Transform.identity().translate(0, 0, 20),
120
- });
121
-
122
- return mech; // auto-solved at defaults
123
- ```
124
-
125
- Returning an unsolved `Assembly` auto-solves at default joint values. Return a `SolvedAssembly` directly for a specific pose:
126
-
127
- ```ts
128
- return mech.solve({ shoulder: 60 });
129
- ```
130
-
131
- **Return types**
132
-
133
- | Return value | Standalone | `require()` result type |
134
- |---|---|---|
135
- | `Assembly` (unsolved) | yes | `ImportedAssembly` |
136
- | `SolvedAssembly` | yes | `SolvedAssembly` |
137
-
138
- **Properties:**
139
-
140
- | Property | Type | Description |
141
- |----------|------|-------------|
142
- | `name` | `string` | — |
143
-
144
- **Connectors**
145
-
146
- #### `usedConnectorRefs()` — Connector refs (e.g. "PartName.connectorName") consumed by connect/match calls.
147
-
148
- ```ts
149
- get usedConnectorRefs(): ReadonlySet<string>
150
- ```
151
-
152
- #### `withConnectors()` — Attach named connectors to a specific part or the assembly as a whole.
153
-
154
- Connectors declared this way are in the part's local coordinate system. They are captured automatically if the incoming [`Shape`](/docs/core#shape) already has connectors via `shape.withConnectors(...)`, but you can also add or override connectors after the fact with this method.
155
-
156
- Use the single-argument overload to attach assembly-level connectors — these are exposed when this assembly is imported as a sub-assembly.
157
-
158
- ```ts
159
- withConnectors(partName: string, connectors: Record<string, ConnectorInput>): Assembly
160
- ```
161
-
162
- #### `getConnectors()` — Get connectors declared on a part in part-local space.
163
-
164
- ```ts
165
- getConnectors(partName: string): ConnectorMap
166
- ```
167
-
168
- #### `getConnector()` — Parse a "PartName.connectorName" reference and return the resolved connector. Throws descriptive errors if the part or connector doesn't exist.
169
-
170
- ```ts
171
- getConnector(ref: string): { partName: string; connectorName: string; connector: ConnectorDef; }
172
- ```
173
-
174
- #### `connect()` — Connect two parts by aligning their declared connectors, automatically computing frame and axis.
175
-
176
- Connector references use `"PartName.connectorName"` format. The system aligns connector origins (child connector lands exactly on parent connector) and derives the joint frame and axis from the connector geometry — no manual `frame` or `axis` math needed.
177
-
178
- **Face-to-face convention:** Connectors always meet face-to-face, like a USB plug meeting a socket. Each connector's axis points "outward" from its part. When two connectors mate, the system brings them together so their axes oppose (anti-parallel). This is the same convention used by `matchTo()`.
179
-
180
- For a revolute joint (hinge), both connectors' axes should point outward from their respective parts along the hinge line. For a prismatic joint (slider), both axes should point along the slide direction from their part's perspective.
181
-
182
- The joint type is inferred from the connector's `kind` field if not specified in `options`.
183
-
184
- When connectors are defined with `start`/`end`, you can control which point on each connector meets via `align` / `parentAlign` / `childAlign` (`'start'`, `'middle'`, `'end'`).
185
-
186
- Use `connect()` when connector origins must physically coincide (flange-to-flange, bolt-into-bore). For mechanisms where parts share an axis but are deliberately spaced apart, use `addRevolute()` with pre-positioned parts instead.
187
-
188
- ```ts
189
- // Hinge: both axes point outward along the hinge line
190
- const frame = box(100, 10, 80).withConnectors({
191
- hinge: connector("hinge", { origin: [0, 0, 40], axis: [0, 0, 1] }),
192
- });
193
- const door = box(60, 4, 80).withConnectors({
194
- hinge: connector("hinge", { origin: [0, 0, 40], axis: [0, 0, -1] }),
195
- });
196
- assembly("Door")
197
- .addPart("Frame", frame)
198
- .addPart("Door", door)
199
- .connect("Frame.hinge", "Door.hinge", { as: "swing", min: 0, max: 110 });
200
- ```
201
-
202
- ```ts
203
- connect(parentConnectorRef: string, childConnectorRef: string, options?: ConnectOptions): Assembly
204
- ```
205
-
206
- #### `match()` — Auto-create a joint by matching typed connectors between two parts.
207
-
208
- Connectors can carry a `connectorType` string and a `gender` (`'male'`, `'female'`, or `'neutral'`). `match()` validates type and gender compatibility (use `{ force: true }` to skip validation) and creates the joint automatically from the connector's `kind` metadata.
209
-
210
- The `pairs` map is `{ childConnector: parentConnector }`. The first pair drives joint creation; additional pairs are validated but do not create additional joints (they constrain the same rigid connection).
211
-
212
- Define connectors on shapes with `shape.withConnectors(...)`:
213
-
214
- ```ts
215
- const door = doorShape.withConnectors({
216
- hinge_top: connector.male("hinge", { origin: [0, 0, 90], axis: [0, 0, 1] }),
217
- hinge_bottom: connector.male("hinge", { origin: [0, 0, 10], axis: [0, 0, 1] }),
218
- });
219
- ```
220
-
221
- Then match in the assembly:
222
-
223
- ```ts
224
- const mech = assembly("Door")
225
- .addPart("Frame", frame)
226
- .addPart("Door", door)
227
- .match("Door", "Frame", { hinge_top: "hinge_top", hinge_bottom: "hinge_bottom" });
228
- // Revolute connectors → auto-creates revolute joint. No manual addRevolute needed.
229
- ```
230
-
231
- ```ts
232
- match(childPartName: string, parentPartName: string, pairs: Record<string, string>, options?: MatchToOptions & { as?: string; }): Assembly
233
- ```
234
-
235
- **References**
236
-
237
- #### `withReferences()` — Attach named placement reference points to this assembly. These are surfaced automatically on the ImportedAssembly when this file is imported via require(), so consumers can use placeReference() without re-declaring them. Returns a new Assembly — does not mutate.
238
-
239
- ```ts
240
- withReferences(refs: Pick<PlacementReferenceInput, "points">): Assembly
241
- ```
242
-
243
- **Solving**
244
-
245
- #### `solve()` — Solve the assembly at the given joint state and return positioned parts.
246
-
247
- Performs a depth-first traversal of the joint graph. Each joint's value is taken from `state`, falling back to `defaultValue`. Coupled joints compute their value from source joints. Values outside `[min, max]` are clamped (a warning is added to `SolvedAssembly.warnings()`).
248
-
249
- If mate constraints were registered via `mate()`, the solver runs a pre-pass to derive base transforms, then the kinematic DFS applies joints on top of those positions.
250
-
251
- **Pitfall — [`jointsView`](/docs/viewport#jointsview) double-rotation:** When calling `toJointsView()`, always solve at the rest pose (all joint values = 0 or default). Solving at a non-zero angle and then animating will double-rotate parts. Use the `defaults` option on `toJointsView()` to set the initial display angle instead.
252
-
253
- This pitfall only applies when `toJointsView()` is active. If you only want a static posed result, return the solved assembly directly and skip `toJointsView()`.
254
-
255
- **Example — static posed output (no `toJointsView()`)**
256
-
257
- ```ts
258
- return mech.solve({ shoulder: 45, elbow: -20 });
259
- ```
260
-
261
- ```ts
262
- solve(state?: JointState): SolvedAssembly
263
- ```
264
-
265
- **Other**
266
-
267
- #### `mate()` — Register mate constraints between parts. Constraints are solved during `solve()` to derive part positions and explode hints. Part references use "partName:featureName" format.
268
-
269
- ```ts
270
- mate(fn: (m: MateBuilder) => void): Assembly
271
- ```
272
-
273
- #### `addFrame()` — Add a virtual reference frame (no geometry) to the assembly graph.
274
-
275
- Useful when you need a named pivot point or coordinate frame that has no visual geometry. Acts like a zero-volume part and can be connected to other parts via joints.
276
-
277
- ```ts
278
- addFrame(name: string, options?: PartOptions): Assembly
279
- ```
280
-
281
- #### `addPart()` — Add a named part to the assembly.
282
-
283
- Connectors declared on the part (via `withConnectors()`) are captured automatically. Parts are positioned at world origin by default unless a `transform` is provided in `options`. For root parts (no incoming joint), `transform` is their final world position.
284
-
285
- When a part is a [`ShapeGroup`](/docs/core#shapegroup), name the group children explicitly to get readable viewport labels (e.g. `"Base Assembly.Body"` instead of `"Base Assembly.1"`):
286
-
287
- ```ts
288
- const housing = group(
289
- { name: "Body", shape: body },
290
- { name: "Lid", shape: lid },
291
- );
292
- assembly.addPart("Base Assembly", housing);
293
- ```
294
-
295
- ```ts
296
- addPart(name: string, part: AssemblyPart, options?: PartOptions): Assembly
297
- ```
298
-
299
- #### `addJoint()` — Add a kinematic joint between a parent and child part.
300
-
301
- `frame` is a transform from the **parent part frame** to the **joint frame at zero state**. The child's world position is computed as:
302
-
303
- ```
304
- childWorld = parentWorld × frame × motion(value) × childBase
305
- ```
306
-
307
- For revolute joints `value` is in degrees; for prismatic joints `value` is in mm. Coupled joints (see `addJointCoupling`) ignore the `state` value passed to `solve()` and compute their value from source joints.
308
-
309
- ```ts
310
- addJoint(name: string, type: JointType, parent: string, child: string, options?: JointOptions): Assembly
311
- ```
312
-
313
- #### `addRevolute()` — Shorthand for `addJoint(name, 'revolute', parent, child, options)`.
314
-
315
- ```ts
316
- addRevolute(name: string, parent: string, child: string, options?: JointOptions): Assembly
317
- ```
318
-
319
- #### `addPrismatic()` — Shorthand for `addJoint(name, 'prismatic', parent, child, options)`.
320
-
321
- ```ts
322
- addPrismatic(name: string, parent: string, child: string, options?: JointOptions): Assembly
323
- ```
324
-
325
- #### `addFixed()` — Shorthand for `addJoint(name, 'fixed', parent, child, options)`.
326
-
327
- Fixed joints rigidly attach a child part to its parent at `frame` with no motion. Before calling `mergeInto()`, use `addFixed()` to collapse multiple root parts into a single root.
328
-
329
- ```ts
330
- addFixed(name: string, parent: string, child: string, options?: JointOptions): Assembly
331
- ```
332
-
333
- #### `addJointCoupling()` — Link a joint's value to a linear combination of other joint values.
334
-
335
- The driven joint's value is computed as:
336
-
337
- ```
338
- driven = offset + Σ(ratio_i × source_i)
339
- ```
340
-
341
- Coupled joints ignore any value passed in `solve(state)` — a warning is emitted if you try to override one. Coupling cycles are rejected. You cannot sweep a coupled joint directly; sweep one of its source joints instead.
342
-
343
- ```ts
344
- assembly
345
- .addRevolute("Steering", "Base", "Turret", { axis: [0, 0, 1] })
346
- .addRevolute("WheelDrive", "Turret", "Wheel", { axis: [1, 0, 0] })
347
- .addRevolute("TopGear", "Base", "TopInput", { axis: [0, 0, 1] })
348
- .addJointCoupling("TopGear", {
349
- terms: [
350
- { joint: "Steering", ratio: 1 },
351
- { joint: "WheelDrive", ratio: 20 / 14 },
352
- ],
353
- });
354
- ```
355
-
356
- ```ts
357
- addJointCoupling(jointName: string, options: JointCouplingOptions): Assembly
358
- ```
359
-
360
- #### `addGearCoupling()` — Link two revolute joints via a gear ratio.
361
-
362
- Choose exactly one ratio source:
363
-
364
- - `ratio` — explicit numeric ratio (driven/driver, negative for external mesh)
365
- - `pair` — a `GearRatioLike` from `lib.gearPair`, `lib.bevelGearPair`, etc. (uses `pair.jointRatio`)
366
- - `driverTeeth` + `drivenTeeth` — auto-computes ratio; use `mesh` to control sign (`'external'` = negative/opposite rotation, `'internal'` = positive, `'bevel'`/`'face'` = negative)
367
-
368
- When `pair` carries a `phaseDeg`, it is auto-applied as the coupling `offset` to align teeth correctly. Override with `offset: 0` if gear shapes already have the phase baked in.
369
-
370
- ```ts
371
- const pair = lib.gearPair({ pinion: { module: 1.25, teeth: 14 }, gear: { module: 1.25, teeth: 42 } });
372
- assembly
373
- .addRevolute("Pinion", "Base", "PinionPart", { axis: [0, 0, 1] })
374
- .addRevolute("Driven", "Base", "GearPart", { axis: [0, 0, 1] })
375
- .addGearCoupling("Driven", "Pinion", { pair });
376
- ```
377
-
378
- ```ts
379
- addGearCoupling(drivenJointName: string, driverJointName: string, options?: GearCouplingOptions): Assembly
380
- ```
381
-
382
- #### `sweepJoint()` — Sample a joint through its motion range, collecting collision data at each step.
383
-
384
- Divides `[from, to]` into `steps` intervals (producing `steps + 1` frames). At each sample, the assembly is solved with the sweeping joint at that value and `baseState` for all others. Returns one `JointSweepFrame` per sample with the joint value, collision findings, and any solve warnings.
385
-
386
- You cannot sweep a coupled joint — sweep one of its source joints instead.
387
-
388
- ```ts
389
- const sweep = mech.sweepJoint("elbow", -10, 135, 12, { shoulder: 35 });
390
- const hits = sweep.filter(frame => frame.collisions.length > 0);
391
- console.log(`Collisions at ${hits.length} of ${sweep.length} poses`);
392
- ```
393
-
394
- ```ts
395
- sweepJoint(jointName: string, from: number, to: number, steps: number, baseState?: JointState, collisionOptions?: CollisionOptions): JointSweepFrame[]
396
- ```
397
-
398
- #### `toJointsView()` — Derive viewport joint controls from the assembly graph and register them.
399
-
400
- Solves the assembly at rest (all joints = default), then converts each joint into a `JointViewInput` with world-space pivot and axis. Fixed joints become hidden zero-range revolute entries so attached parts follow their parent during animation. Joint couplings are forwarded to the viewport automatically.
401
-
402
- This method is optional. Call it only when you want viewport joint sliders, coupled controls, or playback animations. If you only want geometry, return the `Assembly` or `SolvedAssembly` directly and skip `toJointsView()`.
403
-
404
- **Critical pitfall:** Always call `toJointsView()` before solving for display. Then solve at the **rest pose** (no state overrides) and return that solved assembly result directly. Do not flatten it with `.toGroup()` if you want the viewport joint animation to keep working.
405
-
406
- Do not solve at a non-zero angle when using `toJointsView()` — the viewport will apply the same rotation again, double-rotating the part.
407
-
408
- ```ts
409
- mech.toJointsView({
410
- defaults: { J1: 30 },
411
- animations: [{
412
- name: "Swing", duration: 2, loop: true,
413
- keyframes: [{ values: { J1: -45 } }, { values: { J1: 45 } }, { values: { J1: -45 } }],
414
- }],
415
- });
416
-
417
- // Solve at REST — viewport handles posing
418
- return mech.solve();
419
- ```
420
-
421
- ```ts
422
- toJointsView(options?: ToJointsViewOptions): void
423
- ```
424
-
425
- #### `describe()` — Return the serializable assembly definition used by solve/inspect pipelines.
426
-
427
- ```ts
428
- describe(): AssemblyDefinition
429
- ```
430
-
431
- **Compatibility Aliases**
432
-
433
- - `usedPortRefs` -> `usedConnectorRefs`
434
- - `withPorts()` -> `withConnectors()`
435
- - `getPorts()` -> `getConnectors()`
436
- - `getPort()` -> `getConnector()`
437
-
438
- ### `ImportedAssembly`
439
-
440
- A wrapper around an imported `Assembly` that provides kinematic access and convenient transform helpers.
441
-
442
- When a `.forge.js` file returns an unsolved `Assembly`, [`require()`](/docs/core#require) wraps it in an `ImportedAssembly`. This preserves the kinematic structure — you can call `solve()`, `sweepJoint()`, and `mergeInto()` — while also allowing convenience transforms that auto-solve at default values.
443
-
444
- **Kinematic access**
445
-
446
- ```ts
447
- const arm = require("./arm.forge.js");
448
-
449
- const solved = arm.solve({ shoulder: 45 }); // full kinematic solve
450
- const link = arm.part("Link", { shoulder: 60 }); // single part at state
451
- const group = arm.toGroup({ shoulder: 45 }); // only when ShapeGroup behavior is needed
452
- ```
453
-
454
- **Convenience transforms** (auto-solve at defaults, return [`ShapeGroup`](/docs/core#shapegroup)):
455
-
456
- ```ts
457
- const positioned = arm.rotateZ(-90).translate(0, -20, 50);
458
- ```
459
-
460
- **Merging into a parent**
461
-
462
- ```ts
463
- require("./arm.forge.js").mergeInto(robot, {
464
- prefix: "Left Arm",
465
- mountParent: "Chassis",
466
- mountJoint: "leftMount",
467
- mountOptions: { frame: Transform.identity().translate(-70, 0, 10) },
468
- });
469
- ```
470
-
471
- #### `assembly()` — The underlying Assembly — use for sweepJoint, addPart into parent, etc.
472
-
473
- ```ts
474
- get assembly(): Assembly
475
- ```
476
-
477
- #### `solve()` — Solve the assembly at the given joint state (defaults to each joint's default value).
478
-
479
- ```ts
480
- solve(state?: JointState): SolvedAssembly
481
- ```
482
-
483
- #### `part()` — Return a specific named part positioned at the given joint state, with any stored placement offset applied.
484
-
485
- ```ts
486
- part(name: string, state?: JointState): AssemblyPart
487
- ```
488
-
489
- #### `toGroup()` — Convert all assembly parts to a ShapeGroup with named children. Use this for composition, transforms, or child lookup — not as a required render step for assemblies. Child names match the part names used in the assembly. Any stored placement offset and placement references are forwarded to the group.
490
-
491
- ```ts
492
- toGroup(state?: JointState): ShapeGroup
493
- ```
494
-
495
- #### `withReferences()` — Attach named placement reference points to this assembly. Points are simple 3D coordinates (relative to the assembly's own origin). Returns a new ImportedAssembly — does not mutate.
496
-
497
- ```ts
498
- withReferences(refs: Pick<PlacementReferenceInput, "points">): ImportedAssembly
499
- ```
500
-
501
- #### `referenceNames()` — List all attached placement reference names.
502
-
503
- ```ts
504
- referenceNames(kind?: PlacementReferenceKind): string[]
505
- ```
506
-
507
- #### `placeReference()` — Translate the assembly so the named reference point lands on `target`. Returns a new ImportedAssembly — does not mutate. All point refs are translated by the same delta.
508
-
509
- ```ts
510
- placeReference(ref: string, target: [ number, number, number ], offset?: [ number, number, number ]): ImportedAssembly
511
- ```
512
-
513
- #### `translate()` — Solve at defaults and return a translated ShapeGroup.
514
-
515
- ```ts
516
- translate(x: number, y: number, z: number): ShapeGroup
517
- ```
518
-
519
- #### `rotate()` — Solve at defaults and return a rotated ShapeGroup.
520
-
521
- ```ts
522
- rotate(axis: [ number, number, number ], angleDeg: number, options?: { pivot?: [ number, number, number ]; }): ShapeGroup
523
- ```
524
-
525
- #### `rotateX()` — Solve at defaults and return a ShapeGroup rotated around X.
526
-
527
- ```ts
528
- rotateX(angleDeg: number, options?: { pivot?: [ number, number, number ]; }): ShapeGroup
529
- ```
530
-
531
- #### `rotateY()` — Solve at defaults and return a ShapeGroup rotated around Y.
532
-
533
- ```ts
534
- rotateY(angleDeg: number, options?: { pivot?: [ number, number, number ]; }): ShapeGroup
535
- ```
536
-
537
- #### `rotateZ()` — Solve at defaults and return a ShapeGroup rotated around Z.
538
-
539
- ```ts
540
- rotateZ(angleDeg: number, options?: { pivot?: [ number, number, number ]; }): ShapeGroup
541
- ```
542
-
543
- #### `scale()` — Solve at defaults and return a scaled ShapeGroup.
544
-
545
- ```ts
546
- scale(v: number | [ number, number, number ]): ShapeGroup
547
- ```
548
-
549
- #### `mirror()` — Solve at defaults and return a mirrored ShapeGroup.
550
-
551
- ```ts
552
- mirror(normal: [ number, number, number ]): ShapeGroup
553
- ```
554
-
555
- #### `color()` — Solve at defaults and return a colored ShapeGroup.
556
-
557
- ```ts
558
- color(hex: string): ShapeGroup
559
- ```
560
-
561
- #### `child()` — Solve at defaults, get a named child part from the resulting group.
562
-
563
- ```ts
564
- child(name: string): Shape | Sketch | ShapeGroup
565
- ```
566
-
567
- #### `mergeInto()` — Flatten this sub-assembly's parts and joints into `parent` and wire a mount joint.
568
-
569
- All part and joint names from the sub-assembly are prefixed with `"${options.prefix}."` to avoid collisions. After the merge, sub-assembly joints are driven from the parent using the prefixed names:
570
-
571
- ```ts
572
- parent.solve({ "Left Arm.shoulder": 45, "Right Arm.shoulder": -20 })
573
- ```
574
-
575
- Joint couplings inside the sub-assembly are preserved and rewritten with the prefix. Ports from sub-assembly parts are forwarded with the prefix.
576
-
577
- The sub-assembly must have exactly one root part. If it has multiple roots, use `addFixed()` first to consolidate them before merging.
578
-
579
- ```ts
580
- const robot = assembly("Robot").addPart("Chassis", chassis);
581
-
582
- require("./arm.forge.js").mergeInto(robot, {
583
- prefix: "Left Arm",
584
- mountParent: "Chassis",
585
- mountJoint: "leftMount",
586
- mountOptions: { frame: Transform.identity().translate(-70, 0, 10) },
587
- });
588
- ```
589
-
590
- ```ts
591
- mergeInto(parent: Assembly, options: MergeIntoOptions): Assembly
592
- ```
593
-
594
- ### `SolvedAssembly`
595
-
596
- The result of solving an assembly at a specific joint state.
597
-
598
- `SolvedAssembly` holds world-space transforms for every part at a given pose. Top-level scripts can return a `SolvedAssembly` directly for display. Use `toGroup()` when you specifically need a [`ShapeGroup`](/docs/core#shapegroup) for composition, group-style transforms, or named-child lookup. Do not call `toGroup()` just to make a solved assembly render. Use `getPart()` / `getTransform()` to inspect individual parts programmatically.
599
-
600
- **Validation**
601
-
602
- Call `collisionReport()` to detect overlapping parts, or `sweepJoint()` on the parent `Assembly` to check for interference across the joint's motion range.
603
-
604
- ```ts
605
- const solved = mech.solve({ shoulder: 45, elbow: -20 });
606
- console.log("Collisions", solved.collisionReport());
607
- return solved;
608
- ```
609
-
610
- **Properties:**
611
-
612
- | Property | Type | Description |
613
- |----------|------|-------------|
614
- | `name` | `string` | — |
615
-
616
- **Methods:**
617
-
618
- #### `warnings()` — Return any warnings generated during solve (clamped joints, unconverged mates, etc.).
619
-
620
- ```ts
621
- warnings(): string[]
622
- ```
623
-
624
- #### `getJointState()` — Return a snapshot of resolved joint values (after clamping and coupling).
625
-
626
- ```ts
627
- getJointState(): JointState
628
- ```
629
-
630
- #### `mateExplodeHints()` — Explode direction hints derived from mate constraints, or null if no mates.
631
-
632
- ```ts
633
- get mateExplodeHints(): Record<string, { direction: Vec3; }> | null
634
- ```
635
-
636
- #### `mateDof()` — Remaining degrees of freedom after mate constraints, or null if no mates.
637
-
638
- ```ts
639
- get mateDof(): number | null
640
- ```
641
-
642
- #### `mateConverged()` — Whether the mate constraint solver converged, or null if no mates.
643
-
644
- ```ts
645
- get mateConverged(): boolean | null
646
- ```
647
-
648
- #### `getTransform()` — Return the world-space [`Transform`](/docs/core#transform) for the named part at the solved pose.
649
-
650
- ```ts
651
- getTransform(partName: string): Transform
652
- ```
653
-
654
- #### `getPart()` — Return the named part already positioned at its solved world transform.
655
-
656
- ```ts
657
- getPart(partName: string): AssemblyPart
658
- ```
659
-
660
- #### `toGroup()` — Convert all solved parts into a [`ShapeGroup`](/docs/core#shapegroup) with named children.
661
-
662
- Each part becomes a named child in the group, already positioned at its solved world transform. Use this only when you specifically need a [`ShapeGroup`](/docs/core#shapegroup) for composition, [`ShapeGroup`](/docs/core#shapegroup) transforms, or named-child access. Top-level scripts can return the `SolvedAssembly` directly; do not call `toGroup()` just to make a solved assembly render.
663
-
664
- ```ts
665
- const armGroup = mech.solve({ shoulder: 60 }).toGroup(); // only because we need rotateZ()
666
- return armGroup.rotateZ(90);
667
- ```
668
-
669
- ```ts
670
- toGroup(): ShapeGroup
671
- ```
672
-
673
- #### `toSceneObjects()` — Return an array of named scene objects for the viewport renderer.
674
-
675
- Each part becomes `{ name, shape }` or `{ name, group: [...] }` if the part is a [`ShapeGroup`](/docs/core#shapegroup). Top-level scripts should normally return the `SolvedAssembly` directly. Use `toGroup()` when you need [`ShapeGroup`](/docs/core#shapegroup) behavior; use this method only for advanced scene-graph control where you need access to the flat per-part array with metadata.
676
-
677
- ```ts
678
- toSceneObjects(): Array<{ name: string; shape?: Shape; group?: Array<{ name: string; shape: Shape; tags?: string[]; }>; metadata?: PartMetadata; }>
679
- ```
680
-
681
- #### `toScene()` — Backward-compatible alias for `toSceneObjects()`.
682
-
683
- ```ts
684
- toScene(): Array<{ name: string; shape?: Shape; group?: Array<{ name: string; shape: Shape; tags?: string[]; }>; metadata?: PartMetadata; }>
685
- ```
686
-
687
- #### [`bom()`](/docs/output#bom) — Generate a bill of materials for all parts in the solved assembly.
688
-
689
- ```ts
690
- bom(): BomRow[]
691
- ```
692
-
693
- #### `bomCsv()` — Generate a bill of materials as a CSV string.
694
-
695
- ```ts
696
- bomCsv(): string
697
- ```
698
-
699
- #### `collisionReport()` — Detect overlapping (colliding) part pairs in this solved pose.
700
-
701
- Computes boolean intersections between all part pairs and returns findings where the overlap volume exceeds `minOverlapVolume` (default 0.1 mm³).
702
-
703
- ```ts
704
- const solved = mech.solve({ shoulder: 35, elbow: 60 });
705
- console.log("Collisions", solved.collisionReport());
706
- ```
707
-
708
- ```ts
709
- collisionReport(options?: CollisionOptions): CollisionFinding[]
710
- ```
711
-
712
- #### `minClearance()` — Compute the minimum gap (clearance) between two parts in this solved pose.
713
-
714
- Returns `0` if the parts are touching or overlapping. Requires the Manifold backend. `searchLength` bounds the search radius in mm — increase it for widely separated parts.
715
-
716
- ```ts
717
- minClearance(partA: string, partB: string, searchLength?: number): number
718
- ```
719
-
720
- ### `MateBuilder`
721
-
722
- **Properties:**
723
-
724
- | Property | Type | Description |
725
- |----------|------|-------------|
726
- | `constraints` | `Constraint3D[]` | — |
727
-
728
- **Methods:**
729
-
730
- #### `flush()` — Constrain two faces so they stay flush.
731
-
732
- ```ts
733
- flush(faceA: string, faceB: string): string
734
- ```
735
-
736
- #### `align()` — Constrain two faces so their normals align.
737
-
738
- ```ts
739
- align(faceA: string, faceB: string): string
740
- ```
741
-
742
- #### `parallel()` — Constrain two faces so they remain parallel.
743
-
744
- ```ts
745
- parallel(faceA: string, faceB: string): string
746
- ```
747
-
748
- #### `faceDistance()` — Constrain the distance between two faces.
749
-
750
- ```ts
751
- faceDistance(faceA: string, faceB: string, distance: number): string
752
- ```
753
-
754
- #### `concentric()` — Constrain two axes to share the same center line.
755
-
756
- ```ts
757
- concentric(axisA: string, axisB: string): string
758
- ```
759
-
760
- #### `axisParallel()` — Constrain two axes to remain parallel.
761
-
762
- ```ts
763
- axisParallel(axisA: string, axisB: string): string
764
- ```
765
-
766
- #### `pointCoincident()` — Constrain two points to coincide.
767
-
768
- ```ts
769
- pointCoincident(pointA: string, pointB: string): string
770
- ```
771
-
772
- #### `pointOnFace()` — Constrain a point to lie on a face.
773
-
774
- ```ts
775
- pointOnFace(point: string, face: string): string
776
- ```
777
-
778
- #### `pointOnAxis()` — Constrain a point to lie on an axis.
779
-
780
- ```ts
781
- pointOnAxis(point: string, axis: string): string
782
- ```
783
-
784
- #### `angle()` — Constrain the angle between two faces.
785
-
786
- ```ts
787
- angle(faceA: string, faceB: string, degrees: number): string
788
- ```
789
-
790
- #### `totalEquations()` — Total constraint equations.
791
-
792
- ```ts
793
- get totalEquations(): number
794
- ```