okgeometry-api 1.1.1 → 1.1.2
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 +61 -1
- package/dist/Mesh.d.ts.map +1 -1
- package/dist/Mesh.js +156 -1
- package/dist/Mesh.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/wasm-base64.d.ts +1 -1
- package/dist/wasm-base64.js +1 -1
- package/package.json +1 -1
- package/src/Mesh.ts +353 -56
- package/src/index.ts +7 -0
- package/src/wasm-base64.ts +1 -1
- package/wasm/okgeometrycore.js +1 -1
- package/wasm/okgeometrycore_bg.wasm +0 -0
- package/wasm/package.json +1 -1
package/package.json
CHANGED
package/src/Mesh.ts
CHANGED
|
@@ -47,23 +47,77 @@ export interface PlanarCircle {
|
|
|
47
47
|
radius: number;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
export interface PlanarArc {
|
|
51
|
-
points: Point[];
|
|
52
|
-
center: Point;
|
|
53
|
-
radius: number;
|
|
54
|
-
startAngle: number;
|
|
55
|
-
endAngle: number;
|
|
56
|
-
sweepAngle: number;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
interface RawMeshBounds {
|
|
60
|
-
minX: number;
|
|
61
|
-
minY: number;
|
|
62
|
-
minZ: number;
|
|
63
|
-
maxX: number;
|
|
64
|
-
maxY: number;
|
|
65
|
-
maxZ: number;
|
|
66
|
-
}
|
|
50
|
+
export interface PlanarArc {
|
|
51
|
+
points: Point[];
|
|
52
|
+
center: Point;
|
|
53
|
+
radius: number;
|
|
54
|
+
startAngle: number;
|
|
55
|
+
endAngle: number;
|
|
56
|
+
sweepAngle: number;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
interface RawMeshBounds {
|
|
60
|
+
minX: number;
|
|
61
|
+
minY: number;
|
|
62
|
+
minZ: number;
|
|
63
|
+
maxX: number;
|
|
64
|
+
maxY: number;
|
|
65
|
+
maxZ: number;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export type MeshBooleanOperation = "union" | "subtraction" | "intersection";
|
|
69
|
+
|
|
70
|
+
export interface MeshDebugBounds {
|
|
71
|
+
min: Point;
|
|
72
|
+
max: Point;
|
|
73
|
+
center: Point;
|
|
74
|
+
size: Vec3;
|
|
75
|
+
diagonal: number;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface MeshDebugSummary {
|
|
79
|
+
vertexCount: number;
|
|
80
|
+
faceCount: number;
|
|
81
|
+
trustedBooleanInput: boolean;
|
|
82
|
+
isClosedVolume: boolean;
|
|
83
|
+
topology: {
|
|
84
|
+
boundaryEdges: number;
|
|
85
|
+
nonManifoldEdges: number;
|
|
86
|
+
};
|
|
87
|
+
bounds: MeshDebugBounds;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export interface MeshDebugRayHit {
|
|
91
|
+
point: Point;
|
|
92
|
+
normal: Vec3;
|
|
93
|
+
faceIndex: number;
|
|
94
|
+
distance: number;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export interface MeshBooleanDebugProbe {
|
|
98
|
+
label: string;
|
|
99
|
+
origin: Point;
|
|
100
|
+
direction: Vec3;
|
|
101
|
+
maxDistance: number;
|
|
102
|
+
inputAHits: MeshDebugRayHit[];
|
|
103
|
+
inputBHits: MeshDebugRayHit[];
|
|
104
|
+
resultHits: MeshDebugRayHit[];
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export interface MeshBooleanDebugOptions {
|
|
108
|
+
rayPaddingScale?: number;
|
|
109
|
+
maxRayHits?: number;
|
|
110
|
+
probes?: Array<"posX" | "negX" | "posY" | "negY" | "posZ" | "negZ">;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export interface MeshBooleanDebugReport {
|
|
114
|
+
operation: MeshBooleanOperation;
|
|
115
|
+
inputA: MeshDebugSummary;
|
|
116
|
+
inputB: MeshDebugSummary;
|
|
117
|
+
result: Mesh;
|
|
118
|
+
resultSummary: MeshDebugSummary;
|
|
119
|
+
probes: MeshBooleanDebugProbe[];
|
|
120
|
+
}
|
|
67
121
|
|
|
68
122
|
/**
|
|
69
123
|
* Buffer-backed triangle mesh with GPU-ready accessors.
|
|
@@ -71,10 +125,13 @@ interface RawMeshBounds {
|
|
|
71
125
|
*
|
|
72
126
|
* Buffer format: [vertexCount, x1,y1,z1, ..., i1,i2,i3, ...]
|
|
73
127
|
*/
|
|
74
|
-
export class Mesh {
|
|
75
|
-
private _buffer: Float64Array;
|
|
76
|
-
private _vertexCount: number;
|
|
77
|
-
private _trustedBooleanInput: boolean;
|
|
128
|
+
export class Mesh {
|
|
129
|
+
private _buffer: Float64Array;
|
|
130
|
+
private _vertexCount: number;
|
|
131
|
+
private _trustedBooleanInput: boolean;
|
|
132
|
+
private static readonly DEFAULT_BOOLEAN_DEBUG_PROBES: Array<
|
|
133
|
+
"posX" | "negX" | "posY" | "negY" | "posZ" | "negZ"
|
|
134
|
+
> = ["posX", "negX", "posY", "negY", "posZ", "negZ"];
|
|
78
135
|
|
|
79
136
|
private static readonly DEFAULT_BOOLEAN_LIMITS: MeshBooleanLimits = {
|
|
80
137
|
maxInputFacesPerMesh: 120_000,
|
|
@@ -177,10 +234,191 @@ export class Mesh {
|
|
|
177
234
|
return Number.isFinite(diag) && diag > 0 ? diag : 1;
|
|
178
235
|
}
|
|
179
236
|
|
|
180
|
-
private static booleanContactTolerance(a: RawMeshBounds | null, b: RawMeshBounds | null): number {
|
|
181
|
-
const scale = Math.max(Mesh.boundsDiag(a), Mesh.boundsDiag(b));
|
|
182
|
-
return Math.min(1e-4, Math.max(1e-9, scale * 1e-6));
|
|
183
|
-
}
|
|
237
|
+
private static booleanContactTolerance(a: RawMeshBounds | null, b: RawMeshBounds | null): number {
|
|
238
|
+
const scale = Math.max(Mesh.boundsDiag(a), Mesh.boundsDiag(b));
|
|
239
|
+
return Math.min(1e-4, Math.max(1e-9, scale * 1e-6));
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
private static toDebugBounds(bounds: { min: Point; max: Point }): MeshDebugBounds {
|
|
243
|
+
const size = new Vec3(
|
|
244
|
+
bounds.max.x - bounds.min.x,
|
|
245
|
+
bounds.max.y - bounds.min.y,
|
|
246
|
+
bounds.max.z - bounds.min.z,
|
|
247
|
+
);
|
|
248
|
+
return {
|
|
249
|
+
min: bounds.min,
|
|
250
|
+
max: bounds.max,
|
|
251
|
+
center: new Point(
|
|
252
|
+
(bounds.min.x + bounds.max.x) * 0.5,
|
|
253
|
+
(bounds.min.y + bounds.max.y) * 0.5,
|
|
254
|
+
(bounds.min.z + bounds.max.z) * 0.5,
|
|
255
|
+
),
|
|
256
|
+
size,
|
|
257
|
+
diagonal: Math.hypot(size.x, size.y, size.z),
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
private static clampDebugHitCount(count?: number): number {
|
|
262
|
+
if (!Number.isFinite(count)) return 4;
|
|
263
|
+
return Math.max(1, Math.min(32, Math.floor(count ?? 4)));
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
private static collectDebugHits(
|
|
267
|
+
mesh: Mesh,
|
|
268
|
+
origin: Point,
|
|
269
|
+
direction: Vec3,
|
|
270
|
+
maxDistance: number,
|
|
271
|
+
maxHits: number,
|
|
272
|
+
): MeshDebugRayHit[] {
|
|
273
|
+
return mesh.raycastAll(origin, direction, maxDistance).slice(0, maxHits).map((hit) => ({
|
|
274
|
+
point: hit.point,
|
|
275
|
+
normal: hit.normal,
|
|
276
|
+
faceIndex: hit.faceIndex,
|
|
277
|
+
distance: hit.distance,
|
|
278
|
+
}));
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
private static buildBooleanDebugProbes(
|
|
282
|
+
inputA: Mesh,
|
|
283
|
+
inputB: Mesh,
|
|
284
|
+
result: Mesh,
|
|
285
|
+
options?: MeshBooleanDebugOptions,
|
|
286
|
+
): MeshBooleanDebugProbe[] {
|
|
287
|
+
const boundsA = Mesh.toDebugBounds(inputA.getBounds());
|
|
288
|
+
const boundsB = Mesh.toDebugBounds(inputB.getBounds());
|
|
289
|
+
const resultBounds = Mesh.toDebugBounds(result.getBounds());
|
|
290
|
+
const min = new Point(
|
|
291
|
+
Math.min(boundsA.min.x, boundsB.min.x, resultBounds.min.x),
|
|
292
|
+
Math.min(boundsA.min.y, boundsB.min.y, resultBounds.min.y),
|
|
293
|
+
Math.min(boundsA.min.z, boundsB.min.z, resultBounds.min.z),
|
|
294
|
+
);
|
|
295
|
+
const max = new Point(
|
|
296
|
+
Math.max(boundsA.max.x, boundsB.max.x, resultBounds.max.x),
|
|
297
|
+
Math.max(boundsA.max.y, boundsB.max.y, resultBounds.max.y),
|
|
298
|
+
Math.max(boundsA.max.z, boundsB.max.z, resultBounds.max.z),
|
|
299
|
+
);
|
|
300
|
+
const center = new Point(
|
|
301
|
+
(min.x + max.x) * 0.5,
|
|
302
|
+
(min.y + max.y) * 0.5,
|
|
303
|
+
(min.z + max.z) * 0.5,
|
|
304
|
+
);
|
|
305
|
+
const diag = Math.max(
|
|
306
|
+
1e-6,
|
|
307
|
+
Math.hypot(max.x - min.x, max.y - min.y, max.z - min.z),
|
|
308
|
+
);
|
|
309
|
+
const padScale = Number.isFinite(options?.rayPaddingScale)
|
|
310
|
+
? Math.max(0.01, options?.rayPaddingScale ?? 0.25)
|
|
311
|
+
: 0.25;
|
|
312
|
+
const pad = Math.max(1e-3, diag * padScale);
|
|
313
|
+
const maxHits = Mesh.clampDebugHitCount(options?.maxRayHits);
|
|
314
|
+
const probeIds = options?.probes?.length
|
|
315
|
+
? options.probes
|
|
316
|
+
: Mesh.DEFAULT_BOOLEAN_DEBUG_PROBES;
|
|
317
|
+
const probeSpecs: Record<
|
|
318
|
+
"posX" | "negX" | "posY" | "negY" | "posZ" | "negZ",
|
|
319
|
+
{ origin: Point; direction: Vec3 }
|
|
320
|
+
> = {
|
|
321
|
+
posX: {
|
|
322
|
+
origin: new Point(max.x + pad, center.y, center.z),
|
|
323
|
+
direction: new Vec3(-1, 0, 0),
|
|
324
|
+
},
|
|
325
|
+
negX: {
|
|
326
|
+
origin: new Point(min.x - pad, center.y, center.z),
|
|
327
|
+
direction: new Vec3(1, 0, 0),
|
|
328
|
+
},
|
|
329
|
+
posY: {
|
|
330
|
+
origin: new Point(center.x, max.y + pad, center.z),
|
|
331
|
+
direction: new Vec3(0, -1, 0),
|
|
332
|
+
},
|
|
333
|
+
negY: {
|
|
334
|
+
origin: new Point(center.x, min.y - pad, center.z),
|
|
335
|
+
direction: new Vec3(0, 1, 0),
|
|
336
|
+
},
|
|
337
|
+
posZ: {
|
|
338
|
+
origin: new Point(center.x, center.y, max.z + pad),
|
|
339
|
+
direction: new Vec3(0, 0, -1),
|
|
340
|
+
},
|
|
341
|
+
negZ: {
|
|
342
|
+
origin: new Point(center.x, center.y, min.z - pad),
|
|
343
|
+
direction: new Vec3(0, 0, 1),
|
|
344
|
+
},
|
|
345
|
+
};
|
|
346
|
+
const maxDistance = diag + pad * 2;
|
|
347
|
+
|
|
348
|
+
return probeIds.map((id) => {
|
|
349
|
+
const spec = probeSpecs[id];
|
|
350
|
+
return {
|
|
351
|
+
label: id,
|
|
352
|
+
origin: spec.origin,
|
|
353
|
+
direction: spec.direction,
|
|
354
|
+
maxDistance,
|
|
355
|
+
inputAHits: Mesh.collectDebugHits(inputA, spec.origin, spec.direction, maxDistance, maxHits),
|
|
356
|
+
inputBHits: Mesh.collectDebugHits(inputB, spec.origin, spec.direction, maxDistance, maxHits),
|
|
357
|
+
resultHits: Mesh.collectDebugHits(result, spec.origin, spec.direction, maxDistance, maxHits),
|
|
358
|
+
};
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
private static createBooleanDebugReport(
|
|
363
|
+
inputA: Mesh,
|
|
364
|
+
inputB: Mesh,
|
|
365
|
+
result: Mesh,
|
|
366
|
+
operation: MeshBooleanOperation,
|
|
367
|
+
debugOptions?: MeshBooleanDebugOptions,
|
|
368
|
+
): MeshBooleanDebugReport {
|
|
369
|
+
return {
|
|
370
|
+
operation,
|
|
371
|
+
inputA: inputA.debugSummary(),
|
|
372
|
+
inputB: inputB.debugSummary(),
|
|
373
|
+
result,
|
|
374
|
+
resultSummary: result.debugSummary(),
|
|
375
|
+
probes: Mesh.buildBooleanDebugProbes(inputA, inputB, result, debugOptions),
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
private static logSubtractDebugSuccess(
|
|
380
|
+
inputA: Mesh,
|
|
381
|
+
inputB: Mesh,
|
|
382
|
+
result: Mesh,
|
|
383
|
+
options?: MeshBooleanOptions,
|
|
384
|
+
): void {
|
|
385
|
+
try {
|
|
386
|
+
const report = Mesh.createBooleanDebugReport(
|
|
387
|
+
inputA,
|
|
388
|
+
inputB,
|
|
389
|
+
result,
|
|
390
|
+
"subtraction",
|
|
391
|
+
{ maxRayHits: 2, probes: ["posX", "negX", "posY"] },
|
|
392
|
+
);
|
|
393
|
+
console.log("[okgeometry-api] Mesh.subtract debug", {
|
|
394
|
+
options: options ?? null,
|
|
395
|
+
inputA: report.inputA,
|
|
396
|
+
inputB: report.inputB,
|
|
397
|
+
result: report.resultSummary,
|
|
398
|
+
probes: report.probes,
|
|
399
|
+
});
|
|
400
|
+
} catch (debugError) {
|
|
401
|
+
console.error("[okgeometry-api] Mesh.subtract debug logging failed", debugError);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
private static logSubtractDebugFailure(
|
|
406
|
+
inputA: Mesh,
|
|
407
|
+
inputB: Mesh,
|
|
408
|
+
options: MeshBooleanOptions | undefined,
|
|
409
|
+
error: unknown,
|
|
410
|
+
): void {
|
|
411
|
+
try {
|
|
412
|
+
console.error("[okgeometry-api] Mesh.subtract failed", {
|
|
413
|
+
options: options ?? null,
|
|
414
|
+
inputA: inputA.debugSummary(),
|
|
415
|
+
inputB: inputB.debugSummary(),
|
|
416
|
+
error,
|
|
417
|
+
});
|
|
418
|
+
} catch (debugError) {
|
|
419
|
+
console.error("[okgeometry-api] Mesh.subtract failure logging failed", debugError);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
184
422
|
|
|
185
423
|
private static cloneMesh(mesh: Mesh): Mesh {
|
|
186
424
|
return Mesh.fromBuffer(new Float64Array(mesh._buffer), {
|
|
@@ -295,9 +533,22 @@ export class Mesh {
|
|
|
295
533
|
return new Mesh(buffer, true);
|
|
296
534
|
}
|
|
297
535
|
|
|
298
|
-
get trustedBooleanInput(): boolean {
|
|
299
|
-
return this._trustedBooleanInput;
|
|
300
|
-
}
|
|
536
|
+
get trustedBooleanInput(): boolean {
|
|
537
|
+
return this._trustedBooleanInput;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
debugSummary(): MeshDebugSummary {
|
|
541
|
+
const bounds = Mesh.toDebugBounds(this.getBounds());
|
|
542
|
+
const topology = this.topologyMetrics();
|
|
543
|
+
return {
|
|
544
|
+
vertexCount: this.vertexCount,
|
|
545
|
+
faceCount: this.faceCount,
|
|
546
|
+
trustedBooleanInput: this._trustedBooleanInput,
|
|
547
|
+
isClosedVolume: this.isClosedVolume(),
|
|
548
|
+
topology,
|
|
549
|
+
bounds,
|
|
550
|
+
};
|
|
551
|
+
}
|
|
301
552
|
|
|
302
553
|
/**
|
|
303
554
|
* Build an axis-aligned rectangle on a plane basis from opposite corners.
|
|
@@ -1054,12 +1305,12 @@ export class Mesh {
|
|
|
1054
1305
|
return Mesh.fromTrustedBuffer(result);
|
|
1055
1306
|
}
|
|
1056
1307
|
|
|
1057
|
-
static encodeBooleanOperationToken(
|
|
1058
|
-
operation:
|
|
1059
|
-
a: Mesh,
|
|
1060
|
-
b: Mesh,
|
|
1061
|
-
options?: MeshBooleanOptions,
|
|
1062
|
-
): string {
|
|
1308
|
+
static encodeBooleanOperationToken(
|
|
1309
|
+
operation: MeshBooleanOperation,
|
|
1310
|
+
a: Mesh,
|
|
1311
|
+
b: Mesh,
|
|
1312
|
+
options?: MeshBooleanOptions,
|
|
1313
|
+
): string {
|
|
1063
1314
|
const tokens: string[] = [operation];
|
|
1064
1315
|
if (a._trustedBooleanInput && b._trustedBooleanInput) {
|
|
1065
1316
|
tokens.push("trustedInput");
|
|
@@ -1101,22 +1352,29 @@ export class Mesh {
|
|
|
1101
1352
|
* @param options - Optional safety overrides
|
|
1102
1353
|
* @returns New mesh with other's volume removed from this
|
|
1103
1354
|
*/
|
|
1104
|
-
subtract(other: Mesh, options?: MeshBooleanOptions): Mesh {
|
|
1105
|
-
ensureInit();
|
|
1106
|
-
const operationToken = Mesh.encodeBooleanOperationToken("subtraction", this, other, options);
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1355
|
+
subtract(other: Mesh, options?: MeshBooleanOptions): Mesh {
|
|
1356
|
+
ensureInit();
|
|
1357
|
+
const operationToken = Mesh.encodeBooleanOperationToken("subtraction", this, other, options);
|
|
1358
|
+
try {
|
|
1359
|
+
const result = this.runBoolean(
|
|
1360
|
+
other,
|
|
1361
|
+
"subtraction",
|
|
1362
|
+
() => wasm.mesh_boolean_operation(
|
|
1363
|
+
this._vertexCount,
|
|
1364
|
+
this._buffer,
|
|
1365
|
+
other._vertexCount,
|
|
1366
|
+
other._buffer,
|
|
1367
|
+
operationToken,
|
|
1368
|
+
),
|
|
1369
|
+
options,
|
|
1370
|
+
);
|
|
1371
|
+
Mesh.logSubtractDebugSuccess(this, other, result, options);
|
|
1372
|
+
return result;
|
|
1373
|
+
} catch (error) {
|
|
1374
|
+
Mesh.logSubtractDebugFailure(this, other, options, error);
|
|
1375
|
+
throw error;
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1120
1378
|
|
|
1121
1379
|
/**
|
|
1122
1380
|
* Compute boolean intersection with another mesh.
|
|
@@ -1124,9 +1382,9 @@ export class Mesh {
|
|
|
1124
1382
|
* @param options - Optional safety overrides
|
|
1125
1383
|
* @returns New mesh containing only the overlapping volume
|
|
1126
1384
|
*/
|
|
1127
|
-
intersect(other: Mesh, options?: MeshBooleanOptions): Mesh {
|
|
1128
|
-
ensureInit();
|
|
1129
|
-
const operationToken = Mesh.encodeBooleanOperationToken("intersection", this, other, options);
|
|
1385
|
+
intersect(other: Mesh, options?: MeshBooleanOptions): Mesh {
|
|
1386
|
+
ensureInit();
|
|
1387
|
+
const operationToken = Mesh.encodeBooleanOperationToken("intersection", this, other, options);
|
|
1130
1388
|
return this.runBoolean(
|
|
1131
1389
|
other,
|
|
1132
1390
|
"intersection",
|
|
@@ -1137,9 +1395,48 @@ export class Mesh {
|
|
|
1137
1395
|
other._buffer,
|
|
1138
1396
|
operationToken,
|
|
1139
1397
|
),
|
|
1140
|
-
options,
|
|
1141
|
-
);
|
|
1142
|
-
}
|
|
1398
|
+
options,
|
|
1399
|
+
);
|
|
1400
|
+
}
|
|
1401
|
+
|
|
1402
|
+
debugBoolean(
|
|
1403
|
+
other: Mesh,
|
|
1404
|
+
operation: MeshBooleanOperation,
|
|
1405
|
+
options?: MeshBooleanOptions,
|
|
1406
|
+
debugOptions?: MeshBooleanDebugOptions,
|
|
1407
|
+
): MeshBooleanDebugReport {
|
|
1408
|
+
const result = operation === "union"
|
|
1409
|
+
? this.union(other, options)
|
|
1410
|
+
: operation === "subtraction"
|
|
1411
|
+
? this.subtract(other, options)
|
|
1412
|
+
: this.intersect(other, options);
|
|
1413
|
+
|
|
1414
|
+
return Mesh.createBooleanDebugReport(this, other, result, operation, debugOptions);
|
|
1415
|
+
}
|
|
1416
|
+
|
|
1417
|
+
debugUnion(
|
|
1418
|
+
other: Mesh,
|
|
1419
|
+
options?: MeshBooleanOptions,
|
|
1420
|
+
debugOptions?: MeshBooleanDebugOptions,
|
|
1421
|
+
): MeshBooleanDebugReport {
|
|
1422
|
+
return this.debugBoolean(other, "union", options, debugOptions);
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
debugSubtract(
|
|
1426
|
+
other: Mesh,
|
|
1427
|
+
options?: MeshBooleanOptions,
|
|
1428
|
+
debugOptions?: MeshBooleanDebugOptions,
|
|
1429
|
+
): MeshBooleanDebugReport {
|
|
1430
|
+
return this.debugBoolean(other, "subtraction", options, debugOptions);
|
|
1431
|
+
}
|
|
1432
|
+
|
|
1433
|
+
debugIntersect(
|
|
1434
|
+
other: Mesh,
|
|
1435
|
+
options?: MeshBooleanOptions,
|
|
1436
|
+
debugOptions?: MeshBooleanDebugOptions,
|
|
1437
|
+
): MeshBooleanDebugReport {
|
|
1438
|
+
return this.debugBoolean(other, "intersection", options, debugOptions);
|
|
1439
|
+
}
|
|
1143
1440
|
|
|
1144
1441
|
/**
|
|
1145
1442
|
* Compute boolean union in a dedicated Web Worker (non-blocking).
|
package/src/index.ts
CHANGED
|
@@ -35,6 +35,13 @@ export { NurbsSurface } from "./NurbsSurface.js";
|
|
|
35
35
|
// Mesh and operations
|
|
36
36
|
export { Mesh, MeshBooleanExecutionError } from "./Mesh.js";
|
|
37
37
|
export type {
|
|
38
|
+
MeshBooleanOperation,
|
|
39
|
+
MeshBooleanDebugOptions,
|
|
40
|
+
MeshBooleanDebugProbe,
|
|
41
|
+
MeshBooleanDebugReport,
|
|
42
|
+
MeshDebugBounds,
|
|
43
|
+
MeshDebugRayHit,
|
|
44
|
+
MeshDebugSummary,
|
|
38
45
|
MeshBooleanLimits,
|
|
39
46
|
MeshBooleanOptions,
|
|
40
47
|
MeshBooleanAsyncOptions,
|