@metamesh/modeling 0.7.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/README.md +86 -4
  3. package/dist/api/engine.d.ts +4 -0
  4. package/dist/api/geometry.d.ts +1067 -908
  5. package/dist/api/index.d.ts +203 -18
  6. package/dist/api/text.d.ts +21 -7
  7. package/dist/engine/construction-operations.js +52 -10
  8. package/dist/engine/execution.js +55 -2
  9. package/dist/engine/export-3mf.js +17 -1
  10. package/dist/engine/finalization.js +27 -18
  11. package/dist/engine/inspection-operations.js +26 -22
  12. package/dist/engine/loft-operations.js +1 -1
  13. package/dist/engine/mechanical-operations.js +5 -8
  14. package/dist/engine/mesh-view-cache.js +23 -0
  15. package/dist/engine/native/adapter.js +2 -4
  16. package/dist/engine/native/distance.js +42 -0
  17. package/dist/engine/native/status.js +16 -0
  18. package/dist/engine/operation-environment.js +2 -1
  19. package/dist/engine/section-operations.js +3 -3
  20. package/dist/geometry/heightfield.js +101 -42
  21. package/dist/geometry/index.js +3 -0
  22. package/dist/geometry/loft-simple-mesh.js +2 -3
  23. package/dist/geometry/loft-triangulation.js +12 -9
  24. package/dist/geometry/loft.js +2 -6
  25. package/dist/geometry/mechanical/standards.js +2 -3
  26. package/dist/geometry/mechanical/threads.js +2 -3
  27. package/dist/geometry/mesh-centroid.js +36 -0
  28. package/dist/geometry/mesh-solid-intersections.js +123 -0
  29. package/dist/geometry/mesh-solid.js +284 -0
  30. package/dist/geometry/profiles/cross-section.js +102 -0
  31. package/dist/geometry/svg-import.js +8 -1
  32. package/dist/geometry/sweeps/sweep-closed.js +4 -4
  33. package/dist/geometry/sweeps/sweep-mesh.js +2 -6
  34. package/dist/geometry/sweeps/sweep-open.js +4 -4
  35. package/dist/geometry/sweeps/validation.js +1 -2
  36. package/dist/model/operations.js +10 -3
  37. package/dist/text/vector-text-layout.js +46 -3
  38. package/package.json +1 -1
@@ -425,6 +425,17 @@ export declare interface ArcCurve3 {
425
425
  */
426
426
  export declare const computeParallelTransportFrames: (path: readonly Vec3[], initialNormal?: Vec3, normalGuide?: PathNormalGuide, limits?: Partial<GeometrySamplingLimits>) => readonly PathFrame[];
427
427
 
428
+ /**
429
+ * Computes the uniform-density volume centroid of an oriented closed solid, including cavity shells.
430
+ * Coordinates are millimetres. Indexed closure and positive aggregate volume are required; callers
431
+ * may use validateSolidMesh first when geometric intersections and shell orientation are untrusted.
432
+ * Fresh mutable input is inspected on every call, and buffers are never changed.
433
+ *
434
+ * @param mesh - Consistently oriented closed mesh with positive enclosed volume.
435
+ * @returns A fresh immutable XYZ volume centroid.
436
+ */
437
+ export declare function computeTriangleMeshCentroid(mesh: TriangleMesh): Vec3;
438
+
428
439
  /** One sampled component retaining contour identities and logical point correspondence. */
429
440
  export declare interface CorrespondingComponent {
430
441
  /** Stable canonical lowercase identity; unique within the containing topology or output. */
@@ -509,6 +520,39 @@ export declare interface ArcCurve3 {
509
520
  */
510
521
  export declare const cross3: (a: Vec3, b: Vec3) => Vec3;
511
522
 
523
+ /** One explicitly closed planar contour, independent of editor metadata and parameter contracts. */
524
+ export declare interface CrossSectionCurve {
525
+ /** Initial anchor; coordinates may be any finite value. */
526
+ readonly start: CrossSectionPoint;
527
+ /** Ordered chain of 2–32 segments; the final end must exactly match start. */
528
+ readonly segments: readonly CrossSectionSegment[];
529
+ }
530
+
531
+ /** Planar X and upward Y in millimetres, or in units converted by sampling scales. */
532
+ export declare interface CrossSectionPoint {
533
+ /** Horizontal coordinate; physical scaling does not center the contour. */
534
+ readonly x: number;
535
+ /** Upward planar coordinate. */
536
+ readonly y: number;
537
+ }
538
+
539
+ /** Straight or cubic Bézier segment in one closed planar contour. */
540
+ export declare type CrossSectionSegment = {
541
+ /** Straight segment discriminator. */
542
+ readonly type: "line";
543
+ /** Next anchor; the final anchor repeats the curve start. */
544
+ readonly end: CrossSectionPoint;
545
+ } | {
546
+ /** Cubic Bézier segment discriminator. */
547
+ readonly type: "cubic";
548
+ /** Outgoing control from the previous anchor. */
549
+ readonly control1: CrossSectionPoint;
550
+ /** Incoming control at the next anchor. */
551
+ readonly control2: CrossSectionPoint;
552
+ /** Next anchor; the final anchor repeats the curve start. */
553
+ readonly end: CrossSectionPoint;
554
+ };
555
+
512
556
  /** Planar cubic Bézier with explicit endpoint and control coordinates. */
513
557
  export declare interface CubicBezierCurve2 {
514
558
  /** Selects a cubic Bézier through two endpoints and two controls. */
@@ -983,9 +1027,10 @@ export declare interface ArcCurve3 {
983
1027
  export declare function getMetricFastenerStandard(size: MetricFastenerSize): MetricFastenerStandard;
984
1028
 
985
1029
  /**
986
- * Builds a closed indexed solid from a regularly sampled top, matched boundary walls, and flat base.
987
- * Heights are evaluated once per grid point after allocation preflight. Physical XY sizes and all
988
- * output coordinates must fit Float32 storage. Shared wall vertices prevent cracks at the base.
1030
+ * Builds a closed indexed mesh from a rectilinear top, matched boundary walls, and flat base.
1031
+ * Heights run once per grid point after preflight; center-error adds one evaluation per cell.
1032
+ * Top winding is +Z, the base is -Z, and sides face outward. Coordinates and heights must fit
1033
+ * Float32 storage. Explicit axes are captured before sampling; shared wall vertices prevent cracks.
989
1034
  *
990
1035
  * @example Sample a closed wavy mesh
991
1036
  * ```ts
@@ -1000,23 +1045,58 @@ export declare interface ArcCurve3 {
1000
1045
  /** Trusted output ceilings for pure construction; omitted fields use engine defaults. */
1001
1046
  export declare type HeightfieldMeshLimits = Partial<Pick<ModelingLimits, "maxVertices" | "maxTriangles" | "maxBytes">>;
1002
1047
 
1003
- /** A regularly sampled, closed heightfield above a flat base, in millimetres. */
1004
- export declare interface HeightfieldOptions {
1005
- /** Positive XY footprint. */
1006
- readonly size: Vec2;
1007
- /** Exact positive integer X/Y interval counts. */
1008
- readonly segments: readonly [x: number, y: number];
1048
+ /**
1049
+ * A closed rectilinear heightfield above a flat base, with uniform or explicit XY samples in millimetres.
1050
+ *
1051
+ * Uniform sampling requires positive `size: [width, depth]` and positive integer `segments: [x, y]`.
1052
+ * Optional `origin` sets the lower-left XY corner; omitting it centres the footprint on XY.
1053
+ * Alternatively, supply `coordinates: { x, y }` with at least two strictly increasing finite
1054
+ * absolute samples per axis, distinct in Float32. This infers the footprint and interval counts;
1055
+ * `size`, `segments`, and `origin` cannot be combined with explicit coordinates.
1056
+ */
1057
+ export declare type HeightfieldOptions = {
1009
1058
  /** Absolute top Z at the supplied XY point. Every sample must be above baseZ. */
1010
1059
  readonly height: (point: Vec2) => number;
1011
1060
  /** Flat bottom Z. Defaults to zero. */
1012
1061
  readonly baseZ?: number;
1062
+ /**
1063
+ * Top-cell diagonal policy. Defaults to fixed (lower-left to upper-right).
1064
+ * min-edge selects the shorter 3D diagonal; center-error selects the diagonal whose endpoint
1065
+ * average is closest to one extra height sample at the physical cell centre. Ties use fixed.
1066
+ * All policies retain two triangles per cell; neither estimates error elsewhere in the cell.
1067
+ */
1068
+ readonly triangulation?: "fixed" | "min-edge" | "center-error";
1069
+ } & ({
1070
+ /** Positive XY footprint for uniform sampling. */
1071
+ readonly size: Vec2;
1072
+ /** Exact positive integer X/Y interval counts. */
1073
+ readonly segments: readonly [x: number, y: number];
1013
1074
  /** Lower-left footprint XY. Omitted centers the footprint on XY. */
1014
1075
  readonly origin?: Vec2;
1015
- }
1016
-
1017
- /** Predictable regular-grid allocation facts; this does not evaluate the height callback. */
1076
+ /** Explicit coordinates cannot be combined with uniform sampling. */
1077
+ readonly coordinates?: never;
1078
+ } | {
1079
+ /**
1080
+ * Absolute XY coordinates, each with at least two strictly increasing finite values that
1081
+ * remain distinct in Float32. Uneven spacing permits caller-owned local refinement.
1082
+ */
1083
+ readonly coordinates: {
1084
+ /** Absolute X samples in ascending order. */
1085
+ readonly x: readonly number[];
1086
+ /** Absolute Y samples in ascending order. */
1087
+ readonly y: readonly number[];
1088
+ };
1089
+ /** The footprint is inferred from explicit coordinates. */
1090
+ readonly size?: never;
1091
+ /** Interval counts are inferred from explicit coordinates. */
1092
+ readonly segments?: never;
1093
+ /** Explicit coordinates already include their origin. */
1094
+ readonly origin?: never;
1095
+ });
1096
+
1097
+ /** Predictable rectilinear-grid allocation facts; this does not evaluate the height callback. */
1018
1098
  export declare interface HeightfieldPreflight {
1019
- /** Number of grid points and height callback evaluations. */
1099
+ /** Number of top grid points; center-error also evaluates one height per cell. */
1020
1100
  readonly sampleCount: number;
1021
1101
  /** Number of allocated XYZ vertices. */
1022
1102
  readonly vertexCount: number;
@@ -1591,7 +1671,7 @@ export declare interface ArcCurve3 {
1591
1671
  readonly closed?: boolean;
1592
1672
  }
1593
1673
 
1594
- /** Checks regular-grid dimensions and bounds allocation before evaluating any height samples. */
1674
+ /** Checks grid dimensions, coordinate precision, and allocation bounds before evaluating heights. */
1595
1675
  export declare function preflightHeightfield(options: HeightfieldOptions, limits?: HeightfieldMeshLimits): HeightfieldPreflight;
1596
1676
 
1597
1677
  /**
@@ -2148,989 +2228,1068 @@ export declare interface ArcCurve3 {
2148
2228
  readonly radius: number;
2149
2229
  }
2150
2230
 
2151
- /** Samples a planar curve with the same guarantees and policy as spatial sampling.
2152
- * @remarks Private spatial scratch math is shared, while only final planar vectors are copied and
2153
- * frozen. At stationary tangents, outgoing secants are preferred and endpoints use a backward fallback.
2154
- * @example
2155
- * ```ts
2156
- * const turn = sampleCurve2({kind: "arc", center: [0,0], radius: 10, sweepDegrees: 90});
2157
- * ```
2158
- */
2159
- export declare function sampleCurve2(curve: Curve2, options?: CurveSamplingOptions): SampledCurve2;
2160
-
2161
- /**
2162
- * Samples a spatial curve, preserving endpoints and directed unit tangents.
2163
- * @remarks Exact counts use uniform curve parameters, not equal physical distances. Adaptive cubics
2164
- * bound the full control hull. Full-circle arcs repeat their endpoint; closed polylines do not.
2165
- * @example
2166
- * ```ts
2167
- * const path = sampleCurve3({kind: "cubic", start: [0,0,0], control1: [5,0,0], control2: [5,5,5], end: [10,5,5]});
2168
- * ```
2169
- */
2170
- export declare function sampleCurve3(curve: Curve3, options?: CurveSamplingOptions): SampledCurve3;
2171
-
2172
- /**
2173
- * Samples a complete external involute gear boundary in the XY plane.
2174
- *
2175
- * The returned loop is counter-clockwise, closed implicitly without a repeated
2176
- * seam point, and contains no holes. Its center is the origin and its axis is
2177
- * +Z. Bore, hub, keyway, twist, and face-width choices remain generator-owned.
2178
- */
2179
- export declare function sampleCylindricalGearOutline(spec: CylindricalGearSpec, options?: CylindricalGearOutlineOptions): Loop2;
2180
-
2181
- /** Immutable planar points and corresponding directed unit tangents. */
2182
- export declare interface SampledCurve2 {
2183
- /** Curves retain both endpoints, including full-circle seams; closed resampling omits its seam. */
2184
- readonly points: readonly Vec2[];
2185
- /** Directed unit vectors; stationary derivatives use the nearest usable direction. */
2186
- readonly tangents: readonly Vec2[];
2187
- }
2188
-
2189
- /**
2190
- * Immutable spatial points and corresponding directed unit tangents.
2191
- */
2192
- export declare interface SampledCurve3 {
2193
- /** Curves retain both endpoints, including full-circle seams; closed resampling omits its seam. */
2194
- readonly points: readonly Vec3[];
2195
- /** Directed unit vectors; stationary derivatives use the nearest usable direction. */
2196
- readonly tangents: readonly Vec3[];
2197
- }
2198
-
2199
- /** Sampled paths plus conventional pitch and lead measurements. */
2200
- export declare interface SampledThreadHelices {
2201
- /** Axial advance over one revolution, equal to `pitch * starts`. */
2202
- readonly lead: number;
2203
- /** One immutable sampled path for each thread start. */
2204
- readonly paths: readonly Path3[];
2205
- /** Adjacent axial thread spacing in millimetres. */
2206
- readonly pitch: number;
2207
- /** Number of revolutions represented by each path. */
2208
- readonly turns: number;
2209
- }
2210
-
2211
- /**
2212
- * Creates `segments + 1` points including exact helix endpoints from finite positive dimensions.
2213
- * Integrated weights must remain finite. The maxPathPoints ceiling defaults to 100000; excessive
2214
- * exact counts reject before evaluating axial weights or allocating sample arrays.
2215
- */
2216
- export declare const sampleHelix: ({ turns, radius, height, segments, limits, axialWeight, }: SampleHelixOptions) => readonly Vec3[];
2217
-
2218
- /** Options for a sampled +Z helix with millimetre dimensions. */
2219
- export declare interface SampleHelixOptions {
2220
- /** Number of complete rotations around +Z. */
2221
- readonly turns: number;
2222
- /** Explicit output allocation ceilings. */
2223
- readonly limits?: Partial<GeometrySamplingLimits>;
2224
- /** Constant radial distance from the +Z axis. */
2225
- readonly radius: number;
2226
- /** Total axial advance from the first point to the last. */
2227
- readonly height: number;
2228
- /** Number of sampled line segments; the result contains one additional endpoint. */
2229
- readonly segments: number;
2230
- /**
2231
- * Relative axial advance at a normalized turn position. Values are integrated
2232
- * and normalized, so the final endpoint is always exactly `height`.
2233
- */
2234
- readonly axialWeight?: (t: number) => number;
2235
- }
2236
-
2237
2231
  /**
2238
- * Samples the center opening and tooth spaces used to subtract an internal ring gear.
2232
+ * Samples 2–32 connected line/cubic segments into a simple, nonzero-area, immutable CCW XY loop.
2233
+ * Physical scaling precedes adaptive curve sampling; the final end must repeat start exactly.
2234
+ * Shared anchors and the closing seam are emitted once. Winding normalization may change the
2235
+ * starting vertex. The sampled loop is checked for self-intersection and degeneracy by
2236
+ * `normalizeLoop2`; this is a single contour without holes. No editor modes or normalized
2237
+ * coordinate range are required. No native engine, SDK, or ambient resolution is used.
2239
2238
  *
2240
- * Internal tooth tips lie one addendum below the pitch radius and their roots lie one
2241
- * dedendum above it. At the pitch circle, positive backlash widens each sampled space
2242
- * tangentially. The returned CCW loop encloses the center and is intended to be reversed
2243
- * when used as a region hole.
2244
- */
2245
- export declare function sampleInternalCylindricalGearSpaceOutline(spec: CylindricalGearSpec, options?: CylindricalGearOutlineOptions): Loop2;
2246
-
2247
- /**
2248
- * Samples 1–31 line/cubic segments into a deeply immutable open [radius,height] polyline.
2249
- * Anchors must progress strictly upward; nonnegative-radius cubic controls must have ordered
2250
- * heights between their endpoints. Cubics use de Casteljau subdivision with a conservative
2251
- * control-hull chord-error bound. Lines also obey the optional physical edge-length ceiling.
2252
- * Neither normalized coordinates nor editor metadata are required. Endpoints are retained once;
2253
- * no axis closure, winding normalization, or manufacturing repair is performed.
2254
- *
2255
- * @param curve - Open outline in millimetres unless the positive scales convert its coordinates.
2256
- * @param options - Physical resolution and output budget; defaults to 4096 vertices.
2257
- * @returns Frozen open polyline in millimetres, ordered from lowest to highest anchor.
2258
- * @throws {@link GeometryError} for invalid coordinates, order, scale, or exceeded subdivision budget.
2239
+ * @param curve - Closed contour in millimetres unless positive scales convert its coordinates.
2240
+ * @param options - Physical resolution and unique vertex budget; defaults to 4096 vertices.
2241
+ * @returns Frozen counterclockwise loop in millimetres, without a repeated seam endpoint.
2242
+ * @throws {@link GeometryError} for invalid data, topology, scale, or exceeded sampling budgets.
2259
2243
  *
2260
2244
  * @example
2261
2245
  * ```ts
2262
- * const side = sampleOpenProfile({
2263
- * start: { radius: 0.5, height: 0 },
2264
- * segments: [{ type: "line", end: { radius: 1, height: 1 } }],
2265
- * }, { radiusScale: 12, heightScale: 30 });
2246
+ * const section = sampleCrossSection({
2247
+ * start: { x: 0, y: 0 },
2248
+ * segments: [
2249
+ * { type: "line", end: { x: 1, y: 0 } },
2250
+ * { type: "line", end: { x: 0.5, y: 1 } },
2251
+ * { type: "line", end: { x: 0, y: 0 } },
2252
+ * ],
2253
+ * }, { widthScale: 20, heightScale: 12 });
2266
2254
  * ```
2267
2255
  */
2268
- export declare function sampleOpenProfile(curve: OpenProfileCurve, options?: SampleOpenProfileOptions): readonly Vec2[];
2256
+ export declare function sampleCrossSection(curve: CrossSectionCurve, options?: SampleCrossSectionOptions): Loop2;
2269
2257
 
2270
- /** Physical scaling and bounded adaptive subdivision for an open profile. */
2271
- export declare interface SampleOpenProfileOptions {
2272
- /** Positive radius scale; use the desired maximum radius for normalized coordinates. Defaults to 1. */
2273
- readonly radiusScale?: number;
2274
- /** Positive height scale; use the desired total height for normalized coordinates. Defaults to 1. */
2258
+ /** Physical scaling, subdivision policy, and output ceilings for one closed contour. */
2259
+ export declare interface SampleCrossSectionOptions {
2260
+ /** Positive horizontal scale; normalized inputs span this width envelope. Defaults to 1. */
2261
+ readonly widthScale?: number;
2262
+ /** Positive vertical scale; normalized inputs span this height envelope. Defaults to 1. */
2275
2263
  readonly heightScale?: number;
2276
- /** Shared physical policy, evaluated after scaling; exact circular counts do not affect curves. */
2264
+ /** Physical policy evaluated after scaling, using the shared curve sampler. */
2277
2265
  readonly resolution?: GeometryResolution;
2278
- /** Maximum output vertex count within maxProfilePoints. Defaults to the smaller of 4096 and that ceiling. */
2266
+ /** Unique output vertex ceiling, at least three, within maxProfilePoints. Defaults to min(4096, maxProfilePoints). */
2279
2267
  readonly maximumVertices?: number;
2280
- /** Explicit profile and circular allocation ceilings. */
2268
+ /** Selected profile and per-segment path ceilings; omitted values use package defaults. */
2281
2269
  readonly limits?: Partial<GeometrySamplingLimits>;
2282
2270
  }
2283
2271
 
2284
- /**
2285
- * Samples the open top boundary of a finite rack in its XY pitch plane.
2286
- *
2287
- * X follows rack travel, Y is tooth height, and the pitch line is `Y = 0`.
2288
- * The path begins and ends on the root line, omits duplicate adjacent points,
2289
- * and leaves base thickness, mounting features, extrusion, and helical sweep to
2290
- * the owning generator.
2291
- */
2292
- export declare function sampleRackToothPath(spec: RackPitchSpec, limits?: Partial<GeometrySamplingLimits>): Path2;
2293
-
2294
- /**
2295
- * Samples a prepared text layout without shaping text again or loading a font.
2296
- *
2297
- * @param layout - Immutable millimetre paths and measurements retained from text preparation.
2298
- * @param resolution - Explicit curve sampling policy; omitted uses the pure default policy.
2299
- * @param limits - Explicit profile and circular allocation ceilings.
2300
- * @returns Frozen contours with original glyph winding and no repeated closing vertex.
2301
- * @throws GeometryError for empty outlines, invalid paths or policies, over 1000 paths or selected sampling ceilings.
2302
- */
2303
- export declare function sampleTextContours(layout: VectorTextLayout, resolution?: GeometryResolution, limits?: Partial<GeometrySamplingLimits>): readonly Loop2[];
2304
-
2305
- /**
2306
- * Samples evenly phased thread helices with finite `lead = pitch * starts`.
2307
- * All starts together respect maxPathPoints (default 100000); excessive counts fail before allocation.
2272
+ /** Samples a planar curve with the same guarantees and policy as spatial sampling.
2273
+ * @remarks Private spatial scratch math is shared, while only final planar vectors are copied and
2274
+ * frozen. At stationary tangents, outgoing secants are preferred and endpoints use a backward fallback.
2275
+ * @example
2276
+ * ```ts
2277
+ * const turn = sampleCurve2({kind: "arc", center: [0,0], radius: 10, sweepDegrees: 90});
2278
+ * ```
2308
2279
  */
2309
- export declare function sampleThreadHelices(options: ThreadHelixOptions): SampledThreadHelices;
2280
+ export declare function sampleCurve2(curve: Curve2, options?: CurveSamplingOptions): SampledCurve2;
2310
2281
 
2311
2282
  /**
2312
- * Multiplies a vector by a dimensionless scalar.
2283
+ * Samples a spatial curve, preserving endpoints and directed unit tangents.
2284
+ * @remarks Exact counts use uniform curve parameters, not equal physical distances. Adaptive cubics
2285
+ * bound the full control hull. Full-circle arcs repeat their endpoint; closed polylines do not.
2313
2286
  * @example
2314
2287
  * ```ts
2315
- * scale3([1, 2, 3], 2); // [2, 4, 6]
2288
+ * const path = sampleCurve3({kind: "cubic", start: [0,0,0], control1: [5,0,0], control2: [5,5,5], end: [10,5,5]});
2316
2289
  * ```
2317
2290
  */
2318
- export declare const scale3: (vector: Vec3, scale: number) => Vec3;
2291
+ export declare function sampleCurve3(curve: Curve3, options?: CurveSamplingOptions): SampledCurve3;
2319
2292
 
2320
2293
  /**
2321
- * Creates an immutable axis-aligned scale transform.
2322
- *
2323
- * Negative components are reflections. Zero components are rejected because
2324
- * they collapse volume and cannot be inverted.
2294
+ * Samples a complete external involute gear boundary in the XY plane.
2325
2295
  *
2326
- * @param factors - Finite, non-zero XYZ scale factors.
2327
- * @returns A frozen row-major transform.
2296
+ * The returned loop is counter-clockwise, closed implicitly without a repeated
2297
+ * seam point, and contains no holes. Its center is the origin and its axis is
2298
+ * +Z. Bore, hub, keyway, twist, and face-width choices remain generator-owned.
2328
2299
  */
2329
- export declare function scaleTransform3(factors: Vec3): Transform3;
2330
-
2331
- /** Returns the signed area of a non-duplicated loop; positive means CCW. */
2332
- export declare function signedAreaLoop2(loop: Loop2): number;
2333
-
2334
- /** A cubic corner transition with zero curvature at its straight tangent joins. */
2335
- export declare interface SmoothEdgeTreatment {
2336
- /** Selects continuous-curvature cubic rounding, rather than a circular radius. */
2337
- readonly kind: "smooth";
2338
- /** Positive tangent setbacks, equal or [first, second], in millimetres. */
2339
- readonly distance: number | readonly [first: number, second: number];
2340
- /** Exact cubic interval count, positive; overrides physical sampling. */
2341
- readonly segments?: number;
2342
- /** Physical chord/edge-length sampling; circularSegments does not describe a cubic. */
2343
- readonly resolution?: GeometryResolution;
2344
- /** Explicit sampling ceilings, bounded by the host policy. */
2345
- readonly limits?: Partial<GeometrySamplingLimits>;
2346
- }
2300
+ export declare function sampleCylindricalGearOutline(spec: CylindricalGearSpec, options?: CylindricalGearOutlineOptions): Loop2;
2347
2301
 
2348
- /**
2349
- * Exactly one radius or diameter, placement, and tessellation for an origin-centered sphere.
2350
- */
2351
- export declare type SphereOptions = CircularPrimitiveOptions & PrimitivePlacement & ({
2352
- /** Positive radius in millimetres; mutually exclusive with diameter. */
2353
- readonly radius: number;
2354
- /** Full diameter is unavailable when radius is supplied. */
2355
- readonly diameter?: never;
2356
- } | {
2357
- /** Positive full diameter in millimetres; mutually exclusive with radius. */
2358
- readonly diameter: number;
2359
- /** Radius is unavailable when diameter is supplied. */
2360
- readonly radius?: never;
2361
- });
2362
-
2363
- /** Square profile with equal crest and root widths. */
2364
- export declare interface SquareThreadProfileSpec extends ThreadProfileBaseSpec {
2365
- /** Selects the square profile family. */
2366
- readonly kind: "square";
2367
- /**
2368
- * Radial depth in millimetres.
2369
- * @defaultValue `pitch / 2`
2370
- */
2371
- readonly depth?: number;
2302
+ /** Immutable planar points and corresponding directed unit tangents. */
2303
+ export declare interface SampledCurve2 {
2304
+ /** Curves retain both endpoints, including full-circle seams; closed resampling omits its seam. */
2305
+ readonly points: readonly Vec2[];
2306
+ /** Directed unit vectors; stationary derivatives use the nearest usable direction. */
2307
+ readonly tangents: readonly Vec2[];
2372
2308
  }
2373
2309
 
2374
2310
  /**
2375
- * Creates a centered CCW alternating-radius star within the selected profile sampling ceiling.
2376
- *
2377
- * @example Five-point outline
2378
- * ```ts
2379
- * starLoop(12, 5, 6);
2380
- * ```
2381
- */
2382
- export declare const starLoop: (outerRadius: number, points: number, innerRadius?: number, limits?: Partial<GeometrySamplingLimits>) => readonly Vec2[];
2383
-
2384
- /** End-cap treatment for an open stroked path. */
2385
- export declare type StrokePathCap = "butt" | "round" | "square";
2386
-
2387
- /** Join treatment where adjacent stroked path segments meet. */
2388
- export declare type StrokePathJoin = "bevel" | "miter" | "round";
2389
-
2390
- /**
2391
- * Converts a sampled millimetre path into the filled region covered by a centered stroke.
2392
- *
2393
- * Closed paths omit a duplicated seam point. Zero-length sampled segments are ignored, while the
2394
- * effective path must still contain visible length. Round caps and joins use deterministic physical
2395
- * resolution. Bevels fill the outer corner triangle; miters extend the outer edges to their
2396
- * intersection, falling back to bevels above SVG's default miter limit of 4.
2311
+ * Immutable spatial points and corresponding directed unit tangents.
2397
2312
  */
2398
- export declare function strokePathRegion(path: Path2, options: StrokePathRegionOptions): Region2;
2313
+ export declare interface SampledCurve3 {
2314
+ /** Curves retain both endpoints, including full-circle seams; closed resampling omits its seam. */
2315
+ readonly points: readonly Vec3[];
2316
+ /** Directed unit vectors; stationary derivatives use the nearest usable direction. */
2317
+ readonly tangents: readonly Vec3[];
2318
+ }
2399
2319
 
2400
- /** Physical stroke and topology controls for {@link strokePathRegion}. */
2401
- export declare interface StrokePathRegionOptions {
2402
- /** Explicit path, circular and expanded-profile allocation ceilings. */
2403
- readonly limits?: Partial<GeometrySamplingLimits>;
2404
- /** Treat the path as a closed non-duplicated loop. Default: `false`. */
2405
- readonly closed?: boolean;
2406
- /** End-cap treatment for an open path. Ignored for closed paths. Default: `butt`. */
2407
- readonly cap?: StrokePathCap;
2408
- /** Corner treatment; miters exceeding SVG's default limit of 4 become bevels. Default: `miter`. */
2409
- readonly join?: StrokePathJoin;
2410
- /** Physical tessellation policy for round caps and joins. */
2411
- readonly resolution?: GeometryResolution;
2412
- /** Positive total stroke width in millimetres, centered on the sampled path. */
2413
- readonly width: number;
2320
+ /** Sampled paths plus conventional pitch and lead measurements. */
2321
+ export declare interface SampledThreadHelices {
2322
+ /** Axial advance over one revolution, equal to `pitch * starts`. */
2323
+ readonly lead: number;
2324
+ /** One immutable sampled path for each thread start. */
2325
+ readonly paths: readonly Path3[];
2326
+ /** Adjacent axial thread spacing in millimetres. */
2327
+ readonly pitch: number;
2328
+ /** Number of revolutions represented by each path. */
2329
+ readonly turns: number;
2414
2330
  }
2415
2331
 
2416
2332
  /**
2417
- * Subtracts `b` from `a`.
2418
- * @example
2419
- * ```ts
2420
- * subtract3([4, 5, 6], [1, 2, 3]); // [3, 3, 3]
2421
- * ```
2333
+ * Creates `segments + 1` points including exact helix endpoints from finite positive dimensions.
2334
+ * Integrated weights must remain finite. The maxPathPoints ceiling defaults to 100000; excessive
2335
+ * exact counts reject before evaluating axial weights or allocating sample arrays.
2422
2336
  */
2423
- export declare const subtract3: (a: Vec3, b: Vec3) => Vec3;
2337
+ export declare const sampleHelix: ({ turns, radius, height, segments, limits, axialWeight, }: SampleHelixOptions) => readonly Vec3[];
2424
2338
 
2425
- /** Sampling controls for deterministic SVG-to-region conversion. */
2426
- export declare interface SvgImportOptions {
2427
- /** Explicit profile and circular allocation ceilings; bounded SVG source/work limits remain fixed. */
2339
+ /** Options for a sampled +Z helix with millimetre dimensions. */
2340
+ export declare interface SampleHelixOptions {
2341
+ /** Number of complete rotations around +Z. */
2342
+ readonly turns: number;
2343
+ /** Explicit output allocation ceilings. */
2428
2344
  readonly limits?: Partial<GeometrySamplingLimits>;
2429
- /** Exact segments for a complete ellipse or round stroke feature. */
2430
- readonly circularSegments?: number;
2431
- /** Operation-level physical tessellation policy over the active model-wide policy. */
2432
- readonly resolution?: GeometryResolution;
2345
+ /** Constant radial distance from the +Z axis. */
2346
+ readonly radius: number;
2347
+ /** Total axial advance from the first point to the last. */
2348
+ readonly height: number;
2349
+ /** Number of sampled line segments; the result contains one additional endpoint. */
2350
+ readonly segments: number;
2433
2351
  /**
2434
- * `"center"` places the viewport center at the origin. `"document"` places its converted
2435
- * lower-left corner at the origin. Default: `"center"`.
2352
+ * Relative axial advance at a normalized turn position. Values are integrated
2353
+ * and normalized, so the final endpoint is always exactly `height`.
2436
2354
  */
2437
- readonly origin?: "center" | "document";
2438
- }
2439
-
2440
- /** Exact normalized SVG region plus bounded source, geometry, and safe-repair diagnostics. */
2441
- export declare interface SvgRegionPreflight {
2442
- /** Physical and final-topology measurements of `region`. */
2443
- readonly geometry: SvgRegionPreflightGeometryMetrics;
2444
- /** Appearance-preserving cleanup observed during parsing and normalization. */
2445
- readonly repairs: SvgRegionPreflightRepairs;
2446
- /** Canonical millimetre, Y-up geometry. */
2447
- readonly region: Region2;
2448
- /** Bounded source and flattening complexity measurements. */
2449
- readonly source: SvgRegionPreflightSourceMetrics;
2450
- }
2451
-
2452
- /** Physical and final-topology facts for a normalized imported SVG region. */
2453
- export declare interface SvgRegionPreflightGeometryMetrics {
2454
- /** Filled area in square millimetres. */
2455
- readonly area: number;
2456
- /** Millimetre bounds, or `null` when no painted region remains. */
2457
- readonly bounds: Bounds2 | null;
2458
- /** Disconnected filled polygons in the final region. */
2459
- readonly components: number;
2460
- /** Exterior and hole boundary count in the final region. */
2461
- readonly contours: number;
2462
- /** Interior boundary count in the final region. */
2463
- readonly holes: number;
2464
- /** Shortest final boundary edge in millimetres, or `null` for an empty region. */
2465
- readonly minEdgeLength: number | null;
2466
- /** Final boundary edges shorter than the conservative 0.01 mm indicator. */
2467
- readonly shortEdges: number;
2468
- /** Components with less than 0.01 square millimetres of filled area. */
2469
- readonly tinyIslands: number;
2470
- /** Non-duplicated boundary vertices in the final normalized region. */
2471
- readonly vertices: number;
2472
- }
2473
-
2474
- /** Visible, appearance-preserving cleanup counters from bounded SVG import. */
2475
- export declare interface SvgRegionPreflightRepairs {
2476
- /** Graphics elements with neither a visible fill nor a positive-width visible stroke. */
2477
- readonly invisibleElements: number;
2478
- /** Open filled subpaths closed by SVG fill semantics without closing their strokes. */
2479
- readonly implicitFilledClosures: number;
2480
- /** Visibly painted elements whose fill and stroke both resolved to empty geometry. */
2481
- readonly emptyElements: number;
2482
- /** Consecutive repeated flattened vertices discarded before topology resolution. */
2483
- readonly removedDuplicateVertices: number;
2484
- /** Explicit repeated seam vertices removed from otherwise closed contours. */
2485
- readonly removedSeamVertices: number;
2486
- }
2487
-
2488
- /** Bounded source-complexity facts collected while parsing one SVG document. */
2489
- export declare interface SvgRegionPreflightSourceMetrics {
2490
- /** UTF-8 source size, capped at 256 KiB before parsing. */
2491
- readonly bytes: number;
2492
- /** Renderable shape elements, capped at 500; containers and metadata are excluded. */
2493
- readonly elements: number;
2494
- /** Flattened vertices emitted before fill, stroke, and clipping operations. */
2495
- readonly emittedVertices: number;
2496
- /** Path endpoints and control vertices parsed before adaptive flattening. */
2497
- readonly parsedVertices: number;
2355
+ readonly axialWeight?: (t: number) => number;
2498
2356
  }
2499
2357
 
2500
2358
  /**
2501
- * Sweeps one explicitly ordered point loop, with caps or a geometrically matching closed seam.
2359
+ * Samples the center opening and tooth spaces used to subtract an internal ring gear.
2502
2360
  *
2503
- * @example Sweep point data along a bent path
2504
- * ```ts
2505
- * const profile = rectangleLoop({ size: [6, 3] });
2506
- * sweepMesh(profile, [[0, 0, 0], [0, 0, 15], [10, 0, 25]], {
2507
- * orientation: { kind: "transport", initialNormal: [0, 1, 0] },
2508
- * });
2509
- * ```
2361
+ * Internal tooth tips lie one addendum below the pitch radius and their roots lie one
2362
+ * dedendum above it. At the pitch circle, positive backlash widens each sampled space
2363
+ * tangentially. The returned CCW loop encloses the center and is intended to be reversed
2364
+ * when used as a region hole.
2510
2365
  */
2511
- export declare function sweepMesh(profile: Loop2, path: readonly Vec3[], options?: SweepOptions): TriangleMesh;
2366
+ export declare function sampleInternalCylindricalGearSpaceOutline(spec: CylindricalGearSpec, options?: CylindricalGearOutlineOptions): Loop2;
2512
2367
 
2513
2368
  /**
2514
- * Controls shared by pure mesh construction and filled modeling sweeps.
2515
- */
2516
- export declare interface SweepOptions {
2517
- /** Join the path's last station to its first. Open paths retain watertight end caps. */
2518
- readonly closed?: boolean;
2519
- /** Explicit output and sampling allocation ceilings. */
2520
- readonly limits?: Partial<ModelingLimits>;
2521
- /** Explicit frame policy; default transport minimizes rotations, initially projecting +X then +Y then +Z. */
2522
- readonly orientation?: SweepOrientation;
2523
- /** Physical sampling of nonzero twist; inserted stations retain authored station controls. */
2524
- readonly resolution?: GeometryResolution;
2525
- /** Total additional profile rotation in degrees, with progression selected by twistBy. */
2526
- readonly twistDegrees?: number;
2527
- /** Twist advances by physical path length (default), or normalized authored station position, including a closed seam gap. */
2528
- readonly twistBy?: "length" | "stations";
2529
- /** Positive uniform/XY scale, or one XY pair per path station. Defaults to one. */
2530
- readonly scale?: number | Vec2 | readonly Vec2[];
2531
- /** Corresponding point-index advance at a rotationally equivalent closed seam. */
2532
- readonly seamProfileOffset?: number;
2533
- }
2534
-
2535
- /**
2536
- * Explicit profile-X frame policy; all normals are directed, and selected singular policies reject.
2537
- */
2538
- export declare type SweepOrientation = {
2539
- /** Minimizes frame rotation by parallel transport. */
2540
- readonly kind: "transport";
2541
- /** Initial profile +X guide, projected perpendicular to the first tangent. */
2542
- readonly initialNormal?: Vec3;
2543
- } | {
2544
- /** Projects one fixed world-space normal at every path station. */
2545
- readonly kind: "fixed-normal";
2546
- /** Directed profile +X guide; must not be parallel to any local tangent. */
2547
- readonly normal: Vec3;
2548
- } | {
2549
- /** Uses an explicitly directed normal callback at each original normalized station. */
2550
- readonly kind: "guide";
2551
- /** Finite profile +X guide callback, evaluated once per original path station. */
2552
- readonly normal: PathNormalGuide;
2553
- } | {
2554
- /** Uses sampled curvature normals; zero-curvature stations reject. */
2555
- readonly kind: "frenet";
2556
- };
2557
-
2558
- /** End bevel controls shared by threaded rods and cutters. */
2559
- export declare interface ThreadBevelOptions {
2560
- /** Apply a 45-degree bevel at Z=0. */
2561
- readonly bevelBottom?: boolean;
2562
- /**
2563
- * Axial bevel extent in millimetres. Active blunt ends default to one sixth of the compensated
2564
- * male minor radius or female major radius; other ends default to the profile depth.
2565
- */
2566
- readonly bevelSize?: number;
2567
- /** Apply a 45-degree bevel at Z=length. */
2568
- readonly bevelTop?: boolean;
2569
- }
2570
-
2571
- /** Inputs for resolving one shared circular facet count for a mating thread pair. */
2572
- export declare interface ThreadCircularSegmentsOptions {
2573
- /** Explicit circular allocation ceiling for the shared mating grid. */
2574
- readonly limits?: Partial<GeometrySamplingLimits>;
2575
- /** Printable fit whose larger compensated female envelope governs tessellation. */
2576
- readonly fit?: PrintableThreadFit | PrintableThreadFitPolicy;
2577
- /** Nominal major diameter before role-specific compensation. */
2578
- readonly nominalMajorDiameter: number;
2579
- /**
2580
- * Maximum active female face outset beyond the compensated major envelope, in millimetres.
2581
- * This keeps a compensated male/female pair on one role-independent grid when an internal
2582
- * cutter has an enlarged entrance bevel. Default: `0`.
2369
+ * Samples 1–31 line/cubic segments into a deeply immutable open [radius,height] polyline.
2370
+ * Anchors must progress strictly upward; nonnegative-radius cubic controls must have ordered
2371
+ * heights between their endpoints. Cubics use de Casteljau subdivision with a conservative
2372
+ * control-hull chord-error bound. Lines also obey the optional physical edge-length ceiling.
2373
+ * Neither normalized coordinates nor editor metadata are required. Endpoints are retained once;
2374
+ * no axis closure, winding normalization, or manufacturing repair is performed.
2375
+ *
2376
+ * @param curve - Open outline in millimetres unless the positive scales convert its coordinates.
2377
+ * @param options - Physical resolution and output budget; defaults to 4096 vertices.
2378
+ * @returns Frozen open polyline in millimetres, ordered from lowest to highest anchor.
2379
+ * @throws {@link GeometryError} for invalid coordinates, order, scale, or exceeded subdivision budget.
2380
+ *
2381
+ * @example
2382
+ * ```ts
2383
+ * const side = sampleOpenProfile({
2384
+ * start: { radius: 0.5, height: 0 },
2385
+ * segments: [{ type: "line", end: { radius: 1, height: 1 } }],
2386
+ * }, { radiusScale: 12, heightScale: 30 });
2387
+ * ```
2583
2388
  */
2584
- readonly maximumRadialOutset?: number;
2585
- /** Validated mating profile whose pitch and flank capacities govern tessellation. */
2586
- readonly profile: ThreadProfile;
2587
- /** Physical or exact circular resolution policy. */
2588
- readonly resolution?: GeometryResolution;
2589
- /** Number of phased starts. Default: `1`. */
2590
- readonly starts?: number;
2591
- }
2592
-
2593
- /** Options for compensating nominal male or female thread diameters. */
2594
- export declare interface ThreadCompensationOptions {
2595
- /** Named policy or explicit caller-calibrated allowances. */
2596
- readonly fit?: PrintableThreadFit | PrintableThreadFitPolicy;
2597
- /** Nominal sharp or truncated major diameter in millimetres. */
2598
- readonly nominalMajorDiameter: number;
2599
- /** Male or female geometry being compensated. */
2600
- readonly role: ThreadRole;
2601
- /** Radial depth from major to minor envelope in millimetres. */
2602
- readonly threadDepth: number;
2603
- /** Optional numerical tolerance overrides. */
2604
- readonly tolerance?: GeometryToleranceOptions;
2605
- }
2606
-
2607
- /** Nut-edge bevel selection. */
2608
- export declare type ThreadedNutBevel = "automatic" | "both" | "inside" | "none" | "outside";
2609
-
2610
- /**
2611
- * Options for a compensated nut with an internal thread.
2612
- */
2613
- export declare interface ThreadedNutOptions extends Omit<InternalThreadCutterOptions, "bevelBottom" | "bevelSize" | "bevelTop" | "length"> {
2614
- /** Nut body bevel selection. Default: `automatic`. */
2615
- readonly bevel?: ThreadedNutBevel;
2616
- /** Optional physical policy for a round body, independent of the thread's matched facet grid. */
2617
- readonly bodyResolution?: GeometryResolution;
2618
- /** 45-degree body chamfer extent. Default: `min(profile.depth, thickness/4)`. */
2619
- readonly chamferSize?: number;
2620
- /** Leave the bottom outside edge flat for build-plate adhesion. Default: `false`. */
2621
- readonly flushBuildPlateBottom?: boolean;
2622
- /** Nut body shape. */
2623
- readonly shape: ThreadedNutShape;
2624
- /** Nut thickness along +Z in millimetres. */
2625
- readonly thickness: number;
2626
- /** Across-flats width for hex/square or diameter for round, in millimetres. */
2627
- readonly width: number;
2628
- }
2389
+ export declare function sampleOpenProfile(curve: OpenProfileCurve, options?: SampleOpenProfileOptions): readonly Vec2[];
2390
+
2391
+ /** Physical scaling and bounded adaptive subdivision for an open profile. */
2392
+ export declare interface SampleOpenProfileOptions {
2393
+ /** Positive radius scale; use the desired maximum radius for normalized coordinates. Defaults to 1. */
2394
+ readonly radiusScale?: number;
2395
+ /** Positive height scale; use the desired total height for normalized coordinates. Defaults to 1. */
2396
+ readonly heightScale?: number;
2397
+ /** Shared physical policy, evaluated after scaling; exact circular counts do not affect curves. */
2398
+ readonly resolution?: GeometryResolution;
2399
+ /** Maximum output vertex count within maxProfilePoints. Defaults to the smaller of 4096 and that ceiling. */
2400
+ readonly maximumVertices?: number;
2401
+ /** Explicit profile and circular allocation ceilings. */
2402
+ readonly limits?: Partial<GeometrySamplingLimits>;
2403
+ }
2629
2404
 
2630
- /** Allocation-free body, cutter, and end-face facts resolved for a threaded nut. */
2631
- export declare interface ThreadedNutPreflight {
2632
- /** Polygon segment count used by the nut body. */
2633
- readonly bodySegments: number;
2634
- /** Shared 45-degree chamfer size applied to the selected body and cutter edges. */
2635
- readonly chamferSize: number;
2636
- /** Maximum compensated cutter radius at either requested face. */
2637
- readonly cutterFaceRadius: number;
2638
- /** Minimum nut-body inradius across the requested top and bottom faces. */
2639
- readonly minimumBodyFaceInradius: number;
2640
- /** Smallest radial wall left between the body and cutter at either requested face. */
2641
- readonly minimumFaceWall: number;
2642
- /** Conservative allocation facts for the exact extended internal-thread cutter mesh. */
2643
- readonly thread: HelicalThreadSolidMeshPreflight;
2644
- /** Start-aligned circular facet count used by the compensated thread cutter. */
2645
- readonly threadCircularSegments: number;
2646
- }
2405
+ /**
2406
+ * Samples the open top boundary of a finite rack in its XY pitch plane.
2407
+ *
2408
+ * X follows rack travel, Y is tooth height, and the pitch line is `Y = 0`.
2409
+ * The path begins and ends on the root line, omits duplicate adjacent points,
2410
+ * and leaves base thickness, mounting features, extrusion, and helical sweep to
2411
+ * the owning generator.
2412
+ */
2413
+ export declare function sampleRackToothPath(spec: RackPitchSpec, limits?: Partial<GeometrySamplingLimits>): Path2;
2647
2414
 
2648
- /**
2649
- * Supported printable nut body shapes.
2650
- */
2651
- export declare type ThreadedNutShape = "hex" | "round" | "square";
2415
+ /**
2416
+ * Samples a prepared text layout without shaping text again or loading a font.
2417
+ *
2418
+ * @param layout - Immutable millimetre paths and measurements retained from text preparation.
2419
+ * @param resolution - Explicit curve sampling policy; omitted uses the pure default policy.
2420
+ * @param limits - Explicit profile and circular allocation ceilings.
2421
+ * @returns Frozen contours with original glyph winding and no repeated closing vertex.
2422
+ * @throws GeometryError for empty outlines, invalid paths or policies, over 1000 paths or selected sampling ceilings.
2423
+ */
2424
+ export declare function sampleTextContours(layout: VectorTextLayout, resolution?: GeometryResolution, limits?: Partial<GeometrySamplingLimits>): readonly Loop2[];
2652
2425
 
2653
- /**
2654
- * Options for a compensated external threaded rod along +Z.
2655
- */
2656
- export declare interface ThreadedRodOptions extends Omit<HelicalThreadRidgeMeshOptions, "majorDiameter">, ThreadBevelOptions {
2657
- /** Printable fit or caller-calibrated allowances. Default: `normal`. */
2658
- readonly fit?: PrintableThreadFit | PrintableThreadFitPolicy;
2659
- /** Nominal major diameter before male compensation. */
2660
- readonly nominalMajorDiameter: number;
2661
- }
2426
+ /**
2427
+ * Samples evenly phased thread helices with finite `lead = pitch * starts`.
2428
+ * All starts together respect maxPathPoints (default 100000); excessive counts fail before allocation.
2429
+ */
2430
+ export declare function sampleThreadHelices(options: ThreadHelixOptions): SampledThreadHelices;
2662
2431
 
2663
- /** End shape of a generated helical ridge. */
2664
- export declare type ThreadEndStyle = "blunt" | "standard" | "tapered";
2432
+ /**
2433
+ * Multiplies a vector by a dimensionless scalar.
2434
+ * @example
2435
+ * ```ts
2436
+ * scale3([1, 2, 3], 2); // [2, 4, 6]
2437
+ * ```
2438
+ */
2439
+ export declare const scale3: (vector: Vec3, scale: number) => Vec3;
2665
2440
 
2666
- /** Axial end controls for a generated ridge. */
2667
- export declare interface ThreadEndTreatmentOptions {
2668
- /**
2669
- * Ridge shape at the lower working boundary. `blunt` ends at full profile height, `standard`
2670
- * clips the periodic profile at the face, and `tapered` ramps out from the minor envelope.
2671
- * @defaultValue `"blunt"`
2672
- */
2673
- readonly bottom?: ThreadEndStyle;
2674
- /**
2675
- * Non-negative unthreaded envelope length reserved at each non-standard end, in millimetres.
2676
- * Active blunt bevels may raise this reservation to the effective bevel size.
2677
- * @defaultValue `0`
2678
- */
2679
- readonly endLength?: number;
2680
- /**
2681
- * Radial envelope toward which a blunt lead-in collapses.
2682
- * @defaultValue `"minor"`
2683
- */
2684
- readonly leadInEnvelope?: ThreadLeadInEnvelope;
2685
- /**
2686
- * Physical circumferential lead-in length in millimetres.
2687
- * @defaultValue The profile depth.
2688
- */
2689
- readonly leadInLength?: number;
2690
- /**
2691
- * Cross-section scaling curve used by blunt ends. `cut` switches abruptly to the full profile.
2692
- * @defaultValue `"cut"`
2693
- */
2694
- readonly leadInShape?: ThreadLeadInShape;
2695
- /**
2696
- * Ridge shape at the upper working boundary. `blunt` ends at full profile height, `standard`
2697
- * clips the periodic profile at the face, and `tapered` ramps into the minor envelope.
2698
- * @defaultValue `"blunt"`
2699
- */
2700
- readonly top?: ThreadEndStyle;
2701
- }
2441
+ /**
2442
+ * Creates an immutable axis-aligned scale transform.
2443
+ *
2444
+ * Negative components are reflections. Zero components are rejected because
2445
+ * they collapse volume and cannot be inverted.
2446
+ *
2447
+ * @param factors - Finite, non-zero XYZ scale factors.
2448
+ * @returns A frozen row-major transform.
2449
+ */
2450
+ export declare function scaleTransform3(factors: Vec3): Transform3;
2451
+
2452
+ /** Returns the signed area of a non-duplicated loop; positive means CCW. */
2453
+ export declare function signedAreaLoop2(loop: Loop2): number;
2454
+
2455
+ /** A cubic corner transition with zero curvature at its straight tangent joins. */
2456
+ export declare interface SmoothEdgeTreatment {
2457
+ /** Selects continuous-curvature cubic rounding, rather than a circular radius. */
2458
+ readonly kind: "smooth";
2459
+ /** Positive tangent setbacks, equal or [first, second], in millimetres. */
2460
+ readonly distance: number | readonly [first: number, second: number];
2461
+ /** Exact cubic interval count, positive; overrides physical sampling. */
2462
+ readonly segments?: number;
2463
+ /** Physical chord/edge-length sampling; circularSegments does not describe a cubic. */
2464
+ readonly resolution?: GeometryResolution;
2465
+ /** Explicit sampling ceilings, bounded by the host policy. */
2466
+ readonly limits?: Partial<GeometrySamplingLimits>;
2467
+ }
2468
+
2469
+ /** Bounded floating-point intersection and shell-orientation validation settings. */
2470
+ export declare interface SolidMeshValidationOptions {
2471
+ /** Work ceiling for spatial comparisons and containment tests; defaults to 2,000,000 and may only lower it. */
2472
+ readonly maximumTests?: number;
2473
+ /** Distance comparison policy in millimetres; near contacts reject conservatively. */
2474
+ readonly tolerance?: GeometryToleranceOptions;
2475
+ }
2702
2476
 
2703
- /**
2704
- * Direction in which a conventional helical thread advances around +Z.
2705
- */
2706
- export declare type ThreadHandedness = "left" | "right";
2477
+ /**
2478
+ * Exactly one radius or diameter, placement, and tessellation for an origin-centered sphere.
2479
+ */
2480
+ export declare type SphereOptions = CircularPrimitiveOptions & PrimitivePlacement & ({
2481
+ /** Positive radius in millimetres; mutually exclusive with diameter. */
2482
+ readonly radius: number;
2483
+ /** Full diameter is unavailable when radius is supplied. */
2484
+ readonly diameter?: never;
2485
+ } | {
2486
+ /** Positive full diameter in millimetres; mutually exclusive with radius. */
2487
+ readonly diameter: number;
2488
+ /** Radius is unavailable when diameter is supplied. */
2489
+ readonly radius?: never;
2490
+ });
2491
+
2492
+ /** Square profile with equal crest and root widths. */
2493
+ export declare interface SquareThreadProfileSpec extends ThreadProfileBaseSpec {
2494
+ /** Selects the square profile family. */
2495
+ readonly kind: "square";
2496
+ /**
2497
+ * Radial depth in millimetres.
2498
+ * @defaultValue `pitch / 2`
2499
+ */
2500
+ readonly depth?: number;
2501
+ }
2707
2502
 
2708
- /** Conventional helix options: `pitch` is adjacent spacing and lead is `pitch * starts`. */
2709
- export declare interface ThreadHelixOptions {
2710
- /** Helix direction. Default: `right`. */
2711
- readonly handedness?: ThreadHandedness;
2712
- /** Explicit aggregate path allocation ceilings across all starts. */
2713
- readonly limits?: Partial<GeometrySamplingLimits>;
2714
- /** Total sampled axial length in millimetres. */
2715
- readonly length: number;
2716
- /** Angular offset of the first start in degrees. Default: `0`. */
2717
- readonly phaseDegrees?: number;
2718
- /** Adjacent axial thread spacing in millimetres. */
2719
- readonly pitch: number;
2720
- /** Radial distance from the +Z axis in millimetres. */
2721
- readonly radius: number;
2722
- /** Angular sampling density for each revolution. Default: `32`. */
2723
- readonly segmentsPerTurn?: number;
2724
- /** Number of evenly phased helices. Default: `1`. */
2725
- readonly starts?: number;
2726
- /** Optional numerical tolerance overrides. */
2727
- readonly tolerance?: GeometryToleranceOptions;
2728
- }
2503
+ /**
2504
+ * Creates a centered CCW alternating-radius star within the selected profile sampling ceiling.
2505
+ *
2506
+ * @example Five-point outline
2507
+ * ```ts
2508
+ * starLoop(12, 5, 6);
2509
+ * ```
2510
+ */
2511
+ export declare const starLoop: (outerRadius: number, points: number, innerRadius?: number, limits?: Partial<GeometrySamplingLimits>) => readonly Vec2[];
2729
2512
 
2730
- /** Radial envelope toward which a blunt lead-in collapses. */
2731
- export declare type ThreadLeadInEnvelope = "major" | "minor";
2513
+ /** End-cap treatment for an open stroked path. */
2514
+ export declare type StrokePathCap = "butt" | "round" | "square";
2732
2515
 
2733
- /** BOSL2-compatible cross-section scaling curve for a blunt thread lead-in. */
2734
- export declare type ThreadLeadInShape = "cut" | "linear" | "smooth" | "sqrt";
2516
+ /** Join treatment where adjacent stroked path segments meet. */
2517
+ export declare type StrokePathJoin = "bevel" | "miter" | "round";
2735
2518
 
2736
- /**
2737
- * A validated immutable periodic thread profile in `[axial, radial]` millimetres.
2738
- */
2739
- export declare interface ThreadProfile {
2740
- /** Axial width of the flat at the major envelope. */
2741
- readonly crestFlatWidth: number;
2742
- /** Radial distance from the major envelope to the root. */
2743
- readonly depth: number;
2744
- /** Profile family that produced this validated profile. */
2745
- readonly kind: ThreadProfileSpec["kind"];
2746
- /** Adjacent axial thread spacing in millimetres. */
2747
- readonly pitch: number;
2748
- /** Immutable open `[axial, radial]` path spanning one pitch. */
2749
- readonly points: readonly Vec2[];
2750
- /** Axial width of the flat at the minor envelope. */
2751
- readonly rootFlatWidth: number;
2752
- }
2519
+ /**
2520
+ * Converts a sampled millimetre path into the filled region covered by a centered stroke.
2521
+ *
2522
+ * Closed paths omit a duplicated seam point. Zero-length sampled segments are ignored, while the
2523
+ * effective path must still contain visible length. Round caps and joins use deterministic physical
2524
+ * resolution. Bevels fill the outer corner triangle; miters extend the outer edges to their
2525
+ * intersection, falling back to bevels above SVG's default miter limit of 4.
2526
+ */
2527
+ export declare function strokePathRegion(path: Path2, options: StrokePathRegionOptions): Region2;
2528
+
2529
+ /** Physical stroke and topology controls for {@link strokePathRegion}. */
2530
+ export declare interface StrokePathRegionOptions {
2531
+ /** Explicit path, circular and expanded-profile allocation ceilings. */
2532
+ readonly limits?: Partial<GeometrySamplingLimits>;
2533
+ /** Treat the path as a closed non-duplicated loop. Default: `false`. */
2534
+ readonly closed?: boolean;
2535
+ /** End-cap treatment for an open path. Ignored for closed paths. Default: `butt`. */
2536
+ readonly cap?: StrokePathCap;
2537
+ /** Corner treatment; miters exceeding SVG's default limit of 4 become bevels. Default: `miter`. */
2538
+ readonly join?: StrokePathJoin;
2539
+ /** Physical tessellation policy for round caps and joins. */
2540
+ readonly resolution?: GeometryResolution;
2541
+ /** Positive total stroke width in millimetres, centered on the sampled path. */
2542
+ readonly width: number;
2543
+ }
2753
2544
 
2754
- /** Fields shared by all thread profile specifications. */
2755
- export declare interface ThreadProfileBaseSpec {
2756
- /** Adjacent axial thread spacing in millimetres. */
2757
- readonly pitch: number;
2758
- /** Optional numerical tolerance overrides. */
2759
- readonly tolerance?: GeometryToleranceOptions;
2760
- }
2545
+ /**
2546
+ * Subtracts `b` from `a`.
2547
+ * @example
2548
+ * ```ts
2549
+ * subtract3([4, 5, 6], [1, 2, 3]); // [3, 3, 3]
2550
+ * ```
2551
+ */
2552
+ export declare const subtract3: (a: Vec3, b: Vec3) => Vec3;
2553
+
2554
+ /** Sampling controls for deterministic SVG-to-region conversion. */
2555
+ export declare interface SvgImportOptions {
2556
+ /** Explicit profile and circular allocation ceilings; bounded SVG source/work limits remain fixed. */
2557
+ readonly limits?: Partial<GeometrySamplingLimits>;
2558
+ /** Exact segments for a complete ellipse or round stroke feature. */
2559
+ readonly circularSegments?: number;
2560
+ /** Operation-level physical tessellation policy over the active model-wide policy. */
2561
+ readonly resolution?: GeometryResolution;
2562
+ /**
2563
+ * `"center"` places the viewport center at the origin. `"document"` places its converted
2564
+ * lower-left corner at the origin. Default: `"center"`.
2565
+ */
2566
+ readonly origin?: "center" | "document";
2567
+ }
2568
+
2569
+ /** Exact normalized SVG region plus bounded source, geometry, and safe-repair diagnostics. */
2570
+ export declare interface SvgRegionPreflight {
2571
+ /** Physical and final-topology measurements of `region`. */
2572
+ readonly geometry: SvgRegionPreflightGeometryMetrics;
2573
+ /** Appearance-preserving cleanup observed during parsing and normalization. */
2574
+ readonly repairs: SvgRegionPreflightRepairs;
2575
+ /** Canonical millimetre, Y-up geometry. */
2576
+ readonly region: Region2;
2577
+ /** Bounded source and flattening complexity measurements. */
2578
+ readonly source: SvgRegionPreflightSourceMetrics;
2579
+ }
2580
+
2581
+ /** Physical and final-topology facts for a normalized imported SVG region. */
2582
+ export declare interface SvgRegionPreflightGeometryMetrics {
2583
+ /** Filled area in square millimetres. */
2584
+ readonly area: number;
2585
+ /** Millimetre bounds, or `null` when no painted region remains. */
2586
+ readonly bounds: Bounds2 | null;
2587
+ /** Disconnected filled polygons in the final region. */
2588
+ readonly components: number;
2589
+ /** Exterior and hole boundary count in the final region. */
2590
+ readonly contours: number;
2591
+ /** Interior boundary count in the final region. */
2592
+ readonly holes: number;
2593
+ /** Shortest final boundary edge in millimetres, or `null` for an empty region. */
2594
+ readonly minEdgeLength: number | null;
2595
+ /** Final boundary edges shorter than the conservative 0.01 mm indicator. */
2596
+ readonly shortEdges: number;
2597
+ /** Components with less than 0.01 square millimetres of filled area. */
2598
+ readonly tinyIslands: number;
2599
+ /** Non-duplicated boundary vertices in the final normalized region. */
2600
+ readonly vertices: number;
2601
+ }
2602
+
2603
+ /** Visible, appearance-preserving cleanup counters from bounded SVG import. */
2604
+ export declare interface SvgRegionPreflightRepairs {
2605
+ /** Graphics elements with neither a visible fill nor a positive-width visible stroke. */
2606
+ readonly invisibleElements: number;
2607
+ /** Open filled subpaths closed by SVG fill semantics without closing their strokes. */
2608
+ readonly implicitFilledClosures: number;
2609
+ /** Visibly painted elements whose fill and stroke both resolved to empty geometry. */
2610
+ readonly emptyElements: number;
2611
+ /** Consecutive repeated flattened vertices discarded before topology resolution. */
2612
+ readonly removedDuplicateVertices: number;
2613
+ /** Explicit repeated seam vertices removed from otherwise closed contours. */
2614
+ readonly removedSeamVertices: number;
2615
+ }
2616
+
2617
+ /** Bounded source-complexity facts collected while parsing one SVG document. */
2618
+ export declare interface SvgRegionPreflightSourceMetrics {
2619
+ /** UTF-8 source size, capped at 256 KiB before parsing. */
2620
+ readonly bytes: number;
2621
+ /** Renderable shape elements, capped at 500; containers and metadata are excluded. */
2622
+ readonly elements: number;
2623
+ /** Flattened vertices emitted before fill, stroke, and clipping operations. */
2624
+ readonly emittedVertices: number;
2625
+ /** Path endpoints and control vertices parsed before adaptive flattening. */
2626
+ readonly parsedVertices: number;
2627
+ }
2761
2628
 
2762
- /**
2763
- * Supported built-in and caller-defined thread profiles.
2764
- */
2765
- export declare type ThreadProfileSpec = AcmeThreadProfileSpec | ButtressThreadProfileSpec | CustomThreadProfileSpec | SquareThreadProfileSpec | TrapezoidalThreadProfileSpec | TriangularThreadProfileSpec;
2629
+ /**
2630
+ * Sweeps one explicitly ordered point loop, with caps or a geometrically matching closed seam.
2631
+ *
2632
+ * @example Sweep point data along a bent path
2633
+ * ```ts
2634
+ * const profile = rectangleLoop({ size: [6, 3] });
2635
+ * sweepMesh(profile, [[0, 0, 0], [0, 0, 15], [10, 0, 25]], {
2636
+ * orientation: { kind: "transport", initialNormal: [0, 1, 0] },
2637
+ * });
2638
+ * ```
2639
+ */
2640
+ export declare function sweepMesh(profile: Loop2, path: readonly Vec3[], options?: SweepOptions): TriangleMesh;
2766
2641
 
2767
- /** Whether compensation is being applied to an external or internal thread. */
2768
- export declare type ThreadRole = "male" | "female";
2642
+ /**
2643
+ * Controls shared by pure mesh construction and filled modeling sweeps.
2644
+ */
2645
+ export declare interface SweepOptions {
2646
+ /** Join the path's last station to its first. Open paths retain watertight end caps. */
2647
+ readonly closed?: boolean;
2648
+ /** Explicit output and sampling allocation ceilings. */
2649
+ readonly limits?: Partial<ModelingLimits>;
2650
+ /** Explicit frame policy; default transport minimizes rotations, initially projecting +X then +Y then +Z. */
2651
+ readonly orientation?: SweepOrientation;
2652
+ /** Physical sampling of nonzero twist; inserted stations retain authored station controls. */
2653
+ readonly resolution?: GeometryResolution;
2654
+ /** Total additional profile rotation in degrees, with progression selected by twistBy. */
2655
+ readonly twistDegrees?: number;
2656
+ /** Twist advances by physical path length (default), or normalized authored station position, including a closed seam gap. */
2657
+ readonly twistBy?: "length" | "stations";
2658
+ /** Positive uniform/XY scale, or one XY pair per path station. Defaults to one. */
2659
+ readonly scale?: number | Vec2 | readonly Vec2[];
2660
+ /** Corresponding point-index advance at a rotationally equivalent closed seam. */
2661
+ readonly seamProfileOffset?: number;
2662
+ }
2769
2663
 
2770
- /**
2771
- * Dimensions and independent ring/profile tessellation for a torus around the Z axis.
2772
- */
2773
- export declare interface TorusOptions extends PrimitivePlacement {
2774
- /** Explicit sampling ceilings, bounded by the host policy. */
2775
- readonly limits?: Partial<GeometrySamplingLimits>;
2776
- /** Radius from the Z axis to the profile center, in millimetres; greater than `minorRadius`. */
2777
- readonly majorRadius: number;
2778
- /** Exact segment count around the Z axis; omitted uses adaptive resolution. */
2779
- readonly majorSegments?: number;
2780
- /** Radius of the swept circular profile in millimetres. */
2781
- readonly minorRadius: number;
2782
- /** Exact segment count around the swept profile; omitted uses adaptive resolution. */
2783
- readonly minorSegments?: number;
2784
- /** Operation-level physical tessellation policy over the active model-wide policy. */
2785
- readonly resolution?: GeometryResolution;
2786
- }
2664
+ /**
2665
+ * Explicit profile-X frame policy; all normals are directed, and selected singular policies reject.
2666
+ */
2667
+ export declare type SweepOrientation = {
2668
+ /** Minimizes frame rotation by parallel transport. */
2669
+ readonly kind: "transport";
2670
+ /** Initial profile +X guide, projected perpendicular to the first tangent. */
2671
+ readonly initialNormal?: Vec3;
2672
+ } | {
2673
+ /** Projects one fixed world-space normal at every path station. */
2674
+ readonly kind: "fixed-normal";
2675
+ /** Directed profile +X guide; must not be parallel to any local tangent. */
2676
+ readonly normal: Vec3;
2677
+ } | {
2678
+ /** Uses an explicitly directed normal callback at each original normalized station. */
2679
+ readonly kind: "guide";
2680
+ /** Finite profile +X guide callback, evaluated once per original path station. */
2681
+ readonly normal: PathNormalGuide;
2682
+ } | {
2683
+ /** Uses sampled curvature normals; zero-curvature stations reject. */
2684
+ readonly kind: "frenet";
2685
+ };
2686
+
2687
+ /** End bevel controls shared by threaded rods and cutters. */
2688
+ export declare interface ThreadBevelOptions {
2689
+ /** Apply a 45-degree bevel at Z=0. */
2690
+ readonly bevelBottom?: boolean;
2691
+ /**
2692
+ * Axial bevel extent in millimetres. Active blunt ends default to one sixth of the compensated
2693
+ * male minor radius or female major radius; other ends default to the profile depth.
2694
+ */
2695
+ readonly bevelSize?: number;
2696
+ /** Apply a 45-degree bevel at Z=length. */
2697
+ readonly bevelTop?: boolean;
2698
+ }
2699
+
2700
+ /** Inputs for resolving one shared circular facet count for a mating thread pair. */
2701
+ export declare interface ThreadCircularSegmentsOptions {
2702
+ /** Explicit circular allocation ceiling for the shared mating grid. */
2703
+ readonly limits?: Partial<GeometrySamplingLimits>;
2704
+ /** Printable fit whose larger compensated female envelope governs tessellation. */
2705
+ readonly fit?: PrintableThreadFit | PrintableThreadFitPolicy;
2706
+ /** Nominal major diameter before role-specific compensation. */
2707
+ readonly nominalMajorDiameter: number;
2708
+ /**
2709
+ * Maximum active female face outset beyond the compensated major envelope, in millimetres.
2710
+ * This keeps a compensated male/female pair on one role-independent grid when an internal
2711
+ * cutter has an enlarged entrance bevel. Default: `0`.
2712
+ */
2713
+ readonly maximumRadialOutset?: number;
2714
+ /** Validated mating profile whose pitch and flank capacities govern tessellation. */
2715
+ readonly profile: ThreadProfile;
2716
+ /** Physical or exact circular resolution policy. */
2717
+ readonly resolution?: GeometryResolution;
2718
+ /** Number of phased starts. Default: `1`. */
2719
+ readonly starts?: number;
2720
+ }
2721
+
2722
+ /** Options for compensating nominal male or female thread diameters. */
2723
+ export declare interface ThreadCompensationOptions {
2724
+ /** Named policy or explicit caller-calibrated allowances. */
2725
+ readonly fit?: PrintableThreadFit | PrintableThreadFitPolicy;
2726
+ /** Nominal sharp or truncated major diameter in millimetres. */
2727
+ readonly nominalMajorDiameter: number;
2728
+ /** Male or female geometry being compensated. */
2729
+ readonly role: ThreadRole;
2730
+ /** Radial depth from major to minor envelope in millimetres. */
2731
+ readonly threadDepth: number;
2732
+ /** Optional numerical tolerance overrides. */
2733
+ readonly tolerance?: GeometryToleranceOptions;
2734
+ }
2735
+
2736
+ /** Nut-edge bevel selection. */
2737
+ export declare type ThreadedNutBevel = "automatic" | "both" | "inside" | "none" | "outside";
2787
2738
 
2788
- /**
2789
- * A row-major affine 4x4 matrix applied to column vectors.
2790
- *
2791
- * Translation occupies indices 3, 7, and 11. The final row must be
2792
- * `[0, 0, 0, 1]` within the active geometry tolerance.
2793
- */
2794
- export declare type Transform3 = readonly [
2795
- m00: number,
2796
- m01: number,
2797
- m02: number,
2798
- m03: number,
2799
- m10: number,
2800
- m11: number,
2801
- m12: number,
2802
- m13: number,
2803
- m20: number,
2804
- m21: number,
2805
- m22: number,
2806
- m23: number,
2807
- m30: number,
2808
- m31: number,
2809
- m32: number,
2810
- m33: number
2811
- ];
2739
+ /**
2740
+ * Options for a compensated nut with an internal thread.
2741
+ */
2742
+ export declare interface ThreadedNutOptions extends Omit<InternalThreadCutterOptions, "bevelBottom" | "bevelSize" | "bevelTop" | "length"> {
2743
+ /** Nut body bevel selection. Default: `automatic`. */
2744
+ readonly bevel?: ThreadedNutBevel;
2745
+ /** Optional physical policy for a round body, independent of the thread's matched facet grid. */
2746
+ readonly bodyResolution?: GeometryResolution;
2747
+ /** 45-degree body chamfer extent. Default: `min(profile.depth, thickness/4)`. */
2748
+ readonly chamferSize?: number;
2749
+ /** Leave the bottom outside edge flat for build-plate adhesion. Default: `false`. */
2750
+ readonly flushBuildPlateBottom?: boolean;
2751
+ /** Nut body shape. */
2752
+ readonly shape: ThreadedNutShape;
2753
+ /** Nut thickness along +Z in millimetres. */
2754
+ readonly thickness: number;
2755
+ /** Across-flats width for hex/square or diameter for round, in millimetres. */
2756
+ readonly width: number;
2757
+ }
2758
+
2759
+ /** Allocation-free body, cutter, and end-face facts resolved for a threaded nut. */
2760
+ export declare interface ThreadedNutPreflight {
2761
+ /** Polygon segment count used by the nut body. */
2762
+ readonly bodySegments: number;
2763
+ /** Shared 45-degree chamfer size applied to the selected body and cutter edges. */
2764
+ readonly chamferSize: number;
2765
+ /** Maximum compensated cutter radius at either requested face. */
2766
+ readonly cutterFaceRadius: number;
2767
+ /** Minimum nut-body inradius across the requested top and bottom faces. */
2768
+ readonly minimumBodyFaceInradius: number;
2769
+ /** Smallest radial wall left between the body and cutter at either requested face. */
2770
+ readonly minimumFaceWall: number;
2771
+ /** Conservative allocation facts for the exact extended internal-thread cutter mesh. */
2772
+ readonly thread: HelicalThreadSolidMeshPreflight;
2773
+ /** Start-aligned circular facet count used by the compensated thread cutter. */
2774
+ readonly threadCircularSegments: number;
2775
+ }
2812
2776
 
2813
- /**
2814
- * Returns the determinant of a transform's linear 3x3 component.
2815
- *
2816
- * A negative result identifies a reflection; zero is rejected as singular.
2817
- *
2818
- * @param transform - Valid affine transform.
2819
- * @returns Signed linear determinant.
2820
- */
2821
- export declare function transformDeterminant3(transform: Transform3): number;
2777
+ /**
2778
+ * Supported printable nut body shapes.
2779
+ */
2780
+ export declare type ThreadedNutShape = "hex" | "round" | "square";
2822
2781
 
2823
- /**
2824
- * Transforms a closed loop and preserves its original winding convention.
2825
- *
2826
- * Reflections reverse the point order automatically through normalization.
2827
- */
2828
- export declare function transformLoop2(loop: Loop2, transform: Transform3, tolerance?: GeometryToleranceOptions): Loop2;
2782
+ /**
2783
+ * Options for a compensated external threaded rod along +Z.
2784
+ */
2785
+ export declare interface ThreadedRodOptions extends Omit<HelicalThreadRidgeMeshOptions, "majorDiameter">, ThreadBevelOptions {
2786
+ /** Printable fit or caller-calibrated allowances. Default: `normal`. */
2787
+ readonly fit?: PrintableThreadFit | PrintableThreadFitPolicy;
2788
+ /** Nominal major diameter before male compensation. */
2789
+ readonly nominalMajorDiameter: number;
2790
+ }
2791
+
2792
+ /** End shape of a generated helical ridge. */
2793
+ export declare type ThreadEndStyle = "blunt" | "standard" | "tapered";
2794
+
2795
+ /** Axial end controls for a generated ridge. */
2796
+ export declare interface ThreadEndTreatmentOptions {
2797
+ /**
2798
+ * Ridge shape at the lower working boundary. `blunt` ends at full profile height, `standard`
2799
+ * clips the periodic profile at the face, and `tapered` ramps out from the minor envelope.
2800
+ * @defaultValue `"blunt"`
2801
+ */
2802
+ readonly bottom?: ThreadEndStyle;
2803
+ /**
2804
+ * Non-negative unthreaded envelope length reserved at each non-standard end, in millimetres.
2805
+ * Active blunt bevels may raise this reservation to the effective bevel size.
2806
+ * @defaultValue `0`
2807
+ */
2808
+ readonly endLength?: number;
2809
+ /**
2810
+ * Radial envelope toward which a blunt lead-in collapses.
2811
+ * @defaultValue `"minor"`
2812
+ */
2813
+ readonly leadInEnvelope?: ThreadLeadInEnvelope;
2814
+ /**
2815
+ * Physical circumferential lead-in length in millimetres.
2816
+ * @defaultValue The profile depth.
2817
+ */
2818
+ readonly leadInLength?: number;
2819
+ /**
2820
+ * Cross-section scaling curve used by blunt ends. `cut` switches abruptly to the full profile.
2821
+ * @defaultValue `"cut"`
2822
+ */
2823
+ readonly leadInShape?: ThreadLeadInShape;
2824
+ /**
2825
+ * Ridge shape at the upper working boundary. `blunt` ends at full profile height, `standard`
2826
+ * clips the periodic profile at the face, and `tapered` ramps into the minor envelope.
2827
+ * @defaultValue `"blunt"`
2828
+ */
2829
+ readonly top?: ThreadEndStyle;
2830
+ }
2829
2831
 
2830
- /** Applies an XY-plane-preserving affine transform to a 2D path. */
2831
- export declare function transformPath2(path: Path2, transform: Transform3, tolerance?: GeometryToleranceOptions): Path2;
2832
+ /**
2833
+ * Direction in which a conventional helical thread advances around +Z.
2834
+ */
2835
+ export declare type ThreadHandedness = "left" | "right";
2836
+
2837
+ /** Conventional helix options: `pitch` is adjacent spacing and lead is `pitch * starts`. */
2838
+ export declare interface ThreadHelixOptions {
2839
+ /** Helix direction. Default: `right`. */
2840
+ readonly handedness?: ThreadHandedness;
2841
+ /** Explicit aggregate path allocation ceilings across all starts. */
2842
+ readonly limits?: Partial<GeometrySamplingLimits>;
2843
+ /** Total sampled axial length in millimetres. */
2844
+ readonly length: number;
2845
+ /** Angular offset of the first start in degrees. Default: `0`. */
2846
+ readonly phaseDegrees?: number;
2847
+ /** Adjacent axial thread spacing in millimetres. */
2848
+ readonly pitch: number;
2849
+ /** Radial distance from the +Z axis in millimetres. */
2850
+ readonly radius: number;
2851
+ /** Angular sampling density for each revolution. Default: `32`. */
2852
+ readonly segmentsPerTurn?: number;
2853
+ /** Number of evenly phased helices. Default: `1`. */
2854
+ readonly starts?: number;
2855
+ /** Optional numerical tolerance overrides. */
2856
+ readonly tolerance?: GeometryToleranceOptions;
2857
+ }
2858
+
2859
+ /** Radial envelope toward which a blunt lead-in collapses. */
2860
+ export declare type ThreadLeadInEnvelope = "major" | "minor";
2861
+
2862
+ /** BOSL2-compatible cross-section scaling curve for a blunt thread lead-in. */
2863
+ export declare type ThreadLeadInShape = "cut" | "linear" | "smooth" | "sqrt";
2832
2864
 
2833
- /** Applies an affine transform to a 3D path without mutating its points. */
2834
- export declare function transformPath3(path: Path3, transform: Transform3): Path3;
2865
+ /**
2866
+ * A validated immutable periodic thread profile in `[axial, radial]` millimetres.
2867
+ */
2868
+ export declare interface ThreadProfile {
2869
+ /** Axial width of the flat at the major envelope. */
2870
+ readonly crestFlatWidth: number;
2871
+ /** Radial distance from the major envelope to the root. */
2872
+ readonly depth: number;
2873
+ /** Profile family that produced this validated profile. */
2874
+ readonly kind: ThreadProfileSpec["kind"];
2875
+ /** Adjacent axial thread spacing in millimetres. */
2876
+ readonly pitch: number;
2877
+ /** Immutable open `[axial, radial]` path spanning one pitch. */
2878
+ readonly points: readonly Vec2[];
2879
+ /** Axial width of the flat at the minor envelope. */
2880
+ readonly rootFlatWidth: number;
2881
+ }
2882
+
2883
+ /** Fields shared by all thread profile specifications. */
2884
+ export declare interface ThreadProfileBaseSpec {
2885
+ /** Adjacent axial thread spacing in millimetres. */
2886
+ readonly pitch: number;
2887
+ /** Optional numerical tolerance overrides. */
2888
+ readonly tolerance?: GeometryToleranceOptions;
2889
+ }
2835
2890
 
2836
- /** Transforms an explicit outer/hole region with reflection-safe winding correction. */
2837
- export declare function transformRegion2(region: Region2, transform: Transform3, tolerance?: GeometryToleranceOptions): Region2;
2891
+ /**
2892
+ * Supported built-in and caller-defined thread profiles.
2893
+ */
2894
+ export declare type ThreadProfileSpec = AcmeThreadProfileSpec | ButtressThreadProfileSpec | CustomThreadProfileSpec | SquareThreadProfileSpec | TrapezoidalThreadProfileSpec | TriangularThreadProfileSpec;
2838
2895
 
2839
- /**
2840
- * Applies an affine transform to a mesh and preserves outward face orientation.
2841
- *
2842
- * A transform with a negative linear determinant reflects space, so this helper
2843
- * automatically reverses every triangle. Singular transforms are rejected.
2844
- *
2845
- * @param mesh - Mesh to transform without mutation.
2846
- * @param transform - Row-major affine transform.
2847
- * @returns A mesh with fresh transformed positions and copied or reversed indices.
2848
- */
2849
- export declare function transformTriangleMesh(mesh: TriangleMesh, transform: Transform3): TriangleMesh;
2896
+ /** Whether compensation is being applied to an external or internal thread. */
2897
+ export declare type ThreadRole = "male" | "female";
2850
2898
 
2851
- /**
2852
- * Creates an immutable translation transform.
2853
- *
2854
- * @param offset - Finite XYZ translation in model units.
2855
- * @returns A frozen row-major transform.
2856
- */
2857
- export declare function translationTransform3(offset: Vec3): Transform3;
2899
+ /**
2900
+ * Dimensions and independent ring/profile tessellation for a torus around the Z axis.
2901
+ */
2902
+ export declare interface TorusOptions extends PrimitivePlacement {
2903
+ /** Explicit sampling ceilings, bounded by the host policy. */
2904
+ readonly limits?: Partial<GeometrySamplingLimits>;
2905
+ /** Radius from the Z axis to the profile center, in millimetres; greater than `minorRadius`. */
2906
+ readonly majorRadius: number;
2907
+ /** Exact segment count around the Z axis; omitted uses adaptive resolution. */
2908
+ readonly majorSegments?: number;
2909
+ /** Radius of the swept circular profile in millimetres. */
2910
+ readonly minorRadius: number;
2911
+ /** Exact segment count around the swept profile; omitted uses adaptive resolution. */
2912
+ readonly minorSegments?: number;
2913
+ /** Operation-level physical tessellation policy over the active model-wide policy. */
2914
+ readonly resolution?: GeometryResolution;
2915
+ }
2858
2916
 
2859
- /** Trapezoidal thread profile with a configurable included angle. */
2860
- export declare interface TrapezoidalThreadProfileSpec extends ThreadProfileBaseSpec {
2861
- /** Selects the trapezoidal profile family. */
2862
- readonly kind: "trapezoidal";
2863
- /**
2864
- * Radial depth in millimetres.
2865
- * @defaultValue `pitch / 2`
2866
- */
2867
- readonly depth?: number;
2868
- /**
2869
- * Included flank angle in degrees. Use `90` for printable 45-degree slopes.
2870
- * @defaultValue `30`
2871
- */
2872
- readonly threadAngle?: number;
2873
- }
2917
+ /**
2918
+ * A row-major affine 4x4 matrix applied to column vectors.
2919
+ *
2920
+ * Translation occupies indices 3, 7, and 11. The final row must be
2921
+ * `[0, 0, 0, 1]` within the active geometry tolerance.
2922
+ */
2923
+ export declare type Transform3 = readonly [
2924
+ m00: number,
2925
+ m01: number,
2926
+ m02: number,
2927
+ m03: number,
2928
+ m10: number,
2929
+ m11: number,
2930
+ m12: number,
2931
+ m13: number,
2932
+ m20: number,
2933
+ m21: number,
2934
+ m22: number,
2935
+ m23: number,
2936
+ m30: number,
2937
+ m31: number,
2938
+ m32: number,
2939
+ m33: number
2940
+ ];
2874
2941
 
2875
- /**
2876
- * A topology-preserving indexed triangle mesh with XYZ vertex positions.
2877
- */
2878
- export declare interface TriangleMesh {
2879
- /** Three unsigned vertex indices per triangle. */
2880
- readonly indices: Uint32Array;
2881
- /** Flat XYZ coordinates, three finite values per vertex. */
2882
- readonly positions: Float32Array;
2883
- }
2942
+ /**
2943
+ * Returns the determinant of a transform's linear 3x3 component.
2944
+ *
2945
+ * A negative result identifies a reflection; zero is rejected as singular.
2946
+ *
2947
+ * @param transform - Valid affine transform.
2948
+ * @returns Signed linear determinant.
2949
+ */
2950
+ export declare function transformDeterminant3(transform: Transform3): number;
2884
2951
 
2885
- /**
2886
- * Measurements and optional edge-connected topology from one validated mesh traversal.
2887
- */
2888
- export declare interface TriangleMeshAnalysis extends TriangleMeshMeasurements {
2889
- /** Number of referenced edge-connected components when `includeTopology` is requested. */
2890
- readonly connectedComponentCount?: number;
2891
- /** Number of distinct indexed undirected edges when `includeTopology` is requested. */
2892
- readonly edgeCount?: number;
2893
- }
2952
+ /**
2953
+ * Transforms a closed loop and preserves its original winding convention.
2954
+ *
2955
+ * Reflections reverse the point order automatically through normalization.
2956
+ */
2957
+ export declare function transformLoop2(loop: Loop2, transform: Transform3, tolerance?: GeometryToleranceOptions): Loop2;
2894
2958
 
2895
- /**
2896
- * Validation and optional connectivity controls for a shared mesh analysis.
2897
- */
2898
- export declare interface TriangleMeshAnalysisOptions extends TriangleMeshValidationOptions {
2899
- /** Compute indexed edge/component counts and reject unreferenced vertices; defaults to false. */
2900
- readonly includeTopology?: boolean;
2901
- }
2959
+ /** Applies an XY-plane-preserving affine transform to a 2D path. */
2960
+ export declare function transformPath2(path: Path2, transform: Transform3, tolerance?: GeometryToleranceOptions): Path2;
2902
2961
 
2903
- /**
2904
- * Geometric measurements derived from a validated, non-empty triangle mesh.
2905
- */
2906
- export declare interface TriangleMeshMeasurements {
2907
- /** Axis-aligned bounds. */
2908
- readonly bounds: MeshBounds;
2909
- /** Signed enclosed volume; positive values correspond to outward winding. */
2910
- readonly signedVolume: number;
2911
- /** Sum of all triangle areas in squared model units. */
2912
- readonly surfaceArea: number;
2913
- /** Number of indexed triangles. */
2914
- readonly triangleCount: number;
2915
- /** Number of distinct entries in the position buffer. */
2916
- readonly vertexCount: number;
2917
- }
2962
+ /** Applies an affine transform to a 3D path without mutating its points. */
2963
+ export declare function transformPath3(path: Path3, transform: Transform3): Path3;
2918
2964
 
2919
- /** Options controlling bounded triangle-mesh quality analysis. */
2920
- export declare interface TriangleMeshQualityOptions {
2921
- /** Maximum number of triangles inspected. Defaults to `200000`. */
2922
- readonly maximumTriangleCount?: number;
2923
- /** Numeric comparison overrides; model coordinates are interpreted in their existing units. */
2924
- readonly tolerance?: GeometryToleranceOptions;
2925
- }
2965
+ /** Transforms an explicit outer/hole region with reflection-safe winding correction. */
2966
+ export declare function transformRegion2(region: Region2, transform: Transform3, tolerance?: GeometryToleranceOptions): Region2;
2926
2967
 
2927
- /** Structural, topological, and planar-patch measurements for one indexed triangle mesh. */
2928
- export declare interface TriangleMeshQualityReport {
2929
- /** Number of duplicate triangles beyond their first unordered occurrence. */
2930
- readonly duplicateTriangleCount: number;
2931
- /** Number of two-face edges whose incident triangles use the same direction. */
2932
- readonly inconsistentWindingEdgeCount: number;
2933
- /** Whether the mesh has valid faces and exactly two oppositely wound faces at every edge. */
2934
- readonly isClosedOrientedManifold: boolean;
2935
- /** Largest normalized triangle aspect ratio; an equilateral triangle has ratio `1`. */
2936
- readonly maximumTriangleAspectRatio: number;
2937
- /** Largest number of triangles incident to one indexed vertex. */
2938
- readonly maximumVertexTriangleIncidence: number;
2939
- /** Largest number of distinct neighbours connected to one indexed vertex. */
2940
- readonly maximumVertexValence: number;
2941
- /** Smallest interior triangle angle in degrees. */
2942
- readonly minimumTriangleAngleDegrees: number;
2943
- /** Number of triangles at or below the scale-aware zero-area threshold. */
2944
- readonly nearZeroAreaTriangleCount: number;
2945
- /** Number of edges with more than two incident triangles. */
2946
- readonly nonManifoldEdgeCount: number;
2947
- /** Number of edges with exactly one incident triangle. */
2948
- readonly openEdgeCount: number;
2949
- /** Edge-connected coplanar patches in deterministic first-triangle order. */
2950
- readonly planarPatches: readonly PlanarPatchQuality[];
2951
- /** Signed enclosed volume in cubic model units; positive values indicate outward winding. */
2952
- readonly signedVolume: number;
2953
- /** Total triangle area in squared model units. */
2954
- readonly surfaceArea: number;
2955
- /** Number of indexed triangles. */
2956
- readonly triangleCount: number;
2957
- /** Number of entries in the position buffer. */
2958
- readonly vertexCount: number;
2959
- }
2968
+ /**
2969
+ * Applies an affine transform to a mesh and preserves outward face orientation.
2970
+ *
2971
+ * A transform with a negative linear determinant reflects space, so this helper
2972
+ * automatically reverses every triangle. Singular transforms are rejected.
2973
+ *
2974
+ * @param mesh - Mesh to transform without mutation.
2975
+ * @param transform - Row-major affine transform.
2976
+ * @returns A mesh with fresh transformed positions and copied or reversed indices.
2977
+ */
2978
+ export declare function transformTriangleMesh(mesh: TriangleMesh, transform: Transform3): TriangleMesh;
2960
2979
 
2961
- /** Immutable deterministic measurements for a closed, oriented triangle mesh. */
2962
- export declare interface TriangleMeshSignature {
2963
- /** Axis-aligned bounds quantized by `tolerances.position`. */
2964
- readonly bounds: MeshBounds;
2965
- /** Number of edge-connected closed components. */
2966
- readonly connectedComponentCount: number;
2967
- /** Total orientable genus across all connected components. */
2968
- readonly genus: number;
2969
- /** Order-independent hash of quantized vertices and oriented triangles. */
2970
- readonly fingerprint: string;
2971
- /** Signed enclosed volume quantized by `tolerances.signedVolume`. */
2972
- readonly signedVolume: number;
2973
- /** Quantization used to make the signature stable across insignificant numeric drift. */
2974
- readonly tolerances: TriangleMeshSignatureTolerances;
2975
- /** Number of indexed triangles. */
2976
- readonly triangleCount: number;
2977
- /** Number of referenced position-buffer vertices. */
2978
- readonly vertexCount: number;
2979
- }
2980
+ /**
2981
+ * Creates an immutable translation transform.
2982
+ *
2983
+ * @param offset - Finite XYZ translation in model units.
2984
+ * @returns A frozen row-major transform.
2985
+ */
2986
+ export declare function translationTransform3(offset: Vec3): Transform3;
2987
+
2988
+ /** Trapezoidal thread profile with a configurable included angle. */
2989
+ export declare interface TrapezoidalThreadProfileSpec extends ThreadProfileBaseSpec {
2990
+ /** Selects the trapezoidal profile family. */
2991
+ readonly kind: "trapezoidal";
2992
+ /**
2993
+ * Radial depth in millimetres.
2994
+ * @defaultValue `pitch / 2`
2995
+ */
2996
+ readonly depth?: number;
2997
+ /**
2998
+ * Included flank angle in degrees. Use `90` for printable 45-degree slopes.
2999
+ * @defaultValue `30`
3000
+ */
3001
+ readonly threadAngle?: number;
3002
+ }
2980
3003
 
2981
- /** Options controlling deterministic triangle-mesh regression signatures. */
2982
- export declare interface TriangleMeshSignatureOptions {
2983
- /** Maximum accepted triangle count. Defaults to 200,000. */
2984
- readonly maximumTriangleCount?: number;
2985
- /** Position and bounds quantization in model units. Defaults to `1e-5`. */
2986
- readonly positionTolerance?: number;
2987
- /** Signed-volume quantization in cubic model units. Defaults to `1e-4`. */
2988
- readonly volumeTolerance?: number;
2989
- }
3004
+ /**
3005
+ * A topology-preserving indexed triangle mesh with XYZ vertex positions.
3006
+ */
3007
+ export declare interface TriangleMesh {
3008
+ /** Three unsigned vertex indices per triangle. */
3009
+ readonly indices: Uint32Array;
3010
+ /** Flat XYZ coordinates, three finite values per vertex. */
3011
+ readonly positions: Float32Array;
3012
+ }
2990
3013
 
2991
- /** Absolute tolerances recorded in a triangle-mesh regression signature. */
2992
- export declare interface TriangleMeshSignatureTolerances {
2993
- /** Position and bounds quantization in model units. */
2994
- readonly position: number;
2995
- /** Signed-volume quantization in cubic model units. */
2996
- readonly signedVolume: number;
2997
- }
3014
+ /**
3015
+ * Measurements and optional edge-connected topology from one validated mesh traversal.
3016
+ */
3017
+ export declare interface TriangleMeshAnalysis extends TriangleMeshMeasurements {
3018
+ /** Number of referenced edge-connected components when `includeTopology` is requested. */
3019
+ readonly connectedComponentCount?: number;
3020
+ /** Number of distinct indexed undirected edges when `includeTopology` is requested. */
3021
+ readonly edgeCount?: number;
3022
+ }
2998
3023
 
2999
- /** Options controlling structural and manufacturing validation of a mesh. */
3000
- export declare interface TriangleMeshValidationOptions {
3001
- /** Permit an empty position and index buffer. Defaults to `false`. */
3002
- readonly allowEmpty?: boolean;
3003
- /** Require two oppositely wound faces per edge; geometric self-intersections are not detected. */
3004
- readonly requireClosed?: boolean;
3005
- /** Numeric comparison overrides used for zero-area triangle detection. */
3006
- readonly tolerance?: GeometryToleranceOptions;
3007
- }
3024
+ /**
3025
+ * Validation and optional connectivity controls for a shared mesh analysis.
3026
+ */
3027
+ export declare interface TriangleMeshAnalysisOptions extends TriangleMeshValidationOptions {
3028
+ /** Compute indexed edge/component counts and reject unreferenced vertices; defaults to false. */
3029
+ readonly includeTopology?: boolean;
3030
+ }
3008
3031
 
3009
- /**
3010
- * ISO/UTS-like 60-degree truncated triangular profile.
3011
- */
3012
- export declare interface TriangularThreadProfileSpec extends ThreadProfileBaseSpec {
3013
- /** Selects the 60-degree triangular profile family. */
3014
- readonly kind: "triangular";
3015
- /**
3016
- * Crest width divided by pitch.
3017
- * @defaultValue `1 / 8`
3018
- */
3019
- readonly crestFlatRatio?: number;
3020
- /**
3021
- * Root width divided by pitch.
3022
- * @defaultValue `1 / 4`
3023
- */
3024
- readonly rootFlatRatio?: number;
3025
- }
3032
+ /**
3033
+ * Geometric measurements derived from a validated, non-empty triangle mesh.
3034
+ */
3035
+ export declare interface TriangleMeshMeasurements {
3036
+ /** Axis-aligned bounds. */
3037
+ readonly bounds: MeshBounds;
3038
+ /** Signed enclosed volume; positive values correspond to outward winding. */
3039
+ readonly signedVolume: number;
3040
+ /** Sum of all triangle areas in squared model units. */
3041
+ readonly surfaceArea: number;
3042
+ /** Number of indexed triangles. */
3043
+ readonly triangleCount: number;
3044
+ /** Number of distinct entries in the position buffer. */
3045
+ readonly vertexCount: number;
3046
+ }
3047
+
3048
+ /** Options controlling bounded triangle-mesh quality analysis. */
3049
+ export declare interface TriangleMeshQualityOptions {
3050
+ /** Maximum number of triangles inspected. Defaults to `200000`. */
3051
+ readonly maximumTriangleCount?: number;
3052
+ /** Numeric comparison overrides; model coordinates are interpreted in their existing units. */
3053
+ readonly tolerance?: GeometryToleranceOptions;
3054
+ }
3055
+
3056
+ /** Structural, topological, and planar-patch measurements for one indexed triangle mesh. */
3057
+ export declare interface TriangleMeshQualityReport {
3058
+ /** Number of duplicate triangles beyond their first unordered occurrence. */
3059
+ readonly duplicateTriangleCount: number;
3060
+ /** Number of two-face edges whose incident triangles use the same direction. */
3061
+ readonly inconsistentWindingEdgeCount: number;
3062
+ /** Whether the mesh has valid faces and exactly two oppositely wound faces at every edge. */
3063
+ readonly isClosedOrientedManifold: boolean;
3064
+ /** Largest normalized triangle aspect ratio; an equilateral triangle has ratio `1`. */
3065
+ readonly maximumTriangleAspectRatio: number;
3066
+ /** Largest number of triangles incident to one indexed vertex. */
3067
+ readonly maximumVertexTriangleIncidence: number;
3068
+ /** Largest number of distinct neighbours connected to one indexed vertex. */
3069
+ readonly maximumVertexValence: number;
3070
+ /** Smallest interior triangle angle in degrees. */
3071
+ readonly minimumTriangleAngleDegrees: number;
3072
+ /** Number of triangles at or below the scale-aware zero-area threshold. */
3073
+ readonly nearZeroAreaTriangleCount: number;
3074
+ /** Number of edges with more than two incident triangles. */
3075
+ readonly nonManifoldEdgeCount: number;
3076
+ /** Number of edges with exactly one incident triangle. */
3077
+ readonly openEdgeCount: number;
3078
+ /** Edge-connected coplanar patches in deterministic first-triangle order. */
3079
+ readonly planarPatches: readonly PlanarPatchQuality[];
3080
+ /** Signed enclosed volume in cubic model units; positive values indicate outward winding. */
3081
+ readonly signedVolume: number;
3082
+ /** Total triangle area in squared model units. */
3083
+ readonly surfaceArea: number;
3084
+ /** Number of indexed triangles. */
3085
+ readonly triangleCount: number;
3086
+ /** Number of entries in the position buffer. */
3087
+ readonly vertexCount: number;
3088
+ }
3089
+
3090
+ /** Immutable deterministic measurements for a closed, oriented triangle mesh. */
3091
+ export declare interface TriangleMeshSignature {
3092
+ /** Axis-aligned bounds quantized by `tolerances.position`. */
3093
+ readonly bounds: MeshBounds;
3094
+ /** Number of edge-connected closed components. */
3095
+ readonly connectedComponentCount: number;
3096
+ /** Total orientable genus across all connected components. */
3097
+ readonly genus: number;
3098
+ /** Order-independent hash of quantized vertices and oriented triangles. */
3099
+ readonly fingerprint: string;
3100
+ /** Signed enclosed volume quantized by `tolerances.signedVolume`. */
3101
+ readonly signedVolume: number;
3102
+ /** Quantization used to make the signature stable across insignificant numeric drift. */
3103
+ readonly tolerances: TriangleMeshSignatureTolerances;
3104
+ /** Number of indexed triangles. */
3105
+ readonly triangleCount: number;
3106
+ /** Number of referenced position-buffer vertices. */
3107
+ readonly vertexCount: number;
3108
+ }
3109
+
3110
+ /** Options controlling deterministic triangle-mesh regression signatures. */
3111
+ export declare interface TriangleMeshSignatureOptions {
3112
+ /** Maximum accepted triangle count. Defaults to 200,000. */
3113
+ readonly maximumTriangleCount?: number;
3114
+ /** Position and bounds quantization in model units. Defaults to `1e-5`. */
3115
+ readonly positionTolerance?: number;
3116
+ /** Signed-volume quantization in cubic model units. Defaults to `1e-4`. */
3117
+ readonly volumeTolerance?: number;
3118
+ }
3119
+
3120
+ /** Absolute tolerances recorded in a triangle-mesh regression signature. */
3121
+ export declare interface TriangleMeshSignatureTolerances {
3122
+ /** Position and bounds quantization in model units. */
3123
+ readonly position: number;
3124
+ /** Signed-volume quantization in cubic model units. */
3125
+ readonly signedVolume: number;
3126
+ }
3127
+
3128
+ /** Options controlling structural and manufacturing validation of a mesh. */
3129
+ export declare interface TriangleMeshValidationOptions {
3130
+ /** Permit an empty position and index buffer. Defaults to `false`. */
3131
+ readonly allowEmpty?: boolean;
3132
+ /** Require two oppositely wound faces per edge; geometric self-intersections are not detected. */
3133
+ readonly requireClosed?: boolean;
3134
+ /** Numeric comparison overrides used for zero-area triangle detection. */
3135
+ readonly tolerance?: GeometryToleranceOptions;
3136
+ }
3026
3137
 
3027
- /** Ear-clips one normalized simple CCW loop into stable local vertex indices. */
3028
- export declare function triangulateLoop2(loop: Loop2): Uint32Array;
3138
+ /**
3139
+ * ISO/UTS-like 60-degree truncated triangular profile.
3140
+ */
3141
+ export declare interface TriangularThreadProfileSpec extends ThreadProfileBaseSpec {
3142
+ /** Selects the 60-degree triangular profile family. */
3143
+ readonly kind: "triangular";
3144
+ /**
3145
+ * Crest width divided by pitch.
3146
+ * @defaultValue `1 / 8`
3147
+ */
3148
+ readonly crestFlatRatio?: number;
3149
+ /**
3150
+ * Root width divided by pitch.
3151
+ * @defaultValue `1 / 4`
3152
+ */
3153
+ readonly rootFlatRatio?: number;
3154
+ }
3029
3155
 
3030
- /**
3031
- * Dimensions, placement, and tessellation for a hollow Z-axis tube.
3032
- */
3033
- export declare interface TubeOptions extends CircularPrimitiveOptions, PrimitivePlacement {
3034
- /**
3035
- * Centers the tube on the Z origin when `true`; otherwise its bottom is at `Z = 0`.
3036
- * @defaultValue `true`
3037
- */
3038
- readonly center?: boolean;
3039
- /** Total height along Z in millimetres. */
3040
- readonly height: number;
3041
- /** Positive inner radius in millimetres. */
3042
- readonly innerRadius: number;
3043
- /** Outer radius in millimetres; greater than {@link TubeOptions.innerRadius}. */
3044
- readonly outerRadius: number;
3045
- }
3156
+ /** Ear-clips one normalized simple CCW loop into stable local vertex indices. */
3157
+ export declare function triangulateLoop2(loop: Loop2): Uint32Array;
3046
3158
 
3047
- /**
3048
- * Validates that a transform is finite, affine, and non-singular.
3049
- *
3050
- * @param transform - Row-major matrix to validate.
3051
- * @param tolerance - Optional comparison overrides.
3052
- * @returns The original transform after successful validation.
3053
- * @throws {@link GeometryError} For non-finite, non-affine, or singular matrices.
3054
- */
3055
- export declare function validateTransform3(transform: Transform3, tolerance?: GeometryToleranceOptions): Transform3;
3159
+ /**
3160
+ * Dimensions, placement, and tessellation for a hollow Z-axis tube.
3161
+ */
3162
+ export declare interface TubeOptions extends CircularPrimitiveOptions, PrimitivePlacement {
3163
+ /**
3164
+ * Centers the tube on the Z origin when `true`; otherwise its bottom is at `Z = 0`.
3165
+ * @defaultValue `true`
3166
+ */
3167
+ readonly center?: boolean;
3168
+ /** Total height along Z in millimetres. */
3169
+ readonly height: number;
3170
+ /** Positive inner radius in millimetres. */
3171
+ readonly innerRadius: number;
3172
+ /** Outer radius in millimetres; greater than {@link TubeOptions.innerRadius}. */
3173
+ readonly outerRadius: number;
3174
+ }
3056
3175
 
3057
3176
  /**
3058
- * Validates mesh buffers, indices, triangle area, and optionally closed topology.
3177
+ * Checks closed indexed topology, triangle intersections, and alternating nested shell orientation.
3178
+ * Outward exterior shells and inward cavity shells are accepted. Separate shells must not touch,
3179
+ * intersect, or overlap as material. Indexed neighbours may share their own vertex or edge.
3059
3180
  *
3060
- * Closed validation requires each edge to occur exactly twice with opposite
3061
- * directions, rejecting boundary and non-manifold edges. Validation does not
3062
- * mutate or copy the mesh. This establishes edge connectivity, not the absence
3063
- * of geometric self-intersections between faces.
3181
+ * Uses bounded floating-point tests, not exact predicates or repair. Contacts within the selected
3182
+ * tolerance reject conservatively. At most 200,000 triangles and 2,000,000 spatial/containment tests
3183
+ * are supported; exhausting a ceiling throws COMPLEXITY_LIMIT rather than claiming validity.
3184
+ * Input buffers are freshly inspected and never modified; units are millimetres.
3064
3185
  *
3065
- * @param mesh - Mesh to inspect.
3066
- * @param options - Empty-mesh, topology, and tolerance policy.
3067
- * @returns The original mesh after successful validation.
3068
- * @throws {@link GeometryError} When any requested invariant fails.
3069
- */
3070
- export declare function validateTriangleMesh(mesh: TriangleMesh, options?: TriangleMeshValidationOptions): TriangleMesh;
3071
-
3072
- /** A two-dimensional Cartesian vector or point. */
3073
- export declare type Vec2 = readonly [x: number, y: number];
3074
-
3075
- /** A three-dimensional Cartesian vector or point. */
3076
- export declare type Vec3 = readonly [x: number, y: number, z: number];
3186
+ * @param mesh - Closed triangle mesh to inspect.
3187
+ * @param options - Optional lower work ceiling and numeric comparison policy.
3188
+ * @returns The original mesh after every requested check succeeds.
3189
+ */
3190
+ export declare function validateSolidMesh(mesh: TriangleMesh, options?: SolidMeshValidationOptions): TriangleMesh;
3077
3191
 
3078
- /** Exact curve bounds in millimetres; positive Y points upward. */
3079
- export declare interface VectorTextBounds {
3080
- /** Minimum X and Y of visible outlines, including accents, descenders, and overhangs. */
3081
- readonly min: readonly [number, number];
3082
- /** Maximum X and Y of visible outlines. */
3083
- readonly max: readonly [number, number];
3084
- }
3192
+ /**
3193
+ * Validates that a transform is finite, affine, and non-singular.
3194
+ *
3195
+ * @param transform - Row-major matrix to validate.
3196
+ * @param tolerance - Optional comparison overrides.
3197
+ * @returns The original transform after successful validation.
3198
+ * @throws {@link GeometryError} For non-finite, non-affine, or singular matrices.
3199
+ */
3200
+ export declare function validateTransform3(transform: Transform3, tolerance?: GeometryToleranceOptions): Transform3;
3085
3201
 
3086
3202
  /**
3087
- * Immutable vector layout with no browser, font parser, or kernel ownership.
3088
- */
3089
- export declare interface VectorTextLayout {
3090
- /** Nonzero-filled path data in millimetres, positive Y upward; empty for text with no ink. */
3091
- readonly paths: readonly string[];
3092
- /** Exact measurements of these paths and their logical text layout. */
3093
- readonly metrics: VectorTextMetrics;
3094
- }
3203
+ * Validates mesh buffers, indices, triangle area, and optionally closed topology.
3204
+ *
3205
+ * Closed validation requires each edge to occur exactly twice with opposite
3206
+ * directions, rejecting boundary and non-manifold edges. Validation does not
3207
+ * mutate or copy the mesh. This establishes edge connectivity, not the absence
3208
+ * of geometric self-intersections between faces.
3209
+ *
3210
+ * @param mesh - Mesh to inspect.
3211
+ * @param options - Empty-mesh, topology, and tolerance policy.
3212
+ * @returns The original mesh after successful validation.
3213
+ * @throws {@link GeometryError} When any requested invariant fails.
3214
+ */
3215
+ export declare function validateTriangleMesh(mesh: TriangleMesh, options?: TriangleMeshValidationOptions): TriangleMesh;
3216
+
3217
+ /** A two-dimensional Cartesian vector or point. */
3218
+ export declare type Vec2 = readonly [x: number, y: number];
3219
+
3220
+ /** A three-dimensional Cartesian vector or point. */
3221
+ export declare type Vec3 = readonly [x: number, y: number, z: number];
3222
+
3223
+ /** A circular baseline centered at the XY origin, with rigid shaped glyph groups. */
3224
+ export declare interface VectorTextArcBaseline {
3225
+ /** Selects a circular baseline; glyph outlines rotate without bending or stretching. */
3226
+ readonly kind: "arc";
3227
+ /** Baseline radius in millimetres, greater than zero and at most 10000. */
3228
+ readonly radius: number;
3229
+ /** Alignment datum in degrees counterclockwise from +X; defaults to 90. */
3230
+ readonly centerAngleDegrees?: number;
3231
+ /** Reading direction around the circle; defaults to clockwise. */
3232
+ readonly direction?: "clockwise" | "counterclockwise";
3233
+ }
3234
+
3235
+ /** Exact curve bounds in millimetres; positive Y points upward. */
3236
+ export declare interface VectorTextBounds {
3237
+ /** Minimum X and Y of visible outlines, including accents, descenders, and overhangs. */
3238
+ readonly min: readonly [number, number];
3239
+ /** Maximum X and Y of visible outlines. */
3240
+ readonly max: readonly [number, number];
3241
+ }
3095
3242
 
3096
- /**
3097
- * Horizontal multiline text, bounded to 512 UTF-16 units and 16 lines without wrapping.
3098
- */
3099
- export declare interface VectorTextLayoutOptions extends VectorTextOptions {
3100
- /** Place each line's advance at the origin; defaults to left. Ink overhang is preserved. */
3101
- readonly align?: "left" | "center" | "right";
3102
- /** Baseline spacing in ems, 0.5–5; omitted uses the selected face's natural vertical metrics. */
3103
- readonly lineHeight?: number;
3104
- /** Place the first baseline or the complete ink bounds at Y=0; defaults to baseline. */
3105
- readonly verticalAlign?: "baseline" | "top" | "center" | "bottom";
3106
- }
3107
-
3108
- /** Text measurements from the same immutable layout that supplies geometry and SVG outlines. */
3109
- export declare interface VectorTextMetrics {
3110
- /** Visible curve bounds after alignment, or null when the text has no ink. */
3111
- readonly bounds: VectorTextBounds | null;
3112
- /** Unaligned pen displacement: final line advance and negative baseline displacement, in mm. */
3113
- readonly advance: readonly [number, number];
3114
- /** Maximum line advance in millimetres, including spaces; distinct from visible ink width. */
3115
- readonly logicalWidth: number;
3116
- /** Selected font's ascender distance above a baseline in millimetres, independent of the text. */
3117
- readonly ascent: number;
3118
- /** Selected font's descender distance below a baseline in millimetres, a non-negative value. */
3119
- readonly descent: number;
3120
- /** Actual distance between baselines in millimetres. */
3121
- readonly lineHeight: number;
3122
- /** Number of lines, including empty and trailing lines; empty text occupies one line. */
3123
- readonly lineCount: number;
3124
- }
3125
-
3126
- /** Shaping controls for a prepared exact font face; all lengths are in millimetres. */
3127
- export declare interface VectorTextOptions {
3128
- /** Em size in millimetres, greater than zero and at most 10000; not the visible glyph height. */
3129
- readonly fontSize: number;
3130
- /** Actual static or variable weight, 1–1000; defaults to the prepared face's static weight. */
3131
- readonly fontWeight?: number;
3132
- /** Tracking between glyph clusters in millimetres, -100–100; defaults to zero. */
3133
- readonly letterSpacing?: number;
3134
- }
3135
-
3136
- export { }
3243
+ /**
3244
+ * Immutable vector layout with no browser, font parser, or kernel ownership.
3245
+ */
3246
+ export declare interface VectorTextLayout {
3247
+ /** Nonzero-filled path data in millimetres, positive Y upward; empty for text with no ink. */
3248
+ readonly paths: readonly string[];
3249
+ /** Exact measurements of these paths and their logical text layout. */
3250
+ readonly metrics: VectorTextMetrics;
3251
+ }
3252
+
3253
+ /**
3254
+ * Text bounded to 512 UTF-16 units: horizontal lines or one circular line without wrapping.
3255
+ */
3256
+ export declare interface VectorTextLayoutOptions extends VectorTextOptions {
3257
+ /** Place the advance's start, midpoint or end at the datum; defaults to center on arcs, otherwise left. */
3258
+ readonly align?: "left" | "center" | "right";
3259
+ /** Omitted uses horizontal lines. Arcs require one line and baseline vertical alignment. */
3260
+ readonly baseline?: VectorTextArcBaseline;
3261
+ /** Baseline spacing in ems, 0.5–5; omitted uses the selected face's natural vertical metrics. */
3262
+ readonly lineHeight?: number;
3263
+ /** Place the first baseline or complete ink bounds at Y=0; arcs only accept baseline. */
3264
+ readonly verticalAlign?: "baseline" | "top" | "center" | "bottom";
3265
+ }
3266
+
3267
+ /** Text measurements from the same immutable layout that supplies geometry and SVG outlines. */
3268
+ export declare interface VectorTextMetrics {
3269
+ /** Visible curve bounds after alignment, or null when the text has no ink. */
3270
+ readonly bounds: VectorTextBounds | null;
3271
+ /** Unaligned logical advance and negative baseline displacement in mm; arcs retain [arc length, 0]. */
3272
+ readonly advance: readonly [number, number];
3273
+ /** Maximum logical line advance in millimetres, including spaces; arc length on circular baselines. */
3274
+ readonly logicalWidth: number;
3275
+ /** Selected font's ascender distance above a baseline in millimetres, independent of the text. */
3276
+ readonly ascent: number;
3277
+ /** Selected font's descender distance below a baseline in millimetres, a non-negative value. */
3278
+ readonly descent: number;
3279
+ /** Actual distance between baselines in millimetres. */
3280
+ readonly lineHeight: number;
3281
+ /** Number of lines, including empty and trailing lines; empty text occupies one line. */
3282
+ readonly lineCount: number;
3283
+ }
3284
+
3285
+ /** Shaping controls for a prepared exact font face; all lengths are in millimetres. */
3286
+ export declare interface VectorTextOptions {
3287
+ /** Em size in millimetres, greater than zero and at most 10000; not the visible glyph height. */
3288
+ readonly fontSize: number;
3289
+ /** Actual static or variable weight, 1–1000; defaults to the prepared face's static weight. */
3290
+ readonly fontWeight?: number;
3291
+ /** Tracking between glyph clusters in millimetres, -100–100; defaults to zero. */
3292
+ readonly letterSpacing?: number;
3293
+ }
3294
+
3295
+ export { }