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.
- package/dist/assets/{AdminPage-CXvls4-J.js → AdminPage-DcCnj0qo.js} +1 -1
- package/dist/assets/{BenchmarkPage-B27zk8xL.js → BenchmarkPage-BVEpJSVk.js} +1 -1
- package/dist/assets/{BlogPage-CMAVvgQL.js → BlogPage-DHaGP50_.js} +1 -1
- package/dist/assets/{DocsPage-knf4I4h7.js → DocsPage-CDoxHkz8.js} +40 -859
- package/dist/assets/EditorApp-BJ0Dloyh.js +16446 -0
- package/dist/assets/{EmbedViewer-D7ZGlFjx.js → EmbedViewer-CRKZbY0y.js} +2 -2
- package/dist/assets/{LandingPageProofDriven-CnevhTE8.js → LandingPageProofDriven-BxHkYRE7.js} +1 -1
- package/dist/assets/{LegalPage-BPTUmqeg.js → LegalPage-B-u6FrVv.js} +1 -1
- package/dist/assets/{PricingPage-B0D4goG_.js → PricingPage-CzpZ6-Ce.js} +1 -1
- package/dist/assets/{SettingsPage-CFF-UgjI.js → SettingsPage-CIZSSAd0.js} +1 -1
- package/dist/assets/{app-CE3sYcV7.css → app-CjsbDlb7.css} +143 -0
- package/dist/assets/{app-T0pDcSX4.js → app-DaTMg3nH.js} +1310 -290
- package/dist/assets/cli/{render-C5pcIISc.js → render-DPf4AYJK.js} +55 -60
- package/dist/assets/{constructionHistoryWorker-Ba2Hm58b.js → constructionHistoryWorker-AwMMWSxg.js} +1103 -349
- package/dist/assets/{evalWorker-vkx310U2.js → evalWorker-CjZZWRWW.js} +5209 -2643
- package/dist/assets/{inspectWorker-BuTJDVX6.js → inspectWorker-CZsCFtQT.js} +1163 -409
- package/dist/assets/{jointPose-B_Cgedn9.js → jointPose-DzQOViQH.js} +1 -1
- package/dist/assets/{manifold-BWgsjmAM.js → manifold-BYlzU521.js} +1 -1
- package/dist/assets/{manifold-D6IFSkhH.js → manifold-DgXo0T5P.js} +2 -2
- package/dist/assets/{manifold-rZexZI0G.js → manifold-K1SkarlQ.js} +1 -1
- package/dist/assets/{reportWorker-0AGij1Ru.js → reportWorker-B9nWwSrB.js} +8501 -3393
- package/dist/assets/{scalar-sampling-budget-J5cuzxT1.js → scalar-sampling-budget-prBw_s8t.js} +6067 -3479
- package/dist/assets/{scanProxyWorker-Vl4Wxa1y.js → scanProxyWorker-2GtDLk-R.js} +1 -1
- package/dist/assets/{javascript-1kQXfVaz.js → typescript-DBQ6RN5l.js} +874 -22
- package/dist/cli/render.html +1 -1
- package/dist/docs/index.html +3 -3
- package/dist/docs-raw/AI/usage.md +1 -1
- package/dist/docs-raw/CLI.md +77 -240
- package/dist/docs-raw/README.md +6 -0
- package/dist/docs-raw/component-model.md +17 -150
- package/dist/docs-raw/generated/assembly.md +188 -582
- package/dist/docs-raw/generated/concepts.md +259 -3501
- package/dist/docs-raw/generated/core.md +283 -1250
- package/dist/docs-raw/generated/curves.md +387 -1608
- package/dist/docs-raw/generated/legacy.md +162 -0
- package/dist/docs-raw/generated/lib.md +227 -85
- package/dist/docs-raw/generated/output.md +35 -99
- package/dist/docs-raw/generated/runtime-names.md +23 -23
- package/dist/docs-raw/generated/sdf.md +68 -284
- package/dist/docs-raw/generated/sheet-metal.md +68 -335
- package/dist/docs-raw/generated/sketch.md +240 -1161
- package/dist/docs-raw/generated/viewport.md +75 -316
- package/dist/docs-raw/generated/wood.md +21 -49
- package/dist/docs-raw/guides/coordinate-system.md +4 -42
- package/dist/docs-raw/guides/inspection-bundles.md +44 -442
- package/dist/docs-raw/guides/joint-design.md +18 -79
- package/dist/docs-raw/guides/positioning.md +21 -143
- package/dist/docs-raw/guides/scene-presentation.md +89 -0
- package/dist/docs-raw/guides/simready-quickstart.md +171 -0
- package/dist/docs-raw/simulation-workflow.md +273 -0
- package/dist/docs-raw/skills/forgecad-3d-reconstruction.md +25 -111
- package/dist/docs-raw/skills/forgecad-blockout-model.md +20 -117
- package/dist/docs-raw/skills/forgecad-component-model.md +23 -107
- package/dist/docs-raw/skills/forgecad-high-level-spec.md +47 -155
- package/dist/docs-raw/skills/forgecad-image-replicator.md +26 -143
- package/dist/docs-raw/skills/forgecad-lld.md +19 -113
- package/dist/docs-raw/skills/forgecad-make-a-model.md +112 -532
- package/dist/docs-raw/skills/forgecad-model-grader.md +38 -108
- package/dist/docs-raw/skills/forgecad-prepare-prompt.md +24 -211
- package/dist/docs-raw/skills/forgecad-project.md +13 -131
- package/dist/docs-raw/skills/forgecad-reconstruction-benchmark.md +42 -134
- package/dist/docs-raw/skills/forgecad-render-inspect.md +27 -174
- package/dist/docs-raw/skills/forgecad-visual-spec.md +32 -112
- package/dist/docs-raw/skills/forgecad.md +19 -18
- package/dist/docs-raw/skills/index.md +2 -0
- package/dist/docs-raw/welcome.md +2 -2
- package/dist/index.html +2 -2
- package/dist/llms.txt +1 -2
- package/dist/sitemap.xml +25 -13
- package/dist-cli/{check-compiler-SYQ2PWOB.js → check-compiler-II7NLPAB.js} +1 -1
- package/dist-cli/{check-query-propagation-HIAGV62W.js → check-query-propagation-7462TR3R.js} +1 -1
- package/dist-cli/{chunk-SPZE3DUY.js → chunk-UWTJCGXF.js} +5848 -2915
- package/dist-cli/forgecad.js +3496 -703
- package/dist-skill/CONTEXT.md +1797 -7963
- package/dist-skill/SKILL.md +15 -15
- package/dist-skill/docs/API/core/concepts.md +27 -157
- package/dist-skill/docs/CLI.md +77 -240
- package/dist-skill/docs/generated/assembly.md +182 -532
- package/dist-skill/docs/generated/core.md +283 -1250
- package/dist-skill/docs/generated/curves.md +387 -1609
- package/dist-skill/docs/generated/lib.md +227 -85
- package/dist-skill/docs/generated/output.md +35 -99
- package/dist-skill/docs/generated/runtime-names.md +16 -21
- package/dist-skill/docs/generated/sdf.md +68 -284
- package/dist-skill/docs/generated/sheet-metal.md +68 -335
- package/dist-skill/docs/generated/sketch.md +240 -1160
- package/dist-skill/docs/generated/viewport.md +75 -223
- package/dist-skill/docs/generated/wood.md +21 -49
- package/dist-skill/docs/guides/coordinate-system.md +4 -42
- package/dist-skill/docs/guides/inspection-bundles.md +44 -442
- package/dist-skill/docs/guides/joint-design.md +18 -79
- package/dist-skill/docs/guides/positioning.md +21 -143
- package/dist-skill/docs/guides/scene-presentation.md +89 -0
- package/dist-skill/docs/guides/surface-members.md +26 -0
- package/dist-skill/library/forgecad-3d-reconstruction/SKILL.md +23 -111
- package/dist-skill/library/forgecad-blockout-model/SKILL.md +18 -117
- package/dist-skill/library/forgecad-component-model/SKILL.md +21 -107
- package/dist-skill/library/forgecad-high-level-spec/SKILL.md +45 -155
- package/dist-skill/library/forgecad-image-replicator/SKILL.md +24 -143
- package/dist-skill/library/forgecad-lld/SKILL.md +17 -113
- package/dist-skill/library/forgecad-make-a-model/SKILL.md +110 -532
- package/dist-skill/library/forgecad-model-grader/SKILL.md +36 -108
- package/dist-skill/library/forgecad-prepare-prompt/SKILL.md +35 -224
- package/dist-skill/library/forgecad-prepare-prompt/references/default-profiles.md +43 -271
- package/dist-skill/library/forgecad-prepare-prompt/references/master-prompt.md +30 -99
- package/dist-skill/library/forgecad-project/SKILL.md +13 -133
- package/dist-skill/library/forgecad-reconstruction-benchmark/SKILL.md +29 -123
- package/dist-skill/library/forgecad-render-inspect/SKILL.md +25 -174
- package/dist-skill/library/forgecad-visual-spec/SKILL.md +30 -111
- package/dist-skill/website/skills/forgecad-3d-reconstruction.md +58 -0
- package/dist-skill/website/skills/forgecad-blockout-model.md +49 -0
- package/dist-skill/website/skills/forgecad-component-model.md +53 -0
- package/dist-skill/website/skills/forgecad-high-level-spec.md +101 -0
- package/dist-skill/website/skills/forgecad-image-replicator.md +63 -0
- package/dist-skill/website/skills/forgecad-lld.md +41 -0
- package/dist-skill/website/skills/forgecad-make-a-model.md +186 -0
- package/dist-skill/website/skills/forgecad-model-grader.md +82 -0
- package/dist-skill/website/skills/forgecad-prepare-prompt.md +63 -0
- package/dist-skill/website/skills/forgecad-project.md +26 -0
- package/dist-skill/website/skills/forgecad-reconstruction-benchmark.md +60 -0
- package/dist-skill/website/skills/forgecad-render-inspect.md +80 -0
- package/dist-skill/website/skills/forgecad-visual-spec.md +71 -0
- package/dist-skill/website/skills/forgecad.md +122 -0
- package/dist-skill/website/skills/index.md +26 -0
- package/examples/api/comparison-imported-sphere-candidate.forge.js +1 -1
- package/examples/api/conformal-product-ribbon.forge.js +1 -1
- package/examples/api/exact-sheet-shell-assembly.forge.js +1 -1
- package/examples/api/extrude-options.forge.js +4 -2
- package/examples/api/field-loft-drive-tip.forge.js +40 -0
- package/examples/api/guided-loft-olive-oil-bottle.forge.js +1 -1
- package/examples/api/highlight-debug.forge.js +10 -10
- package/examples/api/mesh-import-slats.forge.js +1 -1
- package/examples/api/real-product-curves.forge.js +1 -1
- package/examples/api/sculpt-box-circle-booleans.forge.js +1 -1
- package/examples/api/sdf-shapes.forge.js +2 -5
- package/examples/api/sketch-rounding-strategies.forge.js +6 -6
- package/examples/api/surface-member-bottle-cage.forge.js +3 -3
- package/examples/api/surface-member-conformal-product-ribbon.forge.js +3 -3
- package/examples/api/surface-member-razor-inlay.forge.js +1 -1
- package/examples/api/variable-sweep-test.forge.js +3 -3
- package/examples/mechanical/airplane-propeller.forge.js +74 -39
- package/examples/nurbs-surface.forge.js +1 -1
- package/examples/products/iphone.forge.js +1 -1
- package/examples/robotics/README.md +46 -0
- package/examples/robotics/scout-cam-rover-simready/README.md +119 -0
- package/examples/robotics/scout-cam-rover-simready/lib/dims.js +140 -0
- package/examples/robotics/scout-cam-rover-simready/main.forge.js +343 -0
- package/examples/robotics/scout-cam-rover-simready/parts/body.forge.js +304 -0
- package/examples/robotics/scout-cam-rover-simready/parts/chassis.forge.js +320 -0
- package/examples/robotics/scout-cam-rover-simready/parts/hardware.forge.js +21 -0
- package/examples/robotics/scout-cam-rover-simready/parts/turret.forge.js +70 -0
- package/examples/robotics/scout-cam-rover-simready/parts/wheel.forge.js +116 -0
- package/examples/robotics/simready-asset-crate.forge.js +79 -0
- package/examples/robotics/simready-diff-drive-rover.forge.js +141 -0
- package/examples/robotics/simready-parallel-gripper.forge.js +102 -0
- package/package.json +1 -1
- package/dist/assets/EditorApp-BHMQlJ-D.js +0 -14686
- package/dist/docs-raw/guides/geometry-conventions.md +0 -52
- package/dist/docs-raw/guides/modeling-recipes.md +0 -78
- package/dist-skill/docs/guides/geometry-conventions.md +0 -52
- package/dist-skill/docs/guides/modeling-recipes.md +0 -78
- package/dist-skill/library/forgecad-visual-spec/references/prompt-template.md +0 -79
|
@@ -9,8 +9,8 @@ Smooth curves, lofted surfaces, swept solids, splines, and high-level product sk
|
|
|
9
9
|
|
|
10
10
|
## Contents
|
|
11
11
|
|
|
12
|
-
- [Curves & Surfacing](#curves-surfacing)
|
|
13
|
-
- [Surface Members](#surface-members)
|
|
12
|
+
- [Curves & Surfacing](#curves-surfacing)
|
|
13
|
+
- [Surface Members](#surface-members)
|
|
14
14
|
- [Curve3D](#curve3d)
|
|
15
15
|
- [Route3D](#route3d)
|
|
16
16
|
- [NurbsCurve3D](#nurbscurve3d)
|
|
@@ -23,9 +23,6 @@ Smooth curves, lofted surfaces, swept solids, splines, and high-level product sk
|
|
|
23
23
|
- [ProductStationBuilder](#productstationbuilder)
|
|
24
24
|
- [ProductPanelBuilder](#productpanelbuilder)
|
|
25
25
|
- [ProductRibbonBuilder](#productribbonbuilder)
|
|
26
|
-
- [ProductSpoutBuilder](#productspoutbuilder)
|
|
27
|
-
- [ProductHandleBuilder](#producthandlebuilder)
|
|
28
|
-
- [ProductHandleFeature](#producthandlefeature)
|
|
29
26
|
- [CylinderCarrier](#cylindercarrier)
|
|
30
27
|
- [PlaneCarrier](#planecarrier)
|
|
31
28
|
- [ProductSkinCarrier](#productskincarrier)
|
|
@@ -44,15 +41,12 @@ Smooth curves, lofted surfaces, swept solids, splines, and high-level product sk
|
|
|
44
41
|
- [Product](#product)
|
|
45
42
|
- [Carrier](#carrier)
|
|
46
43
|
- [SurfaceMembers](#surfacemembers)
|
|
47
|
-
- [Slot](#slot)
|
|
48
|
-
- [Counterbore](#counterbore)
|
|
49
|
-
- [Ribs](#ribs)
|
|
50
44
|
|
|
51
45
|
## Functions
|
|
52
46
|
|
|
53
47
|
### Curves & Surfacing
|
|
54
48
|
|
|
55
|
-
#### `Curve.Blend()` — Create an exact G1 blend curve between two directed endpoints.
|
|
49
|
+
#### `Curve.Blend(start: CurveBlendEndpoint, end: CurveBlendEndpoint): NurbsCurve3D` — Create an exact G1 blend curve between two directed endpoints.
|
|
56
50
|
|
|
57
51
|
The returned curve is a cubic non-rational `NurbsCurve3D`: ForgeCAD converts the endpoint positions and tangents into Bezier control points, so the curve can feed `sweep` and exact surface boundaries through the existing `nurbs` IR rather than a sampled polyline.
|
|
58
52
|
|
|
@@ -64,16 +58,12 @@ const rail = Curve.Blend(
|
|
|
64
58
|
const tube = sweep(circle2d(2), rail);
|
|
65
59
|
```
|
|
66
60
|
|
|
67
|
-
```ts
|
|
68
|
-
Curve.Blend(start: CurveBlendEndpoint, end: CurveBlendEndpoint): NurbsCurve3D
|
|
69
|
-
```
|
|
70
|
-
|
|
71
61
|
**`CurveBlendEndpoint`**
|
|
72
62
|
- `point: Vec3` — Endpoint position.
|
|
73
63
|
- `tangent: Vec3` — Tangent direction at this endpoint. Magnitude is ignored.
|
|
74
64
|
- `weight?: number` — Tangent reach relative to the endpoint chord length. Default 1.
|
|
75
65
|
|
|
76
|
-
#### `Curve.BlendG2()` — Create an exact G2 blend curve between two directed endpoints.
|
|
66
|
+
#### `Curve.BlendG2(start: CurveBlendG2Endpoint, end: CurveBlendG2Endpoint): NurbsCurve3D` — Create an exact G2 blend curve between two directed endpoints.
|
|
77
67
|
|
|
78
68
|
This is the curvature-aware companion to `Curve.Blend()`. It returns a degree-5 non-rational `NurbsCurve3D` that matches endpoint position, tangent direction, and optional curvature/second-derivative vectors.
|
|
79
69
|
|
|
@@ -84,15 +74,11 @@ const rail = Curve.BlendG2(
|
|
|
84
74
|
);
|
|
85
75
|
```
|
|
86
76
|
|
|
87
|
-
```ts
|
|
88
|
-
Curve.BlendG2(start: CurveBlendG2Endpoint, end: CurveBlendG2Endpoint): NurbsCurve3D
|
|
89
|
-
```
|
|
90
|
-
|
|
91
77
|
|
|
92
78
|
**`CurveBlendG2Endpoint`** extends CurveBlendEndpoint
|
|
93
79
|
- `curvature?: Vec3` — Optional endpoint curvature/second-derivative vector. Default is zero.
|
|
94
80
|
|
|
95
|
-
#### `Curve.Arc()` — Create an exact circular 3D arc from start, end, and start tangent.
|
|
81
|
+
#### `Curve.Arc(options: CurveArcOptions): NurbsCurve3D` — Create an exact circular 3D arc from start, end, and start tangent.
|
|
96
82
|
|
|
97
83
|
The returned curve is a rational quadratic `NurbsCurve3D`, split into stable spans when needed, so it can feed `sweep` without sampling the authoring intent away.
|
|
98
84
|
|
|
@@ -105,57 +91,25 @@ const rail = Curve.Arc({
|
|
|
105
91
|
const tube = sweep(circle2d(2), rail);
|
|
106
92
|
```
|
|
107
93
|
|
|
108
|
-
```ts
|
|
109
|
-
Curve.Arc(options: CurveArcOptions): NurbsCurve3D
|
|
110
|
-
```
|
|
111
|
-
|
|
112
94
|
**`CurveArcOptions`**
|
|
113
95
|
- `start: Vec3` — Arc start point.
|
|
114
96
|
- `end: Vec3` — Arc end point.
|
|
115
97
|
- `tangent: Vec3` — Tangent direction at the start point. Magnitude is ignored.
|
|
116
98
|
|
|
117
|
-
#### `Curve.Line()` — Create an exact straight 3D NURBS line segment.
|
|
99
|
+
#### `Curve.Line(start: Vec3, end: Vec3): NurbsCurve3D` — Create an exact straight 3D NURBS line segment.
|
|
118
100
|
|
|
119
101
|
```js
|
|
120
102
|
const rail = Curve.Line([0, 0, 0], [80, 0, 15]);
|
|
121
103
|
const rib = sweep(circle2d(2), rail);
|
|
122
104
|
```
|
|
123
105
|
|
|
124
|
-
|
|
125
|
-
Curve.Line(start: Vec3, end: Vec3): NurbsCurve3D
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
#### `Curve.Polyline()` — Create a polyline path as cloned 3D points.
|
|
129
|
-
|
|
130
|
-
Polylines are exact as route/path input to `sweep`. Use `Curve.Route` when the centerline needs bend and endpoint-frame metadata.
|
|
131
|
-
|
|
132
|
-
```ts
|
|
133
|
-
Curve.Polyline(points: Vec3[]): Vec3[]
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
#### `Curve.Spline()` — Create a smooth Catmull-Rom spline path.
|
|
137
|
-
|
|
138
|
-
This is a smooth sampled curve object. Use `Curve.Nurbs` when the path must preserve exact control-point and knot data.
|
|
139
|
-
|
|
140
|
-
```ts
|
|
141
|
-
Curve.Spline(points: Vec3[], options?: Spline3DOptions): Curve3D
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
**`Spline3DOptions`**
|
|
145
|
-
- `closed?: boolean` — Closed loop (default false).
|
|
146
|
-
- `tension?: number` — Catmull-Rom tension in [0, 1]. 0 = very round, 1 = linear-ish. Default 0.5.
|
|
147
|
-
|
|
148
|
-
#### `Curve.Nurbs()` — Create an exact NURBS 3D curve from control points, weights, knots, and degree.
|
|
106
|
+
#### `Curve.Nurbs(points: Vec3[], options?: NurbsCurve3DOptions): NurbsCurve3D` — Create an exact NURBS 3D curve from control points, weights, knots, and degree.
|
|
149
107
|
|
|
150
108
|
```js
|
|
151
109
|
const rail = Curve.Nurbs([[0, 0, 0], [30, 4, 12], [60, -4, 12], [90, 0, 0]]);
|
|
152
110
|
const tube = sweep(circle2d(2), rail);
|
|
153
111
|
```
|
|
154
112
|
|
|
155
|
-
```ts
|
|
156
|
-
Curve.Nurbs(points: Vec3[], options?: NurbsCurve3DOptions): NurbsCurve3D
|
|
157
|
-
```
|
|
158
|
-
|
|
159
113
|
**`NurbsCurve3DOptions`**
|
|
160
114
|
|
|
161
115
|
| Option | Type | Description |
|
|
@@ -165,9 +119,9 @@ Curve.Nurbs(points: Vec3[], options?: NurbsCurve3DOptions): NurbsCurve3D
|
|
|
165
119
|
| `knots?` | `number[]` | Knot vector (default: uniform clamped). Must have length = controlPoints.length + degree + 1. |
|
|
166
120
|
| `closed?` | `boolean` | Whether the curve is closed/periodic (default false). |
|
|
167
121
|
|
|
168
|
-
#### `Curve.Fit()` — Fit a non-rational NURBS curve that interpolates every input point.
|
|
122
|
+
#### `Curve.Fit(points: Vec3[], options?: CurveFitOptions): NurbsCurve3D` — Fit a non-rational NURBS curve that interpolates every input point.
|
|
169
123
|
|
|
170
|
-
This is global B-spline interpolation, not approximate curve reduction: ForgeCAD computes chord-length parameters, averaged clamped knots, solves the control points, then verifies the interpolation residual against `tolerance`.
|
|
124
|
+
This is global B-spline interpolation, not approximate curve reduction: ForgeCAD computes chord-length parameters, averaged clamped knots, solves the control points, then verifies the interpolation residual against `tolerance`. With `{ closed: true }` the fit is standard periodic B-spline interpolation: the curve loops smoothly from the last point back to the first (do not repeat the first point at the end).
|
|
171
125
|
|
|
172
126
|
```js
|
|
173
127
|
const rail = Curve.Fit(
|
|
@@ -175,33 +129,28 @@ const rail = Curve.Fit(
|
|
|
175
129
|
{ degree: 3, tolerance: 0.001 },
|
|
176
130
|
);
|
|
177
131
|
const tube = sweep(circle2d(2), rail);
|
|
178
|
-
```
|
|
179
132
|
|
|
180
|
-
|
|
181
|
-
Curve.Fit(
|
|
133
|
+
// Closed loop through four points — no duplicated closing point
|
|
134
|
+
const loop = Curve.Fit(
|
|
135
|
+
[[30, 0, 0], [0, 30, 0], [-30, 0, 0], [0, -30, 0]],
|
|
136
|
+
{ closed: true },
|
|
137
|
+
);
|
|
182
138
|
```
|
|
183
139
|
|
|
184
140
|
**`CurveFitOptions`**
|
|
185
141
|
- `degree?: number` — Polynomial degree. Default is cubic, reduced automatically for short point lists.
|
|
186
142
|
- `tolerance?: number` — Maximum allowed interpolation residual in model units. Default 1e-7.
|
|
143
|
+
- `closed?: boolean` — Interpolate a closed periodic loop through the points. The loop closes from the last point back to the first automatically — do not repeat the first point at the end.
|
|
187
144
|
|
|
188
|
-
#### `Curve.Trim()
|
|
145
|
+
#### `Curve.Trim<T extends CurveTrimInput>(curve: T, start: number, end: number): CurveTrimOutput<T>` — Extract an exact curve segment from normalized parameter `start` to `end`.
|
|
189
146
|
|
|
190
147
|
`NurbsCurve3D` inputs are trimmed with exact knot insertion/subdomain extraction. Polyline point arrays are trimmed by arclength over their exact line segments. Sampled `Curve3D` splines are rejected until ForgeCAD has a tolerance-controlled rebuild path.
|
|
191
148
|
|
|
192
|
-
|
|
193
|
-
Curve.Trim<T extends CurveTrimInput>(curve: T, start: number, end: number): CurveTrimOutput<T>
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
#### `Curve.Reverse()` — Reverse an exact curve without changing its geometry.
|
|
149
|
+
#### `Curve.Reverse<T extends CurveTrimInput>(curve: T): CurveTrimOutput<T>` — Reverse an exact curve without changing its geometry.
|
|
197
150
|
|
|
198
151
|
`NurbsCurve3D` inputs reverse control points, weights, and knots. Polyline point arrays are cloned and reversed. Sampled `Curve3D` splines are rejected until ForgeCAD has a tolerance-controlled rebuild path.
|
|
199
152
|
|
|
200
|
-
|
|
201
|
-
Curve.Reverse<T extends CurveTrimInput>(curve: T): CurveTrimOutput<T>
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
#### `Curve.Route()` — Build analytic 3D line/arc routes for sweeps.
|
|
153
|
+
#### `Curve.Route: typeof Route3D` — Build analytic 3D line/arc routes for sweeps.
|
|
205
154
|
|
|
206
155
|
`Curve.Route.fromPolyline()` is the canonical route API. It returns a `Route3D` value object, preserving exact route segments, named port frames, and the lowerable `route3d` sweep compile plan.
|
|
207
156
|
|
|
@@ -213,11 +162,7 @@ const route = Curve.Route.fromPolyline(
|
|
|
213
162
|
const tube = sweep(circle2d(4), route);
|
|
214
163
|
```
|
|
215
164
|
|
|
216
|
-
|
|
217
|
-
Curve.Route: typeof Route3D
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
#### `Curve.Helix()` — Build helical paths and swept coils.
|
|
165
|
+
#### `Curve.Helix: { path(options: HelixOptions): CurveHelixPath; coil: CurveHelixCoil; }` — Build helical paths and swept coils.
|
|
221
166
|
|
|
222
167
|
`Curve.Helix` is the canonical namespace for helical paths and coils. It uses the same sweep-based lowering as other curve paths.
|
|
223
168
|
|
|
@@ -226,10 +171,6 @@ const guide = Curve.Helix.path({ radius: 20, pitch: 6, turns: 4 });
|
|
|
226
171
|
const spring = Curve.Helix.coil({ radius: 20, pitch: 6, turns: 4, wireRadius: 1 });
|
|
227
172
|
```
|
|
228
173
|
|
|
229
|
-
```ts
|
|
230
|
-
Curve.Helix: { path(options: HelixOptions): CurveHelixPath; coil: CurveHelixCoil; }
|
|
231
|
-
```
|
|
232
|
-
|
|
233
174
|
**`HelixOptions`**
|
|
234
175
|
|
|
235
176
|
| Option | Type | Description |
|
|
@@ -245,95 +186,60 @@ Curve.Helix: { path(options: HelixOptions): CurveHelixPath; coil: CurveHelixCoil
|
|
|
245
186
|
|
|
246
187
|
`CurveHelixPath`: `{ radius: number, pitch: number, turns: number, height: number, startAngle: number, clockwise: boolean }`
|
|
247
188
|
|
|
248
|
-
#### `Loft.station()` — Create a loft station from a 2D profile and an axis position.
|
|
249
|
-
|
|
250
|
-
```ts
|
|
251
|
-
Loft.station(profile: Sketch, position: number): LoftStation
|
|
252
|
-
```
|
|
189
|
+
#### `Loft.station(profile: Sketch, position: number): LoftStation` — Create a loft station from a 2D profile and an axis position.
|
|
253
190
|
|
|
254
191
|
`LoftStation`: `{ profile: Sketch, position: number }`
|
|
255
192
|
|
|
256
|
-
#### `Loft.
|
|
193
|
+
#### `Loft.field(profiles: Sketch[], heights: number[], options?: FieldLoftOptions): Shape` — Loft by interpolating signed-distance fields instead of matching vertices.
|
|
257
194
|
|
|
258
|
-
|
|
259
|
-
Loft.leftRail(path: LoftGuideRailPath): LoftGuideRail
|
|
260
|
-
```
|
|
261
|
-
|
|
262
|
-
`LoftGuideRail`: `{ side: LoftGuideRailSide, path: LoftGuideRailPath }`
|
|
195
|
+
Use this path when profiles change character, such as round shafts blending into flat, cruciform, or lobed tips. It is Manifold-only, mesh-based, and slower than stitched lofting, but it avoids profile-point correspondence artifacts because it blends profile fields instead of boundary vertices.
|
|
263
196
|
|
|
264
|
-
|
|
197
|
+
**`LoftOptions`**
|
|
198
|
+
- `edgeLength?: number` — Marching-grid edge length for level-set meshing. Smaller = finer.
|
|
199
|
+
- `boundsPadding?: number` — Optional extra bounds padding.
|
|
265
200
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
201
|
+
**`FieldLoftOptions`** extends LoftOptions
|
|
202
|
+
- `simplify?: boolean | "safe"` — Simplification control after field extraction. Default is topology-safe simplification.
|
|
203
|
+
- `maxTriangles?: number` — Hard post-extraction triangle budget. Must be a positive integer. If safe simplification cannot reach it, the build fails.
|
|
269
204
|
|
|
270
|
-
#### `Loft.
|
|
205
|
+
#### `Loft.leftRail(path: LoftGuideRailPath): LoftGuideRail` — Create a guide rail that constrains the section-local negative-X side.
|
|
271
206
|
|
|
272
|
-
|
|
273
|
-
Loft.frontRail(path: LoftGuideRailPath): LoftGuideRail
|
|
274
|
-
```
|
|
207
|
+
`LoftGuideRail`: `{ side: LoftGuideRailSide, path: LoftGuideRailPath }`
|
|
275
208
|
|
|
276
|
-
#### `Loft.
|
|
209
|
+
#### `Loft.rightRail(path: LoftGuideRailPath): LoftGuideRail` — Create a guide rail that constrains the section-local positive-X side.
|
|
277
210
|
|
|
278
|
-
|
|
279
|
-
Loft.backRail(path: LoftGuideRailPath): LoftGuideRail
|
|
280
|
-
```
|
|
211
|
+
#### `Loft.frontRail(path: LoftGuideRailPath): LoftGuideRail` — Create a guide rail that constrains the section-local positive-Y side.
|
|
281
212
|
|
|
282
|
-
#### `Loft.
|
|
213
|
+
#### `Loft.backRail(path: LoftGuideRailPath): LoftGuideRail` — Create a guide rail that constrains the section-local negative-Y side.
|
|
283
214
|
|
|
284
|
-
|
|
285
|
-
Loft.centerRail(path: LoftGuideRailPath): LoftGuideRail
|
|
286
|
-
```
|
|
215
|
+
#### `Loft.centerRail(path: LoftGuideRailPath): LoftGuideRail` — Create a guide rail that moves section centers along the loft.
|
|
287
216
|
|
|
288
|
-
#### `Loft.pathOnXz()` — Place a 2D guide path onto the XZ plane.
|
|
217
|
+
#### `Loft.pathOnXz(path: LoftPath2D, y?: number): Vec3[]` — Place a 2D guide path onto the XZ plane.
|
|
289
218
|
|
|
290
219
|
The path's first coordinate becomes X and its second coordinate becomes Z. Use this for left/right silhouette rails authored with [`path()`](/docs/sketch#path) or [`constrainedSketch()`](/docs/sketch#constrainedsketch).
|
|
291
220
|
|
|
292
|
-
|
|
293
|
-
Loft.pathOnXz(path: LoftPath2D, y?: number): Vec3[]
|
|
294
|
-
```
|
|
295
|
-
|
|
296
|
-
#### `Loft.pathOnYz()` — Place a 2D guide path onto the YZ plane.
|
|
221
|
+
#### `Loft.pathOnYz(path: LoftPath2D, x?: number): Vec3[]` — Place a 2D guide path onto the YZ plane.
|
|
297
222
|
|
|
298
223
|
The path's first coordinate becomes Y and its second coordinate becomes Z. Use this for front/back crown rails authored with [`path()`](/docs/sketch#path) or [`constrainedSketch()`](/docs/sketch#constrainedsketch).
|
|
299
224
|
|
|
300
|
-
|
|
301
|
-
Loft.pathOnYz(path: LoftPath2D, x?: number): Vec3[]
|
|
302
|
-
```
|
|
303
|
-
|
|
304
|
-
#### `Loft.pathOnXy()` — Place a 2D guide path onto the XY plane.
|
|
225
|
+
#### `Loft.pathOnXy(path: LoftPath2D, z?: number): Vec3[]` — Place a 2D guide path onto the XY plane.
|
|
305
226
|
|
|
306
227
|
The path's first coordinate becomes X and its second coordinate becomes Y. Use this when lofting along X or Y and a rail lives in a horizontal sketch plane.
|
|
307
228
|
|
|
308
|
-
|
|
309
|
-
Loft.pathOnXy(path: LoftPath2D, z?: number): Vec3[]
|
|
310
|
-
```
|
|
311
|
-
|
|
312
|
-
#### `Loft.withGuideRails()` — Loft through profile stations while forcing generated sections to follow guide rails.
|
|
229
|
+
#### `Loft.withGuideRails(stations: LoftStation[], rails: LoftGuideRail[], options?: LoftWithGuideRailsOptions): Shape` — Loft through profile stations while forcing generated sections to follow guide rails.
|
|
313
230
|
|
|
314
231
|
Stations define the cross-section family. Guide rails define the side or center paths the loft must pass through. With opposite side rails, the section is scaled to touch both rails. With one side rail, the section keeps its interpolated size unless a center rail is also present.
|
|
315
232
|
|
|
316
|
-
```ts
|
|
317
|
-
Loft.withGuideRails(stations: LoftStation[], rails: LoftGuideRail[], options?: LoftWithGuideRailsOptions): Shape
|
|
318
|
-
```
|
|
319
|
-
|
|
320
|
-
**`LoftOptions`**
|
|
321
|
-
- `edgeLength?: number` — Marching-grid edge length for level-set meshing. Smaller = finer.
|
|
322
|
-
- `boundsPadding?: number` — Optional extra bounds padding.
|
|
323
233
|
|
|
324
234
|
**`LoftWithGuideRailsOptions`** extends LoftOptions
|
|
325
235
|
- `axis?: LoftAxis` — Primary station axis. Default Z.
|
|
326
236
|
- `samples?: number` — Number of generated loft stations including ends. Default scales with station count.
|
|
327
237
|
- `railSamples?: number` — Number of points sampled from curve-backed rails before axis interpolation. Default 64.
|
|
328
238
|
|
|
329
|
-
#### `spline2d()` — Build a smooth Catmull-Rom spline sketch from 2D control points.
|
|
239
|
+
#### `spline2d(points: Vec2[], options?: Spline2DOptions): Sketch` — Build a smooth Catmull-Rom spline sketch from 2D control points.
|
|
330
240
|
|
|
331
241
|
A closed spline (default) returns a filled profile. An open spline requires a strokeWidth option to produce a solid sketch. Use tension (0..1, default 0.5) to control curve tightness.
|
|
332
242
|
|
|
333
|
-
```ts
|
|
334
|
-
spline2d(points: Vec2[], options?: Spline2DOptions): Sketch
|
|
335
|
-
```
|
|
336
|
-
|
|
337
243
|
**`Spline2DOptions`**
|
|
338
244
|
|
|
339
245
|
| Option | Type | Description |
|
|
@@ -344,21 +250,15 @@ spline2d(points: Vec2[], options?: Spline2DOptions): Sketch
|
|
|
344
250
|
| `strokeWidth?` | `number` | For open splines, provide stroke width to return a solid Sketch. If omitted for open splines, an error is thrown. |
|
|
345
251
|
| `join?` | `"Round" \| "Square"` | Stroke join for open splines. Default 'Round'. |
|
|
346
252
|
|
|
347
|
-
#### `loft()` — Loft between multiple sketches along Z stations.
|
|
253
|
+
#### `loft(profiles: Sketch[], heights: number[], options?: LoftOptions): Shape` — Loft between multiple sketches along Z stations.
|
|
348
254
|
|
|
349
255
|
Profiles can differ in topology and vertex count: interpolation is done on signed-distance fields and meshed with level-set extraction. Heights must be strictly increasing. Compatible loft stacks can also stay on the maintained export-backend path.
|
|
350
256
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
```ts
|
|
354
|
-
loft(profiles: Sketch[], heights: number[], options?: LoftOptions): Shape
|
|
355
|
-
```
|
|
257
|
+
The surface is smooth through 3+ stations (C1 spanwise interpolation, like CAD lofts), so it can bow slightly past the straight ruling between stations; sections are matched exactly at their stations. Two-station lofts are ruled. `edgeLength` caps the sample spacing in curved or twisted regions (quality presets scale it); straight regions keep input density.
|
|
356
258
|
|
|
357
|
-
|
|
259
|
+
Performance note: loft is significantly heavier than primitive/extrude/revolve. If the part is axis-symmetric (bottles, vases, knobs), prefer revolve().
|
|
358
260
|
|
|
359
|
-
|
|
360
|
-
sweep(profile: Sketch, path: SweepPathInput, options?: SweepOptions): Shape
|
|
361
|
-
```
|
|
261
|
+
#### `sweep(profile: Sketch, path: SweepPathInput, options?: SweepOptions): Shape`
|
|
362
262
|
|
|
363
263
|
**`SweepOptions`**
|
|
364
264
|
|
|
@@ -369,7 +269,7 @@ sweep(profile: Sketch, path: SweepPathInput, options?: SweepOptions): Shape
|
|
|
369
269
|
| `boundsPadding?` | `number` | Optional extra bounds padding. |
|
|
370
270
|
| `up?` | `Vec3` | Preferred "up" vector for local profile frame. Auto fallback is used near parallel segments. |
|
|
371
271
|
|
|
372
|
-
#### `variableSweep()` — Sweep a variable cross-section along a 3D spine curve.
|
|
272
|
+
#### `variableSweep(spine: SweepPathInput, sections: VariableSweepSection[], options?: VariableSweepOptions): Shape` — Sweep a variable cross-section along a 3D spine curve.
|
|
373
273
|
|
|
374
274
|
Unlike sweep(), which uses a single constant profile, variableSweep() interpolates between multiple profiles at different stations along the spine. This enables organic shapes like tapering tubes, bone-like structures, and sculptural forms.
|
|
375
275
|
|
|
@@ -377,10 +277,6 @@ Each section specifies a t parameter (0 = start, 1 = end of spine) and a 2D prof
|
|
|
377
277
|
|
|
378
278
|
Performance note: like sweep(), this uses level-set meshing internally.
|
|
379
279
|
|
|
380
|
-
```ts
|
|
381
|
-
variableSweep(spine: SweepPathInput, sections: VariableSweepSection[], options?: VariableSweepOptions): Shape
|
|
382
|
-
```
|
|
383
|
-
|
|
384
280
|
**`VariableSweepSection`**
|
|
385
281
|
- `t: number` — Parameter along the spine (0 = start, 1 = end).
|
|
386
282
|
- `profile: Sketch` — Cross-section profile at this station.
|
|
@@ -394,98 +290,11 @@ variableSweep(spine: SweepPathInput, sections: VariableSweepSection[], options?:
|
|
|
394
290
|
| `boundsPadding?` | `number` | Optional extra bounds padding. |
|
|
395
291
|
| `up?` | `Vec3` | Preferred "up" vector for local profile frame. Auto fallback is used near parallel segments. |
|
|
396
292
|
|
|
397
|
-
#### `nurbsSurface()` — Create a NURBS surface from a grid of control points.
|
|
398
|
-
|
|
399
|
-
The control grid is indexed as `controlGrid[u][v]` — each row is a curve in the V direction, and columns trace curves in the U direction.
|
|
400
|
-
|
|
401
|
-
With default options, creates a bicubic non-rational B-spline surface with uniform clamped knots.
|
|
402
|
-
|
|
403
|
-
```js
|
|
404
|
-
// Simple 4×4 control grid — a gently curved surface
|
|
405
|
-
const grid = [
|
|
406
|
-
[[0,0,0], [10,0,2], [20,0,2], [30,0,0]],
|
|
407
|
-
[[0,10,1], [10,10,5], [20,10,5], [30,10,1]],
|
|
408
|
-
[[0,20,1], [10,20,5], [20,20,5], [30,20,1]],
|
|
409
|
-
[[0,30,0], [10,30,2], [20,30,2], [30,30,0]],
|
|
410
|
-
];
|
|
411
|
-
const surface = nurbsSurface(grid, { thickness: 2 });
|
|
412
|
-
```
|
|
413
|
-
|
|
414
|
-
```ts
|
|
415
|
-
nurbsSurface(controlGrid: Vec3[][], options?: NurbsSurfaceOptions): Shape
|
|
416
|
-
```
|
|
417
|
-
|
|
418
|
-
**`NurbsSurfaceOptions`**
|
|
419
|
-
|
|
420
|
-
| Option | Type | Description |
|
|
421
|
-
|--------|------|-------------|
|
|
422
|
-
| `degreeU?` | `number` | Degree in U direction (default 3). |
|
|
423
|
-
| `degreeV?` | `number` | Degree in V direction (default 3). |
|
|
424
|
-
| `weights?` | `number[][]` | Weights grid — same dimensions as controlGrid (default: all 1.0). |
|
|
425
|
-
| `knotsU?` | `number[]` | Knot vector in U direction (default: uniform clamped). |
|
|
426
|
-
| `knotsV?` | `number[]` | Knot vector in V direction (default: uniform clamped). |
|
|
427
|
-
| `thickness?` | `number` | Sheet thickness — if > 0, thickens the surface into a solid (default 0 = surface only). |
|
|
428
|
-
| `resolution?` | `number` | Tessellation resolution — points per direction (default 32). |
|
|
429
|
-
| `domain?` | `SurfaceDomainOptions` | Optional rectangular parameter domain in normalized [0, 1] U/V space. |
|
|
430
|
-
| `trim?` | `SurfaceTrimOptions` | Optional polygonal or NURBS-curve UV trim loops. Truck and OCCT support open trimmed surfaces; Manifold supports sampled thickened trimmed solids. |
|
|
431
|
-
| `tessellation?` | `SurfaceTessellationOptions` | Optional Truck kernel tessellation controls for render mesh generation. |
|
|
432
|
-
| `approximate?` | `boolean` | Explicit opt-in for sampled approximation paths on non-exact backends. |
|
|
433
|
-
|
|
434
|
-
**`SurfaceDomainOptions`**
|
|
435
|
-
|
|
436
|
-
| Option | Type | Description |
|
|
437
|
-
|--------|------|-------------|
|
|
438
|
-
| `uMin?` | `number` | Lower U parameter bound in normalized surface space (default 0). |
|
|
439
|
-
| `uMax?` | `number` | Upper U parameter bound in normalized surface space (default 1). |
|
|
440
|
-
| `vMin?` | `number` | Lower V parameter bound in normalized surface space (default 0). |
|
|
441
|
-
| `vMax?` | `number` | Upper V parameter bound in normalized surface space (default 1). |
|
|
442
|
-
|
|
443
|
-
**`SurfaceTrimOptions`**
|
|
444
|
-
- `outer: SurfaceTrimLoopInput` — Outer trim loop in normalized post-domain UV space.
|
|
445
|
-
- `holes?: SurfaceTrimLoopInput[]` — Optional hole loops in normalized post-domain UV space.
|
|
446
|
-
|
|
447
|
-
**`SurfaceTessellationOptions`**
|
|
448
|
-
|
|
449
|
-
| Option | Type | Description |
|
|
450
|
-
|--------|------|-------------|
|
|
451
|
-
| `mode?` | `"uniform" \| "adaptive"` | `uniform` uses resolution directly; `adaptive` lets the Truck kernel refine open sheets from chord error. |
|
|
452
|
-
| `tolerance?` | `number` | Target chord-error tolerance in model units for adaptive Truck tessellation. |
|
|
453
|
-
| `minResolution?` | `number` | Minimum adaptive samples per direction. |
|
|
454
|
-
| `maxResolution?` | `number` | Maximum adaptive samples per direction. Defaults to `resolution` when omitted. |
|
|
455
|
-
|
|
456
|
-
#### `surfacePatch()` — Create a smooth surface patch from 4 boundary curves (Coons patch).
|
|
457
|
-
|
|
458
|
-
The four curves form the boundary of a quadrilateral patch:
|
|
459
|
-
|
|
460
|
-
- bottom: u=0..1 at v=0 (from corner00 to corner10)
|
|
461
|
-
- top: u=0..1 at v=1 (from corner01 to corner11)
|
|
462
|
-
- left: v=0..1 at u=0 (from corner00 to corner01)
|
|
463
|
-
- right: v=0..1 at u=1 (from corner10 to corner11)
|
|
464
|
-
|
|
465
|
-
The interior is filled using bilinear Coons patch interpolation: P(u,v) = Lc(u,v) + Ld(u,v) - B(u,v)
|
|
466
|
-
|
|
467
|
-
The result is a thin solid created by offsetting the surface mesh along its normals by the specified thickness.
|
|
468
|
-
|
|
469
|
-
Note: curves should meet at corners. Small gaps are tolerated.
|
|
470
|
-
|
|
471
|
-
```ts
|
|
472
|
-
surfacePatch(curves: { ... }, options?: SurfacePatchOptions): Shape
|
|
473
|
-
```
|
|
474
|
-
|
|
475
|
-
**`SurfacePatchOptions`**
|
|
476
|
-
- `resolution?: number` — Number of samples along each direction. Default 24.
|
|
477
|
-
- `thickness?: number` — Thickness of the generated solid. Default 0 for an open exact sheet.
|
|
478
|
-
- `approximate?: boolean` — Allow explicit approximation for non-exact curve inputs such as Curve3D samples.
|
|
479
|
-
|
|
480
293
|
### Surface Members
|
|
481
294
|
|
|
482
|
-
#### `surfaceBand()
|
|
483
|
-
|
|
484
|
-
```ts
|
|
485
|
-
surfaceBand<C extends SurfaceCoordinate>(path: SurfacePath<C> | SurfacePathBuilder<C>, width: WidthProfile, cap?: SurfaceBandCap): SurfaceBand<C>
|
|
486
|
-
```
|
|
295
|
+
#### `surfaceBand<C extends SurfaceCoordinate>(path: SurfacePath<C> | SurfacePathBuilder<C>, width: WidthProfile, cap?: SurfaceBandCap): SurfaceBand<C>`
|
|
487
296
|
|
|
488
|
-
#### `SurfaceBody()` — Start a surface-member body builder for straps, inlays, guards, braces, cuffs, and similar physical members that live on a carrier surface.
|
|
297
|
+
#### `SurfaceBody(name: string): SurfaceBodyBuilder` — Start a surface-member body builder for straps, inlays, guards, braces, cuffs, and similar physical members that live on a carrier surface.
|
|
489
298
|
|
|
490
299
|
```js
|
|
491
300
|
const carrier = Carrier.cylinder('guard-envelope').diameter(84).height(36).clearance(2);
|
|
@@ -506,10 +315,6 @@ const guard = SurfaceBody('simple-guard')
|
|
|
506
315
|
.build();
|
|
507
316
|
```
|
|
508
317
|
|
|
509
|
-
```ts
|
|
510
|
-
SurfaceBody(name: string): SurfaceBodyBuilder
|
|
511
|
-
```
|
|
512
|
-
|
|
513
318
|
---
|
|
514
319
|
|
|
515
320
|
## Classes
|
|
@@ -526,35 +331,15 @@ SurfaceBody(name: string): SurfaceBodyBuilder
|
|
|
526
331
|
|
|
527
332
|
**Methods:**
|
|
528
333
|
|
|
529
|
-
#### `sampleBySegment()` — Sample the curve with a fixed number of points per segment.
|
|
530
|
-
|
|
531
|
-
```ts
|
|
532
|
-
sampleBySegment(samplesPerSegment?: number): Vec3[]
|
|
533
|
-
```
|
|
534
|
-
|
|
535
|
-
#### `sample()` — Sample the curve to an approximate total point count.
|
|
536
|
-
|
|
537
|
-
```ts
|
|
538
|
-
sample(count?: number): Vec3[]
|
|
539
|
-
```
|
|
540
|
-
|
|
541
|
-
#### `pointAt()` — Return the position on the curve at normalized parameter `t` in `[0, 1]`. O(1), no allocations.
|
|
542
|
-
|
|
543
|
-
```ts
|
|
544
|
-
pointAt(t: number): Vec3
|
|
545
|
-
```
|
|
334
|
+
#### `sampleBySegment(samplesPerSegment?: number): Vec3[]` — Sample the curve with a fixed number of points per segment.
|
|
546
335
|
|
|
547
|
-
#### `
|
|
336
|
+
#### `sample(count?: number): Vec3[]` — Sample the curve to an approximate total point count.
|
|
548
337
|
|
|
549
|
-
|
|
550
|
-
tangentAt(t: number): Vec3
|
|
551
|
-
```
|
|
338
|
+
#### `pointAt(t: number): Vec3` — Return the position on the curve at normalized parameter `t` in `[0, 1]`. O(1), no allocations.
|
|
552
339
|
|
|
553
|
-
#### `
|
|
340
|
+
#### `tangentAt(t: number): Vec3` — Return a unit tangent vector at normalized parameter `t` in `[0, 1]`. O(1), analytical derivative.
|
|
554
341
|
|
|
555
|
-
|
|
556
|
-
length(samples?: number): number
|
|
557
|
-
```
|
|
342
|
+
#### `length(samples?: number): number` — Approximate the curve length by polyline sampling.
|
|
558
343
|
|
|
559
344
|
### `Route3D`
|
|
560
345
|
|
|
@@ -571,11 +356,7 @@ const pipe = sweep(difference2d(circle2d(8), circle2d(6)), route);
|
|
|
571
356
|
const outlet = route.port("outlet");
|
|
572
357
|
```
|
|
573
358
|
|
|
574
|
-
#### `fromPolyline()` — Build a line/arc route from virtual polyline corner points.
|
|
575
|
-
|
|
576
|
-
```ts
|
|
577
|
-
static fromPolyline(points: Route3DVec3[], options?: Route3DFromPolylineOptions): Route3D
|
|
578
|
-
```
|
|
359
|
+
#### `static fromPolyline(points: Route3DVec3[], options?: Route3DFromPolylineOptions): Route3D` — Build a line/arc route from virtual polyline corner points.
|
|
579
360
|
|
|
580
361
|
**`Route3DFromPolylineOptions`**
|
|
581
362
|
|
|
@@ -586,41 +367,17 @@ static fromPolyline(points: Route3DVec3[], options?: Route3DFromPolylineOptions)
|
|
|
586
367
|
| `endPort?` | `string` | Name for the end port. Default "end". |
|
|
587
368
|
| `up?` | `Vec3` | Preferred up vector for deterministic port frames. Default [0, 0, 1]. |
|
|
588
369
|
|
|
589
|
-
#### `length()` — Total centerline length, including line and bend arc segments.
|
|
590
|
-
|
|
591
|
-
```ts
|
|
592
|
-
get length(): number
|
|
593
|
-
```
|
|
594
|
-
|
|
595
|
-
#### `segments()` — Exact line and arc segments that make up this route.
|
|
596
|
-
|
|
597
|
-
```ts
|
|
598
|
-
get segments(): Route3DSegment[]
|
|
599
|
-
```
|
|
600
|
-
|
|
601
|
-
#### `ports()` — Named port frames, keyed by port name.
|
|
602
|
-
|
|
603
|
-
```ts
|
|
604
|
-
get ports(): Record<string, RoutePortFrame>
|
|
605
|
-
```
|
|
370
|
+
#### `get length(): number` — Total centerline length, including line and bend arc segments.
|
|
606
371
|
|
|
607
|
-
#### `
|
|
608
|
-
|
|
609
|
-
```ts
|
|
610
|
-
port(name: string): RoutePortFrame
|
|
611
|
-
```
|
|
372
|
+
#### `get segments(): Route3DSegment[]` — Exact line and arc segments that make up this route.
|
|
612
373
|
|
|
613
|
-
#### `
|
|
374
|
+
#### `get ports(): Record<string, RoutePortFrame>` — Named port frames, keyed by port name.
|
|
614
375
|
|
|
615
|
-
|
|
616
|
-
toSweepPathPlan(): SweepPathCompilePlan
|
|
617
|
-
```
|
|
376
|
+
#### `port(name: string): RoutePortFrame` — Return one named route port frame.
|
|
618
377
|
|
|
619
|
-
#### `
|
|
378
|
+
#### `toSweepPathPlan(): SweepPathCompilePlan` — Convert this route to the compile plan consumed by sweep().
|
|
620
379
|
|
|
621
|
-
|
|
622
|
-
toPolyline(options?: number | Route3DToPolylineOptions): Route3DVec3[]
|
|
623
|
-
```
|
|
380
|
+
#### `toPolyline(options?: number | Route3DToPolylineOptions): Route3DVec3[]` — Sample this analytic route as a polyline for inspection or backend lowering.
|
|
624
381
|
|
|
625
382
|
**`Route3DToPolylineOptions`**
|
|
626
383
|
- `samples?: number` — Approximate target point count for the full route.
|
|
@@ -640,41 +397,17 @@ toPolyline(options?: number | Route3DToPolylineOptions): Route3DVec3[]
|
|
|
640
397
|
|
|
641
398
|
**Methods:**
|
|
642
399
|
|
|
643
|
-
#### `pointAt()` — Evaluate the curve at parameter t ∈ [0, 1]. Uses De Boor's algorithm — exact, O(degree²).
|
|
644
|
-
|
|
645
|
-
```ts
|
|
646
|
-
pointAt(t: number): Vec3
|
|
647
|
-
```
|
|
648
|
-
|
|
649
|
-
#### `tangentAt()` — Evaluate the unit tangent vector at parameter t ∈ [0, 1].
|
|
650
|
-
|
|
651
|
-
```ts
|
|
652
|
-
tangentAt(t: number): Vec3
|
|
653
|
-
```
|
|
654
|
-
|
|
655
|
-
#### `sample()` — Sample the curve uniformly at `count` points.
|
|
656
|
-
|
|
657
|
-
```ts
|
|
658
|
-
sample(count?: number): Vec3[]
|
|
659
|
-
```
|
|
660
|
-
|
|
661
|
-
#### `sampleAdaptive()` — Sample with adaptive density — more points in high-curvature regions.
|
|
400
|
+
#### `pointAt(t: number): Vec3` — Evaluate the curve at parameter t ∈ [0, 1]. Uses De Boor's algorithm — exact, O(degree²).
|
|
662
401
|
|
|
663
|
-
|
|
664
|
-
sampleAdaptive(minCount?: number, maxCount?: number): Vec3[]
|
|
665
|
-
```
|
|
402
|
+
#### `tangentAt(t: number): Vec3` — Evaluate the unit tangent vector at parameter t ∈ [0, 1].
|
|
666
403
|
|
|
667
|
-
#### `
|
|
404
|
+
#### `sample(count?: number): Vec3[]` — Sample the curve uniformly at `count` points.
|
|
668
405
|
|
|
669
|
-
|
|
670
|
-
length(samples?: number): number
|
|
671
|
-
```
|
|
406
|
+
#### `sampleAdaptive(minCount?: number, maxCount?: number): Vec3[]` — Sample with adaptive density — more points in high-curvature regions.
|
|
672
407
|
|
|
673
|
-
#### `
|
|
408
|
+
#### `length(samples?: number): number` — Approximate arc length by summing polyline segment lengths.
|
|
674
409
|
|
|
675
|
-
|
|
676
|
-
toPolyline(samples?: number): Vec3[]
|
|
677
|
-
```
|
|
410
|
+
#### `toPolyline(samples?: number): Vec3[]` — Convert to a format compatible with sweep() path input.
|
|
678
411
|
|
|
679
412
|
### `NurbsSurface`
|
|
680
413
|
|
|
@@ -694,59 +427,31 @@ toPolyline(samples?: number): Vec3[]
|
|
|
694
427
|
|
|
695
428
|
**Methods:**
|
|
696
429
|
|
|
697
|
-
#### `pointAt()` — Evaluate the surface at parameters (u, v) ∈ [0, 1]². Uses tensor product evaluation: evaluate basis functions in U and V independently.
|
|
698
|
-
|
|
699
|
-
```ts
|
|
700
|
-
pointAt(u: number, v: number): Vec3
|
|
701
|
-
```
|
|
702
|
-
|
|
703
|
-
#### `normalAt()` — Evaluate the surface normal at (u, v) via cross product of partial derivatives.
|
|
704
|
-
|
|
705
|
-
```ts
|
|
706
|
-
normalAt(u: number, v: number): Vec3
|
|
707
|
-
```
|
|
430
|
+
#### `pointAt(u: number, v: number): Vec3` — Evaluate the surface at parameters (u, v) ∈ [0, 1]². Uses tensor product evaluation: evaluate basis functions in U and V independently.
|
|
708
431
|
|
|
709
|
-
#### `
|
|
432
|
+
#### `normalAt(u: number, v: number): Vec3` — Evaluate the surface normal at (u, v) via cross product of partial derivatives.
|
|
710
433
|
|
|
711
|
-
|
|
712
|
-
tessellate(resU?: number, resV?: number): { positions: Vec3[]; normals: Vec3[]; indices: number[]; }
|
|
713
|
-
```
|
|
434
|
+
#### `tessellate(resU?: number, resV?: number): { positions: Vec3[]; normals: Vec3[]; indices: number[]; }` — Tessellate the surface into a triangle mesh. Returns positions, normals, and triangle indices.
|
|
714
435
|
|
|
715
436
|
### `PathBuilder`
|
|
716
437
|
|
|
717
438
|
**Line Segments**
|
|
718
439
|
|
|
719
|
-
#### `moveTo()` — Move the cursor to an absolute position without drawing a segment.
|
|
440
|
+
#### `moveTo(x: number, y: number): this` — Move the cursor to an absolute position without drawing a segment.
|
|
720
441
|
|
|
721
442
|
When called after the initial [`path()`](/docs/sketch#path), this establishes the start of the outline. Calling `moveTo` again mid-path starts a new sub-path (hole in `close()`, separate segment for [`stroke()`](/docs/sketch#stroke)).
|
|
722
443
|
|
|
723
|
-
|
|
724
|
-
moveTo(x: number, y: number): this
|
|
725
|
-
```
|
|
726
|
-
|
|
727
|
-
#### `lineTo()` — Draw a straight line from the current cursor to an absolute position.
|
|
728
|
-
|
|
729
|
-
```ts
|
|
730
|
-
lineTo(x: number, y: number): this
|
|
731
|
-
```
|
|
444
|
+
#### `lineTo(x: number, y: number): this` — Draw a straight line from the current cursor to an absolute position.
|
|
732
445
|
|
|
733
|
-
#### `lineH()` — Draw a horizontal line segment by `dx` units from the current cursor.
|
|
446
|
+
#### `lineH(dx: number): this` — Draw a horizontal line segment by `dx` units from the current cursor.
|
|
734
447
|
|
|
735
448
|
Positive `dx` moves right; negative moves left.
|
|
736
449
|
|
|
737
|
-
|
|
738
|
-
lineH(dx: number): this
|
|
739
|
-
```
|
|
740
|
-
|
|
741
|
-
#### `lineV()` — Draw a vertical line segment by `dy` units from the current cursor.
|
|
450
|
+
#### `lineV(dy: number): this` — Draw a vertical line segment by `dy` units from the current cursor.
|
|
742
451
|
|
|
743
452
|
Positive `dy` moves up; negative moves down.
|
|
744
453
|
|
|
745
|
-
|
|
746
|
-
lineV(dy: number): this
|
|
747
|
-
```
|
|
748
|
-
|
|
749
|
-
#### `lineAngled()` — Draw a line at the given angle and length from the current cursor.
|
|
454
|
+
#### `lineAngled(length: number, degrees: number): this` — Draw a line at the given angle and length from the current cursor.
|
|
750
455
|
|
|
751
456
|
Angle convention: `0°` points right (+X), `90°` points up (+Y).
|
|
752
457
|
|
|
@@ -755,46 +460,26 @@ Angle convention: `0°` points right (+X), `90°` points up (+Y).
|
|
|
755
460
|
path().moveTo(0, 0).lineH(50).lineV(-70).lineAngled(20, 235).stroke(4);
|
|
756
461
|
```
|
|
757
462
|
|
|
758
|
-
```ts
|
|
759
|
-
lineAngled(length: number, degrees: number): this
|
|
760
|
-
```
|
|
761
|
-
|
|
762
463
|
**Arcs**
|
|
763
464
|
|
|
764
|
-
#### `arc()` — Draw an arc defined by center, radius, and angle range (no trig needed). If the path has no segments yet, automatically moves to the arc start. Positive sweep (startDeg < endDeg) = CCW, negative = CW.
|
|
465
|
+
#### `arc(cx: number, cy: number, radius: number, startDeg: number, endDeg: number): this` — Draw an arc defined by center, radius, and angle range (no trig needed). If the path has no segments yet, automatically moves to the arc start. Positive sweep (startDeg < endDeg) = CCW, negative = CW.
|
|
765
466
|
|
|
766
467
|
```js
|
|
767
468
|
// Arc centered at (10, 0), radius 50, from -30° to +30°
|
|
768
469
|
path().arc(10, 0, 50, -30, 30).stroke(8, 'Round')
|
|
769
470
|
```
|
|
770
471
|
|
|
771
|
-
|
|
772
|
-
arc(cx: number, cy: number, radius: number, startDeg: number, endDeg: number): this
|
|
773
|
-
```
|
|
774
|
-
|
|
775
|
-
#### `arcTo()` — Draw a circular arc from the current position to (x, y) with the given radius. `clockwise=true` → arc curves to the right of the start→end direction. `clockwise=false` → arc curves to the left of the start→end direction.
|
|
776
|
-
|
|
777
|
-
```ts
|
|
778
|
-
arcTo(x: number, y: number, radius: number, clockwise?: boolean): this
|
|
779
|
-
```
|
|
780
|
-
|
|
781
|
-
#### `tangentArcTo()` — G1-continuous arc — radius derived from current tangent + endpoint. Throws if endpoint is collinear with current direction.
|
|
472
|
+
#### `arcTo(x: number, y: number, radius: number, clockwise?: boolean): this` — Draw a circular arc from the current position to (x, y) with the given radius. `clockwise=true` → arc curves to the right of the start→end direction. `clockwise=false` → arc curves to the left of the start→end direction.
|
|
782
473
|
|
|
783
|
-
|
|
784
|
-
tangentArcTo(x: number, y: number): this
|
|
785
|
-
```
|
|
474
|
+
#### `tangentArcTo(x: number, y: number): this` — G1-continuous arc — radius derived from current tangent + endpoint. Throws if endpoint is collinear with current direction.
|
|
786
475
|
|
|
787
476
|
**Curves**
|
|
788
477
|
|
|
789
|
-
#### `bezierTo()` — Cubic bezier from current position to (x, y) via two control points.
|
|
790
|
-
|
|
791
|
-
```ts
|
|
792
|
-
bezierTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number): this
|
|
793
|
-
```
|
|
478
|
+
#### `bezierTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number): this` — Cubic bezier from current position to (x, y) via two control points.
|
|
794
479
|
|
|
795
480
|
**Closing & Output**
|
|
796
481
|
|
|
797
|
-
#### `close()` — Close the path and return a filled [`Sketch`](/docs/sketch#sketch).
|
|
482
|
+
#### `close(): Sketch` — Close the path and return a filled [`Sketch`](/docs/sketch#sketch).
|
|
798
483
|
|
|
799
484
|
The winding of the polygon is automatically corrected to CCW (the expected orientation for ForgeCAD sketches). If the path contains multiple sub-paths (started with subsequent `moveTo` calls), the first sub-path is the outer contour and subsequent sub-paths become holes subtracted from it.
|
|
800
485
|
|
|
@@ -809,21 +494,13 @@ const frame = path()
|
|
|
809
494
|
// (hole would be added with another moveTo and line sequence before close)
|
|
810
495
|
```
|
|
811
496
|
|
|
812
|
-
|
|
813
|
-
close(): Sketch
|
|
814
|
-
```
|
|
815
|
-
|
|
816
|
-
#### `closeLabel()` — Label the closing segment and close the path. Shorthand for labeling the implicit line from the last point back to the start, then closing.
|
|
817
|
-
|
|
818
|
-
```ts
|
|
819
|
-
closeLabel(name: string): Sketch
|
|
820
|
-
```
|
|
497
|
+
#### `closeLabel(name: string): Sketch` — Label the closing segment and close the path. Shorthand for labeling the implicit line from the last point back to the start, then closing.
|
|
821
498
|
|
|
822
|
-
####
|
|
499
|
+
#### `stroke(width: number, join?: "Round" | "Square"): Sketch` — Thicken an open polyline (centerline) into a solid filled profile with uniform width.
|
|
823
500
|
|
|
824
501
|
Expands the path into a closed profile `width` units wide (half-width on each side of the centerline). Use `'Round'` for ribs, wire traces, and organic profiles — it adds semicircular endcaps and rounds joins. Use `'Square'` (default) for sharp miter joins without endcaps.
|
|
825
502
|
|
|
826
|
-
Not the same as rounding corners of a closed polygon — for mixed sharp-and-rounded outlines, build the polygon first and apply [
|
|
503
|
+
Not the same as rounding corners of a closed polygon — for mixed sharp-and-rounded outlines, build the polygon first and apply `.filletCorner([x, y], radius)` per corner.
|
|
827
504
|
|
|
828
505
|
```ts
|
|
829
506
|
// Square-join L-bracket
|
|
@@ -838,51 +515,23 @@ const wire = stroke([[0, 0], [50, 0], [50, -70]], 4);
|
|
|
838
515
|
|
|
839
516
|
and semicircular endcaps.
|
|
840
517
|
|
|
841
|
-
|
|
842
|
-
stroke(width: number, join?: "Round" | "Square"): Sketch
|
|
843
|
-
```
|
|
844
|
-
|
|
845
|
-
#### `label()` — Label the most recently added segment. Labels are born here and grow into face names when the sketch is extruded, lofted, swept, or revolved.
|
|
518
|
+
#### `label(name: string): this` — Label the most recently added segment. Labels are born here and grow into face names when the sketch is extruded, lofted, swept, or revolved.
|
|
846
519
|
|
|
847
520
|
Labels must be unique within a path. Each segment can have at most one label.
|
|
848
521
|
|
|
849
|
-
```ts
|
|
850
|
-
label(name: string): this
|
|
851
|
-
```
|
|
852
|
-
|
|
853
522
|
**Other**
|
|
854
523
|
|
|
855
|
-
#### `getX()` — Current cursor X position.
|
|
856
|
-
|
|
857
|
-
```ts
|
|
858
|
-
getX(): number
|
|
859
|
-
```
|
|
860
|
-
|
|
861
|
-
#### `getY()` — Current cursor Y position.
|
|
862
|
-
|
|
863
|
-
```ts
|
|
864
|
-
getY(): number
|
|
865
|
-
```
|
|
866
|
-
|
|
867
|
-
#### `lineBy()` — Draw a line by a relative `(dx, dy)` displacement from the current cursor.
|
|
868
|
-
|
|
869
|
-
```ts
|
|
870
|
-
lineBy(dx: number, dy: number): this
|
|
871
|
-
```
|
|
524
|
+
#### `getX(): number` — Current cursor X position.
|
|
872
525
|
|
|
873
|
-
#### `
|
|
526
|
+
#### `getY(): number` — Current cursor Y position.
|
|
874
527
|
|
|
875
|
-
|
|
876
|
-
arcBy(dx: number, dy: number, radius: number, clockwise?: boolean): this
|
|
877
|
-
```
|
|
528
|
+
#### `lineBy(dx: number, dy: number): this` — Draw a line by a relative `(dx, dy)` displacement from the current cursor.
|
|
878
529
|
|
|
879
|
-
#### `
|
|
530
|
+
#### `arcBy(dx: number, dy: number, radius: number, clockwise?: boolean): this` — Draw an arc to a point offset from the current cursor.
|
|
880
531
|
|
|
881
|
-
|
|
882
|
-
bezierBy(dcp1x: number, dcp1y: number, dcp2x: number, dcp2y: number, dx: number, dy: number): this
|
|
883
|
-
```
|
|
532
|
+
#### `bezierBy(dcp1x: number, dcp1y: number, dcp2x: number, dcp2y: number, dx: number, dy: number): this` — Draw a cubic Bezier using control points relative to the current cursor.
|
|
884
533
|
|
|
885
|
-
#### `arcAround()` — Arc around a known center point, sweeping by the given angle. Radius is derived from the distance between the current position and the center. Positive sweep = CCW (math convention), negative = CW.
|
|
534
|
+
#### `arcAround(cx: number, cy: number, sweepDeg: number): this` — Arc around a known center point, sweeping by the given angle. Radius is derived from the distance between the current position and the center. Positive sweep = CCW (math convention), negative = CW.
|
|
886
535
|
|
|
887
536
|
```js
|
|
888
537
|
// Arc 90° CCW around (50, 50)
|
|
@@ -891,11 +540,7 @@ path().moveTo(70, 50).arcAround(50, 50, 90)
|
|
|
891
540
|
path().moveTo(10, 0).arcAround(0, 0, -45)
|
|
892
541
|
```
|
|
893
542
|
|
|
894
|
-
|
|
895
|
-
arcAround(cx: number, cy: number, sweepDeg: number): this
|
|
896
|
-
```
|
|
897
|
-
|
|
898
|
-
#### `arcAroundRelative()` — Arc around a center point given as an offset from the current position. `(dx, dy)` is the vector from the current point to the center. Positive sweep = CCW (math convention), negative = CW.
|
|
543
|
+
#### `arcAroundRelative(dx: number, dy: number, sweepDeg: number): this` — Arc around a center point given as an offset from the current position. `(dx, dy)` is the vector from the current point to the center. Positive sweep = CCW (math convention), negative = CW.
|
|
899
544
|
|
|
900
545
|
```js
|
|
901
546
|
// Arc 90° CCW around a center 20 units to the right
|
|
@@ -903,47 +548,23 @@ path().moveTo(50, 50).arcAroundRelative(20, 0, 90)
|
|
|
903
548
|
// Equivalent to: path().moveTo(50, 50).arcAround(70, 50, 90)
|
|
904
549
|
```
|
|
905
550
|
|
|
906
|
-
|
|
907
|
-
arcAroundRelative(dx: number, dy: number, sweepDeg: number): this
|
|
908
|
-
```
|
|
909
|
-
|
|
910
|
-
#### `smoothCapTo()` — Smooth three-arc end cap from the current position to (endX, endY). Inserts: small corner arc → large cap arc → small corner arc, all G1-continuous.
|
|
551
|
+
#### `smoothCapTo(endX: number, endY: number, cornerRadius: number, capRadius: number): this` — Smooth three-arc end cap from the current position to (endX, endY). Inserts: small corner arc → large cap arc → small corner arc, all G1-continuous.
|
|
911
552
|
|
|
912
|
-
|
|
913
|
-
smoothCapTo(endX: number, endY: number, cornerRadius: number, capRadius: number): this
|
|
914
|
-
```
|
|
915
|
-
|
|
916
|
-
#### `tangentBezierTo()` — G1-continuous cubic bezier — first control point is auto-derived from the current tangent direction. `weight` controls how far the auto-placed control point extends along the tangent (default: 1/3 of the chord).
|
|
553
|
+
#### `tangentBezierTo(cp2x: number, cp2y: number, x: number, y: number, weight?: number): this` — G1-continuous cubic bezier — first control point is auto-derived from the current tangent direction. `weight` controls how far the auto-placed control point extends along the tangent (default: 1/3 of the chord).
|
|
917
554
|
|
|
918
555
|
The second control point `(cp2x, cp2y)` must be provided — it controls the arrival curvature. For a fully automatic smooth curve, see `smoothThrough`.
|
|
919
556
|
|
|
920
|
-
|
|
921
|
-
tangentBezierTo(cp2x: number, cp2y: number, x: number, y: number, weight?: number): this
|
|
922
|
-
```
|
|
557
|
+
#### `smoothThrough(waypoints: Vec2[], tension?: number): this` — Catmull-Rom spline through a list of waypoints from the current position. The current position is included as the first point. The last waypoint becomes the new cursor position.
|
|
923
558
|
|
|
924
|
-
#### `
|
|
559
|
+
#### `nurbsTo(controlPoints: Vec2[], opts?: { weights?: number[]; degree?: number; }): this` — Rational B-spline edge to (x, y) with explicit control points and weights.
|
|
925
560
|
|
|
926
|
-
|
|
927
|
-
smoothThrough(waypoints: [ number, number ][], tension?: number): this
|
|
928
|
-
```
|
|
561
|
+
The control points define the B-spline shape between the current position and (x, y). The current position is NOT included in `controlPoints` — it is automatically prepended. The endpoint (x, y) is the last control point.
|
|
929
562
|
|
|
930
|
-
#### `
|
|
931
|
-
|
|
932
|
-
The control points define the B-spline shape between the current position and (x, y). The current position is NOT included in `controlPoints` — it is automatically prepended. The endpoint (x, y) is the last control point.
|
|
933
|
-
|
|
934
|
-
```ts
|
|
935
|
-
nurbsTo(controlPoints: [ number, number ][], opts?: { weights?: number[]; degree?: number; }): this
|
|
936
|
-
```
|
|
937
|
-
|
|
938
|
-
#### `exactArcTo()` — Exact circular arc to (x, y) using a rational quadratic NURBS.
|
|
563
|
+
#### `exactArcTo(x: number, y: number, opts?: { radius?: number; clockwise?: boolean; }): this` — Exact circular arc to (x, y) using a rational quadratic NURBS.
|
|
939
564
|
|
|
940
565
|
Unlike `arcTo()` which tessellates to a polyline, this preserves the exact arc definition. When extruded through the OCCT backend, it produces a true cylindrical face — not a faceted approximation.
|
|
941
566
|
|
|
942
|
-
|
|
943
|
-
exactArcTo(x: number, y: number, opts?: { radius?: number; clockwise?: boolean; }): this
|
|
944
|
-
```
|
|
945
|
-
|
|
946
|
-
#### [`fillet()`](/docs/core#fillet) — Round the last corner (the junction between the previous two segments) with a tangent arc of the given radius.
|
|
567
|
+
#### `fillet(radius: number): this` — Round the last corner (the junction between the previous two segments) with a tangent arc of the given radius.
|
|
947
568
|
|
|
948
569
|
Must be called after at least two line/arc segments that form a corner. The fillet trims back both segments and inserts a tangent arc.
|
|
949
570
|
|
|
@@ -951,21 +572,13 @@ Must be called after at least two line/arc segments that form a corner. The fill
|
|
|
951
572
|
path().moveTo(0,0).lineTo(10,0).lineTo(10,10).fillet(2).lineTo(0,10).close()
|
|
952
573
|
```
|
|
953
574
|
|
|
954
|
-
|
|
955
|
-
fillet(radius: number): this
|
|
956
|
-
```
|
|
957
|
-
|
|
958
|
-
#### [`chamfer()`](/docs/core#chamfer) — Chamfer the last corner with a straight cut of the given distance.
|
|
575
|
+
#### `chamfer(distance: number): this` — Chamfer the last corner with a straight cut of the given distance.
|
|
959
576
|
|
|
960
577
|
```js
|
|
961
578
|
path().moveTo(0,0).lineTo(10,0).lineTo(10,10).chamfer(2).lineTo(0,10).close()
|
|
962
579
|
```
|
|
963
580
|
|
|
964
|
-
|
|
965
|
-
chamfer(distance: number): this
|
|
966
|
-
```
|
|
967
|
-
|
|
968
|
-
#### `mirror()` — Mirror all existing segments across an axis and append the mirrored copy in reverse order, creating a symmetric path. The axis passes through the current cursor position.
|
|
581
|
+
#### `mirror(axis: "x" | "y" | Vec2): this` — Mirror all existing segments across an axis and append the mirrored copy in reverse order, creating a symmetric path. The axis passes through the current cursor position.
|
|
969
582
|
|
|
970
583
|
'y' mirrors across the local Y-axis (flips X), or `[nx, ny]` for an arbitrary axis direction.
|
|
971
584
|
|
|
@@ -974,11 +587,7 @@ chamfer(distance: number): this
|
|
|
974
587
|
path().moveTo(0,0).lineTo(10,0).lineTo(10,5).mirror('x').close()
|
|
975
588
|
```
|
|
976
589
|
|
|
977
|
-
|
|
978
|
-
mirror(axis: "x" | "y" | [ number, number ]): this
|
|
979
|
-
```
|
|
980
|
-
|
|
981
|
-
#### `toPolyline()` — Return the open path as a sampled 2D polyline.
|
|
590
|
+
#### `toPolyline(): Vec2[]` — Return the open path as a sampled 2D polyline.
|
|
982
591
|
|
|
983
592
|
This is for construction geometry such as guide rails, measured centerlines, and curve-driven helpers where the authored path should stay open instead of becoming a filled sketch or stroked profile.
|
|
984
593
|
|
|
@@ -989,15 +598,7 @@ const rail = path()
|
|
|
989
598
|
.toPolyline();
|
|
990
599
|
```
|
|
991
600
|
|
|
992
|
-
|
|
993
|
-
toPolyline(): [ number, number ][]
|
|
994
|
-
```
|
|
995
|
-
|
|
996
|
-
#### `closeOffset()` — Close the path and return an offset version of the filled Sketch. Positive delta expands outward, negative shrinks inward.
|
|
997
|
-
|
|
998
|
-
```ts
|
|
999
|
-
closeOffset(delta: number, join?: "Round" | "Square" | "Miter"): Sketch
|
|
1000
|
-
```
|
|
601
|
+
#### `closeOffset(delta: number, join?: "Round" | "Square" | "Miter"): Sketch` — Close the path and return an offset version of the filled Sketch. Positive delta expands outward, negative shrinks inward.
|
|
1001
602
|
|
|
1002
603
|
### `ProductSkin`
|
|
1003
604
|
|
|
@@ -1013,29 +614,13 @@ closeOffset(delta: number, join?: "Round" | "Square" | "Miter"): Sketch
|
|
|
1013
614
|
|
|
1014
615
|
**Methods:**
|
|
1015
616
|
|
|
1016
|
-
####
|
|
1017
|
-
|
|
1018
|
-
```ts
|
|
1019
|
-
toShape(): Shape
|
|
1020
|
-
```
|
|
1021
|
-
|
|
1022
|
-
#### `with()` — Create a group containing this skin plus named child details.
|
|
1023
|
-
|
|
1024
|
-
```ts
|
|
1025
|
-
with(...children: GroupInput[]): ShapeGroup
|
|
1026
|
-
```
|
|
1027
|
-
|
|
1028
|
-
#### `integrate()` — Boolean-union structural details into the skin body.
|
|
617
|
+
#### `toShape(): Shape` — Return the renderable shape generated for this product skin.
|
|
1029
618
|
|
|
1030
|
-
|
|
1031
|
-
integrate(...details: Shape[]): Shape
|
|
1032
|
-
```
|
|
619
|
+
#### `with(...children: GroupInput[]): ShapeGroup` — Create a group containing this skin plus named child details.
|
|
1033
620
|
|
|
1034
|
-
#### `
|
|
621
|
+
#### `integrate(...details: Shape[]): Shape` — Boolean-union structural details into the skin body.
|
|
1035
622
|
|
|
1036
|
-
|
|
1037
|
-
uv(side: ProductSkinSide, u?: number, v?: number): ProductSkinRefQuery
|
|
1038
|
-
```
|
|
623
|
+
#### `uv(side: ProductSkinSide, u?: number, v?: number): ProductSkinRefQuery` — Create a side/u/v surface-ref query on this skin.
|
|
1039
624
|
|
|
1040
625
|
**`ProductSkinSide`** — Semantic side of a ProductSkin. `back` is accepted as an alias for `rear`.
|
|
1041
626
|
|
|
@@ -1050,41 +635,21 @@ uv(side: ProductSkinSide, u?: number, v?: number): ProductSkinRefQuery
|
|
|
1050
635
|
| `v?` | `number` | Along-axis parameter, 0 at the first cap and 1 at the rear/back cap. Defaults to 0.5. |
|
|
1051
636
|
| `offset?` | `number` | Positive distance away from the surface along the resolved normal. |
|
|
1052
637
|
|
|
1053
|
-
#### `ref()` — Resolve a named ref published with Product.skin().refs(...).
|
|
1054
|
-
|
|
1055
|
-
```ts
|
|
1056
|
-
ref(name: string): ProductSurfaceRef
|
|
1057
|
-
```
|
|
1058
|
-
|
|
1059
|
-
#### `curveOnSurface()` — Create a sampled curve as a sequence of surface refs on this skin.
|
|
638
|
+
#### `ref(name: string): ProductSurfaceRef` — Resolve a named ref published with Product.skin().refs(...).
|
|
1060
639
|
|
|
1061
|
-
|
|
1062
|
-
curveOnSurface(name: string, points: Array<Partial<ProductSkinRefQuery> & { side: ProductSkinSide; }>): ProductSurfaceRef[]
|
|
1063
|
-
```
|
|
640
|
+
#### `curveOnSurface(name: string, points: Array<Partial<ProductSkinRefQuery> & { side: ProductSkinSide; }>): ProductSurfaceRef[]` — Create a sampled curve as a sequence of surface refs on this skin.
|
|
1064
641
|
|
|
1065
|
-
#### `surface()` — Create a fluent surface helper for refs and conformal features on one side of this skin.
|
|
642
|
+
#### `surface(side: ProductSkinSide): ProductSurfaceBuilder` — Create a fluent surface helper for refs and conformal features on one side of this skin.
|
|
1066
643
|
|
|
1067
644
|
Use this when several refs or ribbons share the same skin side; side-local helpers keep path points concise and make it harder to mix sides accidentally.
|
|
1068
645
|
|
|
1069
|
-
|
|
1070
|
-
surface(side: ProductSkinSide): ProductSurfaceBuilder
|
|
1071
|
-
```
|
|
1072
|
-
|
|
1073
|
-
#### `stationAt()` — Interpolate center, width, and depth at a normalized v or absolute axis value.
|
|
1074
|
-
|
|
1075
|
-
```ts
|
|
1076
|
-
stationAt(vOrAxis: number): { ... }
|
|
1077
|
-
```
|
|
646
|
+
#### `stationAt(vOrAxis: number): { ... }` — Interpolate center, width, and depth at a normalized v or absolute axis value.
|
|
1078
647
|
|
|
1079
648
|
**`ProductProfileKind`**
|
|
1080
649
|
|
|
1081
650
|
`"oval" | "roundedRect" | "circle" | "superEllipse" | "custom"`
|
|
1082
651
|
|
|
1083
|
-
#### `frame()` — Build a local surface frame from a side/u/v query.
|
|
1084
|
-
|
|
1085
|
-
```ts
|
|
1086
|
-
frame(query: ProductSkinRefQuery): ProductSurfaceFrame
|
|
1087
|
-
```
|
|
652
|
+
#### `frame(query: ProductSkinRefQuery): ProductSurfaceFrame` — Build a local surface frame from a side/u/v query.
|
|
1088
653
|
|
|
1089
654
|
`ProductSurfaceFrame`: `{ point: Vec3, normal: Vec3, tangentU: Vec3, tangentV: Vec3, matrix: Mat4, skin: string }`
|
|
1090
655
|
|
|
@@ -1094,35 +659,19 @@ frame(query: ProductSkinRefQuery): ProductSurfaceFrame
|
|
|
1094
659
|
|
|
1095
660
|
| Property | Type | Description |
|
|
1096
661
|
|----------|------|-------------|
|
|
1097
|
-
| `name` | `string
|
|
662
|
+
| `name` | `string \| undefined` | — |
|
|
1098
663
|
|
|
1099
664
|
**Methods:**
|
|
1100
665
|
|
|
1101
|
-
#### `frame()` — Resolve this semantic surface ref into a point, normal, tangents, and placement matrix.
|
|
1102
|
-
|
|
1103
|
-
```ts
|
|
1104
|
-
frame(overrides?: Partial<ProductSkinRefQuery>): ProductSurfaceFrame
|
|
1105
|
-
```
|
|
1106
|
-
|
|
1107
|
-
#### `with()` — Return a copy of this ref with side/u/v/offset overrides.
|
|
1108
|
-
|
|
1109
|
-
```ts
|
|
1110
|
-
with(overrides: Partial<ProductSkinRefQuery>): ProductSurfaceRef
|
|
1111
|
-
```
|
|
666
|
+
#### `frame(overrides?: Partial<ProductSkinRefQuery>): ProductSurfaceFrame` — Resolve this semantic surface ref into a point, normal, tangents, and placement matrix.
|
|
1112
667
|
|
|
1113
|
-
#### `
|
|
668
|
+
#### `with(overrides: Partial<ProductSkinRefQuery>): ProductSurfaceRef` — Return a copy of this ref with side/u/v/offset overrides.
|
|
1114
669
|
|
|
1115
|
-
|
|
1116
|
-
attach(detail: Shape | ShapeGroup, options?: ProductAttachOptions): Shape | ShapeGroup
|
|
1117
|
-
```
|
|
670
|
+
#### `attach(detail: Shape | ShapeGroup, options?: ProductAttachOptions): Shape | ShapeGroup` — Place a detail shape or group on this ref's local surface frame.
|
|
1118
671
|
|
|
1119
672
|
`ProductAttachOptions`: `{ offset?: number, inset?: number }`
|
|
1120
673
|
|
|
1121
|
-
#### `querySpec()` — Return the serializable side/u/v query behind this ref.
|
|
1122
|
-
|
|
1123
|
-
```ts
|
|
1124
|
-
querySpec(): ProductSkinRefQuery
|
|
1125
|
-
```
|
|
674
|
+
#### `querySpec(): ProductSkinRefQuery` — Return the serializable side/u/v query behind this ref.
|
|
1126
675
|
|
|
1127
676
|
### `ProductSurfaceBuilder`
|
|
1128
677
|
|
|
@@ -1136,32 +685,16 @@ Fluent helper bound to one ProductSkin side for refs and side-local conformal fe
|
|
|
1136
685
|
|
|
1137
686
|
**Methods:**
|
|
1138
687
|
|
|
1139
|
-
#### `ref()` — Create a ref on this skin side.
|
|
1140
|
-
|
|
1141
|
-
```ts
|
|
1142
|
-
ref(u?: number, v?: number, offset?: number): ProductSurfaceRef
|
|
1143
|
-
```
|
|
1144
|
-
|
|
1145
|
-
#### `uv()` — Create a side/u/v query on this skin side.
|
|
1146
|
-
|
|
1147
|
-
```ts
|
|
1148
|
-
uv(u?: number, v?: number, offset?: number): ProductSkinRefQuery
|
|
1149
|
-
```
|
|
688
|
+
#### `ref(u?: number, v?: number, offset?: number): ProductSurfaceRef` — Create a ref on this skin side.
|
|
1150
689
|
|
|
1151
|
-
#### `
|
|
690
|
+
#### `uv(u?: number, v?: number, offset?: number): ProductSkinRefQuery` — Create a side/u/v query on this skin side.
|
|
1152
691
|
|
|
1153
|
-
|
|
1154
|
-
frame(query?: Partial<ProductSkinRefQuery>): ProductSurfaceFrame
|
|
1155
|
-
```
|
|
692
|
+
#### `frame(query?: Partial<ProductSkinRefQuery>): ProductSurfaceFrame` — Resolve a point/frame on this surface using the builder's side.
|
|
1156
693
|
|
|
1157
|
-
#### `ribbon()` — Start a conformal ribbon on this skin side.
|
|
694
|
+
#### `ribbon(name: string, points: ProductSurfacePathPoint[], options?: ProductRibbonBuildOptions): ProductRibbonBuilder` — Start a conformal ribbon on this skin side.
|
|
1158
695
|
|
|
1159
696
|
Path points use side-local `u`/`v` coordinates; this builder supplies the side. The returned ProductRibbonBuilder is already bound to the source skin and can be further configured before build(). Use `widthSamples` >= 3 when the ribbon must visibly wrap over curved product sections instead of behaving like a flat strip.
|
|
1160
697
|
|
|
1161
|
-
```ts
|
|
1162
|
-
ribbon(name: string, points: ProductSurfacePathPoint[], options?: ProductRibbonBuildOptions): ProductRibbonBuilder
|
|
1163
|
-
```
|
|
1164
|
-
|
|
1165
698
|
**`ProductSurfacePathPoint`** — Side-local path point for Product.surface(side).ribbon(...); the surface helper supplies `side`.
|
|
1166
699
|
- `u?: number` — Across-side parameter on the bound side. Defaults to 0.5.
|
|
1167
700
|
- `v?: number` — Along-axis parameter, 0 at the first cap and 1 at the rear/back cap. Defaults to 0.5.
|
|
@@ -1182,24 +715,7 @@ ribbon(name: string, points: ProductSurfacePathPoint[], options?: ProductRibbonB
|
|
|
1182
715
|
|
|
1183
716
|
`ProductMaterial`: `{ color?: string, material?: ShapeMaterialProps }`
|
|
1184
717
|
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
| Option | Type | Description |
|
|
1188
|
-
|--------|------|-------------|
|
|
1189
|
-
| `metalness?` | `number` | Metalness factor (0 = dielectric, 1 = metal). Default: 0.05 |
|
|
1190
|
-
| `roughness?` | `number` | Roughness factor (0 = mirror, 1 = fully diffuse). Default: 0.35 |
|
|
1191
|
-
| `emissive?` | `string` | Emissive glow color (hex string, e.g. "#ff6b35"). |
|
|
1192
|
-
| `emissiveIntensity?` | `number` | Emissive intensity multiplier. Default: 1 |
|
|
1193
|
-
| `opacity?` | `number` | Opacity (0 = fully transparent, 1 = fully opaque). Default: 1 |
|
|
1194
|
-
| `wireframe?` | `boolean` | Render as wireframe. Default: false |
|
|
1195
|
-
| `clearcoat?` | `number` | Clearcoat intensity (0–1). Default: 0.1 |
|
|
1196
|
-
| `clearcoatRoughness?` | `number` | Clearcoat roughness (0–1). Default: 0.4 |
|
|
1197
|
-
| `transmission?` | `number` | Glass/translucency transmission factor (0–1). Renderer support depends on target. |
|
|
1198
|
-
| `ior?` | `number` | Index of refraction for transmissive materials. Typical glass is ~1.45. |
|
|
1199
|
-
| `thickness?` | `number` | Approximate transmissive volume thickness in model units. |
|
|
1200
|
-
| `specularIntensity?` | `number` | Specular highlight intensity (0–1). |
|
|
1201
|
-
| `specularColor?` | `string` | Specular highlight tint. |
|
|
1202
|
-
| `reflectivity?` | `number` | Reflection strength for supported renderers (0–1). |
|
|
718
|
+
`ShapeMaterialProps` — defined in [core](/docs/core).
|
|
1203
719
|
|
|
1204
720
|
### `ProductSkinBuilder`
|
|
1205
721
|
|
|
@@ -1211,31 +727,19 @@ ribbon(name: string, points: ProductSurfacePathPoint[], options?: ProductRibbonB
|
|
|
1211
727
|
|
|
1212
728
|
**Methods:**
|
|
1213
729
|
|
|
1214
|
-
#### `axis()` — Choose the primary station axis for the skin loft.
|
|
1215
|
-
|
|
1216
|
-
```ts
|
|
1217
|
-
axis(axis: ProductSkinAxis): this
|
|
1218
|
-
```
|
|
730
|
+
#### `axis(axis: ProductSkinAxis): this` — Choose the primary station axis for the skin loft.
|
|
1219
731
|
|
|
1220
732
|
**`ProductSkinAxis`** — Primary world axis used to order ProductSkin loft stations.
|
|
1221
733
|
|
|
1222
734
|
`"X" | "Y" | "Z"`
|
|
1223
735
|
|
|
1224
|
-
#### `stations()` — Set named cross-section stations for the product skin.
|
|
1225
|
-
|
|
1226
|
-
```ts
|
|
1227
|
-
stations(stations: Array<ProductStationBuilder | ProductStationSpec>): this
|
|
1228
|
-
```
|
|
736
|
+
#### `stations(stations: Array<ProductStationBuilder | ProductStationSpec>): this` — Set named cross-section stations for the product skin.
|
|
1229
737
|
|
|
1230
738
|
`ProductStationSpec`: `{ name: string, center: Vec3, profile: ProductStationProfile, crown?: number }`
|
|
1231
739
|
|
|
1232
740
|
`ProductStationProfile`: `{ sketch: Sketch, width: number, depth: number, kind: ProductProfileKind, radius?: number, exponent?: number }`
|
|
1233
741
|
|
|
1234
|
-
#### `rails()` — Attach named guide rails for product-skin construction and downstream surface references.
|
|
1235
|
-
|
|
1236
|
-
```ts
|
|
1237
|
-
rails(rails: Record<string, ProductRailSpec>): this
|
|
1238
|
-
```
|
|
742
|
+
#### `rails(rails: Record<string, ProductRailSpec>): this` — Attach named guide rails for product-skin construction and downstream surface references.
|
|
1239
743
|
|
|
1240
744
|
`ProductRailSpec`: `{ kind: ProductRailKind, points: Vec3[], degree?: number, name?: string }`
|
|
1241
745
|
|
|
@@ -1243,53 +747,21 @@ rails(rails: Record<string, ProductRailSpec>): this
|
|
|
1243
747
|
|
|
1244
748
|
`"bezier" | "nurbs" | "polyline"`
|
|
1245
749
|
|
|
1246
|
-
#### `ref()` — Publish a named semantic surface ref on the skin.
|
|
1247
|
-
|
|
1248
|
-
```ts
|
|
1249
|
-
ref(name: string, query: ProductSkinRefQuery): this
|
|
1250
|
-
```
|
|
1251
|
-
|
|
1252
|
-
#### `refs()` — Publish multiple named semantic surface refs on the skin.
|
|
1253
|
-
|
|
1254
|
-
```ts
|
|
1255
|
-
refs(refs: Record<string, ProductSkinRefQuery>): this
|
|
1256
|
-
```
|
|
1257
|
-
|
|
1258
|
-
#### `uv()` — Create a side/u/v surface-ref query for use in refs(...) or Product.ref(...).
|
|
1259
|
-
|
|
1260
|
-
```ts
|
|
1261
|
-
uv(side: ProductSkinSide, u?: number, v?: number): ProductSkinRefQuery
|
|
1262
|
-
```
|
|
1263
|
-
|
|
1264
|
-
#### `material()` — Apply a product material preset to the lowered skin.
|
|
1265
|
-
|
|
1266
|
-
```ts
|
|
1267
|
-
material(material: ProductMaterial): this
|
|
1268
|
-
```
|
|
750
|
+
#### `ref(name: string, query: ProductSkinRefQuery): this` — Publish a named semantic surface ref on the skin.
|
|
1269
751
|
|
|
1270
|
-
#### `
|
|
1271
|
-
|
|
1272
|
-
```ts
|
|
1273
|
-
color(color: string): this
|
|
1274
|
-
```
|
|
752
|
+
#### `refs(refs: Record<string, ProductSkinRefQuery>): this` — Publish multiple named semantic surface refs on the skin.
|
|
1275
753
|
|
|
1276
|
-
#### `
|
|
754
|
+
#### `uv(side: ProductSkinSide, u?: number, v?: number): ProductSkinRefQuery` — Create a side/u/v surface-ref query for use in refs(...) or Product.ref(...).
|
|
1277
755
|
|
|
1278
|
-
|
|
1279
|
-
edgeLength(value: number): this
|
|
1280
|
-
```
|
|
756
|
+
#### `material(material: ProductMaterial): this` — Apply a product material preset to the lowered skin.
|
|
1281
757
|
|
|
1282
|
-
#### `
|
|
758
|
+
#### `color(color: string): this` — Apply a simple color override to the lowered skin.
|
|
1283
759
|
|
|
1284
|
-
|
|
1285
|
-
wall(thickness: number): this
|
|
1286
|
-
```
|
|
760
|
+
#### `edgeLength(value: number): this` — Set the sampled loft target edge length.
|
|
1287
761
|
|
|
1288
|
-
#### `
|
|
762
|
+
#### `wall(thickness: number): this` — Record intended wall thickness for product design metadata. Use explicit shelling when the model needs real inner-wall geometry.
|
|
1289
763
|
|
|
1290
|
-
|
|
1291
|
-
build(): ProductSkin
|
|
1292
|
-
```
|
|
764
|
+
#### `build(): ProductSkin` — Lower stations and refs into a ProductSkin body.
|
|
1293
765
|
|
|
1294
766
|
### `ProductStationBuilder`
|
|
1295
767
|
|
|
@@ -1301,73 +773,29 @@ build(): ProductSkin
|
|
|
1301
773
|
|
|
1302
774
|
**Methods:**
|
|
1303
775
|
|
|
1304
|
-
#### `at()` — Position this station in world coordinates.
|
|
1305
|
-
|
|
1306
|
-
```ts
|
|
1307
|
-
at(point: Vec3): this
|
|
1308
|
-
```
|
|
1309
|
-
|
|
1310
|
-
#### `z()` — Convenience for traditional Z-up section stacks.
|
|
1311
|
-
|
|
1312
|
-
```ts
|
|
1313
|
-
z(z: number): this
|
|
1314
|
-
```
|
|
1315
|
-
|
|
1316
|
-
#### `y()` — Convenience for product bodies running front-to-back along Y.
|
|
1317
|
-
|
|
1318
|
-
```ts
|
|
1319
|
-
y(y: number): this
|
|
1320
|
-
```
|
|
776
|
+
#### `at(point: Vec3): this` — Position this station in world coordinates.
|
|
1321
777
|
|
|
1322
|
-
#### `
|
|
1323
|
-
|
|
1324
|
-
```ts
|
|
1325
|
-
x(x: number): this
|
|
1326
|
-
```
|
|
778
|
+
#### `z(z: number): this` — Convenience for traditional Z-up section stacks.
|
|
1327
779
|
|
|
1328
|
-
#### `
|
|
780
|
+
#### `y(y: number): this` — Convenience for product bodies running front-to-back along Y.
|
|
1329
781
|
|
|
1330
|
-
|
|
1331
|
-
oval(width: number, depth: number, options?: { segments?: number; }): this
|
|
1332
|
-
```
|
|
782
|
+
#### `x(x: number): this` — Convenience for product bodies running left-to-right along X.
|
|
1333
783
|
|
|
1334
|
-
#### `
|
|
784
|
+
#### `oval(width: number, depth: number, options?: { segments?: number; }): this` — Use an oval cross-section with full width and depth dimensions.
|
|
1335
785
|
|
|
1336
|
-
|
|
1337
|
-
superEllipse(width: number, depth: number, options?: ProductStationSuperEllipseOptions): this
|
|
1338
|
-
```
|
|
786
|
+
#### `superEllipse(width: number, depth: number, options?: ProductStationSuperEllipseOptions): this` — Use a superellipse cross-section for soft-square product surfaces.
|
|
1339
787
|
|
|
1340
788
|
`ProductStationSuperEllipseOptions`: `{ segments?: number, exponent?: number }`
|
|
1341
789
|
|
|
1342
|
-
####
|
|
1343
|
-
|
|
1344
|
-
```ts
|
|
1345
|
-
roundedRect(width: number, depth: number, radius: number): this
|
|
1346
|
-
```
|
|
1347
|
-
|
|
1348
|
-
#### [`circle()`](/docs/sketch#circle) — Use a circular cross-section from a full diameter.
|
|
1349
|
-
|
|
1350
|
-
```ts
|
|
1351
|
-
circle(diameter: number, options?: { segments?: number; }): this
|
|
1352
|
-
```
|
|
1353
|
-
|
|
1354
|
-
#### `custom()` — Use a custom 2D sketch as the station cross-section.
|
|
1355
|
-
|
|
1356
|
-
```ts
|
|
1357
|
-
custom(sketch: Sketch, width: number, depth: number): this
|
|
1358
|
-
```
|
|
790
|
+
#### `roundedRect(width: number, depth: number, radius: number): this` — Use a rounded-rectangle cross-section with the given corner radius.
|
|
1359
791
|
|
|
1360
|
-
#### `
|
|
792
|
+
#### `circle(diameter: number, options?: { segments?: number; }): this` — Use a circular cross-section from a full diameter.
|
|
1361
793
|
|
|
1362
|
-
|
|
1363
|
-
crown(amount: number): this
|
|
1364
|
-
```
|
|
794
|
+
#### `custom(sketch: Sketch, width: number, depth: number): this` — Use a custom 2D sketch as the station cross-section.
|
|
1365
795
|
|
|
1366
|
-
#### `
|
|
796
|
+
#### `crown(amount: number): this` — Set the station crown amount for soft product-section intent.
|
|
1367
797
|
|
|
1368
|
-
|
|
1369
|
-
toSpec(): ProductStationSpec
|
|
1370
|
-
```
|
|
798
|
+
#### `toSpec(): ProductStationSpec` — Return the immutable station spec consumed by Product.skin().
|
|
1371
799
|
|
|
1372
800
|
### `ProductPanelBuilder`
|
|
1373
801
|
|
|
@@ -1379,53 +807,21 @@ toSpec(): ProductStationSpec
|
|
|
1379
807
|
|
|
1380
808
|
**Methods:**
|
|
1381
809
|
|
|
1382
|
-
#### `rounded()` — Use a rounded rectangle panel profile.
|
|
1383
|
-
|
|
1384
|
-
```ts
|
|
1385
|
-
rounded(width: number, height: number, radius?: number): this
|
|
1386
|
-
```
|
|
1387
|
-
|
|
1388
|
-
#### `oval()` — Use an oval panel profile.
|
|
1389
|
-
|
|
1390
|
-
```ts
|
|
1391
|
-
oval(width: number, height: number): this
|
|
1392
|
-
```
|
|
1393
|
-
|
|
1394
|
-
#### `profile()` — Use a custom 2D panel profile.
|
|
1395
|
-
|
|
1396
|
-
```ts
|
|
1397
|
-
profile(profile: Sketch): this
|
|
1398
|
-
```
|
|
1399
|
-
|
|
1400
|
-
#### `thickness()` — Set panel extrusion thickness.
|
|
1401
|
-
|
|
1402
|
-
```ts
|
|
1403
|
-
thickness(thickness: number): this
|
|
1404
|
-
```
|
|
1405
|
-
|
|
1406
|
-
#### `material()` — Apply a product material preset to the panel.
|
|
810
|
+
#### `rounded(width: number, height: number, radius?: number): this` — Use a rounded rectangle panel profile.
|
|
1407
811
|
|
|
1408
|
-
|
|
1409
|
-
material(material: ProductMaterial): this
|
|
1410
|
-
```
|
|
812
|
+
#### `oval(width: number, height: number): this` — Use an oval panel profile.
|
|
1411
813
|
|
|
1412
|
-
#### `
|
|
814
|
+
#### `profile(profile: Sketch): this` — Use a custom 2D panel profile.
|
|
1413
815
|
|
|
1414
|
-
|
|
1415
|
-
color(color: string): this
|
|
1416
|
-
```
|
|
816
|
+
#### `thickness(thickness: number): this` — Set panel extrusion thickness.
|
|
1417
817
|
|
|
1418
|
-
#### `
|
|
818
|
+
#### `material(material: ProductMaterial): this` — Apply a product material preset to the panel.
|
|
1419
819
|
|
|
1420
|
-
|
|
1421
|
-
build(): Shape
|
|
1422
|
-
```
|
|
820
|
+
#### `color(color: string): this` — Apply a simple color override to the panel.
|
|
1423
821
|
|
|
1424
|
-
#### `
|
|
822
|
+
#### `build(): Shape` — Build the panel in local coordinates.
|
|
1425
823
|
|
|
1426
|
-
|
|
1427
|
-
attachTo(ref: ProductRefInput, options?: ProductPanelAttachOptions): Shape
|
|
1428
|
-
```
|
|
824
|
+
#### `attachTo(ref: ProductRefInput, options?: ProductPanelAttachOptions): Shape` — Build and attach this panel to a ProductSurfaceRef.
|
|
1429
825
|
|
|
1430
826
|
**`ProductRefInput`**
|
|
1431
827
|
|
|
@@ -1446,693 +842,190 @@ Builder for thin trim, label, grip, and split-line features that bend with a Pro
|
|
|
1446
842
|
|
|
1447
843
|
**Methods:**
|
|
1448
844
|
|
|
1449
|
-
#### `on()` — Follow a ProductSkin with side/u/v path queries or refs.
|
|
845
|
+
#### `on(skin: ProductSkin, points: ProductRibbonPathPoint[], options?: ProductRibbonBuildOptions): this` — Follow a ProductSkin with side/u/v path queries or refs.
|
|
1450
846
|
|
|
1451
847
|
This is the highest-fidelity mode because every interpolated sample is resolved through ProductSkin.frame(), so the ribbon bends along the selected side as station width/depth changes. All query path points must stay on one side; split side transitions into separate ribbons.
|
|
1452
848
|
|
|
1453
|
-
```ts
|
|
1454
|
-
on(skin: ProductSkin, points: ProductRibbonPathPoint[], options?: ProductRibbonBuildOptions): this
|
|
1455
|
-
```
|
|
1456
|
-
|
|
1457
849
|
**`ProductRibbonPathPoint`** — Path point for Product.ribbon().on(...): either a side/u/v query or a resolved surface ref.
|
|
1458
850
|
|
|
1459
851
|
`ProductSkinRefQuery | ProductSurfaceRef`
|
|
1460
852
|
|
|
1461
|
-
#### `fromRefs()` — Follow explicit surface refs.
|
|
853
|
+
#### `fromRefs(points: ProductSurfaceRef[], options?: ProductRibbonBuildOptions): this` — Follow explicit surface refs.
|
|
1462
854
|
|
|
1463
855
|
Useful for named refs or paths assembled elsewhere. The builder resolves each ref frame and interpolates between those frames; use on(skin, points) when you need full skin-side sampling between sparse control points.
|
|
1464
856
|
|
|
1465
|
-
|
|
1466
|
-
fromRefs(points: ProductSurfaceRef[], options?: ProductRibbonBuildOptions): this
|
|
1467
|
-
```
|
|
857
|
+
#### `width(width: number): this` — Set ribbon width in millimeters.
|
|
1468
858
|
|
|
1469
|
-
#### `
|
|
859
|
+
#### `thickness(thickness: number): this` — Set solid thickness outward from the source surface in millimeters.
|
|
1470
860
|
|
|
1471
|
-
|
|
1472
|
-
width(width: number): this
|
|
1473
|
-
```
|
|
861
|
+
#### `offset(offset: number): this` — Set positive clearance between the source surface and the ribbon's inner face.
|
|
1474
862
|
|
|
1475
|
-
#### `
|
|
863
|
+
#### `samples(samples: number): this` — Set samples along the path.
|
|
1476
864
|
|
|
1477
|
-
|
|
1478
|
-
thickness(thickness: number): this
|
|
1479
|
-
```
|
|
865
|
+
#### `widthSamples(samples: number): this` — Set samples across the width. Use 3+ to bend over curved cross-sections.
|
|
1480
866
|
|
|
1481
|
-
#### `
|
|
867
|
+
#### `resolution(resolution: number): this` — Set NURBS tessellation resolution.
|
|
1482
868
|
|
|
1483
|
-
|
|
1484
|
-
offset(offset: number): this
|
|
1485
|
-
```
|
|
869
|
+
#### `material(material: ProductMaterial): this` — Apply a product material preset.
|
|
1486
870
|
|
|
1487
|
-
#### `
|
|
871
|
+
#### `color(color: string): this` — Apply a simple color override.
|
|
1488
872
|
|
|
1489
|
-
|
|
1490
|
-
samples(samples: number): this
|
|
1491
|
-
```
|
|
873
|
+
#### `build(options?: ProductRibbonBuildOptions): Shape` — Build a conformal ribbon as a thin NURBS surface solid.
|
|
1492
874
|
|
|
1493
|
-
|
|
875
|
+
### `CylinderCarrier`
|
|
1494
876
|
|
|
1495
|
-
|
|
1496
|
-
widthSamples(samples: number): this
|
|
1497
|
-
```
|
|
877
|
+
**Properties:**
|
|
1498
878
|
|
|
1499
|
-
|
|
879
|
+
| Property | Type | Description |
|
|
880
|
+
|----------|------|-------------|
|
|
881
|
+
| `name` | `string` | — |
|
|
882
|
+
| `kind` | `"cylinder"` | — |
|
|
1500
883
|
|
|
1501
|
-
|
|
1502
|
-
resolution(resolution: number): this
|
|
1503
|
-
```
|
|
884
|
+
**Methods:**
|
|
1504
885
|
|
|
1505
|
-
|
|
886
|
+
- `diameter(value: number): this`
|
|
887
|
+
- `radius(value: number): this`
|
|
888
|
+
- `height(value: number): this`
|
|
889
|
+
- `clearance(value: number): this`
|
|
890
|
+
- `center(point: Vec3): this`
|
|
891
|
+
- `path(): SurfacePathBuilder<CylinderSurfaceCoordinate>`
|
|
892
|
+
- `anchor(angle: number, z?: number, options?: { offset?: number; }): SurfaceAnchor<CylinderSurfaceCoordinate>`
|
|
893
|
+
- `front(options?: { z?: number; offset?: number; }): SurfaceAnchor<CylinderSurfaceCoordinate>`
|
|
894
|
+
- `back(options?: { z?: number; offset?: number; }): SurfaceAnchor<CylinderSurfaceCoordinate>`
|
|
895
|
+
- `left(options?: { z?: number; offset?: number; }): SurfaceAnchor<CylinderSurfaceCoordinate>`
|
|
896
|
+
- `right(options?: { z?: number; offset?: number; }): SurfaceAnchor<CylinderSurfaceCoordinate>`
|
|
897
|
+
- `top(options?: { angle?: number; offset?: number; }): SurfaceAnchor<CylinderSurfaceCoordinate>`
|
|
898
|
+
- `bottom(options?: { angle?: number; offset?: number; }): SurfaceAnchor<CylinderSurfaceCoordinate>`
|
|
899
|
+
- `pointAt(coordinate: CylinderSurfaceCoordinate): Vec3`
|
|
900
|
+
- `mirrorPoint(point: Vec3): Vec3`
|
|
901
|
+
- `normalAt(coordinate: CylinderSurfaceCoordinate): Vec3`
|
|
902
|
+
- `tangentAt(coordinate: CylinderSurfaceCoordinate, tangentHint?: Vec3): Vec3`
|
|
903
|
+
- `frameAt(coordinate: CylinderSurfaceCoordinate, tangentHint?: Vec3): SurfaceFrame`
|
|
904
|
+
- `bounds(): SurfaceBounds`
|
|
905
|
+
- `offset(distance: number): CylinderCarrier`
|
|
906
|
+
- `mirrorCoordinate(coordinate: CylinderSurfaceCoordinate): CylinderSurfaceCoordinate`
|
|
907
|
+
- `radiusValueWithClearance(): number`
|
|
1506
908
|
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
909
|
+
`CylinderSurfaceCoordinate`: `{ kind?: "cylinder", angle: number, z: number, offset?: number }`
|
|
910
|
+
|
|
911
|
+
### `PlaneCarrier`
|
|
1510
912
|
|
|
1511
|
-
|
|
913
|
+
**Properties:**
|
|
1512
914
|
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
915
|
+
| Property | Type | Description |
|
|
916
|
+
|----------|------|-------------|
|
|
917
|
+
| `name` | `string` | — |
|
|
918
|
+
| `kind` | `"plane"` | — |
|
|
1516
919
|
|
|
1517
|
-
|
|
920
|
+
**Methods:**
|
|
1518
921
|
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
922
|
+
- `size(width: number, height: number): this`
|
|
923
|
+
- `origin(point: Vec3): this`
|
|
924
|
+
- `normal(normal: Vec3): this`
|
|
925
|
+
- `path(): SurfacePathBuilder<PlaneSurfaceCoordinate>`
|
|
926
|
+
- `anchor(x?: number, y?: number, options?: { offset?: number; }): SurfaceAnchor<PlaneSurfaceCoordinate>`
|
|
927
|
+
- `left(options?: { y?: number; offset?: number; }): SurfaceAnchor<PlaneSurfaceCoordinate>`
|
|
928
|
+
- `right(options?: { y?: number; offset?: number; }): SurfaceAnchor<PlaneSurfaceCoordinate>`
|
|
929
|
+
- `top(options?: { x?: number; offset?: number; }): SurfaceAnchor<PlaneSurfaceCoordinate>`
|
|
930
|
+
- `bottom(options?: { x?: number; offset?: number; }): SurfaceAnchor<PlaneSurfaceCoordinate>`
|
|
931
|
+
- `pointAt(coordinate: PlaneSurfaceCoordinate): Vec3`
|
|
932
|
+
- `mirrorPoint(point: Vec3): Vec3`
|
|
933
|
+
- `normalAt(): Vec3`
|
|
934
|
+
- `tangentAt(coordinate: PlaneSurfaceCoordinate, tangentHint?: Vec3): Vec3`
|
|
935
|
+
- `frameAt(coordinate: PlaneSurfaceCoordinate, tangentHint?: Vec3): SurfaceFrame`
|
|
936
|
+
- `bounds(): SurfaceBounds`
|
|
937
|
+
- `offset(distance: number): PlaneCarrier`
|
|
938
|
+
- `mirrorCoordinate(coordinate: PlaneSurfaceCoordinate): PlaneSurfaceCoordinate`
|
|
939
|
+
|
|
940
|
+
`PlaneSurfaceCoordinate`: `{ kind?: "plane", x: number, y: number, offset?: number }`
|
|
1522
941
|
|
|
1523
|
-
### `
|
|
942
|
+
### `ProductSkinCarrier`
|
|
1524
943
|
|
|
1525
944
|
**Properties:**
|
|
1526
945
|
|
|
1527
946
|
| Property | Type | Description |
|
|
1528
947
|
|----------|------|-------------|
|
|
948
|
+
| `skin` | `ProductSkin` | — |
|
|
1529
949
|
| `name` | `string` | — |
|
|
950
|
+
| `kind` | `"productSkin"` | — |
|
|
1530
951
|
|
|
1531
952
|
**Methods:**
|
|
1532
953
|
|
|
1533
|
-
#### `
|
|
1534
|
-
|
|
1535
|
-
```ts
|
|
1536
|
-
from(ref: ProductSurfaceRef): this
|
|
1537
|
-
```
|
|
1538
|
-
|
|
1539
|
-
#### `sections()` — Set local spout section profiles from root to mouth.
|
|
954
|
+
#### `sideTransition(fromSide: ProductSkinSide, toSide: ProductSkinSide, input?: ProductSkinSideTransitionInput): ProductSkinSideTransition` — Return matching side-local coordinates for an explicit split-member transition.
|
|
1540
955
|
|
|
1541
|
-
|
|
1542
|
-
sections(sections: Array<Sketch | ProductStationBuilder | ProductStationSpec>): this
|
|
1543
|
-
```
|
|
956
|
+
Each SurfacePath still stays on one ProductSkin side. Use this helper to create one member ending on `from`, another starting on `to`, then join named anchors.
|
|
1544
957
|
|
|
1545
|
-
|
|
958
|
+
Rules: only adjacent `left`/`top`/`right`/`bottom` sides are supported — for front/rear caps use `Product.panel()`. `v` is normalized 0–1 along the shared boundary (default 0.5); `name` must be non-empty when provided; `offset` lifts both coordinates off the surface. Throws if the returned boundary coordinates are not physically coincident — check side order, `v`, and `offset`.
|
|
1546
959
|
|
|
1547
|
-
|
|
1548
|
-
projection(length: number): this
|
|
1549
|
-
```
|
|
960
|
+
`ProductSkinSideTransitionInput`: `{ name?: string, v?: number, offset?: number }`
|
|
1550
961
|
|
|
1551
|
-
|
|
962
|
+
`ProductSkinSideTransition`: `{ name?: string, from: ProductSkinSurfaceCoordinate, to: ProductSkinSurfaceCoordinate }`
|
|
1552
963
|
|
|
1553
|
-
|
|
1554
|
-
edgeLength(value: number): this
|
|
1555
|
-
```
|
|
964
|
+
`ProductSkinSurfaceCoordinate`: `{ kind?: "productSkin", side?: ProductSkinSide, u?: number, v?: number, offset?: number }`
|
|
1556
965
|
|
|
1557
|
-
#### `
|
|
966
|
+
#### `sideTransitionChain(sides: ProductSkinSide[], input?: ProductSkinSideTransitionInput): ProductSkinSideTransition[]` — Return a sequence of matching side-local coordinates for an explicit multi-side split-member route.
|
|
1558
967
|
|
|
1559
|
-
|
|
1560
|
-
material(material: ProductMaterial): this
|
|
1561
|
-
```
|
|
968
|
+
Each adjacent side pair becomes one named transition. Build one member per side segment, add transition anchors at each returned pair, then join the anchors. The same validation as `sideTransition()` applies to every adjacent pair.
|
|
1562
969
|
|
|
1563
|
-
#### `
|
|
970
|
+
#### `sideRoute(input: ProductSkinSideRouteInput): ProductSkinSideRoute` — Return side-local member segments for a generated multi-side split-member route.
|
|
1564
971
|
|
|
1565
|
-
|
|
1566
|
-
color(color: string): this
|
|
1567
|
-
```
|
|
972
|
+
The route still compiles as explicit members plus named-anchor joins. This helper only generates the per-side segment endpoints and transition names.
|
|
1568
973
|
|
|
1569
|
-
|
|
974
|
+
**`ProductSkinSideRouteInput`**: `name?: string`, `sides: ProductSkinSide[]`, `from: ProductSkinSurfaceCoordinate`, `to: ProductSkinSurfaceCoordinate`, `v?: number`, `offset?: number`
|
|
1570
975
|
|
|
1571
|
-
|
|
1572
|
-
build(): Shape
|
|
1573
|
-
```
|
|
976
|
+
`ProductSkinSideRoute`: `{ name?: string, transitions: ProductSkinSideTransition[], segments: ProductSkinSideRouteSegment[] }`
|
|
1574
977
|
|
|
1575
|
-
|
|
978
|
+
**`ProductSkinSideRouteSegment`**: `name: string`, `side: ProductSkinSide`, `from: ProductSkinSurfaceCoordinate`, `to: ProductSkinSurfaceCoordinate`, `startAnchorName?: string`, `endAnchorName?: string`
|
|
1576
979
|
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
980
|
+
- `surface(side: ProductSkinSide): ProductSkinCarrier`
|
|
981
|
+
- `path(): SurfacePathBuilder<ProductSkinSurfaceCoordinate>`
|
|
982
|
+
- `pointAt(coordinate: ProductSkinSurfaceCoordinate): Vec3`
|
|
983
|
+
- `mirrorPoint(point: Vec3): Vec3`
|
|
984
|
+
- `normalAt(coordinate: ProductSkinSurfaceCoordinate): Vec3`
|
|
985
|
+
- `tangentAt(coordinate: ProductSkinSurfaceCoordinate, tangentHint?: Vec3): Vec3`
|
|
986
|
+
- `frameAt(coordinate: ProductSkinSurfaceCoordinate, tangentHint?: Vec3): SurfaceFrame`
|
|
987
|
+
- `bounds(): SurfaceBounds`
|
|
988
|
+
- `offset(distance: number): ProductSkinCarrier`
|
|
989
|
+
- `mirrorCoordinate(coordinate: ProductSkinSurfaceCoordinate): ProductSkinSurfaceCoordinate`
|
|
1580
990
|
|
|
1581
|
-
### `
|
|
991
|
+
### `SurfacePath`
|
|
1582
992
|
|
|
1583
993
|
**Properties:**
|
|
1584
994
|
|
|
1585
995
|
| Property | Type | Description |
|
|
1586
996
|
|----------|------|-------------|
|
|
1587
|
-
| `
|
|
997
|
+
| `carrier` | `CarrierSurface<C>` | — |
|
|
998
|
+
| `points` | `C[]` | — |
|
|
999
|
+
| `closedValue` | `boolean` | — |
|
|
1588
1000
|
|
|
1589
1001
|
**Methods:**
|
|
1590
1002
|
|
|
1591
|
-
|
|
1003
|
+
- `closed(): SurfacePath<C>`
|
|
1004
|
+
- `mirror(): SurfacePath<C>`
|
|
1005
|
+
- `coordinateAt(t: number): C`
|
|
1006
|
+
- `sample(count?: number): SurfacePathSample<C>[]`
|
|
1007
|
+
- `length(samples?: number): number`
|
|
1592
1008
|
|
|
1593
|
-
|
|
1594
|
-
between(upper: ProductSurfaceRef, lower: Vec3): this
|
|
1595
|
-
```
|
|
1009
|
+
### `SurfacePathBuilder`
|
|
1596
1010
|
|
|
1597
|
-
|
|
1011
|
+
**Properties:**
|
|
1598
1012
|
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1013
|
+
| Property | Type | Description |
|
|
1014
|
+
|----------|------|-------------|
|
|
1015
|
+
| `carrier` | `CarrierSurface<C>` | — |
|
|
1602
1016
|
|
|
1603
|
-
|
|
1017
|
+
**Methods:**
|
|
1604
1018
|
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1019
|
+
- `from(coordinate: C): this`
|
|
1020
|
+
- `through(coordinate: C): this`
|
|
1021
|
+
- `to(coordinate: C): this`
|
|
1022
|
+
- `around(input: { z: number; fromAngle: number; toAngle: number; offset?: number; }): this`
|
|
1023
|
+
- `closed(): this`
|
|
1024
|
+
- `mirror(): SurfacePath<C>`
|
|
1025
|
+
- `build(): SurfacePath<C>`
|
|
1026
|
+
- `sample(count?: number): SurfacePathSample<C>[]`
|
|
1608
1027
|
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
```ts
|
|
1612
|
-
material(material: ProductMaterial): this
|
|
1613
|
-
```
|
|
1614
|
-
|
|
1615
|
-
#### `padMaterial()` — Apply a product material preset to handle landing pads.
|
|
1616
|
-
|
|
1617
|
-
```ts
|
|
1618
|
-
padMaterial(material: ProductMaterial): this
|
|
1619
|
-
```
|
|
1620
|
-
|
|
1621
|
-
#### `edgeLength()` — Set the sampled loft target edge length for the grip.
|
|
1622
|
-
|
|
1623
|
-
```ts
|
|
1624
|
-
edgeLength(value: number): this
|
|
1625
|
-
```
|
|
1626
|
-
|
|
1627
|
-
#### `build()` — Build the handle grip and landing pads.
|
|
1628
|
-
|
|
1629
|
-
```ts
|
|
1630
|
-
build(): ProductHandleFeature
|
|
1631
|
-
```
|
|
1632
|
-
|
|
1633
|
-
### `ProductHandleFeature`
|
|
1634
|
-
|
|
1635
|
-
**Properties:**
|
|
1636
|
-
|
|
1637
|
-
| Property | Type | Description |
|
|
1638
|
-
|----------|------|-------------|
|
|
1639
|
-
| `grip` | `Shape` | — |
|
|
1640
|
-
| `upperPad` | `Shape` | — |
|
|
1641
|
-
| `lowerPad` | `Shape` | — |
|
|
1642
|
-
|
|
1643
|
-
**Methods:**
|
|
1644
|
-
|
|
1645
|
-
#### `structural()` — Return the physical shapes that make up this handle feature.
|
|
1646
|
-
|
|
1647
|
-
```ts
|
|
1648
|
-
structural(): Shape[]
|
|
1649
|
-
```
|
|
1650
|
-
|
|
1651
|
-
#### [`toShape()`](/docs/sdf#toshape) — Boolean-union the handle feature into a single shape.
|
|
1652
|
-
|
|
1653
|
-
```ts
|
|
1654
|
-
toShape(): Shape
|
|
1655
|
-
```
|
|
1656
|
-
|
|
1657
|
-
#### `toGroup()` — Return the handle as a named ShapeGroup preserving child colors.
|
|
1658
|
-
|
|
1659
|
-
```ts
|
|
1660
|
-
toGroup(): ShapeGroup
|
|
1661
|
-
```
|
|
1662
|
-
|
|
1663
|
-
### `CylinderCarrier`
|
|
1664
|
-
|
|
1665
|
-
**Properties:**
|
|
1666
|
-
|
|
1667
|
-
| Property | Type | Description |
|
|
1668
|
-
|----------|------|-------------|
|
|
1669
|
-
| `name` | `string` | — |
|
|
1670
|
-
| `kind` | `"cylinder"` | — |
|
|
1671
|
-
|
|
1672
|
-
**Methods:**
|
|
1673
|
-
|
|
1674
|
-
#### `diameter()`
|
|
1675
|
-
|
|
1676
|
-
```ts
|
|
1677
|
-
diameter(value: number): this
|
|
1678
|
-
```
|
|
1679
|
-
|
|
1680
|
-
#### `radius()`
|
|
1681
|
-
|
|
1682
|
-
```ts
|
|
1683
|
-
radius(value: number): this
|
|
1684
|
-
```
|
|
1685
|
-
|
|
1686
|
-
#### `height()`
|
|
1687
|
-
|
|
1688
|
-
```ts
|
|
1689
|
-
height(value: number): this
|
|
1690
|
-
```
|
|
1691
|
-
|
|
1692
|
-
#### `clearance()`
|
|
1693
|
-
|
|
1694
|
-
```ts
|
|
1695
|
-
clearance(value: number): this
|
|
1696
|
-
```
|
|
1697
|
-
|
|
1698
|
-
#### `center()`
|
|
1699
|
-
|
|
1700
|
-
```ts
|
|
1701
|
-
center(point: Vec3): this
|
|
1702
|
-
```
|
|
1703
|
-
|
|
1704
|
-
#### [`path()`](/docs/sketch#path)
|
|
1705
|
-
|
|
1706
|
-
```ts
|
|
1707
|
-
path(): SurfacePathBuilder<CylinderSurfaceCoordinate>
|
|
1708
|
-
```
|
|
1709
|
-
|
|
1710
|
-
#### `anchor()`
|
|
1711
|
-
|
|
1712
|
-
```ts
|
|
1713
|
-
anchor(angle: number, z?: number, options?: { offset?: number; }): SurfaceAnchor<CylinderSurfaceCoordinate>
|
|
1714
|
-
```
|
|
1715
|
-
|
|
1716
|
-
#### `front()`
|
|
1717
|
-
|
|
1718
|
-
```ts
|
|
1719
|
-
front(options?: { z?: number; offset?: number; }): SurfaceAnchor<CylinderSurfaceCoordinate>
|
|
1720
|
-
```
|
|
1721
|
-
|
|
1722
|
-
#### `back()`
|
|
1723
|
-
|
|
1724
|
-
```ts
|
|
1725
|
-
back(options?: { z?: number; offset?: number; }): SurfaceAnchor<CylinderSurfaceCoordinate>
|
|
1726
|
-
```
|
|
1727
|
-
|
|
1728
|
-
#### `left()`
|
|
1729
|
-
|
|
1730
|
-
```ts
|
|
1731
|
-
left(options?: { z?: number; offset?: number; }): SurfaceAnchor<CylinderSurfaceCoordinate>
|
|
1732
|
-
```
|
|
1733
|
-
|
|
1734
|
-
#### `right()`
|
|
1735
|
-
|
|
1736
|
-
```ts
|
|
1737
|
-
right(options?: { z?: number; offset?: number; }): SurfaceAnchor<CylinderSurfaceCoordinate>
|
|
1738
|
-
```
|
|
1739
|
-
|
|
1740
|
-
#### `top()`
|
|
1741
|
-
|
|
1742
|
-
```ts
|
|
1743
|
-
top(options?: { angle?: number; offset?: number; }): SurfaceAnchor<CylinderSurfaceCoordinate>
|
|
1744
|
-
```
|
|
1745
|
-
|
|
1746
|
-
#### `bottom()`
|
|
1747
|
-
|
|
1748
|
-
```ts
|
|
1749
|
-
bottom(options?: { angle?: number; offset?: number; }): SurfaceAnchor<CylinderSurfaceCoordinate>
|
|
1750
|
-
```
|
|
1751
|
-
|
|
1752
|
-
#### `pointAt()`
|
|
1753
|
-
|
|
1754
|
-
```ts
|
|
1755
|
-
pointAt(coordinate: CylinderSurfaceCoordinate): Vec3
|
|
1756
|
-
```
|
|
1757
|
-
|
|
1758
|
-
`CylinderSurfaceCoordinate`: `{ kind?: "cylinder", angle: number, z: number, offset?: number }`
|
|
1759
|
-
|
|
1760
|
-
#### `mirrorPoint()`
|
|
1761
|
-
|
|
1762
|
-
```ts
|
|
1763
|
-
mirrorPoint(point: Vec3): Vec3
|
|
1764
|
-
```
|
|
1765
|
-
|
|
1766
|
-
#### `normalAt()`
|
|
1767
|
-
|
|
1768
|
-
```ts
|
|
1769
|
-
normalAt(coordinate: CylinderSurfaceCoordinate): Vec3
|
|
1770
|
-
```
|
|
1771
|
-
|
|
1772
|
-
#### `tangentAt()`
|
|
1773
|
-
|
|
1774
|
-
```ts
|
|
1775
|
-
tangentAt(coordinate: CylinderSurfaceCoordinate, tangentHint?: Vec3): Vec3
|
|
1776
|
-
```
|
|
1777
|
-
|
|
1778
|
-
#### `frameAt()`
|
|
1779
|
-
|
|
1780
|
-
```ts
|
|
1781
|
-
frameAt(coordinate: CylinderSurfaceCoordinate, tangentHint?: Vec3): SurfaceFrame
|
|
1782
|
-
```
|
|
1783
|
-
|
|
1784
|
-
#### `bounds()`
|
|
1785
|
-
|
|
1786
|
-
```ts
|
|
1787
|
-
bounds(): SurfaceBounds
|
|
1788
|
-
```
|
|
1789
|
-
|
|
1790
|
-
#### `offset()`
|
|
1791
|
-
|
|
1792
|
-
```ts
|
|
1793
|
-
offset(distance: number): CylinderCarrier
|
|
1794
|
-
```
|
|
1795
|
-
|
|
1796
|
-
#### `mirrorCoordinate()`
|
|
1797
|
-
|
|
1798
|
-
```ts
|
|
1799
|
-
mirrorCoordinate(coordinate: CylinderSurfaceCoordinate): CylinderSurfaceCoordinate
|
|
1800
|
-
```
|
|
1801
|
-
|
|
1802
|
-
#### `radiusValueWithClearance()`
|
|
1803
|
-
|
|
1804
|
-
```ts
|
|
1805
|
-
radiusValueWithClearance(): number
|
|
1806
|
-
```
|
|
1807
|
-
|
|
1808
|
-
### `PlaneCarrier`
|
|
1809
|
-
|
|
1810
|
-
**Properties:**
|
|
1811
|
-
|
|
1812
|
-
| Property | Type | Description |
|
|
1813
|
-
|----------|------|-------------|
|
|
1814
|
-
| `name` | `string` | — |
|
|
1815
|
-
| `kind` | `"plane"` | — |
|
|
1816
|
-
|
|
1817
|
-
**Methods:**
|
|
1818
|
-
|
|
1819
|
-
#### `size()`
|
|
1820
|
-
|
|
1821
|
-
```ts
|
|
1822
|
-
size(width: number, height: number): this
|
|
1823
|
-
```
|
|
1824
|
-
|
|
1825
|
-
#### `origin()`
|
|
1826
|
-
|
|
1827
|
-
```ts
|
|
1828
|
-
origin(point: Vec3): this
|
|
1829
|
-
```
|
|
1830
|
-
|
|
1831
|
-
#### `normal()`
|
|
1832
|
-
|
|
1833
|
-
```ts
|
|
1834
|
-
normal(normal: Vec3): this
|
|
1835
|
-
```
|
|
1836
|
-
|
|
1837
|
-
#### [`path()`](/docs/sketch#path)
|
|
1838
|
-
|
|
1839
|
-
```ts
|
|
1840
|
-
path(): SurfacePathBuilder<PlaneSurfaceCoordinate>
|
|
1841
|
-
```
|
|
1842
|
-
|
|
1843
|
-
#### `anchor()`
|
|
1844
|
-
|
|
1845
|
-
```ts
|
|
1846
|
-
anchor(x?: number, y?: number, options?: { offset?: number; }): SurfaceAnchor<PlaneSurfaceCoordinate>
|
|
1847
|
-
```
|
|
1848
|
-
|
|
1849
|
-
#### `left()`
|
|
1850
|
-
|
|
1851
|
-
```ts
|
|
1852
|
-
left(options?: { y?: number; offset?: number; }): SurfaceAnchor<PlaneSurfaceCoordinate>
|
|
1853
|
-
```
|
|
1854
|
-
|
|
1855
|
-
#### `right()`
|
|
1856
|
-
|
|
1857
|
-
```ts
|
|
1858
|
-
right(options?: { y?: number; offset?: number; }): SurfaceAnchor<PlaneSurfaceCoordinate>
|
|
1859
|
-
```
|
|
1860
|
-
|
|
1861
|
-
#### `top()`
|
|
1862
|
-
|
|
1863
|
-
```ts
|
|
1864
|
-
top(options?: { x?: number; offset?: number; }): SurfaceAnchor<PlaneSurfaceCoordinate>
|
|
1865
|
-
```
|
|
1866
|
-
|
|
1867
|
-
#### `bottom()`
|
|
1868
|
-
|
|
1869
|
-
```ts
|
|
1870
|
-
bottom(options?: { x?: number; offset?: number; }): SurfaceAnchor<PlaneSurfaceCoordinate>
|
|
1871
|
-
```
|
|
1872
|
-
|
|
1873
|
-
#### `pointAt()`
|
|
1874
|
-
|
|
1875
|
-
```ts
|
|
1876
|
-
pointAt(coordinate: PlaneSurfaceCoordinate): Vec3
|
|
1877
|
-
```
|
|
1878
|
-
|
|
1879
|
-
`PlaneSurfaceCoordinate`: `{ kind?: "plane", x: number, y: number, offset?: number }`
|
|
1880
|
-
|
|
1881
|
-
#### `mirrorPoint()`
|
|
1882
|
-
|
|
1883
|
-
```ts
|
|
1884
|
-
mirrorPoint(point: Vec3): Vec3
|
|
1885
|
-
```
|
|
1886
|
-
|
|
1887
|
-
#### `normalAt()`
|
|
1888
|
-
|
|
1889
|
-
```ts
|
|
1890
|
-
normalAt(): Vec3
|
|
1891
|
-
```
|
|
1892
|
-
|
|
1893
|
-
#### `tangentAt()`
|
|
1894
|
-
|
|
1895
|
-
```ts
|
|
1896
|
-
tangentAt(coordinate: PlaneSurfaceCoordinate, tangentHint?: Vec3): Vec3
|
|
1897
|
-
```
|
|
1898
|
-
|
|
1899
|
-
#### `frameAt()`
|
|
1900
|
-
|
|
1901
|
-
```ts
|
|
1902
|
-
frameAt(coordinate: PlaneSurfaceCoordinate, tangentHint?: Vec3): SurfaceFrame
|
|
1903
|
-
```
|
|
1904
|
-
|
|
1905
|
-
#### `bounds()`
|
|
1906
|
-
|
|
1907
|
-
```ts
|
|
1908
|
-
bounds(): SurfaceBounds
|
|
1909
|
-
```
|
|
1910
|
-
|
|
1911
|
-
#### `offset()`
|
|
1912
|
-
|
|
1913
|
-
```ts
|
|
1914
|
-
offset(distance: number): PlaneCarrier
|
|
1915
|
-
```
|
|
1916
|
-
|
|
1917
|
-
#### `mirrorCoordinate()`
|
|
1918
|
-
|
|
1919
|
-
```ts
|
|
1920
|
-
mirrorCoordinate(coordinate: PlaneSurfaceCoordinate): PlaneSurfaceCoordinate
|
|
1921
|
-
```
|
|
1922
|
-
|
|
1923
|
-
### `ProductSkinCarrier`
|
|
1924
|
-
|
|
1925
|
-
**Properties:**
|
|
1926
|
-
|
|
1927
|
-
| Property | Type | Description |
|
|
1928
|
-
|----------|------|-------------|
|
|
1929
|
-
| `skin` | `ProductSkin` | — |
|
|
1930
|
-
| `name` | `string` | — |
|
|
1931
|
-
| `kind` | `"productSkin"` | — |
|
|
1932
|
-
|
|
1933
|
-
**Methods:**
|
|
1934
|
-
|
|
1935
|
-
#### `surface()`
|
|
1936
|
-
|
|
1937
|
-
```ts
|
|
1938
|
-
surface(side: ProductSkinSide): ProductSkinCarrier
|
|
1939
|
-
```
|
|
1940
|
-
|
|
1941
|
-
#### [`path()`](/docs/sketch#path)
|
|
1942
|
-
|
|
1943
|
-
```ts
|
|
1944
|
-
path(): SurfacePathBuilder<ProductSkinSurfaceCoordinate>
|
|
1945
|
-
```
|
|
1946
|
-
|
|
1947
|
-
`ProductSkinSurfaceCoordinate`: `{ kind?: "productSkin", side?: ProductSkinSide, u?: number, v?: number, offset?: number }`
|
|
1948
|
-
|
|
1949
|
-
#### `sideTransition()` — Return matching side-local coordinates for an explicit split-member transition.
|
|
1950
|
-
|
|
1951
|
-
Each SurfacePath still stays on one ProductSkin side. Use this helper to create one member ending on `from`, another starting on `to`, then join named anchors. The helper validates normalized `v`, non-empty names, adjacency, and physical coincidence before returning anchors.
|
|
1952
|
-
|
|
1953
|
-
```ts
|
|
1954
|
-
sideTransition(fromSide: ProductSkinSide, toSide: ProductSkinSide, input?: ProductSkinSideTransitionInput): ProductSkinSideTransition
|
|
1955
|
-
```
|
|
1956
|
-
|
|
1957
|
-
`ProductSkinSideTransitionInput`: `{ name?: string, v?: number, offset?: number }`
|
|
1958
|
-
|
|
1959
|
-
`ProductSkinSideTransition`: `{ name?: string, from: ProductSkinSurfaceCoordinate, to: ProductSkinSurfaceCoordinate }`
|
|
1960
|
-
|
|
1961
|
-
#### `sideTransitionChain()` — Return a sequence of matching side-local coordinates for an explicit multi-side split-member route.
|
|
1962
|
-
|
|
1963
|
-
Each adjacent side pair becomes one named transition. Build one member per side segment, add transition anchors at each returned pair, then join the anchors. The same validation as `sideTransition()` applies to every adjacent pair.
|
|
1964
|
-
|
|
1965
|
-
```ts
|
|
1966
|
-
sideTransitionChain(sides: ProductSkinSide[], input?: ProductSkinSideTransitionInput): ProductSkinSideTransition[]
|
|
1967
|
-
```
|
|
1968
|
-
|
|
1969
|
-
#### `sideRoute()` — Return side-local member segments for a generated multi-side split-member route.
|
|
1970
|
-
|
|
1971
|
-
The route still compiles as explicit members plus named-anchor joins. This helper only generates the per-side segment endpoints and transition names.
|
|
1972
|
-
|
|
1973
|
-
```ts
|
|
1974
|
-
sideRoute(input: ProductSkinSideRouteInput): ProductSkinSideRoute
|
|
1975
|
-
```
|
|
1976
|
-
|
|
1977
|
-
**`ProductSkinSideRouteInput`**: `name?: string`, `sides: ProductSkinSide[]`, `from: ProductSkinSurfaceCoordinate`, `to: ProductSkinSurfaceCoordinate`, `v?: number`, `offset?: number`
|
|
1978
|
-
|
|
1979
|
-
`ProductSkinSideRoute`: `{ name?: string, transitions: ProductSkinSideTransition[], segments: ProductSkinSideRouteSegment[] }`
|
|
1980
|
-
|
|
1981
|
-
**`ProductSkinSideRouteSegment`**: `name: string`, `side: ProductSkinSide`, `from: ProductSkinSurfaceCoordinate`, `to: ProductSkinSurfaceCoordinate`, `startAnchorName?: string`, `endAnchorName?: string`
|
|
1982
|
-
|
|
1983
|
-
#### `pointAt()`
|
|
1984
|
-
|
|
1985
|
-
```ts
|
|
1986
|
-
pointAt(coordinate: ProductSkinSurfaceCoordinate): Vec3
|
|
1987
|
-
```
|
|
1988
|
-
|
|
1989
|
-
#### `mirrorPoint()`
|
|
1990
|
-
|
|
1991
|
-
```ts
|
|
1992
|
-
mirrorPoint(point: Vec3): Vec3
|
|
1993
|
-
```
|
|
1994
|
-
|
|
1995
|
-
#### `normalAt()`
|
|
1996
|
-
|
|
1997
|
-
```ts
|
|
1998
|
-
normalAt(coordinate: ProductSkinSurfaceCoordinate): Vec3
|
|
1999
|
-
```
|
|
2000
|
-
|
|
2001
|
-
#### `tangentAt()`
|
|
2002
|
-
|
|
2003
|
-
```ts
|
|
2004
|
-
tangentAt(coordinate: ProductSkinSurfaceCoordinate, tangentHint?: Vec3): Vec3
|
|
2005
|
-
```
|
|
2006
|
-
|
|
2007
|
-
#### `frameAt()`
|
|
2008
|
-
|
|
2009
|
-
```ts
|
|
2010
|
-
frameAt(coordinate: ProductSkinSurfaceCoordinate, tangentHint?: Vec3): SurfaceFrame
|
|
2011
|
-
```
|
|
2012
|
-
|
|
2013
|
-
**`SurfaceFrame`**: `point: Vec3`, `normal: Vec3`, `tangentAlong: Vec3`, `tangentAcross: Vec3`, `matrix: Mat4`, `carrier: string`, `representation: SurfaceCarrierKind | string`, `coordinate: SurfaceCoordinate`
|
|
2014
|
-
|
|
2015
|
-
#### `bounds()`
|
|
2016
|
-
|
|
2017
|
-
```ts
|
|
2018
|
-
bounds(): SurfaceBounds
|
|
2019
|
-
```
|
|
2020
|
-
|
|
2021
|
-
**`SurfaceBounds`**: `u?: [ number, number ]`, `v?: [ number, number ]`, `angle?: [ number, number ]`, `z?: [ number, number ]`, `x?: [ number, number ]`, `y?: [ number, number ]`
|
|
2022
|
-
|
|
2023
|
-
#### `offset()`
|
|
2024
|
-
|
|
2025
|
-
```ts
|
|
2026
|
-
offset(distance: number): ProductSkinCarrier
|
|
2027
|
-
```
|
|
2028
|
-
|
|
2029
|
-
#### `mirrorCoordinate()`
|
|
2030
|
-
|
|
2031
|
-
```ts
|
|
2032
|
-
mirrorCoordinate(coordinate: ProductSkinSurfaceCoordinate): ProductSkinSurfaceCoordinate
|
|
2033
|
-
```
|
|
2034
|
-
|
|
2035
|
-
### `SurfacePath`
|
|
2036
|
-
|
|
2037
|
-
**Properties:**
|
|
2038
|
-
|
|
2039
|
-
| Property | Type | Description |
|
|
2040
|
-
|----------|------|-------------|
|
|
2041
|
-
| `carrier` | `CarrierSurface<C>` | — |
|
|
2042
|
-
| `points` | `C[]` | — |
|
|
2043
|
-
| `closedValue` | `boolean` | — |
|
|
2044
|
-
|
|
2045
|
-
**Methods:**
|
|
2046
|
-
|
|
2047
|
-
#### `closed()`
|
|
2048
|
-
|
|
2049
|
-
```ts
|
|
2050
|
-
closed(): SurfacePath<C>
|
|
2051
|
-
```
|
|
2052
|
-
|
|
2053
|
-
#### `mirror()`
|
|
2054
|
-
|
|
2055
|
-
```ts
|
|
2056
|
-
mirror(): SurfacePath<C>
|
|
2057
|
-
```
|
|
2058
|
-
|
|
2059
|
-
#### `coordinateAt()`
|
|
2060
|
-
|
|
2061
|
-
```ts
|
|
2062
|
-
coordinateAt(t: number): C
|
|
2063
|
-
```
|
|
2064
|
-
|
|
2065
|
-
#### `sample()`
|
|
2066
|
-
|
|
2067
|
-
```ts
|
|
2068
|
-
sample(count?: number): SurfacePathSample<C>[]
|
|
2069
|
-
```
|
|
2070
|
-
|
|
2071
|
-
#### `length()`
|
|
2072
|
-
|
|
2073
|
-
```ts
|
|
2074
|
-
length(samples?: number): number
|
|
2075
|
-
```
|
|
2076
|
-
|
|
2077
|
-
### `SurfacePathBuilder`
|
|
2078
|
-
|
|
2079
|
-
**Properties:**
|
|
2080
|
-
|
|
2081
|
-
| Property | Type | Description |
|
|
2082
|
-
|----------|------|-------------|
|
|
2083
|
-
| `carrier` | `CarrierSurface<C>` | — |
|
|
2084
|
-
|
|
2085
|
-
**Methods:**
|
|
2086
|
-
|
|
2087
|
-
#### `from()`
|
|
2088
|
-
|
|
2089
|
-
```ts
|
|
2090
|
-
from(coordinate: C): this
|
|
2091
|
-
```
|
|
2092
|
-
|
|
2093
|
-
#### `through()`
|
|
2094
|
-
|
|
2095
|
-
```ts
|
|
2096
|
-
through(coordinate: C): this
|
|
2097
|
-
```
|
|
2098
|
-
|
|
2099
|
-
#### `to()`
|
|
2100
|
-
|
|
2101
|
-
```ts
|
|
2102
|
-
to(coordinate: C): this
|
|
2103
|
-
```
|
|
2104
|
-
|
|
2105
|
-
#### `around()`
|
|
2106
|
-
|
|
2107
|
-
```ts
|
|
2108
|
-
around(input: { z: number; fromAngle: number; toAngle: number; offset?: number; }): this
|
|
2109
|
-
```
|
|
2110
|
-
|
|
2111
|
-
#### `closed()`
|
|
2112
|
-
|
|
2113
|
-
```ts
|
|
2114
|
-
closed(): this
|
|
2115
|
-
```
|
|
2116
|
-
|
|
2117
|
-
#### `mirror()`
|
|
2118
|
-
|
|
2119
|
-
```ts
|
|
2120
|
-
mirror(): SurfacePath<C>
|
|
2121
|
-
```
|
|
2122
|
-
|
|
2123
|
-
#### `build()`
|
|
2124
|
-
|
|
2125
|
-
```ts
|
|
2126
|
-
build(): SurfacePath<C>
|
|
2127
|
-
```
|
|
2128
|
-
|
|
2129
|
-
#### `sample()`
|
|
2130
|
-
|
|
2131
|
-
```ts
|
|
2132
|
-
sample(count?: number): SurfacePathSample<C>[]
|
|
2133
|
-
```
|
|
2134
|
-
|
|
2135
|
-
### `SurfaceBand`
|
|
1028
|
+
### `SurfaceBand`
|
|
2136
1029
|
|
|
2137
1030
|
**Properties:**
|
|
2138
1031
|
|
|
@@ -2144,34 +1037,19 @@ sample(count?: number): SurfacePathSample<C>[]
|
|
|
2144
1037
|
|
|
2145
1038
|
**Methods:**
|
|
2146
1039
|
|
|
2147
|
-
#### `
|
|
2148
|
-
|
|
2149
|
-
```ts
|
|
2150
|
-
widthAt(t: number): number
|
|
2151
|
-
```
|
|
2152
|
-
|
|
2153
|
-
#### `boundaries()`
|
|
2154
|
-
|
|
2155
|
-
```ts
|
|
2156
|
-
boundaries(samples?: number): SurfaceBandBoundarySample[]
|
|
2157
|
-
```
|
|
2158
|
-
|
|
2159
|
-
#### `withHole()` — Return a new band with a named member-local rounded-slot hole region recorded as inspectable intent.
|
|
2160
|
-
|
|
2161
|
-
```ts
|
|
2162
|
-
withHole(name: string, input: SurfaceBandHoleInput): SurfaceBand<C>
|
|
2163
|
-
```
|
|
1040
|
+
#### `withHole(name: string, input: SurfaceBandHoleInput): SurfaceBand<C>` — Return a new band with a named member-local rounded-slot hole region recorded as inspectable intent.
|
|
2164
1041
|
|
|
2165
1042
|
`SurfaceBandHoleInput`: `{ length: number, width: number, along?: number, across?: number }`
|
|
2166
1043
|
|
|
2167
|
-
#### `holes()` — Resolve recorded hole regions into member-local across/along loops.
|
|
1044
|
+
#### `holes(): SurfaceBandHoleRegion[]` — Resolve recorded hole regions into member-local across/along loops.
|
|
2168
1045
|
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
```
|
|
1046
|
+
- `widthAt(t: number): number`
|
|
1047
|
+
- `boundaries(samples?: number): SurfaceBandBoundarySample[]`
|
|
2172
1048
|
|
|
2173
1049
|
### `SurfaceBodyBuilder`
|
|
2174
1050
|
|
|
1051
|
+
Builder for a named surface-member body. Owns named members — `band()` or `plate()` — and the joins between them. Features (slots, cutouts, lips, cups, ribs) attach to a member's local coordinate system before lowering; this is not a global boolean recipe.
|
|
1052
|
+
|
|
2175
1053
|
**Properties:**
|
|
2176
1054
|
|
|
2177
1055
|
| Property | Type | Description |
|
|
@@ -2180,215 +1058,65 @@ holes(): SurfaceBandHoleRegion[]
|
|
|
2180
1058
|
|
|
2181
1059
|
**Methods:**
|
|
2182
1060
|
|
|
2183
|
-
#### `
|
|
2184
|
-
|
|
2185
|
-
```ts
|
|
2186
|
-
carrier(carrier: CarrierSurface): this
|
|
2187
|
-
```
|
|
2188
|
-
|
|
2189
|
-
`CarrierSurface`: `{ name: string, kind: SurfaceCarrierKind }`
|
|
2190
|
-
|
|
2191
|
-
#### `member()`
|
|
2192
|
-
|
|
2193
|
-
```ts
|
|
2194
|
-
member(name: string): SurfaceMemberBuilder
|
|
2195
|
-
```
|
|
2196
|
-
|
|
2197
|
-
#### `join()`
|
|
1061
|
+
#### `join(from: string, to: string | string[]): SurfaceJoinBuilder` — Declare a join between named members. Only a limited join set lowers to real geometry: close endpoint pairs, selected named-anchor pairs (`.betweenAnchors()`), and sampled band/plate landing pads. Farther, missing-anchor, or ambiguous joins remain diagnostic-only intent — decompose the design into supported joins instead of expecting a fallback.
|
|
2198
1062
|
|
|
2199
|
-
|
|
2200
|
-
join(from: string, to: string | string[]): SurfaceJoinBuilder
|
|
2201
|
-
```
|
|
1063
|
+
#### `autoJoinAtSharedAnchors(): this` — Lower only unambiguous shared-endpoint pairs (exactly two members sharing a point) into junction geometry. Shared points with more than two members produce a warning diagnostic — declare explicit `.join(...)` relationships instead.
|
|
2202
1064
|
|
|
2203
|
-
#### `
|
|
2204
|
-
|
|
2205
|
-
```ts
|
|
2206
|
-
autoJoinAtSharedAnchors(): this
|
|
2207
|
-
```
|
|
1065
|
+
#### `build(): Shape | ShapeGroup` — Build and return only the member + junction geometry. Use `buildWithDiagnostics()` for the member graph and diagnostic codes.
|
|
2208
1066
|
|
|
2209
|
-
|
|
1067
|
+
- `carrier(carrier: CarrierSurface): this`
|
|
1068
|
+
- `member(name: string): SurfaceMemberBuilder`
|
|
2210
1069
|
|
|
2211
|
-
|
|
2212
|
-
build(): Shape | ShapeGroup
|
|
2213
|
-
```
|
|
1070
|
+
`CarrierSurface`: `{ name: string, kind: SurfaceCarrierKind }`
|
|
2214
1071
|
|
|
2215
1072
|
### `SurfaceMemberBuilder`
|
|
2216
1073
|
|
|
2217
|
-
#### `
|
|
2218
|
-
|
|
2219
|
-
```ts
|
|
2220
|
-
plate(): this
|
|
2221
|
-
```
|
|
2222
|
-
|
|
2223
|
-
#### `band()`
|
|
2224
|
-
|
|
2225
|
-
```ts
|
|
2226
|
-
band(): this
|
|
2227
|
-
```
|
|
2228
|
-
|
|
2229
|
-
#### `at()`
|
|
2230
|
-
|
|
2231
|
-
```ts
|
|
2232
|
-
at(anchor: SurfaceAnchor<C>): this
|
|
2233
|
-
```
|
|
1074
|
+
#### `anchorAt(name: string, coordinate: C | SurfaceAnchor<C>): this` — Add a named anchor at a carrier surface coordinate for explicit member joins.
|
|
2234
1075
|
|
|
2235
1076
|
`SurfaceAnchor`: `{ carrier: CarrierSurface<C>, coordinate: C }`
|
|
2236
1077
|
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
size(width: number, height: number): this
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
1078
|
+
- `plate(): this`
|
|
1079
|
+
- `band(): this`
|
|
1080
|
+
- `at(anchor: SurfaceAnchor<C>): this`
|
|
1081
|
+
- `size(width: number, height: number): this`
|
|
1082
|
+
- `path(path: SurfacePath<C> | SurfacePathBuilder<C>): this`
|
|
1083
|
+
- `section(section: MemberSectionInput): this`
|
|
1084
|
+
- `cap(style: SurfaceBandCap): this`
|
|
1085
|
+
- `slot(name: string, feature: MemberFeature | RoundedSlotBuilder): this`
|
|
1086
|
+
- `cutout(name: string, feature: MemberFeature | RoundedSlotBuilder): this`
|
|
1087
|
+
- `counterbore(name: string, feature: MemberFeature | CounterboreBuilder): this`
|
|
1088
|
+
- `features(features: MemberFeature | MemberFeature[]): this`
|
|
1089
|
+
- `profile(name: string, options?: { depth?: number; height?: number; }): this`
|
|
1090
|
+
- `mirrorOf(memberName: string): SurfaceBodyBuilder`
|
|
1091
|
+
- `member(name: string): SurfaceMemberBuilder`
|
|
1092
|
+
- `join(from: string, to: string | string[]): SurfaceJoinBuilder`
|
|
1093
|
+
- `autoJoinAtSharedAnchors(): SurfaceBodyBuilder`
|
|
1094
|
+
- `build(): Shape | ShapeGroup`
|
|
2254
1095
|
|
|
2255
1096
|
**`MemberSectionInput`**: `width?: number`, `thickness: number`, `edgeRadius?: number`, `direction?: MemberOutwardDirection`, `material?: ProductMaterial`, `stations?: MemberSectionStation[]`
|
|
2256
1097
|
|
|
2257
1098
|
`MemberSectionStation`: `{ t: number, width?: number, thickness?: number }`
|
|
2258
1099
|
|
|
2259
|
-
#### `cap()`
|
|
2260
|
-
|
|
2261
|
-
```ts
|
|
2262
|
-
cap(style: SurfaceBandCap): this
|
|
2263
|
-
```
|
|
2264
|
-
|
|
2265
|
-
#### [`slot()`](/docs/sketch#slot)
|
|
2266
|
-
|
|
2267
|
-
```ts
|
|
2268
|
-
slot(name: string, feature: MemberFeature | RoundedSlotBuilder): this
|
|
2269
|
-
```
|
|
2270
|
-
|
|
2271
1100
|
**`MemberFeature`**: `type: MemberFeatureType`, `name?: string`, `length?: number`, `width?: number`, `diameter?: number`, `counterboreDiameter?: number`, `clearanceDiameter?: number`, `height?: number`, `depth?: number`, `count?: number`, `along?: number`, `across?: number`, `verticalTravel?: number`
|
|
2272
1101
|
|
|
2273
|
-
#### `cutout()`
|
|
2274
|
-
|
|
2275
|
-
```ts
|
|
2276
|
-
cutout(name: string, feature: MemberFeature | RoundedSlotBuilder): this
|
|
2277
|
-
```
|
|
2278
|
-
|
|
2279
|
-
#### `counterbore()`
|
|
2280
|
-
|
|
2281
|
-
```ts
|
|
2282
|
-
counterbore(name: string, feature: MemberFeature | CounterboreBuilder): this
|
|
2283
|
-
```
|
|
2284
|
-
|
|
2285
|
-
#### `anchorAt()` — Add a named anchor at a carrier surface coordinate for explicit member joins.
|
|
2286
|
-
|
|
2287
|
-
```ts
|
|
2288
|
-
anchorAt(name: string, coordinate: C | SurfaceAnchor<C>): this
|
|
2289
|
-
```
|
|
2290
|
-
|
|
2291
|
-
#### `features()`
|
|
2292
|
-
|
|
2293
|
-
```ts
|
|
2294
|
-
features(features: MemberFeature | MemberFeature[]): this
|
|
2295
|
-
```
|
|
2296
|
-
|
|
2297
|
-
#### `profile()`
|
|
2298
|
-
|
|
2299
|
-
```ts
|
|
2300
|
-
profile(name: string, options?: { depth?: number; height?: number; }): this
|
|
2301
|
-
```
|
|
2302
|
-
|
|
2303
|
-
#### `mirrorOf()`
|
|
2304
|
-
|
|
2305
|
-
```ts
|
|
2306
|
-
mirrorOf(memberName: string): SurfaceBodyBuilder
|
|
2307
|
-
```
|
|
2308
|
-
|
|
2309
|
-
#### `member()`
|
|
2310
|
-
|
|
2311
|
-
```ts
|
|
2312
|
-
member(name: string): SurfaceMemberBuilder
|
|
2313
|
-
```
|
|
2314
|
-
|
|
2315
|
-
#### `join()`
|
|
2316
|
-
|
|
2317
|
-
```ts
|
|
2318
|
-
join(from: string, to: string | string[]): SurfaceJoinBuilder
|
|
2319
|
-
```
|
|
2320
|
-
|
|
2321
|
-
#### `autoJoinAtSharedAnchors()`
|
|
2322
|
-
|
|
2323
|
-
```ts
|
|
2324
|
-
autoJoinAtSharedAnchors(): SurfaceBodyBuilder
|
|
2325
|
-
```
|
|
2326
|
-
|
|
2327
|
-
#### `build()`
|
|
2328
|
-
|
|
2329
|
-
```ts
|
|
2330
|
-
build(): Shape | ShapeGroup
|
|
2331
|
-
```
|
|
2332
|
-
|
|
2333
1102
|
### `SurfaceJoinBuilder`
|
|
2334
1103
|
|
|
2335
|
-
#### `betweenAnchors()` — Select named anchors on the source and target members before lowering this join.
|
|
2336
|
-
|
|
2337
|
-
```ts
|
|
2338
|
-
betweenAnchors(fromAnchor: string, toAnchor: string): this
|
|
2339
|
-
```
|
|
2340
|
-
|
|
2341
|
-
#### `blend()`
|
|
1104
|
+
#### `betweenAnchors(fromAnchor: string, toAnchor: string): this` — Select named anchors on the source and target members before lowering this join.
|
|
2342
1105
|
|
|
2343
|
-
|
|
2344
|
-
blend(input?: { radius?: number; style?: string; priority?: number; continuity?: string; }): SurfaceBodyBuilder
|
|
2345
|
-
```
|
|
1106
|
+
- `blend(input?: { radius?: number; style?: string; priority?: number; continuity?: string; }): SurfaceBodyBuilder`
|
|
2346
1107
|
|
|
2347
1108
|
### `CounterboreBuilder`
|
|
2348
1109
|
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
at(input: { along?: number; across?: number; z?: number; }): this
|
|
2353
|
-
```
|
|
2354
|
-
|
|
2355
|
-
#### `named()`
|
|
2356
|
-
|
|
2357
|
-
```ts
|
|
2358
|
-
named(name: string): MemberFeature
|
|
2359
|
-
```
|
|
2360
|
-
|
|
2361
|
-
#### `toFeature()`
|
|
2362
|
-
|
|
2363
|
-
```ts
|
|
2364
|
-
toFeature(name?: string): MemberFeature
|
|
2365
|
-
```
|
|
1110
|
+
- `at(input: { along?: number; across?: number; z?: number; }): this`
|
|
1111
|
+
- `named(name: string): MemberFeature`
|
|
1112
|
+
- `toFeature(name?: string): MemberFeature`
|
|
2366
1113
|
|
|
2367
1114
|
### `RoundedSlotBuilder`
|
|
2368
1115
|
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
```
|
|
2374
|
-
|
|
2375
|
-
#### `at()`
|
|
2376
|
-
|
|
2377
|
-
```ts
|
|
2378
|
-
at(input: { along?: number; across?: number; z?: number; }): this
|
|
2379
|
-
```
|
|
2380
|
-
|
|
2381
|
-
#### `named()`
|
|
2382
|
-
|
|
2383
|
-
```ts
|
|
2384
|
-
named(name: string): MemberFeature
|
|
2385
|
-
```
|
|
2386
|
-
|
|
2387
|
-
#### `toFeature()`
|
|
2388
|
-
|
|
2389
|
-
```ts
|
|
2390
|
-
toFeature(name?: string): MemberFeature
|
|
2391
|
-
```
|
|
1116
|
+
- `verticalTravel(value: number): this`
|
|
1117
|
+
- `at(input: { along?: number; across?: number; z?: number; }): this`
|
|
1118
|
+
- `named(name: string): MemberFeature`
|
|
1119
|
+
- `toFeature(name?: string): MemberFeature`
|
|
2392
1120
|
|
|
2393
1121
|
---
|
|
2394
1122
|
|
|
@@ -2400,18 +1128,7 @@ Canonical exact/smooth 3D curve constructors.
|
|
|
2400
1128
|
|
|
2401
1129
|
`Curve.*` is the public home for reference curves and route centerlines that feed `sweep`, `variableSweep`, route visualization, and future path consumers. Standalone 3D curve constructors have been collapsed into this namespace.
|
|
2402
1130
|
|
|
2403
|
-
|
|
2404
|
-
- `BlendG2(start: CurveBlendG2Endpoint, end: CurveBlendG2Endpoint): NurbsCurve3D` — Create an exact G2 blend curve between two directed endpoints. This is the curvature-aware companion to `Curve.Blend()`. It returns a degree-5 non-rational `NurbsCurve3D` that matches endpoint position, tangent direction, and optional curvature/second-derivative vectors.
|
|
2405
|
-
- `Arc(options: CurveArcOptions): NurbsCurve3D` — Create an exact circular 3D arc from start, end, and start tangent. The returned curve is a rational quadratic `NurbsCurve3D`, split into stable spans when needed, so it can feed `sweep` without sampling the authoring intent away.
|
|
2406
|
-
- `Line(start: Vec3, end: Vec3): NurbsCurve3D` — Create an exact straight 3D NURBS line segment.
|
|
2407
|
-
- `Polyline(points: Vec3[]): Vec3[]` — Create a polyline path as cloned 3D points. Polylines are exact as route/path input to `sweep`. Use `Curve.Route` when the centerline needs bend and endpoint-frame metadata.
|
|
2408
|
-
- `Spline(points: Vec3[], options?: Spline3DOptions): Curve3D` — Create a smooth Catmull-Rom spline path. This is a smooth sampled curve object. Use `Curve.Nurbs` when the path must preserve exact control-point and knot data.
|
|
2409
|
-
- `Nurbs(points: Vec3[], options?: NurbsCurve3DOptions): NurbsCurve3D` — Create an exact NURBS 3D curve from control points, weights, knots, and degree.
|
|
2410
|
-
- `Fit(points: Vec3[], options?: CurveFitOptions): NurbsCurve3D` — Fit a non-rational NURBS curve that interpolates every input point. This is global B-spline interpolation, not approximate curve reduction: ForgeCAD computes chord-length parameters, averaged clamped knots, solves the control points, then verifies the interpolation residual against `tolerance`.
|
|
2411
|
-
- `Trim<T extends CurveTrimInput>(curve: T, start: number, end: number): CurveTrimOutput<T>` — Extract an exact curve segment from normalized parameter `start` to `end`. `NurbsCurve3D` inputs are trimmed with exact knot insertion/subdomain extraction. Polyline point arrays are trimmed by arclength over their exact line segments. Sampled `Curve3D` splines are rejected until ForgeCAD has a tolerance-controlled rebuild path.
|
|
2412
|
-
- `Reverse<T extends CurveTrimInput>(curve: T): CurveTrimOutput<T>` — Reverse an exact curve without changing its geometry. `NurbsCurve3D` inputs reverse control points, weights, and knots. Polyline point arrays are cloned and reversed. Sampled `Curve3D` splines are rejected until ForgeCAD has a tolerance-controlled rebuild path.
|
|
2413
|
-
- `Route: typeof Route3D` — Build analytic 3D line/arc routes for sweeps. `Curve.Route.fromPolyline()` is the canonical route API. It returns a `Route3D` value object, preserving exact route segments, named port frames, and the lowerable `route3d` sweep compile plan.
|
|
2414
|
-
- `Helix: { path(options: HelixOptions): CurveHelixPath; coil: CurveHelixCoil; }` — Build helical paths and swept coils. `Curve.Helix` is the canonical namespace for helical paths and coils. It uses the same sweep-based lowering as other curve paths.
|
|
1131
|
+
Members (full entries under [Curves & Surfacing](#curves-surfacing)): `Curve.Blend`, `Curve.BlendG2`, `Curve.Arc`, `Curve.Line`, `Curve.Nurbs`, `Curve.Fit`, `Curve.Trim`, `Curve.Reverse`, `Curve.Route`, `Curve.Helix`.
|
|
2415
1132
|
|
|
2416
1133
|
### `Surface`
|
|
2417
1134
|
|
|
@@ -2420,9 +1137,30 @@ Canonical exact/smooth 3D curve constructors.
|
|
|
2420
1137
|
- `Cone(options: SurfaceConeOptions): Shape` — Create a finite analytic conical or frustum sheet, optionally bounded by start/end angles.
|
|
2421
1138
|
- `Sphere(options: SurfaceSphereOptions): Shape` — Create a finite analytic spherical sheet bounded by longitude and latitude ranges.
|
|
2422
1139
|
- `Torus(options: SurfaceTorusOptions): Shape` — Create a finite analytic torus sheet bounded by major and tube angle ranges.
|
|
2423
|
-
- `Nurbs(controlGrid: Vec3[][], options?: NurbsSurfaceOptions): Shape`
|
|
1140
|
+
- `Nurbs(controlGrid: Vec3[][], options?: NurbsSurfaceOptions): Shape` — Create an exact NURBS surface from a grid of control points.
|
|
1141
|
+
|
|
1142
|
+
The control grid is indexed as `controlGrid[u][v]` — each row is a curve in the V direction, and columns trace curves in the U direction. With default options this builds a bicubic non-rational B-spline sheet with uniform clamped knots; `NurbsSurfaceOptions` controls degrees, weights, knots, trim loops, tessellation, domain, and an optional `thickness` to return a thin solid instead of an open sheet.
|
|
1143
|
+
|
|
1144
|
+
```js
|
|
1145
|
+
// Simple 4×4 control grid — a gently curved surface
|
|
1146
|
+
const grid = [
|
|
1147
|
+
[[0,0,0], [10,0,2], [20,0,2], [30,0,0]],
|
|
1148
|
+
[[0,10,1], [10,10,5], [20,10,5], [30,10,1]],
|
|
1149
|
+
[[0,20,1], [10,20,5], [20,20,5], [30,20,1]],
|
|
1150
|
+
[[0,30,0], [10,30,2], [20,30,2], [30,30,0]],
|
|
1151
|
+
];
|
|
1152
|
+
const sheet = Surface.Nurbs(grid);
|
|
1153
|
+
const panel = Surface.Nurbs(grid, { thickness: 2 });
|
|
1154
|
+
```
|
|
2424
1155
|
- `Ruled(curveA: ExactCurveInput, curveB: ExactCurveInput, options?: SurfaceCommonOptions): Shape`
|
|
2425
|
-
- `Patch(curves: { bottom: ExactCurveInput; top: ExactCurveInput; left: ExactCurveInput; right: ExactCurveInput; }, options?: SurfacePatchOptions): Shape`
|
|
1156
|
+
- `Patch(curves: { bottom: ExactCurveInput; top: ExactCurveInput; left: ExactCurveInput; right: ExactCurveInput; }, options?: SurfacePatchOptions): Shape` — Create a smooth open surface sheet from 4 boundary curves (Coons patch).
|
|
1157
|
+
|
|
1158
|
+
The four curves form the boundary of a quadrilateral patch and should meet at corners (small gaps are tolerated). Boundaries are exact by default: pass `NurbsCurve3D` values or `Shape.edge()` refs, or set `{ approximate: true }` to accept sampled `Curve3D`/`Vec3[]` boundaries. The result is an open sheet — call `.thicken(t)` for a thin solid.
|
|
1159
|
+
|
|
1160
|
+
```js
|
|
1161
|
+
const sheet = Surface.Patch({ bottom, top, left, right });
|
|
1162
|
+
const panel = Surface.Patch({ bottom, top, left, right }).thicken(1.5);
|
|
1163
|
+
```
|
|
2426
1164
|
- `Boundary(input: SurfaceBoundaryInput): Shape`
|
|
2427
1165
|
- `Fill(input: SurfaceFillInput): Shape`
|
|
2428
1166
|
- `Sew(shapes: Shape[], options?: { tolerance?: number; }): Shape`
|
|
@@ -2431,7 +1169,6 @@ Canonical exact/smooth 3D curve constructors.
|
|
|
2431
1169
|
- `Trim(shape: Shape, tool: Shape | SurfacePlaneOp): Shape`
|
|
2432
1170
|
- `Split(shape: Shape, tool: Shape | SurfacePlaneOp): [ Shape, Shape ]`
|
|
2433
1171
|
- `Match(shape: Shape, options: { edge: "u0" | "u1" | "v0" | "v1"; target: EdgeRef; continuity?: SurfaceContinuity; }): Shape`
|
|
2434
|
-
- `MatchEdge(shape: Shape, options: { edge: "u0" | "u1" | "v0" | "v1"; target: EdgeRef; continuity?: SurfaceContinuity; }): Shape`
|
|
2435
1172
|
|
|
2436
1173
|
### `Blend`
|
|
2437
1174
|
|
|
@@ -2450,29 +1187,40 @@ Canonical exact/smooth 3D curve constructors.
|
|
|
2450
1187
|
|
|
2451
1188
|
- `skin(name: string): ProductSkinBuilder` — Start a named product skin builder.
|
|
2452
1189
|
- `station(name: string): ProductStationBuilder` — Start a named cross-section station for Product.skin(...).stations(...).
|
|
2453
|
-
- `rail: {
|
|
2454
|
-
- `profiles: { ... }` —
|
|
1190
|
+
- `rail: { ... }` — Namespaced rail builders for product skin guide rails and handle spines.
|
|
1191
|
+
- `profiles: { ... }` — Product profile helper namespace: oval, superEllipse, roundedRect, and circle — for stations, panels, trims, and openings.
|
|
2455
1192
|
- `materials: { ... }` — Namespaced product material presets for molded plastic, rubber, metal, and transparent parts.
|
|
2456
1193
|
- `applyMaterial(shape: Shape, preset: ProductMaterial | undefined): Shape` — Apply a product material preset to a Shape.
|
|
2457
1194
|
- `scenePreset(name: ProductScenePreset): void` — Apply an opinionated scene preset for product review renders.
|
|
2458
|
-
- `ovalProfile(width: number, depth: number, options?: ProductProfileOptions): Sketch` — Create a centered oval profile from full width/depth dimensions.
|
|
2459
|
-
- `roundedRectProfile(width: number, depth: number, radius: number): Sketch` — Create a centered rounded-rectangle profile.
|
|
2460
|
-
- `circleProfile(diameter: number, options?: ProductProfileOptions): Sketch` — Create a centered circular profile from full diameter.
|
|
2461
|
-
- `superEllipseProfile(width: number, depth: number, options?: ProductSuperEllipseOptions): Sketch` — Create a centered superellipse profile for soft-square product sections.
|
|
2462
1195
|
- `profileSize(sketch: Sketch): { width: number; depth: number; }` — Measure the width and depth of a 2D profile sketch.
|
|
2463
1196
|
- `describeProfile(sketch: Sketch, kind?: ProductProfileKind, radius?: number): ProductProfileDescriptor` — Describe a custom sketch as a product profile.
|
|
2464
1197
|
- `scaleProfileTo(sketch: Sketch, width: number, depth: number): Sketch` — Scale an existing profile sketch to a target width/depth.
|
|
2465
1198
|
- `ref(skin: ProductSkin, query: ProductSkinRefQuery): ProductSurfaceRef` — Create an ad-hoc ProductSurfaceRef from a skin and side/u/v query.
|
|
2466
|
-
- `surface(skin: ProductSkin, side: ProductSkinSide): ProductSurfaceBuilder` — Create a fluent surface helper for refs and conformal features on one side of a skin.
|
|
1199
|
+
- `surface(skin: ProductSkin, side: ProductSkinSide): ProductSurfaceBuilder` — Create a fluent surface helper for refs and conformal features on one side of a skin.
|
|
1200
|
+
|
|
1201
|
+
Equivalent to skin.surface(side), useful when writing in Product.* namespace style.
|
|
2467
1202
|
- `panel(name: string): ProductPanelBuilder` — Start a panel feature builder.
|
|
2468
|
-
- `ribbon(name: string): ProductRibbonBuilder` — Start a conformal ribbon/trim builder for details that should bend with a ProductSkin.
|
|
2469
|
-
|
|
2470
|
-
|
|
1203
|
+
- `ribbon(name: string): ProductRibbonBuilder` — Start a conformal ribbon/trim builder for details that should bend with a ProductSkin.
|
|
1204
|
+
|
|
1205
|
+
Call .on(skin, points) for side/u/v sampling or .fromRefs(points) for explicit surface refs, then configure width, thickness, offset, sampling, material, and color before build().
|
|
2471
1206
|
- `place(detail: Shape | ShapeGroup, ref: ProductRefInput, options?: ProductAttachOptions): Shape | ShapeGroup` — Place a shape or group on a ProductSurfaceRef.
|
|
2472
1207
|
- `landing(name: string, radius?: number, material?: ProductMaterial): Shape` — Small blended landing volume for manual structural bridges and connection proofs.
|
|
2473
1208
|
|
|
2474
1209
|
### `Carrier`
|
|
2475
1210
|
|
|
1211
|
+
Factory for carrier surfaces — the coordinate-and-frame owners that surface members (`SurfaceBody`) live on.
|
|
1212
|
+
|
|
1213
|
+
A carrier owns surface-local coordinates and 3D frames; members and paths are authored in carrier coordinates, never in raw Cartesian math. Cylinder coordinates are `{ angle, z }` with `angle` in degrees — paths handle seam wrapping, so never compute positions with trig. `clearance()`/`offset()` lift geometry off the nominal surface. A ProductSkin carrier path stays on one side (`left`/`right`/`top`/`bottom`); for multi-side detail, split into one member per side and join them at the matching side-local coordinates from `sideTransition()` / `sideTransitionChain()` / `sideRoute()`.
|
|
1214
|
+
|
|
1215
|
+
```ts
|
|
1216
|
+
// Bottle-cage arm: a curved band on a cylinder, authored in degrees + mm
|
|
1217
|
+
const bottle = Carrier.cylinder('bottle').diameter(74).height(170).clearance(1.5);
|
|
1218
|
+
const arm = bottle.path()
|
|
1219
|
+
.from({ angle: -145, z: 18 })
|
|
1220
|
+
.through({ angle: -80, z: 72 })
|
|
1221
|
+
.to({ angle: -34, z: 112 });
|
|
1222
|
+
```
|
|
1223
|
+
|
|
2476
1224
|
- `cylinder(name: string): CylinderCarrier` — Create an analytic cylinder carrier for bottles, limbs, tubes, guards, and cuffs.
|
|
2477
1225
|
- `plane(name: string): PlaneCarrier` — Create an analytic plane carrier for plates and local flat construction surfaces.
|
|
2478
1226
|
- `productSkin(skin: ProductSkin): ProductSkinCarrier` — Adapt an existing ProductSkin into the general surface-member carrier protocol.
|
|
@@ -2480,17 +1228,48 @@ Canonical exact/smooth 3D curve constructors.
|
|
|
2480
1228
|
### `SurfaceMembers`
|
|
2481
1229
|
|
|
2482
1230
|
- `Body(name: string): SurfaceBodyBuilder` — Start a surface-member body builder for straps, inlays, guards, braces, cuffs, and similar physical members that live on a carrier surface.
|
|
1231
|
+
|
|
1232
|
+
```js
|
|
1233
|
+
const carrier = Carrier.cylinder('guard-envelope').diameter(84).height(36).clearance(2);
|
|
1234
|
+
const guard = SurfaceBody('simple-guard')
|
|
1235
|
+
.carrier(carrier)
|
|
1236
|
+
.member('left-strut')
|
|
1237
|
+
.band()
|
|
1238
|
+
.path(carrier.path().from({ angle: -132, z: 6 }).to({ angle: -58, z: 18 }))
|
|
1239
|
+
.section({ width: 5.5, thickness: 2.8, edgeRadius: 0.6 })
|
|
1240
|
+
.member('right-strut')
|
|
1241
|
+
.mirrorOf('left-strut')
|
|
1242
|
+
.member('front-hoop')
|
|
1243
|
+
.band()
|
|
1244
|
+
.path(carrier.path().around({ z: 18, fromAngle: -58, toAngle: 58 }))
|
|
1245
|
+
.section({ width: 6.2, thickness: 3, edgeRadius: 0.7 })
|
|
1246
|
+
.join('left-strut', 'front-hoop').blend({ radius: 3.2 })
|
|
1247
|
+
.join('right-strut', 'front-hoop').blend({ radius: 3.2 })
|
|
1248
|
+
.build();
|
|
1249
|
+
```
|
|
2483
1250
|
- `Band: typeof SurfaceBand`
|
|
2484
1251
|
- `band<C extends SurfaceCoordinate>(path: SurfacePath<C> | SurfacePathBuilder<C>, width: WidthProfile, cap?: SurfaceBandCap): SurfaceBand<C>`
|
|
1252
|
+
- `roundedSlot(input: { length: number; width: number; }): RoundedSlotBuilder` — Create a rounded member-local slot feature for `SurfaceMemberBuilder.slot()`/`.cutout()`.
|
|
2485
1253
|
|
|
2486
|
-
|
|
1254
|
+
Returns a fluent `RoundedSlotBuilder`: chain `.verticalTravel(mm)` to extend the slot for vertical bottle-drop style insertion (travel is summed into the slot length) and `.at({ along, across })` (or `{ z }`) to position it in member-local coordinates.
|
|
2487
1255
|
|
|
2488
|
-
|
|
1256
|
+
```js
|
|
1257
|
+
const arm = body.member('arm', armPath)
|
|
1258
|
+
.slot('upper-mount-slot', SurfaceMembers.roundedSlot({ length: 12, width: 5.7 }).verticalTravel(6).at({ z: 82 }));
|
|
1259
|
+
```
|
|
1260
|
+
- `counterbore(input: { diameter: number; clearanceDiameter: number; depth: number; }): CounterboreBuilder` — Create a cylindrical member-local counterbore feature for `SurfaceMemberBuilder.counterbore()`.
|
|
2489
1261
|
|
|
2490
|
-
|
|
1262
|
+
`diameter` is the counterbore pocket diameter and must be larger than `clearanceDiameter`, the through-hole for the fastener shank. Chain `.at({ along, across })` (or `{ z }`) to position it in member-local coordinates.
|
|
2491
1263
|
|
|
2492
|
-
|
|
1264
|
+
```js
|
|
1265
|
+
const strap = body.member('strap', strapPath)
|
|
1266
|
+
.counterbore('head-pocket', SurfaceMembers.counterbore({ diameter: 9.8, clearanceDiameter: 5.7, depth: 3 }).at({ z: 58 }));
|
|
1267
|
+
```
|
|
1268
|
+
- `ribs(input: { count: number; height: number; }): MemberFeature` — Create a repeated-rib stiffening feature for `SurfaceMemberBuilder.features()`.
|
|
2493
1269
|
|
|
2494
|
-
|
|
1270
|
+
Ribs belong to the surface member and follow its carrier-surface lowering; `count` ribs of the given `height` are distributed along the member.
|
|
2495
1271
|
|
|
2496
|
-
|
|
1272
|
+
```js
|
|
1273
|
+
const grip = body.member('grip', gripPath)
|
|
1274
|
+
.features(SurfaceMembers.ribs({ count: 18, height: 0.35 }));
|
|
1275
|
+
```
|