forgecad 0.9.14 → 0.9.15

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 (219) hide show
  1. package/LICENSE +6 -4
  2. package/README.md +8 -4
  3. package/dist/assets/{AdminPage-eWGs2K6H.js → AdminPage-CDyGUinA.js} +2 -2
  4. package/dist/assets/{BenchmarkPage-CTrLKfpo.js → BenchmarkPage-DfPMY_-d.js} +4 -15
  5. package/dist/assets/{BlogPage-5nPesyds.js → BlogPage-kF0fkdJT.js} +2 -2
  6. package/dist/assets/{DocsPage-C4Y3nbYc.js → DocsPage-B954L3YN.js} +9 -3
  7. package/dist/assets/EditorApp-Beb-IZ0y.js +14014 -0
  8. package/dist/assets/{EditorApp-BAnckbsk.css → EditorApp-CuDLxKqL.css} +698 -0
  9. package/dist/assets/{EmbedViewer-C8fB4n5U.js → EmbedViewer-C77B-TrF.js} +3 -3
  10. package/dist/assets/{LandingPageProofDriven-jSz0LaMM.js → LandingPageProofDriven-Cr6fXMDj.js} +35 -37
  11. package/dist/assets/LegalPage-BRlScr9A.css +91 -0
  12. package/dist/assets/LegalPage-Dzklqmmg.js +39 -0
  13. package/dist/assets/{PricingPage-BMedqFef.css → PricingPage-BPF6HKyO.css} +25 -0
  14. package/dist/assets/{PricingPage-B83B90zh.js → PricingPage-zWXkvlwl.js} +19 -19
  15. package/dist/assets/{SettingsPage-DY889pcu.js → SettingsPage-Bz0of4KQ.js} +2 -2
  16. package/dist/assets/app-CE3sYcV7.css +3890 -0
  17. package/dist/assets/{app-bEww1ic4.js → app-D3kDkggg.js} +2293 -946
  18. package/dist/assets/cli/{render-Cho2uKG_.js → render-DSY3mMQa.js} +337 -7
  19. package/dist/assets/{constructionHistoryWorker-HYwzJY4m.js → constructionHistoryWorker-gpDo-uH2.js} +927 -243
  20. package/dist/assets/{evalWorker-CjQwJSE-.js → evalWorker-CU0Ke6DP.js} +7800 -4164
  21. package/dist/assets/{forgecad_geometry-CH2nvuLA.js → forgecad_geometry-Dgceylq9.js} +43 -1
  22. package/dist/assets/forgecad_geometry_bg-dD4RNQF1.wasm +0 -0
  23. package/dist/assets/{inspectWorker-DeRnMVv1.js → inspectWorker-COyp8XXA.js} +927 -243
  24. package/dist/assets/{javascript-70-4uGcz.js → javascript-1kQXfVaz.js} +1 -1
  25. package/dist/assets/landing-proof-driven-DiGqdtWa.js +18 -0
  26. package/dist/assets/{landing-proof-driven-oFYW6mjz.css → landing-proof-driven-ORyigZ6p.css} +13 -7
  27. package/dist/assets/legalContent-ZfFGMmi4.js +251 -0
  28. package/dist/assets/{manifold-CG9Fokx-.js → manifold-BRI5prcH.js} +1 -1
  29. package/dist/assets/{manifold-uRzgk5O8.js → manifold-C-3h2M7p.js} +2 -2
  30. package/dist/assets/{manifold-rmfAcdwF.js → manifold-DNkrUWpA.js} +1 -1
  31. package/dist/assets/{reportWorker-4cW_ZpoS.js → reportWorker-CdBz5bNg.js} +7538 -10857
  32. package/dist/assets/{scalar-sampling-budget-CfDiFvh7.js → scalar-sampling-budget-wJF98aY9.js} +6935 -4331
  33. package/dist/assets/{scanProxyWorker-Bs2TDgLw.js → scanProxyWorker-B-9VbLIs.js} +32 -1
  34. package/dist/assets/{solver-DuJAO8S6.js → solver-BZ9LPTHs.js} +1 -1
  35. package/dist/assets/solver_bg-DAHZJ_rw.wasm +0 -0
  36. package/dist/assets/{targets-D6PWsv6X.js → targets-B9sGB5nB.js} +1 -1
  37. package/dist/assets/{vendor-react-Da3A2QmU.js → vendor-react-6j1Kke-Y.js} +6 -5
  38. package/dist/cli/render.html +1 -1
  39. package/dist/docs/index.html +2 -2
  40. package/dist/docs-raw/AI/ai-native-cad.md +50 -0
  41. package/dist/docs-raw/AI/usage.md +3 -12
  42. package/dist/docs-raw/CLI.md +30 -10
  43. package/dist/docs-raw/component-model.md +27 -11
  44. package/dist/docs-raw/generated/assembly.md +301 -212
  45. package/dist/docs-raw/generated/concepts.md +235 -237
  46. package/dist/docs-raw/generated/core.md +283 -6
  47. package/dist/docs-raw/generated/curves.md +274 -361
  48. package/dist/docs-raw/generated/lib.md +7 -1
  49. package/dist/docs-raw/generated/output.md +19 -4
  50. package/dist/docs-raw/generated/runtime-names.md +41 -0
  51. package/dist/docs-raw/generated/sdf.md +31 -0
  52. package/dist/docs-raw/generated/sheet-metal.md +9 -0
  53. package/dist/docs-raw/generated/sketch.md +44 -1
  54. package/dist/docs-raw/generated/viewport.md +11 -3
  55. package/dist/docs-raw/guides/coordinate-system.md +20 -16
  56. package/dist/docs-raw/guides/geometry-conventions.md +2 -2
  57. package/dist/docs-raw/guides/inspection-bundles.md +2 -1
  58. package/dist/docs-raw/guides/joint-design.md +24 -0
  59. package/dist/docs-raw/guides/positioning.md +13 -3
  60. package/dist/docs-raw/legal/privacy.md +63 -0
  61. package/dist/docs-raw/legal/software-license.md +55 -0
  62. package/dist/docs-raw/legal/terms.md +87 -0
  63. package/dist/docs-raw/skills/forgecad-3d-reconstruction.md +1 -1
  64. package/dist/docs-raw/skills/forgecad-blockout-model.md +1 -1
  65. package/dist/docs-raw/skills/forgecad-component-model.md +11 -2
  66. package/dist/docs-raw/skills/forgecad-high-level-spec.md +1 -1
  67. package/dist/docs-raw/skills/forgecad-image-replicator.md +8 -8
  68. package/dist/docs-raw/skills/forgecad-lld.md +1 -1
  69. package/dist/docs-raw/skills/forgecad-make-a-model.md +1 -1
  70. package/dist/docs-raw/skills/forgecad-model-grader.md +2 -2
  71. package/dist/docs-raw/skills/forgecad-prepare-prompt.md +2 -2
  72. package/dist/docs-raw/skills/forgecad-project.md +1 -1
  73. package/dist/docs-raw/skills/forgecad-reconstruction-benchmark.md +1 -1
  74. package/dist/docs-raw/skills/forgecad-render-inspect.md +4 -2
  75. package/dist/docs-raw/skills/forgecad-visual-spec.md +1 -1
  76. package/dist/docs-raw/skills/forgecad.md +4 -3
  77. package/dist/index.html +40 -12
  78. package/dist/llms.txt +8 -0
  79. package/dist/site.webmanifest +1 -1
  80. package/dist/sitemap.xml +49 -13
  81. package/dist-cli/{check-compiler-U5SOPN7X.js → check-compiler-SDX5QIXI.js} +1 -2
  82. package/dist-cli/{check-query-propagation-XOKNSSYU.js → check-query-propagation-EAYEFT77.js} +1 -2
  83. package/dist-cli/{chunk-EXWGNL6K.js → chunk-N4O47JLF.js} +12540 -9046
  84. package/dist-cli/forgecad.js +1786 -679
  85. package/dist-cli/{forgecad_geometry-GYVNKPIE.js → forgecad_geometry-QOQIIP53.js} +42 -1
  86. package/dist-cli/forgecad_geometry_bg.wasm +0 -0
  87. package/dist-cli/{solver-46FFSK2U.js → solver-OK4HECRH.js} +0 -1
  88. package/dist-cli/solver_bg.wasm +0 -0
  89. package/dist-skill/CONTEXT.md +1117 -721
  90. package/dist-skill/SKILL.md +3 -2
  91. package/dist-skill/docs/API/core/concepts.md +64 -1
  92. package/dist-skill/docs/CLI.md +30 -10
  93. package/dist-skill/docs/generated/assembly.md +277 -229
  94. package/dist-skill/docs/generated/core.md +283 -6
  95. package/dist-skill/docs/generated/curves.md +272 -362
  96. package/dist-skill/docs/generated/lib.md +7 -1
  97. package/dist-skill/docs/generated/output.md +19 -4
  98. package/dist-skill/docs/generated/runtime-names.md +41 -0
  99. package/dist-skill/docs/generated/sdf.md +31 -0
  100. package/dist-skill/docs/generated/sheet-metal.md +9 -0
  101. package/dist-skill/docs/generated/sketch.md +44 -2
  102. package/dist-skill/docs/generated/viewport.md +2 -87
  103. package/dist-skill/docs/guides/coordinate-system.md +20 -16
  104. package/dist-skill/docs/guides/geometry-conventions.md +2 -2
  105. package/dist-skill/docs/guides/inspection-bundles.md +2 -1
  106. package/dist-skill/docs/guides/joint-design.md +24 -0
  107. package/dist-skill/docs/guides/positioning.md +13 -3
  108. package/dist-skill/library/forgecad-component-model/SKILL.md +10 -1
  109. package/dist-skill/library/forgecad-image-replicator/SKILL.md +6 -6
  110. package/dist-skill/library/forgecad-image-replicator/scripts/compare_images.py +166 -0
  111. package/dist-skill/library/forgecad-model-grader/SKILL.md +1 -1
  112. package/dist-skill/library/forgecad-prepare-prompt/SKILL.md +1 -1
  113. package/dist-skill/library/forgecad-render-inspect/SKILL.md +3 -1
  114. package/examples/api/assembly-kinematics-foundation.forge.js +65 -0
  115. package/examples/api/assembly-kinematics-four-bar.forge.js +115 -0
  116. package/examples/api/assembly-kinematics-limb.forge.js +116 -0
  117. package/examples/api/connector-frame-rig-chain.forge.js +102 -0
  118. package/examples/api/exact-sheet-shell-assembly.forge.js +0 -2
  119. package/examples/api/exact-surface-studio.forge.js +6 -8
  120. package/examples/api/helix-basics.forge.js +6 -6
  121. package/examples/api/lean-foundations/README.md +12 -0
  122. package/examples/api/lean-foundations/curve-blend-exact.forge.js +22 -0
  123. package/examples/api/lean-foundations/curve-fit-interpolation.forge.js +18 -0
  124. package/examples/api/lean-foundations/curve-helix-canonicalization.forge.js +27 -0
  125. package/examples/api/lean-foundations/curve-route-canonicalization.forge.js +16 -0
  126. package/examples/api/lean-foundations/curve-trim-reverse.forge.js +24 -0
  127. package/examples/api/lean-foundations/exact-curve-arc.forge.js +36 -0
  128. package/examples/api/mixed-edge-finishes-proof.forge.js +8 -11
  129. package/examples/api/route3d-elbow.forge.js +68 -0
  130. package/examples/api/transition-curves.forge.js +44 -15
  131. package/examples/api/y-blend-corner-showcase.forge.js +0 -2
  132. package/examples/generative/coral-vase.forge.js +1 -1
  133. package/examples/nurbs-tube.forge.js +1 -1
  134. package/package.json +14 -13
  135. package/dist/assets/EditorApp-lXv53A1m.js +0 -13610
  136. package/dist/assets/app-CsHnaBWt.css +0 -1789
  137. package/dist/assets/forgecad_geometry_bg-C5_E9Oa9.wasm +0 -0
  138. package/dist/assets/solver_bg-CWvv4lnN.wasm +0 -0
  139. package/dist/docs-raw/API/README.md +0 -16
  140. package/dist/docs-raw/API/core/concepts.md +0 -118
  141. package/dist/docs-raw/INDEX.md +0 -138
  142. package/dist/docs-raw/RELEASING.md +0 -87
  143. package/dist/docs-raw/agent-native-api.md +0 -27
  144. package/dist/docs-raw/beta-deployment.md +0 -304
  145. package/dist/docs-raw/beta-operations.md +0 -325
  146. package/dist/docs-raw/blueprint-first.md +0 -145
  147. package/dist/docs-raw/cli-monetization.md +0 -112
  148. package/dist/docs-raw/coding-best-practices.md +0 -120
  149. package/dist/docs-raw/coding.md +0 -340
  150. package/dist/docs-raw/deployment.md +0 -374
  151. package/dist/docs-raw/guides/skill-maintenance.md +0 -161
  152. package/dist/docs-raw/guides/surface-members.md +0 -82
  153. package/dist/docs-raw/harbor-cli.md +0 -854
  154. package/dist/docs-raw/internals/backend-vocabulary.md +0 -35
  155. package/dist/docs-raw/internals/compiler.md +0 -307
  156. package/dist/docs-raw/internals/constraint-solver-quality.md +0 -161
  157. package/dist/docs-raw/internals/constraint-solver.md +0 -176
  158. package/dist/docs-raw/internals/shape-from-slices.md +0 -152
  159. package/dist/docs-raw/internals/sketch-2d-pipeline.md +0 -108
  160. package/dist/docs-raw/platform/admin.md +0 -45
  161. package/dist/docs-raw/platform/architecture.md +0 -82
  162. package/dist/docs-raw/platform/auth.md +0 -139
  163. package/dist/docs-raw/platform/email.md +0 -67
  164. package/dist/docs-raw/platform/google-oauth-setup.md +0 -88
  165. package/dist/docs-raw/platform/observability.md +0 -197
  166. package/dist/docs-raw/platform/projects.md +0 -111
  167. package/dist/docs-raw/platform/sharing.md +0 -90
  168. package/dist/docs-raw/product/README.md +0 -39
  169. package/dist/docs-raw/product/api-as-product-language.md +0 -13
  170. package/dist/docs-raw/product/business-model.md +0 -15
  171. package/dist/docs-raw/product/competitive-positioning.md +0 -17
  172. package/dist/docs-raw/product/creative-manufacturing.md +0 -15
  173. package/dist/docs-raw/product/founder-story.md +0 -11
  174. package/dist/docs-raw/product/manufacturing-workflows.md +0 -15
  175. package/dist/docs-raw/product/onboarding-first-experience.md +0 -256
  176. package/dist/docs-raw/product/product-loop.md +0 -17
  177. package/dist/docs-raw/product/strategic-decisions.md +0 -22
  178. package/dist/docs-raw/product/user-outreach-email-templates.md +0 -161
  179. package/dist/docs-raw/product/user-segments.md +0 -15
  180. package/dist/docs-raw/product/vision.md +0 -26
  181. package/dist/docs-raw/rl-environments.md +0 -350
  182. package/dist/docs-raw/runbook.md +0 -611
  183. package/dist-cli/check-compiler-U5SOPN7X.js.map +0 -1
  184. package/dist-cli/check-query-propagation-XOKNSSYU.js.map +0 -1
  185. package/dist-cli/chunk-EXWGNL6K.js.map +0 -1
  186. package/dist-cli/forgecad.js.map +0 -1
  187. package/dist-cli/forgecad_geometry-GYVNKPIE.js.map +0 -1
  188. package/dist-cli/solver-46FFSK2U.js.map +0 -1
  189. package/dist-skill/SKILL-dev.md +0 -145
  190. package/dist-skill/docs-dev/API/core/concepts.md +0 -118
  191. package/dist-skill/docs-dev/CLI.md +0 -677
  192. package/dist-skill/docs-dev/agent-native-api.md +0 -27
  193. package/dist-skill/docs-dev/blueprint-first.md +0 -145
  194. package/dist-skill/docs-dev/coding-best-practices.md +0 -120
  195. package/dist-skill/docs-dev/coding.md +0 -340
  196. package/dist-skill/docs-dev/component-model.md +0 -164
  197. package/dist-skill/docs-dev/generated/assembly.md +0 -794
  198. package/dist-skill/docs-dev/generated/core.md +0 -2117
  199. package/dist-skill/docs-dev/generated/curves.md +0 -2583
  200. package/dist-skill/docs-dev/generated/lib.md +0 -169
  201. package/dist-skill/docs-dev/generated/output.md +0 -247
  202. package/dist-skill/docs-dev/generated/sdf.md +0 -446
  203. package/dist-skill/docs-dev/generated/sheet-metal.md +0 -504
  204. package/dist-skill/docs-dev/generated/sketch.md +0 -1811
  205. package/dist-skill/docs-dev/generated/viewport.md +0 -585
  206. package/dist-skill/docs-dev/generated/wood.md +0 -108
  207. package/dist-skill/docs-dev/guides/coordinate-system.md +0 -46
  208. package/dist-skill/docs-dev/guides/geometry-conventions.md +0 -52
  209. package/dist-skill/docs-dev/guides/inspection-bundles.md +0 -485
  210. package/dist-skill/docs-dev/guides/joint-design.md +0 -78
  211. package/dist-skill/docs-dev/guides/modeling-recipes.md +0 -78
  212. package/dist-skill/docs-dev/guides/positioning.md +0 -161
  213. package/dist-skill/docs-dev/guides/skill-maintenance.md +0 -161
  214. package/dist-skill/docs-dev/internals/backend-vocabulary.md +0 -35
  215. package/dist-skill/docs-dev/internals/compiler.md +0 -307
  216. package/dist-skill/docs-dev/internals/constraint-solver-quality.md +0 -161
  217. package/dist-skill/docs-dev/internals/constraint-solver.md +0 -176
  218. package/dist-skill/docs-dev/internals/sketch-2d-pipeline.md +0 -108
  219. package/dist-skill/library/forgecad-image-replicator/scripts/compare_images.mjs +0 -289
@@ -1,1811 +0,0 @@
1
- ---
2
- skill-group: sketch
3
- skill-order: 100
4
- ---
5
-
6
- # Sketch API
7
-
8
- 2D geometry creation, transforms, booleans, constrained sketches, and extrusion.
9
-
10
- ## Contents
11
-
12
- - [2D Sketch Primitives](#2d-sketch-primitives) — `path`, `stroke`, `rect`, `circle2d`, `roundedRect`, `polygon`, `ngon`, `ellipse`, `slot`, `arcSlot`, `star`
13
- - [2D Sketch Booleans](#2d-sketch-booleans) — `union2d`, `difference2d`, `intersection2d`
14
- - [2D Sketch Features](#2d-sketch-features) — `filletCorners`
15
- - [Tracked Solid Edge Features](#tracked-solid-edge-features) — `filletTrackedEdge`, `chamferTrackedEdge`
16
- - [2D Text](#2d-text) — `loadFont`, `text2d`, `textWidth`
17
- - [Constrained Sketches](#constrained-sketches) — `constrainedSketch`, `addRect`, `addPolygon`, `addRegularPolygon`
18
- - [2D Geometry Helpers](#2d-geometry-helpers) — `point`, `line`, `circle`, `degrees`, `radians`
19
- - [Sketch](#sketch) — Transforms, Booleans, Features, Promotion, Placement, Labels, Measurement
20
- - [ConstrainedSketchBuilder](#constrainedsketchbuilder) — Drawing, Entities, Geometric Constraints, Dimensional Constraints, Coincidence & Equality, Tangent Transitions, Shape Constraints, Positioning, Solving
21
- - [ConstraintSketch](#constraintsketch)
22
- - [SketchGroupBuilder](#sketchgroupbuilder)
23
- - [Point2D](#point2d)
24
- - [Line2D](#line2d)
25
- - [Circle2D](#circle2d)
26
- - [Rectangle2D](#rectangle2d)
27
-
28
- ## Functions
29
-
30
- ### 2D Sketch Primitives
31
-
32
- #### `path()` — Create a new [`PathBuilder`](/docs/curves#pathbuilder) for tracing a 2D outline point by point.
33
-
34
- [`PathBuilder`](/docs/curves#pathbuilder) is a fluent API for constructing 2D profiles using a mix of line segments, arcs, bezier curves, and splines. Always start with `.moveTo(x, y)` to set the starting point. Call `.close()` to get a filled `Sketch`, or `.stroke(width)` to thicken an open polyline into a solid profile.
35
-
36
- Edge labels can be assigned with `.label('name')` after any segment — they propagate through extrusion, revolve, loft, and sweep into named faces on the resulting [`Shape`](/docs/core#shape).
37
-
38
- ```ts
39
- // Closed triangle
40
- const triangle = path().moveTo(0, 0).lineH(50).lineV(30).close();
41
-
42
- // L-shaped bracket as a stroke
43
- const bracket = path().moveTo(0, 0).lineH(50).lineV(-70).lineAngled(20, 235).stroke(4);
44
-
45
- // Labeled edges for downstream face references
46
- const slot = path()
47
- .moveTo(0, 0)
48
- .lineTo(30, 0).label('bottom')
49
- .lineTo(30, 10)
50
- .lineTo(0, 10).label('top')
51
- .close();
52
- ```
53
-
54
- ```ts
55
- path(): PathBuilder
56
- ```
57
-
58
- #### `stroke()` — Create a stroked polyline sketch from an array of 2D points.
59
-
60
- ```ts
61
- stroke(points: [ number, number ][], width: number, join?: "Round" | "Square"): Sketch
62
- ```
63
-
64
- #### `rect()` — Create a 2D rectangle centered at the origin.
65
-
66
- ```ts
67
- rect(40, 20).extrude(5);
68
- ```
69
-
70
- ```ts
71
- rect(width: number, height: number): Sketch
72
- ```
73
-
74
- #### `circle2d()` — Create a 2D circle centered at the origin.
75
-
76
- Omit `segments` for a smooth (auto-tessellated) circle. Pass an integer to get a regular polygon approximation — e.g. `6` for a hexagon, `8` for an octagon.
77
-
78
- ```ts
79
- circle2d(25).extrude(10); // smooth cylinder
80
- circle2d(25, 6).extrude(10); // hexagonal prism
81
- ```
82
-
83
- ```ts
84
- circle2d(radius: number, segments?: number): Sketch
85
- ```
86
-
87
- #### `roundedRect()` — Create a 2D rectangle with rounded corners, centered at the origin.
88
-
89
- The corner radius is automatically clamped to `min(width/2, height/2)` so it can never exceed the shape dimensions.
90
-
91
- ```ts
92
- roundedRect(60, 30, 5).extrude(3);
93
- ```
94
-
95
- ```ts
96
- roundedRect(width: number, height: number, radius: number): Sketch
97
- ```
98
-
99
- #### `polygon()` — Create a 2D polygon from an array of `[x, y]` points or `Point2D` objects.
100
-
101
- Winding order is normalized automatically — clockwise (CW) input is silently reversed to CCW before being passed to the geometry kernel.
102
-
103
- ```ts
104
- polygon([[0, 0], [50, 0], [25, 40]]).extrude(5); // triangle
105
- ```
106
-
107
- ```ts
108
- polygon(points: ([ number, number ] | Point2D)[]): Sketch
109
- ```
110
-
111
- #### `ngon()` — Create a regular polygon inscribed in a circle of the given radius.
112
-
113
- `radius` is the center-to-vertex (circumradius) distance. Use `sides` of `3` for a triangle, `6` for a hexagon, etc. The first vertex is at the top (−90° from +X).
114
-
115
- ```ts
116
- ngon(6, 20).extrude(10); // hexagonal prism, circumradius 20
117
- ```
118
-
119
- ```ts
120
- ngon(sides: number, radius: number): Sketch
121
- ```
122
-
123
- #### `ellipse()` — Create a 2D ellipse centered at the origin.
124
-
125
- ```ts
126
- ellipse(30, 15).extrude(5);
127
- ellipse(30, 15, 32).extrude(5); // lower-resolution approximation
128
- ```
129
-
130
- ```ts
131
- ellipse(rx: number, ry: number, segments?: number): Sketch
132
- ```
133
-
134
- #### `slot()` — Create a slot (oblong / stadium shape) — a rectangle with semicircular ends, centered at the origin.
135
-
136
- ```ts
137
- slot(40, 10).extrude(3); // 40mm long, 10mm wide slot
138
- ```
139
-
140
- ```ts
141
- slot(length: number, width: number): Sketch
142
- ```
143
-
144
- #### `arcSlot()` — Create an arc-shaped slot (banana / annular sector) centered at the origin.
145
-
146
- The slot is symmetric about the +X axis. The two ends are closed with semicircular caps. `pitchRadius` is the distance from the origin to the centerline of the slot, and `thickness` is the radial width of the slot.
147
-
148
- ```ts
149
- arcSlot(135, 74, 40).extrude(5); // pitch R135, 74° sweep, 40mm wide
150
- ```
151
-
152
- ```ts
153
- arcSlot(pitchRadius: number, sweepDeg: number, thickness: number): Sketch
154
- ```
155
-
156
- #### `star()` — Create a star shape with alternating outer and inner radii.
157
-
158
- ```ts
159
- star(5, 30, 12).extrude(4); // five-pointed star
160
- ```
161
-
162
- ```ts
163
- star(points: number, outerR: number, innerR: number): Sketch
164
- ```
165
-
166
- ### 2D Sketch Booleans
167
-
168
- #### `union2d()` — Combine 2D sketches into a single profile using an additive boolean union.
169
-
170
- Accepts individual sketches or arrays: `union2d(a, b, c)` or `union2d([a, b, c])`. Uses Manifold's batch operation — faster than chaining `.add()` one by one when combining many sketches.
171
-
172
- ```ts
173
- const cross = union2d(rect(60, 10), rect(10, 60));
174
- ```
175
-
176
- ```ts
177
- union2d(...inputs: SketchOperandInput[]): Sketch
178
- ```
179
-
180
- #### `difference2d()` — Subtract one or more 2D sketches from a base sketch.
181
-
182
- The first sketch is the base; all subsequent sketches are subtracted from it. Accepts individual sketches or arrays: `difference2d(base, c1, c2)` or `difference2d([base, c1, c2])`. Uses Manifold's batch operation — faster than chaining `.subtract()` one by one.
183
-
184
- ```ts
185
- const donut = difference2d(circle2d(50), circle2d(30));
186
- ```
187
-
188
- ```ts
189
- difference2d(...inputs: SketchOperandInput[]): Sketch
190
- ```
191
-
192
- #### `intersection2d()` — Keep only the area where all input sketches overlap (intersection boolean).
193
-
194
- Accepts individual sketches or arrays: `intersection2d(a, b)` or `intersection2d([a, b, c])`. Uses Manifold's batch operation — faster than chaining `.intersect()` one by one.
195
-
196
- ```ts
197
- const lens = intersection2d(circle2d(30).translate(-10, 0), circle2d(30).translate(10, 0));
198
- ```
199
-
200
- ```ts
201
- intersection2d(...inputs: SketchOperandInput[]): Sketch
202
- ```
203
-
204
- ### 2D Sketch Features
205
-
206
- #### `filletCorners()` — Create a polygon from points with specific corners rounded to arc fillets.
207
-
208
- Each corner spec identifies a vertex by its index in the `points` array and the desired fillet `radius`. Both convex and concave corners are supported.
209
-
210
- Constraints:
211
-
212
- - Collinear corners cannot be filleted (throws an error)
213
- - Two neighboring fillets whose tangent lengths overlap the same edge will throw
214
- - Radius must be positive and small enough to fit within the adjacent edge lengths
215
-
216
- Use `offset(-r).offset(+r)` instead if you want to round **all** convex corners uniformly. Use `filletCorners` when you need selective or mixed sharp/rounded profiles.
217
-
218
- ```ts
219
- const roof = filletCorners(roofPoints, [
220
- { index: 3, radius: 19 },
221
- { index: 4, radius: 19 },
222
- { index: 5, radius: 19 },
223
- ]);
224
- ```
225
-
226
- ```ts
227
- filletCorners(points: PointInput[], corners: FilletCornerSpec[]): Sketch
228
- ```
229
-
230
- `FilletCornerSpec`: `{ index: number, radius: number, segments?: number }`
231
-
232
- ### Tracked Solid Edge Features
233
-
234
- #### `filletTrackedEdge()` — Round a tracked vertical solid edge with a circular fillet.
235
-
236
- Compiler-owned fillet for a narrow tracked-edge subset on solids.
237
-
238
- This is **not** a general 2D sketch-corner fillet. It currently works only on tracked vertical edges from [`box()`](/docs/core#box) or `Rectangle2D` extrusions (plus rigid transforms and supported preserved descendants of those). Generic sketch extrudes, including `rect(...).extrude(...)`, are outside the supported subset right now.
239
-
240
- **Supported edges:**
241
-
242
- - Tracked vertical edges from [`box()`](/docs/core#box) or `Rectangle2D.extrude()`
243
- - Rigid transforms between tracked source and target
244
- - Untouched sibling tracked vertical edges after earlier `filletTrackedEdge`/`chamferTrackedEdge`
245
-
246
- **Not supported:** edges after shell, hole, cut, trim, difference, intersection, generic sketch extrudes, or tapered extrudes.
247
-
248
- Canonical quadrants: `vert-bl → [1,-1]`, `vert-br → [-1,-1]`, `vert-tr → [-1,1]`, `vert-tl → [1,1]`
249
-
250
- ```ts
251
- const base = Rectangle2D.fromDimensions(0, 0, 50, 50).extrude(20);
252
- const filleted = filletTrackedEdge(base, base.edge('vert-br'), 5, [-1, -1]);
253
- ```
254
-
255
- ```ts
256
- filletTrackedEdge(shape: Shape, edge: EdgeRef, radius: number, quadrant?: [ number, number ], segments?: number): Shape
257
- ```
258
-
259
- **`EdgeRef`**
260
-
261
- | Option | Type | Description |
262
- |--------|------|-------------|
263
- | `start` | `[ number, number, number ]` | Start point |
264
- | `end` | `[ number, number, number ]` | End point |
265
- | `query?` | `EdgeQueryRef` | Compiler-owned edge query when available. |
266
- | `curve?` | `EdgeCurve` | Exact or parametric curve family when the backend/source can identify one. |
267
- | `faceName?` | `string` | Owning face name when the edge is associated with one face in a larger topology. |
268
- | `name` | | — |
269
-
270
- #### `chamferTrackedEdge()` — Bevel a tracked vertical solid edge with a 45° chamfer.
271
-
272
- Compiler-owned chamfer for tracked vertical edges. Requires a compile-plan-covered target. This is not a general 2D sketch-corner tool; supported subset and quadrant semantics are the same as `filletTrackedEdge()` - see that function for details.
273
-
274
- ```ts
275
- const base = Rectangle2D.fromDimensions(0, 0, 50, 50).extrude(20);
276
- const chamfered = chamferTrackedEdge(base, base.edge('vert-br'), 3, [-1, -1]);
277
- ```
278
-
279
- ```ts
280
- chamferTrackedEdge(shape: Shape, edge: EdgeRef, size: number, quadrant?: [ number, number ]): Shape
281
- ```
282
-
283
- ### 2D Text
284
-
285
- #### `loadFont()` — Pre-load and cache a font for use with `text2d()`.
286
-
287
- Fonts are cached by their source string (or `cacheKey` for `ArrayBuffer` sources), so repeated calls with the same path are free. Pre-loading is useful when you call `text2d()` many times with the same font — it avoids repeated disk reads.
288
-
289
- Built-in font names that work everywhere (browser + CLI):
290
-
291
- - `'sans-serif'` or `'inter'` — bundled Inter Regular
292
-
293
- ```ts
294
- const font = loadFont('/path/to/Arial Bold.ttf');
295
- text2d('Title', { size: 12, font }).extrude(1.5);
296
- text2d('Subtitle', { size: 8, font }).extrude(1);
297
- ```
298
-
299
- ```ts
300
- loadFont(source: string | ArrayBuffer, cacheKey?: string): opentype.Font
301
- ```
302
-
303
- #### `text2d()` — Build a filled 2D Sketch from a text string.
304
-
305
- The Sketch origin is at the left end of the text baseline by default. Use `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.
306
-
307
- `text2d()` creates real geometry. For temporary viewport annotations, prefer `Viewport.label()` so the text stays off the geometry and OCCT compile paths. Do not use either form of text to make unclear production geometry readable; model the physical artifact clearly instead.
308
-
309
- Alignment reference table:
310
-
311
- | `align` | `baseline` | Origin |
312
- |------------|--------------|-------------------------------------|
313
- | `'left'` | `'baseline'` | Bottom-left of first char (default) |
314
- | `'center'` | `'center'` | Dead center of text block |
315
- | `'right'` | `'top'` | Top-right corner |
316
-
317
- ```ts
318
- // Extruded nameplate
319
- text2d('FORGE CAD', { size: 8 }).extrude(1.2);
320
-
321
- // Centered label on the XY plane
322
- text2d('V 2.0', { size: 6, align: 'center', baseline: 'center' });
323
-
324
- // Engraved text cut into the top face of a box
325
- const label = text2d('REV A', { size: 5, align: 'center', baseline: 'center' });
326
- plate.subtract(label.onFace(plate, 'top', { protrude: -0.5 }).extrude(1));
327
-
328
- // Custom TTF font
329
- text2d('Hello', { size: 10, font: '/path/to/Arial.ttf' }).extrude(1);
330
-
331
- // Pre-loaded font for reuse
332
- const font = loadFont('/path/to/Arial Bold.ttf');
333
- text2d('Title', { size: 12, font }).extrude(1.5);
334
- ```
335
-
336
- ```ts
337
- text2d(content: string, options?: TextOptions): Sketch
338
- ```
339
-
340
- **`TextOptions`**
341
-
342
- | Option | Type | Description |
343
- |--------|------|-------------|
344
- | `size?` | `number` | Cap height of the text in model units. All other dimensions (stroke weight, spacing) scale proportionally. |
345
- | `letterSpacing?` | `number` | Extra space between characters in model units. Negative values tighten the tracking. |
346
- | `align?` | `"left" \| "center" \| "right"` | Horizontal alignment relative to x = 0. - `'left'` — left edge at x = 0 (default) - `'center'` — centred on x = 0 - `'right'` — right edge at x = 0 |
347
- | `baseline?` | `"baseline" \| "center" \| "top"` | 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 |
348
- | `font?` | `string \| opentype.Font` | 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'`) |
349
- | `flattenTolerance?` | `number` | Bezier flattening tolerance in model units. Smaller = more polygon segments = smoother curves. |
350
-
351
- #### `textWidth()` — Measure the rendered advance width of a string without creating any geometry.
352
-
353
- Uses the same font metrics as `text2d()`. Useful for computing layout dimensions before building the actual sketch — e.g. sizing a plate to fit a label.
354
-
355
- ```ts
356
- const w = textWidth('SERIAL: 001', { size: 6 });
357
- const plate = box(w + 10, 12, 2);
358
- ```
359
-
360
- ```ts
361
- textWidth(content: string, options?: Pick<TextOptions, "size" | "letterSpacing" | "font">): number
362
- ```
363
-
364
- ### Constrained Sketches
365
-
366
- #### `constrainedSketch()` — Create a parametric 2D sketch driven by geometric constraints and a nonlinear solver.
367
-
368
- **Workflow**
369
-
370
- 1. Create a builder with `constrainedSketch()`.
371
- 2. Add geometry — points, lines, circles, arcs — using the builder methods.
372
- 3. Add constraints (`horizontal`, `length`, `fix`, etc.) to drive the geometry.
373
- 4. Call `.solve()` to run the solver and get a `ConstraintSketch` (which extends `Sketch`).
374
-
375
- ```ts
376
- const sk = constrainedSketch();
377
- const p1 = sk.point(0, 0);
378
- const p2 = sk.point(50, 0);
379
- const l1 = sk.line(p1, p2);
380
- sk.fix(p1, 0, 0);
381
- sk.horizontal(l1);
382
- sk.length(l1, 50);
383
- return sk.solve().extrude(10);
384
- ```
385
-
386
- **Solver status**
387
-
388
- ```ts
389
- const result = sk.solve();
390
- result.constraintMeta.status; // 'fully' | 'under' | 'over' | 'over-redundant'
391
- result.constraintMeta.dof; // 0 = fully constrained
392
- result.constraintMeta.maxError; // residual — should be < 1e-6
393
- result.inspect(); // human-readable summary
394
- result.withUpdatedConstraint('cst-5', 120); // update a dimension without rebuilding
395
- ```
396
-
397
- ```ts
398
- constrainedSketch(options?: ConstrainedSketchOptions): ConstrainedSketchBuilder
399
- ```
400
-
401
- **`ConstrainedSketchOptions`**
402
- - `strict?: boolean` — When true, adding a constraint that cannot be satisfied throws instead of silently discarding it.
403
-
404
- #### `addRect()` — Add an axis-aligned rectangle concept to the builder.
405
-
406
- Creates 4 vertices (CCW: bl→br→tr→tl), 4 sides, 4 structural constraints (`horizontal`/`vertical` on each side), CCW winding, a center point, a loop, and a shape. Returns a `ConstrainedRect` handle with 4 DOF (x, y, width, height).
407
-
408
- Use `sk.rect()` as the shorthand builder method.
409
-
410
- ```ts
411
- const sk = constrainedSketch();
412
- const r = sk.rect({ x: 0, y: 0, width: 100, height: 50 });
413
- sk.fix(r.bottomLeft, 0, 0);
414
- sk.length(r.bottom, 120); // override initial width
415
- return sk.solve().extrude(10);
416
- ```
417
-
418
- ```ts
419
- addRect(sk: ConstrainedSketchBuilder, options?: RectOptions): ConstrainedRect
420
- ```
421
-
422
- **`RectOptions`**
423
-
424
- | Option | Type | Description |
425
- |--------|------|-------------|
426
- | `x?` | `number` | Bottom-left x coordinate. Default: 0. |
427
- | `y?` | `number` | Bottom-left y coordinate. Default: 0. |
428
- | `width?` | `number` | Width (along x). Default: 10. |
429
- | `height?` | `number` | Height (along y). Default: 10. |
430
- | `blockRotation?` | `boolean` | Prevent 180° rotation (ensures bottom edge points rightward). Default: false. |
431
-
432
- **`ConstrainedRect`**
433
-
434
- | Option | Type | Description |
435
- |--------|------|-------------|
436
- | `bottom` | `LineId` | bottom-left → bottom-right |
437
- | `right` | `LineId` | bottom-right → top-right |
438
- | `top` | `LineId` | top-right → top-left |
439
- | `left` | `LineId` | top-left → bottom-left |
440
- | `center` | `PointId` | 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)`. |
441
- | `shape` | `ShapeId` | ShapeId for `shapeWidth`, `shapeHeight`, `shapeArea`, `shapeCentroidX/Y`. |
442
- | `vertices` | `[ PointId, PointId, PointId, PointId ]` | CCW-ordered vertex array: [bottomLeft, bottomRight, topRight, topLeft]. |
443
- | `sides` | `[ LineId, LineId, LineId, LineId ]` | CCW-ordered side array: [bottom, right, top, left]. |
444
- | `bottomLeft`, `bottomRight`, `topRight`, `topLeft` | | — |
445
-
446
- #### `addPolygon()` — Add a general polygon concept to the builder.
447
-
448
- Creates n vertices and n sides (CCW: `sides[i]` from `vertices[i]` → `vertices[(i+1) % n]`). Applies a `ccw` constraint to enforce winding. All dimensional constraints (lengths, angles, position) are left to the caller.
449
-
450
- Use `sk.addPolygon()` as the shorthand builder method.
451
-
452
- ```ts
453
- const sk = constrainedSketch();
454
- const tri = sk.addPolygon({ points: [[0,0],[100,0],[50,80]] });
455
- sk.fix(tri.vertex(0), 0, 0);
456
- sk.length(tri.side(0), 100);
457
- return sk.solve().extrude(5);
458
- ```
459
-
460
- ```ts
461
- addPolygon(sk: ConstrainedSketchBuilder, options: PolygonOptions): ConstrainedPolygon
462
- ```
463
-
464
- **`PolygonOptions`**
465
- - `points: ReadonlyArray<readonly [ number, number ]>` — Initial vertex coordinates. Minimum 3 points.
466
- - `addLoop?: boolean` — Whether to register a closed loop for sketch generation. Default: true.
467
- - `blockRotation?: boolean` — Prevent 180° rotation (ensures first edge maintains its initial direction). Default: false.
468
-
469
- **`ConstrainedPolygon`**
470
- - `vertices: PointId[]` — CCW-ordered PointIds.
471
- - `sides: LineId[]` — CCW-ordered LineIds. `sides[i]` runs from `vertices[i]` → `vertices[(i+1) % n]`.
472
- - `shape: ShapeId` — ShapeId for `shapeWidth`, `shapeHeight`, `shapeArea`, `shapeCentroidX/Y`.
473
-
474
- #### `addRegularPolygon()` — Add a regular n-gon concept to the builder.
475
-
476
- Vertices are placed at `(cx + r·cos(startAngle + i·2π/n), cy + r·sin(...))`. Equal-radius and equal-side constraints enforce regularity (4 DOF: center x/y, radius, rotation). The center point is tracked by the solver and exposed via the returned handle.
477
-
478
- Use `sk.regularPolygon()` as the shorthand builder method.
479
-
480
- ```ts
481
- const sk = constrainedSketch();
482
- const hex = sk.regularPolygon({ sides: 6, radius: 25 });
483
- sk.fix(hex.center, 0, 0);
484
- sk.length(hex.side(0), 30); // all sides change (equal constraint)
485
- return sk.solve().extrude(5);
486
- ```
487
-
488
- ```ts
489
- addRegularPolygon(sk: ConstrainedSketchBuilder, options: RegularPolygonOptions): ConstrainedRegularPolygon
490
- ```
491
-
492
- **`RegularPolygonOptions`**
493
-
494
- | Option | Type | Description |
495
- |--------|------|-------------|
496
- | `sides` | `number` | Number of sides (minimum 3). |
497
- | `radius?` | `number` | Circumradius — distance from center to vertex. Default: 10. |
498
- | `cx?` | `number` | Center x coordinate. Default: 0. |
499
- | `cy?` | `number` | Center y coordinate. Default: 0. |
500
- | `startAngle?` | `number` | Angle (in degrees) of vertex[0] measured from the +X axis (CCW positive). Default: 0 (rightmost vertex). |
501
- | `blockRotation?` | `boolean` | Prevent 180° rotation (ensures first edge maintains its initial direction). Default: false. |
502
-
503
-
504
- **`ConstrainedRegularPolygon`** extends ConstrainedPolygon
505
- - `center: PointId` — Center point. Use `sk.fix(poly.center, x, y)` to pin location, or `sk.coincident(poly.center, other)` to align with other geometry.
506
-
507
- ### 2D Geometry Helpers
508
-
509
- #### `point()` — Create an analytic 2D point for measurement and construction geometry.
510
-
511
- ```ts
512
- const p = point(10, 20);
513
- p.distanceTo(point(30, 40)); // Euclidean distance
514
- p.midpointTo(point(30, 40)); // midpoint
515
- p.translate(5, 5); // new shifted point
516
- p.toTuple(); // [10, 20]
517
- ```
518
-
519
- ```ts
520
- point(x: number, y: number): Point2D
521
- ```
522
-
523
- #### `line()` — Create an analytic 2D line segment between two points.
524
-
525
- ```ts
526
- const l = line(0, 0, 50, 0);
527
- l.length; l.midpoint; l.angle; l.direction;
528
- l.parallel(10); // parallel line offset 10 (positive = left)
529
- l.intersect(l2); // Point2D — treats lines as infinite
530
- l.intersectSegment(l2); // Point2D or null — segments only
531
-
532
- Line2D.fromPointAndAngle(point(0, 0), 45, 100);
533
- Line2D.fromPointAndDirection(point(0, 0), [1, 1], 50);
534
- ```
535
-
536
- ```ts
537
- line(x1: number, y1: number, x2: number, y2: number): Line2D
538
- ```
539
-
540
- #### `circle()` — Create an analytic 2D circle for measurement, construction, and extrusion.
541
-
542
- ```ts
543
- const c = circle(0, 0, 25);
544
- c.diameter; c.circumference; c.area;
545
- c.pointAtAngle(90); // Point2D at top (90° CCW from +X)
546
-
547
- // Extrude to cylinder with named faces
548
- const cyl = c.extrude(30);
549
- cyl.face('top'); // FaceRef (planar)
550
- cyl.face('side'); // FaceRef (curved)
551
-
552
- Circle2D.fromDiameter(point(0, 0), 50);
553
- ```
554
-
555
- ```ts
556
- circle(cx: number, cy: number, radius: number): Circle2D
557
- ```
558
-
559
- #### `degrees()` — Identity function that returns degrees unchanged.
560
-
561
- Use for clarity when the unit of an angle value would otherwise be ambiguous — e.g. `param("Angle", degrees(45))`.
562
-
563
- ```ts
564
- degrees(deg: number): number
565
- ```
566
-
567
- #### `radians()` — Convert radians to degrees.
568
-
569
- ForgeCAD's public API uses degrees throughout. Use this when you have a radian value (e.g. from `Math.atan2`) that you want to express in degrees.
570
-
571
- ```ts
572
- radians(rad: number): number
573
- ```
574
-
575
- ---
576
-
577
- ## Classes
578
-
579
- ### `Sketch`
580
-
581
- Immutable 2D profile for extrusion, revolve, and other operations.
582
-
583
- `Sketch` wraps Manifold's `CrossSection` with a chainable 2D API. Every method returns a new `Sketch` — the original is never mutated. Colors, edge labels, and placement data are preserved through all transforms and boolean operations.
584
-
585
- Supported operations:
586
-
587
- - **Transforms** — `translate`, `rotate`, `rotateAround`, `scale`, `mirror`
588
- - **Booleans** — `add` (union), `subtract` (difference), `intersect`
589
- - **Operations** — `offset`, `simplify`
590
- - **Queries** — `area`, `bounds`, `isEmpty`, `numVert`
591
- - **3D operations** — `extrude`, `revolve`, `onFace`
592
- - **Regions** — `regions`, `region`
593
- - **Placement** — `attachTo`
594
-
595
- Named anchor positions used by `attachTo()`: `'center'` | `'top-left'` | `'top-right'` | `'bottom-left'` | `'bottom-right'` | `'top'` | `'bottom'` | `'left'` | `'right'`
596
-
597
- **Properties:**
598
-
599
- | Property | Type | Description |
600
- |----------|------|-------------|
601
- | `cross` | `ProfileBackend` | — |
602
-
603
- **Transforms**
604
-
605
- #### `translate()` — Move the sketch by the given X and Y offset.
606
-
607
- ```ts
608
- translate(x: number, y?: number): Sketch
609
- ```
610
-
611
- #### `rotate()` — Rotate the sketch around its bounding-box center.
612
-
613
- ```ts
614
- rotate(degrees: number): Sketch
615
- ```
616
-
617
- #### `rotateAround()` — Rotate the sketch around a specific pivot point.
618
-
619
- ```ts
620
- rect(20, 20).rotateAround(45, [0, 0]);
621
- ```
622
-
623
- ```ts
624
- rotateAround(degrees: number, pivot: [ number, number ]): Sketch
625
- ```
626
-
627
- #### `scale()` — Scale the sketch relative to its bounding-box center.
628
-
629
- Pass a single number for uniform scaling, or `[sx, sy]` for per-axis scaling.
630
-
631
- ```ts
632
- scale(v: number | [ number, number ]): Sketch
633
- ```
634
-
635
- #### `scaleAround()` — Scale the sketch relative to an arbitrary pivot point.
636
-
637
- ```ts
638
- scaleAround(pivot: [ number, number ], v: number | [ number, number ]): Sketch
639
- ```
640
-
641
- #### `mirror()` — Mirror the sketch across a line through its bounding-box center.
642
-
643
- `normal` is the normal vector of the mirror line (not the line direction). For example, `[1, 0]` mirrors across a vertical line (Y axis direction), and `[0, 1]` mirrors across a horizontal line.
644
-
645
- ```ts
646
- mirror(normal: [ number, number ]): Sketch
647
- ```
648
-
649
- #### `mirrorThrough()` — Mirror the sketch across a line defined by a point and a normal direction.
650
-
651
- ```ts
652
- mirrorThrough(point: [ number, number ], normal: [ number, number ]): Sketch
653
- ```
654
-
655
- **Booleans**
656
-
657
- #### `add()` — Add (union) one or more sketches to this sketch.
658
-
659
- Accepts individual sketches or arrays: `sketch.add(a, b)` or `sketch.add([a, b])`. For combining many sketches at once, prefer the free function `union2d()` which uses Manifold's batch operation and is faster than chaining.
660
-
661
- ```ts
662
- circle2d(20).add(rect(10, 30)).extrude(5);
663
- ```
664
-
665
- ```ts
666
- add(...others: SketchOperandInput[]): Sketch
667
- ```
668
-
669
- #### `subtract()` — Subtract one or more sketches from this sketch.
670
-
671
- Accepts individual sketches or arrays: `sketch.subtract(a, b)` or `sketch.subtract([a, b])`. For subtracting many cutters at once, prefer the free function `difference2d()`.
672
-
673
- ```ts
674
- rect(40, 40).subtract(circle2d(10)).extrude(5);
675
- ```
676
-
677
- ```ts
678
- subtract(...others: SketchOperandInput[]): Sketch
679
- ```
680
-
681
- #### `intersect()` — Intersect this sketch with one or more others (keep overlapping area only).
682
-
683
- Accepts individual sketches or arrays: `sketch.intersect(a, b)` or `sketch.intersect([a, b])`. For intersecting many sketches, prefer the free function `intersection2d()`.
684
-
685
- ```ts
686
- intersect(...others: SketchOperandInput[]): Sketch
687
- ```
688
-
689
- **Features**
690
-
691
- #### `offset()` — Inflate (positive delta) or deflate (negative delta) the sketch contour.
692
-
693
- Use `offset(-r).offset(+r)` to round every convex corner of a closed sketch.
694
-
695
- - `'Round'` — smooth arc at each corner (default)
696
- - `'Square'` — flat mitered extension
697
- - `'Miter'` — sharp pointed extension
698
-
699
- ```ts
700
- rect(40, 20).offset(3); // expand by 3
701
- rect(40, 20).offset(-2).offset(2); // round all convex corners
702
- ```
703
-
704
- ```ts
705
- offset(delta: number, join?: "Square" | "Round" | "Miter"): Sketch
706
- ```
707
-
708
- #### `regions()` — Decompose this sketch into its distinct filled regions, sorted largest-first by area.
709
-
710
- A single sketch can contain several disconnected filled areas (e.g., two separate rectangles, or a ring shape with a hole). This method enumerates all top-level connected regions as independent `Sketch` objects, each with its own outer boundary and associated holes.
711
-
712
- ```ts
713
- const pair = union2d(rect(40, 40), rect(40, 40).translate(60, 0));
714
- const [left, right] = pair.regions(); // largest first
715
- left.extrude(5);
716
- ```
717
-
718
- ```ts
719
- regions(): Sketch[]
720
- ```
721
-
722
- #### `region()` — Select the single filled region that contains the given 2D seed point.
723
-
724
- The seed must lie strictly inside the filled area — not on a boundary edge and not inside a hole. Throws a descriptive error if the seed is outside all regions. If unsure where regions are, use `.regions()` first — each result has `.bounds()`.
725
-
726
- ```ts
727
- const donut = circle2d(50).subtract(circle2d(30));
728
- donut.region([40, 0]).extrude(10); // seed at radius 40, inside the ring
729
- ```
730
-
731
- ```ts
732
- region(seed: [ number, number ]): Sketch
733
- ```
734
-
735
- **Promotion**
736
-
737
- #### `extrude()` — Extrude this 2D sketch along Z to create a 3D solid. Supports twist and scale tapering.
738
-
739
- ```ts
740
- extrude(height: number, opts?: { twist?: number; divisions?: number; scaleTop?: number | [ number, number ]; }): Shape
741
- ```
742
-
743
- #### `revolve()` — Revolve this 2D sketch around the Y axis to create a 3D solid of revolution.
744
-
745
- ```ts
746
- revolve(degrees?: number, segments?: number): Shape
747
- ```
748
-
749
- **Placement**
750
-
751
- #### `attachTo()` — Position this sketch relative to another using named anchor points.
752
-
753
- Computes the translation needed to align `selfAnchor` on this sketch with `targetAnchor` on the target sketch, then applies an optional pixel-exact offset.
754
-
755
- Anchor positions: `'center'` | `'top-left'` | `'top-right'` | `'bottom-left'` | `'bottom-right'` | `'top'` | `'bottom'` | `'left'` | `'right'`
756
-
757
- ```ts
758
- const arm = rect(4, 70).attachTo(plate, 'bottom-left', 'top-left');
759
- const shifted = rect(4, 70).attachTo(plate, 'bottom-left', 'top-left', [5, 0]);
760
- ```
761
-
762
- ```ts
763
- attachTo(target: Sketch, targetAnchor: Anchor, selfAnchor?: Anchor, offset?: [ number, number ]): Sketch
764
- ```
765
-
766
- #### `onFace()` — Place this sketch on a face or planar target in 3D space.
767
-
768
- Use this when a 2D profile should be oriented onto a 3D face before extrusion or other downstream operations.
769
-
770
- ```ts
771
- onFace(parentOrFace: Shape | { toShape(): Shape; } | { _bbox(): { min: number[]; max: number[]; }; } | FaceRef, faceOrOpts?: "front" | "back" | "left" | "right" | "top" | "bottom" | string | FaceRef | { u?: number; v?: number; protrude?: number; selfAnchor?: Anchor; }, opts?: { u?: number; v?: number; protrude?: number; selfAnchor?: Anchor; }): Sketch
772
- ```
773
-
774
- **Labels**
775
-
776
- #### `labelEdge()` — Label the single boundary edge (for circles, single-loop profiles). Returns a new sketch.
777
-
778
- ```ts
779
- labelEdge(name: string): Sketch
780
- ```
781
-
782
- #### `labelEdges()` — Label edges in winding order, or by named map for rect.
783
-
784
- Positional: `labelEdges('bottom', 'right', 'top', 'left')` — one per edge, `null` to skip. Named (rect only): `labelEdges({ bottom: 'floor', top: 'ceiling' })`. Returns a new sketch.
785
-
786
- ```ts
787
- labelEdges(...args: (string | null)[] | [ Record<string, string> ]): Sketch
788
- ```
789
-
790
- #### `edgeLabels()` — List current edge label names.
791
-
792
- ```ts
793
- edgeLabels(): string[]
794
- ```
795
-
796
- #### `prefixLabels()` — Prefix all edge labels. Returns a new sketch with prefixed labels.
797
-
798
- ```ts
799
- prefixLabels(prefix: string): Sketch
800
- ```
801
-
802
- #### `renameLabel()` — Rename a single edge label. Returns a new sketch.
803
-
804
- ```ts
805
- renameLabel(from: string, to: string): Sketch
806
- ```
807
-
808
- #### `dropLabels()` — Remove specific labels. Returns a new sketch.
809
-
810
- ```ts
811
- dropLabels(...names: string[]): Sketch
812
- ```
813
-
814
- #### `dropAllLabels()` — Remove all labels. Returns a new sketch.
815
-
816
- ```ts
817
- dropAllLabels(): Sketch
818
- ```
819
-
820
- **Measurement**
821
-
822
- #### `area()` — Return the total filled area of the sketch.
823
-
824
- ```ts
825
- area(): number
826
- ```
827
-
828
- #### `bounds()` — Return the axis-aligned bounding box of the sketch.
829
-
830
- ```ts
831
- bounds(): ProfileBounds
832
- ```
833
-
834
- #### `isEmpty()` — Return `true` if the sketch contains no filled area.
835
-
836
- ```ts
837
- isEmpty(): boolean
838
- ```
839
-
840
- #### `numVert()` — Return the number of vertices in the polygon representation of the sketch contours.
841
-
842
- ```ts
843
- numVert(): number
844
- ```
845
-
846
- #### `toPolygons()` — Return the sketch as a list of polygons matching its contour topology.
847
-
848
- Useful when you need raw polygon data for inspection or custom export.
849
-
850
- ```ts
851
- toPolygons(): number[][][]
852
- ```
853
-
854
- **Other**
855
-
856
- #### `color()` — Set the display color of this sketch.
857
-
858
- Color is preserved through all transforms and boolean operations. Pass `undefined` to clear the color.
859
-
860
- ```ts
861
- circle2d(20).color('#ff0000').extrude(5);
862
- ```
863
-
864
- ```ts
865
- color(value: string | undefined): Sketch
866
- ```
867
-
868
- #### `clone()` — Create an explicit copy of this sketch for branching variants.
869
-
870
- Because all Sketch operations are immutable, `clone()` is rarely needed. Use it when you want to assign the same sketch to multiple names and continue modifying each independently without confusion.
871
-
872
- ```ts
873
- clone(): Sketch
874
- ```
875
-
876
- ### `ConstrainedSketchBuilder`
877
-
878
- **Drawing**
879
-
880
- #### `moveTo()` — Move the cursor to `(x, y)` and start a new profile loop.
881
-
882
- ```ts
883
- moveTo(x: number, y: number): this
884
- ```
885
-
886
- #### `lineTo()` — Draw a line from the current cursor to `(x, y)`.
887
-
888
- ```ts
889
- lineTo(x: number, y: number): this
890
- ```
891
-
892
- #### `lineH()` — Draw a horizontal line of length `dx` from the current cursor.
893
-
894
- ```ts
895
- lineH(dx: number): this
896
- ```
897
-
898
- #### `lineV()` — Draw a vertical line of length `dy` from the current cursor.
899
-
900
- ```ts
901
- lineV(dy: number): this
902
- ```
903
-
904
- #### `lineAngled()` — Draw a line of the given `length` at `degrees` from +X.
905
-
906
- ```ts
907
- lineAngled(length: number, degrees: number): this
908
- ```
909
-
910
- #### `arcTo()` — Draw a circular arc from the current cursor to `(x, y)` with the given radius.
911
-
912
- ```ts
913
- arcTo(x: number, y: number, radius: number, clockwise?: boolean): this
914
- ```
915
-
916
- #### `arcByCenter()` — Create an arc from an explicit center point and endpoint IDs.
917
-
918
- ```ts
919
- arcByCenter(centerId: PointId, startId: PointId, endId: PointId, clockwise?: boolean, name?: string, fixedRadius?: boolean): ArcId
920
- ```
921
-
922
- #### `bezier()` — Create a cubic Bezier curve from four control points.
923
-
924
- ```ts
925
- bezier(p0: any, p1: any, p2: any, p3: any, name?: string): BezierId
926
- ```
927
-
928
- #### `bezierTo()` — Draw a cubic Bezier from the current cursor to `(x3, y3)`.
929
-
930
- ```ts
931
- bezierTo(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number): this
932
- ```
933
-
934
- #### `blendTo()` — Draw a smooth Bezier tangent to the previous arc.
935
-
936
- ```ts
937
- blendTo(x: number, y: number, weight?: number): this
938
- ```
939
-
940
- #### `label()` — Label the current path segment.
941
-
942
- ```ts
943
- label(name: string): this
944
- ```
945
-
946
- #### `close()` — Close the current path and register the loop.
947
-
948
- ```ts
949
- close(): this
950
- ```
951
-
952
- #### `addLoopCircle()` — Add a circle loop to the path.
953
-
954
- ```ts
955
- addLoopCircle(center: PointId, radius: number, segments?: number): this
956
- ```
957
-
958
- #### `addLoop()` — Add a closed polygon loop from point IDs.
959
-
960
- ```ts
961
- addLoop(points: any[]): this
962
- ```
963
-
964
- #### `addProfileLoop()` — Add a profile loop from prebuilt line/arc/bezier segments.
965
-
966
- ```ts
967
- addProfileLoop(segments: Array<{ kind: "line"; line: any; } | { kind: "arc"; arc: any; } | { kind: "bezier"; bezier: any; }>): this
968
- ```
969
-
970
- **Entities**
971
-
972
- #### `point()` — Add a free point to the sketch at `(x, y)`.
973
-
974
- If `x` or `y` are omitted, the point is placed at the bounding-box center of existing geometry so it starts near other entities rather than at the origin. Throws if either coordinate is `NaN` or `Infinity`.
975
-
976
- ```ts
977
- point(x?: number, y?: number, fixed?: boolean): PointId
978
- ```
979
-
980
- #### `pointAt()` — Return the `PointId` of the point created at the given insertion index.
981
-
982
- ```ts
983
- pointAt(index: number): PointId
984
- ```
985
-
986
- #### `line()` — Connect two existing points with a line segment.
987
-
988
- Pass `construction = true` for a helper line that participates in constraints but is excluded from the solved sketch output (not part of any profile loop).
989
-
990
- ```ts
991
- const axis = sk.line(sk.point(0, -50), sk.point(0, 50), true);
992
- sk.symmetric(p1, p2, axis);
993
- ```
994
-
995
- ```ts
996
- line(a: PointId, b: PointId, construction?: boolean, name?: string): LineId
997
- ```
998
-
999
- #### `lineAt()` — Return the `LineId` of the line created at the given insertion index.
1000
-
1001
- ```ts
1002
- lineAt(index: number): LineId
1003
- ```
1004
-
1005
- #### `circle()` — Add a circle to the sketch with the given center point and initial radius.
1006
-
1007
- The radius is a starting value — if you add a `radius()` or `diameter()` constraint, the solver will adjust it. Non-construction circles automatically register a loop.
1008
-
1009
- ```ts
1010
- circle(center: PointId, radius: number, construction?: boolean, segments?: number, name?: string): CircleId
1011
- ```
1012
-
1013
- #### `circleAt()` — Return the `CircleId` of the circle created at the given insertion index.
1014
-
1015
- ```ts
1016
- circleAt(index: number): CircleId
1017
- ```
1018
-
1019
- #### `shape()` — Register a named shape (closed polygon) from an ordered list of line IDs.
1020
-
1021
- The `ShapeId` can be passed to `shapeWidth()`, `shapeHeight()`, `shapeArea()`, `shapeCentroidX()`, `shapeCentroidY()`, and `shapeEqualCentroid()` constraints. Shape registration is done automatically by concept factories like `rect()` and `addPolygon()`.
1022
-
1023
- ```ts
1024
- shape(lines: LineId[]): ShapeId
1025
- ```
1026
-
1027
- #### [`group()`](/docs/core#group) — Create a rigid-body group with a local coordinate frame.
1028
-
1029
- Points and lines added to the group move together as a unit — the solver sees 3 DOF (x, y, θ) instead of 2N per point. After configuring the group, call `.done()` to register it and receive a `SketchGroupHandle`.
1030
-
1031
- Group points are addressable by their `PointId` in all sketch constraints (e.g. `sk.coincident`, `sk.distance`) just like any other points.
1032
-
1033
- ```ts
1034
- const g = sk.group({ x: 50, y: 30 });
1035
- const p0 = g.point(0, 0); // local origin → world (50, 30)
1036
- const p1 = g.point(100, 0); // local (100,0) → world (150, 30)
1037
- const l = g.line(p0, p1);
1038
- g.fixRotation();
1039
- const handle = g.done();
1040
- // p0, p1 work in constraints like any other PointId:
1041
- sk.coincident(p0, someExternalPoint);
1042
- ```
1043
-
1044
- ```ts
1045
- group(opts?: { x?: number; y?: number; theta?: number; id?: string; }): SketchGroupBuilder
1046
- ```
1047
-
1048
- #### `rect()` — Add an axis-aligned rectangle concept. Returns a `ConstrainedRect` handle with named vertices, sides, and center.
1049
-
1050
- ```ts
1051
- rect(options?: RectOptions): ConstrainedRect
1052
- ```
1053
-
1054
- #### `addPolygon()` — Add a general polygon concept (CCW winding enforced). Returns a `ConstrainedPolygon` handle.
1055
-
1056
- ```ts
1057
- addPolygon(options: PolygonOptions): ConstrainedPolygon
1058
- ```
1059
-
1060
- #### `regularPolygon()` — Add a regular n-gon concept (equal sides, CCW winding). Returns a `ConstrainedRegularPolygon` handle with a center point.
1061
-
1062
- ```ts
1063
- regularPolygon(options: RegularPolygonOptions): ConstrainedRegularPolygon
1064
- ```
1065
-
1066
- #### `groupRect()` — Add a rigid rectangle as a group concept. Returns a `ConstrainedGroupRect` handle with named vertices and sides. The rectangle is fixed in shape — only position (and optionally rotation) varies.
1067
-
1068
- ```ts
1069
- groupRect(options: GroupRectOptions): ConstrainedGroupRect
1070
- ```
1071
-
1072
- **Geometric Constraints**
1073
-
1074
- #### `horizontal()` — Constrain a line to be horizontal (parallel to the X axis).
1075
-
1076
- ```ts
1077
- horizontal(line: any): this
1078
- ```
1079
-
1080
- #### `vertical()` — Constrain a line to be vertical (parallel to the Y axis).
1081
-
1082
- ```ts
1083
- vertical(line: any): this
1084
- ```
1085
-
1086
- #### `parallel()` — Constrain two lines to be parallel.
1087
-
1088
- ```ts
1089
- parallel(a: any, b: any): this
1090
- ```
1091
-
1092
- #### `sameDirection()` — Constrain two lines to point in the same direction.
1093
-
1094
- ```ts
1095
- sameDirection(a: any, b: any): this
1096
- ```
1097
-
1098
- #### `oppositeDirection()` — Constrain two lines to point in opposite directions.
1099
-
1100
- ```ts
1101
- oppositeDirection(a: any, b: any): this
1102
- ```
1103
-
1104
- #### `perpendicular()` — Constrain two lines to be perpendicular.
1105
-
1106
- ```ts
1107
- perpendicular(a: any, b: any): this
1108
- ```
1109
-
1110
- #### `tangent()` — Constrain a line/circle or circle/circle tangency relationship.
1111
-
1112
- ```ts
1113
- tangent(a: any, b: any): this
1114
- ```
1115
-
1116
- #### `collinear()` — Constrain a point to lie on the infinite extension of a line.
1117
-
1118
- ```ts
1119
- collinear(point: any, line: any): this
1120
- ```
1121
-
1122
- #### `symmetric()` — Constrain two points to be symmetric about an axis line.
1123
-
1124
- ```ts
1125
- symmetric(a: any, b: any, axis: any): this
1126
- ```
1127
-
1128
- #### `blockRotation()` — Prevent 180° rotation of a polygon by anchoring its first edge.
1129
-
1130
- ```ts
1131
- blockRotation(points: any[], axis?: "x" | "y"): this
1132
- ```
1133
-
1134
- **Dimensional Constraints**
1135
-
1136
- #### `distance()` — Constrain the Euclidean distance between two points.
1137
-
1138
- ```ts
1139
- distance(a: any, b: any, value: number): this
1140
- ```
1141
-
1142
- #### `length()` — Constrain the length of a line segment.
1143
-
1144
- ```ts
1145
- length(line: any, value: number): this
1146
- ```
1147
-
1148
- #### `angle()` — Constrain the signed angle from line `a` to line `b`.
1149
-
1150
- ```ts
1151
- angle(a: any, b: any, value: number): this
1152
- ```
1153
-
1154
- #### `radius()` — Constrain the radius of a circle.
1155
-
1156
- ```ts
1157
- radius(circle: any, value: number): this
1158
- ```
1159
-
1160
- #### `diameter()` — Constrain the diameter of a circle.
1161
-
1162
- ```ts
1163
- diameter(circle: any, value: number): this
1164
- ```
1165
-
1166
- #### `hDistance()` — Constrain the horizontal distance between two points.
1167
-
1168
- ```ts
1169
- hDistance(a: any, b: any, value: number): this
1170
- ```
1171
-
1172
- #### `vDistance()` — Constrain the vertical distance between two points.
1173
-
1174
- ```ts
1175
- vDistance(a: any, b: any, value: number): this
1176
- ```
1177
-
1178
- #### `pointLineDistance()` — Constrain the signed perpendicular distance from a point to a line.
1179
-
1180
- ```ts
1181
- pointLineDistance(point: any, line: any, value: number): this
1182
- ```
1183
-
1184
- #### `lineDistance()` — Constrain the perpendicular offset distance between two lines.
1185
-
1186
- ```ts
1187
- lineDistance(a: any, b: any, value: number): this
1188
- ```
1189
-
1190
- #### `absoluteAngle()` — Constrain the absolute angle of a line measured from +X.
1191
-
1192
- ```ts
1193
- absoluteAngle(line: any, value: number): this
1194
- ```
1195
-
1196
- #### `arcLength()` — Constrain the arc length of an arc.
1197
-
1198
- ```ts
1199
- arcLength(arc: any, value: number): this
1200
- ```
1201
-
1202
- #### `equalRadius()` — Constrain two circles to have equal radii.
1203
-
1204
- ```ts
1205
- equalRadius(a: any, b: any): this
1206
- ```
1207
-
1208
- #### `angleBetween()` — Constrain the unsigned angle between two lines.
1209
-
1210
- ```ts
1211
- angleBetween(a: any, b: any, value: number): this
1212
- ```
1213
-
1214
- **Coincidence & Equality**
1215
-
1216
- #### `equal()` — Constrain two lines to have equal length.
1217
-
1218
- ```ts
1219
- equal(a: any, b: any): this
1220
- ```
1221
-
1222
- #### `coincident()` — Constrain two points to coincide.
1223
-
1224
- ```ts
1225
- coincident(a: any, b: any): this
1226
- ```
1227
-
1228
- #### `concentric()` — Constrain two circles to share a center.
1229
-
1230
- ```ts
1231
- concentric(a: any, b: any): this
1232
- ```
1233
-
1234
- #### `fix()` — Pin a point at a specific world location.
1235
-
1236
- ```ts
1237
- fix(point: any, x?: number, y?: number): this
1238
- ```
1239
-
1240
- #### `midpoint()` — Constrain a point to lie at the midpoint of a line.
1241
-
1242
- ```ts
1243
- midpoint(point: any, line: any): this
1244
- ```
1245
-
1246
- #### `pointOnCircle()` — Constrain a point to lie on the perimeter of a circle.
1247
-
1248
- ```ts
1249
- pointOnCircle(point: any, circle: any): this
1250
- ```
1251
-
1252
- #### `pointOnLine()` — Constrain a point to lie on the bounded segment of a line.
1253
-
1254
- ```ts
1255
- pointOnLine(point: any, line: any): this
1256
- ```
1257
-
1258
- #### `ccw()` — Constrain all given points to be in counter-clockwise order.
1259
-
1260
- ```ts
1261
- ccw(...points: any[]): this
1262
- ```
1263
-
1264
- **Tangent Transitions**
1265
-
1266
- #### `lineTangentArc()` — Constrain a line to be tangent to an arc at its start or end point.
1267
-
1268
- ```ts
1269
- lineTangentArc(line: any, arc: any, atStart: boolean): this
1270
- ```
1271
-
1272
- #### `arcTangentArc()` — Constrain two arcs to be tangent at their shared junction point.
1273
-
1274
- ```ts
1275
- arcTangentArc(arcA: any, arcB: any, aAtStart?: boolean, bAtStart?: boolean): this
1276
- ```
1277
-
1278
- #### `bezierTangentArc()` — Constrain a Bezier to be tangent to an arc at one endpoint.
1279
-
1280
- ```ts
1281
- bezierTangentArc(bezier: any, arc: any, atBezierStart: boolean, atArcStart: boolean): this
1282
- ```
1283
-
1284
- #### `smoothBlend()` — Create a Bezier blend between two arcs.
1285
-
1286
- ```ts
1287
- smoothBlend(arc1: any, arc2: any, options?: { weight?: number; arc1End?: "start" | "end"; arc2End?: "start" | "end"; }): BezierId
1288
- ```
1289
-
1290
- **Shape Constraints**
1291
-
1292
- #### `shapeWidth()` — Constrain a shape's width.
1293
-
1294
- ```ts
1295
- shapeWidth(shape: any, value: number): this
1296
- ```
1297
-
1298
- #### `shapeHeight()` — Constrain a shape's height.
1299
-
1300
- ```ts
1301
- shapeHeight(shape: any, value: number): this
1302
- ```
1303
-
1304
- #### `shapeCentroidX()` — Constrain a shape's centroid X position.
1305
-
1306
- ```ts
1307
- shapeCentroidX(shape: any, value: number): this
1308
- ```
1309
-
1310
- #### `shapeCentroidY()` — Constrain a shape's centroid Y position.
1311
-
1312
- ```ts
1313
- shapeCentroidY(shape: any, value: number): this
1314
- ```
1315
-
1316
- #### `shapeArea()` — Constrain a shape's area.
1317
-
1318
- ```ts
1319
- shapeArea(shape: any, value: number): this
1320
- ```
1321
-
1322
- #### `shapeEqualCentroid()` — Constrain two shapes to have the same centroid.
1323
-
1324
- ```ts
1325
- shapeEqualCentroid(a: any, b: any): this
1326
- ```
1327
-
1328
- **Positioning**
1329
-
1330
- #### `offsetX()` — Constrain the horizontal (X-axis) offset between two lines. Uses the start-point of each line to measure horizontal distance. `value` is the signed distance: b.startPt.x − a.startPt.x = value.
1331
-
1332
- ```ts
1333
- offsetX(a: any, b: any, value: number): this
1334
- ```
1335
-
1336
- #### `offsetY()` — Constrain the vertical (Y-axis) offset between two lines. Uses the start-point of each line to measure vertical distance. `value` is the signed distance: b.startPt.y − a.startPt.y = value.
1337
-
1338
- ```ts
1339
- offsetY(a: any, b: any, value: number): this
1340
- ```
1341
-
1342
- #### `importPoint()` — Import a `Point2D` object into the sketch.
1343
-
1344
- ```ts
1345
- importPoint(pt: { x: number; y: number; }, fixed?: boolean): PointId
1346
- ```
1347
-
1348
- #### `importLine()` — Import a `Line2D` object into the sketch.
1349
-
1350
- ```ts
1351
- importLine(l: { start: { x: number; y: number; }; end: { x: number; y: number; }; }, fixed?: boolean): LineId
1352
- ```
1353
-
1354
- #### `importRectangle()` — Import a `Rectangle2D` as four points and four lines.
1355
-
1356
- ```ts
1357
- importRectangle(r: { vertices: [ { x: number; y: number; }, { x: number; y: number; }, { x: number; y: number; }, { x: number; y: number; } ]; }, fixed?: boolean): { ... }
1358
- ```
1359
-
1360
- #### `referencePoint()` — Add a fixed reference point at `(x, y)`.
1361
-
1362
- ```ts
1363
- referencePoint(x: number, y: number): PointId
1364
- ```
1365
-
1366
- #### `referenceLine()` — Add a fixed reference line from `(x1, y1)` to `(x2, y2)`.
1367
-
1368
- ```ts
1369
- referenceLine(x1: number, y1: number, x2: number, y2: number): LineId
1370
- ```
1371
-
1372
- #### `referenceFrom()` — Import a single named entity from a solved sketch as fixed reference geometry.
1373
-
1374
- ```ts
1375
- referenceFrom(source: ConstraintSketch, entityId: string): PointId | LineId | null
1376
- ```
1377
-
1378
- #### `referenceAllFrom()` — Import all non-construction entities from a solved sketch as fixed references.
1379
-
1380
- ```ts
1381
- referenceAllFrom(source: ConstraintSketch): { points: Map<string, PointId>; lines: Map<string, LineId>; }
1382
- ```
1383
-
1384
- **Solving**
1385
-
1386
- #### `constrain()` — Add a raw constraint object to the builder.
1387
-
1388
- ```ts
1389
- constrain(constraint: Omit<SketchConstraint, "id">): this
1390
- ```
1391
-
1392
- #### `solve()` — Run the constraint solver and return a solved sketch.
1393
-
1394
- The returned `ConstraintSketch` extends `Sketch` and can be used directly in all 3D operations (`extrude`, `revolve`, etc.). It also exposes `constraintMeta` with the solver status:
1395
-
1396
- ```ts
1397
- const result = sk.solve();
1398
- result.constraintMeta.status; // 'fully' | 'under' | 'over' | 'over-redundant'
1399
- result.constraintMeta.dof; // 0 = fully constrained
1400
- result.constraintMeta.maxError; // residual — should be < 1e-6
1401
- result.inspect(); // human-readable summary
1402
- result.withUpdatedConstraint('cst-5', 120); // update a dimension without rebuilding
1403
- ```
1404
-
1405
- **Troubleshooting**
1406
-
1407
- - **Under-constrained (dof > 0)** — add `fix()`, `length()`, or other dimensional constraints.
1408
- - **Over-constrained** — conflicting constraints are auto-rejected. Check `result.constraintMeta.constraints` and `result.inspect()`.
1409
- - **maxError > 1e-6** — solver did not converge; check for contradictory constraints.
1410
-
1411
- ```ts
1412
- solve(options?: SolveOptions): ConstraintSketch | Sketch
1413
- ```
1414
-
1415
- #### `solveConstraintsOnly()` — Run the solver without building a full `ConstraintSketch`.
1416
-
1417
- Lighter than `solve()` — skips profile and DOF analysis. Useful for lightweight constraint validation or progress monitoring mid-construction.
1418
-
1419
- ```ts
1420
- solveConstraintsOnly(options?: SolveOptions): { maxError: number; rejectedCount: number; definition: ConstraintDefinition; }
1421
- ```
1422
-
1423
- #### `route()` — Start a directional route from coordinates.
1424
-
1425
- Returns a [`RouteBuilder`](/docs/viewport#routebuilder) - describe the path with up/down/left/right/arcLeft/arcRight. Each method returns the entity ID (`LineId` or `ArcId`) for use in `sk.*` constraints.
1426
-
1427
- ```js
1428
- const r = sk.route(0, 0);
1429
- const stem = r.up(18);
1430
- r.arcLeft(8.9);
1431
- const neck = r.down();
1432
- r.done();
1433
- sk.offsetX(stem, neck, 10.8);
1434
- ```
1435
-
1436
- ```ts
1437
- route(x: number, y: number): RouteBuilder
1438
- ```
1439
-
1440
- ### `ConstraintSketch`
1441
-
1442
- **Properties:**
1443
-
1444
- | Property | Type | Description |
1445
- |----------|------|-------------|
1446
- | `constraintMeta` | `SketchConstraintMeta` | — |
1447
- | `definition` | `ConstraintDefinition` | — |
1448
-
1449
- **Methods:**
1450
-
1451
- #### `detectArrangement()` — Enumerate all bounded regions formed by the line arrangement of this sketch. Construction lines are excluded. Regions are returned largest-first by area.
1452
-
1453
- ```ts
1454
- detectArrangement(): Sketch[]
1455
- ```
1456
-
1457
- #### `detectArrangementRegion()` — Select the single arrangement region that contains the given seed point. Throws if no region contains the seed.
1458
-
1459
- ```ts
1460
- detectArrangementRegion(_seed: [ number, number ]): Sketch
1461
- ```
1462
-
1463
- #### `toPolyline()` — Return the solved constrained path as a sampled 2D polyline.
1464
-
1465
- Use this when a construction rail was authored with `constrainedSketch()` and should feed another operation such as `Loft.pathOnXz(...)`. The sketch must contain exactly one profile path.
1466
-
1467
- ```ts
1468
- toPolyline(samples?: number): [ number, number ][]
1469
- ```
1470
-
1471
- #### `withUpdatedConstraint()` — Re-solve the sketch after changing the value of one existing constraint.
1472
-
1473
- Use this for interactive dimension edits without rebuilding the whole sketch graph. It attempts a warm-started solve first, then falls back to a full solve if needed.
1474
-
1475
- ```ts
1476
- withUpdatedConstraint(constraintId: string, value: number): ConstraintSketch
1477
- ```
1478
-
1479
- #### `inspect()` — Return a human-readable diagnostic string of the solved state.
1480
-
1481
- ```ts
1482
- inspect(): string
1483
- ```
1484
-
1485
- ### `SketchGroupBuilder`
1486
-
1487
- #### `point()` — Add a point in local coordinates. Returns its globally-addressable PointId.
1488
-
1489
- ```ts
1490
- point(lx: number, ly: number): PointId
1491
- ```
1492
-
1493
- #### `line()` — Connect two group points with a line. Both must be PointIds from this group.
1494
-
1495
- ```ts
1496
- line(a: PointId, b: PointId, name?: string): LineId
1497
- ```
1498
-
1499
- #### `fixRotation()` — Freeze rotation (theta). Group can still translate - 2 DOF remain.
1500
-
1501
- ```ts
1502
- fixRotation(): this
1503
- ```
1504
-
1505
- #### `fix()` — Freeze all 3 DOF - group is completely fixed.
1506
-
1507
- ```ts
1508
- fix(): this
1509
- ```
1510
-
1511
- #### `done()` — Finalize and register the group with the builder.
1512
-
1513
- ```ts
1514
- done(): SketchGroupHandle
1515
- ```
1516
-
1517
- ### `Point2D`
1518
-
1519
- An immutable 2D point with measurement and construction helpers.
1520
-
1521
- Used as construction geometry in sketches, constraints, and analytic measurements. All methods return new instances — `Point2D` is immutable.
1522
-
1523
- **Properties:**
1524
-
1525
- | Property | Type | Description |
1526
- |----------|------|-------------|
1527
- | `x` | `number` | — |
1528
- | `y` | `number` | — |
1529
-
1530
- **Methods:**
1531
-
1532
- #### `distanceTo()` — Measure straight-line distance to another point.
1533
-
1534
- ```ts
1535
- distanceTo(other: Point2D): number
1536
- ```
1537
-
1538
- #### `midpointTo()` — Compute the midpoint between this point and another point.
1539
-
1540
- ```ts
1541
- midpointTo(other: Point2D): Point2D
1542
- ```
1543
-
1544
- #### `translate()` — Return a point shifted by the given delta.
1545
-
1546
- ```ts
1547
- translate(dx: number, dy: number): Point2D
1548
- ```
1549
-
1550
- #### `toTuple()` — Convert this point to a plain `[x, y]` tuple.
1551
-
1552
- ```ts
1553
- toTuple(): [ number, number ]
1554
- ```
1555
-
1556
- ### `Line2D`
1557
-
1558
- An immutable 2D line segment with length, angle, intersection, and parallel helpers.
1559
-
1560
- Provides both segment-only (`intersectSegment`) and infinite-line (`intersect`) intersection queries. All methods return new instances.
1561
-
1562
- **Properties:**
1563
-
1564
- | Property | Type | Description |
1565
- |----------|------|-------------|
1566
- | `start` | `Point2D` | — |
1567
- | `end` | `Point2D` | — |
1568
-
1569
- **Methods:**
1570
-
1571
- #### `length()` — Length of the line segment.
1572
-
1573
- ```ts
1574
- get length(): number
1575
- ```
1576
-
1577
- #### `midpoint()` — Midpoint of the line segment.
1578
-
1579
- ```ts
1580
- get midpoint(): Point2D
1581
- ```
1582
-
1583
- #### `angle()` — Direction angle in degrees, measured CCW from +X.
1584
-
1585
- ```ts
1586
- get angle(): number
1587
- ```
1588
-
1589
- #### `direction()` — Unit direction vector from start to end.
1590
-
1591
- ```ts
1592
- get direction(): [ number, number ]
1593
- ```
1594
-
1595
- #### `parallel()` — Create a parallel line offset by the given distance.
1596
-
1597
- Positive distance shifts to the left of the line direction.
1598
-
1599
- ```ts
1600
- parallel(distance: number): Line2D
1601
- ```
1602
-
1603
- #### `intersect()` — Intersect this line with another infinite line.
1604
-
1605
- ```ts
1606
- intersect(other: Line2D): Point2D | null
1607
- ```
1608
-
1609
- #### `intersectSegment()` — Intersect this line with another as bounded segments.
1610
-
1611
- ```ts
1612
- intersectSegment(other: Line2D): Point2D | null
1613
- ```
1614
-
1615
- #### `fromCoordinates()` — Create a line from raw coordinates.
1616
-
1617
- ```ts
1618
- static fromCoordinates(x1: number, y1: number, x2: number, y2: number): Line2D
1619
- ```
1620
-
1621
- #### `fromPointAndAngle()` — Create a line from a start point, angle, and length.
1622
-
1623
- ```ts
1624
- static fromPointAndAngle(origin: Point2D, angleDeg: number, length: number): Line2D
1625
- ```
1626
-
1627
- #### `fromPointAndDirection()` — Create a line from a start point, direction vector, and length.
1628
-
1629
- ```ts
1630
- static fromPointAndDirection(origin: Point2D, dir: [ number, number ], length: number): Line2D
1631
- ```
1632
-
1633
- ### `Circle2D`
1634
-
1635
- An immutable 2D circle with area, circumference, and extrusion support.
1636
-
1637
- Extruding a `Circle2D` produces a cylinder with named `top`, `bottom`, and `side` faces accessible via the topology API.
1638
-
1639
- **Properties:**
1640
-
1641
- | Property | Type | Description |
1642
- |----------|------|-------------|
1643
- | `center` | `Point2D` | — |
1644
- | `radius` | `number` | — |
1645
-
1646
- **Methods:**
1647
-
1648
- #### `diameter()` — Diameter of the circle.
1649
-
1650
- ```ts
1651
- get diameter(): number
1652
- ```
1653
-
1654
- #### `circumference()` — Circumference of the circle.
1655
-
1656
- ```ts
1657
- get circumference(): number
1658
- ```
1659
-
1660
- #### `area()` — Area of the circle.
1661
-
1662
- ```ts
1663
- get area(): number
1664
- ```
1665
-
1666
- #### `pointAtAngle()` — Return a point on the circle at the given angle.
1667
-
1668
- ```ts
1669
- pointAtAngle(angleDeg: number): Point2D
1670
- ```
1671
-
1672
- #### `translate()` — Return a translated circle.
1673
-
1674
- ```ts
1675
- translate(dx: number, dy: number): Circle2D
1676
- ```
1677
-
1678
- #### `toSketch()` — Convert this circle to a sketch profile.
1679
-
1680
- ```ts
1681
- toSketch(segments?: number): Sketch
1682
- ```
1683
-
1684
- #### `extrude()` — Extrude the circle into a solid cylinder.
1685
-
1686
- ```ts
1687
- extrude(height: number, segments?: number): Shape
1688
- ```
1689
-
1690
- #### `fromCenterAndRadius()` — Create a circle from its center and radius.
1691
-
1692
- ```ts
1693
- static fromCenterAndRadius(center: Point2D, radius: number): Circle2D
1694
- ```
1695
-
1696
- #### `fromDiameter()` — Create a circle from its center and diameter.
1697
-
1698
- ```ts
1699
- static fromDiameter(center: Point2D, diameter: number): Circle2D
1700
- ```
1701
-
1702
- ### `Rectangle2D`
1703
-
1704
- A rectangle with named sides, vertices, and extrusion support.
1705
-
1706
- Sides are named based on the rectangle's local orientation at construction time. Vertices go: bottom-left, bottom-right, top-right, top-left (CCW).
1707
-
1708
- Use `rect()` for the normal centered sketch primitive. Use `Rectangle2D` when you need named sides/vertices, or an extrusion with tracked vertical edges such as `vert-br` for `filletTrackedEdge()` / `chamferTrackedEdge()`.
1709
-
1710
- Extruding a `Rectangle2D` produces a [`Shape`](/docs/core#shape) with named faces: `top`, `bottom`, `side-left`, `side-right`, `side-top`, `side-bottom`. These are accessible via the topology API (`.face()`, `.edge()`).
1711
-
1712
- ```ts
1713
- const r = Rectangle2D.fromDimensions(0, 0, 100, 60);
1714
- r.side('top'); r.side('left'); // Line2D
1715
- r.vertex('top-left'); // Point2D
1716
- r.width; r.height; r.center;
1717
- const [d1, d2] = r.diagonals(); // [bl-tr, br-tl]
1718
-
1719
- r.toSketch(); // Sketch (for 2D operations)
1720
- r.extrude(20); // Shape with named faces
1721
-
1722
- Rectangle2D.fromCenterAndDimensions(point(50, 30), 100, 60);
1723
- Rectangle2D.from2Corners(point(0, 0), point(100, 60));
1724
- Rectangle2D.from3Points(p1, p2, p3); // free-angle rectangle
1725
- ```
1726
-
1727
- #### `width()` — Width of the rectangle.
1728
-
1729
- ```ts
1730
- get width(): number
1731
- ```
1732
-
1733
- #### `height()` — Height of the rectangle.
1734
-
1735
- ```ts
1736
- get height(): number
1737
- ```
1738
-
1739
- #### `center()` — Geometric center of the rectangle.
1740
-
1741
- ```ts
1742
- get center(): Point2D
1743
- ```
1744
-
1745
- #### `side()` — Return a named side of the rectangle.
1746
-
1747
- ```ts
1748
- side(name: RectSide): Line2D
1749
- ```
1750
-
1751
- #### `sideAt()` — Return a side by index.
1752
-
1753
- ```ts
1754
- sideAt(index: number): Line2D
1755
- ```
1756
-
1757
- #### `vertex()` — Return a named vertex of the rectangle.
1758
-
1759
- ```ts
1760
- vertex(name: RectVertex): Point2D
1761
- ```
1762
-
1763
- #### `diagonals()` — Return the two diagonals of the rectangle.
1764
-
1765
- ```ts
1766
- diagonals(): [ Line2D, Line2D ]
1767
- ```
1768
-
1769
- #### `toSketch()` — Convert the rectangle to a sketch profile.
1770
-
1771
- ```ts
1772
- toSketch(): Sketch
1773
- ```
1774
-
1775
- #### `translate()` — Return a translated rectangle.
1776
-
1777
- ```ts
1778
- translate(dx: number, dy: number): Rectangle2D
1779
- ```
1780
-
1781
- #### `fromDimensions()` — Create an axis-aligned rectangle from origin corner plus width and height.
1782
-
1783
- ```ts
1784
- static fromDimensions(x: number, y: number, width: number, height: number): Rectangle2D
1785
- ```
1786
-
1787
- #### `fromCenterAndDimensions()` — Create a rectangle centered on a point.
1788
-
1789
- ```ts
1790
- static fromCenterAndDimensions(center: Point2D, width: number, height: number): Rectangle2D
1791
- ```
1792
-
1793
- #### `from2Corners()` — Create an axis-aligned rectangle from two opposite corners.
1794
-
1795
- ```ts
1796
- static from2Corners(p1: Point2D, p2: Point2D): Rectangle2D
1797
- ```
1798
-
1799
- #### `from3Points()` — Create a free-angle rectangle from three points.
1800
-
1801
- `p1` and `p2` define one edge, and `p3` chooses the perpendicular side.
1802
-
1803
- ```ts
1804
- static from3Points(p1: Point2D, p2: Point2D, p3: Point2D): Rectangle2D
1805
- ```
1806
-
1807
- #### `extrude()` — Extrude the rectangle into a solid prism with named topology.
1808
-
1809
- ```ts
1810
- extrude(height: number, up?: boolean): Shape
1811
- ```