forgecad 0.9.16 → 0.10.1

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 (162) hide show
  1. package/dist/assets/{AdminPage-CXvls4-J.js → AdminPage-DcCnj0qo.js} +1 -1
  2. package/dist/assets/{BenchmarkPage-B27zk8xL.js → BenchmarkPage-BVEpJSVk.js} +1 -1
  3. package/dist/assets/{BlogPage-CMAVvgQL.js → BlogPage-DHaGP50_.js} +1 -1
  4. package/dist/assets/{DocsPage-knf4I4h7.js → DocsPage-CDoxHkz8.js} +40 -859
  5. package/dist/assets/EditorApp-BJ0Dloyh.js +16446 -0
  6. package/dist/assets/{EmbedViewer-D7ZGlFjx.js → EmbedViewer-CRKZbY0y.js} +2 -2
  7. package/dist/assets/{LandingPageProofDriven-CnevhTE8.js → LandingPageProofDriven-BxHkYRE7.js} +1 -1
  8. package/dist/assets/{LegalPage-BPTUmqeg.js → LegalPage-B-u6FrVv.js} +1 -1
  9. package/dist/assets/{PricingPage-B0D4goG_.js → PricingPage-CzpZ6-Ce.js} +1 -1
  10. package/dist/assets/{SettingsPage-CFF-UgjI.js → SettingsPage-CIZSSAd0.js} +1 -1
  11. package/dist/assets/{app-CE3sYcV7.css → app-CjsbDlb7.css} +143 -0
  12. package/dist/assets/{app-T0pDcSX4.js → app-DaTMg3nH.js} +1310 -290
  13. package/dist/assets/cli/{render-C5pcIISc.js → render-DPf4AYJK.js} +55 -60
  14. package/dist/assets/{constructionHistoryWorker-Ba2Hm58b.js → constructionHistoryWorker-AwMMWSxg.js} +1103 -349
  15. package/dist/assets/{evalWorker-vkx310U2.js → evalWorker-CjZZWRWW.js} +5209 -2643
  16. package/dist/assets/{inspectWorker-BuTJDVX6.js → inspectWorker-CZsCFtQT.js} +1163 -409
  17. package/dist/assets/{jointPose-B_Cgedn9.js → jointPose-DzQOViQH.js} +1 -1
  18. package/dist/assets/{manifold-BWgsjmAM.js → manifold-BYlzU521.js} +1 -1
  19. package/dist/assets/{manifold-D6IFSkhH.js → manifold-DgXo0T5P.js} +2 -2
  20. package/dist/assets/{manifold-rZexZI0G.js → manifold-K1SkarlQ.js} +1 -1
  21. package/dist/assets/{reportWorker-0AGij1Ru.js → reportWorker-B9nWwSrB.js} +8501 -3393
  22. package/dist/assets/{scalar-sampling-budget-J5cuzxT1.js → scalar-sampling-budget-prBw_s8t.js} +6067 -3479
  23. package/dist/assets/{scanProxyWorker-Vl4Wxa1y.js → scanProxyWorker-2GtDLk-R.js} +1 -1
  24. package/dist/assets/{javascript-1kQXfVaz.js → typescript-DBQ6RN5l.js} +874 -22
  25. package/dist/cli/render.html +1 -1
  26. package/dist/docs/index.html +3 -3
  27. package/dist/docs-raw/AI/usage.md +1 -1
  28. package/dist/docs-raw/CLI.md +77 -240
  29. package/dist/docs-raw/README.md +6 -0
  30. package/dist/docs-raw/component-model.md +17 -150
  31. package/dist/docs-raw/generated/assembly.md +188 -582
  32. package/dist/docs-raw/generated/concepts.md +259 -3501
  33. package/dist/docs-raw/generated/core.md +283 -1250
  34. package/dist/docs-raw/generated/curves.md +387 -1608
  35. package/dist/docs-raw/generated/legacy.md +162 -0
  36. package/dist/docs-raw/generated/lib.md +227 -85
  37. package/dist/docs-raw/generated/output.md +35 -99
  38. package/dist/docs-raw/generated/runtime-names.md +23 -23
  39. package/dist/docs-raw/generated/sdf.md +68 -284
  40. package/dist/docs-raw/generated/sheet-metal.md +68 -335
  41. package/dist/docs-raw/generated/sketch.md +240 -1161
  42. package/dist/docs-raw/generated/viewport.md +75 -316
  43. package/dist/docs-raw/generated/wood.md +21 -49
  44. package/dist/docs-raw/guides/coordinate-system.md +4 -42
  45. package/dist/docs-raw/guides/inspection-bundles.md +44 -442
  46. package/dist/docs-raw/guides/joint-design.md +18 -79
  47. package/dist/docs-raw/guides/positioning.md +21 -143
  48. package/dist/docs-raw/guides/scene-presentation.md +89 -0
  49. package/dist/docs-raw/guides/simready-quickstart.md +171 -0
  50. package/dist/docs-raw/simulation-workflow.md +273 -0
  51. package/dist/docs-raw/skills/forgecad-3d-reconstruction.md +25 -111
  52. package/dist/docs-raw/skills/forgecad-blockout-model.md +20 -117
  53. package/dist/docs-raw/skills/forgecad-component-model.md +23 -107
  54. package/dist/docs-raw/skills/forgecad-high-level-spec.md +47 -155
  55. package/dist/docs-raw/skills/forgecad-image-replicator.md +26 -143
  56. package/dist/docs-raw/skills/forgecad-lld.md +19 -113
  57. package/dist/docs-raw/skills/forgecad-make-a-model.md +112 -532
  58. package/dist/docs-raw/skills/forgecad-model-grader.md +38 -108
  59. package/dist/docs-raw/skills/forgecad-prepare-prompt.md +24 -211
  60. package/dist/docs-raw/skills/forgecad-project.md +13 -131
  61. package/dist/docs-raw/skills/forgecad-reconstruction-benchmark.md +42 -134
  62. package/dist/docs-raw/skills/forgecad-render-inspect.md +27 -174
  63. package/dist/docs-raw/skills/forgecad-visual-spec.md +32 -112
  64. package/dist/docs-raw/skills/forgecad.md +19 -18
  65. package/dist/docs-raw/skills/index.md +2 -0
  66. package/dist/docs-raw/welcome.md +2 -2
  67. package/dist/index.html +2 -2
  68. package/dist/llms.txt +1 -2
  69. package/dist/sitemap.xml +25 -13
  70. package/dist-cli/{check-compiler-SYQ2PWOB.js → check-compiler-II7NLPAB.js} +1 -1
  71. package/dist-cli/{check-query-propagation-HIAGV62W.js → check-query-propagation-7462TR3R.js} +1 -1
  72. package/dist-cli/{chunk-SPZE3DUY.js → chunk-UWTJCGXF.js} +5848 -2915
  73. package/dist-cli/forgecad.js +3496 -703
  74. package/dist-skill/CONTEXT.md +1797 -7963
  75. package/dist-skill/SKILL.md +15 -15
  76. package/dist-skill/docs/API/core/concepts.md +27 -157
  77. package/dist-skill/docs/CLI.md +77 -240
  78. package/dist-skill/docs/generated/assembly.md +182 -532
  79. package/dist-skill/docs/generated/core.md +283 -1250
  80. package/dist-skill/docs/generated/curves.md +387 -1609
  81. package/dist-skill/docs/generated/lib.md +227 -85
  82. package/dist-skill/docs/generated/output.md +35 -99
  83. package/dist-skill/docs/generated/runtime-names.md +16 -21
  84. package/dist-skill/docs/generated/sdf.md +68 -284
  85. package/dist-skill/docs/generated/sheet-metal.md +68 -335
  86. package/dist-skill/docs/generated/sketch.md +240 -1160
  87. package/dist-skill/docs/generated/viewport.md +75 -223
  88. package/dist-skill/docs/generated/wood.md +21 -49
  89. package/dist-skill/docs/guides/coordinate-system.md +4 -42
  90. package/dist-skill/docs/guides/inspection-bundles.md +44 -442
  91. package/dist-skill/docs/guides/joint-design.md +18 -79
  92. package/dist-skill/docs/guides/positioning.md +21 -143
  93. package/dist-skill/docs/guides/scene-presentation.md +89 -0
  94. package/dist-skill/docs/guides/surface-members.md +26 -0
  95. package/dist-skill/library/forgecad-3d-reconstruction/SKILL.md +23 -111
  96. package/dist-skill/library/forgecad-blockout-model/SKILL.md +18 -117
  97. package/dist-skill/library/forgecad-component-model/SKILL.md +21 -107
  98. package/dist-skill/library/forgecad-high-level-spec/SKILL.md +45 -155
  99. package/dist-skill/library/forgecad-image-replicator/SKILL.md +24 -143
  100. package/dist-skill/library/forgecad-lld/SKILL.md +17 -113
  101. package/dist-skill/library/forgecad-make-a-model/SKILL.md +110 -532
  102. package/dist-skill/library/forgecad-model-grader/SKILL.md +36 -108
  103. package/dist-skill/library/forgecad-prepare-prompt/SKILL.md +35 -224
  104. package/dist-skill/library/forgecad-prepare-prompt/references/default-profiles.md +43 -271
  105. package/dist-skill/library/forgecad-prepare-prompt/references/master-prompt.md +30 -99
  106. package/dist-skill/library/forgecad-project/SKILL.md +13 -133
  107. package/dist-skill/library/forgecad-reconstruction-benchmark/SKILL.md +29 -123
  108. package/dist-skill/library/forgecad-render-inspect/SKILL.md +25 -174
  109. package/dist-skill/library/forgecad-visual-spec/SKILL.md +30 -111
  110. package/dist-skill/website/skills/forgecad-3d-reconstruction.md +58 -0
  111. package/dist-skill/website/skills/forgecad-blockout-model.md +49 -0
  112. package/dist-skill/website/skills/forgecad-component-model.md +53 -0
  113. package/dist-skill/website/skills/forgecad-high-level-spec.md +101 -0
  114. package/dist-skill/website/skills/forgecad-image-replicator.md +63 -0
  115. package/dist-skill/website/skills/forgecad-lld.md +41 -0
  116. package/dist-skill/website/skills/forgecad-make-a-model.md +186 -0
  117. package/dist-skill/website/skills/forgecad-model-grader.md +82 -0
  118. package/dist-skill/website/skills/forgecad-prepare-prompt.md +63 -0
  119. package/dist-skill/website/skills/forgecad-project.md +26 -0
  120. package/dist-skill/website/skills/forgecad-reconstruction-benchmark.md +60 -0
  121. package/dist-skill/website/skills/forgecad-render-inspect.md +80 -0
  122. package/dist-skill/website/skills/forgecad-visual-spec.md +71 -0
  123. package/dist-skill/website/skills/forgecad.md +122 -0
  124. package/dist-skill/website/skills/index.md +26 -0
  125. package/examples/api/comparison-imported-sphere-candidate.forge.js +1 -1
  126. package/examples/api/conformal-product-ribbon.forge.js +1 -1
  127. package/examples/api/exact-sheet-shell-assembly.forge.js +1 -1
  128. package/examples/api/extrude-options.forge.js +4 -2
  129. package/examples/api/field-loft-drive-tip.forge.js +40 -0
  130. package/examples/api/guided-loft-olive-oil-bottle.forge.js +1 -1
  131. package/examples/api/highlight-debug.forge.js +10 -10
  132. package/examples/api/mesh-import-slats.forge.js +1 -1
  133. package/examples/api/real-product-curves.forge.js +1 -1
  134. package/examples/api/sculpt-box-circle-booleans.forge.js +1 -1
  135. package/examples/api/sdf-shapes.forge.js +2 -5
  136. package/examples/api/sketch-rounding-strategies.forge.js +6 -6
  137. package/examples/api/surface-member-bottle-cage.forge.js +3 -3
  138. package/examples/api/surface-member-conformal-product-ribbon.forge.js +3 -3
  139. package/examples/api/surface-member-razor-inlay.forge.js +1 -1
  140. package/examples/api/variable-sweep-test.forge.js +3 -3
  141. package/examples/mechanical/airplane-propeller.forge.js +74 -39
  142. package/examples/nurbs-surface.forge.js +1 -1
  143. package/examples/products/iphone.forge.js +1 -1
  144. package/examples/robotics/README.md +46 -0
  145. package/examples/robotics/scout-cam-rover-simready/README.md +119 -0
  146. package/examples/robotics/scout-cam-rover-simready/lib/dims.js +140 -0
  147. package/examples/robotics/scout-cam-rover-simready/main.forge.js +343 -0
  148. package/examples/robotics/scout-cam-rover-simready/parts/body.forge.js +304 -0
  149. package/examples/robotics/scout-cam-rover-simready/parts/chassis.forge.js +320 -0
  150. package/examples/robotics/scout-cam-rover-simready/parts/hardware.forge.js +21 -0
  151. package/examples/robotics/scout-cam-rover-simready/parts/turret.forge.js +70 -0
  152. package/examples/robotics/scout-cam-rover-simready/parts/wheel.forge.js +116 -0
  153. package/examples/robotics/simready-asset-crate.forge.js +79 -0
  154. package/examples/robotics/simready-diff-drive-rover.forge.js +141 -0
  155. package/examples/robotics/simready-parallel-gripper.forge.js +102 -0
  156. package/package.json +1 -1
  157. package/dist/assets/EditorApp-BHMQlJ-D.js +0 -14686
  158. package/dist/docs-raw/guides/geometry-conventions.md +0 -52
  159. package/dist/docs-raw/guides/modeling-recipes.md +0 -78
  160. package/dist-skill/docs/guides/geometry-conventions.md +0 -52
  161. package/dist-skill/docs/guides/modeling-recipes.md +0 -78
  162. package/dist-skill/library/forgecad-visual-spec/references/prompt-template.md +0 -79
@@ -9,13 +9,10 @@ skill-order: 100
9
9
 
10
10
  ## Contents
11
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`
12
+ - [2D Sketch Primitives](#2d-sketch-primitives)
13
+ - [2D Sketch Booleans](#2d-sketch-booleans)
14
+ - [2D Text](#2d-text)
15
+ - [Constrained Sketches](#constrained-sketches)
19
16
  - [Sketch](#sketch) — Transforms, Booleans, Features, Promotion, Placement, Labels, Measurement
20
17
  - [ConstrainedSketchBuilder](#constrainedsketchbuilder) — Drawing, Entities, Geometric Constraints, Dimensional Constraints, Coincidence & Equality, Tangent Transitions, Shape Constraints, Positioning, Solving
21
18
  - [ConstraintSketch](#constraintsketch)
@@ -29,7 +26,7 @@ skill-order: 100
29
26
 
30
27
  ### 2D Sketch Primitives
31
28
 
32
- #### `path()` — Create a new [`PathBuilder`](/docs/curves#pathbuilder) for tracing a 2D outline point by point.
29
+ #### `path(): PathBuilder` — Create a new [`PathBuilder`](/docs/curves#pathbuilder) for tracing a 2D outline point by point.
33
30
 
34
31
  [`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
32
 
@@ -51,27 +48,17 @@ const slot = path()
51
48
  .close();
52
49
  ```
53
50
 
54
- ```ts
55
- path(): PathBuilder
56
- ```
51
+ #### `stroke(points: Vec2[], width: number, join?: "Round" | "Square"): Sketch` — Thicken a 2D polyline (centerline) into a solid filled profile of uniform width.
57
52
 
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
- ```
53
+ Standalone equivalent of `path()...stroke(width, join)`. Use for centerline-based geometry ribs, wire traces, brackets. For rounding corners of a *closed* outline use `.filletCorners(radius)` (all corners) or `.filletCorner([x, y], radius)` (one corner) instead.
63
54
 
64
- #### `rect()` — Create a 2D rectangle centered at the origin.
55
+ #### `rect(width: number, height: number): Sketch` — Create a 2D rectangle centered at the origin.
65
56
 
66
57
  ```ts
67
58
  rect(40, 20).extrude(5);
68
59
  ```
69
60
 
70
- ```ts
71
- rect(width: number, height: number): Sketch
72
- ```
73
-
74
- #### `circle2d()` — Create a 2D circle centered at the origin.
61
+ #### `circle2d(radius: number, segments?: number): Sketch` — Create a 2D circle centered at the origin.
75
62
 
76
63
  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
64
 
@@ -80,11 +67,7 @@ circle2d(25).extrude(10); // smooth cylinder
80
67
  circle2d(25, 6).extrude(10); // hexagonal prism
81
68
  ```
82
69
 
83
- ```ts
84
- circle2d(radius: number, segments?: number): Sketch
85
- ```
86
-
87
- #### `roundedRect()` — Create a 2D rectangle with rounded corners, centered at the origin.
70
+ #### `roundedRect(width: number, height: number, radius: number): Sketch` — Create a 2D rectangle with rounded corners, centered at the origin.
88
71
 
89
72
  The corner radius is automatically clamped to `min(width/2, height/2)` so it can never exceed the shape dimensions.
90
73
 
@@ -92,11 +75,7 @@ The corner radius is automatically clamped to `min(width/2, height/2)` so it can
92
75
  roundedRect(60, 30, 5).extrude(3);
93
76
  ```
94
77
 
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.
78
+ #### `polygon(points: (Vec2 | Point2D)[]): Sketch` — Create a 2D polygon from an array of `[x, y]` points or `Point2D` objects.
100
79
 
101
80
  Winding order is normalized automatically — clockwise (CW) input is silently reversed to CCW before being passed to the geometry kernel.
102
81
 
@@ -104,11 +83,7 @@ Winding order is normalized automatically — clockwise (CW) input is silently r
104
83
  polygon([[0, 0], [50, 0], [25, 40]]).extrude(5); // triangle
105
84
  ```
106
85
 
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.
86
+ #### `ngon(sides: number, radius: number): Sketch` — Create a regular polygon inscribed in a circle of the given radius.
112
87
 
113
88
  `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
89
 
@@ -116,32 +91,20 @@ polygon(points: ([ number, number ] | Point2D)[]): Sketch
116
91
  ngon(6, 20).extrude(10); // hexagonal prism, circumradius 20
117
92
  ```
118
93
 
119
- ```ts
120
- ngon(sides: number, radius: number): Sketch
121
- ```
122
-
123
- #### `ellipse()` — Create a 2D ellipse centered at the origin.
94
+ #### `ellipse(rx: number, ry: number, segments?: number): Sketch` — Create a 2D ellipse centered at the origin.
124
95
 
125
96
  ```ts
126
97
  ellipse(30, 15).extrude(5);
127
98
  ellipse(30, 15, 32).extrude(5); // lower-resolution approximation
128
99
  ```
129
100
 
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.
101
+ #### `slot(length: number, width: number): Sketch` — Create a slot (oblong / stadium shape) — a rectangle with semicircular ends, centered at the origin.
135
102
 
136
103
  ```ts
137
104
  slot(40, 10).extrude(3); // 40mm long, 10mm wide slot
138
105
  ```
139
106
 
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.
107
+ #### `arcSlot(pitchRadius: number, sweepDeg: number, thickness: number): Sketch` — Create an arc-shaped slot (banana / annular sector) centered at the origin.
145
108
 
146
109
  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
110
 
@@ -149,23 +112,9 @@ The slot is symmetric about the +X axis. The two ends are closed with semicircul
149
112
  arcSlot(135, 74, 40).extrude(5); // pitch R135, 74° sweep, 40mm wide
150
113
  ```
151
114
 
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
115
  ### 2D Sketch Booleans
167
116
 
168
- #### `union2d()` — Combine 2D sketches into a single profile using an additive boolean union.
117
+ #### `union2d(...inputs: SketchOperandInput[]): Sketch` — Combine 2D sketches into a single profile using an additive boolean union.
169
118
 
170
119
  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
120
 
@@ -173,11 +122,7 @@ Accepts individual sketches or arrays: `union2d(a, b, c)` or `union2d([a, b, c])
173
122
  const cross = union2d(rect(60, 10), rect(10, 60));
174
123
  ```
175
124
 
176
- ```ts
177
- union2d(...inputs: SketchOperandInput[]): Sketch
178
- ```
179
-
180
- #### `difference2d()` — Subtract one or more 2D sketches from a base sketch.
125
+ #### `difference2d(...inputs: SketchOperandInput[]): Sketch` — Subtract one or more 2D sketches from a base sketch.
181
126
 
182
127
  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
128
 
@@ -185,11 +130,7 @@ The first sketch is the base; all subsequent sketches are subtracted from it. Ac
185
130
  const donut = difference2d(circle2d(50), circle2d(30));
186
131
  ```
187
132
 
188
- ```ts
189
- difference2d(...inputs: SketchOperandInput[]): Sketch
190
- ```
191
-
192
- #### `intersection2d()` — Keep only the area where all input sketches overlap (intersection boolean).
133
+ #### `intersection2d(...inputs: SketchOperandInput[]): Sketch` — Keep only the area where all input sketches overlap (intersection boolean).
193
134
 
194
135
  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
136
 
@@ -197,92 +138,9 @@ Accepts individual sketches or arrays: `intersection2d(a, b)` or `intersection2d
197
138
  const lens = intersection2d(circle2d(30).translate(-10, 0), circle2d(30).translate(10, 0));
198
139
  ```
199
140
 
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
141
  ### 2D Text
284
142
 
285
- #### `loadFont()` — Pre-load and cache a font for use with `text2d()`.
143
+ #### `loadFont(source: string | ArrayBuffer, cacheKey?: string): opentype.Font` — Pre-load and cache a font for use with `text2d()`.
286
144
 
287
145
  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
146
 
@@ -296,11 +154,7 @@ text2d('Title', { size: 12, font }).extrude(1.5);
296
154
  text2d('Subtitle', { size: 8, font }).extrude(1);
297
155
  ```
298
156
 
299
- ```ts
300
- loadFont(source: string | ArrayBuffer, cacheKey?: string): opentype.Font
301
- ```
302
-
303
- #### `text2d()` — Build a filled 2D Sketch from a text string.
157
+ #### `text2d(content: string, options?: TextOptions): Sketch` — Build a filled 2D Sketch from a text string.
304
158
 
305
159
  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
160
 
@@ -333,10 +187,6 @@ const font = loadFont('/path/to/Arial Bold.ttf');
333
187
  text2d('Title', { size: 12, font }).extrude(1.5);
334
188
  ```
335
189
 
336
- ```ts
337
- text2d(content: string, options?: TextOptions): Sketch
338
- ```
339
-
340
190
  **`TextOptions`**
341
191
 
342
192
  | Option | Type | Description |
@@ -348,7 +198,7 @@ text2d(content: string, options?: TextOptions): Sketch
348
198
  | `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
199
  | `flattenTolerance?` | `number` | Bezier flattening tolerance in model units. Smaller = more polygon segments = smoother curves. |
350
200
 
351
- #### `textWidth()` — Measure the rendered advance width of a string without creating any geometry.
201
+ #### `textWidth(content: string, options?: Pick<TextOptions, "size" | "letterSpacing" | "font">): number` — Measure the rendered advance width of a string without creating any geometry.
352
202
 
353
203
  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
204
 
@@ -357,13 +207,9 @@ const w = textWidth('SERIAL: 001', { size: 6 });
357
207
  const plate = box(w + 10, 12, 2);
358
208
  ```
359
209
 
360
- ```ts
361
- textWidth(content: string, options?: Pick<TextOptions, "size" | "letterSpacing" | "font">): number
362
- ```
363
-
364
210
  ### Constrained Sketches
365
211
 
366
- #### `constrainedSketch()` — Create a parametric 2D sketch driven by geometric constraints and a nonlinear solver.
212
+ #### `constrainedSketch(options?: ConstrainedSketchOptions): ConstrainedSketchBuilder` — Create a parametric 2D sketch driven by geometric constraints and a nonlinear solver.
367
213
 
368
214
  **Workflow**
369
215
 
@@ -394,184 +240,9 @@ result.inspect(); // human-readable summary
394
240
  result.withUpdatedConstraint('cst-5', 120); // update a dimension without rebuilding
395
241
  ```
396
242
 
397
- ```ts
398
- constrainedSketch(options?: ConstrainedSketchOptions): ConstrainedSketchBuilder
399
- ```
400
-
401
243
  **`ConstrainedSketchOptions`**
402
244
  - `strict?: boolean` — When true, adding a constraint that cannot be satisfied throws instead of silently discarding it.
403
245
 
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
246
  ---
576
247
 
577
248
  ## Classes
@@ -586,7 +257,7 @@ Supported operations:
586
257
 
587
258
  - **Transforms** — `translate`, `rotate`, `rotateAround`, `scale`, `mirror`
588
259
  - **Booleans** — `add` (union), `subtract` (difference), `intersect`
589
- - **Operations** — `offset`, `simplify`
260
+ - **Operations** — `offset`, `simplify`, `filletCorners`, `filletCorner`, `chamferCorners`, `chamferCorner`
590
261
  - **Queries** — `area`, `bounds`, `isEmpty`, `numVert`
591
262
  - **3D operations** — `extrude`, `revolve`, `onFace`
592
263
  - **Regions** — `regions`, `region`
@@ -602,59 +273,31 @@ Named anchor positions used by `attachTo()`: `'center'` | `'top-left'` | `'top-r
602
273
 
603
274
  **Transforms**
604
275
 
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.
276
+ #### `translate(x: number, y?: number): Sketch` — Move the sketch by the given X and Y offset.
612
277
 
613
- ```ts
614
- rotate(degrees: number): Sketch
615
- ```
278
+ #### `rotate(degrees: number): Sketch` — Rotate the sketch around its bounding-box center.
616
279
 
617
- #### `rotateAround()` — Rotate the sketch around a specific pivot point.
280
+ #### `rotateAround(degrees: number, pivot: Vec2): Sketch` — Rotate the sketch around a specific pivot point.
618
281
 
619
282
  ```ts
620
283
  rect(20, 20).rotateAround(45, [0, 0]);
621
284
  ```
622
285
 
623
- ```ts
624
- rotateAround(degrees: number, pivot: [ number, number ]): Sketch
625
- ```
626
-
627
- #### `scale()` — Scale the sketch relative to its bounding-box center.
286
+ #### `scale(v: number | Vec2): Sketch` — Scale the sketch relative to its bounding-box center.
628
287
 
629
288
  Pass a single number for uniform scaling, or `[sx, sy]` for per-axis scaling.
630
289
 
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
- ```
290
+ #### `scaleAround(pivot: Vec2, v: number | Vec2): Sketch` — Scale the sketch relative to an arbitrary pivot point.
640
291
 
641
- #### `mirror()` — Mirror the sketch across a line through its bounding-box center.
292
+ #### `mirror(normal: Vec2): Sketch` — Mirror the sketch across a line through its bounding-box center.
642
293
 
643
294
  `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
295
 
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
- ```
296
+ #### `mirrorThrough(point: Vec2, normal: Vec2): Sketch` — Mirror the sketch across a line defined by a point and a normal direction.
654
297
 
655
298
  **Booleans**
656
299
 
657
- #### `add()` — Add (union) one or more sketches to this sketch.
300
+ #### `add(...others: SketchOperandInput[]): Sketch` — Add (union) one or more sketches to this sketch.
658
301
 
659
302
  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
303
 
@@ -662,11 +305,7 @@ Accepts individual sketches or arrays: `sketch.add(a, b)` or `sketch.add([a, b])
662
305
  circle2d(20).add(rect(10, 30)).extrude(5);
663
306
  ```
664
307
 
665
- ```ts
666
- add(...others: SketchOperandInput[]): Sketch
667
- ```
668
-
669
- #### `subtract()` — Subtract one or more sketches from this sketch.
308
+ #### `subtract(...others: SketchOperandInput[]): Sketch` — Subtract one or more sketches from this sketch.
670
309
 
671
310
  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
311
 
@@ -674,81 +313,91 @@ Accepts individual sketches or arrays: `sketch.subtract(a, b)` or `sketch.subtra
674
313
  rect(40, 40).subtract(circle2d(10)).extrude(5);
675
314
  ```
676
315
 
677
- ```ts
678
- subtract(...others: SketchOperandInput[]): Sketch
679
- ```
680
-
681
- #### `intersect()` — Intersect this sketch with one or more others (keep overlapping area only).
316
+ #### `intersect(...others: SketchOperandInput[]): Sketch` — Intersect this sketch with one or more others (keep overlapping area only).
682
317
 
683
318
  Accepts individual sketches or arrays: `sketch.intersect(a, b)` or `sketch.intersect([a, b])`. For intersecting many sketches, prefer the free function `intersection2d()`.
684
319
 
685
- ```ts
686
- intersect(...others: SketchOperandInput[]): Sketch
687
- ```
688
-
689
320
  **Features**
690
321
 
691
- #### `offset()` — Inflate (positive delta) or deflate (negative delta) the sketch contour.
322
+ #### `offset(delta: number, join?: "Square" | "Round" | "Miter"): Sketch` — Inflate (positive delta) or deflate (negative delta) the sketch contour.
692
323
 
693
- Use `offset(-r).offset(+r)` to round every convex corner of a closed sketch.
324
+ For rounding corners, prefer `filletCorners(radius)` (all corners) or `filletCorner([x, y], radius)` (one corner) — they round only true corners and keep concave geometry exact.
694
325
 
695
326
  - `'Round'` — smooth arc at each corner (default)
696
327
  - `'Square'` — flat mitered extension
697
328
  - `'Miter'` — sharp pointed extension
698
329
 
699
330
  ```ts
700
- rect(40, 20).offset(3); // expand by 3
701
- rect(40, 20).offset(-2).offset(2); // round all convex corners
331
+ rect(40, 20).offset(3); // expand by 3
702
332
  ```
703
333
 
704
- ```ts
705
- offset(delta: number, join?: "Square" | "Round" | "Miter"): Sketch
706
- ```
334
+ #### `filletCorners(radius: number): Sketch` — Round every significant corner of this sketch with the same fillet radius.
707
335
 
708
- #### `regions()`Decompose this sketch into its distinct filled regions, sorted largest-first by area.
336
+ Works on any sketch primitives, boolean results, attached or composed profiles. A vertex counts as a corner when its turn angle is at least 30°, so vertices that belong to tessellated circles or earlier fillets are left untouched. Both convex and concave corners are rounded. Holes are preserved, and their corners are rounded too.
709
337
 
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.
338
+ Throws if the sketch has no significant corners, or if the radius does not fit a corner (the error names the corner and the maximum radius).
711
339
 
712
340
  ```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);
341
+ rect(60, 30).filletCorners(5).extrude(4); // rounded plate
342
+ polygon(bracketPts).filletCorners(3); // every corner of an outline
716
343
  ```
717
344
 
345
+ #### `filletCorner(at: Vec2, radius: number): Sketch` — Round the single corner of this sketch nearest to a seed point.
346
+
347
+ Selects the significant corner (turn angle ≥ 30°) closest to `at` — the seed does not need to be exact, just nearer to the intended corner than to any other (like `region([x, y])` seed selection). Throws if two corners are equidistant from the seed, naming both so you can move the seed.
348
+
349
+ Chain calls to round several corners with different radii.
350
+
718
351
  ```ts
719
- regions(): Sketch[]
352
+ polygon(roofPts)
353
+ .filletCorner([45, 86], 14) // peak
354
+ .filletCorner([24, 74], 8); // left shoulder
720
355
  ```
721
356
 
722
- #### `region()` — Select the single filled region that contains the given 2D seed point.
357
+ #### `chamferCorners(size: number): Sketch` — Bevel every significant corner of this sketch with a straight chamfer.
723
358
 
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()`.
359
+ Replaces each significant corner (turn angle 30°) with a straight cut set back `size` along both adjacent edges. Tessellated arcs are left untouched; holes are preserved. Throws if the sketch has no significant corners or the size does not fit a corner.
725
360
 
726
361
  ```ts
727
- const donut = circle2d(50).subtract(circle2d(30));
728
- donut.region([40, 0]).extrude(10); // seed at radius 40, inside the ring
362
+ rect(60, 30).chamferCorners(4).extrude(4); // beveled plate outline
729
363
  ```
730
364
 
365
+ #### `chamferCorner(at: Vec2, size: number): Sketch` — Bevel the single corner of this sketch nearest to a seed point.
366
+
367
+ Selects the significant corner (turn angle ≥ 30°) closest to `at` and replaces it with a straight cut set back `size` along both adjacent edges. Throws if two corners are equidistant from the seed. Chain calls to bevel several corners with different sizes.
368
+
731
369
  ```ts
732
- region(seed: [ number, number ]): Sketch
370
+ rect(60, 30).chamferCorner([30, 15], 6); // bevel only the top-right corner
733
371
  ```
734
372
 
735
- **Promotion**
373
+ #### `regions(): Sketch[]` — Decompose this sketch into its distinct filled regions, sorted largest-first by area.
736
374
 
737
- #### `extrude()` Extrude this 2D sketch along Z to create a 3D solid. Supports twist and scale tapering.
375
+ 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.
738
376
 
739
377
  ```ts
740
- extrude(height: number, opts?: { twist?: number; divisions?: number; scaleTop?: number | [ number, number ]; }): Shape
378
+ const pair = union2d(rect(40, 40), rect(40, 40).translate(60, 0));
379
+ const [left, right] = pair.regions(); // largest first
380
+ left.extrude(5);
741
381
  ```
742
382
 
743
- #### `revolve()` — Revolve this 2D sketch around the world Z axis. Sketch X is radius; sketch Y becomes world Z height.
383
+ #### `region(seed: Vec2): Sketch` — Select the single filled region that contains the given 2D seed point.
384
+
385
+ 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()`.
744
386
 
745
387
  ```ts
746
- revolve(degrees?: number, segments?: number): Shape
388
+ const donut = circle2d(50).subtract(circle2d(30));
389
+ donut.region([40, 0]).extrude(10); // seed at radius 40, inside the ring
747
390
  ```
748
391
 
392
+ **Promotion**
393
+
394
+ #### `extrude(height: number, opts?: { twist?: number; divisions?: number; scaleTop?: number | Vec2; }): Shape` — Extrude this 2D sketch along Z to create a 3D solid. Supports twist and scale tapering.
395
+
396
+ #### `revolve(degrees?: number, segments?: number): Shape` — Revolve this 2D sketch around the world Z axis. Sketch X is radius; sketch Y becomes world Z height. Keep the profile at X > 0 unless it intentionally touches the axis.
397
+
749
398
  **Placement**
750
399
 
751
- #### `attachTo()` — Position this sketch relative to another using named anchor points.
400
+ #### `attachTo(target: Sketch, targetAnchor: Anchor, selfAnchor?: Anchor, offset?: Vec2): Sketch` — Position this sketch relative to another using named anchor points.
752
401
 
753
402
  Computes the translation needed to align `selfAnchor` on this sketch with `targetAnchor` on the target sketch, then applies an optional pixel-exact offset.
754
403
 
@@ -759,117 +408,47 @@ const arm = rect(4, 70).attachTo(plate, 'bottom-left', 'top-left');
759
408
  const shifted = rect(4, 70).attachTo(plate, 'bottom-left', 'top-left', [5, 0]);
760
409
  ```
761
410
 
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.
411
+ #### `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` — Place this sketch on a face or planar target in 3D space.
767
412
 
768
413
  Use this when a 2D profile should be oriented onto a 3D face before extrusion or other downstream operations.
769
414
 
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
- ```
415
+ `FaceRef` — defined in [core](/docs/core).
773
416
 
774
- **`FaceRef`**
417
+ **Labels**
775
418
 
776
- | Option | Type | Description |
777
- |--------|------|-------------|
778
- | `normal` | `[ number, number, number ]` | Normal direction of the face |
779
- | `center` | `[ number, number, number ]` | Center point of the face |
780
- | `query?` | `FaceQueryRef` | Compiler-owned face query when available. |
781
- | `planar?` | `boolean` | True when the face can host a 2D sketch placement frame |
782
- | `uAxis?` | `[ number, number, number ]` | Face-local horizontal axis for planar faces |
783
- | `vAxis?` | `[ number, number, number ]` | Face-local vertical axis for planar faces |
784
- | `surface?` | `FaceSurface` | Analytic surface family when the backend can identify one. |
785
- | `descendant?` | `FaceDescendantMetadata` | Shared descendant-resolution metadata when this face is a semantic region/set. |
786
- | `name` | | — |
787
-
788
- **`FaceDescendantMetadata`**: `kind: "single" | "face-set"`, `semantic: FaceDescendantSemantic`, `memberCount: number`, `memberNames: string[]`, `coplanar: boolean`
789
-
790
- **Labels**
791
-
792
- #### `labelEdge()` — Label the single boundary edge (for circles, single-loop profiles). Returns a new sketch.
793
-
794
- ```ts
795
- labelEdge(name: string): Sketch
796
- ```
419
+ #### `labelEdge(name: string): Sketch` Label the single boundary edge (for circles, single-loop profiles). Returns a new sketch.
797
420
 
798
- #### `labelEdges()` — Label edges in winding order, or by named map for rect.
421
+ #### `labelEdges(...args: (string | null)[] | [ Record<string, string> ]): Sketch` — Label edges in winding order, or by named map for rect.
799
422
 
800
423
  Positional: `labelEdges('bottom', 'right', 'top', 'left')` — one per edge, `null` to skip. Named (rect only): `labelEdges({ bottom: 'floor', top: 'ceiling' })`. Returns a new sketch.
801
424
 
802
- ```ts
803
- labelEdges(...args: (string | null)[] | [ Record<string, string> ]): Sketch
804
- ```
425
+ #### `edgeLabels(): string[]` — List current edge label names.
805
426
 
806
- #### `edgeLabels()` — List current edge label names.
427
+ #### `prefixLabels(prefix: string): Sketch` — Prefix all edge labels. Returns a new sketch with prefixed labels.
807
428
 
808
- ```ts
809
- edgeLabels(): string[]
810
- ```
429
+ #### `renameLabel(from: string, to: string): Sketch` — Rename a single edge label. Returns a new sketch.
811
430
 
812
- #### `prefixLabels()` — Prefix all edge labels. Returns a new sketch with prefixed labels.
813
-
814
- ```ts
815
- prefixLabels(prefix: string): Sketch
816
- ```
431
+ #### `dropLabels(...names: string[]): Sketch` — Remove specific labels. Returns a new sketch.
817
432
 
818
- #### `renameLabel()` — Rename a single edge label. Returns a new sketch.
819
-
820
- ```ts
821
- renameLabel(from: string, to: string): Sketch
822
- ```
823
-
824
- #### `dropLabels()` — Remove specific labels. Returns a new sketch.
825
-
826
- ```ts
827
- dropLabels(...names: string[]): Sketch
828
- ```
829
-
830
- #### `dropAllLabels()` — Remove all labels. Returns a new sketch.
831
-
832
- ```ts
833
- dropAllLabels(): Sketch
834
- ```
433
+ #### `dropAllLabels(): Sketch` — Remove all labels. Returns a new sketch.
835
434
 
836
435
  **Measurement**
837
436
 
838
- #### `area()` — Return the total filled area of the sketch.
437
+ #### `area(): number` — Return the total filled area of the sketch.
839
438
 
840
- ```ts
841
- area(): number
842
- ```
439
+ #### `bounds(): ProfileBounds` — Return the axis-aligned bounding box of the sketch.
843
440
 
844
- #### `bounds()` — Return the axis-aligned bounding box of the sketch.
441
+ #### `isEmpty(): boolean` — Return `true` if the sketch contains no filled area.
845
442
 
846
- ```ts
847
- bounds(): ProfileBounds
848
- ```
849
-
850
- #### `isEmpty()` — Return `true` if the sketch contains no filled area.
851
-
852
- ```ts
853
- isEmpty(): boolean
854
- ```
855
-
856
- #### `numVert()` — Return the number of vertices in the polygon representation of the sketch contours.
857
-
858
- ```ts
859
- numVert(): number
860
- ```
443
+ #### `numVert(): number` — Return the number of vertices in the polygon representation of the sketch contours.
861
444
 
862
- #### `toPolygons()` — Return the sketch as a list of polygons matching its contour topology.
445
+ #### `toPolygons(): number[][][]` — Return the sketch as a list of polygons matching its contour topology.
863
446
 
864
447
  Useful when you need raw polygon data for inspection or custom export.
865
448
 
866
- ```ts
867
- toPolygons(): number[][][]
868
- ```
869
-
870
449
  **Other**
871
450
 
872
- #### `color()` — Set the display color of this sketch.
451
+ #### `color(value: string | undefined): Sketch` — Set the display color of this sketch.
873
452
 
874
453
  Color is preserved through all transforms and boolean operations. Pass `undefined` to clear the color.
875
454
 
@@ -877,129 +456,53 @@ Color is preserved through all transforms and boolean operations. Pass `undefine
877
456
  circle2d(20).color('#ff0000').extrude(5);
878
457
  ```
879
458
 
880
- ```ts
881
- color(value: string | undefined): Sketch
882
- ```
883
-
884
- #### `clone()` — Create an explicit copy of this sketch for branching variants.
459
+ #### `clone(): Sketch` — Create an explicit copy of this sketch for branching variants.
885
460
 
886
461
  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.
887
462
 
888
- ```ts
889
- clone(): Sketch
890
- ```
891
-
892
463
  ### `ConstrainedSketchBuilder`
893
464
 
894
465
  **Drawing**
895
466
 
896
- #### `moveTo()` — Move the cursor to `(x, y)` and start a new profile loop.
467
+ #### `moveTo(x: number, y: number): this` — Move the cursor to `(x, y)` and start a new profile loop.
897
468
 
898
- ```ts
899
- moveTo(x: number, y: number): this
900
- ```
469
+ #### `lineTo(x: number, y: number): this` — Draw a line from the current cursor to `(x, y)`.
901
470
 
902
- #### `lineTo()` — Draw a line from the current cursor to `(x, y)`.
471
+ #### `lineH(dx: number): this` — Draw a horizontal line of length `dx` from the current cursor.
903
472
 
904
- ```ts
905
- lineTo(x: number, y: number): this
906
- ```
473
+ #### `lineV(dy: number): this` — Draw a vertical line of length `dy` from the current cursor.
907
474
 
908
- #### `lineH()` — Draw a horizontal line of length `dx` from the current cursor.
475
+ #### `lineAngled(length: number, degrees: number): this` — Draw a line of the given `length` at `degrees` from +X.
909
476
 
910
- ```ts
911
- lineH(dx: number): this
912
- ```
477
+ #### `arcTo(x: number, y: number, radius: number, clockwise?: boolean): this` — Draw a circular arc from the current cursor to `(x, y)` with the given radius.
913
478
 
914
- #### `lineV()` — Draw a vertical line of length `dy` from the current cursor.
479
+ #### `arcByCenter(centerId: PointId, startId: PointId, endId: PointId, clockwise?: boolean, name?: string, fixedRadius?: boolean): ArcId` — Create an arc from an explicit center point and endpoint IDs.
915
480
 
916
- ```ts
917
- lineV(dy: number): this
918
- ```
481
+ #### `bezier(p0: any, p1: any, p2: any, p3: any, name?: string): BezierId` — Create a cubic Bezier curve from four control points.
919
482
 
920
- #### `lineAngled()` — Draw a line of the given `length` at `degrees` from +X.
483
+ #### `bezierTo(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number): this` — Draw a cubic Bezier from the current cursor to `(x3, y3)`.
921
484
 
922
- ```ts
923
- lineAngled(length: number, degrees: number): this
924
- ```
485
+ #### `blendTo(x: number, y: number, weight?: number): this` — Draw a smooth Bezier tangent to the previous arc.
925
486
 
926
- #### `arcTo()` — Draw a circular arc from the current cursor to `(x, y)` with the given radius.
487
+ #### `label(name: string): this` — Label the current path segment.
927
488
 
928
- ```ts
929
- arcTo(x: number, y: number, radius: number, clockwise?: boolean): this
930
- ```
931
-
932
- #### `arcByCenter()` — Create an arc from an explicit center point and endpoint IDs.
933
-
934
- ```ts
935
- arcByCenter(centerId: PointId, startId: PointId, endId: PointId, clockwise?: boolean, name?: string, fixedRadius?: boolean): ArcId
936
- ```
937
-
938
- #### `bezier()` — Create a cubic Bezier curve from four control points.
939
-
940
- ```ts
941
- bezier(p0: any, p1: any, p2: any, p3: any, name?: string): BezierId
942
- ```
943
-
944
- #### `bezierTo()` — Draw a cubic Bezier from the current cursor to `(x3, y3)`.
945
-
946
- ```ts
947
- bezierTo(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number): this
948
- ```
949
-
950
- #### `blendTo()` — Draw a smooth Bezier tangent to the previous arc.
951
-
952
- ```ts
953
- blendTo(x: number, y: number, weight?: number): this
954
- ```
955
-
956
- #### `label()` — Label the current path segment.
957
-
958
- ```ts
959
- label(name: string): this
960
- ```
961
-
962
- #### `close()` — Close the current path and register the loop.
963
-
964
- ```ts
965
- close(): this
966
- ```
967
-
968
- #### `addLoopCircle()` — Add a circle loop to the path.
969
-
970
- ```ts
971
- addLoopCircle(center: PointId, radius: number, segments?: number): this
972
- ```
489
+ #### `close(): this` — Close the current path and register the loop.
973
490
 
974
- #### `addLoop()` — Add a closed polygon loop from point IDs.
491
+ #### `addLoopCircle(center: PointId, radius: number, segments?: number): this` — Add a circle loop to the path.
975
492
 
976
- ```ts
977
- addLoop(points: any[]): this
978
- ```
493
+ #### `addLoop(points: any[]): this` — Add a closed polygon loop from point IDs.
979
494
 
980
- #### `addProfileLoop()` — Add a profile loop from prebuilt line/arc/bezier segments.
981
-
982
- ```ts
983
- addProfileLoop(segments: Array<{ kind: "line"; line: any; } | { kind: "arc"; arc: any; } | { kind: "bezier"; bezier: any; }>): this
984
- ```
495
+ #### `addProfileLoop(segments: Array<{ kind: "line"; line: any; } | { kind: "arc"; arc: any; } | { kind: "bezier"; bezier: any; }>): this` — Add a profile loop from prebuilt line/arc/bezier segments.
985
496
 
986
497
  **Entities**
987
498
 
988
- #### `point()` — Add a free point to the sketch at `(x, y)`.
499
+ #### `point(x?: number, y?: number, fixed?: boolean): PointId` — Add a free point to the sketch at `(x, y)`.
989
500
 
990
501
  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`.
991
502
 
992
- ```ts
993
- point(x?: number, y?: number, fixed?: boolean): PointId
994
- ```
503
+ #### `pointAt(index: number): PointId` — Return the `PointId` of the point created at the given insertion index.
995
504
 
996
- #### `pointAt()` Return the `PointId` of the point created at the given insertion index.
997
-
998
- ```ts
999
- pointAt(index: number): PointId
1000
- ```
1001
-
1002
- #### `line()` — Connect two existing points with a line segment.
505
+ #### `line(a: PointId, b: PointId, construction?: boolean, name?: string): LineId` Connect two existing points with a line segment.
1003
506
 
1004
507
  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).
1005
508
 
@@ -1008,39 +511,19 @@ const axis = sk.line(sk.point(0, -50), sk.point(0, 50), true);
1008
511
  sk.symmetric(p1, p2, axis);
1009
512
  ```
1010
513
 
1011
- ```ts
1012
- line(a: PointId, b: PointId, construction?: boolean, name?: string): LineId
1013
- ```
1014
-
1015
- #### `lineAt()` — Return the `LineId` of the line created at the given insertion index.
514
+ #### `lineAt(index: number): LineId` — Return the `LineId` of the line created at the given insertion index.
1016
515
 
1017
- ```ts
1018
- lineAt(index: number): LineId
1019
- ```
1020
-
1021
- #### `circle()` — Add a circle to the sketch with the given center point and initial radius.
516
+ #### `circle(center: PointId, radius: number, construction?: boolean, segments?: number, name?: string): CircleId` — Add a circle to the sketch with the given center point and initial radius.
1022
517
 
1023
518
  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.
1024
519
 
1025
- ```ts
1026
- circle(center: PointId, radius: number, construction?: boolean, segments?: number, name?: string): CircleId
1027
- ```
1028
-
1029
- #### `circleAt()` — Return the `CircleId` of the circle created at the given insertion index.
1030
-
1031
- ```ts
1032
- circleAt(index: number): CircleId
1033
- ```
520
+ #### `circleAt(index: number): CircleId` — Return the `CircleId` of the circle created at the given insertion index.
1034
521
 
1035
- #### `shape()` — Register a named shape (closed polygon) from an ordered list of line IDs.
522
+ #### `shape(lines: LineId[]): ShapeId` — Register a named shape (closed polygon) from an ordered list of line IDs.
1036
523
 
1037
524
  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()`.
1038
525
 
1039
- ```ts
1040
- shape(lines: LineId[]): ShapeId
1041
- ```
1042
-
1043
- #### [`group()`](/docs/core#group) — Create a rigid-body group with a local coordinate frame.
526
+ #### `group(opts?: { x?: number; y?: number; theta?: number; id?: string; }): SketchGroupBuilder` — Create a rigid-body group with a local coordinate frame.
1044
527
 
1045
528
  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`.
1046
529
 
@@ -1057,33 +540,39 @@ const handle = g.done();
1057
540
  sk.coincident(p0, someExternalPoint);
1058
541
  ```
1059
542
 
1060
- ```ts
1061
- group(opts?: { x?: number; y?: number; theta?: number; id?: string; }): SketchGroupBuilder
1062
- ```
543
+ #### `rect(options?: RectOptions): ConstrainedRect` — Add an axis-aligned rectangle concept. Returns a `ConstrainedRect` handle with named vertices, sides, and center.
1063
544
 
1064
- #### `rect()` — Add an axis-aligned rectangle concept. Returns a `ConstrainedRect` handle with named vertices, sides, and center.
545
+ **`RectOptions`**
1065
546
 
1066
- ```ts
1067
- rect(options?: RectOptions): ConstrainedRect
1068
- ```
547
+ | Option | Type | Description |
548
+ |--------|------|-------------|
549
+ | `x?` | `number` | Bottom-left x coordinate. Default: 0. |
550
+ | `y?` | `number` | Bottom-left y coordinate. Default: 0. |
551
+ | `width?` | `number` | Width (along x). Default: 10. |
552
+ | `height?` | `number` | Height (along y). Default: 10. |
553
+ | `blockRotation?` | `boolean` | Prevent 180° rotation (ensures bottom edge points rightward). Default: false. |
1069
554
 
1070
- #### `addPolygon()` — Add a general polygon concept (CCW winding enforced). Returns a `ConstrainedPolygon` handle.
555
+ #### `addPolygon(options: PolygonOptions): ConstrainedPolygon` — Add a general polygon concept (CCW winding enforced). Returns a `ConstrainedPolygon` handle.
1071
556
 
1072
- ```ts
1073
- addPolygon(options: PolygonOptions): ConstrainedPolygon
1074
- ```
557
+ **`PolygonOptions`**
558
+ - `points: ReadonlyArray<readonly Vec2>` — Initial vertex coordinates. Minimum 3 points.
559
+ - `addLoop?: boolean` — Whether to register a closed loop for sketch generation. Default: true.
560
+ - `blockRotation?: boolean` — Prevent 180° rotation (ensures first edge maintains its initial direction). Default: false.
1075
561
 
1076
- #### `regularPolygon()` — Add a regular n-gon concept (equal sides, CCW winding). Returns a `ConstrainedRegularPolygon` handle with a center point.
562
+ #### `regularPolygon(options: RegularPolygonOptions): ConstrainedRegularPolygon` — Add a regular n-gon concept (equal sides, CCW winding). Returns a `ConstrainedRegularPolygon` handle with a center point.
1077
563
 
1078
- ```ts
1079
- regularPolygon(options: RegularPolygonOptions): ConstrainedRegularPolygon
1080
- ```
564
+ **`RegularPolygonOptions`**
1081
565
 
1082
- #### `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.
566
+ | Option | Type | Description |
567
+ |--------|------|-------------|
568
+ | `sides` | `number` | Number of sides (minimum 3). |
569
+ | `radius?` | `number` | Circumradius — distance from center to vertex. Default: 10. |
570
+ | `cx?` | `number` | Center x coordinate. Default: 0. |
571
+ | `cy?` | `number` | Center y coordinate. Default: 0. |
572
+ | `startAngle?` | `number` | Angle (in degrees) of vertex[0] measured from the +X axis (CCW positive). Default: 0 (rightmost vertex). |
573
+ | `blockRotation?` | `boolean` | Prevent 180° rotation (ensures first edge maintains its initial direction). Default: false. |
1083
574
 
1084
- ```ts
1085
- groupRect(options: GroupRectOptions): ConstrainedGroupRect
1086
- ```
575
+ #### `groupRect(options: GroupRectOptions): ConstrainedGroupRect` — 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.
1087
576
 
1088
577
  **`GroupRectOptions`**
1089
578
 
@@ -1097,325 +586,115 @@ groupRect(options: GroupRectOptions): ConstrainedGroupRect
1097
586
 
1098
587
  **Geometric Constraints**
1099
588
 
1100
- #### `horizontal()` — Constrain a line to be horizontal (parallel to the X axis).
1101
-
1102
- ```ts
1103
- horizontal(line: any): this
1104
- ```
1105
-
1106
- #### `vertical()` — Constrain a line to be vertical (parallel to the Y axis).
1107
-
1108
- ```ts
1109
- vertical(line: any): this
1110
- ```
1111
-
1112
- #### `parallel()` — Constrain two lines to be parallel.
1113
-
1114
- ```ts
1115
- parallel(a: any, b: any): this
1116
- ```
1117
-
1118
- #### `sameDirection()` — Constrain two lines to point in the same direction.
589
+ #### `horizontal(line: any): this` — Constrain a line to be horizontal (parallel to the X axis).
1119
590
 
1120
- ```ts
1121
- sameDirection(a: any, b: any): this
1122
- ```
1123
-
1124
- #### `oppositeDirection()` — Constrain two lines to point in opposite directions.
1125
-
1126
- ```ts
1127
- oppositeDirection(a: any, b: any): this
1128
- ```
1129
-
1130
- #### `perpendicular()` — Constrain two lines to be perpendicular.
591
+ #### `vertical(line: any): this` — Constrain a line to be vertical (parallel to the Y axis).
1131
592
 
1132
- ```ts
1133
- perpendicular(a: any, b: any): this
1134
- ```
593
+ #### `parallel(a: any, b: any): this` — Constrain two lines to be parallel.
1135
594
 
1136
- #### `tangent()` — Constrain a line/circle or circle/circle tangency relationship.
595
+ #### `sameDirection(a: any, b: any): this` — Constrain two lines to point in the same direction.
1137
596
 
1138
- ```ts
1139
- tangent(a: any, b: any): this
1140
- ```
597
+ #### `oppositeDirection(a: any, b: any): this` — Constrain two lines to point in opposite directions.
1141
598
 
1142
- #### `collinear()` — Constrain a point to lie on the infinite extension of a line.
1143
-
1144
- ```ts
1145
- collinear(point: any, line: any): this
1146
- ```
599
+ #### `perpendicular(a: any, b: any): this` — Constrain two lines to be perpendicular.
1147
600
 
1148
- #### `symmetric()` — Constrain two points to be symmetric about an axis line.
601
+ #### `tangent(a: any, b: any): this` — Constrain a line/circle or circle/circle tangency relationship.
1149
602
 
1150
- ```ts
1151
- symmetric(a: any, b: any, axis: any): this
1152
- ```
603
+ #### `collinear(point: any, line: any): this` — Constrain a point to lie on the infinite extension of a line.
1153
604
 
1154
- #### `blockRotation()` — Prevent 180° rotation of a polygon by anchoring its first edge.
605
+ #### `symmetric(a: any, b: any, axis: any): this` — Constrain two points to be symmetric about an axis line.
1155
606
 
1156
- ```ts
1157
- blockRotation(points: any[], axis?: "x" | "y"): this
1158
- ```
607
+ #### `blockRotation(points: any[], axis?: "x" | "y"): this` — Prevent 180° rotation of a polygon by anchoring its first edge.
1159
608
 
1160
609
  **Dimensional Constraints**
1161
610
 
1162
- #### `distance()` — Constrain the Euclidean distance between two points.
1163
-
1164
- ```ts
1165
- distance(a: any, b: any, value: number): this
1166
- ```
1167
-
1168
- #### `length()` — Constrain the length of a line segment.
1169
-
1170
- ```ts
1171
- length(line: any, value: number): this
1172
- ```
1173
-
1174
- #### `angle()` — Constrain the signed angle from line `a` to line `b`.
1175
-
1176
- ```ts
1177
- angle(a: any, b: any, value: number): this
1178
- ```
1179
-
1180
- #### `radius()` — Constrain the radius of a circle.
1181
-
1182
- ```ts
1183
- radius(circle: any, value: number): this
1184
- ```
1185
-
1186
- #### `diameter()` — Constrain the diameter of a circle.
1187
-
1188
- ```ts
1189
- diameter(circle: any, value: number): this
1190
- ```
1191
-
1192
- #### `hDistance()` — Constrain the horizontal distance between two points.
1193
-
1194
- ```ts
1195
- hDistance(a: any, b: any, value: number): this
1196
- ```
1197
-
1198
- #### `vDistance()` — Constrain the vertical distance between two points.
611
+ #### `distance(a: any, b: any, value: number): this` — Constrain the Euclidean distance between two points.
1199
612
 
1200
- ```ts
1201
- vDistance(a: any, b: any, value: number): this
1202
- ```
613
+ #### `length(line: any, value: number): this` — Constrain the length of a line segment.
1203
614
 
1204
- #### `pointLineDistance()` — Constrain the signed perpendicular distance from a point to a line.
615
+ #### `angle(a: any, b: any, value: number): this` — Constrain the signed angle from line `a` to line `b`.
1205
616
 
1206
- ```ts
1207
- pointLineDistance(point: any, line: any, value: number): this
1208
- ```
617
+ #### `radius(circle: any, value: number): this` — Constrain the radius of a circle.
1209
618
 
1210
- #### `lineDistance()` — Constrain the perpendicular offset distance between two lines.
1211
-
1212
- ```ts
1213
- lineDistance(a: any, b: any, value: number): this
1214
- ```
619
+ #### `diameter(circle: any, value: number): this` — Constrain the diameter of a circle.
1215
620
 
1216
- #### `absoluteAngle()` — Constrain the absolute angle of a line measured from +X.
621
+ #### `hDistance(a: any, b: any, value: number): this` — Constrain the horizontal distance between two points.
1217
622
 
1218
- ```ts
1219
- absoluteAngle(line: any, value: number): this
1220
- ```
623
+ #### `vDistance(a: any, b: any, value: number): this` — Constrain the vertical distance between two points.
1221
624
 
1222
- #### `arcLength()` — Constrain the arc length of an arc.
625
+ #### `pointLineDistance(point: any, line: any, value: number): this` — Constrain the signed perpendicular distance from a point to a line.
1223
626
 
1224
- ```ts
1225
- arcLength(arc: any, value: number): this
1226
- ```
627
+ #### `lineDistance(a: any, b: any, value: number): this` — Constrain the perpendicular offset distance between two lines.
1227
628
 
1228
- #### `equalRadius()` — Constrain two circles to have equal radii.
629
+ #### `absoluteAngle(line: any, value: number): this` — Constrain the absolute angle of a line measured from +X.
1229
630
 
1230
- ```ts
1231
- equalRadius(a: any, b: any): this
1232
- ```
631
+ #### `arcLength(arc: any, value: number): this` — Constrain the arc length of an arc.
1233
632
 
1234
- #### `angleBetween()` — Constrain the unsigned angle between two lines.
633
+ #### `equalRadius(a: any, b: any): this` — Constrain two circles to have equal radii.
1235
634
 
1236
- ```ts
1237
- angleBetween(a: any, b: any, value: number): this
1238
- ```
635
+ #### `angleBetween(a: any, b: any, value: number): this` — Constrain the unsigned angle between two lines.
1239
636
 
1240
637
  **Coincidence & Equality**
1241
638
 
1242
- #### `equal()` — Constrain two lines to have equal length.
1243
-
1244
- ```ts
1245
- equal(a: any, b: any): this
1246
- ```
1247
-
1248
- #### `coincident()` — Constrain two points to coincide.
1249
-
1250
- ```ts
1251
- coincident(a: any, b: any): this
1252
- ```
639
+ #### `equal(a: any, b: any): this` — Constrain two lines to have equal length.
1253
640
 
1254
- #### `concentric()` — Constrain two circles to share a center.
641
+ #### `coincident(a: any, b: any): this` — Constrain two points to coincide.
1255
642
 
1256
- ```ts
1257
- concentric(a: any, b: any): this
1258
- ```
643
+ #### `concentric(a: any, b: any): this` — Constrain two circles to share a center.
1259
644
 
1260
- #### `fix()` — Pin a point at a specific world location.
645
+ #### `fix(point: any, x?: number, y?: number): this` — Pin a point at a specific world location.
1261
646
 
1262
- ```ts
1263
- fix(point: any, x?: number, y?: number): this
1264
- ```
647
+ #### `midpoint(point: any, line: any): this` — Constrain a point to lie at the midpoint of a line.
1265
648
 
1266
- #### `midpoint()` — Constrain a point to lie at the midpoint of a line.
649
+ #### `pointOnCircle(point: any, circle: any): this` — Constrain a point to lie on the perimeter of a circle.
1267
650
 
1268
- ```ts
1269
- midpoint(point: any, line: any): this
1270
- ```
651
+ #### `pointOnLine(point: any, line: any): this` — Constrain a point to lie on the bounded segment of a line.
1271
652
 
1272
- #### `pointOnCircle()` — Constrain a point to lie on the perimeter of a circle.
1273
-
1274
- ```ts
1275
- pointOnCircle(point: any, circle: any): this
1276
- ```
1277
-
1278
- #### `pointOnLine()` — Constrain a point to lie on the bounded segment of a line.
1279
-
1280
- ```ts
1281
- pointOnLine(point: any, line: any): this
1282
- ```
1283
-
1284
- #### `ccw()` — Constrain all given points to be in counter-clockwise order.
1285
-
1286
- ```ts
1287
- ccw(...points: any[]): this
1288
- ```
653
+ #### `ccw(...points: any[]): this` — Constrain all given points to be in counter-clockwise order.
1289
654
 
1290
655
  **Tangent Transitions**
1291
656
 
1292
- #### `lineTangentArc()` — Constrain a line to be tangent to an arc at its start or end point.
1293
-
1294
- ```ts
1295
- lineTangentArc(line: any, arc: any, atStart: boolean): this
1296
- ```
1297
-
1298
- #### `arcTangentArc()` — Constrain two arcs to be tangent at their shared junction point.
1299
-
1300
- ```ts
1301
- arcTangentArc(arcA: any, arcB: any, aAtStart?: boolean, bAtStart?: boolean): this
1302
- ```
657
+ #### `lineTangentArc(line: any, arc: any, atStart: boolean): this` — Constrain a line to be tangent to an arc at its start or end point.
1303
658
 
1304
- #### `bezierTangentArc()` — Constrain a Bezier to be tangent to an arc at one endpoint.
1305
-
1306
- ```ts
1307
- bezierTangentArc(bezier: any, arc: any, atBezierStart: boolean, atArcStart: boolean): this
1308
- ```
659
+ #### `arcTangentArc(arcA: any, arcB: any, aAtStart?: boolean, bAtStart?: boolean): this` — Constrain two arcs to be tangent at their shared junction point.
1309
660
 
1310
- #### `smoothBlend()` — Create a Bezier blend between two arcs.
661
+ #### `bezierTangentArc(bezier: any, arc: any, atBezierStart: boolean, atArcStart: boolean): this` — Constrain a Bezier to be tangent to an arc at one endpoint.
1311
662
 
1312
- ```ts
1313
- smoothBlend(arc1: any, arc2: any, options?: { weight?: number; arc1End?: "start" | "end"; arc2End?: "start" | "end"; }): BezierId
1314
- ```
663
+ #### `smoothBlend(arc1: any, arc2: any, options?: { weight?: number; arc1End?: "start" | "end"; arc2End?: "start" | "end"; }): BezierId` — Create a Bezier blend between two arcs.
1315
664
 
1316
665
  **Shape Constraints**
1317
666
 
1318
- #### `shapeWidth()` — Constrain a shape's width.
1319
-
1320
- ```ts
1321
- shapeWidth(shape: any, value: number): this
1322
- ```
1323
-
1324
- #### `shapeHeight()` — Constrain a shape's height.
1325
-
1326
- ```ts
1327
- shapeHeight(shape: any, value: number): this
1328
- ```
1329
-
1330
- #### `shapeCentroidX()` — Constrain a shape's centroid X position.
1331
-
1332
- ```ts
1333
- shapeCentroidX(shape: any, value: number): this
1334
- ```
1335
-
1336
- #### `shapeCentroidY()` — Constrain a shape's centroid Y position.
667
+ #### `shapeWidth(shape: any, value: number): this` — Constrain a shape's width.
1337
668
 
1338
- ```ts
1339
- shapeCentroidY(shape: any, value: number): this
1340
- ```
669
+ #### `shapeHeight(shape: any, value: number): this` — Constrain a shape's height.
1341
670
 
1342
- #### `shapeArea()` — Constrain a shape's area.
671
+ #### `shapeCentroidX(shape: any, value: number): this` — Constrain a shape's centroid X position.
1343
672
 
1344
- ```ts
1345
- shapeArea(shape: any, value: number): this
1346
- ```
673
+ #### `shapeCentroidY(shape: any, value: number): this` — Constrain a shape's centroid Y position.
1347
674
 
1348
- #### `shapeEqualCentroid()` — Constrain two shapes to have the same centroid.
675
+ #### `shapeArea(shape: any, value: number): this` — Constrain a shape's area.
1349
676
 
1350
- ```ts
1351
- shapeEqualCentroid(a: any, b: any): this
1352
- ```
677
+ #### `shapeEqualCentroid(a: any, b: any): this` — Constrain two shapes to have the same centroid.
1353
678
 
1354
679
  **Positioning**
1355
680
 
1356
- #### `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.
1357
-
1358
- ```ts
1359
- offsetX(a: any, b: any, value: number): this
1360
- ```
1361
-
1362
- #### `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.
1363
-
1364
- ```ts
1365
- offsetY(a: any, b: any, value: number): this
1366
- ```
1367
-
1368
- #### `importPoint()` — Import a `Point2D` object into the sketch.
1369
-
1370
- ```ts
1371
- importPoint(pt: { x: number; y: number; }, fixed?: boolean): PointId
1372
- ```
1373
-
1374
- #### `importLine()` — Import a `Line2D` object into the sketch.
1375
-
1376
- ```ts
1377
- importLine(l: { start: { x: number; y: number; }; end: { x: number; y: number; }; }, fixed?: boolean): LineId
1378
- ```
1379
-
1380
- #### `importRectangle()` — Import a `Rectangle2D` as four points and four lines.
1381
-
1382
- ```ts
1383
- importRectangle(r: { vertices: [ { x: number; y: number; }, { x: number; y: number; }, { x: number; y: number; }, { x: number; y: number; } ]; }, fixed?: boolean): { ... }
1384
- ```
1385
-
1386
- #### `referencePoint()` — Add a fixed reference point at `(x, y)`.
1387
-
1388
- ```ts
1389
- referencePoint(x: number, y: number): PointId
1390
- ```
1391
-
1392
- #### `referenceLine()` — Add a fixed reference line from `(x1, y1)` to `(x2, y2)`.
681
+ #### `offsetX(a: any, b: any, value: number): this` — 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.
1393
682
 
1394
- ```ts
1395
- referenceLine(x1: number, y1: number, x2: number, y2: number): LineId
1396
- ```
683
+ #### `offsetY(a: any, b: any, value: number): this` — 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.
1397
684
 
1398
- #### `referenceFrom()` Import a single named entity from a solved sketch as fixed reference geometry.
685
+ #### `referencePoint(x: number, y: number): PointId` Add a fixed reference point at `(x, y)`.
1399
686
 
1400
- ```ts
1401
- referenceFrom(source: ConstraintSketch, entityId: string): PointId | LineId | null
1402
- ```
687
+ #### `referenceLine(x1: number, y1: number, x2: number, y2: number): LineId` — Add a fixed reference line from `(x1, y1)` to `(x2, y2)`.
1403
688
 
1404
- #### `referenceAllFrom()` — Import all non-construction entities from a solved sketch as fixed references.
689
+ #### `referenceFrom(source: ConstraintSketch, entityId: string): PointId | LineId | null` — Import a single named entity from a solved sketch as fixed reference geometry.
1405
690
 
1406
- ```ts
1407
- referenceAllFrom(source: ConstraintSketch): { points: Map<string, PointId>; lines: Map<string, LineId>; }
1408
- ```
691
+ #### `referenceAllFrom(source: ConstraintSketch): { points: Map<string, PointId>; lines: Map<string, LineId>; }` — Import all non-construction entities from a solved sketch as fixed references.
1409
692
 
1410
693
  **Solving**
1411
694
 
1412
- #### `constrain()` — Add a raw constraint object to the builder.
1413
-
1414
- ```ts
1415
- constrain(constraint: Omit<SketchConstraint, "id">): this
1416
- ```
695
+ #### `constrain(constraint: Omit<SketchConstraint, "id">): this` — Add a raw constraint object to the builder.
1417
696
 
1418
- #### `solve()` — Run the constraint solver and return a solved sketch.
697
+ #### `solve(options?: SolveOptions): ConstraintSketch | Sketch` — Run the constraint solver and return a solved sketch.
1419
698
 
1420
699
  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:
1421
700
 
@@ -1434,10 +713,6 @@ result.withUpdatedConstraint('cst-5', 120); // update a dimension without rebuil
1434
713
  - **Over-constrained** — conflicting constraints are auto-rejected. Check `result.constraintMeta.constraints` and `result.inspect()`.
1435
714
  - **maxError > 1e-6** — solver did not converge; check for contradictory constraints.
1436
715
 
1437
- ```ts
1438
- solve(options?: SolveOptions): ConstraintSketch | Sketch
1439
- ```
1440
-
1441
716
  **`SolveOptions`**
1442
717
 
1443
718
  | Option | Type | Description |
@@ -1455,15 +730,11 @@ solve(options?: SolveOptions): ConstraintSketch | Sketch
1455
730
  | `debugConstructiveTranscript?` | `boolean` | Capture a readable constructive transcript in `constraintMeta.debug`. |
1456
731
  | `debugSvgSnapshots?` | `boolean` | Capture SVG snapshots for constructive steps in `constraintMeta.debug`. |
1457
732
 
1458
- #### `solveConstraintsOnly()` — Run the solver without building a full `ConstraintSketch`.
733
+ #### `solveConstraintsOnly(options?: SolveOptions): { maxError: number; rejectedCount: number; definition: ConstraintDefinition; }` — Run the solver without building a full `ConstraintSketch`.
1459
734
 
1460
735
  Lighter than `solve()` — skips profile and DOF analysis. Useful for lightweight constraint validation or progress monitoring mid-construction.
1461
736
 
1462
- ```ts
1463
- solveConstraintsOnly(options?: SolveOptions): { maxError: number; rejectedCount: number; definition: ConstraintDefinition; }
1464
- ```
1465
-
1466
- #### `route()` — Start a directional route from coordinates.
737
+ #### `route(x: number, y: number): RouteBuilder` — Start a directional route from coordinates.
1467
738
 
1468
739
  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.
1469
740
 
@@ -1476,10 +747,6 @@ r.done();
1476
747
  sk.offsetX(stem, neck, 10.8);
1477
748
  ```
1478
749
 
1479
- ```ts
1480
- route(x: number, y: number): RouteBuilder
1481
- ```
1482
-
1483
750
  ### `ConstraintSketch`
1484
751
 
1485
752
  **Properties:**
@@ -1491,71 +758,31 @@ route(x: number, y: number): RouteBuilder
1491
758
 
1492
759
  **Methods:**
1493
760
 
1494
- #### `detectArrangement()` — Enumerate all bounded regions formed by the line arrangement of this sketch. Construction lines are excluded. Regions are returned largest-first by area.
1495
-
1496
- ```ts
1497
- detectArrangement(): Sketch[]
1498
- ```
761
+ #### `detectArrangement(): Sketch[]` — Enumerate all bounded regions formed by the line arrangement of this sketch. Construction lines are excluded. Regions are returned largest-first by area.
1499
762
 
1500
- #### `detectArrangementRegion()` — Select the single arrangement region that contains the given seed point. Throws if no region contains the seed.
763
+ #### `detectArrangementRegion(_seed: Vec2): Sketch` — Select the single arrangement region that contains the given seed point. Throws if no region contains the seed.
1501
764
 
1502
- ```ts
1503
- detectArrangementRegion(_seed: [ number, number ]): Sketch
1504
- ```
1505
-
1506
- #### `toPolyline()` — Return the solved constrained path as a sampled 2D polyline.
765
+ #### `toPolyline(samples?: number): Vec2[]` — Return the solved constrained path as a sampled 2D polyline.
1507
766
 
1508
767
  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.
1509
768
 
1510
- ```ts
1511
- toPolyline(samples?: number): [ number, number ][]
1512
- ```
1513
-
1514
- #### `withUpdatedConstraint()` — Re-solve the sketch after changing the value of one existing constraint.
769
+ #### `withUpdatedConstraint(constraintId: string, value: number): ConstraintSketch` — Re-solve the sketch after changing the value of one existing constraint.
1515
770
 
1516
771
  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.
1517
772
 
1518
- ```ts
1519
- withUpdatedConstraint(constraintId: string, value: number): ConstraintSketch
1520
- ```
1521
-
1522
- #### `inspect()` — Return a human-readable diagnostic string of the solved state.
1523
-
1524
- ```ts
1525
- inspect(): string
1526
- ```
773
+ #### `inspect(): string` — Return a human-readable diagnostic string of the solved state.
1527
774
 
1528
775
  ### `SketchGroupBuilder`
1529
776
 
1530
- #### `point()` — Add a point in local coordinates. Returns its globally-addressable PointId.
777
+ #### `point(lx: number, ly: number): PointId` — Add a point in local coordinates. Returns its globally-addressable PointId.
1531
778
 
1532
- ```ts
1533
- point(lx: number, ly: number): PointId
1534
- ```
1535
-
1536
- #### `line()` — Connect two group points with a line. Both must be PointIds from this group.
1537
-
1538
- ```ts
1539
- line(a: PointId, b: PointId, name?: string): LineId
1540
- ```
1541
-
1542
- #### `fixRotation()` — Freeze rotation (theta). Group can still translate - 2 DOF remain.
779
+ #### `line(a: PointId, b: PointId, name?: string): LineId` — Connect two group points with a line. Both must be PointIds from this group.
1543
780
 
1544
- ```ts
1545
- fixRotation(): this
1546
- ```
781
+ #### `fixRotation(): this` — Freeze rotation (theta). Group can still translate - 2 DOF remain.
1547
782
 
1548
- #### `fix()` — Freeze all 3 DOF - group is completely fixed.
783
+ #### `fix(): this` — Freeze all 3 DOF - group is completely fixed.
1549
784
 
1550
- ```ts
1551
- fix(): this
1552
- ```
1553
-
1554
- #### `done()` — Finalize and register the group with the builder.
1555
-
1556
- ```ts
1557
- done(): SketchGroupHandle
1558
- ```
785
+ #### `done(): SketchGroupHandle` — Finalize and register the group with the builder.
1559
786
 
1560
787
  ### `Point2D`
1561
788
 
@@ -1572,29 +799,13 @@ Used as construction geometry in sketches, constraints, and analytic measurement
1572
799
 
1573
800
  **Methods:**
1574
801
 
1575
- #### `distanceTo()` — Measure straight-line distance to another point.
1576
-
1577
- ```ts
1578
- distanceTo(other: Point2D): number
1579
- ```
1580
-
1581
- #### `midpointTo()` — Compute the midpoint between this point and another point.
1582
-
1583
- ```ts
1584
- midpointTo(other: Point2D): Point2D
1585
- ```
1586
-
1587
- #### `translate()` — Return a point shifted by the given delta.
802
+ #### `distanceTo(other: Point2D): number` — Measure straight-line distance to another point.
1588
803
 
1589
- ```ts
1590
- translate(dx: number, dy: number): Point2D
1591
- ```
804
+ #### `midpointTo(other: Point2D): Point2D` — Compute the midpoint between this point and another point.
1592
805
 
1593
- #### `toTuple()` — Convert this point to a plain `[x, y]` tuple.
806
+ #### `translate(dx: number, dy: number): Point2D` — Return a point shifted by the given delta.
1594
807
 
1595
- ```ts
1596
- toTuple(): [ number, number ]
1597
- ```
808
+ #### `toTuple(): Vec2` — Convert this point to a plain `[x, y]` tuple.
1598
809
 
1599
810
  ### `Line2D`
1600
811
 
@@ -1611,67 +822,27 @@ Provides both segment-only (`intersectSegment`) and infinite-line (`intersect`)
1611
822
 
1612
823
  **Methods:**
1613
824
 
1614
- #### `length()` — Length of the line segment.
1615
-
1616
- ```ts
1617
- get length(): number
1618
- ```
1619
-
1620
- #### `midpoint()` — Midpoint of the line segment.
1621
-
1622
- ```ts
1623
- get midpoint(): Point2D
1624
- ```
1625
-
1626
- #### `angle()` — Direction angle in degrees, measured CCW from +X.
825
+ #### `get length(): number` — Length of the line segment.
1627
826
 
1628
- ```ts
1629
- get angle(): number
1630
- ```
827
+ #### `get midpoint(): Point2D` — Midpoint of the line segment.
1631
828
 
1632
- #### `direction()` — Unit direction vector from start to end.
829
+ #### `get angle(): number` — Direction angle in degrees, measured CCW from +X.
1633
830
 
1634
- ```ts
1635
- get direction(): [ number, number ]
1636
- ```
831
+ #### `get direction(): Vec2` — Unit direction vector from start to end.
1637
832
 
1638
- #### `parallel()` — Create a parallel line offset by the given distance.
833
+ #### `parallel(distance: number): Line2D` — Create a parallel line offset by the given distance.
1639
834
 
1640
835
  Positive distance shifts to the left of the line direction.
1641
836
 
1642
- ```ts
1643
- parallel(distance: number): Line2D
1644
- ```
1645
-
1646
- #### `intersect()` — Intersect this line with another infinite line.
837
+ #### `intersect(other: Line2D): Point2D | null` — Intersect this line with another infinite line.
1647
838
 
1648
- ```ts
1649
- intersect(other: Line2D): Point2D | null
1650
- ```
1651
-
1652
- #### `intersectSegment()` — Intersect this line with another as bounded segments.
1653
-
1654
- ```ts
1655
- intersectSegment(other: Line2D): Point2D | null
1656
- ```
1657
-
1658
- #### `fromCoordinates()` — Create a line from raw coordinates.
839
+ #### `intersectSegment(other: Line2D): Point2D | null` — Intersect this line with another as bounded segments.
1659
840
 
1660
- ```ts
1661
- static fromCoordinates(x1: number, y1: number, x2: number, y2: number): Line2D
1662
- ```
841
+ #### `static fromCoordinates(x1: number, y1: number, x2: number, y2: number): Line2D` — Create a line from raw coordinates.
1663
842
 
1664
- #### `fromPointAndAngle()` — Create a line from a start point, angle, and length.
843
+ #### `static fromPointAndAngle(origin: Point2D, angleDeg: number, length: number): Line2D` — Create a line from a start point, angle, and length.
1665
844
 
1666
- ```ts
1667
- static fromPointAndAngle(origin: Point2D, angleDeg: number, length: number): Line2D
1668
- ```
1669
-
1670
- #### `fromPointAndDirection()` — Create a line from a start point, direction vector, and length.
1671
-
1672
- ```ts
1673
- static fromPointAndDirection(origin: Point2D, dir: [ number, number ], length: number): Line2D
1674
- ```
845
+ #### `static fromPointAndDirection(origin: Point2D, dir: Vec2, length: number): Line2D` — Create a line from a start point, direction vector, and length.
1675
846
 
1676
847
  ### `Circle2D`
1677
848
 
@@ -1688,59 +859,23 @@ Extruding a `Circle2D` produces a cylinder with named `top`, `bottom`, and `side
1688
859
 
1689
860
  **Methods:**
1690
861
 
1691
- #### `diameter()` — Diameter of the circle.
1692
-
1693
- ```ts
1694
- get diameter(): number
1695
- ```
1696
-
1697
- #### `circumference()` — Circumference of the circle.
1698
-
1699
- ```ts
1700
- get circumference(): number
1701
- ```
1702
-
1703
- #### `area()` — Area of the circle.
1704
-
1705
- ```ts
1706
- get area(): number
1707
- ```
1708
-
1709
- #### `pointAtAngle()` — Return a point on the circle at the given angle.
1710
-
1711
- ```ts
1712
- pointAtAngle(angleDeg: number): Point2D
1713
- ```
862
+ #### `get diameter(): number` — Diameter of the circle.
1714
863
 
1715
- #### `translate()` — Return a translated circle.
864
+ #### `get circumference(): number` — Circumference of the circle.
1716
865
 
1717
- ```ts
1718
- translate(dx: number, dy: number): Circle2D
1719
- ```
1720
-
1721
- #### `toSketch()` — Convert this circle to a sketch profile.
1722
-
1723
- ```ts
1724
- toSketch(segments?: number): Sketch
1725
- ```
866
+ #### `get area(): number` — Area of the circle.
1726
867
 
1727
- #### `extrude()` — Extrude the circle into a solid cylinder.
868
+ #### `pointAtAngle(angleDeg: number): Point2D` — Return a point on the circle at the given angle.
1728
869
 
1729
- ```ts
1730
- extrude(height: number, segments?: number): Shape
1731
- ```
870
+ #### `translate(dx: number, dy: number): Circle2D` — Return a translated circle.
1732
871
 
1733
- #### `fromCenterAndRadius()` — Create a circle from its center and radius.
872
+ #### `toSketch(segments?: number): Sketch` — Convert this circle to a sketch profile.
1734
873
 
1735
- ```ts
1736
- static fromCenterAndRadius(center: Point2D, radius: number): Circle2D
1737
- ```
874
+ #### `extrude(height: number, segments?: number): Shape` — Extrude the circle into a solid cylinder.
1738
875
 
1739
- #### `fromDiameter()` — Create a circle from its center and diameter.
876
+ #### `static fromCenterAndRadius(center: Point2D, radius: number): Circle2D` — Create a circle from its center and radius.
1740
877
 
1741
- ```ts
1742
- static fromDiameter(center: Point2D, diameter: number): Circle2D
1743
- ```
878
+ #### `static fromDiameter(center: Point2D, diameter: number): Circle2D` — Create a circle from its center and diameter.
1744
879
 
1745
880
  ### `Rectangle2D`
1746
881
 
@@ -1762,93 +897,37 @@ const [d1, d2] = r.diagonals(); // [bl-tr, br-tl]
1762
897
  r.toSketch(); // Sketch (for 2D operations)
1763
898
  r.extrude(20); // Shape with named faces
1764
899
 
1765
- Rectangle2D.fromCenterAndDimensions(point(50, 30), 100, 60);
1766
- Rectangle2D.from2Corners(point(0, 0), point(100, 60));
900
+ Rectangle2D.fromCenterAndDimensions(new Point2D(50, 30), 100, 60);
901
+ Rectangle2D.from2Corners(new Point2D(0, 0), new Point2D(100, 60));
1767
902
  Rectangle2D.from3Points(p1, p2, p3); // free-angle rectangle
1768
903
  ```
1769
904
 
1770
- #### `width()` — Width of the rectangle.
1771
-
1772
- ```ts
1773
- get width(): number
1774
- ```
1775
-
1776
- #### `height()` — Height of the rectangle.
1777
-
1778
- ```ts
1779
- get height(): number
1780
- ```
1781
-
1782
- #### `center()` — Geometric center of the rectangle.
1783
-
1784
- ```ts
1785
- get center(): Point2D
1786
- ```
1787
-
1788
- #### `side()` — Return a named side of the rectangle.
1789
-
1790
- ```ts
1791
- side(name: RectSide): Line2D
1792
- ```
1793
-
1794
- #### `sideAt()` — Return a side by index.
1795
-
1796
- ```ts
1797
- sideAt(index: number): Line2D
1798
- ```
1799
-
1800
- #### `vertex()` — Return a named vertex of the rectangle.
1801
-
1802
- ```ts
1803
- vertex(name: RectVertex): Point2D
1804
- ```
1805
-
1806
- #### `diagonals()` — Return the two diagonals of the rectangle.
905
+ #### `get width(): number` — Width of the rectangle.
1807
906
 
1808
- ```ts
1809
- diagonals(): [ Line2D, Line2D ]
1810
- ```
907
+ #### `get height(): number` — Height of the rectangle.
1811
908
 
1812
- #### `toSketch()` — Convert the rectangle to a sketch profile.
909
+ #### `get center(): Point2D` — Geometric center of the rectangle.
1813
910
 
1814
- ```ts
1815
- toSketch(): Sketch
1816
- ```
911
+ #### `side(name: RectSide): Line2D` — Return a named side of the rectangle.
1817
912
 
1818
- #### `translate()` — Return a translated rectangle.
913
+ #### `sideAt(index: number): Line2D` — Return a side by index.
1819
914
 
1820
- ```ts
1821
- translate(dx: number, dy: number): Rectangle2D
1822
- ```
915
+ #### `vertex(name: RectVertex): Point2D` — Return a named vertex of the rectangle.
1823
916
 
1824
- #### `fromDimensions()` Create an axis-aligned rectangle from origin corner plus width and height.
917
+ #### `diagonals(): [ Line2D, Line2D ]` Return the two diagonals of the rectangle.
1825
918
 
1826
- ```ts
1827
- static fromDimensions(x: number, y: number, width: number, height: number): Rectangle2D
1828
- ```
919
+ #### `toSketch(): Sketch` — Convert the rectangle to a sketch profile.
1829
920
 
1830
- #### `fromCenterAndDimensions()` — Create a rectangle centered on a point.
921
+ #### `translate(dx: number, dy: number): Rectangle2D` — Return a translated rectangle.
1831
922
 
1832
- ```ts
1833
- static fromCenterAndDimensions(center: Point2D, width: number, height: number): Rectangle2D
1834
- ```
923
+ #### `static fromDimensions(x: number, y: number, width: number, height: number): Rectangle2D` — Create an axis-aligned rectangle from origin corner plus width and height.
1835
924
 
1836
- #### `from2Corners()` — Create an axis-aligned rectangle from two opposite corners.
925
+ #### `static fromCenterAndDimensions(center: Point2D, width: number, height: number): Rectangle2D` — Create a rectangle centered on a point.
1837
926
 
1838
- ```ts
1839
- static from2Corners(p1: Point2D, p2: Point2D): Rectangle2D
1840
- ```
927
+ #### `static from2Corners(p1: Point2D, p2: Point2D): Rectangle2D` — Create an axis-aligned rectangle from two opposite corners.
1841
928
 
1842
- #### `from3Points()` — Create a free-angle rectangle from three points.
929
+ #### `static from3Points(p1: Point2D, p2: Point2D, p3: Point2D): Rectangle2D` — Create a free-angle rectangle from three points.
1843
930
 
1844
931
  `p1` and `p2` define one edge, and `p3` chooses the perpendicular side.
1845
932
 
1846
- ```ts
1847
- static from3Points(p1: Point2D, p2: Point2D, p3: Point2D): Rectangle2D
1848
- ```
1849
-
1850
- #### `extrude()` — Extrude the rectangle into a solid prism with named topology.
1851
-
1852
- ```ts
1853
- extrude(height: number, up?: boolean): Shape
1854
- ```
933
+ #### `extrude(height: number, up?: boolean): Shape` — Extrude the rectangle into a solid prism with named topology.