okgeometry-api 1.47.0 → 1.48.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.
- package/dist/Mesh.d.ts +55 -31
- package/dist/Mesh.d.ts.map +1 -1
- package/dist/Mesh.js +48 -2
- package/dist/Mesh.js.map +1 -1
- package/dist/mesh-boolean.protocol.d.ts +30 -1
- package/dist/mesh-boolean.protocol.d.ts.map +1 -1
- package/dist/mesh-boolean.worker.d.ts.map +1 -1
- package/dist/mesh-boolean.worker.js +23 -0
- package/dist/mesh-boolean.worker.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 +74 -17
- package/src/mesh-boolean.protocol.ts +19 -1
- package/src/mesh-boolean.worker.ts +33 -0
- package/src/wasm-base64.ts +1 -1
package/package.json
CHANGED
package/src/Mesh.ts
CHANGED
|
@@ -50,6 +50,23 @@ export interface HlrLine {
|
|
|
50
50
|
b3: Point;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
/** View parameters for `Mesh.hlrProject` / `hlrProjectAsync`. */
|
|
54
|
+
export interface HlrProjectOptions {
|
|
55
|
+
viewDir: { x: number; y: number; z: number };
|
|
56
|
+
up: { x: number; y: number; z: number };
|
|
57
|
+
section?: {
|
|
58
|
+
origin: { x: number; y: number; z: number };
|
|
59
|
+
normal: { x: number; y: number; z: number };
|
|
60
|
+
};
|
|
61
|
+
featureAngleDeg?: number;
|
|
62
|
+
/**
|
|
63
|
+
* View depth in world units beyond the section plane — geometry farther
|
|
64
|
+
* than this is discarded (drafting far clip). Requires `section`; <= 0
|
|
65
|
+
* or absent = unlimited.
|
|
66
|
+
*/
|
|
67
|
+
depth?: number;
|
|
68
|
+
}
|
|
69
|
+
|
|
53
70
|
export interface PlanarRectangle {
|
|
54
71
|
corners: [Point, Point, Point, Point];
|
|
55
72
|
width: number;
|
|
@@ -4322,24 +4339,21 @@ export class Mesh {
|
|
|
4322
4339
|
*/
|
|
4323
4340
|
static hlrProject(
|
|
4324
4341
|
meshes: Mesh[],
|
|
4325
|
-
options:
|
|
4326
|
-
viewDir: { x: number; y: number; z: number };
|
|
4327
|
-
up: { x: number; y: number; z: number };
|
|
4328
|
-
section?: {
|
|
4329
|
-
origin: { x: number; y: number; z: number };
|
|
4330
|
-
normal: { x: number; y: number; z: number };
|
|
4331
|
-
};
|
|
4332
|
-
featureAngleDeg?: number;
|
|
4333
|
-
/**
|
|
4334
|
-
* View depth in world units beyond the section plane — geometry
|
|
4335
|
-
* farther than this is discarded (drafting far clip). Requires
|
|
4336
|
-
* `section`; <= 0 or absent = unlimited.
|
|
4337
|
-
*/
|
|
4338
|
-
depth?: number;
|
|
4339
|
-
}
|
|
4342
|
+
options: HlrProjectOptions
|
|
4340
4343
|
): HlrLine[] {
|
|
4344
|
+
return Mesh.parseHlrResult(Mesh.hlrProjectRaw(meshes, options));
|
|
4345
|
+
}
|
|
4346
|
+
|
|
4347
|
+
/**
|
|
4348
|
+
* The raw f64 result of `hlrProject` (wasm layout: [count, (class,
|
|
4349
|
+
* meshIndex, ax, ay, bx, by, a3xyz, b3xyz) x count]). The worker path
|
|
4350
|
+
* transfers this buffer back to the main thread, which parses it with
|
|
4351
|
+
* `parseHlrResult` — HlrLine carries Point instances, which do not
|
|
4352
|
+
* survive structured clone.
|
|
4353
|
+
*/
|
|
4354
|
+
static hlrProjectRaw(meshes: Mesh[], options: HlrProjectOptions): Float64Array {
|
|
4341
4355
|
ensureInit();
|
|
4342
|
-
if (meshes.length === 0) return [];
|
|
4356
|
+
if (meshes.length === 0) return new Float64Array([0]);
|
|
4343
4357
|
const packed = Mesh.packMeshes(meshes);
|
|
4344
4358
|
const s = options.section;
|
|
4345
4359
|
const result = wasm.hlr_project_meshes(
|
|
@@ -4355,9 +4369,14 @@ export class Mesh {
|
|
|
4355
4369
|
if (result.length === 0) {
|
|
4356
4370
|
const error = wasm.geometry_last_error?.();
|
|
4357
4371
|
if (error) throw new Error(`hlrProject failed: ${error}`);
|
|
4358
|
-
return [];
|
|
4372
|
+
return new Float64Array([0]);
|
|
4359
4373
|
}
|
|
4374
|
+
return result;
|
|
4375
|
+
}
|
|
4360
4376
|
|
|
4377
|
+
/** Parse a `hlrProjectRaw` result buffer into classified lines. */
|
|
4378
|
+
static parseHlrResult(result: Float64Array): HlrLine[] {
|
|
4379
|
+
if (result.length === 0) return [];
|
|
4361
4380
|
const lines: HlrLine[] = [];
|
|
4362
4381
|
const count = result[0];
|
|
4363
4382
|
let offset = 1;
|
|
@@ -4376,6 +4395,44 @@ export class Mesh {
|
|
|
4376
4395
|
return lines;
|
|
4377
4396
|
}
|
|
4378
4397
|
|
|
4398
|
+
/**
|
|
4399
|
+
* Async `Mesh.hlrProject` on the worker pool — the whole-scene projection
|
|
4400
|
+
* scales with MODEL size, not edit size, and must not block the UI
|
|
4401
|
+
* thread. `options.transforms` (row-major, aligned with `meshes`) bakes
|
|
4402
|
+
* WORKER-side so the main thread never pays the per-mesh transform pass;
|
|
4403
|
+
* pass LOCAL meshes with their placement transforms. Worker
|
|
4404
|
+
* INFRASTRUCTURE failures fall back to the synchronous main-thread path
|
|
4405
|
+
* (baking transforms first); kernel failures propagate.
|
|
4406
|
+
*/
|
|
4407
|
+
static async hlrProjectAsync(
|
|
4408
|
+
meshes: Mesh[],
|
|
4409
|
+
options: HlrProjectOptions & { transforms?: (number[] | undefined)[] },
|
|
4410
|
+
asyncOptions?: MeshBooleanAsyncOptions
|
|
4411
|
+
): Promise<HlrLine[]> {
|
|
4412
|
+
if (meshes.length === 0) return [];
|
|
4413
|
+
const { transforms, ...view } = options;
|
|
4414
|
+
try {
|
|
4415
|
+
const { buffer } = await runMeshHeavyInWorkerPool(
|
|
4416
|
+
"hlrProject",
|
|
4417
|
+
meshes.map((m) => m._buffer),
|
|
4418
|
+
{
|
|
4419
|
+
...asyncOptions,
|
|
4420
|
+
trusted: meshes.map((m) => m._trustedBooleanInput),
|
|
4421
|
+
residents: meshes,
|
|
4422
|
+
params: { hlr: { ...view, transforms } },
|
|
4423
|
+
}
|
|
4424
|
+
);
|
|
4425
|
+
return Mesh.parseHlrResult(new Float64Array(buffer));
|
|
4426
|
+
} catch (error) {
|
|
4427
|
+
if (!shouldFallbackFromWorkerFailure(error)) throw error;
|
|
4428
|
+
console.warn("Mesh.hlrProjectAsync worker failed; falling back to main thread.", error);
|
|
4429
|
+
const baked = meshes.map((m, i) =>
|
|
4430
|
+
transforms?.[i] ? m.applyMatrix(transforms[i]) : m
|
|
4431
|
+
);
|
|
4432
|
+
return Mesh.hlrProject(baked, view);
|
|
4433
|
+
}
|
|
4434
|
+
}
|
|
4435
|
+
|
|
4379
4436
|
/**
|
|
4380
4437
|
* Compute intersection curves with another mesh.
|
|
4381
4438
|
* @param other - Mesh to intersect with
|
|
@@ -205,7 +205,12 @@ export type MeshHeavyOperation =
|
|
|
205
205
|
| "solidSplitBySurface"
|
|
206
206
|
| "diagnostics"
|
|
207
207
|
| "repair"
|
|
208
|
-
| "importStl"
|
|
208
|
+
| "importStl"
|
|
209
|
+
// hlrProject: [mesh0, mesh1, ...] (LOCAL-space; per-mesh transforms
|
|
210
|
+
// ride `params.hlr.transforms` and bake worker-side).
|
|
211
|
+
// Response buffer = the raw f64 hlr result (parse with
|
|
212
|
+
// Mesh.parseHlrResult).
|
|
213
|
+
| "hlrProject";
|
|
209
214
|
|
|
210
215
|
export interface MeshHeavyParams {
|
|
211
216
|
resolution?: number;
|
|
@@ -249,6 +254,19 @@ export interface MeshHeavyParams {
|
|
|
249
254
|
preserveFeatures?: boolean;
|
|
250
255
|
/** isotropicRemesh: re-project onto the original surface each iteration. */
|
|
251
256
|
project?: boolean;
|
|
257
|
+
/** hlrProject: view/section parameters + optional per-mesh row-major
|
|
258
|
+
* transforms (aligned with the request buffers, baked worker-side). */
|
|
259
|
+
hlr?: {
|
|
260
|
+
viewDir: { x: number; y: number; z: number };
|
|
261
|
+
up: { x: number; y: number; z: number };
|
|
262
|
+
section?: {
|
|
263
|
+
origin: { x: number; y: number; z: number };
|
|
264
|
+
normal: { x: number; y: number; z: number };
|
|
265
|
+
};
|
|
266
|
+
featureAngleDeg?: number;
|
|
267
|
+
depth?: number;
|
|
268
|
+
transforms?: (number[] | undefined)[];
|
|
269
|
+
};
|
|
252
270
|
}
|
|
253
271
|
|
|
254
272
|
export interface MeshHeavyWorkerRequest {
|
|
@@ -268,6 +268,17 @@ function runHeavyOperation(message: {
|
|
|
268
268
|
featureAngleDeg?: number;
|
|
269
269
|
preserveFeatures?: boolean;
|
|
270
270
|
project?: boolean;
|
|
271
|
+
hlr?: {
|
|
272
|
+
viewDir: { x: number; y: number; z: number };
|
|
273
|
+
up: { x: number; y: number; z: number };
|
|
274
|
+
section?: {
|
|
275
|
+
origin: { x: number; y: number; z: number };
|
|
276
|
+
normal: { x: number; y: number; z: number };
|
|
277
|
+
};
|
|
278
|
+
featureAngleDeg?: number;
|
|
279
|
+
depth?: number;
|
|
280
|
+
transforms?: (number[] | undefined)[];
|
|
281
|
+
};
|
|
271
282
|
};
|
|
272
283
|
options: { allowUnsafe?: boolean; limits?: unknown; debugForceFaceID?: boolean };
|
|
273
284
|
}): { buffer: ArrayBuffer; meta?: Record<string, string | number | boolean> } {
|
|
@@ -308,6 +319,28 @@ function runHeavyOperation(message: {
|
|
|
308
319
|
const result = mesh.voxelRemesh(params.resolution ?? 0, params.iso ?? 0.5);
|
|
309
320
|
return packSingleResult(result, params);
|
|
310
321
|
}
|
|
322
|
+
case "hlrProject": {
|
|
323
|
+
const view = params.hlr;
|
|
324
|
+
if (!view) throw new Error("hlrProject requires hlr params");
|
|
325
|
+
const input = meshes();
|
|
326
|
+
// Bake per-mesh transforms HERE — the whole point of the worker job
|
|
327
|
+
// is that the main thread pays neither the projection nor the
|
|
328
|
+
// per-mesh transform pass. applyMatrix returns a NEW mesh, so
|
|
329
|
+
// worker-resident operands are never mutated.
|
|
330
|
+
const baked = input.map((m, i) => {
|
|
331
|
+
const t = view.transforms?.[i];
|
|
332
|
+
return t ? m.applyMatrix(t) : m;
|
|
333
|
+
});
|
|
334
|
+
const raw = Mesh.hlrProjectRaw(baked, {
|
|
335
|
+
viewDir: view.viewDir,
|
|
336
|
+
up: view.up,
|
|
337
|
+
section: view.section,
|
|
338
|
+
featureAngleDeg: view.featureAngleDeg,
|
|
339
|
+
depth: view.depth,
|
|
340
|
+
});
|
|
341
|
+
// Copy before transfer: the wasm result may view the wasm heap.
|
|
342
|
+
return { buffer: new Float64Array(raw).buffer };
|
|
343
|
+
}
|
|
311
344
|
case "isotropicRemesh": {
|
|
312
345
|
const [mesh] = meshes();
|
|
313
346
|
const r = mesh.remesh({
|