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
@@ -5,336 +5,230 @@ skill-order: 100
5
5
 
6
6
  # Output & Annotations
7
7
 
8
- > **Auto-generated** from `src/forge/forge-public-api.ts`. Do not edit by hand — run `npm run gen:docs` to regenerate.
9
-
10
8
  Dimensions, BOM entries, verification checks, and sketch export.
11
9
 
12
- ## Functions
10
+ ## Contents
13
11
 
14
- ### Annotations & Output
12
+ - [Annotations & Output](#annotations-output) — `bom`, `robotExport`, `dim`, `dimLine`
13
+ - [Sketch Export](#sketch-export) — `sketchToDxf`, `sketchToSvg`
15
14
 
16
- Add dimensions, BOM entries, verification checks, and robot export.
15
+ ## Functions
17
16
 
18
- #### `bom()`
17
+ ### Annotations & Output
19
18
 
20
- ```ts
21
- bom(quantity: number, description: string, opts?: BomOpts): void
22
- ```
19
+ #### `bom()` — Register a Bill of Materials entry for report export.
23
20
 
24
- Add a bill-of-materials entry.
21
+ BOM entries are accumulated during script execution and exported alongside the model in report views. Rows are grouped by normalized `description + unit`. Pass an explicit `key` to force multiple descriptions to collapse into a single line item.
25
22
 
26
- <details><summary><code>BomOpts</code></summary>
23
+ - `quantity` must be a finite number `>= 0`. A quantity of `0` is silently ignored (useful for conditional scripting with `param()`-driven counts).
24
+ - `unit` defaults to `"pieces"` when omitted or empty.
25
+ - The assembly `solved.bom()` / `solved.bomCsv()` API is separate and covers per-part assembly metadata; this function is for free-form purchased-item annotation.
27
26
 
28
27
  ```ts
29
- interface BomOpts {
30
- /** Quantity unit label, e.g. "mm", "pieces", "kg". Default: "pieces" */
31
- unit?: string;
32
- /** Optional explicit grouping key used during report aggregation. */
33
- key?: string;
34
- }
35
- ```
36
-
37
- </details>
28
+ const tubeLen = param("Tube Length", 1200, { min: 300, max: 4000, unit: "mm" });
29
+ const boltCount = param("Bolt Count", 16, { min: 0, max: 200, integer: true });
38
30
 
39
- #### `robotExport()`
31
+ bom(tubeLen, "iron tube 30 x 20", { unit: "mm" });
32
+ bom(boltCount, "M4 bolt, 16 mm length");
33
+ bom(4, "rubber foot", { key: "foot-rubber" }); // explicit aggregation key
40
34
 
41
- ```ts
42
- robotExport(options: RobotExportOptions): CollectedRobotExport
35
+ // Structured metadata for richer reports:
36
+ bom(tubeLen, "rectangular steel tube", {
37
+ unit: "mm",
38
+ material: "steel",
39
+ section: [30, 20],
40
+ wall: 3,
41
+ });
43
42
  ```
44
43
 
45
- Declare that the current script should export an assembly as a robot package for the SDF CLI. Configures inertial properties, joint limits, and optional plugins (e.g. diff-drive for Gazebo).
46
-
47
- <details><summary><code>RobotExportOptions</code></summary>
48
-
49
44
  ```ts
50
- interface RobotExportOptions {
51
- assembly: Assembly;
52
- modelName?: string;
53
- state?: JointState;
54
- static?: boolean;
55
- selfCollide?: boolean;
56
- allowAutoDisable?: boolean;
57
- links?: Record<string, RobotLinkExportOptions>;
58
- joints?: Record<string, RobotJointExportOptions>;
59
- diffDrive?: RobotDiffDrivePluginOptions;
60
- jointStatePublisher?: RobotJointStatePublisherOptions;
61
- world?: RobotWorldOptions;
62
- }
45
+ bom(quantity: number, description: string, opts?: BomOpts): void
63
46
  ```
64
47
 
65
- </details>
48
+ **`BomOpts`**
66
49
 
67
- <details><summary><code>RobotLinkExportOptions</code></summary>
50
+ | Option | Type | Description |
51
+ |--------|------|-------------|
52
+ | `unit?` | `string` | Quantity unit label, e.g. "mm", "pieces", "kg". Default: "pieces" |
53
+ | `key?` | `string` | Optional explicit grouping key used during report aggregation. |
54
+ | `material?` | `string` | Material name, e.g. "steel", "birch plywood", "nylon" |
55
+ | `dimensions?` | `number[]` | Overall dimensions `[width, height]` or `[width, height, thickness]` in the entry's unit |
56
+ | `section?` | `number[]` | Cross-section dimensions `[w, h]` for tubes and profiles |
57
+ | `wall?` | `number` | Wall thickness for hollow sections (mm) |
58
+ | `diameter?` | `number` | Diameter for round stock, bolts, dowels (mm) |
59
+ | `length?` | `number` | Length for fasteners (mm) |
60
+ | `process?` | `string` | Manufacturing process, e.g. "laser cut", "CNC", "welded" |
61
+ | `notes?` | `string` | Free-form notes |
62
+ | `grain?` | `string` | Wood grain direction, e.g. "long", "cross" |
68
63
 
69
- ```ts
70
- interface RobotLinkExportOptions {
71
- massKg?: number;
72
- densityKgM3?: number;
73
- collision?: "visual" | "convex" | "box" | "none";
74
- }
75
- ```
76
-
77
- </details>
78
-
79
- <details><summary><code>RobotJointExportOptions</code></summary>
64
+ #### `robotExport()` — Declare that this script should export the assembly as a SDF/URDF robot package.
80
65
 
81
- ```ts
82
- interface RobotJointExportOptions {
83
- effort?: number;
84
- velocity?: number;
85
- damping?: number;
86
- friction?: number;
87
- }
88
- ```
66
+ Call `robotExport()` alongside your assembly definition. The CLI commands `forgecad export sdf` and `forgecad export urdf` pick up the declaration and produce a robot package with:
89
67
 
90
- </details>
68
+ - Mesh-based inertia tensors (full 6-component, not bounding-box approximations)
69
+ - Separate collision meshes (convex hull by default — ~50–80% smaller)
70
+ - Joint mimic elements derived from `addJointCoupling` / `addGearCoupling`
91
71
 
92
- <details><summary><code>RobotDiffDrivePluginOptions</code></summary>
72
+ **Collision mesh modes** (set per-link via `links["PartName"].collision`):
93
73
 
94
- ```ts
95
- interface RobotDiffDrivePluginOptions {
96
- leftJoints: string[];
97
- rightJoints: string[];
98
- wheelSeparationMm: number;
99
- wheelRadiusMm: number;
100
- topic?: string;
101
- odomTopic?: string;
102
- tfTopic?: string;
103
- frameId?: string;
104
- odomFrameId?: string;
105
- maxLinearVelocity?: number;
106
- maxAngularVelocity?: number;
107
- linearAcceleration?: number;
108
- angularAcceleration?: number;
109
- }
110
- ```
74
+ | Mode | Description | Default | |------|-------------|---------| | `'convex'` | Convex hull (separate `_collision.stl`) | Yes | | `'box'` | AABB primitive — fastest physics | | | `'visual'` | Same mesh as visual — exact but slow | | | `'none'` | No collision geometry | |
111
75
 
112
- </details>
76
+ **Unit conventions:**
113
77
 
114
- <details><summary><code>RobotJointStatePublisherOptions</code></summary>
78
+ - Revolute `velocity` is in degrees/second in Forge; exporters convert to rad/s.
79
+ - Prismatic distances are in mm in Forge; exported in meters.
80
+ - `massKg` is preferred; `densityKgM3` is used when mass is unknown.
81
+ - Couplings with multiple terms: only the primary term (largest ratio) maps to `<mimic>` — SDF/URDF support single-leader mimic only. Dropped terms emit a warning.
115
82
 
116
83
  ```ts
117
- interface RobotJointStatePublisherOptions {
118
- enabled?: boolean;
119
- joints?: string[];
120
- topic?: string;
121
- updateRate?: number;
122
- }
123
- ```
124
-
125
- </details>
84
+ const rover = assembly("Scout")
85
+ .addPart("Chassis", box(300, 220, 50, true))
86
+ .addPart("Left Wheel", cylinder(30, 60, undefined, 48, true))
87
+ .addRevolute("leftWheel", "Chassis", "Left Wheel", {
88
+ axis: [0, 1, 0],
89
+ frame: Transform.identity().translate(90, 140, 60),
90
+ effort: 20, velocity: 1080,
91
+ });
126
92
 
127
- <details><summary><code>RobotWorldOptions</code></summary>
128
-
129
- ```ts
130
- interface RobotWorldOptions {
131
- name?: string;
132
- generateDemoWorld?: boolean;
133
- spawnPose?: RobotPose6;
134
- keyboardTeleop?: RobotWorldKeyboardTeleopOptions;
135
- }
93
+ robotExport({
94
+ assembly: rover,
95
+ modelName: "Scout",
96
+ links: {
97
+ Chassis: { massKg: 10 },
98
+ "Left Wheel": { massKg: 0.8 },
99
+ },
100
+ plugins: {
101
+ diffDrive: {
102
+ leftJoints: ["leftWheel"], rightJoints: ["rightWheel"],
103
+ wheelSeparationMm: 280, wheelRadiusMm: 60,
104
+ },
105
+ },
106
+ world: { generateDemoWorld: true },
107
+ });
136
108
  ```
137
109
 
138
- </details>
110
+ **CLI usage**
139
111
 
140
- <details><summary><code>RobotWorldKeyboardTeleopOptions</code></summary>
112
+ ```bash
113
+ forgecad export sdf model.forge.js # SDF package (Gazebo/Ignition)
114
+ forgecad export urdf model.forge.js # URDF package (ROS/PyBullet/MuJoCo)
115
+ ```
141
116
 
142
117
  ```ts
143
- interface RobotWorldKeyboardTeleopOptions {
144
- enabled?: boolean;
145
- linearStep?: number;
146
- angularStep?: number;
147
- }
118
+ robotExport(options: RobotExportOptions): CollectedRobotExport
148
119
  ```
149
120
 
150
- </details>
121
+ **`RobotExportOptions`**: `assembly: Assembly`, `modelName?: string`, `state?: JointState`, `static?: boolean`, `selfCollide?: boolean`, `allowAutoDisable?: boolean`, `links?: Record<string, RobotLinkExportOptions>`, `joints?: Record<string, RobotJointExportOptions>`, `diffDrive?: RobotDiffDrivePluginOptions`, `jointStatePublisher?: RobotJointStatePublisherOptions`, `world?: RobotWorldOptions`
151
122
 
152
- <details><summary><code>CollectedRobotExport</code></summary>
123
+ `RobotLinkExportOptions`: `{ massKg?: number, densityKgM3?: number, collision?: "visual" | "convex" | "box" | "none" }`
153
124
 
154
- ```ts
155
- interface CollectedRobotExport {
156
- modelName: string;
157
- assembly: AssemblyDefinition;
158
- state: JointState;
159
- static: boolean;
160
- selfCollide: boolean;
161
- allowAutoDisable: boolean;
162
- links: Record<string, RobotLinkExportOptions>;
163
- joints: Record<string, RobotJointExportOptions>;
164
- diffDrive?: RobotDiffDrivePluginOptions;
165
- jointStatePublisher?: RobotJointStatePublisherOptions;
166
- world: RobotWorldOptions | null;
167
- }
168
- ```
125
+ `RobotJointExportOptions`: `{ effort?: number, velocity?: number, damping?: number, friction?: number }`
169
126
 
170
- </details>
127
+ **`RobotDiffDrivePluginOptions`**: `leftJoints: string[]`, `rightJoints: string[]`, `wheelSeparationMm: number`, `wheelRadiusMm: number`, `topic?: string`, `odomTopic?: string`, `tfTopic?: string`, `frameId?: string`, `odomFrameId?: string`, `maxLinearVelocity?: number`, `maxAngularVelocity?: number`, `linearAcceleration?: number`, `angularAcceleration?: number`
171
128
 
172
- <details><summary><code>AssemblyDefinition</code></summary>
129
+ `RobotJointStatePublisherOptions`: `{ enabled?: boolean, joints?: string[], topic?: string, updateRate?: number }`
173
130
 
174
- ```ts
175
- interface AssemblyDefinition {
176
- name: string;
177
- parts: AssemblyPartDef[];
178
- joints: AssemblyJointDef[];
179
- jointCouplings: AssemblyJointCouplingDef[];
180
- }
181
- ```
131
+ `RobotWorldOptions`: `{ name?: string, generateDemoWorld?: boolean, spawnPose?: RobotPose6, keyboardTeleop?: RobotWorldKeyboardTeleopOptions }`
182
132
 
183
- </details>
133
+ `RobotWorldKeyboardTeleopOptions`: `{ enabled?: boolean, linearStep?: number, angularStep?: number }`
184
134
 
185
- <details><summary><code>AssemblyPartDef</code></summary>
135
+ **`CollectedRobotExport`**: `modelName: string`, `assembly: AssemblyDefinition`, `state: JointState`, `static: boolean`, `selfCollide: boolean`, `allowAutoDisable: boolean`, `links: Record<string, RobotLinkExportOptions>`, `joints: Record<string, RobotJointExportOptions>`, `diffDrive?: RobotDiffDrivePluginOptions`, `jointStatePublisher?: RobotJointStatePublisherOptions`, `world: RobotWorldOptions | null`
186
136
 
187
- ```ts
188
- interface AssemblyPartDef {
189
- name: string;
190
- part: AssemblyPart;
191
- base: Transform;
192
- metadata?: PartMetadata;
193
- }
194
- ```
137
+ `AssemblyDefinition`: `{ name: string, parts: AssemblyPartDef[], joints: AssemblyJointDef[], jointCouplings: AssemblyJointCouplingDef[] }`
195
138
 
196
- </details>
139
+ `AssemblyPartDef`: `{ name: string, part: AssemblyPart, base: Transform, metadata?: PartMetadata }`
197
140
 
198
- <details><summary><code>PartMetadata</code></summary>
141
+ **`PartMetadata`**: `material?: string`, `process?: string`, `tolerance?: string`, `qty?: number`, `notes?: string`, `densityKgM3?: number`, `massKg?: number`
199
142
 
200
- ```ts
201
- interface PartMetadata {
202
- material?: string;
203
- process?: string;
204
- tolerance?: string;
205
- qty?: number;
206
- notes?: string;
207
- densityKgM3?: number;
208
- massKg?: number;
209
- }
210
- ```
143
+ **`AssemblyJointDef`**: `name: string`, `type: JointType`, `parent: string`, `child: string`, `frame: Transform`, `axis: Vec3`, `min?: number`, `max?: number`, `defaultValue: number`, `unit?: string`, `effort?: number`, `velocity?: number`, `damping?: number`, `friction?: number`
211
144
 
212
- </details>
145
+ `AssemblyJointCouplingDef`: `{ joint: string, terms: JointCouplingTermRecord[], offset: number }`
213
146
 
214
- <details><summary><code>AssemblyJointDef</code></summary>
147
+ `JointCouplingTermRecord`: `{ joint: string, ratio: number }`
215
148
 
216
- ```ts
217
- interface AssemblyJointDef {
218
- name: string;
219
- type: JointType;
220
- parent: string;
221
- child: string;
222
- frame: Transform;
223
- axis: Vec3;
224
- min?: number;
225
- max?: number;
226
- defaultValue: number;
227
- unit?: string;
228
- effort?: number;
229
- velocity?: number;
230
- damping?: number;
231
- friction?: number;
232
- }
233
- ```
234
-
235
- </details>
149
+ #### `dim()` — Add a dimension annotation between two points.
236
150
 
237
- <details><summary><code>AssemblyJointCouplingDef</code></summary>
151
+ Dimension annotations are purely visual callouts rendered in the viewport and report export. They do not affect geometry or constrain the model.
238
152
 
239
- ```ts
240
- interface AssemblyJointCouplingDef {
241
- joint: string;
242
- terms: JointCouplingTermRecord[];
243
- offset: number;
244
- }
245
- ```
153
+ Point arguments accept 2D tuples `[x, y]`, 3D tuples `[x, y, z]`, or [`Point2D`](/docs/sketch#point2d) objects (Z is treated as 0 for 2D inputs).
246
154
 
247
- </details>
155
+ **Ownership Rules (Report Pages)**
248
156
 
249
- <details><summary><code>JointCouplingTermRecord</code></summary>
157
+ - `currentComponent: true` — deterministic ownership by the calling import instance. Use when authoring reusable imported parts.
158
+ - `component: "Part Name"` — route dimension to another named returned object.
159
+ - Multiple owners: dimension is shared and appears on the assembly overview page.
160
+ - No ownership set: report export infers ownership via endpoint-in-bbox.
250
161
 
251
162
  ```ts
252
- interface JointCouplingTermRecord {
253
- joint: string;
254
- ratio: number;
255
- }
163
+ dim([-w / 2, 0, 0], [w / 2, 0, 0], { label: "Width" });
164
+ dim([0, 0, -h / 2], [0, 0, h / 2], { label: "Height", offset: 14 });
165
+ dim([0, 0, 0], [100, 0, 0], { component: "Base", color: "#00AAFF" });
256
166
  ```
257
167
 
258
- </details>
259
-
260
- #### `dim()`
168
+ `component` (string or string[] — report ownership), `currentComponent` (boolean)
261
169
 
262
170
  ```ts
263
- dim(from: PointArg$1, to: PointArg$1, opts?: DimOpts): void
171
+ dim(from: PointArg, to: PointArg, opts?: DimOpts): void
264
172
  ```
265
173
 
266
- Add a dimension annotation between two points.
174
+ `DimOpts`: `{ offset?: number, label?: string, color?: string, component?: string | string[], currentComponent?: boolean }`
175
+
176
+ #### `dimLine()` — Add a dimension annotation along a [`Line2D`](/docs/sketch#line2d).
267
177
 
268
- <details><summary><code>DimOpts</code></summary>
178
+ Convenience wrapper around { points from a constrained-sketch [`Line2D`](/docs/sketch#line2d) entity. All `opts` are forwarded unchanged.
269
179
 
270
180
  ```ts
271
- interface DimOpts {
272
- offset?: number;
273
- label?: string;
274
- color?: string;
275
- component?: string | string[];
276
- currentComponent?: boolean;
277
- }
181
+ const a = point(0, 0);
182
+ const b = point(100, 0);
183
+ dimLine(line(a, b), { label: "Span", offset: -8 });
278
184
  ```
279
185
 
280
- </details>
281
-
282
- #### `dimLine()`
283
-
284
186
  ```ts
285
187
  dimLine(l: Line2D, opts?: DimOpts): void
286
188
  ```
287
189
 
288
- Add a dimension annotation along a Line2D.
289
-
290
190
  ### Sketch Export
291
191
 
292
- Export 2D sketches to SVG or DXF format strings.
192
+ #### `sketchToDxf()` — Export a 2D sketch as a DXF string (R12/AC1009 — maximally compatible).
293
193
 
294
- #### `sketchToDxf()`
194
+ For regular sketches, each polygon loop becomes a closed `LWPOLYLINE`. For constrained sketches, exports raw `LINE`, `CIRCLE`, and `ARC` entities from the constraint edge geometry, which preserves internal/shared edges that `toPolygons()` would merge away.
195
+
196
+ The R12 format is chosen for maximum compatibility with CAM tools, laser-cutter software, and older CAD readers.
295
197
 
296
198
  ```ts
297
- sketchToDxf(sketch: Sketch, options?: SketchDxfOptions): string
199
+ const s = rect(100, 60);
200
+ const dxf = sketchToDxf(s, { layer: 'cut' });
298
201
  ```
299
202
 
300
- Export a 2D sketch as a DXF string (R12/AC1009 — maximally compatible). For regular sketches, each polygon loop becomes a closed LWPOLYLINE. For constraint sketches, exports LINE, CIRCLE, and ARC entities from the constraint edge geometry.
301
-
302
- <details><summary><code>SketchDxfOptions</code></summary>
303
-
304
203
  ```ts
305
- interface SketchDxfOptions {
306
- /** DXF layer name. Default: "0" */
307
- layer?: string;
308
- /** DXF color index (1–255, AutoCAD ACI). Default: 7 (white/black) */
309
- colorIndex?: number;
310
- }
204
+ sketchToDxf(sketch: Sketch, options?: SketchDxfOptions): string
311
205
  ```
312
206
 
313
- </details>
207
+ **`SketchDxfOptions`**
208
+ - `layer?: string` — DXF layer name. Default: "0"
209
+ - `colorIndex?: number` — DXF color index (1–255, AutoCAD ACI). Default: 7 (white/black)
314
210
 
315
- #### `sketchToSvg()`
211
+ #### `sketchToSvg()` — Export a 2D sketch as an SVG string.
316
212
 
317
- ```ts
318
- sketchToSvg(sketch: Sketch, options?: SketchSvgOptions): string
319
- ```
213
+ For regular sketches, exports filled polygon regions. For constrained sketches, exports raw edge geometry (LINE, ARC, CIRCLE) which preserves internal/shared edges that `toPolygons()` would merge away.
320
214
 
321
- Export a 2D sketch as an SVG string. For regular sketches, exports filled polygon regions. For constraint sketches, exports line/arc/circle edge geometry. The SVG uses the sketch's native coordinate system (Y-up) with a transform that flips Y so the output renders correctly in SVG's Y-down space. Coordinates are in sketch units (typically mm).
215
+ The SVG uses the sketch's native coordinate system (Y-up) with a CSS transform that flips Y so the output renders correctly in SVG's Y-down space. Coordinates are in sketch units (typically mm).
322
216
 
323
- <details><summary><code>SketchSvgOptions</code></summary>
217
+ ```ts
218
+ const s = rect(100, 60);
219
+ const svg = sketchToSvg(s, { stroke: '#333', strokeWidth: 0.8 });
220
+ ```
324
221
 
325
222
  ```ts
326
- interface SketchSvgOptions {
327
- /** Stroke color. Default: "black" */
328
- stroke?: string;
329
- /** Stroke width in sketch units. Default: 0.5 */
330
- strokeWidth?: number;
331
- /** Fill color. Default: "none" */
332
- fill?: string;
333
- /** Padding around the sketch bounding box in sketch units. Default: 2 */
334
- padding?: number;
335
- /** If set, scale so 1 sketch-unit = this many px. Otherwise auto-fit. */
336
- pixelsPerUnit?: number;
337
- }
223
+ sketchToSvg(sketch: Sketch, options?: SketchSvgOptions): string
338
224
  ```
339
225
 
340
- </details>
226
+ **`SketchSvgOptions`**
227
+
228
+ | Option | Type | Description |
229
+ |--------|------|-------------|
230
+ | `stroke?` | `string` | Stroke color. Default: "black" |
231
+ | `strokeWidth?` | `number` | Stroke width in sketch units. Default: 0.5 |
232
+ | `fill?` | `string` | Fill color. Default: "none" |
233
+ | `padding?` | `number` | Padding around the sketch bounding box in sketch units. Default: 2 |
234
+ | `pixelsPerUnit?` | `number` | If set, scale so 1 sketch-unit = this many px. Otherwise auto-fit. |
@@ -0,0 +1,208 @@
1
+ ---
2
+ skill-group: sdf
3
+ skill-order: 100
4
+ ---
5
+
6
+ # SDF Modeling (Experimental)
7
+
8
+ Signed Distance Field modeling for organic forms, smooth booleans, TPMS lattices, and deformations. Access via `sdf.*`. Experimental — slower render times and lower mesh quality than B-rep.
9
+
10
+ ## Contents
11
+
12
+ - [SdfShape](#sdfshape)
13
+ - [sdf](#sdf)
14
+
15
+ ---
16
+
17
+ ## Classes
18
+
19
+ ### `SdfShape`
20
+
21
+ An immutable SDF expression. Supports SDF-specific operations (smooth booleans, domain warps, etc.) and converts to a ForgeCAD Shape via `.toShape()`.
22
+
23
+ #### `toShape()` — Mesh this SDF into a ForgeCAD Shape via Manifold.levelSet(). Once converted, the result is a regular Shape — booleans, transforms, export all work.
24
+
25
+ ```ts
26
+ toShape(options?: SdfToShapeOptions): Shape
27
+ ```
28
+
29
+ #### [`union()`](/docs/core#union) — SDF union (sharp).
30
+
31
+ ```ts
32
+ union(...others: SdfShape[]): SdfShape
33
+ ```
34
+
35
+ #### `subtract()` — SDF difference (sharp) — subtracts others from this.
36
+
37
+ ```ts
38
+ subtract(...others: SdfShape[]): SdfShape
39
+ ```
40
+
41
+ #### `intersect()` — SDF intersection (sharp).
42
+
43
+ ```ts
44
+ intersect(...others: SdfShape[]): SdfShape
45
+ ```
46
+
47
+ #### `smoothUnion()` — Smooth union — blends shapes together with a smooth radius.
48
+
49
+ ```ts
50
+ smoothUnion(other: SdfShape, radius: number): SdfShape
51
+ ```
52
+
53
+ #### `smoothSubtract()` — Smooth difference — smoothly carves other from this.
54
+
55
+ ```ts
56
+ smoothSubtract(other: SdfShape, radius: number): SdfShape
57
+ ```
58
+
59
+ #### `smoothIntersect()` — Smooth intersection — smoothly intersects.
60
+
61
+ ```ts
62
+ smoothIntersect(other: SdfShape, radius: number): SdfShape
63
+ ```
64
+
65
+ #### `morph()` — Morph between this shape and another. t=0 → this, t=1 → other.
66
+
67
+ ```ts
68
+ morph(other: SdfShape, t: number): SdfShape
69
+ ```
70
+
71
+ #### `translate()`
72
+
73
+ ```ts
74
+ translate(x: number, y: number, z: number): SdfShape
75
+ ```
76
+
77
+ #### `rotate()` — Rotate around an arbitrary axis through the origin.
78
+
79
+ ```ts
80
+ rotate(axis: [ number, number, number ], angleDeg: number): SdfShape
81
+ ```
82
+
83
+ #### `rotateX()` — Rotate around the X axis by the given angle in degrees.
84
+
85
+ ```ts
86
+ rotateX(angleDeg: number): SdfShape
87
+ ```
88
+
89
+ #### `rotateY()` — Rotate around the Y axis by the given angle in degrees.
90
+
91
+ ```ts
92
+ rotateY(angleDeg: number): SdfShape
93
+ ```
94
+
95
+ #### `rotateZ()` — Rotate around the Z axis by the given angle in degrees.
96
+
97
+ ```ts
98
+ rotateZ(angleDeg: number): SdfShape
99
+ ```
100
+
101
+ #### `scale()`
102
+
103
+ ```ts
104
+ scale(factor: number): SdfShape
105
+ ```
106
+
107
+ #### `twist()` — Twist around the Z axis.
108
+
109
+ ```ts
110
+ twist(degreesPerUnit: number): SdfShape
111
+ ```
112
+
113
+ #### `bend()` — Bend around the Z axis with given radius.
114
+
115
+ ```ts
116
+ bend(radius: number): SdfShape
117
+ ```
118
+
119
+ #### `repeat()` — Repeat in space. Spacing of 0 on an axis means no repetition. Count of 0 = infinite.
120
+
121
+ ```ts
122
+ repeat(spacing: Vec3, count?: Vec3): SdfShape
123
+ ```
124
+
125
+ #### `shell()` — Hollow out, keeping only a shell of given thickness.
126
+
127
+ ```ts
128
+ shell(thickness: number): SdfShape
129
+ ```
130
+
131
+ #### `displace()` — Displace the surface by a function of position, or by a pattern SdfShape.
132
+
133
+ ```js
134
+ // Function displacement
135
+ shape.displace((x, y, z) => Math.sin(x) * 0.5)
136
+
137
+ // Pattern displacement (e.g. basketWeave)
138
+ shape.displace(sdf.basketWeave({ threads: 16, spacing: 3 }))
139
+ ```
140
+
141
+ ```ts
142
+ displace(fn: ((x: number, y: number, z: number) => number) | SdfShape, constants?: Record<string, number>): SdfShape
143
+ ```
144
+
145
+ #### `surfaceDisplace()` — Displace the surface using a 2D pattern in surface-local UV coordinates.
146
+
147
+ Automatically detects the shape's UV parametrization (sphere, cylinder, torus) from the SDF tree. Falls back to triplanar mapping for arbitrary shapes.
148
+
149
+ UV coordinates are in **surface millimeters** — patterns defined with `spacing: 3` always produce 3mm spacing, regardless of shape size.
150
+
151
+ ```js
152
+ // Surface-following basket weave — auto-detects sphere UV
153
+ sdf.sphere(27).shell(3)
154
+ .surfaceDisplace(sdf.basketWeave({ spacing: 3, depth: 0.8 }))
155
+ .toShape()
156
+
157
+ // Custom 2D pattern via function
158
+ shape.surfaceDisplace((u, v) => -Math.sin(u * 2) * 0.3)
159
+ ```
160
+
161
+ ```ts
162
+ surfaceDisplace(pattern: SurfacePattern | ((u: number, v: number) => number), options?: SurfaceDisplaceOptions): SdfShape
163
+ ```
164
+
165
+ #### `onion()` — Create concentric onion layers.
166
+
167
+ ```ts
168
+ onion(layers: number, thickness: number): SdfShape
169
+ ```
170
+
171
+ ---
172
+
173
+ ## Constants
174
+
175
+ ### `sdf`
176
+
177
+ SDF modeling — signed distance field primitives, smooth booleans, TPMS lattices, domain warps, and surface patterns. **Experimental.** Slower render times and lower mesh quality than B-rep. Use for organic forms, smooth blending, or TPMS lattices where these trade-offs are acceptable. For mechanical parts, prefer B-rep. All shapes live as a lazy expression tree until `.toShape()` is called, which meshes them via `Manifold.levelSet()` and returns a regular Shape. ```js const shape = sdf.smoothUnion(sdf.sphere(10), sdf.box(15, 15, 15), { radius: 3 }) .toShape({ edgeLength: 0.5 }) .color('#4488cc'); ```
178
+
179
+ - `sphere(radius: number): SdfShape` — Create an SDF sphere centered at the origin.
180
+ - `box(x: number, y: number, z: number): SdfShape` — Create an SDF box centered at the origin with given full dimensions (not half-extents).
181
+ - `cylinder(height: number, radius: number): SdfShape` — Create an SDF cylinder centered at the origin, axis along Z.
182
+ - `torus(majorRadius: number, minorRadius: number): SdfShape` — Create an SDF torus centered at the origin, lying in the XY plane.
183
+ - `capsule(height: number, radius: number): SdfShape` — Create an SDF capsule centered at the origin, axis along Z.
184
+ - `cone(height: number, radius: number): SdfShape` — Create an SDF cone with base at z=0 and tip at z=height.
185
+ - `smoothUnion(a: SdfShape, b: SdfShape, options: { radius: number; }): SdfShape` — Smooth union — blends shapes together with a smooth transition radius.
186
+ - `smoothDifference(a: SdfShape, b: SdfShape, options: { radius: number; }): SdfShape` — Smooth difference — smoothly subtracts b from a.
187
+ - `smoothIntersection(a: SdfShape, b: SdfShape, options: { radius: number; }): SdfShape` — Smooth intersection — smoothly intersects a and b.
188
+ - `morph(a: SdfShape, b: SdfShape, t: number): SdfShape` — Morph between two SDF shapes. t=0 → a, t=1 → b.
189
+ - `blend(a: SdfShape, b: SdfShape, fn: (x: number, y: number, z: number) => number, options?: BlendOptions): SdfShape` — Spatially blend between two SDF patterns. The blend function receives (x, y, z) and returns 0..1: 0 = fully pattern `a`, 1 = fully pattern `b`.
190
+ - `gyroid(options: TpmsOptions): SdfShape` — Gyroid TPMS lattice — the most common lattice for additive manufacturing.
191
+ - `schwarzP(options: TpmsOptions): SdfShape` — Schwarz-P TPMS lattice — isotropic pore structure.
192
+ - `diamond(options: TpmsOptions): SdfShape` — Diamond TPMS lattice — stiffest TPMS structure.
193
+ - `lidinoid(options: TpmsOptions): SdfShape` — Lidinoid TPMS lattice — visually distinct from gyroid, popular in research and art.
194
+ - `noise(options?: NoiseOptions): SdfShape` — 3D Simplex noise field — produces organic, natural-looking displacements.
195
+ - `voronoi(options?: VoronoiOptions): SdfShape` — 3D Voronoi pattern — organic cellular structures like bone, coral, or soap bubbles.
196
+ - `honeycomb(options?: HoneycombOptions): SdfShape` — Honeycomb (hexagonal) lattice pattern. Intersect with your shape to apply.
197
+ - `waves(options?: WavesOptions): SdfShape` — Sinusoidal wave ridges — parallel ridges along an axis.
198
+ - `knurl(options?: KnurlOptions): SdfShape` — Knurl pattern — crossed helical grooves for grips and handles.
199
+ - `perforated(options?: PerforatedOptions): SdfShape` — Perforated plate pattern — regular array of cylindrical holes.
200
+ - `scales(options?: ScalesOptions): SdfShape` — Fish/dragon scale pattern — overlapping circular scales in hex-packed rows.
201
+ - `brick(options?: BrickOptions): SdfShape` — Brick/stone wall pattern — running bond with mortar grooves.
202
+ - `weave(options?: WeaveOptions): SdfShape` — Grid lattice pattern — two families of infinite slabs crossing at 90°.
203
+ - `basketWeave(options?: BasketWeaveOptions): SurfacePattern` — Basket weave surface pattern — threads with over-under crossings in UV space. Returns a SurfacePattern for use with `.surfaceDisplace()`.
204
+ - `twist(shape: SdfShape, degreesPerUnit: number): SdfShape` — Twist an SDF shape around the Z axis.
205
+ - `bend(shape: SdfShape, radius: number): SdfShape` — Bend an SDF shape around the Z axis.
206
+ - `repeat(shape: SdfShape, spacing: Vec3, count?: Vec3): SdfShape` — Repeat an SDF shape in space.
207
+ - `SurfacePattern: typeof SurfacePattern` — A 2D surface pattern — a heightmap function for use with `.surfaceDisplace()`.
208
+ - `fromFunction(fn: (x: number, y: number, z: number) => number, bounds: { min: Vec3; max: Vec3; }, constants?: Record<string, number>): SdfShape` — Create an SDF shape from an arbitrary distance function. You must provide bounds since the function is opaque.