@bldrs-ai/conway 1.511.1441 → 1.513.1447
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/compiled/examples/browser-bundled.cjs +82 -16
- package/compiled/examples/cli-bundled.cjs +98 -23
- package/compiled/examples/cli-step-bundled.cjs +82 -16
- package/compiled/examples/validator-bundled.cjs +82 -16
- package/compiled/src/compat/web-ifc/ifc_api_proxy_ifc.d.ts +3 -2
- package/compiled/src/compat/web-ifc/ifc_api_proxy_ifc.d.ts.map +1 -1
- package/compiled/src/compat/web-ifc/ifc_api_proxy_ifc.js +69 -25
- package/compiled/src/compat/web-ifc/parse_aabb_imposter.d.ts +41 -0
- package/compiled/src/compat/web-ifc/parse_aabb_imposter.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/parse_aabb_imposter.js +161 -0
- package/compiled/src/compat/web-ifc/parse_aabb_imposter.test.d.ts +2 -0
- package/compiled/src/compat/web-ifc/parse_aabb_imposter.test.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/parse_aabb_imposter.test.js +39 -0
- package/compiled/src/compat/web-ifc/streamed_preview_channel.d.ts +13 -0
- package/compiled/src/compat/web-ifc/streamed_preview_channel.d.ts.map +1 -1
- package/compiled/src/core/progress.d.ts +8 -1
- package/compiled/src/core/progress.d.ts.map +1 -1
- package/compiled/src/core/progress.js +9 -4
- package/compiled/src/core/progress_log.d.ts +1 -0
- package/compiled/src/core/progress_log.d.ts.map +1 -1
- package/compiled/src/core/progress_log.js +7 -2
- package/compiled/src/core/progress_log.test.js +21 -0
- package/compiled/src/ifc/ifc_stream_open.test.js +60 -0
- package/compiled/src/step/parsing/step_parser.d.ts +2 -2
- package/compiled/src/step/parsing/step_parser.d.ts.map +1 -1
- package/compiled/src/step/parsing/step_parser.js +8 -2
- package/compiled/src/step/parsing/streaming_index_builder.d.ts +4 -4
- package/compiled/src/step/parsing/streaming_index_builder.d.ts.map +1 -1
- package/compiled/src/step/step_buffer_provider.d.ts +4 -3
- package/compiled/src/step/step_buffer_provider.d.ts.map +1 -1
- package/compiled/src/step/step_buffer_provider.js +4 -3
- package/compiled/src/step/step_entity_base.d.ts.map +1 -1
- package/compiled/src/step/step_entity_base.js +9 -0
- package/compiled/src/step/step_model_base.d.ts +9 -0
- package/compiled/src/step/step_model_base.d.ts.map +1 -1
- package/compiled/src/step/step_model_base.js +72 -13
- package/compiled/src/version/version.js +1 -1
- package/compiled/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -944,7 +944,7 @@ var EntityTypesIfcCount = 909;
|
|
|
944
944
|
var entity_types_ifc_gen_default = EntityTypesIfc;
|
|
945
945
|
|
|
946
946
|
// compiled/src/version/version.js
|
|
947
|
-
var versionString = "Conway v1.
|
|
947
|
+
var versionString = "Conway v1.513.1447";
|
|
948
948
|
|
|
949
949
|
// compiled/dependencies/conway-geom/interface/conway_geometry.js
|
|
950
950
|
var wasmType = "";
|
|
@@ -3824,7 +3824,10 @@ var StepParser = class extends StepHeaderParser {
|
|
|
3824
3824
|
if (!charws(SEMICOLON)) {
|
|
3825
3825
|
return syntaxError();
|
|
3826
3826
|
}
|
|
3827
|
-
|
|
3827
|
+
{
|
|
3828
|
+
const recordLen = input.address - startElement2;
|
|
3829
|
+
onRecordIndexed?.(topLevelCount, expressID, 0, input.buffer.subarray(input.cursor - recordLen, input.cursor));
|
|
3830
|
+
}
|
|
3828
3831
|
++topLevelCount;
|
|
3829
3832
|
pushEntry({
|
|
3830
3833
|
address: startElement2,
|
|
@@ -3914,7 +3917,10 @@ var StepParser = class extends StepHeaderParser {
|
|
|
3914
3917
|
if (!charws(SEMICOLON)) {
|
|
3915
3918
|
return syntaxError();
|
|
3916
3919
|
}
|
|
3917
|
-
|
|
3920
|
+
{
|
|
3921
|
+
const recordLen = input.address - startElement;
|
|
3922
|
+
onRecordIndexed?.(topLevelCount, expressID, foundItem, input.buffer.subarray(input.cursor - recordLen, input.cursor));
|
|
3923
|
+
}
|
|
3918
3924
|
++topLevelCount;
|
|
3919
3925
|
pushEntry({
|
|
3920
3926
|
address: startElement,
|
|
@@ -5530,6 +5536,9 @@ var StepModelBase = class {
|
|
|
5530
5536
|
if (element.vtableIndex === void 0 && !this.populateVtableEntryRaw(element)) {
|
|
5531
5537
|
return void 0;
|
|
5532
5538
|
}
|
|
5539
|
+
if (element.buffer === void 0) {
|
|
5540
|
+
this.populateBufferEntry(localID);
|
|
5541
|
+
}
|
|
5533
5542
|
const vtable = element.vtable;
|
|
5534
5543
|
const buffer = element.buffer;
|
|
5535
5544
|
if (vtable === void 0 || buffer === void 0 || offset >= (element.vtableCount ?? 0)) {
|
|
@@ -5599,6 +5608,11 @@ var StepModelBase = class {
|
|
|
5599
5608
|
}
|
|
5600
5609
|
const element = this.entry(localID);
|
|
5601
5610
|
element.buffer = this.bufferProvider_.acquire(element.address, element.length).buffer;
|
|
5611
|
+
if (element.multiMapping !== void 0) {
|
|
5612
|
+
for (const mapped of element.multiMapping) {
|
|
5613
|
+
mapped.buffer = this.bufferProvider_.acquire(mapped.address, mapped.length).buffer;
|
|
5614
|
+
}
|
|
5615
|
+
}
|
|
5602
5616
|
}
|
|
5603
5617
|
/**
|
|
5604
5618
|
* Get the size in bytes of the backing buffer for this.
|
|
@@ -5719,24 +5733,39 @@ var StepModelBase = class {
|
|
|
5719
5733
|
if (!this.isSourceExternal) {
|
|
5720
5734
|
return seen;
|
|
5721
5735
|
}
|
|
5722
|
-
const
|
|
5736
|
+
const frontier = [];
|
|
5737
|
+
const enqueue = (id) => {
|
|
5738
|
+
if (id < this.count_ && !seen.has(id)) {
|
|
5739
|
+
frontier.push(id);
|
|
5740
|
+
}
|
|
5741
|
+
};
|
|
5742
|
+
enqueue(localID);
|
|
5723
5743
|
if (extraLocalIDs !== void 0) {
|
|
5724
5744
|
for (const extra of extraLocalIDs) {
|
|
5725
|
-
|
|
5745
|
+
enqueue(extra);
|
|
5726
5746
|
}
|
|
5727
5747
|
}
|
|
5728
|
-
while (
|
|
5729
|
-
const
|
|
5730
|
-
|
|
5731
|
-
|
|
5748
|
+
while (frontier.length > 0) {
|
|
5749
|
+
const wave = [];
|
|
5750
|
+
for (const id of frontier) {
|
|
5751
|
+
if (seen.has(id) || id >= this.count_) {
|
|
5752
|
+
continue;
|
|
5753
|
+
}
|
|
5754
|
+
seen.add(id);
|
|
5755
|
+
this.pinByLocalID(id);
|
|
5756
|
+
wave.push(id);
|
|
5757
|
+
}
|
|
5758
|
+
frontier.length = 0;
|
|
5759
|
+
if (wave.length === 0) {
|
|
5760
|
+
break;
|
|
5732
5761
|
}
|
|
5733
|
-
|
|
5734
|
-
|
|
5735
|
-
|
|
5736
|
-
|
|
5737
|
-
|
|
5738
|
-
|
|
5739
|
-
|
|
5762
|
+
await Promise.all(wave.map((id) => this.ensureResidentByLocalID(id)));
|
|
5763
|
+
for (const id of wave) {
|
|
5764
|
+
for (const expressID of this.scanRecordRefs_(id)) {
|
|
5765
|
+
const referenced = this.expressIDMap_.get(expressID);
|
|
5766
|
+
if (referenced !== void 0 && !seen.has(referenced)) {
|
|
5767
|
+
frontier.push(referenced);
|
|
5768
|
+
}
|
|
5740
5769
|
}
|
|
5741
5770
|
}
|
|
5742
5771
|
}
|
|
@@ -5765,6 +5794,35 @@ var StepModelBase = class {
|
|
|
5765
5794
|
}
|
|
5766
5795
|
this.bufferProvider_.unpinRange?.(this.address_[localID], this.length_[localID]);
|
|
5767
5796
|
}
|
|
5797
|
+
/**
|
|
5798
|
+
* Drop captured source-window views on `localIDs` so the LRU can
|
|
5799
|
+
* evict those chunks. Vtables stay — `acquire` of the same
|
|
5800
|
+
* `(address, length)` is at a stable base. The next
|
|
5801
|
+
* `ensureResident` + field read rematerialises the view.
|
|
5802
|
+
*
|
|
5803
|
+
* @param localIDs Records whose `buffer` views to drop.
|
|
5804
|
+
*/
|
|
5805
|
+
releaseSourceViews(localIDs) {
|
|
5806
|
+
if (!this.isSourceExternal) {
|
|
5807
|
+
return;
|
|
5808
|
+
}
|
|
5809
|
+
for (const localID of localIDs) {
|
|
5810
|
+
if (localID >= this.count_) {
|
|
5811
|
+
continue;
|
|
5812
|
+
}
|
|
5813
|
+
const item = this.complexEntries_?.get(localID) ?? this.descriptorCache_[localID];
|
|
5814
|
+
if (item === void 0) {
|
|
5815
|
+
continue;
|
|
5816
|
+
}
|
|
5817
|
+
item.buffer = void 0;
|
|
5818
|
+
if (item.multiMapping !== void 0) {
|
|
5819
|
+
for (const mapped of item.multiMapping) {
|
|
5820
|
+
mapped.buffer = void 0;
|
|
5821
|
+
}
|
|
5822
|
+
}
|
|
5823
|
+
}
|
|
5824
|
+
releaseScratchParsingBuffer();
|
|
5825
|
+
}
|
|
5768
5826
|
/**
|
|
5769
5827
|
* Unpin every local ID in `localIDs` (best-effort; missing IDs are
|
|
5770
5828
|
* ignored). Use after {@link ensureResidentClosureByLocalID}, which
|
|
@@ -11228,6 +11286,7 @@ var StepEntityBase = class {
|
|
|
11228
11286
|
*/
|
|
11229
11287
|
extractParseBuffer(offset, baseOffset, depth, result, module2, optional) {
|
|
11230
11288
|
offset -= this.multiReference_ !== void 0 ? baseOffset : 0;
|
|
11289
|
+
this.guaranteeBuffer();
|
|
11231
11290
|
const internalReference = this.guaranteeVTable(depth);
|
|
11232
11291
|
if (offset >= internalReference.vtableCount) {
|
|
11233
11292
|
throw new Error("Couldn't read field due to too few fields in record");
|
|
@@ -11340,6 +11399,7 @@ var StepEntityBase = class {
|
|
|
11340
11399
|
* @return {Uint8Array} The buffer for this.
|
|
11341
11400
|
*/
|
|
11342
11401
|
get buffer() {
|
|
11402
|
+
this.guaranteeBuffer();
|
|
11343
11403
|
return this.internalReference_.buffer;
|
|
11344
11404
|
}
|
|
11345
11405
|
/**
|
|
@@ -11430,6 +11490,9 @@ var StepEntityBase = class {
|
|
|
11430
11490
|
throw new Error("Entity does not have matching table entry to read from model");
|
|
11431
11491
|
}
|
|
11432
11492
|
}
|
|
11493
|
+
if (classReference.buffer === void 0) {
|
|
11494
|
+
this.model.populateBufferEntry(this.localID);
|
|
11495
|
+
}
|
|
11433
11496
|
this.internalReference_.buffer = classReference.buffer;
|
|
11434
11497
|
return classReference;
|
|
11435
11498
|
}
|
|
@@ -11440,6 +11503,9 @@ var StepEntityBase = class {
|
|
|
11440
11503
|
throw new Error("Entity does not have matching table entry to read from model");
|
|
11441
11504
|
}
|
|
11442
11505
|
}
|
|
11506
|
+
if (internalReference.buffer === void 0) {
|
|
11507
|
+
this.guaranteeBuffer();
|
|
11508
|
+
}
|
|
11443
11509
|
return internalReference;
|
|
11444
11510
|
}
|
|
11445
11511
|
/**
|
|
@@ -253,8 +253,9 @@ export declare class IfcApiProxyIfc implements IfcApiModelPassthrough {
|
|
|
253
253
|
/**
|
|
254
254
|
* Windowed-from-birth twin of parseColumnarAndExtractAsync: the
|
|
255
255
|
* source stays in `store`, parse windows are filled through it, and
|
|
256
|
-
* the model never holds a resident copy.
|
|
257
|
-
* skipped (
|
|
256
|
+
* the model never holds a resident copy. The full prefix-extract
|
|
257
|
+
* preview channel is skipped (it needs a resident prefix); a sparse
|
|
258
|
+
* AABB imposter rides onRecordIndexed instead. Deferred opens
|
|
258
259
|
* page prep closures before prepareDemandExtraction; non-deferred
|
|
259
260
|
* opens drain the demand pump with per-product residency.
|
|
260
261
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ifc_api_proxy_ifc.d.ts","sourceRoot":"","sources":["../../../../src/compat/web-ifc/ifc_api_proxy_ifc.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,cAAc,EACf,MAAM,aAAa,CAAA;AAEpB,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAA;AAC7D,OAAO,YAAY,MAAM,0BAA0B,CAAA;AACnD,OAAO,EACL,QAAQ,EACR,WAAW,EACX,WAAW,EACX,cAAc,EACd,cAAc,EACd,WAAW,EACX,MAAM,EACP,MAAM,WAAW,CAAA;AAClB,OAAO,EAAE,qBAAqB,EAA8B,MAAM,iCAAiC,CAAA;AACnG,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAA;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAC1D,OAAO,KAAK,QAAQ,MAAM,WAAW,CAAA;AAGrC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAEhD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"ifc_api_proxy_ifc.d.ts","sourceRoot":"","sources":["../../../../src/compat/web-ifc/ifc_api_proxy_ifc.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,cAAc,EACf,MAAM,aAAa,CAAA;AAEpB,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAA;AAC7D,OAAO,YAAY,MAAM,0BAA0B,CAAA;AACnD,OAAO,EACL,QAAQ,EACR,WAAW,EACX,WAAW,EACX,cAAc,EACd,cAAc,EACd,WAAW,EACX,MAAM,EACP,MAAM,WAAW,CAAA;AAClB,OAAO,EAAE,qBAAqB,EAA8B,MAAM,iCAAiC,CAAA;AACnG,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAA;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAC1D,OAAO,KAAK,QAAQ,MAAM,WAAW,CAAA;AAGrC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAEhD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAiBrD,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAA;AAE3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAA;AA2BzE;;;;;GAKG;AACH,UAAU,iBAAiB;IACzB,UAAU,EAAE,cAAc,CAAA;IAC1B,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;uEACmE;IACnE,yBAAyB,CAAC,EAAE,MAAM,EAAE,CAAA;IACpC,YAAY,EAAE,MAAM,CAAA;IACpB,UAAU,EAAE,UAAU,CAAA;IACtB,KAAK,EAAE,YAAY,CAAA;IACnB,KAAK,EAAE,eAAe,CAAA;IACtB,cAAc,EAAE,qBAAqB,CAAA;IACrC,gBAAgB,EAAE,MAAM,CAAA;IACxB,wEAAwE;IACxE,OAAO,CAAC,EAAE,eAAe,CAAA;CAC1B;AAED;;GAEG;AACH,qBAAa,cAAe,YAAW,sBAAsB;aA2GvC,OAAO,EAAE,MAAM;IAE/B,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC;IA5G9B,EAAE,CAAC,EAAE,GAAG,CAAY;IAEpB,KAAK,EACH;QAAC,YAAY;QACX,eAAe;QACf,GAAG,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,QAAQ,CAAC,CAAC;QAC/C,GAAG,CAAC,MAAM,EAAE,CAAC,cAAc,EAAE,iBAAiB,EAAE,MAAM,EAAE,CAAC,CAAC;QAE1D,MAAM,CAAC,QAAQ,CAAC;QAAE,QAAQ,CAAC,IAAI;KAAC,CAAA;IACpC,UAAU,EAAE,cAAc,CAAA;IAE1B,yEAAyE;IACzE,OAAO,CAAC,eAAe,CAAuB;IAE9C,iEAAiE;IACjE,OAAO,CAAC,aAAa,CAAiB;IAEtC,4EAA4E;IAC5E,OAAO,CAAC,gBAAgB,CAAC,CAAiB;IAE1C,yEAAyE;IACzE,OAAO,CAAC,qBAAqB,CAAiB;IAE9C,sEAAsE;IACtE,OAAO,CAAC,eAAe,CAAC,CAAU;IAElC;;;;;;;OAOG;IACH,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAA4B;IAElE,sEAAsE;IACtE,OAAO,CAAC,aAAa,CAAI;IAEzB;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,iBAAiB,CAAC,CAAoB;IAE9C,qEAAqE;IACrE,OAAO,CAAC,uBAAuB,CAAI;IAEnC;;;;;;;;;OASG;IACH,OAAO,CAAC,mBAAmB,CAAC,CAAU;IAEtC;;;;;;;;;;OAUG;IACH,OAAO,CAAC,8BAA8B,CAAiB;IAEvD,cAAc,EAAE,OAAO,CAAQ;IAC/B,mBAAmB,EAAE,MAAM,CAAI;IAC/B,QAAQ,EAAE,MAAM,EAAE,CAAmD;IAGrE,YAAY,EAAE,QAAQ,CAAC,IAAI,CAK1B;IAED;;OAEG;IACH,UAAU,gBAA0B;IAEpC;;;;OAIG;gBAGiB,OAAO,EAAE,MAAM,EAC/B,IAAI,EAAE,UAAU,EACC,UAAU,EAAE,GAAG,EACf,QAAQ,CAAC,EAAE,cAAc,YAAA,EAC1C,WAAW,CAAC,EAAE,iBAAiB;IAuKnC;;;;;;;;;;OAUG;WACiB,WAAW,CAC3B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,UAAU,EAChB,UAAU,EAAE,GAAG,EACf,QAAQ,CAAC,EAAE,cAAc,GAAI,OAAO,CAAC,cAAc,CAAC;IAQxD;;;;;;;;;;;;;;;OAeG;WACiB,cAAc,CAC9B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,UAAU,EAChB,UAAU,EAAE,GAAG,EACf,QAAQ,CAAC,EAAE,cAAc,GAAI,OAAO,CAAC,cAAc,CAAC;IAQxD;;;;;;;;;;;;;;;OAeG;WACiB,cAAc,CAC9B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,UAAU,EAChB,UAAU,EAAE,GAAG,EACf,QAAQ,CAAC,EAAE,cAAc,GAAI,OAAO,CAAC,cAAc,CAAC;IAQxD;;;;;;;;;;;OAWG;WACiB,eAAe,CAC/B,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,qBAAqB,EAC5B,UAAU,EAAE,GAAG,EACf,QAAQ,CAAC,EAAE,cAAc,GAAI,OAAO,CAAC,cAAc,CAAC;IASxD;;;;;;OAMG;IACH,OAAO,CAAC,MAAM,CAAC,uBAAuB;IAwCtC;;;;;;OAMG;IACH,OAAO,CAAC,MAAM,CAAC,WAAW;IAU1B;;;;;;;;OAQG;IACH,OAAO,CAAC,MAAM,CAAC,eAAe;IAsF9B;;;;;;;;;OASG;mBACkB,oBAAoB;IAsFzC;;;;;;;;;;;;;;;;;;;;;;OAsBG;mBACkB,4BAA4B;IAyJjD;;;;;;;;;;;;;;;OAeG;mBACkB,sBAAsB;IAkM3C;;;;OAIG;IACH,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IA4BxC;;;;;OAKG;IACH,WAAW,CAAC,QAAQ,CAAC,EAAE,cAAc,GAAG,MAAM;IAM9C;;;;OAIG;IACH,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU;IAO5C;;;;;;OAMG;IACH,WAAW,CAAC,iBAAiB,EAAE,MAAM,GAAG,WAAW;IA8BnD;;;;;;OAMG;IACH,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,OAAe;IA0BnD;;;;;;;;;;;;OAYG;IACH,qBAAqB,CAAC,SAAS,EAAE,MAAM,GACrC;QAAE,IAAI,CAAC,EAAE,eAAe,CAAC;QACvB,QAAQ,CAAC,EAAE,eAAe,CAAC;QAC3B,QAAQ,CAAC,EAAE,eAAe,CAAA;KAAE;IAoChC;;;;;;OAMG;IACH,kBAAkB,IAAI,IAAI;IAI1B;;;;;OAKG;IACH,IAAI,gBAAgB,IAAI,OAAO,CAE9B;IAED;;;;;;;;;;OAUG;IACH,0BAA0B,CACtB,KAAK,EAAE,qBAAqB,EAC5B,UAAU,CAAC,EAAE,MAAM,EACnB,iBAAiB,CAAC,EAAE,MAAM,GAAI,IAAI;IAItC;;;;;;;;;;;OAWG;IACG,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI1D;;;;;;;;;;;OAWG;IACH,cAAc,IAAI,gBAAgB,CAAC,MAAM,CAAC;IAI1C;;;;OAIG;IACH,iBAAiB,IAAI,MAAM,CAAC,WAAW,CAAC;IAoBxC;;;;OAIG;IACH,SAAS,CAAC,UAAU,EAAE,GAAG;IAIzB;;;;OAIG;IACH,WAAW,CAAC,IAAI,EAAE,GAAG,GAAG,IAAI;IAkB5B;;;;;OAKG;IACH,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,WAAW;IAgD9C;;;;OAIG;IACH,gBAAgB,CAAC,IAAI,EAAE,WAAW;IAIlC;;;;;OAKG;IACH,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IA6ChD;;;;OAIG;IACH,WAAW,IAAI,MAAM,CAAC,MAAM,CAAC;IA0C7B;;;;OAIG;IACH,yBAAyB,CAAC,oBAAoB,EAAE,KAAK,CAAC,MAAM,CAAC;IAU7D;;;;OAIG;IACH,qBAAqB,IAAI,KAAK,CAAC,MAAM,CAAC;IAetC;;;;;;OAMG;IACH,sBAAsB,IAAI,KAAK,CAAC,MAAM,CAAC;IAIvC;;;;;OAKG;IACH,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,YAAY;IAIvD;;;;;OAKG;IACH,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW;IAIrD;;;;;;OAMG;IACH,WAAW,CAAC,IAAI,EAAE,YAAY,GAAG,WAAW,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAC/E,YAAY,GAAG,WAAW;IAK5B;;;;OAIG;IACH,UAAU;IAIV;;;;;;;;;;;;;OAaG;IACH,eAAe,IAAI,OAAO;IAoC1B;0EACsE;IACtE,OAAO,CAAC,SAAS,CAAQ;IAEzB;;;;;;;;;;;;;;;;;OAiBG;IACH,oBAAoB,CAChB,SAAS,EAAE,MAAM,EACjB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,GAAI;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAC;IAmBrF;;;;;;;;;OASG;IACG,yBAAyB,CAC3B,SAAS,EAAE,MAAM,EACjB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,GACvC,OAAO,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAC,CAAC;IA4GnD;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IAsC9B;;;;;;;OAOG;IACH,OAAO,CAAC,kBAAkB;IAwE1B;;;;;;;;;;;;;;;;;;;OAmBG;IACH,OAAO,CAAC,gBAAgB;IAmLxB;;;;OAIG;IACH,eAAe,CAAE,YAAY,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI;IAqLvD;;;;;OAKG;IACH,wBAAwB,CACpB,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,EACpB,YAAY,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI;IAgK1C;;;;OAIG;IACH,eAAe,IAAI,MAAM,CAAC,QAAQ,CAAC;IA2MnC;;;;;OAKG;IACH,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,QAAQ;IAqDxC;;;;;OAKG;IACH,4BAA4B,IAAI,IAAI;CAwBrC"}
|
|
@@ -14,6 +14,7 @@ import { BufferByteSource, StoreByteSource } from "../../step/parsing/byte_sourc
|
|
|
14
14
|
import { buildIndexStreamingAsync, buildColumnarIndexStreamingAsync, } from "../../step/parsing/streaming_index_builder.js";
|
|
15
15
|
import { ColumnarIndexSink } from "../../step/parsing/columnar_index.js";
|
|
16
16
|
import { ifcPreviewAdapter, StreamedPreviewChannel, } from "./streamed_preview_channel.js";
|
|
17
|
+
import { makeParseAabbImposter } from "./parse_aabb_imposter.js";
|
|
17
18
|
import { ExtractResult } from "../../index.js";
|
|
18
19
|
import { IfcGeometryExtraction } from "../../ifc/ifc_geometry_extraction.js";
|
|
19
20
|
import { ParseResult } from "../../index.js";
|
|
@@ -36,6 +37,8 @@ const STREAMED_PARSE_POOL_BYTES = 1024 * 1024;
|
|
|
36
37
|
* is scratch — it does not stay resident after parse. */
|
|
37
38
|
// eslint-disable-next-line no-magic-numbers
|
|
38
39
|
const STORE_PARSE_POOL_BYTES = 16 * 1024 * 1024;
|
|
40
|
+
// eslint-disable-next-line no-magic-numbers
|
|
41
|
+
const BYTES_PER_MIB = 1024 * 1024;
|
|
39
42
|
/**
|
|
40
43
|
* The proxy for IFC from the shim.
|
|
41
44
|
*/
|
|
@@ -594,8 +597,9 @@ export class IfcApiProxyIfc {
|
|
|
594
597
|
/**
|
|
595
598
|
* Windowed-from-birth twin of parseColumnarAndExtractAsync: the
|
|
596
599
|
* source stays in `store`, parse windows are filled through it, and
|
|
597
|
-
* the model never holds a resident copy.
|
|
598
|
-
* skipped (
|
|
600
|
+
* the model never holds a resident copy. The full prefix-extract
|
|
601
|
+
* preview channel is skipped (it needs a resident prefix); a sparse
|
|
602
|
+
* AABB imposter rides onRecordIndexed instead. Deferred opens
|
|
599
603
|
* page prep closures before prepareDemandExtraction; non-deferred
|
|
600
604
|
* opens drain the demand pump with per-product residency.
|
|
601
605
|
*
|
|
@@ -625,7 +629,9 @@ export class IfcApiProxyIfc {
|
|
|
625
629
|
const parseTick = tracker !== void 0 ?
|
|
626
630
|
(cursorBytes) => tracker.update(cursorBytes) : void 0;
|
|
627
631
|
const parseStartTime = Date.now();
|
|
628
|
-
const
|
|
632
|
+
const onRecordIndexed = settings?.ON_PREVIEW_MESH !== void 0 ?
|
|
633
|
+
makeParseAabbImposter(settings.ON_PREVIEW_MESH) : void 0;
|
|
634
|
+
const { result, columns } = await buildColumnarIndexStreamingAsync(new StoreByteSource(store), parser, STORE_PARSE_POOL_BYTES, onRecordIndexed, parseTick);
|
|
629
635
|
const parseEndTime = Date.now();
|
|
630
636
|
tracker?.endPhase(fileSize);
|
|
631
637
|
if (result !== ParseResult.COMPLETE) {
|
|
@@ -642,6 +648,7 @@ export class IfcApiProxyIfc {
|
|
|
642
648
|
conwayGeometry.prepareDemandExtraction();
|
|
643
649
|
}
|
|
644
650
|
finally {
|
|
651
|
+
model.releaseSourceViews(prepPins);
|
|
645
652
|
model.unpinLocalIDs(prepPins);
|
|
646
653
|
}
|
|
647
654
|
if (deferGeometry) {
|
|
@@ -663,24 +670,46 @@ export class IfcApiProxyIfc {
|
|
|
663
670
|
const aggregateTargets = conwayGeometry.aggregateTargetLocalIDs();
|
|
664
671
|
let completed = 0;
|
|
665
672
|
tracker?.setPhaseTotal(model.typeCount(IfcProduct));
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
673
|
+
// eslint-disable-next-line no-magic-numbers
|
|
674
|
+
const EXTRACT_BATCH = 8;
|
|
675
|
+
const pending = [];
|
|
676
|
+
const flushProductBatch = async () => {
|
|
677
|
+
if (pending.length === 0) {
|
|
678
|
+
return;
|
|
669
679
|
}
|
|
670
|
-
const pins =
|
|
680
|
+
const pins = new Set();
|
|
671
681
|
try {
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
682
|
+
await Promise.all(pending.map((localID) => conwayGeometry.ensureResidentForProductExtract(localID, pins)));
|
|
683
|
+
for (const localID of pending) {
|
|
684
|
+
try {
|
|
685
|
+
conwayGeometry.extractProductGeometryByLocalID(localID);
|
|
686
|
+
}
|
|
687
|
+
catch (error) {
|
|
688
|
+
Logger.error(`Error extracting product localID ${localID}: ` +
|
|
689
|
+
`${error instanceof Error ? error.message : String(error)}`);
|
|
690
|
+
}
|
|
691
|
+
++completed;
|
|
692
|
+
}
|
|
677
693
|
}
|
|
678
694
|
finally {
|
|
695
|
+
model.releaseSourceViews(pins);
|
|
679
696
|
model.unpinLocalIDs(pins);
|
|
697
|
+
pending.length = 0;
|
|
698
|
+
}
|
|
699
|
+
tracker?.update(completed, {
|
|
700
|
+
residentSourceMb: model.residentSourceBytes / BYTES_PER_MIB,
|
|
701
|
+
});
|
|
702
|
+
};
|
|
703
|
+
for (const product of model.types(IfcProduct)) {
|
|
704
|
+
if (aggregateTargets.has(product.localID)) {
|
|
705
|
+
continue;
|
|
706
|
+
}
|
|
707
|
+
pending.push(product.localID);
|
|
708
|
+
if (pending.length >= EXTRACT_BATCH) {
|
|
709
|
+
await flushProductBatch();
|
|
680
710
|
}
|
|
681
|
-
++completed;
|
|
682
|
-
tracker?.update(completed);
|
|
683
711
|
}
|
|
712
|
+
await flushProductBatch();
|
|
684
713
|
for (const relAggregate of model.types(IfcRelAggregates)) {
|
|
685
714
|
const pins = await conwayGeometry.ensureResidentForAggregateExtract(relAggregate);
|
|
686
715
|
try {
|
|
@@ -691,10 +720,13 @@ export class IfcApiProxyIfc {
|
|
|
691
720
|
`${error instanceof Error ? error.message : String(error)}`);
|
|
692
721
|
}
|
|
693
722
|
finally {
|
|
723
|
+
model.releaseSourceViews(pins);
|
|
694
724
|
model.unpinLocalIDs(pins);
|
|
695
725
|
}
|
|
696
726
|
++completed;
|
|
697
|
-
tracker?.update(completed
|
|
727
|
+
tracker?.update(completed, {
|
|
728
|
+
residentSourceMb: model.residentSourceBytes / BYTES_PER_MIB,
|
|
729
|
+
});
|
|
698
730
|
}
|
|
699
731
|
const endTime = Date.now();
|
|
700
732
|
tracker?.endPhase();
|
|
@@ -1283,19 +1315,28 @@ export class IfcApiProxyIfc {
|
|
|
1283
1315
|
this.geometryPhaseStarted_ = true;
|
|
1284
1316
|
}
|
|
1285
1317
|
const productEnd = Math.min(this.demandCursor_ + budget, products.length);
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1318
|
+
const batchIDs = products.slice(this.demandCursor_, productEnd);
|
|
1319
|
+
if (batchIDs.length > 0) {
|
|
1320
|
+
// One pin set for the batch so mapped geometry stays resident
|
|
1321
|
+
// across the instances that share it.
|
|
1322
|
+
const pins = new Set();
|
|
1289
1323
|
try {
|
|
1290
|
-
|
|
1291
|
-
|
|
1324
|
+
await Promise.all(batchIDs.map((localID) => this.conwayGeometry_.ensureResidentForProductExtract(localID, pins)));
|
|
1325
|
+
for (const localID of batchIDs) {
|
|
1326
|
+
try {
|
|
1327
|
+
if (this.conwayGeometry_.extractProductGeometryByLocalID(localID)) {
|
|
1328
|
+
++extracted;
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
catch (error) {
|
|
1332
|
+
Logger.error(`Error extracting product localID ${localID}: ` +
|
|
1333
|
+
`${error instanceof Error ? error.message : String(error)}`);
|
|
1334
|
+
}
|
|
1292
1335
|
}
|
|
1293
|
-
|
|
1294
|
-
catch (error) {
|
|
1295
|
-
Logger.error(`Error extracting product localID ${localID}: ` +
|
|
1296
|
-
`${error instanceof Error ? error.message : String(error)}`);
|
|
1336
|
+
this.demandCursor_ = productEnd;
|
|
1297
1337
|
}
|
|
1298
1338
|
finally {
|
|
1339
|
+
this.model[0].releaseSourceViews(pins);
|
|
1299
1340
|
this.model[0].unpinLocalIDs(pins);
|
|
1300
1341
|
}
|
|
1301
1342
|
}
|
|
@@ -1314,6 +1355,7 @@ export class IfcApiProxyIfc {
|
|
|
1314
1355
|
`${error instanceof Error ? error.message : String(error)}`);
|
|
1315
1356
|
}
|
|
1316
1357
|
finally {
|
|
1358
|
+
this.model[0].releaseSourceViews(pins);
|
|
1317
1359
|
this.model[0].unpinLocalIDs(pins);
|
|
1318
1360
|
}
|
|
1319
1361
|
}
|
|
@@ -1323,13 +1365,15 @@ export class IfcApiProxyIfc {
|
|
|
1323
1365
|
}
|
|
1324
1366
|
const remaining = (products.length - this.demandCursor_) +
|
|
1325
1367
|
(aggregates.length - this.demandAggregatesCursor_);
|
|
1368
|
+
const windowMb = this.model[0].residentSourceBytes / BYTES_PER_MIB;
|
|
1326
1369
|
if (this.progressTracker_ !== void 0) {
|
|
1327
1370
|
const completed = totalWork - remaining;
|
|
1328
1371
|
if (remaining === 0) {
|
|
1372
|
+
this.progressTracker_.update(completed, { residentSourceMb: windowMb });
|
|
1329
1373
|
this.progressTracker_.endPhase(totalWork);
|
|
1330
1374
|
}
|
|
1331
1375
|
else {
|
|
1332
|
-
this.progressTracker_.update(completed);
|
|
1376
|
+
this.progressTracker_.update(completed, { residentSourceMb: windowMb });
|
|
1333
1377
|
}
|
|
1334
1378
|
}
|
|
1335
1379
|
return { extracted, remaining };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { PreviewMeshPayload } from "./streamed_preview_channel.js";
|
|
2
|
+
export interface Aabb3 {
|
|
3
|
+
min: [
|
|
4
|
+
number,
|
|
5
|
+
number,
|
|
6
|
+
number
|
|
7
|
+
];
|
|
8
|
+
max: [
|
|
9
|
+
number,
|
|
10
|
+
number,
|
|
11
|
+
number
|
|
12
|
+
];
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Min/max of every STEP real triple in `bytes`. Used for
|
|
16
|
+
* IfcCartesianPointList3D bodies: the numbers live in the record, so a
|
|
17
|
+
* store-backed parse can emit an AABB without hydrating the entity or
|
|
18
|
+
* paging a closure.
|
|
19
|
+
*
|
|
20
|
+
* @param bytes The record's source bytes (window view; do not retain).
|
|
21
|
+
* @return {Aabb3 | null} Bounds, or null if fewer than MIN_POINTS triples.
|
|
22
|
+
*/
|
|
23
|
+
export declare function aabbFromStepReals(bytes: Uint8Array): Aabb3 | null;
|
|
24
|
+
/**
|
|
25
|
+
* Column-major 4x4: IFC Z-up box → Y-up, translated to the box centre
|
|
26
|
+
* and scaled to its size. Share instances a shared unit cube with this.
|
|
27
|
+
*
|
|
28
|
+
* @param aabb The IFC-space bounds.
|
|
29
|
+
* @return {number[]} 16-element matrix.
|
|
30
|
+
*/
|
|
31
|
+
export declare function aabbToPreviewMatrix(aabb: Aabb3): number[];
|
|
32
|
+
/**
|
|
33
|
+
* Stateful filter: every IMPOSTER_STRIDE-th IfcCartesianPointList3D
|
|
34
|
+
* becomes a tiny preview payload. The view `recordBytes` is into the
|
|
35
|
+
* sliding parse window; do not retain it.
|
|
36
|
+
*
|
|
37
|
+
* @param onMesh Preview consumer (Share's ON_PREVIEW_MESH).
|
|
38
|
+
* @return A callback matching onRecordIndexed.
|
|
39
|
+
*/
|
|
40
|
+
export declare function makeParseAabbImposter(onMesh: (mesh: PreviewMeshPayload) => void): (localID: number, expressID: number, typeID: number | undefined, recordBytes?: Uint8Array) => void;
|
|
41
|
+
//# sourceMappingURL=parse_aabb_imposter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse_aabb_imposter.d.ts","sourceRoot":"","sources":["../../../../src/compat/web-ifc/parse_aabb_imposter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAA;AAoBpE,MAAM,WAAW,KAAK;IACpB,GAAG,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IAC7B,GAAG,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;CAC9B;AAGD;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAE,KAAK,EAAE,UAAU,GAAI,KAAK,GAAG,IAAI,CA8EnE;AAGD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAE,IAAI,EAAE,KAAK,GAAI,MAAM,EAAE,CAgB3D;AAGD;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACjC,MAAM,EAAE,CAAE,IAAI,EAAE,kBAAkB,KAAM,IAAI,GAC5C,CAAE,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,WAAW,CAAC,EAAE,UAAU,KAAM,IAAI,CAoCvC"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import EntityTypesIfc from "../../ifc/ifc4_gen/entity_types_ifc.gen.js";
|
|
2
|
+
import ParsingBuffer from "../../parsing/parsing_buffer.js";
|
|
3
|
+
/* eslint-disable no-magic-numbers */
|
|
4
|
+
/** Emit every Nth point-list AABB — sparse on purpose. */
|
|
5
|
+
const IMPOSTER_STRIDE = 8;
|
|
6
|
+
/** Skip lists with fewer than this many points (noise). */
|
|
7
|
+
const MIN_POINTS = 8;
|
|
8
|
+
/** Cap so one huge tessellation list cannot stall the parse yield. */
|
|
9
|
+
const SCAN_BUDGET_BYTES = 128 * 1024;
|
|
10
|
+
const IMPOSTER_COLOR = { x: 0.45, y: 0.75, z: 0.95, w: 0.35 };
|
|
11
|
+
const CHAR_HASH = 35;
|
|
12
|
+
const CHAR_EQ = 61;
|
|
13
|
+
const CHAR_LPAREN = 40;
|
|
14
|
+
/**
|
|
15
|
+
* Min/max of every STEP real triple in `bytes`. Used for
|
|
16
|
+
* IfcCartesianPointList3D bodies: the numbers live in the record, so a
|
|
17
|
+
* store-backed parse can emit an AABB without hydrating the entity or
|
|
18
|
+
* paging a closure.
|
|
19
|
+
*
|
|
20
|
+
* @param bytes The record's source bytes (window view; do not retain).
|
|
21
|
+
* @return {Aabb3 | null} Bounds, or null if fewer than MIN_POINTS triples.
|
|
22
|
+
*/
|
|
23
|
+
export function aabbFromStepReals(bytes) {
|
|
24
|
+
let minX = Infinity;
|
|
25
|
+
let minY = Infinity;
|
|
26
|
+
let minZ = Infinity;
|
|
27
|
+
let maxX = -Infinity;
|
|
28
|
+
let maxY = -Infinity;
|
|
29
|
+
let maxZ = -Infinity;
|
|
30
|
+
let points = 0;
|
|
31
|
+
let axis = 0;
|
|
32
|
+
let x = 0;
|
|
33
|
+
let y = 0;
|
|
34
|
+
// Skip `#id=TYPENAME(` so the express ID is not a phantom first real.
|
|
35
|
+
let start = 0;
|
|
36
|
+
const end = Math.min(bytes.length, SCAN_BUDGET_BYTES);
|
|
37
|
+
if (bytes[start] === CHAR_HASH) {
|
|
38
|
+
while (start < end && bytes[start] !== CHAR_EQ) {
|
|
39
|
+
++start;
|
|
40
|
+
}
|
|
41
|
+
if (start < end) {
|
|
42
|
+
++start;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
while (start < end && bytes[start] !== CHAR_LPAREN) {
|
|
46
|
+
++start;
|
|
47
|
+
}
|
|
48
|
+
const input = new ParsingBuffer(bytes, start, end);
|
|
49
|
+
while (!input.finished) {
|
|
50
|
+
const value = input.readReal();
|
|
51
|
+
if (value === void 0) {
|
|
52
|
+
input.step();
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
if (axis === 0) {
|
|
56
|
+
x = value;
|
|
57
|
+
axis = 1;
|
|
58
|
+
}
|
|
59
|
+
else if (axis === 1) {
|
|
60
|
+
y = value;
|
|
61
|
+
axis = 2;
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
if (x < minX) {
|
|
65
|
+
minX = x;
|
|
66
|
+
}
|
|
67
|
+
if (y < minY) {
|
|
68
|
+
minY = y;
|
|
69
|
+
}
|
|
70
|
+
if (value < minZ) {
|
|
71
|
+
minZ = value;
|
|
72
|
+
}
|
|
73
|
+
if (x > maxX) {
|
|
74
|
+
maxX = x;
|
|
75
|
+
}
|
|
76
|
+
if (y > maxY) {
|
|
77
|
+
maxY = y;
|
|
78
|
+
}
|
|
79
|
+
if (value > maxZ) {
|
|
80
|
+
maxZ = value;
|
|
81
|
+
}
|
|
82
|
+
++points;
|
|
83
|
+
axis = 0;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (points < MIN_POINTS || !Number.isFinite(minX)) {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
return { min: [minX, minY, minZ], max: [maxX, maxY, maxZ] };
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Column-major 4x4: IFC Z-up box → Y-up, translated to the box centre
|
|
93
|
+
* and scaled to its size. Share instances a shared unit cube with this.
|
|
94
|
+
*
|
|
95
|
+
* @param aabb The IFC-space bounds.
|
|
96
|
+
* @return {number[]} 16-element matrix.
|
|
97
|
+
*/
|
|
98
|
+
export function aabbToPreviewMatrix(aabb) {
|
|
99
|
+
const sx = Math.max(aabb.max[0] - aabb.min[0], 0.001);
|
|
100
|
+
const sy = Math.max(aabb.max[1] - aabb.min[1], 0.001);
|
|
101
|
+
const sz = Math.max(aabb.max[2] - aabb.min[2], 0.001);
|
|
102
|
+
const cx = (aabb.min[0] + aabb.max[0]) * 0.5;
|
|
103
|
+
const cy = (aabb.min[1] + aabb.max[1]) * 0.5;
|
|
104
|
+
const cz = (aabb.min[2] + aabb.max[2]) * 0.5;
|
|
105
|
+
// Z-up → Y-up, then scale/centre for a unit cube.
|
|
106
|
+
return [
|
|
107
|
+
sx,
|
|
108
|
+
0,
|
|
109
|
+
0,
|
|
110
|
+
0,
|
|
111
|
+
0,
|
|
112
|
+
sz,
|
|
113
|
+
0,
|
|
114
|
+
0,
|
|
115
|
+
0,
|
|
116
|
+
0,
|
|
117
|
+
sy,
|
|
118
|
+
0,
|
|
119
|
+
cx,
|
|
120
|
+
cz,
|
|
121
|
+
-cy,
|
|
122
|
+
1,
|
|
123
|
+
];
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Stateful filter: every IMPOSTER_STRIDE-th IfcCartesianPointList3D
|
|
127
|
+
* becomes a tiny preview payload. The view `recordBytes` is into the
|
|
128
|
+
* sliding parse window; do not retain it.
|
|
129
|
+
*
|
|
130
|
+
* @param onMesh Preview consumer (Share's ON_PREVIEW_MESH).
|
|
131
|
+
* @return A callback matching onRecordIndexed.
|
|
132
|
+
*/
|
|
133
|
+
export function makeParseAabbImposter(onMesh) {
|
|
134
|
+
let seen = 0;
|
|
135
|
+
return (_localID, expressID, typeID, recordBytes) => {
|
|
136
|
+
if (typeID !== EntityTypesIfc.IFCCARTESIANPOINTLIST3D ||
|
|
137
|
+
recordBytes === void 0) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
++seen;
|
|
141
|
+
if (seen % IMPOSTER_STRIDE !== 0) {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
try {
|
|
145
|
+
const aabb = aabbFromStepReals(recordBytes);
|
|
146
|
+
if (aabb === null) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
onMesh({
|
|
150
|
+
expressID,
|
|
151
|
+
geometryExpressID: -1,
|
|
152
|
+
color: IMPOSTER_COLOR,
|
|
153
|
+
flatTransformation: aabbToPreviewMatrix(aabb),
|
|
154
|
+
aabb,
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
// Preview must never break the parse.
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse_aabb_imposter.test.d.ts","sourceRoot":"","sources":["../../../../src/compat/web-ifc/parse_aabb_imposter.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { describe, expect, test } from "@jest/globals";
|
|
2
|
+
import { aabbFromStepReals, aabbToPreviewMatrix, makeParseAabbImposter, } from "./parse_aabb_imposter.js";
|
|
3
|
+
import EntityTypesIfc from "../../ifc/ifc4_gen/entity_types_ifc.gen.js";
|
|
4
|
+
describe("parse_aabb_imposter", () => {
|
|
5
|
+
test("aabbFromStepReals reads IFCCARTESIANPOINTLIST3D triples", () => {
|
|
6
|
+
const text = "#10=IFCCARTESIANPOINTLIST3D(((0.,0.,0.),(1.,2.,3.),(-1.,0.,1.)," +
|
|
7
|
+
"(4.,5.,6.),(0.,0.,1.),(0.,1.,0.),(1.,0.,0.),(2.,2.,2.)));";
|
|
8
|
+
const bytes = new TextEncoder().encode(text);
|
|
9
|
+
const aabb = aabbFromStepReals(bytes);
|
|
10
|
+
expect(aabb).not.toBeNull();
|
|
11
|
+
expect(aabb.min).toEqual([-1, 0, 0]);
|
|
12
|
+
expect(aabb.max).toEqual([4, 5, 6]);
|
|
13
|
+
});
|
|
14
|
+
test("aabbFromStepReals returns null for a short list", () => {
|
|
15
|
+
const text = "#1=IFCCARTESIANPOINTLIST3D(((0.,0.,0.),(1.,1.,1.)));";
|
|
16
|
+
expect(aabbFromStepReals(new TextEncoder().encode(text))).toBeNull();
|
|
17
|
+
});
|
|
18
|
+
test("aabbToPreviewMatrix is Z-up to Y-up and centres the box", () => {
|
|
19
|
+
const matrix = aabbToPreviewMatrix({ min: [0, 0, 0], max: [2, 4, 6] });
|
|
20
|
+
expect(matrix[0]).toBe(2);
|
|
21
|
+
expect(matrix[5]).toBe(6);
|
|
22
|
+
expect(matrix[10]).toBe(4);
|
|
23
|
+
expect(matrix[12]).toBe(1);
|
|
24
|
+
expect(matrix[13]).toBe(3);
|
|
25
|
+
expect(matrix[14]).toBe(-2);
|
|
26
|
+
});
|
|
27
|
+
test("makeParseAabbImposter emits every 8th point list", () => {
|
|
28
|
+
const emitted = [];
|
|
29
|
+
const emit = makeParseAabbImposter((mesh) => emitted.push(mesh));
|
|
30
|
+
const points = Array.from({ length: 8 }, (_, i) => `(${i}.,0.,0.)`).join(",");
|
|
31
|
+
const bytes = new TextEncoder().encode(`#1=IFCCARTESIANPOINTLIST3D((${points}));`);
|
|
32
|
+
for (let i = 1; i <= 8; ++i) {
|
|
33
|
+
emit(i, i * 10, EntityTypesIfc.IFCCARTESIANPOINTLIST3D, bytes);
|
|
34
|
+
}
|
|
35
|
+
expect(emitted).toHaveLength(1);
|
|
36
|
+
expect(emitted[0].aabb).toBeDefined();
|
|
37
|
+
expect(emitted[0].expressID).toBe(80);
|
|
38
|
+
});
|
|
39
|
+
});
|