okgeometry-api 0.4.4 → 0.4.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/Mesh.d.ts CHANGED
@@ -3,6 +3,10 @@ import { Vec3 } from "./Vec3.js";
3
3
  import { Plane } from "./Plane.js";
4
4
  import { Polyline } from "./Polyline.js";
5
5
  import type { SweepableCurve, RotationAxis } from "./types.js";
6
+ import { MeshBooleanExecutionError } from "./mesh-boolean.protocol.js";
7
+ import type { MeshBooleanAsyncOptions, MeshBooleanOptions } from "./mesh-boolean.protocol.js";
8
+ export { MeshBooleanExecutionError };
9
+ export type { MeshBooleanAsyncOptions, MeshBooleanLimits, MeshBooleanOptions, MeshBooleanErrorCode, MeshBooleanErrorPayload, MeshBooleanProgressEvent, } from "./mesh-boolean.protocol.js";
6
10
  export interface PlanarRectangle {
7
11
  corners: [Point, Point, Point, Point];
8
12
  width: number;
@@ -12,6 +16,14 @@ export interface PlanarCircle {
12
16
  points: Point[];
13
17
  radius: number;
14
18
  }
19
+ export interface PlanarArc {
20
+ points: Point[];
21
+ center: Point;
22
+ radius: number;
23
+ startAngle: number;
24
+ endAngle: number;
25
+ sweepAngle: number;
26
+ }
15
27
  /**
16
28
  * Buffer-backed triangle mesh with GPU-ready accessors.
17
29
  * All geometry lives in a Float64Array from WASM.
@@ -21,12 +33,28 @@ export interface PlanarCircle {
21
33
  export declare class Mesh {
22
34
  private _buffer;
23
35
  private _vertexCount;
36
+ private static readonly DEFAULT_BOOLEAN_LIMITS;
24
37
  private _positionBuffer;
25
38
  private _indexBuffer;
26
39
  private _vertices;
27
40
  private _faces;
28
41
  private _edgeVertexPairs;
29
42
  private constructor();
43
+ /**
44
+ * Configure default size for the shared boolean worker pool.
45
+ */
46
+ static configureBooleanWorkerPool(options: {
47
+ size: number;
48
+ }): void;
49
+ /**
50
+ * Dispose all shared boolean worker pools.
51
+ */
52
+ static disposeBooleanWorkerPools(): void;
53
+ private static resolveBooleanLimits;
54
+ private static computeRawBounds;
55
+ private static boundsOverlap;
56
+ private static cloneMesh;
57
+ private static emptyMesh;
30
58
  /**
31
59
  * Float32 xyz positions for Three.js BufferGeometry.
32
60
  * Lazy-computed and cached.
@@ -70,6 +98,22 @@ export declare class Mesh {
70
98
  * Radius is measured in the plane orthogonal to `normal`.
71
99
  */
72
100
  static buildPlanarCircle(center: Point, radiusPoint: Point, normal: Vec3, segments?: number): PlanarCircle;
101
+ /**
102
+ * Build a planar arc from center, start, and end points.
103
+ * Uses the shortest signed sweep between start and end around `normal`.
104
+ */
105
+ static buildPlanarArcCenterStartEnd(center: Point, startPoint: Point, endPoint: Point, normal: Vec3, segments?: number): PlanarArc;
106
+ /**
107
+ * Build a planar arc from start/end points and a radius control point.
108
+ * Radius is measured from start point to radiusPoint in the active plane.
109
+ * The best of 4 candidates (2 centers x minor/major sweeps) is selected by
110
+ * midpoint proximity to radiusPoint.
111
+ */
112
+ static buildPlanarArcStartEndRadius(startPoint: Point, endPoint: Point, radiusPoint: Point, normal: Vec3, segments?: number): PlanarArc | null;
113
+ private static resolveArcBasis;
114
+ private static angleOnBasis;
115
+ private static normalizeSignedAngle;
116
+ private static projectPointToPlane;
73
117
  /**
74
118
  * Create a planar patch mesh from boundary points using CDT (Constrained Delaunay Triangulation).
75
119
  * Correctly handles both convex and concave polygons.
@@ -229,24 +273,43 @@ export declare class Mesh {
229
273
  * @returns New scaled mesh
230
274
  */
231
275
  scaleXYZ(sx: number, sy: number, sz: number): Mesh;
276
+ private runBoolean;
232
277
  /**
233
278
  * Compute boolean union with another mesh.
234
279
  * @param other - Mesh to union with
280
+ * @param options - Optional safety overrides
235
281
  * @returns New mesh containing volume of both inputs
236
282
  */
237
- union(other: Mesh): Mesh;
283
+ union(other: Mesh, options?: MeshBooleanOptions): Mesh;
238
284
  /**
239
285
  * Compute boolean subtraction with another mesh.
240
286
  * @param other - Mesh to subtract
287
+ * @param options - Optional safety overrides
241
288
  * @returns New mesh with other's volume removed from this
242
289
  */
243
- subtract(other: Mesh): Mesh;
290
+ subtract(other: Mesh, options?: MeshBooleanOptions): Mesh;
244
291
  /**
245
292
  * Compute boolean intersection with another mesh.
246
293
  * @param other - Mesh to intersect with
294
+ * @param options - Optional safety overrides
247
295
  * @returns New mesh containing only the overlapping volume
248
296
  */
249
- intersect(other: Mesh): Mesh;
297
+ intersect(other: Mesh, options?: MeshBooleanOptions): Mesh;
298
+ /**
299
+ * Compute boolean union in a dedicated Web Worker (non-blocking).
300
+ * Defaults to allowUnsafe=true so high-poly jobs can run off the UI thread.
301
+ */
302
+ unionAsync(other: Mesh, options?: MeshBooleanAsyncOptions): Promise<Mesh>;
303
+ /**
304
+ * Compute boolean subtraction in a dedicated Web Worker (non-blocking).
305
+ * Defaults to allowUnsafe=true so high-poly jobs can run off the UI thread.
306
+ */
307
+ subtractAsync(other: Mesh, options?: MeshBooleanAsyncOptions): Promise<Mesh>;
308
+ /**
309
+ * Compute boolean intersection in a dedicated Web Worker (non-blocking).
310
+ * Defaults to allowUnsafe=true so high-poly jobs can run off the UI thread.
311
+ */
312
+ intersectAsync(other: Mesh, options?: MeshBooleanAsyncOptions): Promise<Mesh>;
250
313
  /**
251
314
  * Compute intersection curves with a plane.
252
315
  * @param plane - Cutting plane
@@ -1 +1 @@
1
- {"version":3,"file":"Mesh.d.ts","sourceRoot":"","sources":["../src/Mesh.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Mesh.d.ts","sourceRoot":"","sources":["../src/Mesh.ts"],"names":[],"mappings":"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"}
package/dist/Mesh.js CHANGED
@@ -9,7 +9,10 @@ import { Polygon } from "./Polygon.js";
9
9
  import { NurbsCurve } from "./NurbsCurve.js";
10
10
  import { PolyCurve } from "./PolyCurve.js";
11
11
  import { pointsToCoords, parsePolylineBuffer as parsePolylineBuf } from "./BufferCodec.js";
12
+ import { configureDefaultMeshBooleanWorkerPool, disposeMeshBooleanWorkerPools, runMeshBooleanInWorkerPool, } from "./mesh-boolean.pool.js";
13
+ import { MeshBooleanExecutionError } from "./mesh-boolean.protocol.js";
12
14
  import * as wasm from "../wasm/okgeometrycore_bg.js";
15
+ export { MeshBooleanExecutionError };
13
16
  /**
14
17
  * Buffer-backed triangle mesh with GPU-ready accessors.
15
18
  * All geometry lives in a Float64Array from WASM.
@@ -27,6 +30,72 @@ export class Mesh {
27
30
  this._buffer = buffer;
28
31
  this._vertexCount = buffer.length > 0 ? buffer[0] : 0;
29
32
  }
33
+ /**
34
+ * Configure default size for the shared boolean worker pool.
35
+ */
36
+ static configureBooleanWorkerPool(options) {
37
+ configureDefaultMeshBooleanWorkerPool(options);
38
+ }
39
+ /**
40
+ * Dispose all shared boolean worker pools.
41
+ */
42
+ static disposeBooleanWorkerPools() {
43
+ disposeMeshBooleanWorkerPools();
44
+ }
45
+ static resolveBooleanLimits(overrides) {
46
+ const defaults = Mesh.DEFAULT_BOOLEAN_LIMITS;
47
+ return {
48
+ maxInputFacesPerMesh: overrides?.maxInputFacesPerMesh ?? defaults.maxInputFacesPerMesh,
49
+ maxCombinedInputFaces: overrides?.maxCombinedInputFaces ?? defaults.maxCombinedInputFaces,
50
+ maxFaceProduct: overrides?.maxFaceProduct ?? defaults.maxFaceProduct,
51
+ };
52
+ }
53
+ static computeRawBounds(mesh) {
54
+ if (mesh._vertexCount <= 0)
55
+ return null;
56
+ const data = mesh._buffer;
57
+ const limit = 1 + mesh._vertexCount * 3;
58
+ let minX = data[1];
59
+ let minY = data[2];
60
+ let minZ = data[3];
61
+ let maxX = minX;
62
+ let maxY = minY;
63
+ let maxZ = minZ;
64
+ for (let i = 4; i < limit; i += 3) {
65
+ const x = data[i];
66
+ const y = data[i + 1];
67
+ const z = data[i + 2];
68
+ if (x < minX)
69
+ minX = x;
70
+ if (y < minY)
71
+ minY = y;
72
+ if (z < minZ)
73
+ minZ = z;
74
+ if (x > maxX)
75
+ maxX = x;
76
+ if (y > maxY)
77
+ maxY = y;
78
+ if (z > maxZ)
79
+ maxZ = z;
80
+ }
81
+ return { minX, minY, minZ, maxX, maxY, maxZ };
82
+ }
83
+ static boundsOverlap(a, b, eps = 1e-9) {
84
+ if (!a || !b)
85
+ return false;
86
+ return a.minX <= b.maxX + eps
87
+ && a.maxX + eps >= b.minX
88
+ && a.minY <= b.maxY + eps
89
+ && a.maxY + eps >= b.minY
90
+ && a.minZ <= b.maxZ + eps
91
+ && a.maxZ + eps >= b.minZ;
92
+ }
93
+ static cloneMesh(mesh) {
94
+ return Mesh.fromBuffer(new Float64Array(mesh._buffer));
95
+ }
96
+ static emptyMesh() {
97
+ return Mesh.fromBuffer(new Float64Array(0));
98
+ }
30
99
  // ── GPU-ready buffers ──────────────────────────────────────────
31
100
  /**
32
101
  * Float32 xyz positions for Three.js BufferGeometry.
@@ -146,6 +215,190 @@ export class Mesh {
146
215
  radius,
147
216
  };
148
217
  }
218
+ /**
219
+ * Build a planar arc from center, start, and end points.
220
+ * Uses the shortest signed sweep between start and end around `normal`.
221
+ */
222
+ static buildPlanarArcCenterStartEnd(center, startPoint, endPoint, normal, segments = 64) {
223
+ const n = normal.normalize();
224
+ const minSegments = Math.max(2, Math.floor(segments));
225
+ const startRaw = startPoint.sub(center);
226
+ const endRaw = endPoint.sub(center);
227
+ const startVec = startRaw.sub(n.scale(startRaw.dot(n)));
228
+ const endVec = endRaw.sub(n.scale(endRaw.dot(n)));
229
+ const radius = startVec.length();
230
+ const endLen = endVec.length();
231
+ if (radius < 1e-12 || endLen < 1e-12) {
232
+ return {
233
+ points: [],
234
+ center,
235
+ radius: 0,
236
+ startAngle: 0,
237
+ endAngle: 0,
238
+ sweepAngle: 0,
239
+ };
240
+ }
241
+ const basis = Mesh.resolveArcBasis(center, radius, n);
242
+ const startAngle = Mesh.angleOnBasis(startVec, basis.uAxis, basis.vAxis);
243
+ const endAngleRaw = Mesh.angleOnBasis(endVec.scale(radius / endLen), basis.uAxis, basis.vAxis);
244
+ const sweepAngle = Mesh.normalizeSignedAngle(endAngleRaw - startAngle);
245
+ if (Math.abs(sweepAngle) < 1e-9) {
246
+ return {
247
+ points: [],
248
+ center,
249
+ radius: 0,
250
+ startAngle: 0,
251
+ endAngle: 0,
252
+ sweepAngle: 0,
253
+ };
254
+ }
255
+ const endAngle = startAngle + sweepAngle;
256
+ const arc = new Arc(center, radius, startAngle, endAngle, n);
257
+ return {
258
+ points: arc.sample(minSegments),
259
+ center,
260
+ radius,
261
+ startAngle,
262
+ endAngle,
263
+ sweepAngle,
264
+ };
265
+ }
266
+ /**
267
+ * Build a planar arc from start/end points and a radius control point.
268
+ * Radius is measured from start point to radiusPoint in the active plane.
269
+ * The best of 4 candidates (2 centers x minor/major sweeps) is selected by
270
+ * midpoint proximity to radiusPoint.
271
+ */
272
+ static buildPlanarArcStartEndRadius(startPoint, endPoint, radiusPoint, normal, segments = 64) {
273
+ const n = normal.normalize();
274
+ const minSegments = Math.max(2, Math.floor(segments));
275
+ const start = Mesh.projectPointToPlane(startPoint, startPoint, n);
276
+ const end = Mesh.projectPointToPlane(endPoint, startPoint, n);
277
+ const guide = Mesh.projectPointToPlane(radiusPoint, startPoint, n);
278
+ const chord = end.sub(start);
279
+ const chordLength = chord.length();
280
+ if (chordLength < 1e-9) {
281
+ return null;
282
+ }
283
+ const radius = guide.sub(start).length();
284
+ const halfChord = chordLength * 0.5;
285
+ if (!Number.isFinite(radius) || radius < halfChord + 1e-9) {
286
+ return null;
287
+ }
288
+ const chordDir = chord.scale(1 / chordLength);
289
+ const perpRaw = n.cross(chordDir);
290
+ const perpLen = perpRaw.length();
291
+ if (perpLen < 1e-12) {
292
+ return null;
293
+ }
294
+ const perp = perpRaw.scale(1 / perpLen);
295
+ const hSq = radius * radius - halfChord * halfChord;
296
+ if (hSq < 0) {
297
+ return null;
298
+ }
299
+ const h = Math.sqrt(Math.max(0, hSq));
300
+ const mid = start.add(chord.scale(0.5));
301
+ const centers = [mid.add(perp.scale(h)), mid.add(perp.scale(-h))];
302
+ const candidates = [];
303
+ for (const center of centers) {
304
+ const startVec = start.sub(center);
305
+ const endVec = end.sub(center);
306
+ if (startVec.length() < 1e-12 || endVec.length() < 1e-12) {
307
+ continue;
308
+ }
309
+ const basis = Mesh.resolveArcBasis(center, radius, n);
310
+ const startAngle = Mesh.angleOnBasis(startVec, basis.uAxis, basis.vAxis);
311
+ const endAngleRaw = Mesh.angleOnBasis(endVec, basis.uAxis, basis.vAxis);
312
+ const minorSweep = Mesh.normalizeSignedAngle(endAngleRaw - startAngle);
313
+ if (Math.abs(minorSweep) < 1e-9) {
314
+ continue;
315
+ }
316
+ const majorSweep = minorSweep > 0
317
+ ? minorSweep - Math.PI * 2
318
+ : minorSweep + Math.PI * 2;
319
+ const sweepOptions = [minorSweep];
320
+ if (Math.abs(majorSweep) > 1e-9) {
321
+ sweepOptions.push(majorSweep);
322
+ }
323
+ for (const sweepAngle of sweepOptions) {
324
+ const endAngle = startAngle + sweepAngle;
325
+ const arc = new Arc(center, radius, startAngle, endAngle, n);
326
+ const midPoint = arc.pointAt(0.5);
327
+ candidates.push({
328
+ center,
329
+ radius,
330
+ startAngle,
331
+ endAngle,
332
+ sweepAngle,
333
+ points: arc.sample(minSegments),
334
+ score: midPoint.distanceTo(guide),
335
+ });
336
+ }
337
+ }
338
+ if (candidates.length === 0) {
339
+ return null;
340
+ }
341
+ candidates.sort((a, b) => a.score - b.score);
342
+ const winner = candidates[0];
343
+ return {
344
+ points: winner.points,
345
+ center: winner.center,
346
+ radius: winner.radius,
347
+ startAngle: winner.startAngle,
348
+ endAngle: winner.endAngle,
349
+ sweepAngle: winner.sweepAngle,
350
+ };
351
+ }
352
+ static resolveArcBasis(center, radius, normal) {
353
+ if (radius > 1e-12) {
354
+ const circle = new Circle(center, radius, normal);
355
+ const p0 = circle.pointAt(0);
356
+ const pQuarter = circle.pointAt(0.25);
357
+ const uRaw = p0.sub(center);
358
+ const vRaw = pQuarter.sub(center);
359
+ const uLen = uRaw.length();
360
+ const vLen = vRaw.length();
361
+ if (uLen > 1e-12 && vLen > 1e-12) {
362
+ return {
363
+ uAxis: uRaw.scale(1 / uLen),
364
+ vAxis: vRaw.scale(1 / vLen),
365
+ };
366
+ }
367
+ }
368
+ const n = normal.normalize();
369
+ const reference = Math.abs(n.z) < 0.9 ? Vec3.Z : Vec3.X;
370
+ const uRaw = n.cross(reference);
371
+ const uLen = uRaw.length();
372
+ if (uLen < 1e-12) {
373
+ return { uAxis: Vec3.X, vAxis: Vec3.Y };
374
+ }
375
+ const uAxis = uRaw.scale(1 / uLen);
376
+ const vRaw = n.cross(uAxis);
377
+ const vLen = vRaw.length();
378
+ if (vLen < 1e-12) {
379
+ return { uAxis, vAxis: Vec3.Y };
380
+ }
381
+ return { uAxis, vAxis: vRaw.scale(1 / vLen) };
382
+ }
383
+ static angleOnBasis(vector, uAxis, vAxis) {
384
+ return Math.atan2(vector.dot(vAxis), vector.dot(uAxis));
385
+ }
386
+ static normalizeSignedAngle(angle) {
387
+ const twoPi = Math.PI * 2;
388
+ let wrapped = angle % twoPi;
389
+ if (wrapped <= -Math.PI) {
390
+ wrapped += twoPi;
391
+ }
392
+ else if (wrapped > Math.PI) {
393
+ wrapped -= twoPi;
394
+ }
395
+ return wrapped;
396
+ }
397
+ static projectPointToPlane(point, planeOrigin, planeNormal) {
398
+ const offset = point.sub(planeOrigin);
399
+ const projected = offset.sub(planeNormal.scale(offset.dot(planeNormal)));
400
+ return planeOrigin.add(projected);
401
+ }
149
402
  /**
150
403
  * Create a planar patch mesh from boundary points using CDT (Constrained Delaunay Triangulation).
151
404
  * Correctly handles both convex and concave polygons.
@@ -516,33 +769,107 @@ export class Mesh {
516
769
  ensureInit();
517
770
  return new Mesh(wasm.mesh_scale(this._vertexCount, this._buffer, sx, sy, sz));
518
771
  }
772
+ runBoolean(other, operation, invoke, options) {
773
+ const faceCountA = this.faceCount;
774
+ const faceCountB = other.faceCount;
775
+ if (operation === "union") {
776
+ if (faceCountA === 0)
777
+ return Mesh.cloneMesh(other);
778
+ if (faceCountB === 0)
779
+ return Mesh.cloneMesh(this);
780
+ }
781
+ else if (operation === "intersection") {
782
+ if (faceCountA === 0 || faceCountB === 0)
783
+ return Mesh.emptyMesh();
784
+ }
785
+ else {
786
+ if (faceCountA === 0)
787
+ return Mesh.emptyMesh();
788
+ if (faceCountB === 0)
789
+ return Mesh.cloneMesh(this);
790
+ }
791
+ const boundsA = Mesh.computeRawBounds(this);
792
+ const boundsB = Mesh.computeRawBounds(other);
793
+ if (!Mesh.boundsOverlap(boundsA, boundsB)) {
794
+ if (operation === "union")
795
+ return Mesh.mergeMeshes([this, other]);
796
+ if (operation === "intersection")
797
+ return Mesh.emptyMesh();
798
+ return Mesh.cloneMesh(this);
799
+ }
800
+ if (!options?.allowUnsafe) {
801
+ const limits = Mesh.resolveBooleanLimits(options?.limits);
802
+ const maxInputFaces = Math.max(faceCountA, faceCountB);
803
+ const combinedInputFaces = faceCountA + faceCountB;
804
+ const faceProduct = faceCountA * faceCountB;
805
+ if (maxInputFaces > limits.maxInputFacesPerMesh
806
+ || combinedInputFaces > limits.maxCombinedInputFaces
807
+ || faceProduct > limits.maxFaceProduct) {
808
+ throw new Error(`Boolean ${operation} blocked by safety limits `
809
+ + `(A faces=${faceCountA}, B faces=${faceCountB}, faceProduct=${faceProduct}). `
810
+ + "Simplify inputs, run in a Worker, or pass allowUnsafe: true to force execution.");
811
+ }
812
+ }
813
+ const result = invoke();
814
+ if (operation === "union" && result.length === 0) {
815
+ throw new Error("Boolean union failed and returned an empty mesh buffer.");
816
+ }
817
+ return Mesh.fromBuffer(result);
818
+ }
519
819
  // ── Booleans ───────────────────────────────────────────────────
520
820
  /**
521
821
  * Compute boolean union with another mesh.
522
822
  * @param other - Mesh to union with
823
+ * @param options - Optional safety overrides
523
824
  * @returns New mesh containing volume of both inputs
524
825
  */
525
- union(other) {
826
+ union(other, options) {
526
827
  ensureInit();
527
- return new Mesh(wasm.mesh_boolean_union(this._vertexCount, this._buffer, other._vertexCount, other._buffer));
828
+ return this.runBoolean(other, "union", () => wasm.mesh_boolean_union(this._vertexCount, this._buffer, other._vertexCount, other._buffer), options);
528
829
  }
529
830
  /**
530
831
  * Compute boolean subtraction with another mesh.
531
832
  * @param other - Mesh to subtract
833
+ * @param options - Optional safety overrides
532
834
  * @returns New mesh with other's volume removed from this
533
835
  */
534
- subtract(other) {
836
+ subtract(other, options) {
535
837
  ensureInit();
536
- return new Mesh(wasm.mesh_boolean_subtraction(this._vertexCount, this._buffer, other._vertexCount, other._buffer));
838
+ return this.runBoolean(other, "subtraction", () => wasm.mesh_boolean_subtraction(this._vertexCount, this._buffer, other._vertexCount, other._buffer), options);
537
839
  }
538
840
  /**
539
841
  * Compute boolean intersection with another mesh.
540
842
  * @param other - Mesh to intersect with
843
+ * @param options - Optional safety overrides
541
844
  * @returns New mesh containing only the overlapping volume
542
845
  */
543
- intersect(other) {
846
+ intersect(other, options) {
544
847
  ensureInit();
545
- return new Mesh(wasm.mesh_boolean_intersection(this._vertexCount, this._buffer, other._vertexCount, other._buffer));
848
+ return this.runBoolean(other, "intersection", () => wasm.mesh_boolean_intersection(this._vertexCount, this._buffer, other._vertexCount, other._buffer), options);
849
+ }
850
+ /**
851
+ * Compute boolean union in a dedicated Web Worker (non-blocking).
852
+ * Defaults to allowUnsafe=true so high-poly jobs can run off the UI thread.
853
+ */
854
+ async unionAsync(other, options) {
855
+ const result = await runMeshBooleanInWorkerPool("union", this._buffer, other._buffer, options);
856
+ return Mesh.fromBuffer(result);
857
+ }
858
+ /**
859
+ * Compute boolean subtraction in a dedicated Web Worker (non-blocking).
860
+ * Defaults to allowUnsafe=true so high-poly jobs can run off the UI thread.
861
+ */
862
+ async subtractAsync(other, options) {
863
+ const result = await runMeshBooleanInWorkerPool("subtraction", this._buffer, other._buffer, options);
864
+ return Mesh.fromBuffer(result);
865
+ }
866
+ /**
867
+ * Compute boolean intersection in a dedicated Web Worker (non-blocking).
868
+ * Defaults to allowUnsafe=true so high-poly jobs can run off the UI thread.
869
+ */
870
+ async intersectAsync(other, options) {
871
+ const result = await runMeshBooleanInWorkerPool("intersection", this._buffer, other._buffer, options);
872
+ return Mesh.fromBuffer(result);
546
873
  }
547
874
  // ── Intersection queries ───────────────────────────────────────
548
875
  /**
@@ -813,4 +1140,9 @@ export class Mesh {
813
1140
  return wasm.mesh_export_obj(this._vertexCount, this._buffer);
814
1141
  }
815
1142
  }
1143
+ Mesh.DEFAULT_BOOLEAN_LIMITS = {
1144
+ maxInputFacesPerMesh: 120000,
1145
+ maxCombinedInputFaces: 180000,
1146
+ maxFaceProduct: 500000000,
1147
+ };
816
1148
  //# sourceMappingURL=Mesh.js.map