@snaptrude/plugin-core 0.0.0-dev-20260921132444 → 0.0.0-surfaces-20260923052616

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/api-manifest.json +767 -31
  3. package/dist/api/core/geom/create/index.d.ts +924 -100
  4. package/dist/api/core/geom/create/index.d.ts.map +1 -1
  5. package/dist/api/core/geom/query/brep.d.ts +55 -1
  6. package/dist/api/core/geom/query/brep.d.ts.map +1 -1
  7. package/dist/api/core/geom/query/curve.d.ts +58 -35
  8. package/dist/api/core/geom/query/curve.d.ts.map +1 -1
  9. package/dist/api/core/geom/query/edge.d.ts +2 -2
  10. package/dist/api/core/geom/query/face.d.ts +105 -0
  11. package/dist/api/core/geom/query/face.d.ts.map +1 -1
  12. package/dist/api/core/geom/update/curve.d.ts +5 -5
  13. package/dist/api/core/geom/update/profile.d.ts +1 -1
  14. package/dist/api/design/create/grids.d.ts +2 -2
  15. package/dist/api/design/create/grids.d.ts.map +1 -1
  16. package/dist/api/design/family.d.ts +65 -8
  17. package/dist/api/design/family.d.ts.map +1 -1
  18. package/dist/api/design/query/geometry/index.d.ts +33 -5
  19. package/dist/api/design/query/geometry/index.d.ts.map +1 -1
  20. package/dist/api/design/query/grids.d.ts +4 -3
  21. package/dist/api/design/query/grids.d.ts.map +1 -1
  22. package/dist/api/design/query/index.d.ts +47 -0
  23. package/dist/api/design/query/index.d.ts.map +1 -1
  24. package/dist/api/design/query/spaces.d.ts +5 -5
  25. package/dist/api/design/update/index.d.ts +87 -0
  26. package/dist/api/design/update/index.d.ts.map +1 -1
  27. package/dist/api/entity/referenceLine.d.ts +2 -2
  28. package/dist/api/entity/referenceLine.d.ts.map +1 -1
  29. package/dist/api/entity/space.d.ts +5 -4
  30. package/dist/api/entity/space.d.ts.map +1 -1
  31. package/dist/api/entity/story.d.ts +4 -4
  32. package/dist/api/program/site.d.ts +4 -4
  33. package/dist/api/program/spreadsheet.d.ts +4 -4
  34. package/dist/handles.d.ts +12 -3
  35. package/dist/handles.d.ts.map +1 -1
  36. package/dist/index.cjs +3413 -2943
  37. package/dist/index.cjs.map +1 -1
  38. package/dist/index.d.ts +2 -0
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +3366 -2943
  41. package/dist/index.js.map +1 -1
  42. package/dist/massParameters.d.ts +287 -0
  43. package/dist/massParameters.d.ts.map +1 -0
  44. package/dist/massParameters.ops.d.ts +137 -0
  45. package/dist/massParameters.ops.d.ts.map +1 -0
  46. package/package.json +13 -13
  47. package/src/api/core/geom/create/index.ts +1019 -101
  48. package/src/api/core/geom/query/brep.ts +56 -1
  49. package/src/api/core/geom/query/curve.ts +25 -2
  50. package/src/api/core/geom/query/edge.ts +2 -2
  51. package/src/api/core/geom/query/face.ts +109 -4
  52. package/src/api/design/family.ts +66 -8
  53. package/src/api/design/query/geometry/index.ts +35 -4
  54. package/src/api/design/query/index.ts +50 -0
  55. package/src/api/design/update/index.ts +94 -0
  56. package/src/handles.ts +15 -3
  57. package/src/index.ts +2 -0
  58. package/src/massParameters.ops.ts +245 -0
  59. package/src/massParameters.ts +427 -0
  60. package/test/massParameters.test.mjs +938 -0
@@ -1,14 +1,41 @@
1
1
  import * as z from "zod";
2
2
  import { PluginApiReturn } from "../../../../types";
3
- import { Vec3Handle, LineHandle, ArcHandle, CircleHandle, CurveHandle, ProfileHandle, ContourHandle, BrepHandle, FaceHandle, EdgeHandle, Vec3Components } from "../../../../handles";
3
+ import type { SweepAlongCurveRecordOptions } from "../../../../massParameters";
4
+ import { Vec3Handle, LineHandle, ArcHandle, SplineHandle, CircleHandle, CurveHandle, ProfileHandle, ContourHandle, BrepHandle, FaceHandle, EdgeHandle, Vec3Components } from "../../../../handles";
5
+ /** Maximum boundary items one patch may span. */
6
+ export declare const MAX_PATCH_BOUNDARY_CURVES = 16;
7
+ /** Maximum interior points one patch may be pulled through. */
8
+ export declare const MAX_PATCH_INTERIOR_POINTS = 64;
9
+ /**
10
+ * An edge named together with the solid it belongs to — an edge handle cannot
11
+ * name its own solid, and one patch may meet two solids. `face` is the adjacent
12
+ * face a tangent patch continues: REQUIRED under `continuity: "tangent"`
13
+ * (a solid edge has two faces — the wall or the top of a rim — and only the
14
+ * caller knows which), ignored otherwise. Owner LAST, like every read that
15
+ * takes `(face, brep)`.
16
+ */
17
+ export type OwnedEdge = {
18
+ edge: EdgeHandle;
19
+ brep: BrepHandle;
20
+ face?: FaceHandle;
21
+ };
22
+ /**
23
+ * The trailing bag of {@linkcode PluginGeomCreateApi.brepFromSweepAlongCurve}:
24
+ * the recorded switches plus `rail`, a live curve handle that never enters a
25
+ * record (a record is pure JSON, and a dead handle would not regenerate).
26
+ */
27
+ export type SweepAlongCurveOptions = SweepAlongCurveRecordOptions & {
28
+ rail?: CurveHandle;
29
+ };
4
30
  /**
5
31
  * Curve creation — construct new geometric curves from point handles (all-handle
6
32
  * model, §11).
7
33
  *
8
34
  * Each method takes point handles ({@linkcode Vec3Handle}) and returns an opaque
9
- * curve handle ({@linkcode LineHandle} or {@linkcode ArcHandle}) that you pass to
10
- * query, update, or entity-creation methods. Read geometry back as plain values
11
- * via the `snaptrude.core.geom.query.*` methods.
35
+ * curve handle ({@linkcode LineHandle}, {@linkcode ArcHandle}, or
36
+ * {@linkcode SplineHandle}) that you pass to query, update, or entity-creation
37
+ * methods. Read geometry back as plain values via the
38
+ * `snaptrude.core.geom.query.*` methods.
12
39
  *
13
40
  * Accessed via `snaptrude.core.geom.create`.
14
41
  */
@@ -69,6 +96,88 @@ export declare abstract class PluginGeomCreateApi {
69
96
  * ```
70
97
  */
71
98
  abstract circle(centrePoint: Vec3Handle, axis: Vec3Handle, radius: number): PluginApiReturn<CircleHandle>;
99
+ /**
100
+ * Create an open NURBS curve passing exactly THROUGH each point, in order
101
+ * (centripetal Catmull-Rom fit → clamped cubic B-spline; C1-smooth, no cusps
102
+ * on uneven spacing). Host API call — returns a handle. The points are
103
+ * interpolated, NOT control points. For a CLOSED smooth loop use
104
+ * {@linkcode PluginGeomCreateApi.profileFromSplinePoints} — closed splines
105
+ * exist only as profiles, never as a single curve handle.
106
+ *
107
+ * Pure host-side math — the geometry kernel is not loaded. The result is a
108
+ * {@linkcode CurveHandle}: pass it to `profileFromCurves` alongside lines and
109
+ * arcs, or read it back via `core.geom.query.curve.*`.
110
+ *
111
+ * @param points 3..256 ordered through-points; consecutive points must be distinct
112
+ * @returns The new open curve as a {@linkcode SplineHandle}
113
+ * @throws VALIDATION if fewer than 3 points (2 points are a straight line —
114
+ * use {@linkcode PluginGeomCreateApi.line}), more than 256 points, or two
115
+ * consecutive points coincide
116
+ *
117
+ * @examplePrompt Draw a smooth curve through these points
118
+ * @examplePrompt Make a wavy edge that passes through A, B, C and D
119
+ * @examplePrompt Freeform curved wall path through these clicks
120
+ *
121
+ * # Example
122
+ * ```ts
123
+ * const spline = await snaptrude.core.geom.create.splineFromPoints([p0, p1, p2, p3])
124
+ * // Mixed profile: smooth top, straight closing base
125
+ * const base = await snaptrude.core.geom.create.line(p3, p0)
126
+ * const profile = await snaptrude.core.geom.create.profileFromCurves([spline, base])
127
+ * ```
128
+ */
129
+ abstract splineFromPoints(points: Vec3Handle[]): PluginApiReturn<SplineHandle>;
130
+ /**
131
+ * Create an open NURBS curve DEFINED BY control points — the curve is pulled
132
+ * TOWARD the interior points, not through them; it starts at the first point
133
+ * and ends at the last. Knots are computed for you (clamped, uniform) —
134
+ * there is no knot-vector argument. For a curve that must pass THROUGH given
135
+ * points use {@linkcode PluginGeomCreateApi.splineFromPoints}.
136
+ *
137
+ * A curve made here records as `splinePoles` in a mass recipe and is
138
+ * re-minted verbatim on edit — so an agent that read a `splinePoles` curve
139
+ * back off a mass can move its poles and rebuild the mass with
140
+ * `design.update.parameters`. Pure host-side math — the geometry kernel is
141
+ * not loaded, and nothing is created in the scene.
142
+ *
143
+ * @param controlPoints 3..512 control points ({@linkcode Vec3Handle}s), in order
144
+ * @param options.degree 2 or 3; default `min(3, controlPoints.length - 1)`
145
+ * @returns The new open curve as a {@linkcode SplineHandle}
146
+ * @throws VALIDATION when fewer than `degree + 1` points are given, two
147
+ * consecutive points coincide, or `degree` is not 2 or 3
148
+ *
149
+ * @examplePrompt Draw a smooth curve controlled by these four points
150
+ * @examplePrompt Rebuild this edge from its control polygon
151
+ *
152
+ * # Example
153
+ * ```ts
154
+ * const curve = await snaptrude.core.geom.create.splineFromControlPoints([p0, p1, p2, p3])
155
+ * // Quadratic instead of the default cubic
156
+ * const tighter = await snaptrude.core.geom.create.splineFromControlPoints(
157
+ * [p0, p1, p2, p3],
158
+ * { degree: 2 },
159
+ * )
160
+ * ```
161
+ */
162
+ abstract splineFromControlPoints(controlPoints: Vec3Handle[], options?: {
163
+ degree?: number;
164
+ }): PluginApiReturn<SplineHandle>;
165
+ /**
166
+ * Drops a curve onto a face along the face's normal and returns the curves it
167
+ * lands on — one per connected run, empty when the curve misses the face
168
+ * entirely. Host API call — returns new curve handles; the inputs are
169
+ * read-only. No lengths are involved: the result is a curve in the same
170
+ * internal length units as its inputs.
171
+ *
172
+ * @param curve The curve to project
173
+ * @param face The face to project onto
174
+ * @param faceBrep The solid `face` belongs to — a face handle cannot name its
175
+ * own solid
176
+ * @returns The projected curves as {@linkcode CurveHandle}`[]`
177
+ * @throws VALIDATION if `face` is not a face of `faceBrep`
178
+ * @throws OPERATION_FAILED if the kernel could not project the curve
179
+ */
180
+ abstract curvesFromProjection(curve: CurveHandle, face: FaceHandle, faceBrep: BrepHandle): PluginApiReturn<CurveHandle[]>;
72
181
  /**
73
182
  * Create a closed profile from an ordered list of point handles connected by
74
183
  * line segments (last auto-connected to first). Host API call — returns a handle.
@@ -101,8 +210,41 @@ export declare abstract class PluginGeomCreateApi {
101
210
  */
102
211
  abstract profileFromCurves(curves: CurveHandle[]): PluginApiReturn<ProfileHandle>;
103
212
  /**
104
- * Create an axis-aligned **rectangle** profile (XZ plane) of `width` × `depth`,
105
- * centred at `center` (defaults to the origin). Host API call — returns a handle.
213
+ * Create a CLOSED smooth profile passing through each point, in order, with
214
+ * the loop closed smoothly back from the last point to the first (do NOT
215
+ * repeat the first point). Host API call — returns a handle. This is the
216
+ * closed counterpart of {@linkcode PluginGeomCreateApi.splineFromPoints} and
217
+ * the one-call route from points to an extrudable outline: wrap in
218
+ * `contourFromProfile` and extrude/loft/sweep as usual.
219
+ *
220
+ * The whole loop is smooth — this call takes no mixed straight/spline input.
221
+ * For a profile that is part curve and part straight, build the pieces with
222
+ * `splineFromPoints` + `line` and join them with
223
+ * {@linkcode PluginGeomCreateApi.profileFromCurves}.
224
+ *
225
+ * @param points 3..256 ordered through-points of the loop (first point NOT repeated)
226
+ * @returns The new closed profile as a {@linkcode ProfileHandle}
227
+ * @throws VALIDATION if fewer than 3 points, more than 256 points,
228
+ * consecutive points coincide (including last→first), or the loop
229
+ * self-intersects
230
+ *
231
+ * @examplePrompt Make a blob-shaped floor plate through these points
232
+ * @examplePrompt Organic curved outline through these corners
233
+ * @examplePrompt Freeform podium profile
234
+ *
235
+ * # Example
236
+ * ```ts
237
+ * const profile = await snaptrude.core.geom.create.profileFromSplinePoints([p0, p1, p2, p3, p4])
238
+ * const contour = await snaptrude.core.geom.create.contourFromProfile(profile)
239
+ * const brep = await snaptrude.core.geom.create.brepFromExtrusion(contour, { x: 0, y: 1, z: 0 }, 3)
240
+ * const podium = await snaptrude.design.create.massFromBrep(brep, "Podium")
241
+ * ```
242
+ */
243
+ abstract profileFromSplinePoints(points: Vec3Handle[]): PluginApiReturn<ProfileHandle>;
244
+ /**
245
+ * Create an axis-aligned **rectangle** profile in the XZ plane,
246
+ * `width` × `depth`, centred at `center` (defaults to the origin). Host API
247
+ * call — returns a handle.
106
248
  *
107
249
  * Pair with `design.create.space` / `design.create.spaces` to author a rectangular
108
250
  * (box) space — there is no dedicated rectangular-space creator; build the profile
@@ -210,15 +352,30 @@ export declare abstract class PluginGeomCreateApi {
210
352
  *
211
353
  * @param contour The cross-section to extrude (outer profile + optional holes)
212
354
  * @param direction Extrusion direction as plain `{x, y, z}` components (non-zero, normalised by the host)
213
- * @param amount Extrusion distance (non-zero; negative extrudes opposite to `direction`)
355
+ * @param amount Extrusion distance in internal length units (non-zero; negative extrudes opposite to `direction`)
356
+ * @param options Optional twist and taper, both about `direction` through the
357
+ * base contour's centroid. `twistInDegrees` — total rotation base → top in
358
+ * DEGREES (an angle: never scaled by the project's length unit), positive
359
+ * turning the top CLOCKWISE seen from the far end of `direction` looking
360
+ * back at the base — for the usual upward extrusion, the plan view;
361
+ * `topScale` — the top outline's scale, a ratio (1 = no taper); `levels` —
362
+ * how many sections to build through, a count (2..64). Leave `levels` out
363
+ * and the host resolves one and writes it into the record, so the mass
364
+ * regenerates identically ever after. An extrusion without twist or
365
+ * taper (no `options`, or zero twist and a `topScale` of 1) is
366
+ * built exactly as before these options existed.
214
367
  * @returns The new solid as a {@linkcode BrepHandle}
215
368
  * @throws if the extrusion is degenerate (zero amount, zero direction, or a
216
- * direction lying in the contour plane) or the contour cannot be extruded
217
- * into a valid solid
369
+ * direction lying in the plane of the contour) or the contour cannot be
370
+ * extruded into a valid solid
371
+ * @throws VALIDATION if `twistInDegrees` is not finite, `topScale` is not a
372
+ * positive finite ratio, or `levels` is outside 2..64
218
373
  *
219
374
  * @examplePrompt Extrude this profile 3 metres up
220
375
  * @examplePrompt Make a solid by extruding this outline
221
376
  * @examplePrompt Create a cylinder from a circle profile
377
+ * @examplePrompt Extrude this floor plate 40m up with a 90 degree twist
378
+ * @examplePrompt Taper this tower to 60 percent of its footprint at the top
222
379
  *
223
380
  * # Example
224
381
  * ```ts
@@ -228,7 +385,80 @@ export declare abstract class PluginGeomCreateApi {
228
385
  * const faceCount = await snaptrude.core.geom.query.brep.getFaceCount(brep) // 6
229
386
  * ```
230
387
  */
231
- abstract brepFromExtrusion(contour: ContourHandle, direction: Vec3Components, amount: number): PluginApiReturn<BrepHandle>;
388
+ abstract brepFromExtrusion(contour: ContourHandle, direction: Vec3Components, amount: number, options?: {
389
+ twistInDegrees?: number;
390
+ topScale?: number;
391
+ levels?: number;
392
+ }): PluginApiReturn<BrepHandle>;
393
+ /**
394
+ * Stretches a surface across a closed loop of boundary curves and thickens it
395
+ * into a SOLID in one call — a roof over four curves, a canopy between two
396
+ * rails, a blend across a gap. `thickness` is in internal length units and is
397
+ * required: only solids reach the canvas, and there is no separate surface
398
+ * object to keep. Pass edges as `{ edge, brep, face }` with
399
+ * `continuity: "tangent"` to leave the named face smoothly. The result carries
400
+ * NO recipe (`design.query.getParameters` returns `null`) — label it when you
401
+ * commit it, because the label is all the provenance there is.
402
+ *
403
+ * Runs on the OpenCascade kernel (the first kernel call loads a wasm of tens
404
+ * of MB — expect a pause of seconds).
405
+ *
406
+ * @param boundary 3..16 items forming ONE closed loop (ends meeting within
407
+ * tolerance): a curve, or an edge named WITH the solid it belongs to
408
+ * ({@linkcode OwnedEdge}) — an edge handle cannot name its own solid, and
409
+ * one patch may meet two solids. Read scene breps with
410
+ * `design.query.geometry.getBrep(x, { frame: "world" })` so every item is in
411
+ * one frame.
412
+ * @param thickness Solid thickness in internal length units (> 0)
413
+ * @param options `interiorPoints` pull the surface through them (≤ 64, plain
414
+ * `{x, y, z}` in the same frame as the boundary). `continuity` —
415
+ * `"position"` (default) or `"tangent"`: every boundary item must then be an
416
+ * edge item that also names the `face` to continue (a solid edge has two
417
+ * faces — the wall or the top of a rim). `side` — `"below"` (default) or
418
+ * `"above"`: which side of the boundary the solid grows to.
419
+ * @returns The thickened patch as a new {@linkcode BrepHandle}
420
+ * @throws VALIDATION if the boundary is not one closed loop (the message names
421
+ * the gap and its size), a count cap is exceeded, `thickness` is not
422
+ * positive, `continuity: "tangent"` is used with a curve item or with an
423
+ * edge item that names no `face` (the message names the edge's two candidate
424
+ * faces), or a `face` is not adjacent to its `edge`
425
+ * @throws OPERATION_FAILED if the kernel could not fill the boundary, the
426
+ * filled surface misses its own boundary by more than 0.254 mm (the message
427
+ * carries the measured gap), or the thicken produced no solid
428
+ *
429
+ * @examplePrompt Patch a roof over these four boundary curves, 250 mm thick
430
+ * @examplePrompt Span a canopy between these two curved rails, 300 mm thick
431
+ *
432
+ * # Example
433
+ * ```ts
434
+ * // A roof over four curves
435
+ * const roof = await snaptrude.core.geom.create.brepFromPatch(
436
+ * [curveA, curveB, curveC, curveD],
437
+ * 0.25,
438
+ * )
439
+ * const mass = await snaptrude.design.create.massFromBrep(roof, "Roof patch")
440
+ * ```
441
+ *
442
+ * ```ts
443
+ * // A canopy between two towers' rims, leaving every wall it meets smoothly:
444
+ * // with `continuity: "tangent"` EVERY item is an edge naming its face.
445
+ * const canopy = await snaptrude.core.geom.create.brepFromPatch(
446
+ * [
447
+ * { edge: rimA, brep: towerA, face: wallA },
448
+ * { edge: sideA, brep: towerA, face: endA },
449
+ * { edge: rimB, brep: towerB, face: wallB },
450
+ * { edge: sideB, brep: towerB, face: endB },
451
+ * ],
452
+ * 0.3,
453
+ * { continuity: "tangent" },
454
+ * )
455
+ * ```
456
+ */
457
+ abstract brepFromPatch(boundary: (CurveHandle | OwnedEdge)[], thickness: number, options?: {
458
+ interiorPoints?: Vec3Components[];
459
+ continuity?: "position" | "tangent";
460
+ side?: "below" | "above";
461
+ }): PluginApiReturn<BrepHandle>;
232
462
  /**
233
463
  * Create a closed solid **B-rep** by lofting between a bottom and a top
234
464
  * contour, optionally through intermediate cross-sections. Host API call —
@@ -242,8 +472,8 @@ export declare abstract class PluginGeomCreateApi {
242
472
  * unchanged. A pair whose side faces would be non-planar under every
243
473
  * correspondence still builds for hole-free straight-edged pairs — planar
244
474
  * side quads stay quads and warped ones split into planar triangles (the
245
- * triangulated lane); arc-bearing or holed twisted pairs are rejected, as is
246
- * auto-matching that would pair an arc with a straight edge. Matching hole
475
+ * triangulated fallback); arc-bearing or holed twisted pairs are rejected, as
476
+ * is auto-matching that would pair an arc with a straight edge. Matching hole
247
477
  * counts are allowed in the two-section form. With intermediates the loft
248
478
  * is a chain of ruled segments folded into one solid: sections must be
249
479
  * planar and hole-free, ordered bottom → intermediates → top. The contours
@@ -257,7 +487,9 @@ export declare abstract class PluginGeomCreateApi {
257
487
  * bottom — sections are auto-matched)
258
488
  * @param intermediateContours Optional in-between cross-sections, ordered
259
489
  * bottom to top (hole-free; edge counts may differ — every section is
260
- * normalized to the largest)
490
+ * normalized to the largest). Any count is accepted; a loft of more
491
+ * than 32 sections counting the bottom and the top still builds but
492
+ * carries no parameter record (records are capped, calls are not)
261
493
  * @param options Optional behavior switches. `compatibility` — `"auto"`
262
494
  * (default) inserts vertices to match differing edge counts; `"strict"`
263
495
  * skips normalization and throws VALIDATION when outer edge counts (or,
@@ -265,9 +497,13 @@ export declare abstract class PluginGeomCreateApi {
265
497
  * `"auto"` (default) searches seam rotations on straight-edge sections to
266
498
  * avoid a twist; `"authored"` keeps the authored start-vertex
267
499
  * correspondence unchanged (a twisted correspondence then builds through
268
- * the triangulated lane for hole-free straight-edged pairs).
500
+ * the triangulated fallback for hole-free straight-edged pairs).
269
501
  * `{ compatibility: "strict", seamAlignment: "authored" }` reproduces
270
- * pre-0.9.4 lofting exactly.
502
+ * pre-0.9.4 lofting exactly. `smoothing` — `"ruled"` (default) keeps the
503
+ * straight-sided behaviour described above; `"smooth"` lofts every
504
+ * section in ONE kernel pass, so the sides curve continuously through the
505
+ * intermediates instead of creasing at each one (a vase, a curved tower —
506
+ * the sections must still be planar and hole-free).
271
507
  * @returns The new solid as a {@linkcode BrepHandle}
272
508
  * @throws VALIDATION if the contours are coincident, their hole counts
273
509
  * differ, any section has holes when intermediates are present
@@ -289,6 +525,7 @@ export declare abstract class PluginGeomCreateApi {
289
525
  * @examplePrompt Loft these outlines even though their corners don't line up
290
526
  * @examplePrompt Loft these outlines exactly as authored, corner to corner
291
527
  * @examplePrompt Fail the loft if my sections don't have matching edge counts
528
+ * @examplePrompt Loft these three outlines with smoothly curving sides
292
529
  *
293
530
  * # Example
294
531
  * ```ts
@@ -305,6 +542,7 @@ export declare abstract class PluginGeomCreateApi {
305
542
  abstract brepFromLoft(bottomContour: ContourHandle, topContour: ContourHandle, intermediateContours?: ContourHandle[], options?: {
306
543
  compatibility?: "strict" | "auto";
307
544
  seamAlignment?: "authored" | "auto";
545
+ smoothing?: "ruled" | "smooth";
308
546
  }): PluginApiReturn<BrepHandle>;
309
547
  /**
310
548
  * Create a closed solid **B-rep** from indexed mesh data: a vertex position
@@ -432,46 +670,107 @@ export declare abstract class PluginGeomCreateApi {
432
670
  */
433
671
  abstract brepFromIntersection(a: BrepHandle, b: BrepHandle): PluginApiReturn<BrepHandle>;
434
672
  /**
435
- * Rounds the given straight edges of a solid with a constant radius. Host
436
- * API call — returns a new {@linkcode BrepHandle}; the input brep is
437
- * read-only.
438
- *
439
- * v1 fillets straight edges only, and no two filleted edges may share a
440
- * vertex — corner blends produce spherical patches Snaptrude cannot
441
- * represent. Runs on the OpenCascade kernel (the first kernel call loads a
442
- * wasm of tens of MB — expect a pause of seconds).
673
+ * Rounds the given edges of a solid with a constant radius. Host API call —
674
+ * returns a new {@linkcode BrepHandle}; the input brep is read-only.
675
+ *
676
+ * Works on curved solids: edges may be straight, circular or spline, and
677
+ * adjacent edges (corner blends) are allowed. To pick a **rim** — the circle
678
+ * where a cylinder meets a flat cap — walk the edges and keep the ones whose
679
+ * two faces are a `cylinder` and a `plane`:
680
+ * `core.geom.query.brep.listEdges(brep)` → per edge
681
+ * `core.geom.query.edge.listFaces(edge)` → `core.geom.query.face.getSurfaceKind`
682
+ * on both faces. (`core.geom.query.brep.listEdgesBetween` takes two VERTEX
683
+ * indices — it is NOT a face-pair lookup.) For one cap's rim only, the
684
+ * shorter walk is: find the cap (call `getSurfaceKind` on each face from
685
+ * `brep.listFaces`), then `core.geom.query.face.listEdges(capFace)`.
686
+ *
687
+ * When the input brep carries a creation recipe, the result carries it too,
688
+ * with this operation appended to `operations`; `design.create.massFromBrep`
689
+ * then keeps the mass editable through `design.update.parameters`.
690
+ *
691
+ * Runs on the OpenCascade kernel (the first kernel call loads a wasm of tens
692
+ * of MB — expect a pause of seconds).
443
693
  *
444
694
  * Inspect the result via `core.geom.query.brep.*`, or commit it to the scene
445
695
  * with `design.create.massFromBrep`.
446
696
  *
447
697
  * @param brep The solid whose edges to round
448
- * @param edges The straight edges to fillet (≥1, all on `brep`, no two sharing a vertex)
449
- * @param radius Fillet radius (positive, finite)
698
+ * @param edges The edges to fillet (one or more, all on `brep`, no
699
+ * duplicates; more than 64 still fillets but the result carries no
700
+ * parameter record)
701
+ * @param radius Fillet radius in internal length units (positive, finite) —
702
+ * the radius at the START of the blend when a variable form is used
703
+ * @param options Optional VARIABLE blend, in one of two forms, each naming
704
+ * exactly ONE edge: the law belongs to the whole tangent chain that edge
705
+ * lies on, and it is measured from that edge's start. `endRadius` —
706
+ * the radius at the far end, in internal length units, interpolated
707
+ * linearly along the chain; needs an OPEN chain with two distinct ends, and
708
+ * is refused on a closed rim (where the kernel silently builds a constant
709
+ * radius) — use `radii` there. `radii` — a sampled law instead:
710
+ * `position` is normalised ARC LENGTH along the chain (a ratio 0..1, never
711
+ * converted), `radius` is internal length units; 2..32 rows with strictly
712
+ * increasing `position`. On a closed rim 0 and 1 are the same point, so give
713
+ * them the same radius and put the variation in the interior rows. The two
714
+ * forms are mutually exclusive; without either, the fillet has one constant
715
+ * radius.
450
716
  * @returns The filleted solid as a new {@linkcode BrepHandle}
451
- * @throws VALIDATION if `edges` is empty, `radius` is not a positive finite
452
- * number, an edge is not on `brep`, an edge is an arc (v1 fillets straight
453
- * edges only), or two edges share a vertex (fillet non-adjacent edges)
454
- * @throws OPERATION_FAILED if the kernel cannot build the fillet (the radius
455
- * likely exceeds the adjacent face size — reduce it) or the result
456
- * contains curved surfaces Snaptrude cannot represent
457
- *
458
- * @examplePrompt Round the edges of this mass
717
+ * @throws VALIDATION if `edges` is empty or holds a duplicate, `radius` is
718
+ * not a positive finite number, an edge is not on `brep`, or an edge has no
719
+ * crease to round — it is a seam of a closed face, or it lies between two
720
+ * patches of one smooth surface; for a variable blend, if `endRadius` and
721
+ * `radii` are both given, more than one edge is passed, a `radii` table is
722
+ * outside 2..32 rows or its positions do not strictly increase within
723
+ * 0..1, or `endRadius` names a closed rim (the message points at `radii`)
724
+ * @throws PRECONDITION_FAILED if an edge could not be located on the kernel
725
+ * solid after healing (select a different edge, or fillet before the
726
+ * operation that curved the solid), or the kernel could not blend the edge
727
+ * named in the message (reduce the radius or drop that edge)
728
+ * @throws OPERATION_FAILED if the kernel or the translation fails, or the
729
+ * result is non-manifold, splits into several solids, or contains a surface
730
+ * Snaptrude cannot represent
731
+ *
732
+ * @examplePrompt Round the rim of the column with 200 mm
733
+ * @examplePrompt Soften where the dome meets the wall
459
734
  * @examplePrompt Fillet the corners of the podium with a 0.5m radius
460
735
  * @examplePrompt Soften the vertical edges of this tower
736
+ * @examplePrompt Blend this edge from 200mm at one end to 600mm at the other
737
+ * @examplePrompt Round this rim wider at the back than at the front
461
738
  *
462
739
  * # Example
463
740
  * ```ts
464
- * const brep = await snaptrude.core.geom.create.brepFromExtrusion(contour, { x: 0, y: 1, z: 0 }, 3)
465
- * const edges = await snaptrude.core.geom.query.brep.listEdges(brep)
466
- * const rounded = await snaptrude.core.geom.create.brepFromFillet(brep, [edges[0]], 0.3)
741
+ * // Rim = every edge between the cylinder side and a plane cap
742
+ * const edges = await snaptrude.core.geom.query.brep.listEdges(column)
743
+ * const rim = []
744
+ * for (const edge of edges) {
745
+ * const faces = await snaptrude.core.geom.query.edge.listFaces(edge)
746
+ * const kinds = await Promise.all(
747
+ * faces.map((f) => snaptrude.core.geom.query.face.getSurfaceKind(f)),
748
+ * )
749
+ * if (kinds.includes("cylinder") && kinds.includes("plane")) rim.push(edge)
750
+ * }
751
+ * const rounded = await snaptrude.core.geom.create.brepFromFillet(column, rim, 0.787) // 200 mm
467
752
  * ```
468
753
  */
469
- abstract brepFromFillet(brep: BrepHandle, edges: EdgeHandle[], radius: number): PluginApiReturn<BrepHandle>;
754
+ abstract brepFromFillet(brep: BrepHandle, edges: EdgeHandle[], radius: number, options?: {
755
+ endRadius?: number;
756
+ radii?: {
757
+ position: number;
758
+ radius: number;
759
+ }[];
760
+ }): PluginApiReturn<BrepHandle>;
470
761
  /**
471
762
  * Grows or shrinks a solid by offsetting every face — positive distance
472
763
  * moves faces outward, negative moves them inward. Host API call — returns
473
764
  * a new {@linkcode BrepHandle}; the input brep is read-only.
474
765
  *
766
+ * Works on curved solids: a sphere offsets to a sphere, a torus to a torus,
767
+ * a cylinder to a cylinder. There is nothing to select — the whole solid is
768
+ * offset.
769
+ *
770
+ * When the input brep carries a creation recipe, the result carries it too,
771
+ * with this operation appended to `operations`; `design.create.massFromBrep`
772
+ * then keeps the mass editable through `design.update.parameters`.
773
+ *
475
774
  * Runs on the OpenCascade kernel (the first kernel call loads a wasm of
476
775
  * tens of MB — expect a pause of seconds).
477
776
  *
@@ -483,9 +782,15 @@ export declare abstract class PluginGeomCreateApi {
483
782
  * @returns The offset solid as a new {@linkcode BrepHandle}
484
783
  * @throws VALIDATION if `distance` is not finite, is too small to offset
485
784
  * anything, or an inward distance consumes the solid entirely
486
- * @throws OPERATION_FAILED if the kernel cannot build the offset or the
487
- * result contains curved surfaces Snaptrude cannot represent
488
- *
785
+ * @throws OPERATION_FAILED if the kernel or the translation fails, or the
786
+ * result is non-manifold, splits into several solids, or contains a surface
787
+ * Snaptrude cannot represent (an offset free-form NURBS surface may have no
788
+ * exact representation — the model is left unchanged). A distance too
789
+ * large for the solid is reported here, with a hint asking for a smaller
790
+ * one. There is no per-face refusal: the whole call fails, and the error
791
+ * names no face
792
+ *
793
+ * @examplePrompt Thicken the torus ring by 100 mm
489
794
  * @examplePrompt Grow this solid by 0.5m in every direction
490
795
  * @examplePrompt Shrink this mass by 200mm
491
796
  * @examplePrompt Offset the building envelope outward by 1m
@@ -503,6 +808,18 @@ export declare abstract class PluginGeomCreateApi {
503
808
  * input brep is read-only. The outer surface is kept and the walls grow
504
809
  * inward.
505
810
  *
811
+ * Works on curved solids: the open faces may be spherical, cylindrical,
812
+ * conical, toroidal or free-form patches, not only flat ones. To open the
813
+ * flat base of a dome, check every face first —
814
+ * `core.geom.query.brep.listFaces` then
815
+ * `core.geom.query.face.getSurfaceKind` on each — and keep the `"plane"`
816
+ * one. A closed curved surface is stored as several patches (a sphere as
817
+ * lunes), so opening "the sphere" may mean passing several faces.
818
+ *
819
+ * When the input brep carries a creation recipe, the result carries it too,
820
+ * with this operation appended to `operations`; `design.create.massFromBrep`
821
+ * then keeps the mass editable through `design.update.parameters`.
822
+ *
506
823
  * Runs on the OpenCascade kernel (the first kernel call loads a wasm of
507
824
  * tens of MB — expect a pause of seconds).
508
825
  *
@@ -510,24 +827,36 @@ export declare abstract class PluginGeomCreateApi {
510
827
  * with `design.create.massFromBrep`.
511
828
  *
512
829
  * @param brep The solid to hollow
513
- * @param openFaces The faces to remove as openings (≥1, all on `brep`)
830
+ * @param openFaces The faces to remove as openings (one or more, all on
831
+ * `brep`, no duplicates; more than 32 still shells but the result carries
832
+ * no parameter record)
514
833
  * @param thickness Wall thickness (positive, finite, smaller than half the solid's smallest span)
515
834
  * @returns The hollowed solid as a new {@linkcode BrepHandle}
516
- * @throws VALIDATION if `openFaces` is empty, a face is not on `brep`,
517
- * `thickness` is not a positive finite number, or the thickness is too
518
- * large (it must be smaller than half the solid's smallest span)
519
- * @throws OPERATION_FAILED if the kernel cannot build the shell or the
520
- * result contains curved surfaces Snaptrude cannot represent
521
- *
835
+ * @throws VALIDATION if `openFaces` is empty or holds a duplicate, a face is
836
+ * not on `brep`, `thickness` is not a positive finite number, or the
837
+ * thickness is too large (it must be smaller than half the solid's smallest
838
+ * span)
839
+ * @throws OPERATION_FAILED if the kernel or the translation fails, or the
840
+ * result is non-manifold, splits into several solids, or contains a surface
841
+ * Snaptrude cannot represent. A thickness too large for the solid is
842
+ * reported here, with a hint asking for one below half the smallest span.
843
+ * There is no per-face refusal: the whole call fails, and the error
844
+ * names no face
845
+ *
846
+ * @examplePrompt Hollow the dome into a 300 mm shell, open at the base
522
847
  * @examplePrompt Hollow this mass into 200mm walls
523
848
  * @examplePrompt Shell this form with the top face open
524
849
  * @examplePrompt Turn this solid tower into a tube open at both ends
525
850
  *
526
851
  * # Example
527
852
  * ```ts
528
- * const brep = await snaptrude.core.geom.create.brepFromExtrusion(contour, { x: 0, y: 1, z: 0 }, 3)
529
- * const faces = await snaptrude.core.geom.query.brep.listFaces(brep)
530
- * const hollow = await snaptrude.core.geom.create.brepFromShell(brep, [faces[0]], 0.2)
853
+ * // Open the dome at its flat base: the one face whose surface is a plane
854
+ * const faces = await snaptrude.core.geom.query.brep.listFaces(dome)
855
+ * const base = []
856
+ * for (const face of faces) {
857
+ * if ((await snaptrude.core.geom.query.face.getSurfaceKind(face)) === "plane") base.push(face)
858
+ * }
859
+ * const hollow = await snaptrude.core.geom.create.brepFromShell(dome, base, 1.181) // 300 mm
531
860
  * ```
532
861
  */
533
862
  abstract brepFromShell(brep: BrepHandle, openFaces: FaceHandle[], thickness: number): PluginApiReturn<BrepHandle>;
@@ -567,28 +896,84 @@ export declare abstract class PluginGeomCreateApi {
567
896
  */
568
897
  abstract brepsFromSplit(brep: BrepHandle, planeOrigin: Vec3Components, planeNormal: Vec3Components): PluginApiReturn<BrepHandle[]>;
569
898
  /**
570
- * Bevels the given straight edges of a solid with a symmetric planar cut.
571
- * Host API call — returns a new {@linkcode BrepHandle}; the input brep is
572
- * read-only.
899
+ * Cuts a solid with a FACE of another solid — the curved twin of
900
+ * {@linkcode PluginGeomCreateApi.brepsFromSplit}, which cuts with a plane.
901
+ * Host API call — returns new {@linkcode BrepHandle}s; both inputs are
902
+ * read-only. BOTH breps must be in the same frame: read scene masses with
903
+ * `design.query.geometry.getBrep(x, { frame: "world" })` (the default is each
904
+ * mass's own local frame, and two masses have two). The pieces come back in
905
+ * DESCENDING volume order; pick the one you want with
906
+ * `core.geom.query.brep.getCentroid` or `getVolume` and commit it. A piece
907
+ * carries no recipe — label it.
908
+ *
909
+ * Runs on the OpenCascade kernel (the first kernel call loads a wasm of tens
910
+ * of MB — expect a pause of seconds).
911
+ *
912
+ * @param brep The solid to cut
913
+ * @param toolFace The cutting face, read-only
914
+ * @param toolBrep The solid `toolFace` belongs to — a face handle cannot name
915
+ * its own solid
916
+ * @returns The resulting pieces as {@linkcode BrepHandle}`[]`, largest first
917
+ * @throws VALIDATION if `toolFace` is not a face of `toolBrep`, `toolBrep` IS
918
+ * `brep`, or the cut produced a single part — the surface does not pass all
919
+ * the way through (extend it past the mass on every side, and check both
920
+ * breps were read in the same frame)
921
+ * @throws OPERATION_FAILED if the kernel could not split the solid
922
+ *
923
+ * @examplePrompt Cut this mass with the curved roof surface and keep the lower part
924
+ *
925
+ * # Example
926
+ * ```ts
927
+ * const target = await snaptrude.design.query.geometry.getBrep(tower, { frame: "world" })
928
+ * const tool = await snaptrude.design.query.geometry.getBrep(roof, { frame: "world" })
929
+ * const [toolFace] = await snaptrude.core.geom.query.brep.listFaces(tool)
930
+ * const pieces = await snaptrude.core.geom.create.brepsFromSplitByFace(target, toolFace, tool)
931
+ * ```
932
+ */
933
+ abstract brepsFromSplitByFace(brep: BrepHandle, toolFace: FaceHandle, toolBrep: BrepHandle): PluginApiReturn<BrepHandle[]>;
934
+ /**
935
+ * Bevels the given edges of a solid with a symmetric planar cut. Host API
936
+ * call — returns a new {@linkcode BrepHandle}; the input brep is read-only.
937
+ *
938
+ * Works on curved solids: edges may be straight, circular or spline, and
939
+ * adjacent edges are allowed. Pick edges the same way as for
940
+ * {@linkcode PluginGeomCreateApi.brepFromFillet} — `brep.listEdges`, then
941
+ * `core.geom.query.edge.listFaces` and `core.geom.query.face.getSurfaceKind`
942
+ * on both faces of each edge. (`core.geom.query.brep.listEdgesBetween` takes
943
+ * two VERTEX indices — it is NOT a face-pair lookup.) Chamfering a cylinder's
944
+ * rim yields a cone patch where a fillet would yield a torus patch.
573
945
  *
574
- * v1 chamfers straight edges only, and no two chamfered edges may share a
575
- * vertex. Runs on the OpenCascade kernel (the first kernel call loads a
576
- * wasm of tens of MB — expect a pause of seconds).
946
+ * When the input brep carries a creation recipe, the result carries it too,
947
+ * with this operation appended to `operations`; `design.create.massFromBrep`
948
+ * then keeps the mass editable through `design.update.parameters`.
949
+ *
950
+ * Runs on the OpenCascade kernel (the first kernel call loads a wasm of tens
951
+ * of MB — expect a pause of seconds).
577
952
  *
578
953
  * Inspect the result via `core.geom.query.brep.*`, or commit it to the scene
579
954
  * with `design.create.massFromBrep`.
580
955
  *
581
956
  * @param brep The solid whose edges to bevel
582
- * @param edges The straight edges to chamfer (≥1, all on `brep`, no two sharing a vertex)
957
+ * @param edges The edges to chamfer (one or more, all on `brep`, no
958
+ * duplicates; more than 64 still chamfers but the result carries no
959
+ * parameter record)
583
960
  * @param distance Chamfer distance from the edge on each adjacent face (positive, finite)
584
961
  * @returns The chamfered solid as a new {@linkcode BrepHandle}
585
- * @throws VALIDATION if `edges` is empty, `distance` is not a positive
586
- * finite number, an edge is not on `brep`, an edge is an arc (v1 chamfers
587
- * straight edges only), or two edges share a vertex (chamfer non-adjacent
588
- * edges)
589
- * @throws OPERATION_FAILED if the kernel cannot build the chamfer (the
590
- * distance likely exceeds the adjacent face size — reduce it)
591
- *
962
+ * @throws VALIDATION if `edges` is empty or holds a duplicate, `distance` is
963
+ * not a positive finite number, an edge is not on `brep`, or an edge has no
964
+ * crease to cut — it is a seam of a closed face, or it lies between two
965
+ * patches of one smooth surface
966
+ * @throws PRECONDITION_FAILED if an edge could not be located on the kernel
967
+ * solid after healing (select a different edge, or chamfer before the
968
+ * operation that curved the solid)
969
+ * @throws OPERATION_FAILED if the kernel or the translation fails, or the
970
+ * result is non-manifold, splits into several solids, or contains a surface
971
+ * Snaptrude cannot represent. A distance larger than an adjacent face
972
+ * is reported here, with a hint asking for a smaller one. Unlike
973
+ * {@linkcode PluginGeomCreateApi.brepFromFillet}, the kernel does not say
974
+ * which edge failed a chamfer, so the error names no edge
975
+ *
976
+ * @examplePrompt Chamfer the top edge of the cylinder
592
977
  * @examplePrompt Bevel these edges by 100mm
593
978
  * @examplePrompt Chamfer the top edges of the plinth
594
979
  * @examplePrompt Cut a 45-degree flat along the corners of this mass
@@ -619,11 +1004,15 @@ export declare abstract class PluginGeomCreateApi {
619
1004
  * tapering across a bend or along an arc edge would create faces Snaptrude
620
1005
  * cannot represent and throws (sweep each straight run separately and union
621
1006
  * the results instead). An optional `transition` picks the corner
622
- * treatment: `"miter"` (default) is today's sharp mitred bend;
1007
+ * treatment: `"miter"` (default) is a sharp mitred bend; `"round"`
1008
+ * carries the section around each turning corner on a tangent circular arc,
1009
+ * so the corner patch is a real curved (cylindrical) surface rather than a
1010
+ * flat cut (open paths only — `"round"` on a closed ring path is refused);
623
1011
  * `{ bevel: b }` chamfers each turning corner by cutting `b` back along
624
1012
  * both adjacent legs (works on open and closed paths — each leg must be
625
- * long enough for its cuts). On a corner-less path `transition` has no effect, and the
626
- * varying-scale lane takes straight paths, so it never sees a corner.
1013
+ * long enough for its cuts). On a corner-less path `transition` has no
1014
+ * effect, and a varying scale only accepts straight paths, so it never meets
1015
+ * a corner.
627
1016
  *
628
1017
  * Open paths run on the OpenCascade kernel (the first kernel call loads a
629
1018
  * wasm of tens of MB — expect a pause of seconds); closed paths are
@@ -633,19 +1022,22 @@ export declare abstract class PluginGeomCreateApi {
633
1022
  * with `design.create.massFromBrep`.
634
1023
  *
635
1024
  * @param profile The cross-section to sweep (hole-free contour)
636
- * @param path The polyline path as plain `{x, y, z}` points (≥2; repeat the
637
- * first point as the last to close the path into a ring)
1025
+ * @param path The polyline path as plain `{x, y, z}` points (2 or more;
1026
+ * repeat the first point as the last to close the path into a ring; more
1027
+ * than 512 points still sweeps but the result carries no parameter record)
638
1028
  * @param options Optional scale law and corner transition. Scale law:
639
1029
  * `startScale`/`endScale` (linear taper by arc length) or `scales` (one
640
1030
  * factor per path point; mutually exclusive with
641
1031
  * `startScale`/`endScale`); every factor must be finite and within
642
- * 1e-3..1e3. `transition`: `"miter"` (default, sharp corners) or
643
- * `{ bevel: b }` (chamfered corners, `b` finite within 1e-3..1e3; open
644
- * and closed paths)
1032
+ * 1e-3..1e3. `transition`: `"miter"` (default, sharp corners),
1033
+ * `"round"` (arc-carried corners — curved corner patches; open paths
1034
+ * only) or `{ bevel: b }` (chamfered corners, `b` finite within
1035
+ * 1e-3..1e3; open and closed paths)
645
1036
  * @returns The swept solid as a new {@linkcode BrepHandle}
646
1037
  * @throws VALIDATION if the profile has holes, the path has fewer than 2
647
- * points, consecutive path points coincide, a coordinate is not finite,
648
- * or the profile plane contains the first path segment's direction
1038
+ * points, consecutive path points coincide, a
1039
+ * coordinate is not finite, or the profile plane contains the first
1040
+ * path segment's direction
649
1041
  * (degenerate sweep); for closed paths, if the ring has fewer than 3
650
1042
  * distinct corners, the path is non-planar, a corner doubles back, the
651
1043
  * profile has an arc edge, or the profile is too large for a mitred
@@ -653,11 +1045,14 @@ export declare abstract class PluginGeomCreateApi {
653
1045
  * is combined with `startScale`/`endScale`, `scales` does not match the
654
1046
  * path length, or a varying scale is used on a bent or closed path or
655
1047
  * with an arc-edged profile; for `{ bevel }`, if a leg is too short for
656
- * the cuts its beveled corners take from it or a corner nearly doubles
657
- * back so its chamfer collapses (the errors name the corner)
1048
+ * the cuts its bevelled corners take from it or a corner nearly doubles
1049
+ * back so its bevel collapses (the errors name the corner)
1050
+ * @throws PRECONDITION_FAILED if `transition` is `"round"` and the path is
1051
+ * closed — round corners work on open paths only; use `"miter"` or
1052
+ * `{ bevel }` on a ring
658
1053
  * @throws OPERATION_FAILED if the kernel cannot sweep the profile into a
659
- * valid solid or a transition patch is a curved surface Snaptrude cannot
660
- * represent
1054
+ * valid solid — including a `"round"` corner whose arc does not fit its
1055
+ * legs, which is not pre-checked and so is not named per corner
661
1056
  *
662
1057
  * @examplePrompt Sweep this profile along the corridor path
663
1058
  * @examplePrompt Extrude the railing section along this route
@@ -666,6 +1061,7 @@ export declare abstract class PluginGeomCreateApi {
666
1061
  * @examplePrompt Taper this duct from 1x1 to 2x2 along its run
667
1062
  * @examplePrompt Sweep a column section that narrows toward the top
668
1063
  * @examplePrompt Chamfer the corners of this swept frame by 200mm
1064
+ * @examplePrompt Sweep this handrail with rounded corners at the bends
669
1065
  *
670
1066
  * # Example
671
1067
  * ```ts
@@ -701,17 +1097,69 @@ export declare abstract class PluginGeomCreateApi {
701
1097
  startScale?: number;
702
1098
  endScale?: number;
703
1099
  scales?: number[];
704
- transition?: "miter" | {
1100
+ transition?: "miter" | "round" | {
705
1101
  bevel: number;
706
1102
  };
707
1103
  }): PluginApiReturn<BrepHandle>;
1104
+ /**
1105
+ * Sweeps a cross-section along a SMOOTH path — splines, arcs and lines chained
1106
+ * end to end — with control of how the profile turns.
1107
+ * {@linkcode PluginGeomCreateApi.brepFromSweep} takes a polyline path; this
1108
+ * takes curves. Host API call — returns a new {@linkcode BrepHandle}; the
1109
+ * inputs are read-only. Records as `sweepAlongCurve`, so the orientation stays
1110
+ * editable through `design.update.parameters`. The properties panel shows it
1111
+ * read-only, because it is a text value, not a number.
1112
+ *
1113
+ * Runs on the OpenCascade kernel (the first kernel call loads a wasm of tens
1114
+ * of MB — expect a pause of seconds).
1115
+ *
1116
+ * @param profile Hole-free cross-section contour; placed at the first curve's start
1117
+ * @param path 1..64 curves, ordered, meeting end to end within tolerance
1118
+ * @param options `orientation` — `"upright"` (default) keeps the profile's up
1119
+ * aligned with world up (ducts, handrails, ribbons that must not roll);
1120
+ * `"frenet"` lets it roll with the path's curvature; `"fixed"` carries the
1121
+ * authored frame along unchanged, which is a pure translation — use it to
1122
+ * bend a footprint along an arc. `rail` is a second guide curve.
1123
+ * @returns The swept solid as a new {@linkcode BrepHandle}
1124
+ * @throws VALIDATION if the path curves are not connected, the path is closed,
1125
+ * the profile has holes, the first tangent lies in the profile plane, the
1126
+ * path runs vertically under `"upright"` (that frame is undefined there —
1127
+ * the message names the run and points at `"frenet"`), the path turns
1128
+ * parallel to the profile under `"fixed"`, or `rail` is passed on a kernel
1129
+ * build that cannot carry it
1130
+ * @throws OPERATION_FAILED if the kernel could not sweep the profile — a
1131
+ * self-intersection on a tight bend
1132
+ *
1133
+ * @examplePrompt Sweep a 600x400 duct along this curved route and keep it upright
1134
+ * @examplePrompt Run this handrail along the curved stair edge
1135
+ * @examplePrompt Bend this footprint along the arc
1136
+ *
1137
+ * # Example
1138
+ * ```ts
1139
+ * const route = await snaptrude.core.geom.create.splineFromPoints(points)
1140
+ * const duct = await snaptrude.core.geom.create.brepFromSweepAlongCurve(profile, [route], {
1141
+ * orientation: "upright",
1142
+ * })
1143
+ * ```
1144
+ */
1145
+ abstract brepFromSweepAlongCurve(profile: ContourHandle, path: CurveHandle[], options?: SweepAlongCurveOptions): PluginApiReturn<BrepHandle>;
708
1146
  /**
709
1147
  * Revolves a planar profile about an axis to make a solid of revolution — a
710
1148
  * full turn by default. Host API call — returns a new
711
1149
  * {@linkcode BrepHandle}; the input contour is read-only. Holes in the
712
- * profile are allowed. Profile segments must stay parallel or perpendicular
713
- * to the axis — inclined or arc segments would revolve into surfaces
714
- * Snaptrude cannot represent.
1150
+ * profile are allowed, and segments may run at any angle to the axis: an
1151
+ * inclined segment revolves into a cone, an arc into a sphere or torus
1152
+ * section. This is the general route to domes, vases, columns and rotundas.
1153
+ *
1154
+ * Two rules bind the axis to the profile. First, the axis line must lie IN
1155
+ * the profile's plane — a revolution turns a planar section about a line
1156
+ * drawn in that same plane. An axis that misses the plane (skew to it, or
1157
+ * parallel but offset out of it) is refused: move the axis into the
1158
+ * profile's plane, or move the profile onto the axis's plane. Second,
1159
+ * within that plane the whole profile stays on ONE side of the axis.
1160
+ * Vertices and whole segments may lie ON the axis — that is how a dome's
1161
+ * pole and a cylinder's inner edge are authored — but no part of the profile
1162
+ * may cross to the other side, which would sweep a self-intersecting solid.
715
1163
  *
716
1164
  * Runs on the OpenCascade kernel (the first kernel call loads a wasm of
717
1165
  * tens of MB — expect a pause of seconds).
@@ -725,19 +1173,25 @@ export declare abstract class PluginGeomCreateApi {
725
1173
  * @param angleInDegrees Optional revolution angle in degrees (0 < angle ≤ 360; default 360)
726
1174
  * @returns The revolved solid as a new {@linkcode BrepHandle}
727
1175
  * @throws VALIDATION if `axisDirection` is zero-length, `angleInDegrees` is
728
- * not in (0, 360], the axis passes through the profile interior, or a
729
- * coordinate is not finite
730
- * @throws OPERATION_FAILED if the kernel cannot revolve the profile or the
731
- * result contains curved surfaces Snaptrude cannot represent (keep
732
- * profile segments parallel or perpendicular to the axis)
1176
+ * not in (0, 360], a coordinate is not finite, or the profile crosses the
1177
+ * axis (the message names the offending segment — keep the whole profile
1178
+ * on one side; points may touch the axis but not cross it)
1179
+ * @throws PRECONDITION_FAILED if the axis does not lie in the profile's
1180
+ * plane — skew to it, or parallel but offset out of it (the message asks
1181
+ * you to move the axis into the plane of the profile)
1182
+ * @throws OPERATION_FAILED if the kernel cannot revolve the profile into a
1183
+ * valid solid
733
1184
  *
734
1185
  * @examplePrompt Create a dome from this section
735
1186
  * @examplePrompt Revolve this profile 360 degrees around the vertical axis
736
1187
  * @examplePrompt Build a rotunda by revolving this wall section
1188
+ * @examplePrompt Make a dome by revolving a quarter-circle about the vertical axis
1189
+ * @examplePrompt Turn this curved outline into a vase
737
1190
  *
738
1191
  * # Example
739
1192
  * ```ts
740
- * // A cylinder: revolve a 2m-wide, 3m-tall rectangle about the Y axis at its edge
1193
+ * // A cylinder: revolve a 2m-wide, 3m-tall rectangle about the Y axis at
1194
+ * // its edge — the left edge sits ON the axis, which is legal.
741
1195
  * const rect = await snaptrude.core.geom.create.profileFromLinePoints([
742
1196
  * await snaptrude.core.math.vec3.new(0, 0, 0),
743
1197
  * await snaptrude.core.math.vec3.new(2, 0, 0),
@@ -753,6 +1207,136 @@ export declare abstract class PluginGeomCreateApi {
753
1207
  * ```
754
1208
  */
755
1209
  abstract brepFromRevolution(profile: ContourHandle, axisOrigin: Vec3Components, axisDirection: Vec3Components, angleInDegrees?: number): PluginApiReturn<BrepHandle>;
1210
+ /**
1211
+ * Create a solid **sphere** B-rep (boundary representation: the solid's
1212
+ * exact faces, edges and vertices) from a centre and radius. Host API call
1213
+ * — returns a {@linkcode BrepHandle}; commit it to the scene with
1214
+ * `design.create.massFromBrep`. The result carries an exact spherical
1215
+ * surface (not a faceted approximation) and a creation recipe — read the
1216
+ * committed mass's parameters back with `design.query.getParameters` and edit
1217
+ * them with `design.update.parameters`.
1218
+ *
1219
+ * Runs on the OpenCascade kernel (the first kernel call loads a wasm of tens
1220
+ * of MB — expect a pause of seconds).
1221
+ *
1222
+ * @param centre Sphere centre as plain `{x, y, z}` components (raw Babylon units)
1223
+ * @param radius Sphere radius (> 0, raw Babylon units)
1224
+ * @returns The new solid as a {@linkcode BrepHandle}
1225
+ * @throws VALIDATION if `radius` is not a positive finite number or a
1226
+ * coordinate is not finite
1227
+ *
1228
+ * @examplePrompt Create a sphere of radius 5 at the origin
1229
+ * @examplePrompt Add a 3m ball on top of the tower
1230
+ *
1231
+ * # Example
1232
+ * ```ts
1233
+ * const brep = await snaptrude.core.geom.create.brepFromSphere({ x: 0, y: 5, z: 0 }, 5)
1234
+ * const mass = await snaptrude.design.create.massFromBrep(brep, "Sphere")
1235
+ * ```
1236
+ */
1237
+ abstract brepFromSphere(centre: Vec3Components, radius: number): PluginApiReturn<BrepHandle>;
1238
+ /**
1239
+ * Create a solid **cylinder** B-rep from its bottom-cap centre, axis
1240
+ * direction, radius and height. Host API call — returns a
1241
+ * {@linkcode BrepHandle}; commit with `design.create.massFromBrep`. The
1242
+ * bottom cap sits AT `base` and the solid extends `height` along `axis` —
1243
+ * place `base` on the floor and use axis `{x: 0, y: 1, z: 0}` for an upright
1244
+ * column. Carries a creation recipe (radius, height), editable through
1245
+ * `design.update.parameters`.
1246
+ *
1247
+ * Runs on the OpenCascade kernel (the first kernel call loads a wasm of tens
1248
+ * of MB — expect a pause of seconds).
1249
+ *
1250
+ * @param base Centre of the bottom cap as plain `{x, y, z}` components
1251
+ * @param axis Axis direction as plain `{x, y, z}` components (non-zero, normalised by the host)
1252
+ * @param radius Cylinder radius (> 0)
1253
+ * @param height Cylinder height along `axis` (> 0)
1254
+ * @returns The new solid as a {@linkcode BrepHandle}
1255
+ * @throws VALIDATION if `radius`/`height` are not positive finite numbers or
1256
+ * `axis` is zero-length
1257
+ *
1258
+ * @examplePrompt Create a cylinder 2m across and 4m tall
1259
+ * @examplePrompt Add a circular column here
1260
+ *
1261
+ * # Example
1262
+ * ```ts
1263
+ * const brep = await snaptrude.core.geom.create.brepFromCylinder(
1264
+ * { x: 0, y: 0, z: 0 },
1265
+ * { x: 0, y: 1, z: 0 },
1266
+ * 1,
1267
+ * 4,
1268
+ * )
1269
+ * const column = await snaptrude.design.create.massFromBrep(brep, "Column")
1270
+ * ```
1271
+ */
1272
+ abstract brepFromCylinder(base: Vec3Components, axis: Vec3Components, radius: number, height: number): PluginApiReturn<BrepHandle>;
1273
+ /**
1274
+ * Create a solid **cone or frustum** B-rep: bottom-cap centre, axis, base
1275
+ * radius, height, and an optional top radius (default 0 — a full cone to a
1276
+ * point; > 0 — a frustum / tapered column). Host API call — returns a
1277
+ * {@linkcode BrepHandle}; commit with `design.create.massFromBrep`. Carries
1278
+ * a creation recipe (radii + height), editable through `design.update.parameters`.
1279
+ *
1280
+ * Runs on the OpenCascade kernel (the first kernel call loads a wasm of tens
1281
+ * of MB — expect a pause of seconds).
1282
+ *
1283
+ * @param base Centre of the bottom cap as plain `{x, y, z}` components
1284
+ * @param axis Axis direction as plain `{x, y, z}` components (non-zero, normalised by the host)
1285
+ * @param baseRadius Radius at the base (> 0)
1286
+ * @param height Height along `axis` (> 0)
1287
+ * @param topRadius Optional radius at the top (≥ 0, ≠ `baseRadius`; default 0 = apex)
1288
+ * @returns The new solid as a {@linkcode BrepHandle}
1289
+ * @throws VALIDATION if radii/height are invalid, `topRadius === baseRadius`
1290
+ * (that is a cylinder — use {@linkcode PluginGeomCreateApi.brepFromCylinder}),
1291
+ * or `axis` is zero-length
1292
+ *
1293
+ * @examplePrompt Create a cone roof 4m wide and 3m tall
1294
+ * @examplePrompt Make a tapered column narrowing from 1m to 0.6m
1295
+ *
1296
+ * # Example
1297
+ * ```ts
1298
+ * const roof = await snaptrude.core.geom.create.brepFromCone(
1299
+ * { x: 0, y: 9, z: 0 },
1300
+ * { x: 0, y: 1, z: 0 },
1301
+ * 2,
1302
+ * 3,
1303
+ * )
1304
+ * ```
1305
+ */
1306
+ abstract brepFromCone(base: Vec3Components, axis: Vec3Components, baseRadius: number, height: number, topRadius?: number): PluginApiReturn<BrepHandle>;
1307
+ /**
1308
+ * Create a solid **torus** (ring / donut) B-rep from its centre, plane
1309
+ * normal, ring radius and tube radius. Host API call — returns a
1310
+ * {@linkcode BrepHandle}; commit with `design.create.massFromBrep`.
1311
+ * `majorRadius` is centre-to-tube-centre; `minorRadius` is the tube's own
1312
+ * radius and must be strictly smaller. Carries a creation recipe, editable
1313
+ * through `design.update.parameters`.
1314
+ *
1315
+ * Runs on the OpenCascade kernel (the first kernel call loads a wasm of tens
1316
+ * of MB — expect a pause of seconds).
1317
+ *
1318
+ * @param centre Torus centre as plain `{x, y, z}` components
1319
+ * @param axis Plane normal of the ring as plain `{x, y, z}` components (non-zero)
1320
+ * @param majorRadius Ring radius, centre to tube centre (> 0)
1321
+ * @param minorRadius Tube radius (> 0 and < `majorRadius` — a self-intersecting torus is rejected)
1322
+ * @returns The new solid as a {@linkcode BrepHandle}
1323
+ * @throws VALIDATION if a radius is invalid, `minorRadius >= majorRadius`,
1324
+ * or `axis` is zero-length
1325
+ *
1326
+ * @examplePrompt Create a donut-shaped ring 10m across with a 1m tube
1327
+ * @examplePrompt Add a torus canopy around the tower
1328
+ *
1329
+ * # Example
1330
+ * ```ts
1331
+ * const ring = await snaptrude.core.geom.create.brepFromTorus(
1332
+ * { x: 0, y: 6, z: 0 },
1333
+ * { x: 0, y: 1, z: 0 },
1334
+ * 5,
1335
+ * 1,
1336
+ * )
1337
+ * ```
1338
+ */
1339
+ abstract brepFromTorus(centre: Vec3Components, axis: Vec3Components, majorRadius: number, minorRadius: number): PluginApiReturn<BrepHandle>;
756
1340
  }
757
1341
  /**
758
1342
  * Arguments for {@linkcode PluginGeomCreateApi.line}.
@@ -799,6 +1383,32 @@ export declare const PluginGeomCreateCircleArgs: z.ZodObject<{
799
1383
  radius: z.ZodNumber;
800
1384
  }, z.core.$strip>;
801
1385
  export type PluginGeomCreateCircleArgs = z.infer<typeof PluginGeomCreateCircleArgs>;
1386
+ /**
1387
+ * Arguments for {@linkcode PluginGeomCreateApi.splineFromPoints}.
1388
+ *
1389
+ * | Property | Type | Description |
1390
+ * |---|---|---|
1391
+ * | `points` | {@linkcode Vec3Handle}`[]` | 3..256 ordered through-points of the curve |
1392
+ */
1393
+ export declare const PluginGeomCreateSplineFromPointsArgs: z.ZodObject<{
1394
+ points: z.ZodArray<z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../../..").Handle<"vec3">, string>>>;
1395
+ }, z.core.$strip>;
1396
+ export type PluginGeomCreateSplineFromPointsArgs = z.infer<typeof PluginGeomCreateSplineFromPointsArgs>;
1397
+ /**
1398
+ * Arguments for {@linkcode PluginGeomCreateApi.splineFromControlPoints}.
1399
+ *
1400
+ * | Property | Type | Description |
1401
+ * |---|---|---|
1402
+ * | `controlPoints` | {@linkcode Vec3Handle}`[]` | 3..512 control points of the curve, in order |
1403
+ * | `options` | `object`? | `degree`: 2 or 3 (default `min(3, controlPoints.length - 1)`) |
1404
+ */
1405
+ export declare const PluginGeomCreateSplineFromControlPointsArgs: z.ZodObject<{
1406
+ controlPoints: z.ZodArray<z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../../..").Handle<"vec3">, string>>>;
1407
+ options: z.ZodOptional<z.ZodObject<{
1408
+ degree: z.ZodOptional<z.ZodNumber>;
1409
+ }, z.core.$strip>>;
1410
+ }, z.core.$strip>;
1411
+ export type PluginGeomCreateSplineFromControlPointsArgs = z.infer<typeof PluginGeomCreateSplineFromControlPointsArgs>;
802
1412
  /**
803
1413
  * Arguments for {@linkcode PluginGeomCreateApi.profileFromLinePoints}.
804
1414
  *
@@ -818,9 +1428,20 @@ export type PluginGeomCreateProfileFromLinePointsArgs = z.infer<typeof PluginGeo
818
1428
  * | `curves` | {@linkcode CurveHandle}`[]` | Ordered curve handles forming a closed loop |
819
1429
  */
820
1430
  export declare const PluginGeomCreateProfileFromCurvesArgs: z.ZodObject<{
821
- curves: z.ZodArray<z.ZodUnion<readonly [z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../../..").Handle<"line">, string>>, z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../../..").Handle<"arc">, string>>]>>;
1431
+ curves: z.ZodArray<z.ZodType<CurveHandle, unknown, z.core.$ZodTypeInternals<CurveHandle, unknown>>>;
822
1432
  }, z.core.$strip>;
823
1433
  export type PluginGeomCreateProfileFromCurvesArgs = z.infer<typeof PluginGeomCreateProfileFromCurvesArgs>;
1434
+ /**
1435
+ * Arguments for {@linkcode PluginGeomCreateApi.profileFromSplinePoints}.
1436
+ *
1437
+ * | Property | Type | Description |
1438
+ * |---|---|---|
1439
+ * | `points` | {@linkcode Vec3Handle}`[]` | 3..256 ordered through-points of the closed loop (first point NOT repeated) |
1440
+ */
1441
+ export declare const PluginGeomCreateProfileFromSplinePointsArgs: z.ZodObject<{
1442
+ points: z.ZodArray<z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../../..").Handle<"vec3">, string>>>;
1443
+ }, z.core.$strip>;
1444
+ export type PluginGeomCreateProfileFromSplinePointsArgs = z.infer<typeof PluginGeomCreateProfileFromSplinePointsArgs>;
824
1445
  /**
825
1446
  * Arguments for {@linkcode PluginGeomCreateApi.contourFromProfile}.
826
1447
  *
@@ -868,6 +1489,7 @@ export type PluginGeomCreateBrepFromFacesArgs = z.infer<typeof PluginGeomCreateB
868
1489
  * | `contour` | {@linkcode ContourHandle} | The cross-section to extrude |
869
1490
  * | `direction` | {@linkcode Vec3Components} | Extrusion direction (non-zero, finite components) |
870
1491
  * | `amount` | `number` | Extrusion distance (finite, non-zero) |
1492
+ * | `options` | `object`? | Optional twist and taper: `twistInDegrees` (an angle, finite), `topScale` (a ratio, finite and positive) and `levels` (a count, 2..64) |
871
1493
  */
872
1494
  export declare const PluginGeomCreateBrepFromExtrusionArgs: z.ZodObject<{
873
1495
  contour: z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../../..").Handle<"contour">, string>>;
@@ -877,6 +1499,11 @@ export declare const PluginGeomCreateBrepFromExtrusionArgs: z.ZodObject<{
877
1499
  z: z.ZodNumber;
878
1500
  }, z.core.$strip>;
879
1501
  amount: z.ZodNumber;
1502
+ options: z.ZodOptional<z.ZodObject<{
1503
+ twistInDegrees: z.ZodOptional<z.ZodNumber>;
1504
+ topScale: z.ZodOptional<z.ZodNumber>;
1505
+ levels: z.ZodOptional<z.ZodNumber>;
1506
+ }, z.core.$strip>>;
880
1507
  }, z.core.$strip>;
881
1508
  export type PluginGeomCreateBrepFromExtrusionArgs = z.infer<typeof PluginGeomCreateBrepFromExtrusionArgs>;
882
1509
  /**
@@ -886,8 +1513,8 @@ export type PluginGeomCreateBrepFromExtrusionArgs = z.infer<typeof PluginGeomCre
886
1513
  * |---|---|---|
887
1514
  * | `bottomContour` | {@linkcode ContourHandle} | The bottom cross-section |
888
1515
  * | `topContour` | {@linkcode ContourHandle} | The top cross-section |
889
- * | `intermediateContours` | {@linkcode ContourHandle}`[]`? | Optional in-between cross-sections, ordered bottom to top |
890
- * | `options` | `object`? | Optional behavior switches: `compatibility` (`"strict"` throws on mismatched edge counts instead of auto-matching; default `"auto"`) and `seamAlignment` (`"authored"` keeps the authored correspondence instead of searching seam rotations; default `"auto"`) |
1516
+ * | `intermediateContours` | {@linkcode ContourHandle}`[]`? | Optional in-between cross-sections, ordered bottom to top (any count; more than 32 sections in all builds but carries no parameter record) |
1517
+ * | `options` | `object`? | Optional behavior switches: `compatibility` (`"strict"` throws on mismatched edge counts instead of auto-matching; default `"auto"`), `seamAlignment` (`"authored"` keeps the authored correspondence instead of searching seam rotations; default `"auto"`) and `smoothing` (`"smooth"` lofts every section in one pass, so the sides curve through the intermediates; default `"ruled"`) |
891
1518
  */
892
1519
  export declare const PluginGeomCreateBrepFromLoftArgs: z.ZodObject<{
893
1520
  bottomContour: z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../../..").Handle<"contour">, string>>;
@@ -902,6 +1529,10 @@ export declare const PluginGeomCreateBrepFromLoftArgs: z.ZodObject<{
902
1529
  auto: "auto";
903
1530
  authored: "authored";
904
1531
  }>>;
1532
+ smoothing: z.ZodOptional<z.ZodEnum<{
1533
+ ruled: "ruled";
1534
+ smooth: "smooth";
1535
+ }>>;
905
1536
  }, z.core.$strip>>;
906
1537
  }, z.core.$strip>;
907
1538
  export type PluginGeomCreateBrepFromLoftArgs = z.infer<typeof PluginGeomCreateBrepFromLoftArgs>;
@@ -944,15 +1575,62 @@ export type PluginGeomCreateBrepBooleanArgs = z.infer<typeof PluginGeomCreateBre
944
1575
  * | Property | Type | Description |
945
1576
  * |---|---|---|
946
1577
  * | `brep` | {@linkcode BrepHandle} | The solid whose edges to round |
947
- * | `edges` | {@linkcode EdgeHandle}`[]` | The straight edges to fillet (≥1) |
948
- * | `radius` | `number` | Fillet radius (positive, finite) |
1578
+ * | `edges` | {@linkcode EdgeHandle}`[]` | The edges to fillet (one or more; more than 64 builds but carries no parameter record) |
1579
+ * | `radius` | `number` | Fillet radius (positive, finite); the start radius of a variable blend |
1580
+ * | `options` | `object`? | Optional variable blend: `endRadius` (positive, finite) or `radii` (2..32 rows of `{ position, radius }`, `position` a ratio 0..1 strictly increasing). Mutually exclusive, and either one takes exactly ONE edge |
949
1581
  */
950
1582
  export declare const PluginGeomCreateBrepFromFilletArgs: z.ZodObject<{
951
1583
  brep: z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../../..").Handle<"brep">, string>>;
952
1584
  edges: z.ZodArray<z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../../..").Handle<"edge">, string>>>;
953
1585
  radius: z.ZodNumber;
1586
+ options: z.ZodOptional<z.ZodObject<{
1587
+ endRadius: z.ZodOptional<z.ZodNumber>;
1588
+ radii: z.ZodOptional<z.ZodArray<z.ZodObject<{
1589
+ position: z.ZodNumber;
1590
+ radius: z.ZodNumber;
1591
+ }, z.core.$strip>>>;
1592
+ }, z.core.$strip>>;
954
1593
  }, z.core.$strip>;
955
1594
  export type PluginGeomCreateBrepFromFilletArgs = z.infer<typeof PluginGeomCreateBrepFromFilletArgs>;
1595
+ /** An edge with the solid it belongs to. See {@linkcode OwnedEdge}. */
1596
+ export declare const OwnedEdge: z.ZodObject<{
1597
+ edge: z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../../..").Handle<"edge">, string>>;
1598
+ brep: z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../../..").Handle<"brep">, string>>;
1599
+ face: z.ZodOptional<z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../../..").Handle<"face">, string>>>;
1600
+ }, z.core.$strip>;
1601
+ /**
1602
+ * Arguments for {@linkcode PluginGeomCreateApi.brepFromPatch}.
1603
+ *
1604
+ * | Property | Type | Description |
1605
+ * |---|---|---|
1606
+ * | `boundary` | ({@linkcode CurveHandle} \| {@linkcode OwnedEdge})`[]` | 3..16 items forming one closed loop |
1607
+ * | `thickness` | `number` | Solid thickness in internal length units (positive, finite) |
1608
+ * | `options` | `object`? | `interiorPoints` (≤ 64 plain `{x, y, z}` the surface is pulled through), `continuity` (`"position"` default, or `"tangent"` — every item must then be an edge item naming its `face`), `side` (`"below"` default, or `"above"`) |
1609
+ */
1610
+ export declare const PluginGeomCreateBrepFromPatchArgs: z.ZodObject<{
1611
+ boundary: z.ZodArray<z.ZodUnion<readonly [z.ZodType<CurveHandle, unknown, z.core.$ZodTypeInternals<CurveHandle, unknown>>, z.ZodObject<{
1612
+ edge: z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../../..").Handle<"edge">, string>>;
1613
+ brep: z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../../..").Handle<"brep">, string>>;
1614
+ face: z.ZodOptional<z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../../..").Handle<"face">, string>>>;
1615
+ }, z.core.$strip>]>>;
1616
+ thickness: z.ZodNumber;
1617
+ options: z.ZodOptional<z.ZodObject<{
1618
+ interiorPoints: z.ZodOptional<z.ZodArray<z.ZodObject<{
1619
+ x: z.ZodNumber;
1620
+ y: z.ZodNumber;
1621
+ z: z.ZodNumber;
1622
+ }, z.core.$strip>>>;
1623
+ continuity: z.ZodOptional<z.ZodEnum<{
1624
+ position: "position";
1625
+ tangent: "tangent";
1626
+ }>>;
1627
+ side: z.ZodOptional<z.ZodEnum<{
1628
+ below: "below";
1629
+ above: "above";
1630
+ }>>;
1631
+ }, z.core.$strip>>;
1632
+ }, z.core.$strip>;
1633
+ export type PluginGeomCreateBrepFromPatchArgs = z.infer<typeof PluginGeomCreateBrepFromPatchArgs>;
956
1634
  /**
957
1635
  * Arguments for {@linkcode PluginGeomCreateApi.brepFromOffset}.
958
1636
  *
@@ -972,7 +1650,7 @@ export type PluginGeomCreateBrepFromOffsetArgs = z.infer<typeof PluginGeomCreate
972
1650
  * | Property | Type | Description |
973
1651
  * |---|---|---|
974
1652
  * | `brep` | {@linkcode BrepHandle} | The solid to hollow |
975
- * | `openFaces` | {@linkcode FaceHandle}`[]` | The faces to remove as openings (≥1) |
1653
+ * | `openFaces` | {@linkcode FaceHandle}`[]` | The faces to remove as openings (one or more; more than 32 builds but carries no parameter record) |
976
1654
  * | `thickness` | `number` | Wall thickness (positive, finite) |
977
1655
  */
978
1656
  export declare const PluginGeomCreateBrepFromShellArgs: z.ZodObject<{
@@ -1004,13 +1682,43 @@ export declare const PluginGeomCreateBrepsFromSplitArgs: z.ZodObject<{
1004
1682
  }, z.core.$strip>;
1005
1683
  }, z.core.$strip>;
1006
1684
  export type PluginGeomCreateBrepsFromSplitArgs = z.infer<typeof PluginGeomCreateBrepsFromSplitArgs>;
1685
+ /**
1686
+ * Arguments for {@linkcode PluginGeomCreateApi.brepsFromSplitByFace}.
1687
+ *
1688
+ * | Property | Type | Description |
1689
+ * |---|---|---|
1690
+ * | `brep` | {@linkcode BrepHandle} | The solid to cut |
1691
+ * | `toolFace` | {@linkcode FaceHandle} | The cutting face (read-only) |
1692
+ * | `toolBrep` | {@linkcode BrepHandle} | The solid `toolFace` belongs to (owner last) |
1693
+ */
1694
+ export declare const PluginGeomCreateBrepsFromSplitByFaceArgs: z.ZodObject<{
1695
+ brep: z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../../..").Handle<"brep">, string>>;
1696
+ toolFace: z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../../..").Handle<"face">, string>>;
1697
+ toolBrep: z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../../..").Handle<"brep">, string>>;
1698
+ }, z.core.$strip>;
1699
+ export type PluginGeomCreateBrepsFromSplitByFaceArgs = z.infer<typeof PluginGeomCreateBrepsFromSplitByFaceArgs>;
1700
+ /**
1701
+ * Arguments for {@linkcode PluginGeomCreateApi.curvesFromProjection}.
1702
+ *
1703
+ * | Property | Type | Description |
1704
+ * |---|---|---|
1705
+ * | `curve` | {@linkcode CurveHandle} | The curve to project |
1706
+ * | `face` | {@linkcode FaceHandle} | The face to project onto |
1707
+ * | `faceBrep` | {@linkcode BrepHandle} | The solid `face` belongs to (owner last) |
1708
+ */
1709
+ export declare const PluginGeomCreateCurvesFromProjectionArgs: z.ZodObject<{
1710
+ curve: z.ZodType<CurveHandle, unknown, z.core.$ZodTypeInternals<CurveHandle, unknown>>;
1711
+ face: z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../../..").Handle<"face">, string>>;
1712
+ faceBrep: z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../../..").Handle<"brep">, string>>;
1713
+ }, z.core.$strip>;
1714
+ export type PluginGeomCreateCurvesFromProjectionArgs = z.infer<typeof PluginGeomCreateCurvesFromProjectionArgs>;
1007
1715
  /**
1008
1716
  * Arguments for {@linkcode PluginGeomCreateApi.brepFromChamfer}.
1009
1717
  *
1010
1718
  * | Property | Type | Description |
1011
1719
  * |---|---|---|
1012
1720
  * | `brep` | {@linkcode BrepHandle} | The solid whose edges to bevel |
1013
- * | `edges` | {@linkcode EdgeHandle}`[]` | The straight edges to chamfer (≥1) |
1721
+ * | `edges` | {@linkcode EdgeHandle}`[]` | The edges to chamfer (one or more; more than 64 builds but carries no parameter record) |
1014
1722
  * | `distance` | `number` | Chamfer distance from the edge on each adjacent face (positive, finite) |
1015
1723
  */
1016
1724
  export declare const PluginGeomCreateBrepFromChamferArgs: z.ZodObject<{
@@ -1025,8 +1733,8 @@ export type PluginGeomCreateBrepFromChamferArgs = z.infer<typeof PluginGeomCreat
1025
1733
  * | Property | Type | Description |
1026
1734
  * |---|---|---|
1027
1735
  * | `profile` | {@linkcode ContourHandle} | The cross-section to sweep (hole-free) |
1028
- * | `path` | {@linkcode Vec3Components}`[]` | The polyline path (≥2 points, finite components; repeating the first point as the last closes it into a ring — closed paths must be flat and straight-segmented and take a straight-edged profile) |
1029
- * | `options` | `object`? | Optional scale law: `startScale`/`endScale` (linear taper by arc length) or per-point `scales` (mutually exclusive; factors finite, 1e-3..1e3; `scales.length` must equal `path.length`). Optional corner `transition`: `"miter"` (default) or `{ bevel }` (chamfered corners; finite, 1e-3..1e3) |
1736
+ * | `path` | {@linkcode Vec3Components}`[]` | The polyline path (2 or more points, finite components — more than 512 builds but carries no parameter record; repeating the first point as the last closes it into a ring — closed paths must be flat and straight-segmented and take a straight-edged profile) |
1737
+ * | `options` | `object`? | Optional scale law: `startScale`/`endScale` (linear taper by arc length) or per-point `scales` (mutually exclusive; factors finite, 1e-3..1e3; `scales.length` must equal `path.length`). Optional corner `transition`: `"miter"` (default), `"round"` (arc-carried corners) or `{ bevel }` (chamfered corners; finite, 1e-3..1e3) |
1030
1738
  */
1031
1739
  export declare const PluginGeomCreateBrepFromSweepArgs: z.ZodObject<{
1032
1740
  profile: z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../../..").Handle<"contour">, string>>;
@@ -1039,20 +1747,42 @@ export declare const PluginGeomCreateBrepFromSweepArgs: z.ZodObject<{
1039
1747
  startScale: z.ZodOptional<z.ZodNumber>;
1040
1748
  endScale: z.ZodOptional<z.ZodNumber>;
1041
1749
  scales: z.ZodOptional<z.ZodArray<z.ZodNumber>>;
1042
- transition: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"miter">, z.ZodObject<{
1750
+ transition: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"miter">, z.ZodLiteral<"round">, z.ZodObject<{
1043
1751
  bevel: z.ZodNumber;
1044
1752
  }, z.core.$strip>]>>;
1045
1753
  }, z.core.$strip>>;
1046
1754
  }, z.core.$strip>;
1047
1755
  export type PluginGeomCreateBrepFromSweepArgs = z.infer<typeof PluginGeomCreateBrepFromSweepArgs>;
1756
+ /**
1757
+ * Arguments for {@linkcode PluginGeomCreateApi.brepFromSweepAlongCurve}.
1758
+ *
1759
+ * | Property | Type | Description |
1760
+ * |---|---|---|
1761
+ * | `profile` | {@linkcode ContourHandle} | The cross-section to sweep (hole-free) |
1762
+ * | `path` | {@linkcode CurveHandle}`[]` | 1..64 curves, ordered, meeting end to end |
1763
+ * | `options` | `object`? | `orientation` — `"upright"` (default), `"frenet"` or `"fixed"`; `rail` — a second guide {@linkcode CurveHandle} |
1764
+ */
1765
+ export declare const PluginGeomCreateBrepFromSweepAlongCurveArgs: z.ZodObject<{
1766
+ profile: z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../../..").Handle<"contour">, string>>;
1767
+ path: z.ZodArray<z.ZodType<CurveHandle, unknown, z.core.$ZodTypeInternals<CurveHandle, unknown>>>;
1768
+ options: z.ZodOptional<z.ZodObject<{
1769
+ orientation: z.ZodOptional<z.ZodEnum<{
1770
+ fixed: "fixed";
1771
+ frenet: "frenet";
1772
+ upright: "upright";
1773
+ }>>;
1774
+ rail: z.ZodOptional<z.ZodType<CurveHandle, unknown, z.core.$ZodTypeInternals<CurveHandle, unknown>>>;
1775
+ }, z.core.$strip>>;
1776
+ }, z.core.$strip>;
1777
+ export type PluginGeomCreateBrepFromSweepAlongCurveArgs = z.infer<typeof PluginGeomCreateBrepFromSweepAlongCurveArgs>;
1048
1778
  /**
1049
1779
  * Arguments for {@linkcode PluginGeomCreateApi.brepFromRevolution}.
1050
1780
  *
1051
1781
  * | Property | Type | Description |
1052
1782
  * |---|---|---|
1053
1783
  * | `profile` | {@linkcode ContourHandle} | The cross-section to revolve (holes allowed) |
1054
- * | `axisOrigin` | {@linkcode Vec3Components} | A point on the revolution axis (finite components) |
1055
- * | `axisDirection` | {@linkcode Vec3Components} | The axis direction (non-zero, finite components) |
1784
+ * | `axisOrigin` | {@linkcode Vec3Components} | A point on the revolution axis (finite components; the axis must lie in the plane of the profile) |
1785
+ * | `axisDirection` | {@linkcode Vec3Components} | The axis direction (non-zero, finite components; the axis must lie in the plane of the profile) |
1056
1786
  * | `angleInDegrees` | `number`? | Revolution angle in degrees (0 < angle ≤ 360; default 360) |
1057
1787
  */
1058
1788
  export declare const PluginGeomCreateBrepFromRevolutionArgs: z.ZodObject<{
@@ -1070,4 +1800,98 @@ export declare const PluginGeomCreateBrepFromRevolutionArgs: z.ZodObject<{
1070
1800
  angleInDegrees: z.ZodOptional<z.ZodNumber>;
1071
1801
  }, z.core.$strip>;
1072
1802
  export type PluginGeomCreateBrepFromRevolutionArgs = z.infer<typeof PluginGeomCreateBrepFromRevolutionArgs>;
1803
+ /**
1804
+ * Arguments for {@linkcode PluginGeomCreateApi.brepFromSphere}.
1805
+ *
1806
+ * | Property | Type | Description |
1807
+ * |---|---|---|
1808
+ * | `centre` | {@linkcode Vec3Components} | Sphere centre (finite components) |
1809
+ * | `radius` | `number` | Sphere radius (finite; positivity is checked host-side so the error names the parameter) |
1810
+ */
1811
+ export declare const PluginGeomCreateBrepFromSphereArgs: z.ZodObject<{
1812
+ centre: z.ZodObject<{
1813
+ x: z.ZodNumber;
1814
+ y: z.ZodNumber;
1815
+ z: z.ZodNumber;
1816
+ }, z.core.$strip>;
1817
+ radius: z.ZodNumber;
1818
+ }, z.core.$strip>;
1819
+ export type PluginGeomCreateBrepFromSphereArgs = z.infer<typeof PluginGeomCreateBrepFromSphereArgs>;
1820
+ /**
1821
+ * Arguments for {@linkcode PluginGeomCreateApi.brepFromCylinder}.
1822
+ *
1823
+ * | Property | Type | Description |
1824
+ * |---|---|---|
1825
+ * | `base` | {@linkcode Vec3Components} | Centre of the bottom cap (finite components) |
1826
+ * | `axis` | {@linkcode Vec3Components} | Axis direction (non-zero, finite components) |
1827
+ * | `radius` | `number` | Cylinder radius (finite, positive) |
1828
+ * | `height` | `number` | Height along `axis` (finite, positive) |
1829
+ */
1830
+ export declare const PluginGeomCreateBrepFromCylinderArgs: z.ZodObject<{
1831
+ base: z.ZodObject<{
1832
+ x: z.ZodNumber;
1833
+ y: z.ZodNumber;
1834
+ z: z.ZodNumber;
1835
+ }, z.core.$strip>;
1836
+ axis: z.ZodObject<{
1837
+ x: z.ZodNumber;
1838
+ y: z.ZodNumber;
1839
+ z: z.ZodNumber;
1840
+ }, z.core.$strip>;
1841
+ radius: z.ZodNumber;
1842
+ height: z.ZodNumber;
1843
+ }, z.core.$strip>;
1844
+ export type PluginGeomCreateBrepFromCylinderArgs = z.infer<typeof PluginGeomCreateBrepFromCylinderArgs>;
1845
+ /**
1846
+ * Arguments for {@linkcode PluginGeomCreateApi.brepFromCone}.
1847
+ *
1848
+ * | Property | Type | Description |
1849
+ * |---|---|---|
1850
+ * | `base` | {@linkcode Vec3Components} | Centre of the bottom cap (finite components) |
1851
+ * | `axis` | {@linkcode Vec3Components} | Axis direction (non-zero, finite components) |
1852
+ * | `baseRadius` | `number` | Radius at the base (finite, positive) |
1853
+ * | `height` | `number` | Height along `axis` (finite, positive) |
1854
+ * | `topRadius` | `number`? | Radius at the top (finite, ≥ 0, ≠ `baseRadius`; default 0 = apex) |
1855
+ */
1856
+ export declare const PluginGeomCreateBrepFromConeArgs: z.ZodObject<{
1857
+ base: z.ZodObject<{
1858
+ x: z.ZodNumber;
1859
+ y: z.ZodNumber;
1860
+ z: z.ZodNumber;
1861
+ }, z.core.$strip>;
1862
+ axis: z.ZodObject<{
1863
+ x: z.ZodNumber;
1864
+ y: z.ZodNumber;
1865
+ z: z.ZodNumber;
1866
+ }, z.core.$strip>;
1867
+ baseRadius: z.ZodNumber;
1868
+ height: z.ZodNumber;
1869
+ topRadius: z.ZodOptional<z.ZodNumber>;
1870
+ }, z.core.$strip>;
1871
+ export type PluginGeomCreateBrepFromConeArgs = z.infer<typeof PluginGeomCreateBrepFromConeArgs>;
1872
+ /**
1873
+ * Arguments for {@linkcode PluginGeomCreateApi.brepFromTorus}.
1874
+ *
1875
+ * | Property | Type | Description |
1876
+ * |---|---|---|
1877
+ * | `centre` | {@linkcode Vec3Components} | Torus centre (finite components) |
1878
+ * | `axis` | {@linkcode Vec3Components} | Plane normal of the ring (non-zero, finite components) |
1879
+ * | `majorRadius` | `number` | Ring radius, centre to tube centre (finite, positive) |
1880
+ * | `minorRadius` | `number` | Tube radius (finite, positive, strictly less than `majorRadius`) |
1881
+ */
1882
+ export declare const PluginGeomCreateBrepFromTorusArgs: z.ZodObject<{
1883
+ centre: z.ZodObject<{
1884
+ x: z.ZodNumber;
1885
+ y: z.ZodNumber;
1886
+ z: z.ZodNumber;
1887
+ }, z.core.$strip>;
1888
+ axis: z.ZodObject<{
1889
+ x: z.ZodNumber;
1890
+ y: z.ZodNumber;
1891
+ z: z.ZodNumber;
1892
+ }, z.core.$strip>;
1893
+ majorRadius: z.ZodNumber;
1894
+ minorRadius: z.ZodNumber;
1895
+ }, z.core.$strip>;
1896
+ export type PluginGeomCreateBrepFromTorusArgs = z.infer<typeof PluginGeomCreateBrepFromTorusArgs>;
1073
1897
  //# sourceMappingURL=index.d.ts.map