@ifc-lite/geometry 4.1.0 → 4.2.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 +6 -3
- package/dist/diagnostics.d.ts +42 -3
- package/dist/diagnostics.d.ts.map +1 -1
- package/dist/diagnostics.js +37 -8
- package/dist/diagnostics.js.map +1 -1
- package/dist/energy-export-bridge.d.ts +35 -0
- package/dist/energy-export-bridge.d.ts.map +1 -0
- package/dist/energy-export-bridge.js +31 -0
- package/dist/energy-export-bridge.js.map +1 -0
- package/dist/geometry-parallel.d.ts +2 -1
- package/dist/geometry-parallel.d.ts.map +1 -1
- package/dist/geometry-parallel.js +29 -85
- package/dist/geometry-parallel.js.map +1 -1
- package/dist/geometry.worker.d.ts +7 -0
- package/dist/geometry.worker.d.ts.map +1 -1
- package/dist/geometry.worker.js +3 -2
- package/dist/geometry.worker.js.map +1 -1
- package/dist/hbjson-stats.d.ts +28 -0
- package/dist/hbjson-stats.d.ts.map +1 -0
- package/dist/hbjson-stats.js +5 -0
- package/dist/hbjson-stats.js.map +1 -0
- package/dist/ifc-lite-bridge.d.ts +11 -14
- package/dist/ifc-lite-bridge.d.ts.map +1 -1
- package/dist/ifc-lite-bridge.js +12 -16
- package/dist/ifc-lite-bridge.js.map +1 -1
- package/dist/index.d.ts +23 -20
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +56 -63
- package/dist/index.js.map +1 -1
- package/dist/packed-instanced-decoder.d.ts +20 -3
- package/dist/packed-instanced-decoder.d.ts.map +1 -1
- package/dist/packed-instanced-decoder.js +122 -17
- package/dist/packed-instanced-decoder.js.map +1 -1
- package/dist/shard-stitch.d.ts +110 -0
- package/dist/shard-stitch.d.ts.map +1 -0
- package/dist/shard-stitch.js +112 -0
- package/dist/shard-stitch.js.map +1 -0
- package/dist/symbolic-types.d.ts +3 -2
- package/dist/symbolic-types.d.ts.map +1 -1
- package/dist/types.d.ts +5 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/wasm-asset-error.d.ts +17 -0
- package/dist/wasm-asset-error.d.ts.map +1 -1
- package/dist/wasm-asset-error.js +32 -0
- package/dist/wasm-asset-error.js.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -26,9 +26,11 @@ console.log(`${result.meshes.length} meshes, ${result.totalTriangles} triangles`
|
|
|
26
26
|
## Stream geometry (recommended for large models)
|
|
27
27
|
|
|
28
28
|
```typescript
|
|
29
|
+
const buffer = new Uint8Array(await file.arrayBuffer());
|
|
30
|
+
|
|
29
31
|
for await (const event of processor.processStreaming(buffer)) {
|
|
30
32
|
if (event.type === 'batch') {
|
|
31
|
-
renderer.
|
|
33
|
+
renderer.addMeshes(event.meshes, true);
|
|
32
34
|
console.log(`Loaded ${event.totalSoFar} meshes so far`);
|
|
33
35
|
} else if (event.type === 'complete') {
|
|
34
36
|
console.log(`Done: ${event.totalMeshes} meshes`);
|
|
@@ -54,8 +56,7 @@ Unset / `'medium'` reproduces the engine's historical densities byte-for-byte. L
|
|
|
54
56
|
## Coordinate handling
|
|
55
57
|
|
|
56
58
|
```typescript
|
|
57
|
-
|
|
58
|
-
|
|
59
|
+
const buffer = new Uint8Array(await file.arrayBuffer());
|
|
59
60
|
const result = await processor.process(buffer);
|
|
60
61
|
|
|
61
62
|
// Models with large world coordinates (geo-referenced) get auto-shifted
|
|
@@ -92,6 +93,8 @@ If your bundler can't transform
|
|
|
92
93
|
wasm URLs through the `processAdaptive` / `processParallel` `wasmUrls`
|
|
93
94
|
option:
|
|
94
95
|
|
|
96
|
+
<!-- Reason: Vite-only `?url` import specifier, unresolvable by tsc. -->
|
|
97
|
+
<!-- docs-check: skip -->
|
|
95
98
|
```ts
|
|
96
99
|
// Vite's `?url` suffix yields a fully-resolved URL string at build time.
|
|
97
100
|
// `@ifc-lite/wasm` exposes the binary at the `./ifc-lite_bg.wasm` subpath
|
package/dist/diagnostics.d.ts
CHANGED
|
@@ -15,9 +15,19 @@
|
|
|
15
15
|
export interface GeometryDiagnostics {
|
|
16
16
|
/**
|
|
17
17
|
* Contract version handshake (mirrors Rust
|
|
18
|
-
* `GEOMETRY_DIAGNOSTICS_SCHEMA_VERSION`, currently
|
|
19
|
-
*
|
|
20
|
-
*
|
|
18
|
+
* `GEOMETRY_DIAGNOSTICS_SCHEMA_VERSION`, currently 3 — that constant carries
|
|
19
|
+
* the per-version changelog and is the single source of truth). Bumped on
|
|
20
|
+
* field renames, field removals, and count-semantics changes; also on an
|
|
21
|
+
* additive field whose absence a consumer must tell apart from a real zero,
|
|
22
|
+
* which is why 2 (removed `guardSaved`) and 3 (added
|
|
23
|
+
* `totalUnsupportedItems`) both bumped. A purely additive optional field
|
|
24
|
+
* that no consumer gates on does not bump.
|
|
25
|
+
*
|
|
26
|
+
* REQUIRED, not optional: the Rust field is a plain `u32` serialized
|
|
27
|
+
* unconditionally, so every producer since #1514 writes the key. A value of
|
|
28
|
+
* `0` is what Rust's `#[serde(default)]` yields when it READS a payload
|
|
29
|
+
* written before #1514, and is the only "pre-versioned producer" signal a
|
|
30
|
+
* consumer sees.
|
|
21
31
|
*/
|
|
22
32
|
schemaVersion: number;
|
|
23
33
|
/** Total CSG boolean failures (un-cut openings, emptied hosts, kernel fallbacks). */
|
|
@@ -58,6 +68,13 @@ export interface GeometryDiagnostics {
|
|
|
58
68
|
/** Optional: absent on payloads produced before this counter existed (#1649). */
|
|
59
69
|
deferTooManyOpenings?: number;
|
|
60
70
|
};
|
|
71
|
+
/**
|
|
72
|
+
* Content-hash references the geometry pass refused because they exceeded
|
|
73
|
+
* `u32::MAX` (#3421 / #3752). Nonzero means some instancing was skipped, not
|
|
74
|
+
* that geometry is wrong. Optional: absent on payloads from producers
|
|
75
|
+
* predating the counter.
|
|
76
|
+
*/
|
|
77
|
+
oversizedRefDrops?: number;
|
|
61
78
|
/** Bounded top-N worst-failing hosts (opt-in per-product detail). */
|
|
62
79
|
worstHosts: Array<{
|
|
63
80
|
productId: number;
|
|
@@ -75,6 +92,28 @@ export interface GeometryDiagnostics {
|
|
|
75
92
|
* subtraction ran, otherwise the pre-cut count). */
|
|
76
93
|
triangleCount?: number;
|
|
77
94
|
}>;
|
|
95
|
+
/**
|
|
96
|
+
* Representation items dropped from the output: no processor is registered
|
|
97
|
+
* for the IFC type, or the registered processor errored (degenerate/failed
|
|
98
|
+
* geometry). Excludes elements with no Body representation at all — those
|
|
99
|
+
* are correctly absent from the 3D view and never counted here. Absent on
|
|
100
|
+
* a payload produced before this counter existed (schemaVersion < 3).
|
|
101
|
+
*
|
|
102
|
+
* A lower bound on instances: a drop inside a `RepresentationMap` source is
|
|
103
|
+
* counted once per walking router, not once per `IfcMappedItem` occurrence
|
|
104
|
+
* that reuses the cached source. That is once model-wide on the wasm batch
|
|
105
|
+
* path, which uses one router; the native pool builds a router per element,
|
|
106
|
+
* and a source whose items ALL drop is never published to the shared cache
|
|
107
|
+
* (it meshes to nothing), so there it contributes once per owning element.
|
|
108
|
+
* Read it as "these types were dropped", never as a count of affected
|
|
109
|
+
* elements or of distinct sources.
|
|
110
|
+
*/
|
|
111
|
+
totalUnsupportedItems?: number;
|
|
112
|
+
/** `totalUnsupportedItems` broken down by IFC type, sorted desc by count. */
|
|
113
|
+
unsupportedItemsByType?: Array<{
|
|
114
|
+
reason: string;
|
|
115
|
+
count: number;
|
|
116
|
+
}>;
|
|
78
117
|
}
|
|
79
118
|
/**
|
|
80
119
|
* Merge two GeometryDiagnostics (per-batch -> per-load, or per-worker ->
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../src/diagnostics.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,mBAAmB;IAClC
|
|
1
|
+
{"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../src/diagnostics.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;;;;;;;;;;;;OAeG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB,qFAAqF;IACrF,gBAAgB,EAAE,MAAM,CAAC;IACzB,8EAA8E;IAC9E,oBAAoB,EAAE,MAAM,CAAC;IAC7B,oEAAoE;IACpE,iBAAiB,EAAE,MAAM,CAAC;IAC1B,yCAAyC;IACzC,cAAc,EAAE;QACd,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,MAAM,CAAC;QACjB,cAAc,EAAE,MAAM,CAAC;QACvB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,mEAAmE;IACnE,gBAAgB,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3D;;;;;;OAMG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB,2DAA2D;IAC3D,QAAQ,EAAE;QACR,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,MAAM,CAAC;QACpB,eAAe,EAAE,MAAM,CAAC;QACxB,eAAe,EAAE,MAAM,CAAC;QACxB,YAAY,EAAE,MAAM,CAAC;QACrB,aAAa,EAAE,MAAM,CAAC;QACtB,eAAe,EAAE,MAAM,CAAC;QACxB,iFAAiF;QACjF,oBAAoB,CAAC,EAAE,MAAM,CAAC;KAC/B,CAAC;IACF;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,qEAAqE;IACrE,UAAU,EAAE,KAAK,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,WAAW,EAAE,MAAM,CAAC;QACpB,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B;6EACqE;QACrE,IAAI,CAAC,EAAE;YAAE,GAAG,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;YAAC,GAAG,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;SAAE,CAAC;QACxE;6DACqD;QACrD,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB,CAAC,CAAC;IACH;;;;;;;;;;;;;;;OAeG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,6EAA6E;IAC7E,sBAAsB,CAAC,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACnE;AA0BD;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,CAAC,EAAE,mBAAmB,GAAG,IAAI,GAAG,SAAS,EACzC,CAAC,EAAE,mBAAmB,GAAG,IAAI,GAAG,SAAS,GACxC,mBAAmB,GAAG,IAAI,CAgF5B;AAED,2EAA2E;AAC3E,MAAM,WAAW,6BAA6B;IAC5C,IAAI,EAAE,UAAU,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB;0EACsE;IACtE,WAAW,CAAC,EAAE,mBAAmB,CAAC;CACnC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kCAAkC,CAChD,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,mBAAmB,GAAG,IAAI,GACtC,6BAA6B,CAM/B"}
|
package/dist/diagnostics.js
CHANGED
|
@@ -3,6 +3,24 @@
|
|
|
3
3
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
4
|
/** Cap on the merged worst-hosts detail list (matches the Rust WORST_HOSTS_LIMIT). */
|
|
5
5
|
const WORST_HOSTS_LIMIT = 16;
|
|
6
|
+
/**
|
|
7
|
+
* Sum two reason-keyed lists by key, count-desc then reason-asc. The tie-break
|
|
8
|
+
* is load-bearing, not cosmetic: without it equal counts come out in Map
|
|
9
|
+
* insertion order, so the same model could render a different string on two
|
|
10
|
+
* runs. Shared by `failuresByReason` and `unsupportedItemsByType` so the two
|
|
11
|
+
* cannot order themselves differently. Agrees with the Rust `summarize` for the
|
|
12
|
+
* ASCII `Ifc*` type names and reason labels that actually reach here; the two
|
|
13
|
+
* are not identical orderings in general, since Rust ties break on byte order
|
|
14
|
+
* and `localeCompare` does not.
|
|
15
|
+
*/
|
|
16
|
+
function mergeReasonCounts(a, b) {
|
|
17
|
+
const byKey = new Map();
|
|
18
|
+
for (const r of [...a, ...b])
|
|
19
|
+
byKey.set(r.reason, (byKey.get(r.reason) ?? 0) + r.count);
|
|
20
|
+
return [...byKey.entries()]
|
|
21
|
+
.map(([reason, count]) => ({ reason, count }))
|
|
22
|
+
.sort((x, y) => y.count - x.count || x.reason.localeCompare(y.reason));
|
|
23
|
+
}
|
|
6
24
|
/**
|
|
7
25
|
* Merge two GeometryDiagnostics (per-batch -> per-load, or per-worker ->
|
|
8
26
|
* per-model). Scalars sum; classification + rectFast sum field-wise;
|
|
@@ -15,14 +33,7 @@ export function mergeGeometryDiagnostics(a, b) {
|
|
|
15
33
|
if (!b)
|
|
16
34
|
return a;
|
|
17
35
|
const schemaVersion = Math.max(a.schemaVersion ?? 0, b.schemaVersion ?? 0);
|
|
18
|
-
const
|
|
19
|
-
for (const r of a.failuresByReason)
|
|
20
|
-
reasons.set(r.reason, (reasons.get(r.reason) ?? 0) + r.count);
|
|
21
|
-
for (const r of b.failuresByReason)
|
|
22
|
-
reasons.set(r.reason, (reasons.get(r.reason) ?? 0) + r.count);
|
|
23
|
-
const failuresByReason = [...reasons.entries()]
|
|
24
|
-
.map(([reason, count]) => ({ reason, count }))
|
|
25
|
-
.sort((x, y) => y.count - x.count || x.reason.localeCompare(y.reason));
|
|
36
|
+
const failuresByReason = mergeReasonCounts(a.failuresByReason, b.failuresByReason);
|
|
26
37
|
// Fold by productId first (a host whose geometry spans batches/workers can
|
|
27
38
|
// appear in both operands' lists) before re-ranking and capping, mirroring the
|
|
28
39
|
// failuresByReason merge-by-key above. Copy each entry so the operands are not
|
|
@@ -47,6 +58,22 @@ export function mergeGeometryDiagnostics(a, b) {
|
|
|
47
58
|
const worstHosts = [...hostById.values()]
|
|
48
59
|
.sort((x, y) => y.csgFailures - x.csgFailures || x.productId - y.productId)
|
|
49
60
|
.slice(0, WORST_HOSTS_LIMIT);
|
|
61
|
+
// Whether EITHER operand actually carried the counter. Folding an absent field
|
|
62
|
+
// to 0 here would hand back `totalUnsupportedItems: 0` on a payload still
|
|
63
|
+
// labelled `schemaVersion: 2` — "we counted, and nothing was dropped" built out
|
|
64
|
+
// of "this producer never counted". That is the precise confusion the v3 bump
|
|
65
|
+
// exists to prevent, so absence has to survive the merge: the fields are
|
|
66
|
+
// omitted unless at least one side supplied one.
|
|
67
|
+
const countedUnsupported = a.totalUnsupportedItems !== undefined ||
|
|
68
|
+
b.totalUnsupportedItems !== undefined ||
|
|
69
|
+
a.unsupportedItemsByType !== undefined ||
|
|
70
|
+
b.unsupportedItemsByType !== undefined;
|
|
71
|
+
const unsupportedFields = countedUnsupported
|
|
72
|
+
? {
|
|
73
|
+
totalUnsupportedItems: (a.totalUnsupportedItems ?? 0) + (b.totalUnsupportedItems ?? 0),
|
|
74
|
+
unsupportedItemsByType: mergeReasonCounts(a.unsupportedItemsByType ?? [], b.unsupportedItemsByType ?? []),
|
|
75
|
+
}
|
|
76
|
+
: {};
|
|
50
77
|
return {
|
|
51
78
|
schemaVersion,
|
|
52
79
|
totalCsgFailures: a.totalCsgFailures + b.totalCsgFailures,
|
|
@@ -70,7 +97,9 @@ export function mergeGeometryDiagnostics(a, b) {
|
|
|
70
97
|
deferNoOpenings: a.rectFast.deferNoOpenings + b.rectFast.deferNoOpenings,
|
|
71
98
|
deferTooManyOpenings: (a.rectFast.deferTooManyOpenings ?? 0) + (b.rectFast.deferTooManyOpenings ?? 0),
|
|
72
99
|
},
|
|
100
|
+
oversizedRefDrops: (a.oversizedRefDrops ?? 0) + (b.oversizedRefDrops ?? 0),
|
|
73
101
|
worstHosts,
|
|
102
|
+
...unsupportedFields,
|
|
74
103
|
};
|
|
75
104
|
}
|
|
76
105
|
/**
|
package/dist/diagnostics.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diagnostics.js","sourceRoot":"","sources":["../src/diagnostics.ts"],"names":[],"mappings":"AAAA;;+DAE+D;
|
|
1
|
+
{"version":3,"file":"diagnostics.js","sourceRoot":"","sources":["../src/diagnostics.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HBJSON / DFJSON `IfcAPI` call sites for `IfcLiteBridge`, split out to keep
|
|
3
|
+
* `ifc-lite-bridge.ts` under the module-size ratchet (`scripts/check-module-size.mjs`).
|
|
4
|
+
* Pure functions over an already-initialized `IfcAPI` handle — no bridge state, so
|
|
5
|
+
* `IfcLiteBridge` just forwards into these through its existing `runExport` error
|
|
6
|
+
* wrapper (init guard + structured error logging + fatal-wasm-error marking stay
|
|
7
|
+
* there, not duplicated here).
|
|
8
|
+
*/
|
|
9
|
+
import type { IfcAPI } from '@ifc-lite/wasm';
|
|
10
|
+
import type { HbjsonStats } from './hbjson-stats.js';
|
|
11
|
+
/**
|
|
12
|
+
* Export the `IfcSpace` volumes in `content` as a Honeybee HBJSON string
|
|
13
|
+
* (Ladybug Tools energy/daylight model). Rooms are built analytically from
|
|
14
|
+
* extruded-area profiles (watertight by construction).
|
|
15
|
+
*/
|
|
16
|
+
export declare function callExportHbjson(api: IfcAPI, content: Uint8Array, name: string): Uint8Array;
|
|
17
|
+
/**
|
|
18
|
+
* Like {@link callExportHbjson}, but also returns the export's coverage stats
|
|
19
|
+
* (`HbjsonStats`: spaces seen, rooms emitted, spaces skipped as degenerate, plus
|
|
20
|
+
* apertures / doors / shades / constructions / interior adjacencies) so a caller
|
|
21
|
+
* can tell whether a "successful" export silently dropped `IfcSpace` volumes.
|
|
22
|
+
* Runs the export once — `content` and `stats` come from the same wasm call.
|
|
23
|
+
*/
|
|
24
|
+
export declare function callExportHbjsonWithStats(api: IfcAPI, content: Uint8Array, name: string): {
|
|
25
|
+
content: Uint8Array;
|
|
26
|
+
stats: HbjsonStats;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Export the `IfcSpace` volumes in `content` as a Dragonfly DFJSON string
|
|
30
|
+
* (Ladybug Tools energy model). Each space becomes an extruded `Room2D`
|
|
31
|
+
* (floor polygon + height) grouped into stories — the simpler target for
|
|
32
|
+
* mostly-vertical-wall models.
|
|
33
|
+
*/
|
|
34
|
+
export declare function callExportDfjson(api: IfcAPI, content: Uint8Array, name: string): string;
|
|
35
|
+
//# sourceMappingURL=energy-export-bridge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"energy-export-bridge.d.ts","sourceRoot":"","sources":["../src/energy-export-bridge.ts"],"names":[],"mappings":"AAIA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,CAE3F;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CACvC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,UAAU,EACnB,IAAI,EAAE,MAAM,GACX;IAAE,OAAO,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,WAAW,CAAA;CAAE,CAE7C;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAEvF"}
|
|
@@ -0,0 +1,31 @@
|
|
|
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
|
+
* Export the `IfcSpace` volumes in `content` as a Honeybee HBJSON string
|
|
6
|
+
* (Ladybug Tools energy/daylight model). Rooms are built analytically from
|
|
7
|
+
* extruded-area profiles (watertight by construction).
|
|
8
|
+
*/
|
|
9
|
+
export function callExportHbjson(api, content, name) {
|
|
10
|
+
return api.exportHbjson(content, name);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Like {@link callExportHbjson}, but also returns the export's coverage stats
|
|
14
|
+
* (`HbjsonStats`: spaces seen, rooms emitted, spaces skipped as degenerate, plus
|
|
15
|
+
* apertures / doors / shades / constructions / interior adjacencies) so a caller
|
|
16
|
+
* can tell whether a "successful" export silently dropped `IfcSpace` volumes.
|
|
17
|
+
* Runs the export once — `content` and `stats` come from the same wasm call.
|
|
18
|
+
*/
|
|
19
|
+
export function callExportHbjsonWithStats(api, content, name) {
|
|
20
|
+
return api.exportHbjsonWithStats(content, name);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Export the `IfcSpace` volumes in `content` as a Dragonfly DFJSON string
|
|
24
|
+
* (Ladybug Tools energy model). Each space becomes an extruded `Room2D`
|
|
25
|
+
* (floor polygon + height) grouped into stories — the simpler target for
|
|
26
|
+
* mostly-vertical-wall models.
|
|
27
|
+
*/
|
|
28
|
+
export function callExportDfjson(api, content, name) {
|
|
29
|
+
return api.exportDfjson(content, name);
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=energy-export-bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"energy-export-bridge.js","sourceRoot":"","sources":["../src/energy-export-bridge.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAc/D;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAW,EAAE,OAAmB,EAAE,IAAY;IAC7E,OAAO,GAAG,CAAC,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;AACzC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,yBAAyB,CACvC,GAAW,EACX,OAAmB,EACnB,IAAY;IAEZ,OAAO,GAAG,CAAC,qBAAqB,CAAC,OAAO,EAAE,IAAI,CAAgD,CAAC;AACjG,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAW,EAAE,OAAmB,EAAE,IAAY;IAC7E,OAAO,GAAG,CAAC,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;AACzC,CAAC"}
|
|
@@ -78,7 +78,8 @@ export interface ProcessParallelOptions {
|
|
|
78
78
|
* `scanEntitiesFastBytes` call (~10 s on 1 GB files under WASM
|
|
79
79
|
* contention with the geometry workers).
|
|
80
80
|
*/
|
|
81
|
-
onEntityIndex?: (ids: Uint32Array, starts: Uint32Array, lengths: Uint32Array
|
|
81
|
+
onEntityIndex?: (ids: Uint32Array, starts: Uint32Array, lengths: Uint32Array, oversizedIdCount?: number, // #3395 refused records
|
|
82
|
+
malformedRecordCount?: number) => void;
|
|
82
83
|
/**
|
|
83
84
|
* Issue #540 — "Merge Multilayer Walls" load-time toggle. When
|
|
84
85
|
* `true`, the geometry workers' IfcAPI receive
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"geometry-parallel.d.ts","sourceRoot":"","sources":["../src/geometry-parallel.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,KAAK,EAAY,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAChE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAGzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"geometry-parallel.d.ts","sourceRoot":"","sources":["../src/geometry-parallel.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,6 +9,7 @@ import { restashWasmPanicLocation } from './wasm-panic-forward.js';
|
|
|
9
9
|
// `IfcLiteBridge.init()` path can reuse whatever this pool already compiled
|
|
10
10
|
// (and vice versa) instead of fetching the same binary a second time.
|
|
11
11
|
import { compileSharedWasmModule } from './wasm-shared-module.js';
|
|
12
|
+
import { stitchShards } from './shard-stitch.js';
|
|
12
13
|
/**
|
|
13
14
|
* Prepass class-byte layout, mirroring the `PREPASS_CLASS_*` definitions in
|
|
14
15
|
* `rust/processing/src/shard_classes.rs` (the source of truth — these are
|
|
@@ -158,84 +159,6 @@ function terminateWorkerQuietly(worker, label) {
|
|
|
158
159
|
console.warn(`[stream] ${label} terminate failed:`, err);
|
|
159
160
|
}
|
|
160
161
|
}
|
|
161
|
-
/**
|
|
162
|
-
* SPIKE: stitch N speculative shard scans into the full entity index —
|
|
163
|
-
* byte-identical to the single-threaded scan. Port of the native
|
|
164
|
-
* `parallel_scan::stitch`: shard 0 is authoritative (header-aware start); for
|
|
165
|
-
* shard i>0 the previous shard's validated `handoff` is a real entity start, so
|
|
166
|
-
* binary-search shard i's `starts` for it and drop the speculative prefix before
|
|
167
|
-
* it. Concatenates the validated slices in shard order (= file order), so
|
|
168
|
-
* last-wins on a duplicate id is preserved when the worker rebuilds its map.
|
|
169
|
-
*
|
|
170
|
-
* Returns null on the rare "handoff not found" case (speculative overshoot / a
|
|
171
|
-
* record spanning a whole shard), which needs the serial-rescan fallback the JS
|
|
172
|
-
* spike doesn't implement — the caller falls back to the pre-pass's own index.
|
|
173
|
-
*/
|
|
174
|
-
function stitchShards(shards) {
|
|
175
|
-
const n = shards.length;
|
|
176
|
-
// Phase 1 — locate each shard's validated slice (binary-search the previous
|
|
177
|
-
// shard's handoff) WITHOUT copying, so the output size is exact before any
|
|
178
|
-
// allocation. Exactness matters: the id/start/length columns are allocated
|
|
179
|
-
// SAB-backed below and handed to every worker as full-buffer views, so a
|
|
180
|
-
// cap-sized buffer would let consumers read past the last real record.
|
|
181
|
-
const sliceFrom = new Array(n).fill(0);
|
|
182
|
-
let used = 1;
|
|
183
|
-
let w = shards[0].ids.length; // shard 0 is authoritative, take every record
|
|
184
|
-
let expectedStart = shards[0].handoff; // -1 => no more real entities
|
|
185
|
-
for (let i = 1; i < n; i++) {
|
|
186
|
-
if (expectedStart < 0)
|
|
187
|
-
break;
|
|
188
|
-
// starts is strictly increasing → binary-search for expectedStart.
|
|
189
|
-
const starts = shards[i].starts;
|
|
190
|
-
let lo = 0;
|
|
191
|
-
let hi = starts.length - 1;
|
|
192
|
-
let p = -1;
|
|
193
|
-
while (lo <= hi) {
|
|
194
|
-
const mid = (lo + hi) >>> 1;
|
|
195
|
-
const v = starts[mid];
|
|
196
|
-
if (v === expectedStart) {
|
|
197
|
-
p = mid;
|
|
198
|
-
break;
|
|
199
|
-
}
|
|
200
|
-
if (v < expectedStart)
|
|
201
|
-
lo = mid + 1;
|
|
202
|
-
else
|
|
203
|
-
hi = mid - 1;
|
|
204
|
-
}
|
|
205
|
-
if (p < 0) {
|
|
206
|
-
// Handoff not present in this shard — fallback path (not implemented here).
|
|
207
|
-
return null;
|
|
208
|
-
}
|
|
209
|
-
sliceFrom[i] = p;
|
|
210
|
-
w += starts.length - p;
|
|
211
|
-
expectedStart = shards[i].handoff;
|
|
212
|
-
used = i + 1;
|
|
213
|
-
}
|
|
214
|
-
// Phase 2 — single concatenation copy, straight into SharedArrayBuffer-backed
|
|
215
|
-
// columns. The stitched index used to be copied THREE times per column on the
|
|
216
|
-
// main thread (cap-array stitch → `.slice()` to contiguous → `.set()` into
|
|
217
|
-
// fresh SABs in deliverEntityIndex); writing the stitch output into SABs
|
|
218
|
-
// directly makes index delivery zero-copy (~450 MB of critical-path memcpy
|
|
219
|
-
// saved on a 19M-entity file). `classes` stays plain: its only consumer past
|
|
220
|
-
// the span-extraction loop is the pre-pass worker, which takes it by transfer.
|
|
221
|
-
const sabAvailable = typeof SharedArrayBuffer !== 'undefined';
|
|
222
|
-
const u32Column = (len) => new Uint32Array(sabAvailable ? new SharedArrayBuffer(len * 4) : new ArrayBuffer(len * 4));
|
|
223
|
-
const outIds = u32Column(w);
|
|
224
|
-
const outStarts = u32Column(w);
|
|
225
|
-
const outLengths = u32Column(w);
|
|
226
|
-
const outClasses = new Uint8Array(w);
|
|
227
|
-
let o = 0;
|
|
228
|
-
for (let i = 0; i < used; i++) {
|
|
229
|
-
const s = shards[i];
|
|
230
|
-
const p = sliceFrom[i];
|
|
231
|
-
outIds.set(p === 0 ? s.ids : s.ids.subarray(p), o);
|
|
232
|
-
outStarts.set(p === 0 ? s.starts : s.starts.subarray(p), o);
|
|
233
|
-
outLengths.set(p === 0 ? s.lengths : s.lengths.subarray(p), o);
|
|
234
|
-
outClasses.set(p === 0 ? s.classes : s.classes.subarray(p), o);
|
|
235
|
-
o += s.ids.length - p;
|
|
236
|
-
}
|
|
237
|
-
return { ids: outIds, starts: outStarts, lengths: outLengths, classes: outClasses };
|
|
238
|
-
}
|
|
239
162
|
export async function* processParallel(buffer, coordinator, sharedRtcOffset,
|
|
240
163
|
/** Optional pre-allocated SAB the caller already shares with another worker. */
|
|
241
164
|
existingSab, options) {
|
|
@@ -367,6 +290,11 @@ existingSab, options) {
|
|
|
367
290
|
lengths: msg.lengths,
|
|
368
291
|
classes: msg.classes,
|
|
369
292
|
handoff: msg.handoff,
|
|
293
|
+
// Absent on an older wasm build: "does not report", which is not the
|
|
294
|
+
// same claim as zero, but zero is all a host with no offsets can say.
|
|
295
|
+
oversizedIdStarts: msg.oversizedIdStarts ?? new Uint32Array(0),
|
|
296
|
+
// Absent = "no stop reported". TODO(#3699): no wasm build sets it yet.
|
|
297
|
+
malformedStart: msg.malformedStart,
|
|
370
298
|
};
|
|
371
299
|
shardResultsRemaining--;
|
|
372
300
|
console.log(`[stream][shard] worker[${workerIndex}] shard ${si} done @ ${elapsed()}ms (${msg.ids.length} entities, remaining=${shardResultsRemaining})`);
|
|
@@ -810,7 +738,14 @@ existingSab, options) {
|
|
|
810
738
|
* gate and drain. Shared by the pre-pass path and the SPIKE sharded-early
|
|
811
739
|
* path so both distribute the index identically.
|
|
812
740
|
*/
|
|
813
|
-
const deliverEntityIndex = (ids, starts, lengths, source
|
|
741
|
+
const deliverEntityIndex = (ids, starts, lengths, source,
|
|
742
|
+
// #3395: the parser worker builds the model from these columns alone, so
|
|
743
|
+
// without the count it reports a clean load that is short by that many.
|
|
744
|
+
oversizedIdCount,
|
|
745
|
+
// #3790: 1, or undefined when nothing reported (never coerced to 0 -- no
|
|
746
|
+
// producer can say "I ran clean" yet). Worse than a refusal: not "one
|
|
747
|
+
// record the parser will not find" but "every record after it is missing".
|
|
748
|
+
malformedRecordCount) => {
|
|
814
749
|
console.log(`[stream] entity-index (${source}) @ ${elapsed()}ms (${ids.length} entries)`);
|
|
815
750
|
if (typeof SharedArrayBuffer !== 'undefined') {
|
|
816
751
|
// Sharded-stitch columns arrive already SAB-backed (stitchShards writes
|
|
@@ -850,7 +785,7 @@ existingSab, options) {
|
|
|
850
785
|
}
|
|
851
786
|
if (options?.onEntityIndex) {
|
|
852
787
|
try {
|
|
853
|
-
options.onEntityIndex(new Uint32Array(sabIds), new Uint32Array(sabStarts), new Uint32Array(sabLengths));
|
|
788
|
+
options.onEntityIndex(new Uint32Array(sabIds), new Uint32Array(sabStarts), new Uint32Array(sabLengths), oversizedIdCount, malformedRecordCount);
|
|
854
789
|
}
|
|
855
790
|
catch (err) {
|
|
856
791
|
console.warn('[stream] onEntityIndex callback failed:', err);
|
|
@@ -871,7 +806,7 @@ existingSab, options) {
|
|
|
871
806
|
}
|
|
872
807
|
if (options?.onEntityIndex) {
|
|
873
808
|
try {
|
|
874
|
-
options.onEntityIndex(ids.slice(), starts.slice(), lengths.slice());
|
|
809
|
+
options.onEntityIndex(ids.slice(), starts.slice(), lengths.slice(), oversizedIdCount, malformedRecordCount);
|
|
875
810
|
}
|
|
876
811
|
catch (err) {
|
|
877
812
|
console.warn('[stream] onEntityIndex callback failed:', err);
|
|
@@ -904,9 +839,16 @@ existingSab, options) {
|
|
|
904
839
|
const starts = stitched.starts;
|
|
905
840
|
const lengths = stitched.lengths;
|
|
906
841
|
entityIndexDeliveredEarly = true;
|
|
842
|
+
// The stitch's attributed count, NOT the per-shard sum. Summing reports
|
|
843
|
+
// refusals a discarded speculative prefix invented, which on a file with
|
|
844
|
+
// nothing oversized in it is a warning about a file that is fine (#3430).
|
|
845
|
+
const oversizedIdCount = stitched.oversizedIdCount;
|
|
846
|
+
// Attributed by the stitch for the same reason (#3790): a shard that began
|
|
847
|
+
// inside a quoted value reports a stop the file does not contain.
|
|
848
|
+
const malformedRecordCount = stitched.malformedRecordCount;
|
|
907
849
|
// set-entity-index reaches every worker FIRST (FIFO), so the style-shard
|
|
908
850
|
// messages below always find the index installed.
|
|
909
|
-
deliverEntityIndex(ids, starts, lengths, 'sharded');
|
|
851
|
+
deliverEntityIndex(ids, starts, lengths, 'sharded', oversizedIdCount, malformedRecordCount);
|
|
910
852
|
// Extract the styled-item span triples (class 4) in FILE ORDER from the
|
|
911
853
|
// stitched columns, split into one contiguous slice per worker, and
|
|
912
854
|
// resolve them in parallel while everyone waits on the pre-pass scan.
|
|
@@ -1185,7 +1127,9 @@ existingSab, options) {
|
|
|
1185
1127
|
console.log(`[stream] pre-pass entity-index arrived @ ${elapsed()}ms (already delivered via shards; ignoring)`);
|
|
1186
1128
|
}
|
|
1187
1129
|
else {
|
|
1188
|
-
|
|
1130
|
+
// TODO(#3699): the Rust pre-pass emits no malformed count yet, so
|
|
1131
|
+
// this is undefined ("nothing reported"), carried as such.
|
|
1132
|
+
deliverEntityIndex(ids, starts, lengths, 'prepass', evt.oversizedIdCount ?? 0, evt.malformedRecordCount);
|
|
1189
1133
|
}
|
|
1190
1134
|
}
|
|
1191
1135
|
else if (evt.type === 'prepass-columns') {
|
|
@@ -1442,8 +1386,8 @@ existingSab, options) {
|
|
|
1442
1386
|
const loadDiagnostics = diagnostics;
|
|
1443
1387
|
if (loadDiagnostics && loadDiagnostics.totalCsgFailures > 0) {
|
|
1444
1388
|
console.warn(`[ifc-lite] ${loadDiagnostics.totalCsgFailures} CSG failure(s) across ` +
|
|
1445
|
-
`${loadDiagnostics.productsWithFailures} product(s) this load -
|
|
1446
|
-
`
|
|
1389
|
+
`${loadDiagnostics.productsWithFailures} product(s) this load - see ` +
|
|
1390
|
+
`diagnostics.failuresByReason; not every reason leaves an opening/void uncut`);
|
|
1447
1391
|
}
|
|
1448
1392
|
yield {
|
|
1449
1393
|
type: 'complete',
|