forgecad 0.6.3 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (234) hide show
  1. package/README.md +3 -12
  2. package/dist/assets/{AdminPage-CeqCUUgu.js → AdminPage-D4bocK4E.js} +250 -151
  3. package/dist/assets/{BlogPage-P_AJP0v9.js → BlogPage-CJEXL_zJ.js} +94 -70
  4. package/dist/assets/{DocsPage-CKRV2iq2.js → DocsPage-D3A_g8V3.js} +329 -163
  5. package/dist/assets/{EditorApp-CnC2k4cW.css → EditorApp-BWYUSpUN.css} +590 -136
  6. package/dist/assets/EditorApp-Cihhqcsq.js +11692 -0
  7. package/dist/assets/{EmbedViewer-DBlzmQ5i.js → EmbedViewer-kWjKaC_t.js} +2 -4
  8. package/dist/assets/LandingPageProofDriven-Bg2IUc3l.css +856 -0
  9. package/dist/assets/LandingPageProofDriven-DXkKlyhI.js +601 -0
  10. package/dist/assets/PricingPage-BsU5vzEx.js +232 -0
  11. package/dist/assets/{SettingsPage-BqCh9JcC.js → SettingsPage-PqvpAKIs.js} +129 -5
  12. package/dist/assets/{evalWorker-Ql-aKwLA.js → evalWorker-C-hzNUMy.js} +8949 -3161
  13. package/dist/assets/{Viewport-CoB46f5R.js → index-Pz321YAt.js} +38382 -7501
  14. package/dist/assets/{index-2hfs_ub0.css → index-ay13WNfa.css} +726 -53
  15. package/dist/assets/{javascript-DCxGoE5Y.js → javascript-DAl8Gmyo.js} +1 -1
  16. package/dist/assets/{manifold-CqNMHHKO.js → manifold-BcbjWLIo.js} +4 -3
  17. package/dist/assets/{manifold-Cce9wRFz.js → manifold-DBckbFgx.js} +1 -1
  18. package/dist/assets/{manifold-D6BeHIOo.js → manifold-O2AAGXyj.js} +1 -1
  19. package/dist/assets/{reportWorker-sFEFonXf.js → reportWorker-Dxr-5A7w.js} +8760 -3559
  20. package/dist/assets/{vendor-react-Dt7-aaJH.js → vendor-react-CG3i_wp0.js} +65 -8
  21. package/dist/docs/index.html +2 -2
  22. package/dist/docs-raw/CLI.md +341 -718
  23. package/dist/docs-raw/generated/assembly.md +699 -112
  24. package/dist/docs-raw/generated/concepts.md +1834 -1346
  25. package/dist/docs-raw/generated/core.md +1012 -1059
  26. package/dist/docs-raw/generated/curves.md +759 -116
  27. package/dist/docs-raw/generated/lib.md +43 -748
  28. package/dist/docs-raw/generated/output.md +139 -245
  29. package/dist/docs-raw/generated/sdf.md +208 -0
  30. package/dist/docs-raw/generated/sheet-metal.md +473 -21
  31. package/dist/docs-raw/generated/sketch.md +1518 -362
  32. package/dist/docs-raw/generated/viewport.md +368 -299
  33. package/dist/docs-raw/generated/wood.md +104 -0
  34. package/dist/index.html +2 -2
  35. package/dist/landing/proof-ams-adapter.png +0 -0
  36. package/dist/landing/proof-bolt-and-nut.png +0 -0
  37. package/dist/landing/proof-fillet-enclosure.png +0 -0
  38. package/dist/landing/proof-glasses.png +0 -0
  39. package/dist/landing/proof-gyroid.png +0 -0
  40. package/dist/sitemap.xml +6 -6
  41. package/dist-cli/forgecad.js +12321 -5700
  42. package/dist-cli/forgecad.js.map +1 -0
  43. package/dist-cli/solver-46FFSK2U.js +363 -0
  44. package/dist-cli/solver-46FFSK2U.js.map +1 -0
  45. package/dist-skill/CONTEXT.md +4890 -6302
  46. package/dist-skill/SKILL-dev.md +22 -66
  47. package/dist-skill/SKILL.md +20 -59
  48. package/dist-skill/docs/API/core/concepts.md +37 -92
  49. package/dist-skill/docs/CLI.md +341 -718
  50. package/dist-skill/docs/generated/assembly.md +699 -112
  51. package/dist-skill/docs/generated/core.md +1012 -1059
  52. package/dist-skill/docs/generated/curves.md +759 -116
  53. package/dist-skill/docs/generated/lib.md +43 -748
  54. package/dist-skill/docs/generated/output.md +139 -245
  55. package/dist-skill/docs/generated/sdf.md +208 -0
  56. package/dist-skill/docs/generated/sheet-metal.md +473 -21
  57. package/dist-skill/docs/generated/sketch.md +1518 -362
  58. package/dist-skill/docs/generated/viewport.md +368 -299
  59. package/dist-skill/docs/generated/wood.md +104 -0
  60. package/dist-skill/docs/guides/coordinate-system.md +11 -17
  61. package/dist-skill/docs/guides/geometry-conventions.md +13 -70
  62. package/dist-skill/docs/guides/joint-design.md +78 -0
  63. package/dist-skill/docs/guides/modeling-recipes.md +22 -195
  64. package/dist-skill/docs/guides/positioning.md +88 -147
  65. package/dist-skill/docs-dev/API/core/concepts.md +78 -0
  66. package/dist-skill/docs-dev/CLI.md +488 -0
  67. package/dist-skill/{docs → docs-dev}/blueprint-first.md +5 -0
  68. package/dist-skill/{docs → docs-dev}/coding-best-practices.md +6 -8
  69. package/dist-skill/{docs → docs-dev}/coding.md +2 -4
  70. package/dist-skill/docs-dev/component-model.md +164 -0
  71. package/dist-skill/docs-dev/generated/assembly.md +779 -0
  72. package/dist-skill/docs-dev/generated/core.md +1676 -0
  73. package/dist-skill/docs-dev/generated/curves.md +855 -0
  74. package/dist-skill/docs-dev/generated/lib.md +55 -0
  75. package/dist-skill/docs-dev/generated/output.md +234 -0
  76. package/dist-skill/docs-dev/generated/sdf.md +208 -0
  77. package/dist-skill/docs-dev/generated/sheet-metal.md +506 -0
  78. package/dist-skill/docs-dev/generated/sketch.md +1753 -0
  79. package/dist-skill/docs-dev/generated/viewport.md +513 -0
  80. package/dist-skill/docs-dev/generated/wood.md +104 -0
  81. package/dist-skill/docs-dev/guides/coordinate-system.md +46 -0
  82. package/dist-skill/docs-dev/guides/geometry-conventions.md +52 -0
  83. package/dist-skill/docs-dev/guides/joint-design.md +78 -0
  84. package/dist-skill/docs-dev/guides/modeling-recipes.md +77 -0
  85. package/dist-skill/docs-dev/guides/positioning.md +151 -0
  86. package/dist-skill/{docs → docs-dev}/guides/skill-maintenance.md +21 -10
  87. package/dist-skill/{docs → docs-dev}/internals/compiler.md +5 -6
  88. package/dist-skill/{docs → docs-dev}/internals/constraint-solver-quality.md +0 -1
  89. package/dist-skill/{docs → docs-dev}/internals/constraint-solver.md +0 -1
  90. package/dist-skill/{docs → docs-dev}/internals/sketch-2d-pipeline.md +2 -3
  91. package/examples/api/attachTo-basics.forge.js +8 -8
  92. package/examples/api/bill-of-materials.forge.js +9 -9
  93. package/examples/api/bolt-pattern.forge.js +5 -5
  94. package/examples/api/boolean-operations.forge.js +5 -5
  95. package/examples/api/bounding-box-visualizer.forge.js +3 -3
  96. package/examples/api/clone-duplicate.forge.js +2 -2
  97. package/examples/api/colors-union-vs-array.forge.js +6 -6
  98. package/examples/api/connector-assembly.forge.js +8 -6
  99. package/examples/api/connector-basics.forge.js +7 -7
  100. package/examples/api/constrained-sketch-mechanical.forge.js +4 -4
  101. package/examples/api/elbow-test.forge.js +3 -3
  102. package/examples/api/extrude-options.forge.js +8 -14
  103. package/examples/api/feature-created-faces.forge.js +6 -10
  104. package/examples/api/fillet-showcase.forge.js +2 -2
  105. package/examples/api/folded-service-panel-cover.forge.js +2 -2
  106. package/examples/api/gears-tier1.forge.js +5 -5
  107. package/examples/api/group-test.forge.js +3 -3
  108. package/examples/api/group-vs-union.forge.js +1 -1
  109. package/examples/api/highlight-debug.forge.js +4 -0
  110. package/examples/api/js-module-pillars.js +1 -1
  111. package/examples/api/js-module-scene.js +2 -2
  112. package/examples/api/mesh-import-slats.forge.js +4 -4
  113. package/examples/api/patterns.forge.js +3 -3
  114. package/examples/api/pointAlong-orientation.forge.js +3 -3
  115. package/examples/api/profile-2020-b-slot6.forge.js +4 -5
  116. package/examples/api/route-perimeter-flange.forge.js +1 -1
  117. package/examples/api/sdf-rover-demo.forge.js +10 -10
  118. package/examples/api/sketch-on-face-demo.forge.js +2 -2
  119. package/examples/api/sketch-regions.forge.js +4 -4
  120. package/examples/api/sketch-rounding-strategies.forge.js +1 -1
  121. package/examples/api/smooth-curve-connections.forge.js +1 -1
  122. package/examples/api/transition-curves.forge.js +4 -4
  123. package/examples/api/variable-sweep-pure-sdf-test.forge.js +162 -0
  124. package/examples/api/variable-sweep-test.forge.js +2 -2
  125. package/examples/api/wood-joinery.forge.js +60 -0
  126. package/examples/compiler-corpus/enclosure-shell-cuts.forge.js +3 -3
  127. package/examples/compiler-corpus/fastener-plate-variants.forge.js +2 -2
  128. package/examples/constraints/01-fully-constrained-rect.forge.js +2 -2
  129. package/examples/constraints/02-underconstrained-triangle.forge.js +1 -1
  130. package/examples/constraints/03-redundant-constraints.forge.js +2 -2
  131. package/examples/constraints/05-parallel-with-linedistance.forge.js +2 -2
  132. package/examples/constraints/06-complex-spectrogram.forge.js +1 -1
  133. package/examples/constraints/07-perpendicular-chain.forge.js +4 -4
  134. package/examples/constraints/08-symmetric-bracket.forge.js +4 -4
  135. package/examples/constraints/09-stress-spiral.forge.js +1 -1
  136. package/examples/constraints/10-stress-honeycomb.forge.js +1 -1
  137. package/examples/constraints/11-surface-grid.forge.js +2 -2
  138. package/examples/constraints/12-surface-nested.forge.js +4 -4
  139. package/examples/constraints/13-surface-complex.forge.js +1 -1
  140. package/examples/exact-arc-housing.forge.js +12 -0
  141. package/examples/experiments/drone-arm.forge.js +53 -0
  142. package/examples/furniture/adjustable-table.forge.js +15 -15
  143. package/examples/furniture/bathroom.forge.js +26 -26
  144. package/examples/furniture/chair.forge.js +13 -13
  145. package/examples/furniture/picture-frame.forge.js +6 -6
  146. package/examples/furniture/shoe-rack-doors.forge.js +8 -8
  147. package/examples/furniture/shoe-rack.forge.js +7 -7
  148. package/examples/furniture/table-lamp.forge.js +8 -8
  149. package/examples/gcode/lissajous-vase.forge.js +4 -4
  150. package/examples/gcode/math-surface.forge.js +3 -3
  151. package/examples/gcode/parametric-vase.forge.js +4 -4
  152. package/examples/gcode/spiral-tower.forge.js +4 -4
  153. package/examples/generative/crystal-growth.forge.js +9 -9
  154. package/examples/generative/frost-spires.forge.js +9 -9
  155. package/examples/generative/golden-spiral-tower.forge.js +11 -11
  156. package/examples/generative/molten-forge.forge.js +6 -6
  157. package/examples/generative/neon-coral.forge.js +7 -7
  158. package/examples/mechanical/3d-printer.forge.js +37 -37
  159. package/examples/mechanical/5-finger-robot-hand.forge.js +19 -19
  160. package/examples/mechanical/airplane-propeller.forge.js +9 -9
  161. package/examples/mechanical/bolt-and-nut.forge.js +10 -10
  162. package/examples/mechanical/door-with-hinges.forge.js +7 -7
  163. package/examples/mechanical/fillet-enclosure.forge.js +15 -11
  164. package/examples/mechanical/headphone-hanger-v2.forge.js +11 -11
  165. package/examples/mechanical/robot_hand.forge.js +24 -24
  166. package/examples/mechanical/robot_hand_2.forge.js +26 -26
  167. package/examples/nurbs-surface.forge.js +8 -0
  168. package/examples/nurbs-tube.forge.js +7 -0
  169. package/examples/products/bottle.forge.js +8 -8
  170. package/examples/products/chess-set.forge.js +25 -25
  171. package/examples/products/classical-piano.forge.js +20 -20
  172. package/examples/products/clock.forge.js +33 -33
  173. package/examples/products/cup.forge.js +5 -5
  174. package/examples/products/iphone.forge.js +20 -20
  175. package/examples/products/laptop.forge.js +24 -24
  176. package/examples/products/laser-cut-box.forge.js +6 -6
  177. package/examples/products/laser-cut-tray.forge.js +6 -6
  178. package/examples/products/liquid-soap-dispenser.forge.js +23 -23
  179. package/examples/products/origami-fish.forge.js +14 -12
  180. package/examples/products/spiderman-cake.forge.js +6 -6
  181. package/examples/shelf/container.forge.js +5 -5
  182. package/examples/shelf/shelf-unit.forge.js +6 -6
  183. package/examples/toolbox/bolted-joint.forge.js +7 -7
  184. package/package.json +9 -4
  185. package/dist/assets/EditorApp-B-vQvgam.js +0 -9888
  186. package/dist/assets/LandingPage-C5n9hDXI.js +0 -322
  187. package/dist/assets/PublishedModelPage-Dt7PCVBj.js +0 -146
  188. package/dist/assets/__vite-browser-external-CURh0WXD.js +0 -8
  189. package/dist/assets/deserializeRunResult-BLAFoiE0.js +0 -19365
  190. package/dist/assets/index-1CYp3zUp.js +0 -1455
  191. package/dist-skill/docs/API/API.md +0 -1666
  192. package/dist-skill/docs/API/README.md +0 -37
  193. package/dist-skill/docs/API/assembly/assembly.md +0 -617
  194. package/dist-skill/docs/API/core/edge-queries.md +0 -130
  195. package/dist-skill/docs/API/core/parameters.md +0 -122
  196. package/dist-skill/docs/API/core/reserved-terms.md +0 -137
  197. package/dist-skill/docs/API/core/sdf.md +0 -326
  198. package/dist-skill/docs/API/core/skill-cli.md +0 -194
  199. package/dist-skill/docs/API/core/skill-guide.md +0 -205
  200. package/dist-skill/docs/API/core/specs.md +0 -186
  201. package/dist-skill/docs/API/core/topology.md +0 -372
  202. package/dist-skill/docs/API/entities.md +0 -268
  203. package/dist-skill/docs/API/output/bom.md +0 -58
  204. package/dist-skill/docs/API/output/brep-export.md +0 -87
  205. package/dist-skill/docs/API/output/dimensions.md +0 -67
  206. package/dist-skill/docs/API/output/export.md +0 -110
  207. package/dist-skill/docs/API/output/gcode.md +0 -195
  208. package/dist-skill/docs/API/runtime/viewport.md +0 -420
  209. package/dist-skill/docs/API/sheet-metal/sheet-metal.md +0 -185
  210. package/dist-skill/docs/API/sketch/anchor.md +0 -37
  211. package/dist-skill/docs/API/sketch/booleans.md +0 -91
  212. package/dist-skill/docs/API/sketch/core.md +0 -73
  213. package/dist-skill/docs/API/sketch/extrude.md +0 -62
  214. package/dist-skill/docs/API/sketch/on-face.md +0 -104
  215. package/dist-skill/docs/API/sketch/operations.md +0 -78
  216. package/dist-skill/docs/API/sketch/path.md +0 -75
  217. package/dist-skill/docs/API/sketch/primitives.md +0 -146
  218. package/dist-skill/docs/API/sketch/regions.md +0 -80
  219. package/dist-skill/docs/API/sketch/text.md +0 -108
  220. package/dist-skill/docs/API/sketch/transforms.md +0 -65
  221. package/dist-skill/docs/API/toolbox/fasteners.md +0 -129
  222. package/dist-skill/docs/INDEX.md +0 -94
  223. package/dist-skill/docs/RELEASING.md +0 -55
  224. package/dist-skill/docs/cli-monetization.md +0 -111
  225. package/dist-skill/docs/deployment.md +0 -281
  226. package/dist-skill/docs/generated/concepts.md +0 -2112
  227. package/dist-skill/docs/internals/shape-from-slices.md +0 -152
  228. package/dist-skill/docs/platform/admin.md +0 -45
  229. package/dist-skill/docs/platform/architecture.md +0 -79
  230. package/dist-skill/docs/platform/auth.md +0 -110
  231. package/dist-skill/docs/platform/email.md +0 -67
  232. package/dist-skill/docs/platform/projects.md +0 -111
  233. package/dist-skill/docs/platform/sharing.md +0 -90
  234. package/dist-skill/docs/runbook.md +0 -345
@@ -1,2112 +0,0 @@
1
- # API by Concept
2
-
3
- > **Auto-generated** from `@concept` tags in `src/forge/forge-public-api.ts`. Do not edit by hand — run `npm run gen:docs` to regenerate.
4
-
5
- Every public API function belongs to one of 16 fundamental concepts. This document groups them by concept rather than by module, making it easy to see the full set of operations for each idea.
6
-
7
- ## Concepts
8
-
9
- - **[C1: Primitive Construction](#c1-primitive-construction)** — Create geometry from parameters — no input geometry required. *(19 functions)*
10
- - **[C2: Boolean Combination](#c2-boolean-combination)** — Combine same-dimension geometry using CSG set operations. *(3 functions)*
11
- - **[C3: Rigid Transform](#c3-rigid-transform)** — Reposition or reorient geometry without changing its shape. *(3 functions)*
12
- - **[C4: Dimensional Promotion](#c4-dimensional-promotion)** — Convert a 2D profile into a 3D solid (extrude, revolve, loft, sweep). *(12 functions)*
13
- - **[C5: Topology Query](#c5-topology-query)** — Select or inspect named faces and edges on a shape. *(3 functions)*
14
- - **[C6: Edge Feature](#c6-edge-feature)** — Modify edges of a solid — fillets, chamfers, draft, offset. *(7 functions)*
15
- - **[C7: Pattern Replication](#c7-pattern-replication)** — Duplicate geometry in regular arrangements (linear, circular, mirror). *(6 functions)*
16
- - **[C8: Constraint Solving](#c8-constraint-solving)** — Define geometry by relationships and let a solver find positions. *(7 functions)*
17
- - **[C9: Spatial Placement](#c9-spatial-placement)** — Position geometry relative to other geometry using semantic anchors. *(0 functions)*
18
- - **[C10: Assembly & Kinematics](#c10-assembly-kinematics)** — Compose parts with joints for kinematic simulation. *(4 functions)*
19
- - **[C11: Parameterization & UI](#c11-parameterization-ui)** — Declare user-facing controls that drive model geometry. *(6 functions)*
20
- - **[C12: Dimensional Demotion](#c12-dimensional-demotion)** — Extract 2D geometry from a 3D solid (section, projection). *(3 functions)*
21
- - **[C13: Export & Output](#c13-export-output)** — Convert geometry to external formats (STL, 3MF, SVG, DXF, G-code, PDF). *(5 functions)*
22
- - **[C14: Visual & Debugging](#c14-visual-debugging)** — Control viewport appearance and debugging aids. *(5 functions)*
23
- - **[C15: Import & Composition](#c15-import-composition)** — Bring external geometry or other ForgeCAD modules into the current script. *(1 functions)*
24
- - **[C16: Part Library](#c16-part-library)** — Pre-built parametric parts accessible via `lib.*`. *(0 functions)*
25
-
26
- ---
27
-
28
- ## C1: Primitive Construction
29
-
30
- Create geometry from parameters — no input geometry required.
31
-
32
- #### `arcBridgeBetweenRects()`
33
-
34
- ```ts
35
- arcBridgeBetweenRects(rectA: RectAreaArg, rectB: RectAreaArg, segments?: number): Shape
36
- ```
37
-
38
- Build an arc bridge between two rectangular areas.
39
-
40
- #### `circle2d()`
41
-
42
- ```ts
43
- circle2d(radius: number, segments?: number): Sketch
44
- ```
45
-
46
- Create a 2D circle centered at the origin. Use segments for lower-poly approximations.
47
-
48
- #### `ellipse()`
49
-
50
- ```ts
51
- ellipse(rx: number, ry: number, segments?: number): Sketch
52
- ```
53
-
54
- Create a 2D ellipse centered at the origin with the given X and Y radii.
55
-
56
- #### `loadFont()`
57
-
58
- ```ts
59
- loadFont(source: string | ArrayBuffer, cacheKey?: string): opentype$1.Font
60
- ```
61
-
62
- Load and cache a font. - A built-in font name: `'sans-serif'` or `'inter'` (works everywhere) - A file path to a TTF/OTF/WOFF file (CLI/Node only) - An ArrayBuffer of font data (works everywhere)
63
-
64
- #### `ngon()`
65
-
66
- ```ts
67
- ngon(sides: number, radius: number): Sketch
68
- ```
69
-
70
- Create a regular polygon (equilateral triangle, hexagon, etc.) inscribed in a circle of the given radius.
71
-
72
- #### `path()`
73
-
74
- ```ts
75
- path(): PathBuilder
76
- ```
77
-
78
- Create a path builder for constructing 2D outlines.
79
-
80
- #### `polar()`
81
-
82
- ```ts
83
- polar(length: number, angleDeg: number, from?: [ number, number ]): [ number, number ]
84
- ```
85
-
86
- Compute a point by moving a given distance at a given angle from a start point. Angle is in degrees, measured CCW from the +X axis (standard math convention). Returns `[x, y]`. ```js polar(10, 45) // [7.07, 7.07] — from origin polar(10, 45, [5, 5]) // [12.07, 12.07] — from (5,5) ```
87
-
88
- #### `polygon()`
89
-
90
- ```ts
91
- polygon(points: ([ number, number ] | Point2D)[]): Sketch
92
- ```
93
-
94
- Create a 2D polygon from an array of [x, y] points or Point2D objects. Winding is normalized to CCW.
95
-
96
- #### `polygonVertices()`
97
-
98
- ```ts
99
- polygonVertices(sides: number, radius: number, options?: PolygonVerticesOptions): LayoutPoint[]
100
- ```
101
-
102
- Compute the vertex positions of a regular polygon. Default orientation places the first vertex at the top (90 degrees), matching the convention used by `ngon()`. Eliminates manual Math.sqrt(3) for triangles, pentagon vertex math, etc: ```js // Before — manual equilateral triangle const v1 = [center.x - r/2, center.y + r * Math.sqrt(3)/2]; const v2 = [center.x - r/2, center.y - r * Math.sqrt(3)/2]; const v3 = [center.x + r, center.y]; // After — declarative const [v1, v2, v3] = polygonVertices(3, r); ```
103
-
104
- <details><summary><code>PolygonVerticesOptions</code></summary>
105
-
106
- ```ts
107
- interface PolygonVerticesOptions {
108
- /** Angle of the first vertex in degrees (default: 90 = top). */
109
- startDeg?: number;
110
- /** Center X coordinate (default: 0). */
111
- centerX?: number;
112
- /** Center Y coordinate (default: 0). */
113
- centerY?: number;
114
- }
115
- ```
116
-
117
- </details>
118
-
119
- <details><summary><code>LayoutPoint</code></summary>
120
-
121
- ```ts
122
- interface LayoutPoint {
123
- x: number;
124
- y: number;
125
- }
126
- ```
127
-
128
- </details>
129
-
130
- #### `rect()`
131
-
132
- ```ts
133
- rect(width: number, height: number, center?: boolean): Sketch
134
- ```
135
-
136
- Create a 2D rectangle. When center is true, the origin is at the rectangle center; otherwise at the bottom-left corner.
137
-
138
- #### `arcSlot()`
139
-
140
- ```ts
141
- arcSlot(pitchRadius: number, sweepDeg: number, thickness: number): Sketch
142
- ```
143
-
144
- Create an arc-shaped slot (banana/annular sector) centered at the origin. The slot is symmetric about the +X axis. ```js arcSlot(135, 74, 40) // pitch R135, 74° sweep, 40mm wide ```
145
-
146
- #### `routePerimeter()`
147
-
148
- ```ts
149
- routePerimeter(steps: PerimeterStep[]): Sketch
150
- ```
151
-
152
- Route a smooth closed perimeter around a sequence of construction circles, connected by tangent fillet arcs. Steps must alternate: circle, fillet, circle, fillet, ... The sequence wraps — the last fillet connects back to the first circle. ```js const outline = routePerimeter([ { center: [0, 0], radius: 45 }, { fillet: 5 }, { center: polar(60, 60), radius: 18 }, { fillet: 17 }, { center: polar(60, 120), radius: 18 }, { fillet: 5 }, ]) ```
153
-
154
- #### `roundedRect()`
155
-
156
- ```ts
157
- roundedRect(width: number, height: number, radius: number, center?: boolean): Sketch
158
- ```
159
-
160
- Create a 2D rectangle with rounded corners. The radius is clamped to fit within the dimensions.
161
-
162
- #### `slot()`
163
-
164
- ```ts
165
- slot(length: number, width: number): Sketch
166
- ```
167
-
168
- Create a slot (stadium/discorectangle) — a rectangle with semicircular ends, centered at origin.
169
-
170
- #### `spline2d()`
171
-
172
- ```ts
173
- spline2d(points: Vec2[], options?: Spline2DOptions): Sketch
174
- ```
175
-
176
- Build a smooth Catmull-Rom spline sketch from 2D control points. A closed spline (default) returns a filled profile. An open spline requires a strokeWidth option to produce a solid sketch. Use tension (0..1, default 0.5) to control curve tightness.
177
-
178
- <details><summary><code>Spline2DOptions</code></summary>
179
-
180
- ```ts
181
- interface Spline2DOptions {
182
- /** Closed loop (default true). */
183
- closed?: boolean;
184
- /** Catmull-Rom tension in [0, 1]. 0 = very round, 1 = linear-ish. Default 0.5. */
185
- tension?: number;
186
- /** Samples per segment (minimum 3). Default 16. */
187
- samplesPerSegment?: number;
188
- /** For open splines, provide stroke width to return a solid Sketch. If omitted for open splines, an error is thrown. */
189
- strokeWidth?: number;
190
- /** Stroke join for open splines. Default 'Round'. */
191
- join?: "Round" | "Square";
192
- }
193
- ```
194
-
195
- </details>
196
-
197
- #### `star()`
198
-
199
- ```ts
200
- star(points: number, outerR: number, innerR: number): Sketch
201
- ```
202
-
203
- Create a star shape with alternating outer and inner radii.
204
-
205
- #### `stroke()`
206
-
207
- ```ts
208
- stroke(points: [ number, number ][], width: number, join?: "Round" | "Square"): Sketch
209
- ```
210
-
211
- Create a stroked polyline sketch from an array of 2D points.
212
-
213
- #### `text2d()`
214
-
215
- ```ts
216
- text2d(content: string, options?: TextOptions): Sketch
217
- ```
218
-
219
- Build a 2-D filled Sketch from a text string. The Sketch origin is at the left end of the text baseline by default (see `align` and `baseline` options to adjust placement). Text is rendered using the bundled Inter font by default, or any TTF/OTF/WOFF font you provide. // Extruded nameplate text2d('FORGE CAD', { size: 8 }).extrude(1.2) // Centered label on the XY plane text2d('V 2.0', { size: 6, align: 'center', baseline: 'center' })
220
-
221
- <details><summary><code>TextOptions</code></summary>
222
-
223
- ```ts
224
- interface TextOptions {
225
- /** Cap height of the text in model units. All other dimensions (stroke weight, spacing) scale proportionally. */
226
- size?: number;
227
- /** Extra space between characters in model units. Negative values tighten the tracking. */
228
- letterSpacing?: number;
229
- /** Horizontal alignment relative to x = 0. - `'left'` — left edge at x = 0 (default) - `'center'` — centred on x = 0 - `'right'` — right edge at x = 0 */
230
- align?: "left" | "center" | "right";
231
- /** Vertical alignment relative to y = 0. - `'baseline'` — y = 0 is the text baseline (bottom of capital letters) - `'center'` — y = 0 is the vertical midpoint of the cap height - `'top'` — y = 0 is the top of capital letters */
232
- baseline?: "baseline" | "center" | "top";
233
- /** Font to use for text rendering. - `'sans-serif'` or `'inter'` — bundled Inter font (works everywhere, including browser) - **file path** — path to a TTF, OTF, or WOFF font file (CLI/Node only) - **Font object** — a previously loaded opentype.js Font (from `loadFont()`) - **omitted** — uses the bundled Inter font (same as `'sans-serif'`) text2d('Hello World', { size: 10 }) // default Inter text2d('Custom Font', { size: 10, font: '/path/to/font.ttf' }) */
234
- font?: string | opentype$1.Font;
235
- /** Bezier flattening tolerance in model units. Smaller = more polygon segments = smoother curves. */
236
- flattenTolerance?: number;
237
- }
238
- ```
239
-
240
- </details>
241
-
242
- #### `textWidth()`
243
-
244
- ```ts
245
- textWidth(content: string, options?: Pick<TextOptions, "size" | "letterSpacing" | "font">): number
246
- ```
247
-
248
- Returns the rendered width of a string in model units (same options as text2d).
249
-
250
- ---
251
-
252
- ## C2: Boolean Combination
253
-
254
- Combine same-dimension geometry using CSG set operations.
255
-
256
- #### `difference2d()`
257
-
258
- ```ts
259
- difference2d(...inputs: SketchOperandInput[]): Sketch
260
- ```
261
-
262
- Subtract 2D sketches from a base sketch. The first sketch is the base; all others are subtracted.
263
-
264
- #### `intersection2d()`
265
-
266
- ```ts
267
- intersection2d(...inputs: SketchOperandInput[]): Sketch
268
- ```
269
-
270
- Keep only the overlapping area of the input sketches (intersection boolean).
271
-
272
- #### `union2d()`
273
-
274
- ```ts
275
- union2d(...inputs: SketchOperandInput[]): Sketch
276
- ```
277
-
278
- Combine 2D sketches into a single profile (additive boolean). Accepts individual sketches or arrays.
279
-
280
- ---
281
-
282
- ## C3: Rigid Transform
283
-
284
- Reposition or reorient geometry without changing its shape.
285
-
286
- #### `degrees()`
287
-
288
- ```ts
289
- degrees(deg: number): number
290
- ```
291
-
292
- Convert degrees to degrees (identity — for readability in scripts)
293
-
294
- #### `radians()`
295
-
296
- ```ts
297
- radians(rad: number): number
298
- ```
299
-
300
- Convert radians to degrees
301
-
302
- #### `composeChain()`
303
-
304
- ```ts
305
- composeChain(...steps: TransformInput[]): Transform
306
- ```
307
-
308
- Compose transforms in chain order. Equivalent to Transform.identity().mul(a).mul(b).mul(c)...
309
-
310
- ---
311
-
312
- ## C4: Dimensional Promotion
313
-
314
- Convert a 2D profile into a 3D solid (extrude, revolve, loft, sweep).
315
-
316
- #### `connectEdges()`
317
-
318
- ```ts
319
- connectEdges(edgeA: EdgeSegment, edgeB: EdgeSegment, options?: ConnectEdgesOptions): Shape
320
- ```
321
-
322
- <details><summary><code>EdgeSegment</code></summary>
323
-
324
- ```ts
325
- interface EdgeSegment {
326
- /** Stable index within the extraction (deterministic for a given mesh). */
327
- index: number;
328
- start: Vec3;
329
- end: Vec3;
330
- midpoint: Vec3;
331
- /** Normalized direction from start → end. */
332
- direction: Vec3;
333
- length: number;
334
- /** Dihedral angle in degrees (0 = coplanar, 180 = knife edge). */
335
- dihedralAngle: number;
336
- /** true = outside corner (convex), false = inside corner (concave). */
337
- convex: boolean;
338
- /** Normal of first adjacent face. */
339
- normalA: Vec3;
340
- /** Normal of second adjacent face (same as normalA for boundary edges). */
341
- normalB: Vec3;
342
- /** true if this is a boundary (unmatched) edge — unusual for closed solids. */
343
- boundary: boolean;
344
- }
345
- ```
346
-
347
- </details>
348
-
349
- <details><summary><code>TransitionCurveOptions</code></summary>
350
-
351
- ```ts
352
- interface TransitionCurveOptions {
353
- /** Weight for the start edge. Controls tangent magnitude at the start. - 1.0 (default): balanced transition - > 1.0: curve follows start edge longer before turning - < 1.0: curve turns sooner at the start */
354
- weightA?: number;
355
- /** Weight for the end edge. Controls tangent magnitude at the end. - 1.0 (default): balanced transition - > 1.0: curve follows end edge longer before turning - < 1.0: curve turns sooner at the end */
356
- weightB?: number;
357
- /** Number of sample points for the output polyline. Default 64. Higher values give smoother curves at the cost of more geometry. */
358
- samples?: number;
359
- }
360
- ```
361
-
362
- </details>
363
-
364
- <details><summary><code>TransitionSurfaceOptions</code> extends TransitionCurveOptions</summary>
365
-
366
- ```ts
367
- interface TransitionSurfaceOptions extends TransitionCurveOptions {
368
- /** Cross-section profile to sweep along the transition curve. If omitted, a circular profile with `radius` is used. */
369
- profile?: Sketch;
370
- /** Radius of circular cross-section (used when `profile` is omitted). Default: 5% of chord length. */
371
- radius?: number;
372
- width: number;
373
- height: number;
374
- /** Preferred up vector for the sweep frame. Default: auto-detected. */
375
- up?: Vec3$7;
376
- /** Edge length for level-set meshing. Smaller = finer. */
377
- edgeLength?: number;
378
- /** Extra bounds padding for level-set meshing. */
379
- boundsPadding?: number;
380
- }
381
- ```
382
-
383
- </details>
384
-
385
- <details><summary><code>ConnectEdgesOptions</code> extends TransitionSurfaceOptions</summary>
386
-
387
- ```ts
388
- interface ConnectEdgesOptions extends TransitionSurfaceOptions {
389
- /** Which end of edge A to connect. Default: 'start'. */
390
- endA?: EdgeEnd;
391
- /** Which end of edge B to connect. Default: 'start'. */
392
- endB?: EdgeEnd;
393
- /** Tangent mode for edge A. Default: 'along'. */
394
- tangentModeA?: TangentMode;
395
- /** Tangent mode for edge B. Default: 'along'. */
396
- tangentModeB?: TangentMode;
397
- /** Explicit tangent for edge A. */
398
- tangentA?: Vec3$7;
399
- /** Explicit tangent for edge B. */
400
- tangentB?: Vec3$7;
401
- /** Flip tangent A. */
402
- flipA?: boolean;
403
- /** Flip tangent B. */
404
- flipB?: boolean;
405
- }
406
- ```
407
-
408
- </details>
409
-
410
- #### `hermiteTransition()`
411
-
412
- ```ts
413
- hermiteTransition(a: EdgeEndpoint, b: EdgeEndpoint): HermiteCurve3D
414
- ```
415
-
416
- Create a Hermite transition curve between two edge endpoints. The curve starts at `a.point` tangent to `a.tangent` and ends at `b.point` tangent to `b.tangent`, with smooth G1-continuous interpolation. Weight controls: - weight = 1.0 (default): balanced transition - weight > 1.0: curve follows this edge's direction longer before turning - weight < 1.0: curve turns sooner, shorter tangent influence
417
-
418
- <details><summary><code>EdgeEndpoint</code></summary>
419
-
420
- ```ts
421
- interface EdgeEndpoint {
422
- /** Connection point on the edge */
423
- point: Vec3$5;
424
- /** Tangent direction along the edge at the connection point */
425
- tangent: Vec3$5;
426
- /** Surface normal at the connection point (optional, for future G2 support) */
427
- normal?: Vec3$5;
428
- /** Weight controlling how far the curve follows this edge's tangent. Default 1.0. */
429
- weight?: number;
430
- }
431
- ```
432
-
433
- </details>
434
-
435
- #### `hermiteTransitionG2()`
436
-
437
- ```ts
438
- hermiteTransitionG2(a: QuinticHermiteCurveEndpoint, b: QuinticHermiteCurveEndpoint): QuinticHermiteCurve3D
439
- ```
440
-
441
- Create a quintic Hermite transition curve between two edge endpoints (G2 continuity). The curve starts at `a.point` tangent to `a.tangent` with curvature `a.curvature`, and ends at `b.point` tangent to `b.tangent` with curvature `b.curvature`, with smooth G2-continuous interpolation matching position, tangent, and curvature.
442
-
443
- <details><summary><code>QuinticHermiteCurveEndpoint</code></summary>
444
-
445
- ```ts
446
- interface QuinticHermiteCurveEndpoint {
447
- /** Position */
448
- point: Vec3$5;
449
- /** Tangent direction (will be normalized internally) */
450
- tangent: Vec3$5;
451
- /** Second derivative / curvature vector. Default [0, 0, 0]. */
452
- curvature?: Vec3$5;
453
- /** Weight: scales tangent magnitude relative to chord length. Default 1.0. */
454
- weight?: number;
455
- }
456
- ```
457
-
458
- </details>
459
-
460
- #### `loft()`
461
-
462
- ```ts
463
- loft(profiles: Sketch[], heights: number[], options?: LoftOptions): Shape
464
- ```
465
-
466
- Loft between multiple sketches along Z stations. Profiles can differ in topology and vertex count: interpolation is done on signed-distance fields and meshed with level-set extraction. Heights must be strictly increasing. Compatible loft stacks can export through the OCCT exact route. Performance note: loft is significantly heavier than primitive/extrude/revolve. If the part is axis-symmetric (bottles, vases, knobs), prefer revolve().
467
-
468
- <details><summary><code>LoftOptions</code></summary>
469
-
470
- ```ts
471
- interface LoftOptions {
472
- /** Marching-grid edge length for level-set meshing. Smaller = finer. */
473
- edgeLength?: number;
474
- /** Optional extra bounds padding. */
475
- boundsPadding?: number;
476
- }
477
- ```
478
-
479
- </details>
480
-
481
- #### `loftAlongSpine()`
482
-
483
- ```ts
484
- loftAlongSpine(profiles: Sketch[], spine: Curve3D | Vec3$4[], tValues: number[], options?: LoftAlongSpineOptions): Shape
485
- ```
486
-
487
- Loft between multiple profiles positioned along an arbitrary 3D spine curve. Unlike loft() which only supports Z heights, loftAlongSpine() places each profile at a position along a 3D spine, oriented perpendicular to the spine tangent. This enables lofting along curved paths — e.g., a wing root-to-tip transition that follows a swept-back leading edge. The tValues array specifies where each profile sits along the spine (0 = start, 1 = end). Must have the same length as profiles and be in [0, 1]. Internally uses variableSweep infrastructure with SDF interpolation. Performance note: uses level-set meshing, heavier than simple loft().
488
-
489
- <details><summary><code>LoftAlongSpineOptions</code></summary>
490
-
491
- ```ts
492
- interface LoftAlongSpineOptions {
493
- /** Number of samples when spine is a Curve3D. Default 48. */
494
- samples?: number;
495
- /** Marching-grid edge length for level-set meshing. Smaller = finer. */
496
- edgeLength?: number;
497
- /** Optional extra bounds padding. */
498
- boundsPadding?: number;
499
- /** Preferred "up" vector for local profile frame. Auto fallback is used near parallel segments. */
500
- up?: Vec3$4;
501
- }
502
- ```
503
-
504
- </details>
505
-
506
- #### `spline3d()`
507
-
508
- ```ts
509
- spline3d(points: Vec3$4[], options?: Spline3DOptions): Curve3D
510
- ```
511
-
512
- Create a reusable 3D spline curve object (Catmull-Rom). The returned Curve3D provides sample(), pointAt(t), tangentAt(t), and length() for downstream use in sweep() or manual path operations.
513
-
514
- <details><summary><code>Spline3DOptions</code></summary>
515
-
516
- ```ts
517
- interface Spline3DOptions {
518
- /** Closed loop (default false). */
519
- closed?: boolean;
520
- /** Catmull-Rom tension in [0, 1]. 0 = very round, 1 = linear-ish. Default 0.5. */
521
- tension?: number;
522
- }
523
- ```
524
-
525
- </details>
526
-
527
- #### `surfacePatch()`
528
-
529
- ```ts
530
- surfacePatch(curves: { ... }, options?: SurfacePatchOptions): Shape
531
- ```
532
-
533
- Create a smooth surface patch from 4 boundary curves (Coons patch). The four curves form the boundary of a quadrilateral patch: - bottom: u=0..1 at v=0 (from corner00 to corner10) - top: u=0..1 at v=1 (from corner01 to corner11) - left: v=0..1 at u=0 (from corner00 to corner01) - right: v=0..1 at u=1 (from corner10 to corner11) The interior is filled using bilinear Coons patch interpolation: P(u,v) = Lc(u,v) + Ld(u,v) - B(u,v) The result is a thin solid created by offsetting the surface mesh along its normals by the specified thickness. Note: curves should meet at corners. Small gaps are tolerated.
534
-
535
- <details><summary><code>SurfacePatchOptions</code></summary>
536
-
537
- ```ts
538
- interface SurfacePatchOptions {
539
- /** Number of samples along each direction. Default 24. */
540
- resolution?: number;
541
- /** Thickness of the generated solid. Default 0.5. */
542
- thickness?: number;
543
- }
544
- ```
545
-
546
- </details>
547
-
548
- #### `sweep()`
549
-
550
- ```ts
551
- sweep(profile: Sketch, path: Curve3D | Vec3$4[], options?: SweepOptions): Shape
552
- ```
553
-
554
- Sweep a 2D profile along a 3D path to create a solid. Path can be a Curve3D from spline3d() or an array of [x,y,z] points (polyline). The profile is interpreted in the local frame normal plane. Compatible sweeps can export through the OCCT exact route using the canonical path representation. Performance note: sweep uses level-set meshing internally. Prefer direct primitives/extrude/revolve when they can express the same shape.
555
-
556
- <details><summary><code>SweepOptions</code></summary>
557
-
558
- ```ts
559
- interface SweepOptions {
560
- /** Number of samples when path is a Curve3D. Default 48. */
561
- samples?: number;
562
- /** Marching-grid edge length for level-set meshing. Smaller = finer. */
563
- edgeLength?: number;
564
- /** Optional extra bounds padding. */
565
- boundsPadding?: number;
566
- /** Preferred "up" vector for local profile frame. Auto fallback is used near parallel segments. */
567
- up?: Vec3$4;
568
- }
569
- ```
570
-
571
- </details>
572
-
573
- #### `variableSweep()`
574
-
575
- ```ts
576
- variableSweep(spine: Curve3D | Vec3$4[], sections: VariableSweepSection[], options?: VariableSweepOptions): Shape
577
- ```
578
-
579
- Sweep a variable cross-section along a 3D spine curve. Unlike sweep(), which uses a single constant profile, variableSweep() interpolates between multiple profiles at different stations along the spine. This enables organic shapes like tapering tubes, bone-like structures, and sculptural forms. Each section specifies a t parameter (0 = start, 1 = end of spine) and a 2D profile sketch. The SDF-based level-set mesher smoothly blends between profiles at intermediate positions. Performance note: like sweep(), this uses level-set meshing internally.
580
-
581
- <details><summary><code>VariableSweepSection</code></summary>
582
-
583
- ```ts
584
- interface VariableSweepSection {
585
- /** Parameter along the spine (0 = start, 1 = end). */
586
- t: number;
587
- /** Cross-section profile at this station. */
588
- profile: Sketch;
589
- }
590
- ```
591
-
592
- </details>
593
-
594
- <details><summary><code>VariableSweepOptions</code></summary>
595
-
596
- ```ts
597
- interface VariableSweepOptions {
598
- /** Number of samples when spine is a Curve3D. Default 48. */
599
- samples?: number;
600
- /** Marching-grid edge length for level-set meshing. Smaller = finer. */
601
- edgeLength?: number;
602
- /** Optional extra bounds padding. */
603
- boundsPadding?: number;
604
- /** Preferred "up" vector for local profile frame. Auto fallback is used near parallel segments. */
605
- up?: Vec3$4;
606
- }
607
- ```
608
-
609
- </details>
610
-
611
- #### `transitionCurve()`
612
-
613
- ```ts
614
- transitionCurve(edgeA: TransitionEdge, edgeB: TransitionEdge, options?: TransitionCurveOptions): HermiteCurve3D
615
- ```
616
-
617
- Create a smooth transition curve between two edges. Returns a `HermiteCurve3D` that starts at `edgeA.point` tangent to `edgeA.tangent` and ends at `edgeB.point` tangent to `edgeB.tangent`. The curve maintains G1 continuity (matching tangent direction) at both endpoints. Weight parameters control the shape of the transition. ```js // Connect two edges with a balanced transition const curve = transitionCurve( { point: [0, 0, 0], tangent: [1, 0, 0] }, { point: [10, 5, 0], tangent: [1, 0, 0] }, ); // Weighted: curve hugs edge A longer const weighted = transitionCurve( { point: [0, 0, 0], tangent: [1, 0, 0] }, { point: [10, 5, 0], tangent: [1, 0, 0] }, { weightA: 2.0, weightB: 0.5 }, ); ```
618
-
619
- <details><summary><code>TransitionEdge</code></summary>
620
-
621
- ```ts
622
- interface TransitionEdge {
623
- /** Connection point on the edge. Can be any point along the edge where the transition should connect. */
624
- point: Vec3$7;
625
- /** Tangent direction at the connection point. This is the direction the curve should initially follow when leaving this edge. For a straight edge, this is typically the edge direction pointing "outward" (away from the body of the edge, toward the other edge). */
626
- tangent: Vec3$7;
627
- /** Surface normal at the connection point (optional). Used as a hint for the sweep frame's up vector. */
628
- normal?: Vec3$7;
629
- }
630
- ```
631
-
632
- </details>
633
-
634
- #### `transitionCurveFromPoints()`
635
-
636
- ```ts
637
- transitionCurveFromPoints(startPoint: Vec3$7, startTangent: Vec3$7, endPoint: Vec3$7, endTangent: Vec3$7, options?: TransitionCurveOptions): HermiteCurve3D
638
- ```
639
-
640
- Convenience: create a transition curve from raw coordinate data. Useful when you have endpoints and directions as plain arrays without constructing TransitionEdge objects.
641
-
642
- #### `transitionSurface()`
643
-
644
- ```ts
645
- transitionSurface(edgeA: TransitionEdge, edgeB: TransitionEdge, options?: TransitionSurfaceOptions): Shape
646
- ```
647
-
648
- Create a solid transition surface between two edges by sweeping a profile along a Hermite transition curve. This produces a watertight solid that smoothly connects the two edges. Works with both Manifold and OCCT backends. ```js // Circular tube connecting two edges const tube = transitionSurface( { point: [0, 0, 0], tangent: [1, 0, 0] }, { point: [10, 5, 3], tangent: [0, 1, 0] }, { radius: 0.5 }, ); // Custom profile with weights const custom = transitionSurface( { point: [0, 0, 0], tangent: [1, 0, 0] }, { point: [10, 5, 3], tangent: [0, 1, 0] }, { profile: mySketch, weightA: 1.5, weightB: 0.8 }, ); ```
649
-
650
- ---
651
-
652
- ## C5: Topology Query
653
-
654
- Select or inspect named faces and edges on a shape.
655
-
656
- #### `coalesceEdges()`
657
-
658
- ```ts
659
- coalesceEdges(segments: EdgeSegment[], tolerance?: number): EdgeSegment[]
660
- ```
661
-
662
- Coalesce collinear edge segments into longer logical edges. Multiple short mesh segments along the same line (e.g. from tessellation) are merged into a single EdgeSegment spanning the full extent. The `tolerance` controls how far endpoints can deviate from collinearity.
663
-
664
- <details><summary><code>EdgeSegment</code></summary>
665
-
666
- ```ts
667
- interface EdgeSegment {
668
- /** Stable index within the extraction (deterministic for a given mesh). */
669
- index: number;
670
- start: Vec3;
671
- end: Vec3;
672
- midpoint: Vec3;
673
- /** Normalized direction from start → end. */
674
- direction: Vec3;
675
- length: number;
676
- /** Dihedral angle in degrees (0 = coplanar, 180 = knife edge). */
677
- dihedralAngle: number;
678
- /** true = outside corner (convex), false = inside corner (concave). */
679
- convex: boolean;
680
- /** Normal of first adjacent face. */
681
- normalA: Vec3;
682
- /** Normal of second adjacent face (same as normalA for boundary edges). */
683
- normalB: Vec3;
684
- /** true if this is a boundary (unmatched) edge — unusual for closed solids. */
685
- boundary: boolean;
686
- }
687
- ```
688
-
689
- </details>
690
-
691
- #### `selectEdge()`
692
-
693
- ```ts
694
- selectEdge(shape: Shape, query?: EdgeQuery): EdgeSegment
695
- ```
696
-
697
- Select the single best-matching edge from a shape. When `near` is specified, returns the closest matching edge. Otherwise returns the first matching edge (by mesh order). Throws if no edges match.
698
-
699
- <details><summary><code>EdgeQuery</code></summary>
700
-
701
- ```ts
702
- interface EdgeQuery {
703
- /** Sort by proximity to this point (closest first). */
704
- near?: Vec3;
705
- /** Filter: edge direction approximately parallel to this vector. */
706
- parallel?: Vec3;
707
- /** Filter: edge direction approximately perpendicular to this vector. */
708
- perpendicular?: Vec3;
709
- /** Filter: only convex (outside corner) edges. */
710
- convex?: boolean;
711
- /** Filter: only concave (inside corner) edges. */
712
- concave?: boolean;
713
- /** Filter: minimum dihedral angle in degrees. */
714
- minAngle?: number;
715
- /** Filter: maximum dihedral angle in degrees. */
716
- maxAngle?: number;
717
- /** Filter: minimum edge length. */
718
- minLength?: number;
719
- /** Filter: maximum edge length. */
720
- maxLength?: number;
721
- /** Filter: edge midpoint must be within this bounding region. */
722
- within?: BoundingRegion;
723
- /** Shorthand: edge midpoint Z ≈ this value (within tolerance). */
724
- atZ?: number;
725
- /** Tolerance for approximate matches (default: 1.0). */
726
- tolerance?: number;
727
- /** Angular tolerance in degrees for parallel/perpendicular (default: 10). */
728
- angleTolerance?: number;
729
- }
730
- ```
731
-
732
- </details>
733
-
734
- <details><summary><code>BoundingRegion</code></summary>
735
-
736
- ```ts
737
- interface BoundingRegion {
738
- xMin?: number;
739
- xMax?: number;
740
- yMin?: number;
741
- yMax?: number;
742
- zMin?: number;
743
- zMax?: number;
744
- }
745
- ```
746
-
747
- </details>
748
-
749
- #### `selectEdges()`
750
-
751
- ```ts
752
- selectEdges(shape: Shape, query?: EdgeQuery): EdgeSegment[]
753
- ```
754
-
755
- Select all edges from a shape that match the given query. Extracts sharp edges from the mesh (dihedral angle > 1°), applies filters, and returns the matching EdgeSegment array.
756
-
757
- ---
758
-
759
- ## C6: Edge Feature
760
-
761
- Modify edges of a solid — fillets, chamfers, draft, offset.
762
-
763
- #### `filletEdgeSegment()`
764
-
765
- ```ts
766
- filletEdgeSegment(shape: Shape, segment: EdgeSegment, radius: number, segments?: number): Shape
767
- ```
768
-
769
- Apply a fillet (rounded edge) to a mesh-selected edge. Works on any straight edge of any shape — not limited to tracked box edges. The edge must have been obtained from selectEdge() / selectEdges().
770
-
771
- <details><summary><code>EdgeSegment</code></summary>
772
-
773
- ```ts
774
- interface EdgeSegment {
775
- /** Stable index within the extraction (deterministic for a given mesh). */
776
- index: number;
777
- start: Vec3;
778
- end: Vec3;
779
- midpoint: Vec3;
780
- /** Normalized direction from start → end. */
781
- direction: Vec3;
782
- length: number;
783
- /** Dihedral angle in degrees (0 = coplanar, 180 = knife edge). */
784
- dihedralAngle: number;
785
- /** true = outside corner (convex), false = inside corner (concave). */
786
- convex: boolean;
787
- /** Normal of first adjacent face. */
788
- normalA: Vec3;
789
- /** Normal of second adjacent face (same as normalA for boundary edges). */
790
- normalB: Vec3;
791
- /** true if this is a boundary (unmatched) edge — unusual for closed solids. */
792
- boundary: boolean;
793
- }
794
- ```
795
-
796
- </details>
797
-
798
- #### `chamferEdgeSegment()`
799
-
800
- ```ts
801
- chamferEdgeSegment(shape: Shape, segment: EdgeSegment, size: number): Shape
802
- ```
803
-
804
- Apply a chamfer (beveled edge) to a mesh-selected edge. Works on any straight edge of any shape — not limited to tracked box edges.
805
-
806
- #### `chamfer()`
807
-
808
- ```ts
809
- chamfer(shape: Shape, size: number, edges?: EdgeSelector): Shape
810
- ```
811
-
812
- Apply chamfers (beveled edges) to one or more edges of a shape. Works on both straight and curved edges. Supports OCCT and Manifold backends. // Chamfer all edges chamfer(myShape, 1) // Chamfer vertical edges only chamfer(myShape, 2, { parallel: [0, 0, 1] })
813
-
814
- #### `draft()`
815
-
816
- ```ts
817
- draft(shape: Shape, angleDeg: number, pullDirection?: [ number, number, number ], neutralPlaneOffset?: number): Shape
818
- ```
819
-
820
- Apply a draft angle (taper) to all faces of a solid for mold extraction. Draft angle is a manufacturing feature that adds taper to the vertical faces of a solid so that it can be extracted from a mold. The neutral plane is where the draft angle is zero — faces above and below are tapered symmetrically. Requires the OCCT backend. Throws on Manifold. // Add 3° draft to a box for injection molding draft(myBox, 3) // Draft with custom pull direction and neutral plane draft(myShape, 2, [0, 0, 1], 10)
821
-
822
- #### `fillet()`
823
-
824
- ```ts
825
- fillet(shape: Shape, radius: number, edges?: EdgeSelector, segments?: number): Shape
826
- ```
827
-
828
- Apply fillets (rounded edges) to one or more edges of a shape. Works on both straight and curved edges. Supports OCCT and Manifold backends. When using OCCT, all edges are filleted in a single kernel operation for best quality. When using Manifold, edges are filleted sequentially. - EdgeSegment: a single edge from selectEdge() - EdgeSegment[]: multiple edges from selectEdges() - EdgeQuery: inline query (same options as selectEdges) - undefined: all sharp edges on the shape // Fillet all edges fillet(myShape, 2) // Fillet edges at the top fillet(myShape, 1.5, { atZ: 20, convex: true }) // Fillet specific edges const edges = selectEdges(myShape, { parallel: [0, 0, 1] }) fillet(myShape, 3, edges)
829
-
830
- #### `offsetSolid()`
831
-
832
- ```ts
833
- offsetSolid(shape: Shape, thickness: number): Shape
834
- ```
835
-
836
- Uniformly offset all surfaces of a solid inward or outward by a thickness value. Unlike shell(), which hollows a solid, offsetSolid() produces a new solid whose surfaces are all shifted by the given thickness. Positive = outward, negative = inward. Requires the OCCT backend. Throws on Manifold. // Grow a box outward by 1mm on all sides offsetSolid(myBox, 1) // Shrink a shape inward by 0.5mm offsetSolid(myShape, -0.5)
837
-
838
- #### `filletCorners()`
839
-
840
- ```ts
841
- filletCorners(points: PointInput[], corners: FilletCornerSpec[]): Sketch
842
- ```
843
-
844
- Create a polygon from points with specified corners rounded to arc fillets. Each corner spec identifies a vertex index and radius.
845
-
846
- <details><summary><code>FilletCornerSpec</code></summary>
847
-
848
- ```ts
849
- interface FilletCornerSpec {
850
- index: number;
851
- radius: number;
852
- segments?: number;
853
- }
854
- ```
855
-
856
- </details>
857
-
858
- ---
859
-
860
- ## C7: Pattern Replication
861
-
862
- Duplicate geometry in regular arrangements (linear, circular, mirror).
863
-
864
- #### `circularLayout()`
865
-
866
- ```ts
867
- circularLayout(count: number, radius: number, options?: CircularLayoutOptions): LayoutPoint[]
868
- ```
869
-
870
- Compute evenly-spaced positions around a circle. Eliminates the most common trig pattern in CAD scripts: ```js // Before — manual trig for (let i = 0; i < 12; i++) { const angle = i * 30 * Math.PI / 180; markers.push(marker.translate(r * Math.cos(angle), r * Math.sin(angle), 0)); } // After — declarative for (const {x, y} of circularLayout(12, r)) { markers.push(marker.translate(x, y, 0)); } ```
871
-
872
- <details><summary><code>CircularLayoutOptions</code></summary>
873
-
874
- ```ts
875
- interface CircularLayoutOptions {
876
- /** Angle of the first element in degrees (default: 0 = +X axis). */
877
- startDeg?: number;
878
- /** Center X coordinate (default: 0). */
879
- centerX?: number;
880
- /** Center Y coordinate (default: 0). */
881
- centerY?: number;
882
- }
883
- ```
884
-
885
- </details>
886
-
887
- <details><summary><code>LayoutPoint</code></summary>
888
-
889
- ```ts
890
- interface LayoutPoint {
891
- x: number;
892
- y: number;
893
- }
894
- ```
895
-
896
- </details>
897
-
898
- #### `circularPattern()`
899
-
900
- ```ts
901
- circularPattern(shape: Shape, count: number, centerXOrOpts?: number | CircularPatternOptions, centerY?: number): Shape
902
- ```
903
-
904
- Repeat a shape in a circular pattern around an axis and union the copies. Simple usage (Z axis, matches legacy signature): circularPattern(shape, 6) circularPattern(shape, 6, 10, 20) // centerX=10, centerY=20 Advanced usage (arbitrary axis): circularPattern(shape, 6, { axis: [1, 0, 0], origin: [0, 0, 50] })
905
-
906
- <details><summary><code>CircularPatternOptions</code></summary>
907
-
908
- ```ts
909
- interface CircularPatternOptions {
910
- /** Center X of the rotation (default: 0). Used when axis is Z (legacy mode). */
911
- centerX?: number;
912
- /** Center Y of the rotation (default: 0). Used when axis is Z (legacy mode). */
913
- centerY?: number;
914
- }
915
- ```
916
-
917
- </details>
918
-
919
- #### `circularPattern2d()`
920
-
921
- ```ts
922
- circularPattern2d(sketch: Sketch, count: number, centerXOrOpts?: number | { centerX?: number; centerY?: number; startDeg?: number; }, centerY?: number): Sketch
923
- ```
924
-
925
- Repeat a sketch in a circular pattern around a center point
926
-
927
- #### `linearPattern()`
928
-
929
- ```ts
930
- linearPattern(shape: Shape, count: number, dx: number, dy: number, dz?: number): Shape
931
- ```
932
-
933
- Repeat a shape in a linear pattern along a direction vector and union the copies.
934
-
935
- #### `linearPattern2d()`
936
-
937
- ```ts
938
- linearPattern2d(sketch: Sketch, count: number, dx: number, dy?: number): Sketch
939
- ```
940
-
941
- Repeat a sketch in a linear pattern
942
-
943
- #### `mirrorCopy()`
944
-
945
- ```ts
946
- mirrorCopy(shape: Shape, normal: [ number, number, number ]): Shape
947
- ```
948
-
949
- Mirror a shape across a plane defined by its normal and union the mirror with the original.
950
-
951
- ---
952
-
953
- ## C8: Constraint Solving
954
-
955
- Define geometry by relationships and let a solver find positions.
956
-
957
- #### `addPolygon()`
958
-
959
- ```ts
960
- addPolygon(sk: ConstrainedSketchBuilder, options: PolygonOptions): ConstrainedPolygon
961
- ```
962
-
963
- Add a general polygon concept to the builder. Creates n vertices and n sides (CCW: `sides[i]` from `vertices[i]` → `vertices[(i+1) % n]`). Applies a `ccw` constraint to enforce winding. The user is responsible for all dimensional constraints. ```ts const sk = constrainedSketch(); const tri = addPolygon(sk, { points: [[0,0],[100,0],[50,80]] }); sk.fix(tri.vertex(0), 0, 0); sk.length(tri.side(0), 100); ```
964
-
965
- <details><summary><code>PolygonOptions</code></summary>
966
-
967
- ```ts
968
- interface PolygonOptions {
969
- /** Whether to register a closed loop for sketch generation. Default: true. */
970
- addLoop?: boolean;
971
- /** Prevent 180° rotation (ensures first edge maintains its initial direction). Default: false. */
972
- blockRotation?: boolean;
973
- }
974
- ```
975
-
976
- </details>
977
-
978
- <details><summary><code>ConstrainedPolygon</code></summary>
979
-
980
- ```ts
981
- interface ConstrainedPolygon {
982
- /** CCW-ordered PointIds. */
983
- vertices: PointId[];
984
- /** CCW-ordered LineIds. `sides[i]` runs from `vertices[i]` → `vertices[(i+1) % n]`. */
985
- sides: LineId[];
986
- /** ShapeId for `shapeWidth`, `shapeHeight`, `shapeArea`, `shapeCentroidX/Y`. */
987
- shape: ShapeId;
988
- }
989
- ```
990
-
991
- </details>
992
-
993
- #### `addRect()`
994
-
995
- ```ts
996
- addRect(sk: ConstrainedSketchBuilder, options?: RectOptions): ConstrainedRect
997
- ```
998
-
999
- Add an axis-aligned rectangle concept to the builder. Creates 4 vertices (CCW: bl→br→tr→tl), 4 sides, applies 4 structural constraints (`horizontal`/`vertical` on each side), enforces CCW winding, registers a loop and a shape, and returns a `ConstrainedRect` handle. ```ts const sk = constrainedSketch(); const rect = addRect(sk, { x: 0, y: 0, width: 100, height: 50 }); sk.fix(rect.bottomLeft, 0, 0); sk.length(rect.bottom, 120); ```
1000
-
1001
- <details><summary><code>RectOptions</code></summary>
1002
-
1003
- ```ts
1004
- interface RectOptions {
1005
- /** Bottom-left x coordinate. Default: 0. */
1006
- x?: number;
1007
- /** Bottom-left y coordinate. Default: 0. */
1008
- y?: number;
1009
- /** Width (along x). Default: 10. */
1010
- width?: number;
1011
- /** Height (along y). Default: 10. */
1012
- height?: number;
1013
- /** Prevent 180° rotation (ensures bottom edge points rightward). Default: false. */
1014
- blockRotation?: boolean;
1015
- }
1016
- ```
1017
-
1018
- </details>
1019
-
1020
- <details><summary><code>ConstrainedRect</code></summary>
1021
-
1022
- ```ts
1023
- interface ConstrainedRect {
1024
- bottomLeft: PointId;
1025
- bottomRight: PointId;
1026
- topRight: PointId;
1027
- topLeft: PointId;
1028
- /** bottom-left → bottom-right */
1029
- bottom: LineId;
1030
- /** bottom-right → top-right */
1031
- right: LineId;
1032
- /** top-right → top-left */
1033
- top: LineId;
1034
- /** top-left → bottom-left */
1035
- left: LineId;
1036
- /** Center point constrained to the geometric center via `midpoint` on the diagonal. Can be used in further constraints: `sk.fix(rect.center, 0, 0)`, `sk.coincident(rect.center, other)`. */
1037
- center: PointId;
1038
- /** ShapeId for `shapeWidth`, `shapeHeight`, `shapeArea`, `shapeCentroidX/Y`. */
1039
- shape: ShapeId;
1040
- }
1041
- ```
1042
-
1043
- </details>
1044
-
1045
- #### `addRegularPolygon()`
1046
-
1047
- ```ts
1048
- addRegularPolygon(sk: ConstrainedSketchBuilder, options: RegularPolygonOptions): ConstrainedRegularPolygon
1049
- ```
1050
-
1051
- Add a regular n-gon concept to the builder. Vertices are placed at `(cx + r·cos(startAngle + i·2π/n), cy + r·sin(...))`. Equal-side constraints enforce regularity. The center point is constrained to the centroid via midpoint constraints on the first diagonal. ```ts const sk = constrainedSketch(); const hex = addRegularPolygon(sk, { sides: 6, radius: 25, cx: 0, cy: 0 }); sk.fix(hex.center, 0, 0); sk.length(hex.side(0), 30); // changes all sides (equal constraint) ```
1052
-
1053
- <details><summary><code>RegularPolygonOptions</code></summary>
1054
-
1055
- ```ts
1056
- interface RegularPolygonOptions {
1057
- /** Number of sides (minimum 3). */
1058
- sides: number;
1059
- /** Circumradius — distance from center to vertex. Default: 10. */
1060
- radius?: number;
1061
- /** Center x coordinate. Default: 0. */
1062
- cx?: number;
1063
- /** Center y coordinate. Default: 0. */
1064
- cy?: number;
1065
- /** Angle (in degrees) of vertex[0] measured from the +X axis (CCW positive). Default: 0 (rightmost vertex). */
1066
- startAngle?: number;
1067
- /** Prevent 180° rotation (ensures first edge maintains its initial direction). Default: false. */
1068
- blockRotation?: boolean;
1069
- }
1070
- ```
1071
-
1072
- </details>
1073
-
1074
-
1075
- <details><summary><code>ConstrainedRegularPolygon</code> extends ConstrainedPolygon</summary>
1076
-
1077
- ```ts
1078
- interface ConstrainedRegularPolygon extends ConstrainedPolygon {
1079
- /** Center point. Use `sk.fix(poly.center, x, y)` to pin location, or `sk.coincident(poly.center, other)` to align with other geometry. */
1080
- center: PointId;
1081
- }
1082
- ```
1083
-
1084
- </details>
1085
-
1086
- #### `circle()`
1087
-
1088
- ```ts
1089
- circle(cx: number, cy: number, radius: number): Circle2D
1090
- ```
1091
-
1092
- Create an analytic 2D circle for measurement, construction, and extrusion. Provides diameter, circumference, area, and toSketch().
1093
-
1094
- #### `constrainedSketch()`
1095
-
1096
- ```ts
1097
- constrainedSketch(options?: ConstrainedSketchOptions): ConstrainedSketchBuilder
1098
- ```
1099
-
1100
- Build a parametric 2D sketch with geometric constraints solved by the built-in constraint solver.
1101
-
1102
- <details><summary><code>ConstrainedSketchOptions</code></summary>
1103
-
1104
- ```ts
1105
- interface ConstrainedSketchOptions {
1106
- /** When true, adding a constraint that cannot be satisfied throws instead of silently discarding it. */
1107
- strict?: boolean;
1108
- }
1109
- ```
1110
-
1111
- </details>
1112
-
1113
- #### `line()`
1114
-
1115
- ```ts
1116
- line(x1: number, y1: number, x2: number, y2: number): Line2D
1117
- ```
1118
-
1119
- Create an analytic 2D line segment between two points. Provides length, midpoint, angle, intersection, and parallel helpers.
1120
-
1121
- #### `point()`
1122
-
1123
- ```ts
1124
- point(x: number, y: number): Point2D
1125
- ```
1126
-
1127
- Create an analytic 2D point for measurement and construction geometry.
1128
-
1129
- ---
1130
-
1131
- ## C9: Spatial Placement
1132
-
1133
- Position geometry relative to other geometry using semantic anchors.
1134
-
1135
- *No free functions — see class methods (Shape, Sketch, ConstrainedSketchBuilder).*
1136
-
1137
- ---
1138
-
1139
- ## C10: Assembly & Kinematics
1140
-
1141
- Compose parts with joints for kinematic simulation.
1142
-
1143
- #### `assembly()`
1144
-
1145
- ```ts
1146
- assembly(name?: string): Assembly
1147
- ```
1148
-
1149
- Create an assembly container with named parts and joints for kinematic mechanisms. Build with addPart(), addJoint(), addJointCoupling(), addGearCoupling(), then solve() to get positioned parts. Supports revolute, prismatic, and fixed joint types.
1150
-
1151
- #### `bomToCsv()`
1152
-
1153
- ```ts
1154
- bomToCsv(rows: BomRow[]): string
1155
- ```
1156
-
1157
- Convert BOM rows from a solved assembly into a CSV string.
1158
-
1159
- <details><summary><code>BomRow</code></summary>
1160
-
1161
- ```ts
1162
- interface BomRow {
1163
- part: string;
1164
- qty: number;
1165
- material?: string;
1166
- process?: string;
1167
- tolerance?: string;
1168
- notes?: string;
1169
- metadata?: PartMetadata;
1170
- }
1171
- ```
1172
-
1173
- </details>
1174
-
1175
- <details><summary><code>PartMetadata</code></summary>
1176
-
1177
- ```ts
1178
- interface PartMetadata {
1179
- material?: string;
1180
- process?: string;
1181
- tolerance?: string;
1182
- qty?: number;
1183
- notes?: string;
1184
- densityKgM3?: number;
1185
- massKg?: number;
1186
- }
1187
- ```
1188
-
1189
- </details>
1190
-
1191
- #### `joint()`
1192
-
1193
- ```ts
1194
- joint(name: string, shape: Shape, pivot: [ number, number, number ], opts?: RevoluteJointOpts): Shape
1195
- ```
1196
-
1197
- Create a revolute (hinge) joint. Auto-creates a param slider and rotates the shape.
1198
-
1199
- <details><summary><code>RevoluteJointOpts</code></summary>
1200
-
1201
- ```ts
1202
- interface RevoluteJointOpts {
1203
- min?: number;
1204
- max?: number;
1205
- default?: number;
1206
- unit?: string;
1207
- reverse?: boolean;
1208
- }
1209
- ```
1210
-
1211
- </details>
1212
-
1213
- #### `jointsView()`
1214
-
1215
- ```ts
1216
- jointsView(options?: JointsViewOptions): void
1217
- ```
1218
-
1219
- Configure runtime joint controls that animate object transforms in the viewport without re-running the script.
1220
-
1221
- <details><summary><code>JointsViewOptions</code></summary>
1222
-
1223
- ```ts
1224
- interface JointsViewOptions {
1225
- enabled?: boolean;
1226
- joints?: JointViewInput[];
1227
- couplings?: JointViewCouplingInput[];
1228
- animations?: JointViewAnimationInput[];
1229
- defaultAnimation?: string;
1230
- }
1231
- ```
1232
-
1233
- </details>
1234
-
1235
- <details><summary><code>JointViewInput</code></summary>
1236
-
1237
- ```ts
1238
- interface JointViewInput {
1239
- name: string;
1240
- child: string;
1241
- parent?: string;
1242
- type?: JointViewType;
1243
- axis?: JointViewAxis;
1244
- min?: number;
1245
- max?: number;
1246
- default?: number;
1247
- unit?: string;
1248
- hidden?: boolean;
1249
- }
1250
- ```
1251
-
1252
- </details>
1253
-
1254
- <details><summary><code>JointViewCouplingInput</code></summary>
1255
-
1256
- ```ts
1257
- interface JointViewCouplingInput {
1258
- joint: string;
1259
- terms: JointViewCouplingTermInput[];
1260
- offset?: number;
1261
- }
1262
- ```
1263
-
1264
- </details>
1265
-
1266
- <details><summary><code>JointViewCouplingTermInput</code></summary>
1267
-
1268
- ```ts
1269
- interface JointViewCouplingTermInput {
1270
- joint: string;
1271
- ratio?: number;
1272
- }
1273
- ```
1274
-
1275
- </details>
1276
-
1277
- <details><summary><code>JointViewAnimationInput</code></summary>
1278
-
1279
- ```ts
1280
- interface JointViewAnimationInput {
1281
- name: string;
1282
- duration?: number;
1283
- loop?: boolean;
1284
- continuous?: boolean;
1285
- keyframes: JointViewAnimationKeyframeInput[];
1286
- }
1287
- ```
1288
-
1289
- </details>
1290
-
1291
- <details><summary><code>JointViewAnimationKeyframeInput</code></summary>
1292
-
1293
- ```ts
1294
- interface JointViewAnimationKeyframeInput {
1295
- /** Timeline position [0, 1]. If omitted from ALL keyframes, positions are auto-computed from tick weights. */
1296
- at?: number;
1297
- /** Relative weight of the segment from this keyframe to the next (default 1). Only used in tick-based mode (when `at` is omitted). Last keyframe's ticks value is ignored. */
1298
- ticks?: number;
1299
- values: Record<string, number>;
1300
- }
1301
- ```
1302
-
1303
- </details>
1304
-
1305
- ---
1306
-
1307
- ## C11: Parameterization & UI
1308
-
1309
- Declare user-facing controls that drive model geometry.
1310
-
1311
- #### `boolParam()`
1312
-
1313
- ```ts
1314
- boolParam(name: string, defaultValue: boolean): boolean
1315
- ```
1316
-
1317
- Declare a boolean parameter. Returns the current boolean value. Renders as a checkbox in the UI.
1318
-
1319
- #### `choiceParam()`
1320
-
1321
- ```ts
1322
- choiceParam(name: string, defaultValue: string, choices: string[]): string
1323
- ```
1324
-
1325
- Declare a choice parameter. Returns the selected string label. Renders as a dropdown in the UI. `defaultValue` must match one of the supplied `choices`. Overrides may be passed either as the choice label or as a numeric index, but labels are preferred because they are clearer in CLI/import usage.
1326
-
1327
- #### `listParam()`
1328
-
1329
- ```ts
1330
- listParam<T extends Record<string, number | boolean | string>>(name: string, defaultItems: T[], opts: { ... }): T[]
1331
- ```
1332
-
1333
- Declare a list parameter — an array of struct items with per-field controls. Returns the current list of items (with overrides applied). Each item is an object whose fields match the keys in defaultItems. Boolean fields (marked with `boolean: true` in field defs) return as booleans. Choice fields (marked with `choices: [...]` in field defs) return as strings. All other fields return as numbers.
1334
-
1335
- <details><summary><code>ListParamFieldDef</code></summary>
1336
-
1337
- ```ts
1338
- interface ListParamFieldDef {
1339
- min?: number;
1340
- max?: number;
1341
- step?: number;
1342
- unit?: string;
1343
- integer?: boolean;
1344
- boolean?: boolean;
1345
- choices?: string[];
1346
- }
1347
- ```
1348
-
1349
- </details>
1350
-
1351
- #### `param()`
1352
-
1353
- ```ts
1354
- param(name: string, defaultValue: number, opts?: { min?: number; max?: number; step?: number; unit?: string; integer?: boolean; reverse?: boolean; }): number
1355
- ```
1356
-
1357
- Declare a parameter. Returns the current value (default or overridden). Each call registers the param for UI generation.
1358
-
1359
- #### `dim()`
1360
-
1361
- ```ts
1362
- dim(from: PointArg$1, to: PointArg$1, opts?: DimOpts): void
1363
- ```
1364
-
1365
- Add a dimension annotation between two points.
1366
-
1367
- <details><summary><code>DimOpts</code></summary>
1368
-
1369
- ```ts
1370
- interface DimOpts {
1371
- offset?: number;
1372
- label?: string;
1373
- color?: string;
1374
- component?: string | string[];
1375
- currentComponent?: boolean;
1376
- }
1377
- ```
1378
-
1379
- </details>
1380
-
1381
- #### `dimLine()`
1382
-
1383
- ```ts
1384
- dimLine(l: Line2D, opts?: DimOpts): void
1385
- ```
1386
-
1387
- Add a dimension annotation along a Line2D.
1388
-
1389
- ---
1390
-
1391
- ## C12: Dimensional Demotion
1392
-
1393
- Extract 2D geometry from a 3D solid (section, projection).
1394
-
1395
- #### `faceProfile()`
1396
-
1397
- ```ts
1398
- faceProfile(shape: Shape, face: FaceSelector): Sketch
1399
- ```
1400
-
1401
- #### `intersectWithPlane()`
1402
-
1403
- ```ts
1404
- intersectWithPlane(shape: Shape, plane: PlaneSpec): Sketch
1405
- ```
1406
-
1407
- Cross-section: slice a 3D shape with a plane and return the intersection as a 2D Sketch.
1408
-
1409
- #### `projectToPlane()`
1410
-
1411
- ```ts
1412
- projectToPlane(shape: Shape, plane: PlaneSpec): Sketch
1413
- ```
1414
-
1415
- Orthographically project a 3D shape onto a plane and return the silhouette as a 2D Sketch.
1416
-
1417
- ---
1418
-
1419
- ## C13: Export & Output
1420
-
1421
- Convert geometry to external formats (STL, 3MF, SVG, DXF, G-code, PDF).
1422
-
1423
- #### `bom()`
1424
-
1425
- ```ts
1426
- bom(quantity: number, description: string, opts?: BomOpts): void
1427
- ```
1428
-
1429
- Add a bill-of-materials entry.
1430
-
1431
- <details><summary><code>BomOpts</code></summary>
1432
-
1433
- ```ts
1434
- interface BomOpts {
1435
- /** Quantity unit label, e.g. "mm", "pieces", "kg". Default: "pieces" */
1436
- unit?: string;
1437
- /** Optional explicit grouping key used during report aggregation. */
1438
- key?: string;
1439
- }
1440
- ```
1441
-
1442
- </details>
1443
-
1444
- #### `robotExport()`
1445
-
1446
- ```ts
1447
- robotExport(options: RobotExportOptions): CollectedRobotExport
1448
- ```
1449
-
1450
- 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).
1451
-
1452
- <details><summary><code>RobotExportOptions</code></summary>
1453
-
1454
- ```ts
1455
- interface RobotExportOptions {
1456
- assembly: Assembly;
1457
- modelName?: string;
1458
- state?: JointState;
1459
- static?: boolean;
1460
- selfCollide?: boolean;
1461
- allowAutoDisable?: boolean;
1462
- links?: Record<string, RobotLinkExportOptions>;
1463
- joints?: Record<string, RobotJointExportOptions>;
1464
- diffDrive?: RobotDiffDrivePluginOptions;
1465
- jointStatePublisher?: RobotJointStatePublisherOptions;
1466
- world?: RobotWorldOptions;
1467
- }
1468
- ```
1469
-
1470
- </details>
1471
-
1472
- <details><summary><code>RobotLinkExportOptions</code></summary>
1473
-
1474
- ```ts
1475
- interface RobotLinkExportOptions {
1476
- massKg?: number;
1477
- densityKgM3?: number;
1478
- collision?: "visual" | "convex" | "box" | "none";
1479
- }
1480
- ```
1481
-
1482
- </details>
1483
-
1484
- <details><summary><code>RobotJointExportOptions</code></summary>
1485
-
1486
- ```ts
1487
- interface RobotJointExportOptions {
1488
- effort?: number;
1489
- velocity?: number;
1490
- damping?: number;
1491
- friction?: number;
1492
- }
1493
- ```
1494
-
1495
- </details>
1496
-
1497
- <details><summary><code>RobotDiffDrivePluginOptions</code></summary>
1498
-
1499
- ```ts
1500
- interface RobotDiffDrivePluginOptions {
1501
- leftJoints: string[];
1502
- rightJoints: string[];
1503
- wheelSeparationMm: number;
1504
- wheelRadiusMm: number;
1505
- topic?: string;
1506
- odomTopic?: string;
1507
- tfTopic?: string;
1508
- frameId?: string;
1509
- odomFrameId?: string;
1510
- maxLinearVelocity?: number;
1511
- maxAngularVelocity?: number;
1512
- linearAcceleration?: number;
1513
- angularAcceleration?: number;
1514
- }
1515
- ```
1516
-
1517
- </details>
1518
-
1519
- <details><summary><code>RobotJointStatePublisherOptions</code></summary>
1520
-
1521
- ```ts
1522
- interface RobotJointStatePublisherOptions {
1523
- enabled?: boolean;
1524
- joints?: string[];
1525
- topic?: string;
1526
- updateRate?: number;
1527
- }
1528
- ```
1529
-
1530
- </details>
1531
-
1532
- <details><summary><code>RobotWorldOptions</code></summary>
1533
-
1534
- ```ts
1535
- interface RobotWorldOptions {
1536
- name?: string;
1537
- generateDemoWorld?: boolean;
1538
- spawnPose?: RobotPose6;
1539
- keyboardTeleop?: RobotWorldKeyboardTeleopOptions;
1540
- }
1541
- ```
1542
-
1543
- </details>
1544
-
1545
- <details><summary><code>RobotWorldKeyboardTeleopOptions</code></summary>
1546
-
1547
- ```ts
1548
- interface RobotWorldKeyboardTeleopOptions {
1549
- enabled?: boolean;
1550
- linearStep?: number;
1551
- angularStep?: number;
1552
- }
1553
- ```
1554
-
1555
- </details>
1556
-
1557
- <details><summary><code>CollectedRobotExport</code></summary>
1558
-
1559
- ```ts
1560
- interface CollectedRobotExport {
1561
- modelName: string;
1562
- assembly: AssemblyDefinition;
1563
- state: JointState;
1564
- static: boolean;
1565
- selfCollide: boolean;
1566
- allowAutoDisable: boolean;
1567
- links: Record<string, RobotLinkExportOptions>;
1568
- joints: Record<string, RobotJointExportOptions>;
1569
- diffDrive?: RobotDiffDrivePluginOptions;
1570
- jointStatePublisher?: RobotJointStatePublisherOptions;
1571
- world: RobotWorldOptions | null;
1572
- }
1573
- ```
1574
-
1575
- </details>
1576
-
1577
- <details><summary><code>AssemblyDefinition</code></summary>
1578
-
1579
- ```ts
1580
- interface AssemblyDefinition {
1581
- name: string;
1582
- parts: AssemblyPartDef[];
1583
- joints: AssemblyJointDef[];
1584
- jointCouplings: AssemblyJointCouplingDef[];
1585
- }
1586
- ```
1587
-
1588
- </details>
1589
-
1590
- <details><summary><code>AssemblyPartDef</code></summary>
1591
-
1592
- ```ts
1593
- interface AssemblyPartDef {
1594
- name: string;
1595
- part: AssemblyPart;
1596
- base: Transform;
1597
- metadata?: PartMetadata;
1598
- }
1599
- ```
1600
-
1601
- </details>
1602
-
1603
- <details><summary><code>PartMetadata</code></summary>
1604
-
1605
- ```ts
1606
- interface PartMetadata {
1607
- material?: string;
1608
- process?: string;
1609
- tolerance?: string;
1610
- qty?: number;
1611
- notes?: string;
1612
- densityKgM3?: number;
1613
- massKg?: number;
1614
- }
1615
- ```
1616
-
1617
- </details>
1618
-
1619
- <details><summary><code>AssemblyJointDef</code></summary>
1620
-
1621
- ```ts
1622
- interface AssemblyJointDef {
1623
- name: string;
1624
- type: JointType;
1625
- parent: string;
1626
- child: string;
1627
- frame: Transform;
1628
- axis: Vec3;
1629
- min?: number;
1630
- max?: number;
1631
- defaultValue: number;
1632
- unit?: string;
1633
- effort?: number;
1634
- velocity?: number;
1635
- damping?: number;
1636
- friction?: number;
1637
- }
1638
- ```
1639
-
1640
- </details>
1641
-
1642
- <details><summary><code>AssemblyJointCouplingDef</code></summary>
1643
-
1644
- ```ts
1645
- interface AssemblyJointCouplingDef {
1646
- joint: string;
1647
- terms: JointCouplingTermRecord[];
1648
- offset: number;
1649
- }
1650
- ```
1651
-
1652
- </details>
1653
-
1654
- <details><summary><code>JointCouplingTermRecord</code></summary>
1655
-
1656
- ```ts
1657
- interface JointCouplingTermRecord {
1658
- joint: string;
1659
- ratio: number;
1660
- }
1661
- ```
1662
-
1663
- </details>
1664
-
1665
- #### `sheetMetal()`
1666
-
1667
- ```ts
1668
- sheetMetal(options: SheetMetalOptions): SheetMetalPart
1669
- ```
1670
-
1671
- Create a sheet-metal part with flanges, bend allowances, and flat pattern unfolding. Define the base panel, thickness, bend radius, and K-factor, then chain .flange() and .cutout() calls. Materialize with .folded() or .flatPattern().
1672
-
1673
- <details><summary><code>SheetMetalOptions</code></summary>
1674
-
1675
- ```ts
1676
- interface SheetMetalOptions {
1677
- width: number;
1678
- height: number;
1679
- thickness: number;
1680
- bendRadius: number;
1681
- kFactor: number;
1682
- kind?: "rect";
1683
- size: number;
1684
- }
1685
- ```
1686
-
1687
- </details>
1688
-
1689
- #### `sketchToDxf()`
1690
-
1691
- ```ts
1692
- sketchToDxf(sketch: Sketch, options?: SketchDxfOptions): string
1693
- ```
1694
-
1695
- 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.
1696
-
1697
- <details><summary><code>SketchDxfOptions</code></summary>
1698
-
1699
- ```ts
1700
- interface SketchDxfOptions {
1701
- /** DXF layer name. Default: "0" */
1702
- layer?: string;
1703
- /** DXF color index (1–255, AutoCAD ACI). Default: 7 (white/black) */
1704
- colorIndex?: number;
1705
- }
1706
- ```
1707
-
1708
- </details>
1709
-
1710
- #### `sketchToSvg()`
1711
-
1712
- ```ts
1713
- sketchToSvg(sketch: Sketch, options?: SketchSvgOptions): string
1714
- ```
1715
-
1716
- 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).
1717
-
1718
- <details><summary><code>SketchSvgOptions</code></summary>
1719
-
1720
- ```ts
1721
- interface SketchSvgOptions {
1722
- /** Stroke color. Default: "black" */
1723
- stroke?: string;
1724
- /** Stroke width in sketch units. Default: 0.5 */
1725
- strokeWidth?: number;
1726
- /** Fill color. Default: "none" */
1727
- fill?: string;
1728
- /** Padding around the sketch bounding box in sketch units. Default: 2 */
1729
- padding?: number;
1730
- /** If set, scale so 1 sketch-unit = this many px. Otherwise auto-fit. */
1731
- pixelsPerUnit?: number;
1732
- }
1733
- ```
1734
-
1735
- </details>
1736
-
1737
- ---
1738
-
1739
- ## C14: Visual & Debugging
1740
-
1741
- Control viewport appearance and debugging aids.
1742
-
1743
- #### `explodeView()`
1744
-
1745
- ```ts
1746
- explodeView(options?: ExplodeViewOptions): void
1747
- ```
1748
-
1749
- Configure viewport exploded-view behavior for the current script execution. Multiple calls merge; later values override earlier ones.
1750
-
1751
- <details><summary><code>ExplodeViewOptions</code></summary>
1752
-
1753
- ```ts
1754
- interface ExplodeViewOptions {
1755
- /** Set false to disable viewport explode offsets for this script output. */
1756
- enabled?: boolean;
1757
- /** Scales the UI explode amount. Default: 1 */
1758
- amountScale?: number;
1759
- /** Per-depth stage multipliers (depth 1 = first level). If depth exceeds this array, the last value is reused. Default when omitted: reciprocal depth (1, 1/2, 1/3, ...) */
1760
- stages?: number[];
1761
- /** Global direction mode fallback. Default: 'radial' */
1762
- mode?: ExplodeViewDirection;
1763
- /** Global axis lock fallback. */
1764
- axisLock?: ExplodeAxis;
1765
- /** Per-object overrides by final object name. */
1766
- byName?: Record<string, ExplodeViewDirective>;
1767
- /** Per-tree-path overrides using slash-separated object tree segments. */
1768
- byPath?: Record<string, ExplodeViewDirective>;
1769
- }
1770
- ```
1771
-
1772
- </details>
1773
-
1774
- <details><summary><code>ExplodeDirective</code></summary>
1775
-
1776
- ```ts
1777
- interface ExplodeDirective {
1778
- /** Multiplier applied to `amount` for this node */
1779
- stage?: number;
1780
- /** Direction mode for this node */
1781
- direction?: ExplodeDirection;
1782
- /** Optional axis lock after direction is resolved */
1783
- axisLock?: ExplodeAxis;
1784
- }
1785
- ```
1786
-
1787
- </details>
1788
-
1789
- <details><summary><code>ExplodeViewDirective</code> extends ExplodeDirective</summary>
1790
-
1791
- ```ts
1792
- interface ExplodeViewDirective extends ExplodeDirective {
1793
- }
1794
- ```
1795
-
1796
- </details>
1797
-
1798
- #### `cutPlane()`
1799
-
1800
- ```ts
1801
- cutPlane(name: string, normal: [ number, number, number ], options?: CutPlaneOptions): void
1802
- ```
1803
-
1804
- <details><summary><code>CutPlaneOptions</code></summary>
1805
-
1806
- ```ts
1807
- interface CutPlaneOptions {
1808
- /** Optional offset along the plane normal (primarily for object-form overload). */
1809
- offset?: number;
1810
- /** Object names to keep uncut for this plane. */
1811
- exclude?: CutPlaneExcludeInput;
1812
- }
1813
- ```
1814
-
1815
- </details>
1816
-
1817
- #### `scene()`
1818
-
1819
- ```ts
1820
- scene(options: SceneOptions): void
1821
- ```
1822
-
1823
- Configure the scene environment for the current script execution. Controls camera, lighting, background, fog, and post-processing. Multiple calls merge; later values override earlier ones. ```js scene({ background: '#0a0a0a', camera: { position: [200, 100, 150], target: [0, 0, 30], fov: 60 }, lights: [ { type: 'ambient', color: '#1a1a2e', intensity: 0.2 }, { type: 'point', position: [0, 0, 100], color: '#ff6b35', intensity: 2 }, ], fog: { color: '#0a0a0a', near: 100, far: 500 }, postProcessing: { bloom: { intensity: 1.5, threshold: 0.8, radius: 0.4 }, }, }); ```
1824
-
1825
- <details><summary><code>SceneOptions</code></summary>
1826
-
1827
- ```ts
1828
- interface SceneOptions {
1829
- background?: string | SceneBackgroundGradient;
1830
- camera?: SceneCameraConfig;
1831
- lights?: SceneLightConfig[];
1832
- environment?: SceneEnvironmentConfig;
1833
- fog?: SceneFogConfig;
1834
- postProcessing?: ScenePostProcessingConfig;
1835
- ground?: SceneGroundConfig;
1836
- /** Default capture parameters for `forgecad capture` — CLI flags override these. */
1837
- capture?: SceneCaptureConfig;
1838
- }
1839
- ```
1840
-
1841
- </details>
1842
-
1843
- <details><summary><code>SceneBackgroundGradient</code></summary>
1844
-
1845
- ```ts
1846
- interface SceneBackgroundGradient {
1847
- top: string;
1848
- bottom: string;
1849
- }
1850
- ```
1851
-
1852
- </details>
1853
-
1854
- <details><summary><code>SceneCameraConfig</code></summary>
1855
-
1856
- ```ts
1857
- interface SceneCameraConfig {
1858
- fov?: number;
1859
- type?: "perspective" | "orthographic";
1860
- }
1861
- ```
1862
-
1863
- </details>
1864
-
1865
- <details><summary><code>SceneLightConfig</code></summary>
1866
-
1867
- ```ts
1868
- interface SceneLightConfig {
1869
- type: SceneLightType;
1870
- color?: string;
1871
- intensity?: number;
1872
- /** Ground color for hemisphere lights */
1873
- groundColor?: string;
1874
- /** Sky color alias for hemisphere lights (same as color) */
1875
- skyColor?: string;
1876
- /** Spot light cone angle in radians */
1877
- angle?: number;
1878
- /** Spot light penumbra (0–1) */
1879
- penumbra?: number;
1880
- /** Point/spot light decay */
1881
- decay?: number;
1882
- /** Point/spot light distance (0 = infinite) */
1883
- distance?: number;
1884
- /** Whether this light casts shadows */
1885
- castShadow?: boolean;
1886
- }
1887
- ```
1888
-
1889
- </details>
1890
-
1891
- <details><summary><code>SceneEnvironmentConfig</code></summary>
1892
-
1893
- ```ts
1894
- interface SceneEnvironmentConfig {
1895
- /** Built-in preset name or 'none' to disable */
1896
- preset?: "studio" | "sunset" | "dawn" | "warehouse" | "forest" | "apartment" | "lobby" | "city" | "park" | "night" | "none";
1897
- /** Environment map intensity */
1898
- intensity?: number;
1899
- /** Use environment map as scene background */
1900
- background?: boolean;
1901
- }
1902
- ```
1903
-
1904
- </details>
1905
-
1906
- <details><summary><code>SceneFogConfig</code></summary>
1907
-
1908
- ```ts
1909
- interface SceneFogConfig {
1910
- color?: string;
1911
- /** Linear fog near distance */
1912
- near?: number;
1913
- /** Linear fog far distance */
1914
- far?: number;
1915
- /** Exponential fog density (if set, uses FogExp2 instead of linear Fog) */
1916
- density?: number;
1917
- }
1918
- ```
1919
-
1920
- </details>
1921
-
1922
- <details><summary><code>ScenePostProcessingConfig</code></summary>
1923
-
1924
- ```ts
1925
- interface ScenePostProcessingConfig {
1926
- bloom?: SceneBloomConfig;
1927
- vignette?: SceneVignetteConfig;
1928
- grain?: SceneGrainConfig;
1929
- toneMappingExposure?: number;
1930
- }
1931
- ```
1932
-
1933
- </details>
1934
-
1935
- <details><summary><code>SceneBloomConfig</code></summary>
1936
-
1937
- ```ts
1938
- interface SceneBloomConfig {
1939
- intensity?: number;
1940
- threshold?: number;
1941
- radius?: number;
1942
- }
1943
- ```
1944
-
1945
- </details>
1946
-
1947
- <details><summary><code>SceneVignetteConfig</code></summary>
1948
-
1949
- ```ts
1950
- interface SceneVignetteConfig {
1951
- darkness?: number;
1952
- offset?: number;
1953
- }
1954
- ```
1955
-
1956
- </details>
1957
-
1958
- <details><summary><code>SceneGrainConfig</code></summary>
1959
-
1960
- ```ts
1961
- interface SceneGrainConfig {
1962
- intensity?: number;
1963
- }
1964
- ```
1965
-
1966
- </details>
1967
-
1968
- <details><summary><code>SceneGroundConfig</code></summary>
1969
-
1970
- ```ts
1971
- interface SceneGroundConfig {
1972
- /** Show a ground plane */
1973
- visible?: boolean;
1974
- /** Ground color */
1975
- color?: string;
1976
- /** Offset below the model's bounding box minimum Z. Default 0 (flush with model bottom). */
1977
- offset?: number;
1978
- /** Receive shadows on the ground */
1979
- receiveShadow?: boolean;
1980
- }
1981
- ```
1982
-
1983
- </details>
1984
-
1985
- <details><summary><code>SceneCaptureConfig</code></summary>
1986
-
1987
- ```ts
1988
- interface SceneCaptureConfig {
1989
- /** Frames for one full orbit rotation (default: 72) */
1990
- framesPerTurn?: number;
1991
- /** Frozen frames before motion starts (default: 6) */
1992
- holdFrames?: number;
1993
- /** Orbit pitch angle in degrees (default: auto from camera) */
1994
- pitchDeg?: number;
1995
- /** Output frame rate (default: 24) */
1996
- fps?: number;
1997
- /** Output frame size in pixels (default: 960) */
1998
- size?: number;
1999
- /** Canvas background color for capture (default: '#252526') */
2000
- background?: string;
2001
- }
2002
- ```
2003
-
2004
- </details>
2005
-
2006
- #### `viewConfig()`
2007
-
2008
- ```ts
2009
- viewConfig(options?: ViewConfigOptions): void
2010
- ```
2011
-
2012
- Configure runtime viewport visuals for the current script execution. Multiple calls merge; later values override earlier ones.
2013
-
2014
- <details><summary><code>ViewConfigOptions</code></summary>
2015
-
2016
- ```ts
2017
- interface ViewConfigOptions {
2018
- jointOverlay?: JointOverlayViewConfigOptions;
2019
- }
2020
- ```
2021
-
2022
- </details>
2023
-
2024
- <details><summary><code>JointOverlayViewConfigOptions</code></summary>
2025
-
2026
- ```ts
2027
- interface JointOverlayViewConfigOptions {
2028
- enabled?: boolean;
2029
- axisColor?: string;
2030
- axisCoreColor?: string;
2031
- arcColor?: string;
2032
- zeroColor?: string;
2033
- arcVisualLimitDeg?: number;
2034
- axisLengthScale?: number;
2035
- axisLengthMin?: number;
2036
- axisLineRadiusScale?: number;
2037
- axisLineRadiusMin?: number;
2038
- axisLineRadiusMax?: number;
2039
- spokeLineRadiusScale?: number;
2040
- spokeLineRadiusMin?: number;
2041
- spokeLineRadiusMax?: number;
2042
- arcLineRadiusScale?: number;
2043
- arcLineRadiusMin?: number;
2044
- arcLineRadiusMax?: number;
2045
- axisDotRadiusScale?: number;
2046
- axisDotRadiusMin?: number;
2047
- axisArrowRadiusScale?: number;
2048
- axisArrowRadiusMin?: number;
2049
- axisArrowLengthScale?: number;
2050
- axisArrowLengthMin?: number;
2051
- axisArrowOffsetFactor?: number;
2052
- arcRadiusScale?: number;
2053
- arcRadiusMin?: number;
2054
- arcDotRadiusScale?: number;
2055
- arcDotRadiusMin?: number;
2056
- arcArrowRadiusScale?: number;
2057
- arcArrowRadiusMin?: number;
2058
- arcArrowLengthScale?: number;
2059
- arcArrowLengthMin?: number;
2060
- arcArrowOffsetFactor?: number;
2061
- arcStepDeg?: number;
2062
- arcMinSteps?: number;
2063
- arcTubeSegmentsMin?: number;
2064
- arcTubeSegmentsFactor?: number;
2065
- arcTubeRadialSegments?: number;
2066
- }
2067
- ```
2068
-
2069
- </details>
2070
-
2071
- #### `spec()`
2072
-
2073
- ```ts
2074
- spec(name: string, checkFn: (...args: any[]) => void): Spec
2075
- ```
2076
-
2077
- Create a named spec — a reusable bundle of verification checks. ```js const fitSpec = spec("Fits enclosure", (shape) => { verify.lessThan("Width", shape.boundingBox().max[0] - shape.boundingBox().min[0], 200); verify.notEmpty("Has geometry", shape); }); fitSpec.check(myShape); // grouped as "Fits enclosure" in the Checks panel fitSpec.check(otherShape); // can be reused on multiple shapes ``` calls `verify.*` methods. Any verify calls made inside this function are tagged with the spec name for grouped display.
2078
-
2079
- <details><summary><code>Spec</code></summary>
2080
-
2081
- ```ts
2082
- interface Spec {
2083
- /** The display name of this spec */
2084
- name: string;
2085
- }
2086
- ```
2087
-
2088
- </details>
2089
-
2090
- ---
2091
-
2092
- ## C15: Import & Composition
2093
-
2094
- Bring external geometry or other ForgeCAD modules into the current script.
2095
-
2096
- #### `group()`
2097
-
2098
- ```ts
2099
- group(...items: GroupInput[]): ShapeGroup
2100
- ```
2101
-
2102
- Group multiple shapes/sketches for joint transforms without merging into a single mesh. Unlike union(), colors and individual identities are preserved. Children can be plain shapes, named descriptors ({ name, shape/sketch/group }), or nested groups. The returned ShapeGroup supports all Shape transforms (translate, rotate, etc.).
2103
-
2104
- ---
2105
-
2106
- ## C16: Part Library
2107
-
2108
- Pre-built parametric parts accessible via `lib.*`.
2109
-
2110
- *No free functions — see class methods (Shape, Sketch, ConstrainedSketchBuilder).*
2111
-
2112
- ---