@ifc-lite/geometry 7.7.0 → 7.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.
- package/README.md +54 -0
- package/dist/byte-streaming-prepass-result.d.ts +11 -0
- package/dist/byte-streaming-prepass-result.d.ts.map +1 -1
- package/dist/domain-export-call.d.ts.map +1 -1
- package/dist/domain-export-call.js +8 -1
- package/dist/domain-export-call.js.map +1 -1
- package/dist/export-errors.d.ts +7 -0
- package/dist/export-errors.d.ts.map +1 -1
- package/dist/export-errors.js +12 -0
- package/dist/export-errors.js.map +1 -1
- package/dist/geometry-parallel-options.d.ts +15 -0
- package/dist/geometry-parallel-options.d.ts.map +1 -1
- package/dist/geometry-parallel.d.ts +2 -47
- package/dist/geometry-parallel.d.ts.map +1 -1
- package/dist/geometry-parallel.js +59 -157
- package/dist/geometry-parallel.js.map +1 -1
- package/dist/geometry-worker-pool.d.ts +72 -0
- package/dist/geometry-worker-pool.d.ts.map +1 -0
- package/dist/geometry-worker-pool.js +176 -0
- package/dist/geometry-worker-pool.js.map +1 -0
- package/dist/geometry.worker.d.ts.map +1 -1
- package/dist/geometry.worker.js +19 -25
- package/dist/geometry.worker.js.map +1 -1
- package/dist/hung-job-recovery.d.ts +26 -2
- package/dist/hung-job-recovery.d.ts.map +1 -1
- package/dist/hung-job-recovery.js +42 -7
- package/dist/hung-job-recovery.js.map +1 -1
- package/dist/ifc-lite-bridge.d.ts +13 -2
- package/dist/ifc-lite-bridge.d.ts.map +1 -1
- package/dist/ifc-lite-bridge.js +27 -26
- package/dist/ifc-lite-bridge.js.map +1 -1
- package/dist/in-call-heartbeat.d.ts +20 -0
- package/dist/in-call-heartbeat.d.ts.map +1 -0
- package/dist/in-call-heartbeat.js +39 -0
- package/dist/in-call-heartbeat.js.map +1 -0
- package/dist/index.d.ts +21 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +27 -28
- package/dist/index.js.map +1 -1
- package/dist/landxml-terrain-export.d.ts +41 -0
- package/dist/landxml-terrain-export.d.ts.map +1 -0
- package/dist/landxml-terrain-export.js +14 -0
- package/dist/landxml-terrain-export.js.map +1 -0
- package/dist/main-engine-init.d.ts +5 -0
- package/dist/main-engine-init.d.ts.map +1 -0
- package/dist/main-engine-init.js +42 -0
- package/dist/main-engine-init.js.map +1 -0
- package/dist/perf-flags.d.ts +55 -0
- package/dist/perf-flags.d.ts.map +1 -0
- package/dist/perf-flags.js +66 -0
- package/dist/perf-flags.js.map +1 -0
- package/dist/prepass-routing.d.ts +53 -0
- package/dist/prepass-routing.d.ts.map +1 -0
- package/dist/prepass-routing.js +100 -0
- package/dist/prepass-routing.js.map +1 -0
- package/dist/scan-proposals.d.ts +132 -0
- package/dist/scan-proposals.d.ts.map +1 -0
- package/dist/scan-proposals.js +12 -0
- package/dist/scan-proposals.js.map +1 -0
- package/dist/scan-segmentation.d.ts +205 -0
- package/dist/scan-segmentation.d.ts.map +1 -0
- package/dist/scan-segmentation.js +17 -0
- package/dist/scan-segmentation.js.map +1 -0
- package/dist/warm-pool.d.ts +27 -0
- package/dist/warm-pool.d.ts.map +1 -0
- package/dist/warm-pool.js +48 -0
- package/dist/warm-pool.js.map +1 -0
- package/dist/wasm-shared-module.d.ts +17 -19
- package/dist/wasm-shared-module.d.ts.map +1 -1
- package/dist/wasm-shared-module.js +90 -77
- package/dist/wasm-shared-module.js.map +1 -1
- package/dist/wasm-streaming-guard.d.ts +2 -0
- package/dist/wasm-streaming-guard.d.ts.map +1 -0
- package/dist/wasm-streaming-guard.js +22 -0
- package/dist/wasm-streaming-guard.js.map +1 -0
- package/dist/worker-count.d.ts +10 -0
- package/dist/worker-count.d.ts.map +1 -1
- package/dist/worker-count.js +19 -0
- package/dist/worker-count.js.map +1 -1
- package/dist/worker-trace.d.ts +16 -0
- package/dist/worker-trace.d.ts.map +1 -0
- package/dist/worker-trace.js +39 -0
- package/dist/worker-trace.js.map +1 -0
- package/dist/world-frame.d.ts +24 -0
- package/dist/world-frame.d.ts.map +1 -1
- package/dist/world-frame.js +34 -0
- package/dist/world-frame.js.map +1 -1
- package/package.json +18 -7
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure planning helpers of the parallel pipeline (moved out of
|
|
3
|
+
* `geometry-parallel.ts`, which re-exports them): the pre-pass class-byte span
|
|
4
|
+
* lists and content-affinity job routing.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Prepass class-byte layout, mirroring the `PREPASS_CLASS_*` definitions in
|
|
8
|
+
* `rust/processing/src/shard_classes.rs` (the source of truth — these are
|
|
9
|
+
* pinned to it by `prepass-class-spans.test.ts`).
|
|
10
|
+
*
|
|
11
|
+
* The producer packs a named code in the LOW bits and composes FLAG bits on
|
|
12
|
+
* top (`PREPASS_CLASS_FLAG_GEOMETRY_JOB` 0x80, `..._FLAG_TYPE_CANDIDATE`
|
|
13
|
+
* 0x40), so a consumer must mask before comparing — the Rust consumer does
|
|
14
|
+
* (`gpu_meshes/prepass_discovery.rs`), and so does {@link extractPrepassSpanLists}.
|
|
15
|
+
*/
|
|
16
|
+
export declare const PREPASS_CLASS_CODE_MASK = 63;
|
|
17
|
+
/** `IFCSTYLEDITEM`. */
|
|
18
|
+
export declare const PREPASS_CLASS_STYLED_ITEM = 4;
|
|
19
|
+
/** `IFCINDEXEDCOLOURMAP`. */
|
|
20
|
+
export declare const PREPASS_CLASS_INDEXED_COLOUR_MAP = 5;
|
|
21
|
+
/** `IFCMATERIALDEFINITIONREPRESENTATION`. */
|
|
22
|
+
export declare const PREPASS_CLASS_MATERIAL_DEF_REPR = 6;
|
|
23
|
+
/** `IFCRELASSOCIATESMATERIAL`. */
|
|
24
|
+
export declare const PREPASS_CLASS_REL_ASSOCIATES_MATERIAL = 7;
|
|
25
|
+
/** `IFCRELVOIDSELEMENT`. */
|
|
26
|
+
export declare const PREPASS_CLASS_REL_VOIDS = 8;
|
|
27
|
+
/** `IFCRELFILLSELEMENT`. */
|
|
28
|
+
export declare const PREPASS_CLASS_REL_FILLS = 9;
|
|
29
|
+
/** `IFCRELAGGREGATES`. */
|
|
30
|
+
export declare const PREPASS_CLASS_REL_AGGREGATES = 10;
|
|
31
|
+
/**
|
|
32
|
+
* Build one `(id, start, length)` span list per host-consumed prepass class
|
|
33
|
+
* from the stitched shard columns, in FILE ORDER. Every comparison goes
|
|
34
|
+
* through {@link PREPASS_CLASS_CODE_MASK}, so a record that carries a flag bit
|
|
35
|
+
* alongside its named code still lands in its list instead of being dropped.
|
|
36
|
+
* Returns exact-size arrays (one entry per class in `HOST_SPAN_CLASSES`,
|
|
37
|
+
* empty when the file has none).
|
|
38
|
+
*/
|
|
39
|
+
export declare function extractPrepassSpanLists(classes: Uint8Array, ids: Uint32Array, starts: Uint32Array, lengths: Uint32Array): Map<number, Uint32Array>;
|
|
40
|
+
/**
|
|
41
|
+
* Plan content-affinity routing for one chunk: assign each job (by index) to a
|
|
42
|
+
* worker bucket so that every job sharing an affinity key lands on the SAME
|
|
43
|
+
* worker — across the whole stream, since `keyToWorker` is the caller's sticky
|
|
44
|
+
* map. New keys are handed out round-robin from `startWorker`, so each worker
|
|
45
|
+
* owns roughly `1/workerCount` of the distinct keys (≈ distinct geometries, the
|
|
46
|
+
* dominant meshing cost). Pure: mutates only the passed `keyToWorker` and returns
|
|
47
|
+
* the advanced round-robin cursor. (#1130 follow-up — see `affinity_key` in Rust.)
|
|
48
|
+
*/
|
|
49
|
+
export declare function planAffinityRouting(affinity: Uint32Array, totalJobs: number, workerCount: number, keyToWorker: Map<number, number>, startWorker: number): {
|
|
50
|
+
buckets: number[][];
|
|
51
|
+
nextWorker: number;
|
|
52
|
+
};
|
|
53
|
+
//# sourceMappingURL=prepass-routing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prepass-routing.d.ts","sourceRoot":"","sources":["../src/prepass-routing.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AAEH;;;;;;;;;GASG;AACH,eAAO,MAAM,uBAAuB,KAAO,CAAC;AAC5C,uBAAuB;AACvB,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAC3C,6BAA6B;AAC7B,eAAO,MAAM,gCAAgC,IAAI,CAAC;AAClD,6CAA6C;AAC7C,eAAO,MAAM,+BAA+B,IAAI,CAAC;AACjD,kCAAkC;AAClC,eAAO,MAAM,qCAAqC,IAAI,CAAC;AACvD,4BAA4B;AAC5B,eAAO,MAAM,uBAAuB,IAAI,CAAC;AACzC,4BAA4B;AAC5B,eAAO,MAAM,uBAAuB,IAAI,CAAC;AACzC,0BAA0B;AAC1B,eAAO,MAAM,4BAA4B,KAAK,CAAC;AAa/C;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,UAAU,EACnB,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,WAAW,GACnB,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAmB1B;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,WAAW,EACrB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAChC,WAAW,EAAE,MAAM,GAClB;IAAE,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAc7C"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
/**
|
|
5
|
+
* Pure planning helpers of the parallel pipeline (moved out of
|
|
6
|
+
* `geometry-parallel.ts`, which re-exports them): the pre-pass class-byte span
|
|
7
|
+
* lists and content-affinity job routing.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Prepass class-byte layout, mirroring the `PREPASS_CLASS_*` definitions in
|
|
11
|
+
* `rust/processing/src/shard_classes.rs` (the source of truth — these are
|
|
12
|
+
* pinned to it by `prepass-class-spans.test.ts`).
|
|
13
|
+
*
|
|
14
|
+
* The producer packs a named code in the LOW bits and composes FLAG bits on
|
|
15
|
+
* top (`PREPASS_CLASS_FLAG_GEOMETRY_JOB` 0x80, `..._FLAG_TYPE_CANDIDATE`
|
|
16
|
+
* 0x40), so a consumer must mask before comparing — the Rust consumer does
|
|
17
|
+
* (`gpu_meshes/prepass_discovery.rs`), and so does {@link extractPrepassSpanLists}.
|
|
18
|
+
*/
|
|
19
|
+
export const PREPASS_CLASS_CODE_MASK = 0x3f;
|
|
20
|
+
/** `IFCSTYLEDITEM`. */
|
|
21
|
+
export const PREPASS_CLASS_STYLED_ITEM = 4;
|
|
22
|
+
/** `IFCINDEXEDCOLOURMAP`. */
|
|
23
|
+
export const PREPASS_CLASS_INDEXED_COLOUR_MAP = 5;
|
|
24
|
+
/** `IFCMATERIALDEFINITIONREPRESENTATION`. */
|
|
25
|
+
export const PREPASS_CLASS_MATERIAL_DEF_REPR = 6;
|
|
26
|
+
/** `IFCRELASSOCIATESMATERIAL`. */
|
|
27
|
+
export const PREPASS_CLASS_REL_ASSOCIATES_MATERIAL = 7;
|
|
28
|
+
/** `IFCRELVOIDSELEMENT`. */
|
|
29
|
+
export const PREPASS_CLASS_REL_VOIDS = 8;
|
|
30
|
+
/** `IFCRELFILLSELEMENT`. */
|
|
31
|
+
export const PREPASS_CLASS_REL_FILLS = 9;
|
|
32
|
+
/** `IFCRELAGGREGATES`. */
|
|
33
|
+
export const PREPASS_CLASS_REL_AGGREGATES = 10;
|
|
34
|
+
/** The classes the host builds span lists for (every other code is ignored). */
|
|
35
|
+
const HOST_SPAN_CLASSES = [
|
|
36
|
+
PREPASS_CLASS_STYLED_ITEM,
|
|
37
|
+
PREPASS_CLASS_INDEXED_COLOUR_MAP,
|
|
38
|
+
PREPASS_CLASS_MATERIAL_DEF_REPR,
|
|
39
|
+
PREPASS_CLASS_REL_ASSOCIATES_MATERIAL,
|
|
40
|
+
PREPASS_CLASS_REL_VOIDS,
|
|
41
|
+
PREPASS_CLASS_REL_FILLS,
|
|
42
|
+
PREPASS_CLASS_REL_AGGREGATES,
|
|
43
|
+
];
|
|
44
|
+
/**
|
|
45
|
+
* Build one `(id, start, length)` span list per host-consumed prepass class
|
|
46
|
+
* from the stitched shard columns, in FILE ORDER. Every comparison goes
|
|
47
|
+
* through {@link PREPASS_CLASS_CODE_MASK}, so a record that carries a flag bit
|
|
48
|
+
* alongside its named code still lands in its list instead of being dropped.
|
|
49
|
+
* Returns exact-size arrays (one entry per class in `HOST_SPAN_CLASSES`,
|
|
50
|
+
* empty when the file has none).
|
|
51
|
+
*/
|
|
52
|
+
export function extractPrepassSpanLists(classes, ids, starts, lengths) {
|
|
53
|
+
// Sized by the code mask rather than by the highest class the host consumes:
|
|
54
|
+
// a masked code is always < 64, so a class added on the Rust side cannot
|
|
55
|
+
// write out of bounds here (typed arrays discard such writes silently).
|
|
56
|
+
const counts = new Uint32Array(PREPASS_CLASS_CODE_MASK + 1);
|
|
57
|
+
for (let i = 0; i < classes.length; i++)
|
|
58
|
+
counts[classes[i] & PREPASS_CLASS_CODE_MASK]++;
|
|
59
|
+
const slots = new Map();
|
|
60
|
+
for (const k of HOST_SPAN_CLASSES)
|
|
61
|
+
slots.set(k, { arr: new Uint32Array(counts[k] * 3), w: 0 });
|
|
62
|
+
for (let i = 0; i < classes.length; i++) {
|
|
63
|
+
const slot = slots.get(classes[i] & PREPASS_CLASS_CODE_MASK);
|
|
64
|
+
if (!slot)
|
|
65
|
+
continue;
|
|
66
|
+
slot.arr[slot.w] = ids[i];
|
|
67
|
+
slot.arr[slot.w + 1] = starts[i];
|
|
68
|
+
slot.arr[slot.w + 2] = lengths[i];
|
|
69
|
+
slot.w += 3;
|
|
70
|
+
}
|
|
71
|
+
const spans = new Map();
|
|
72
|
+
for (const [k, slot] of slots)
|
|
73
|
+
spans.set(k, slot.arr);
|
|
74
|
+
return spans;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Plan content-affinity routing for one chunk: assign each job (by index) to a
|
|
78
|
+
* worker bucket so that every job sharing an affinity key lands on the SAME
|
|
79
|
+
* worker — across the whole stream, since `keyToWorker` is the caller's sticky
|
|
80
|
+
* map. New keys are handed out round-robin from `startWorker`, so each worker
|
|
81
|
+
* owns roughly `1/workerCount` of the distinct keys (≈ distinct geometries, the
|
|
82
|
+
* dominant meshing cost). Pure: mutates only the passed `keyToWorker` and returns
|
|
83
|
+
* the advanced round-robin cursor. (#1130 follow-up — see `affinity_key` in Rust.)
|
|
84
|
+
*/
|
|
85
|
+
export function planAffinityRouting(affinity, totalJobs, workerCount, keyToWorker, startWorker) {
|
|
86
|
+
const buckets = Array.from({ length: workerCount }, () => []);
|
|
87
|
+
let nextWorker = startWorker % workerCount;
|
|
88
|
+
for (let j = 0; j < totalJobs; j++) {
|
|
89
|
+
const key = affinity[j];
|
|
90
|
+
let w = keyToWorker.get(key);
|
|
91
|
+
if (w === undefined) {
|
|
92
|
+
w = nextWorker;
|
|
93
|
+
nextWorker = (nextWorker + 1) % workerCount;
|
|
94
|
+
keyToWorker.set(key, w);
|
|
95
|
+
}
|
|
96
|
+
buckets[w].push(j);
|
|
97
|
+
}
|
|
98
|
+
return { buckets, nextWorker };
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=prepass-routing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prepass-routing.js","sourceRoot":"","sources":["../src/prepass-routing.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed entry to scan-to-BIM element proposals (#6894). The logic is Rust
|
|
3
|
+
* (`ifc_lite_processing::scan_proposals`): opposite wall faces pair into
|
|
4
|
+
* walls, floors and ceilings into slabs, vertical cylinders into columns and
|
|
5
|
+
* the rest into pipes. This module only types the JSON the wasm call takes
|
|
6
|
+
* and returns.
|
|
7
|
+
*
|
|
8
|
+
* Proposals are in the IFC model frame: Z up, metres. `scanToModel` maps the
|
|
9
|
+
* segmentation report's frame into it; for the viewer's Y-up, decode-relative
|
|
10
|
+
* scan sample that is the point cloud's placement composed with the Y-up to
|
|
11
|
+
* Z-up swap and the model's world offset.
|
|
12
|
+
*/
|
|
13
|
+
import type { IfcAPI } from '@ifc-lite/wasm';
|
|
14
|
+
import type { ScanSegmentationReport, ScanVec3 } from './scan-segmentation.js';
|
|
15
|
+
export type ProposalSchema = 'IFC2X3' | 'IFC4' | 'IFC4X3';
|
|
16
|
+
/** Every field is optional; omitted fields take the Rust defaults below. */
|
|
17
|
+
export interface ScanProposalOptions {
|
|
18
|
+
/**
|
|
19
|
+
* Row-major 4x4 similarity (rotation, uniform scale, translation) from the
|
|
20
|
+
* report's frame to the IFC model frame. Default identity. Reflections and
|
|
21
|
+
* non-uniform scale are refused.
|
|
22
|
+
*/
|
|
23
|
+
scanToModel?: number[];
|
|
24
|
+
/** Decides the pipe class: IfcFlowSegment in IFC2X3, else IfcPipeSegment. Default IFC4. */
|
|
25
|
+
schema?: ProposalSchema;
|
|
26
|
+
/** Horizontal / vertical tolerance in the model frame. Default 10 degrees. */
|
|
27
|
+
classificationAngleDegrees?: number;
|
|
28
|
+
/** Wall faces pair when parallel within this. Default 5 degrees. */
|
|
29
|
+
pairingAngleDegrees?: number;
|
|
30
|
+
/** Paired wall faces lie this far apart or more. Default 0.05 m. */
|
|
31
|
+
minWallThicknessMetres?: number;
|
|
32
|
+
/** ... and at most this far. Default 0.6 m. */
|
|
33
|
+
maxWallThicknessMetres?: number;
|
|
34
|
+
/** Thickness of a wall seen from one side, placed behind the scanned side. Default 0.2 m. */
|
|
35
|
+
defaultWallThicknessMetres?: number;
|
|
36
|
+
/** Paired faces overlap along the wall by this share of the shorter one. Default 0.5. */
|
|
37
|
+
minWallOverlapFraction?: number;
|
|
38
|
+
/** Shorter vertical faces are not walls. Default 0.5 m. */
|
|
39
|
+
minWallLengthMetres?: number;
|
|
40
|
+
/** Lower vertical faces are not walls. Default 1 m. */
|
|
41
|
+
minWallHeightMetres?: number;
|
|
42
|
+
/** Smaller horizontal planes are not slabs. Default 1 m^2. */
|
|
43
|
+
minSlabAreaSquareMetres?: number;
|
|
44
|
+
/** Thickness of a slab seen from one side. Default 0.2 m. */
|
|
45
|
+
defaultSlabThicknessMetres?: number;
|
|
46
|
+
/** A ceiling and the floor above pair into one slab when this close (and at least `minWallThicknessMetres` apart). Default 0.6 m. */
|
|
47
|
+
maxSlabThicknessMetres?: number;
|
|
48
|
+
/** Wall and column ends within this of a floor or ceiling extend to it. Default 0.3 m. */
|
|
49
|
+
levelSnapMetres?: number;
|
|
50
|
+
/** A point inside the scanned space (model frame). Default: area-weighted plane centroid. */
|
|
51
|
+
interiorPoint?: ScanVec3 | null;
|
|
52
|
+
}
|
|
53
|
+
export type ProposalClass = 'IfcWall' | 'IfcSlab' | 'IfcColumn' | 'IfcPipeSegment' | 'IfcFlowSegment';
|
|
54
|
+
/** How the proposal was derived. */
|
|
55
|
+
export type ProposalBasis = 'pairedFaces' | 'singleFace' | 'floorCeilingPair' | 'floor' | 'ceiling' | 'cylinder';
|
|
56
|
+
/** An index into the segmentation report's `planes` or `cylinders`. */
|
|
57
|
+
export interface DetectionRef {
|
|
58
|
+
kind: 'plane' | 'cylinder';
|
|
59
|
+
index: number;
|
|
60
|
+
}
|
|
61
|
+
export interface ProposalFit {
|
|
62
|
+
/** Inlier-weighted RMS of the sources' residuals. */
|
|
63
|
+
rmsMetres: number;
|
|
64
|
+
inlierPoints: number;
|
|
65
|
+
inlierVoxels: number;
|
|
66
|
+
/** Measured area of the sources (cylinders: arc x radius x length). */
|
|
67
|
+
areaSquareMetres: number;
|
|
68
|
+
}
|
|
69
|
+
export type ProposalGeometry =
|
|
70
|
+
/** Axis line on the wall's centre plane, at its base elevation. */
|
|
71
|
+
{
|
|
72
|
+
kind: 'wall';
|
|
73
|
+
start: ScanVec3;
|
|
74
|
+
end: ScanVec3;
|
|
75
|
+
thicknessMetres: number;
|
|
76
|
+
heightMetres: number;
|
|
77
|
+
}
|
|
78
|
+
/** Top face outline, counter-clockwise from above; the slab extends `thicknessMetres` below. */
|
|
79
|
+
| {
|
|
80
|
+
kind: 'slab';
|
|
81
|
+
outline: ScanVec3[];
|
|
82
|
+
thicknessMetres: number;
|
|
83
|
+
}
|
|
84
|
+
/** `radiusMetres`: the fitted radius; a polygonal column gets the circle of equal cross-section area. */
|
|
85
|
+
| {
|
|
86
|
+
kind: 'column';
|
|
87
|
+
base: ScanVec3;
|
|
88
|
+
heightMetres: number;
|
|
89
|
+
radiusMetres: number;
|
|
90
|
+
} | {
|
|
91
|
+
kind: 'pipe';
|
|
92
|
+
start: ScanVec3;
|
|
93
|
+
end: ScanVec3;
|
|
94
|
+
radiusMetres: number;
|
|
95
|
+
};
|
|
96
|
+
export interface ScanElementProposal {
|
|
97
|
+
/** Stable within one report: `wall-0`, `slab-2`, `column-1`, `pipe-0`. */
|
|
98
|
+
id: string;
|
|
99
|
+
ifcClass: ProposalClass;
|
|
100
|
+
/** 0..1: prior(basis) x fit quality x coverage. */
|
|
101
|
+
confidence: number;
|
|
102
|
+
basis: ProposalBasis;
|
|
103
|
+
sources: DetectionRef[];
|
|
104
|
+
fit: ProposalFit;
|
|
105
|
+
geometry: ProposalGeometry;
|
|
106
|
+
}
|
|
107
|
+
export interface ScanProposalStats {
|
|
108
|
+
verticalPlanes: number;
|
|
109
|
+
horizontalPlanes: number;
|
|
110
|
+
slopedPlanes: number;
|
|
111
|
+
pairedWalls: number;
|
|
112
|
+
singleFaceWalls: number;
|
|
113
|
+
facesTooSmall: number;
|
|
114
|
+
pairedSlabs: number;
|
|
115
|
+
singleSlabs: number;
|
|
116
|
+
slabsTooSmall: number;
|
|
117
|
+
columns: number;
|
|
118
|
+
pipes: number;
|
|
119
|
+
}
|
|
120
|
+
export interface ScanProposalReport {
|
|
121
|
+
algorithm: string;
|
|
122
|
+
/** Walls, then slabs, columns and pipes; each class by descending support. */
|
|
123
|
+
proposals: ScanElementProposal[];
|
|
124
|
+
/** Uniform scale of `scanToModel`. */
|
|
125
|
+
transformScale: number;
|
|
126
|
+
stats: ScanProposalStats;
|
|
127
|
+
}
|
|
128
|
+
/** The wasm surface this needs: an initialised `IfcAPI` satisfies it. */
|
|
129
|
+
export type ScanProposalEngine = Pick<IfcAPI, 'proposeScanElements'>;
|
|
130
|
+
/** Propose IFC elements from `report`. Throws the Rust error message on invalid options. */
|
|
131
|
+
export declare function proposeScanElements(engine: ScanProposalEngine, report: ScanSegmentationReport, options?: ScanProposalOptions): ScanProposalReport;
|
|
132
|
+
//# sourceMappingURL=scan-proposals.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan-proposals.d.ts","sourceRoot":"","sources":["../src/scan-proposals.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
/** Propose IFC elements from `report`. Throws the Rust error message on invalid options. */
|
|
5
|
+
export function proposeScanElements(engine, report, options = {}) {
|
|
6
|
+
if (options.scanToModel && options.scanToModel.length !== 16) {
|
|
7
|
+
throw new RangeError(`scanToModel needs 16 row-major values, got ${options.scanToModel.length}`);
|
|
8
|
+
}
|
|
9
|
+
const bytes = engine.proposeScanElements(JSON.stringify(report), JSON.stringify(options));
|
|
10
|
+
return JSON.parse(new TextDecoder().decode(bytes));
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=scan-proposals.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan-proposals.js","sourceRoot":"","sources":["../src/scan-proposals.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AA4H/D,4FAA4F;AAC5F,MAAM,UAAU,mBAAmB,CACjC,MAA0B,EAC1B,MAA8B,EAC9B,UAA+B,EAAE;IAEjC,IAAI,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,WAAW,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;QAC7D,MAAM,IAAI,UAAU,CAAC,8CAA8C,OAAO,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC;IACnG,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,CAAC,mBAAmB,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;IAC1F,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAuB,CAAC;AAC3E,CAAC"}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed entry to plane and cylinder detection in point clouds (#6870, #6893). The algorithm is
|
|
3
|
+
* Rust (`ifc_lite_processing::scan_segmentation`); this module only frames
|
|
4
|
+
* the input and types the JSON report the wasm call returns.
|
|
5
|
+
*
|
|
6
|
+
* Coordinates are metres in the frame of the supplied positions, plus
|
|
7
|
+
* `options.origin` on output. The viewer's retained reservoir sample is Y-up
|
|
8
|
+
* and decode-relative: pass `upAxis: [0, 1, 0]`.
|
|
9
|
+
*/
|
|
10
|
+
import type { IfcAPI } from '@ifc-lite/wasm';
|
|
11
|
+
export type ScanVec3 = [number, number, number];
|
|
12
|
+
/** Axis-aligned crop box in the positions' frame (inclusive). */
|
|
13
|
+
export interface ScanRegion {
|
|
14
|
+
min: ScanVec3;
|
|
15
|
+
max: ScanVec3;
|
|
16
|
+
}
|
|
17
|
+
/** Every field is optional; omitted fields take the Rust defaults below. */
|
|
18
|
+
export interface ScanSegmentationOptions {
|
|
19
|
+
/** Averaging voxel edge. Default 0.03 m; 0.005..=1. */
|
|
20
|
+
voxelSizeMetres?: number;
|
|
21
|
+
/**
|
|
22
|
+
* Voxel budget; past it the voxel size doubles. Default 1,500,000. Memory
|
|
23
|
+
* is roughly 180 bytes per voxel: the 8,000,000 maximum (with 2 normal
|
|
24
|
+
* rings) peaks near 1.4 GB, more than a browser tab should spend.
|
|
25
|
+
*/
|
|
26
|
+
maxVoxels?: number;
|
|
27
|
+
/** Normal neighbourhood: 1 = 26 neighbours (default), 2 = 124. */
|
|
28
|
+
normalNeighborRings?: number;
|
|
29
|
+
/** Occupied voxels (self included) a normal needs. Default 6. */
|
|
30
|
+
minNeighbors?: number;
|
|
31
|
+
/**
|
|
32
|
+
* Seed voxels have curvature at most this, or at most the curvature of the
|
|
33
|
+
* flattest 5 % of voxels when noise lifts even flat surfaces above it.
|
|
34
|
+
* Default 0.02.
|
|
35
|
+
*/
|
|
36
|
+
maxSeedCurvature?: number;
|
|
37
|
+
/** Growth and merge angle tolerance. Default 10 degrees. */
|
|
38
|
+
maxNormalAngleDegrees?: number;
|
|
39
|
+
/** Growth and merge distance tolerance. Default 0.02 m. */
|
|
40
|
+
maxPlaneDistanceMetres?: number;
|
|
41
|
+
/** Robust refit band in MADs. Default 2.5. */
|
|
42
|
+
madScale?: number;
|
|
43
|
+
/** Regions whose normals turn faster than this (1/radius) are curved. Default 1 per metre. */
|
|
44
|
+
maxBendPerMetre?: number;
|
|
45
|
+
/** Smaller planes are dropped. Default 0.25 m^2. */
|
|
46
|
+
minPlaneAreaSquareMetres?: number;
|
|
47
|
+
/** Horizontal / vertical classification tolerance. Default 10 degrees. */
|
|
48
|
+
classificationAngleDegrees?: number;
|
|
49
|
+
/** Up direction of the positions' frame. Default [0, 0, 1]. */
|
|
50
|
+
upAxis?: ScanVec3;
|
|
51
|
+
/** When given, every plane normal faces the scanner. */
|
|
52
|
+
scannerPosition?: ScanVec3 | null;
|
|
53
|
+
/** Added to every output coordinate. Default [0, 0, 0]. */
|
|
54
|
+
origin?: ScanVec3;
|
|
55
|
+
/** Only points inside this box take part. */
|
|
56
|
+
region?: ScanRegion | null;
|
|
57
|
+
/** Largest planes kept. Default 10,000. */
|
|
58
|
+
maxPlanes?: number;
|
|
59
|
+
/** Look for cylinders (columns, pipes) among non-planar voxels. Default true. */
|
|
60
|
+
detectCylinders?: boolean;
|
|
61
|
+
/** Accepted cylinder radius range. The minimum defaults to two voxel edges (null), the maximum to 2 m. */
|
|
62
|
+
minCylinderRadiusMetres?: number | null;
|
|
63
|
+
maxCylinderRadiusMetres?: number;
|
|
64
|
+
/** Share of a group a candidate must fit. Default 0.6. */
|
|
65
|
+
minCylinderInlierFraction?: number;
|
|
66
|
+
/** Minimum circumference covered. Default 90 degrees. */
|
|
67
|
+
minCylinderArcDegrees?: number;
|
|
68
|
+
/** Minimum length along the axis. Default 0.3 m. */
|
|
69
|
+
minCylinderLengthMetres?: number;
|
|
70
|
+
/** RANSAC draws per candidate. Default 256. */
|
|
71
|
+
cylinderDraws?: number;
|
|
72
|
+
/** Voxels each draw is scored on. Default 2,048. */
|
|
73
|
+
cylinderScoreSample?: number;
|
|
74
|
+
/** Largest non-planar groups examined. Default 1,024. */
|
|
75
|
+
maxCylinderGroups?: number;
|
|
76
|
+
}
|
|
77
|
+
export type ScanPlaneOrientation = 'horizontal' | 'vertical' | 'sloped';
|
|
78
|
+
/** `scanner`: the normal faces `scannerPosition`. `canonical`: horizontal planes face up, others a fixed axis sign. */
|
|
79
|
+
export type ScanNormalSource = 'scanner' | 'canonical';
|
|
80
|
+
export interface ScanPlaneExtent {
|
|
81
|
+
center: ScanVec3;
|
|
82
|
+
uAxis: ScanVec3;
|
|
83
|
+
vAxis: ScanVec3;
|
|
84
|
+
uLength: number;
|
|
85
|
+
vLength: number;
|
|
86
|
+
corners: [ScanVec3, ScanVec3, ScanVec3, ScanVec3];
|
|
87
|
+
}
|
|
88
|
+
export interface ScanPlane {
|
|
89
|
+
/** Unit normal; `normal . x + d = 0`. */
|
|
90
|
+
normal: ScanVec3;
|
|
91
|
+
d: number;
|
|
92
|
+
centroid: ScanVec3;
|
|
93
|
+
inlierPoints: number;
|
|
94
|
+
inlierVoxels: number;
|
|
95
|
+
areaSquareMetres: number;
|
|
96
|
+
rmsMetres: number;
|
|
97
|
+
extent: ScanPlaneExtent;
|
|
98
|
+
orientation: ScanPlaneOrientation;
|
|
99
|
+
normalSource: ScanNormalSource;
|
|
100
|
+
}
|
|
101
|
+
/** Axis relative to `upAxis`: vertical is a column, horizontal a pipe or beam. */
|
|
102
|
+
export type ScanAxisOrientation = 'vertical' | 'horizontal' | 'sloped';
|
|
103
|
+
/** The faces of a polygonal column: a regular polygon of `faces` sides about the axis. */
|
|
104
|
+
export interface ScanFacets {
|
|
105
|
+
/** Sides of the whole polygon (6 or more), seen or not. */
|
|
106
|
+
faces: number;
|
|
107
|
+
/**
|
|
108
|
+
* Unit outward normal of one face, across the axis; the others follow at
|
|
109
|
+
* multiples of 360 / `faces` degrees. The face nearest the frame's +x
|
|
110
|
+
* (+y when the axis runs along x).
|
|
111
|
+
*/
|
|
112
|
+
faceNormal: ScanVec3;
|
|
113
|
+
/** Distance from the axis to each face (inradius). */
|
|
114
|
+
apothem: number;
|
|
115
|
+
}
|
|
116
|
+
export interface ScanCylinder {
|
|
117
|
+
axisStart: ScanVec3;
|
|
118
|
+
axisEnd: ScanVec3;
|
|
119
|
+
/** Unit; points up unless horizontal. */
|
|
120
|
+
axisDirection: ScanVec3;
|
|
121
|
+
/** For a faceted column, the circumradius (axis to corner). */
|
|
122
|
+
radius: number;
|
|
123
|
+
length: number;
|
|
124
|
+
/** Lowest and highest axis end along `upAxis`. */
|
|
125
|
+
heightRange: [number, number];
|
|
126
|
+
/** Circumference covered by the inliers, in degrees; for pieces joined across a density gap, the larger piece's arc (a lower bound). */
|
|
127
|
+
arcDegrees: number;
|
|
128
|
+
inlierPoints: number;
|
|
129
|
+
inlierVoxels: number;
|
|
130
|
+
rmsMetres: number;
|
|
131
|
+
orientation: ScanAxisOrientation;
|
|
132
|
+
/** Set for a polygonal column (a ring of six or more flat faces); null when round. */
|
|
133
|
+
faceted: ScanFacets | null;
|
|
134
|
+
}
|
|
135
|
+
export interface ScanSegmentationStats {
|
|
136
|
+
inputPoints: number;
|
|
137
|
+
acceptedPoints: number;
|
|
138
|
+
rejectedPoints: number;
|
|
139
|
+
outsideRegionPoints: number;
|
|
140
|
+
/** f32 spacing at the largest coordinate: the finest resolution the positions carry. */
|
|
141
|
+
coordinateSpacingMetres: number;
|
|
142
|
+
voxelSizeMetres: number;
|
|
143
|
+
coarsenings: number;
|
|
144
|
+
voxels: number;
|
|
145
|
+
voxelsWithNormals: number;
|
|
146
|
+
seedVoxels: number;
|
|
147
|
+
/** The curvature gate the seeds passed: `maxSeedCurvature`, or higher on noisy data. */
|
|
148
|
+
seedCurvature: number;
|
|
149
|
+
regionsGrown: number;
|
|
150
|
+
regionsMerged: number;
|
|
151
|
+
curvedRegionsRejected: number;
|
|
152
|
+
smallRegionsRejected: number;
|
|
153
|
+
planarVoxels: number;
|
|
154
|
+
cylinderGroups: number;
|
|
155
|
+
cylindersRejectedAsSpheres: number;
|
|
156
|
+
cylinderCandidatesBelowShare: number;
|
|
157
|
+
cylinderRefitsFailed: number;
|
|
158
|
+
cylindersRejectedForRadius: number;
|
|
159
|
+
cylindersRejectedAsSparse: number;
|
|
160
|
+
cylindersRejectedAsFacets: number;
|
|
161
|
+
cylindersRejectedAsPierced: number;
|
|
162
|
+
cylindersRejectedForUnevenArc: number;
|
|
163
|
+
cylindersRejectedAsDuplicates: number;
|
|
164
|
+
cylindersJoinedAcrossGaps: number;
|
|
165
|
+
cylindersRejectedForArc: number;
|
|
166
|
+
cylindersRejectedForLength: number;
|
|
167
|
+
/** Rings of adjacent vertical planes about a common axis, examined as wide or polygonal columns. */
|
|
168
|
+
planeRings: number;
|
|
169
|
+
/** Rings neither round nor a regular polygon of six or more faces: they stay planes. */
|
|
170
|
+
planeRingsRejectedAsIrregular: number;
|
|
171
|
+
/** Rings with scanned surface inside their footprint (a bay or niche seen from the room). */
|
|
172
|
+
planeRingsRejectedAsHollow: number;
|
|
173
|
+
/** Planes removed because they lie on a reported cylinder or are a faceted column's faces. */
|
|
174
|
+
planesAbsorbedIntoCylinders: number;
|
|
175
|
+
}
|
|
176
|
+
/** Which bounds acted; a bound that acts is always reported. */
|
|
177
|
+
export interface ScanSegmentationLimits {
|
|
178
|
+
voxelBudgetCoarsened: boolean;
|
|
179
|
+
planeLimitHit: boolean;
|
|
180
|
+
/** Positions too far from their frame origin for the voxel size; pass a local `origin`. */
|
|
181
|
+
coordinatePrecisionDegraded: boolean;
|
|
182
|
+
cylinderGroupLimitHit: boolean;
|
|
183
|
+
}
|
|
184
|
+
export interface ScanSegmentationReport {
|
|
185
|
+
algorithm: string;
|
|
186
|
+
/** Largest area first. A surface reported as a cylinder is not also a plane. */
|
|
187
|
+
planes: ScanPlane[];
|
|
188
|
+
/** Longest first; round and faceted columns, pipes. */
|
|
189
|
+
cylinders: ScanCylinder[];
|
|
190
|
+
stats: ScanSegmentationStats;
|
|
191
|
+
limits: ScanSegmentationLimits;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* xyz positions; `count` limits them to a prefix, so a reservoir whose buffer
|
|
195
|
+
* is larger than its fill (the viewer's retained scan sample) passes as is.
|
|
196
|
+
*/
|
|
197
|
+
export interface ScanPointInput {
|
|
198
|
+
positions: Float32Array;
|
|
199
|
+
count?: number;
|
|
200
|
+
}
|
|
201
|
+
/** The wasm surface this needs: an initialised `IfcAPI` satisfies it. */
|
|
202
|
+
export type ScanSegmentationEngine = Pick<IfcAPI, 'segmentScanPoints'>;
|
|
203
|
+
/** Detect planes and cylinders in `input`. Throws the Rust error message on invalid options. */
|
|
204
|
+
export declare function segmentScan(engine: ScanSegmentationEngine, input: ScanPointInput, options?: ScanSegmentationOptions): ScanSegmentationReport;
|
|
205
|
+
//# sourceMappingURL=scan-segmentation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan-segmentation.d.ts","sourceRoot":"","sources":["../src/scan-segmentation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
/** Detect planes and cylinders in `input`. Throws the Rust error message on invalid options. */
|
|
5
|
+
export function segmentScan(engine, input, options = {}) {
|
|
6
|
+
const available = Math.floor(input.positions.length / 3);
|
|
7
|
+
const count = input.count ?? available;
|
|
8
|
+
if (!Number.isInteger(count) || count < 0 || count > available) {
|
|
9
|
+
throw new RangeError(`Scan point count ${count} must be an integer within 0..${available}`);
|
|
10
|
+
}
|
|
11
|
+
const positions = count === available && input.positions.length === count * 3
|
|
12
|
+
? input.positions
|
|
13
|
+
: input.positions.subarray(0, count * 3);
|
|
14
|
+
const bytes = engine.segmentScanPoints(positions, JSON.stringify(options));
|
|
15
|
+
return JSON.parse(new TextDecoder().decode(bytes));
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=scan-segmentation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan-segmentation.js","sourceRoot":"","sources":["../src/scan-segmentation.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AA2N/D,gGAAgG;AAChG,MAAM,UAAU,WAAW,CACzB,MAA8B,EAC9B,KAAqB,EACrB,UAAmC,EAAE;IAErC,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACzD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,SAAS,CAAC;IACvC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,SAAS,EAAE,CAAC;QAC/D,MAAM,IAAI,UAAU,CAAC,oBAAoB,KAAK,iCAAiC,SAAS,EAAE,CAAC,CAAC;IAC9F,CAAC;IACD,MAAM,SAAS,GAAG,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,SAAS,CAAC,MAAM,KAAK,KAAK,GAAG,CAAC;QAC3E,CAAC,CAAC,KAAK,CAAC,SAAS;QACjB,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,MAAM,CAAC,iBAAiB,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;IAC3E,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAA2B,CAAC;AAC/E,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The realm's one pool of prewarmed geometry workers (#7036) and the calls a
|
|
3
|
+
* host uses to fill and empty it. Behind the `warmPool` perf flag: with the
|
|
4
|
+
* experiment disabled, `getWarmGeometryWorkerPool()` is null, nothing is prewarmed
|
|
5
|
+
* and every load spawns its own workers exactly as before.
|
|
6
|
+
*/
|
|
7
|
+
import { GeometryWorkerPool, type GeometryWorkerPoolStats } from './geometry-worker-pool.js';
|
|
8
|
+
/** The shared pool, or null when the flag is off or the realm has no workers. */
|
|
9
|
+
export declare function getWarmGeometryWorkerPool(): GeometryWorkerPool | null;
|
|
10
|
+
/**
|
|
11
|
+
* Fill the pool with the workers a parallel load of `fileSizeMB` will use (its
|
|
12
|
+
* geometry workers plus the pre-pass worker), each with the engine
|
|
13
|
+
* instantiated from the shared compiled module. Call it as soon as a load is
|
|
14
|
+
* requested, so the spawn overlaps the file read. Resolves to the number of
|
|
15
|
+
* workers started (0 when the pool is off, already holds them, or the module
|
|
16
|
+
* could not be compiled: the load then spawns as before).
|
|
17
|
+
*/
|
|
18
|
+
export declare function prewarmGeometryWorkers(options?: {
|
|
19
|
+
fileSizeMB?: number;
|
|
20
|
+
workerCountOverride?: number;
|
|
21
|
+
wasmUrl?: string;
|
|
22
|
+
}): Promise<number>;
|
|
23
|
+
/** Terminate every idle prewarmed worker (memory pressure, a hidden tab, a resource-limit retry). */
|
|
24
|
+
export declare function releaseWarmGeometryWorkers(reason?: string): number;
|
|
25
|
+
/** Idle-pool counters for `?perfMem=1` and the benchmark guards; null before the pool exists. */
|
|
26
|
+
export declare function warmGeometryWorkerPoolStats(): GeometryWorkerPoolStats | null;
|
|
27
|
+
//# sourceMappingURL=warm-pool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"warm-pool.d.ts","sourceRoot":"","sources":["../src/warm-pool.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AAEH,OAAO,EAAE,kBAAkB,EAAE,KAAK,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAQ7F,iFAAiF;AACjF,wBAAgB,yBAAyB,IAAI,kBAAkB,GAAG,IAAI,CAGrE;AAED;;;;;;;GAOG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,GAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GACpF,OAAO,CAAC,MAAM,CAAC,CAOjB;AAED,qGAAqG;AACrG,wBAAgB,0BAA0B,CAAC,MAAM,SAAY,GAAG,MAAM,CAErE;AAED,iGAAiG;AACjG,wBAAgB,2BAA2B,IAAI,uBAAuB,GAAG,IAAI,CAE5E"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
/**
|
|
5
|
+
* The realm's one pool of prewarmed geometry workers (#7036) and the calls a
|
|
6
|
+
* host uses to fill and empty it. Behind the `warmPool` perf flag: with the
|
|
7
|
+
* experiment disabled, `getWarmGeometryWorkerPool()` is null, nothing is prewarmed
|
|
8
|
+
* and every load spawns its own workers exactly as before.
|
|
9
|
+
*/
|
|
10
|
+
import { GeometryWorkerPool } from './geometry-worker-pool.js';
|
|
11
|
+
import { postGeometryWorkerInit } from './geometry-worker-init.js';
|
|
12
|
+
import { readWarmPoolFlag } from './perf-flags.js';
|
|
13
|
+
import { compileSharedWasmModule } from './wasm-shared-module.js';
|
|
14
|
+
import { planLoadWorkerCount } from './worker-count.js';
|
|
15
|
+
let shared = null;
|
|
16
|
+
/** The shared pool, or null when the flag is off or the realm has no workers. */
|
|
17
|
+
export function getWarmGeometryWorkerPool() {
|
|
18
|
+
if (typeof Worker === 'undefined' || !readWarmPoolFlag())
|
|
19
|
+
return null;
|
|
20
|
+
return (shared ??= new GeometryWorkerPool());
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Fill the pool with the workers a parallel load of `fileSizeMB` will use (its
|
|
24
|
+
* geometry workers plus the pre-pass worker), each with the engine
|
|
25
|
+
* instantiated from the shared compiled module. Call it as soon as a load is
|
|
26
|
+
* requested, so the spawn overlaps the file read. Resolves to the number of
|
|
27
|
+
* workers started (0 when the pool is off, already holds them, or the module
|
|
28
|
+
* could not be compiled: the load then spawns as before).
|
|
29
|
+
*/
|
|
30
|
+
export async function prewarmGeometryWorkers(options = {}) {
|
|
31
|
+
const pool = getWarmGeometryWorkerPool();
|
|
32
|
+
if (!pool)
|
|
33
|
+
return 0;
|
|
34
|
+
const module = await compileSharedWasmModule(options.wasmUrl);
|
|
35
|
+
if (!module)
|
|
36
|
+
return 0;
|
|
37
|
+
const { count } = planLoadWorkerCount(options.fileSizeMB ?? 8, options.workerCountOverride);
|
|
38
|
+
return pool.prewarm(count + 1, options.wasmUrl ?? '', (worker) => postGeometryWorkerInit(worker, undefined, module));
|
|
39
|
+
}
|
|
40
|
+
/** Terminate every idle prewarmed worker (memory pressure, a hidden tab, a resource-limit retry). */
|
|
41
|
+
export function releaseWarmGeometryWorkers(reason = 'release') {
|
|
42
|
+
return shared?.drain(reason) ?? 0;
|
|
43
|
+
}
|
|
44
|
+
/** Idle-pool counters for `?perfMem=1` and the benchmark guards; null before the pool exists. */
|
|
45
|
+
export function warmGeometryWorkerPoolStats() {
|
|
46
|
+
return shared?.stats() ?? null;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=warm-pool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"warm-pool.js","sourceRoot":"","sources":["../src/warm-pool.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D;;;;;GAKG;AAEH,OAAO,EAAE,kBAAkB,EAAgC,MAAM,2BAA2B,CAAC;AAC7F,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAExD,IAAI,MAAM,GAA8B,IAAI,CAAC;AAE7C,iFAAiF;AACjF,MAAM,UAAU,yBAAyB;IACvC,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,CAAC,gBAAgB,EAAE;QAAE,OAAO,IAAI,CAAC;IACtE,OAAO,CAAC,MAAM,KAAK,IAAI,kBAAkB,EAAE,CAAC,CAAC;AAC/C,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,UAAmF,EAAE;IAErF,MAAM,IAAI,GAAG,yBAAyB,EAAE,CAAC;IACzC,IAAI,CAAC,IAAI;QAAE,OAAO,CAAC,CAAC;IACpB,MAAM,MAAM,GAAG,MAAM,uBAAuB,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9D,IAAI,CAAC,MAAM;QAAE,OAAO,CAAC,CAAC;IACtB,MAAM,EAAE,KAAK,EAAE,GAAG,mBAAmB,CAAC,OAAO,CAAC,UAAU,IAAI,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC5F,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,GAAG,CAAC,EAAE,OAAO,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,sBAAsB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;AACvH,CAAC;AAED,qGAAqG;AACrG,MAAM,UAAU,0BAA0B,CAAC,MAAM,GAAG,SAAS;IAC3D,OAAO,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AACpC,CAAC;AAED,iGAAiG;AACjG,MAAM,UAAU,2BAA2B;IACzC,OAAO,MAAM,EAAE,KAAK,EAAE,IAAI,IAAI,CAAC;AACjC,CAAC"}
|