@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.
Files changed (39) hide show
  1. package/compiled/examples/browser-bundled.cjs +82 -16
  2. package/compiled/examples/cli-bundled.cjs +98 -23
  3. package/compiled/examples/cli-step-bundled.cjs +82 -16
  4. package/compiled/examples/validator-bundled.cjs +82 -16
  5. package/compiled/src/compat/web-ifc/ifc_api_proxy_ifc.d.ts +3 -2
  6. package/compiled/src/compat/web-ifc/ifc_api_proxy_ifc.d.ts.map +1 -1
  7. package/compiled/src/compat/web-ifc/ifc_api_proxy_ifc.js +69 -25
  8. package/compiled/src/compat/web-ifc/parse_aabb_imposter.d.ts +41 -0
  9. package/compiled/src/compat/web-ifc/parse_aabb_imposter.d.ts.map +1 -0
  10. package/compiled/src/compat/web-ifc/parse_aabb_imposter.js +161 -0
  11. package/compiled/src/compat/web-ifc/parse_aabb_imposter.test.d.ts +2 -0
  12. package/compiled/src/compat/web-ifc/parse_aabb_imposter.test.d.ts.map +1 -0
  13. package/compiled/src/compat/web-ifc/parse_aabb_imposter.test.js +39 -0
  14. package/compiled/src/compat/web-ifc/streamed_preview_channel.d.ts +13 -0
  15. package/compiled/src/compat/web-ifc/streamed_preview_channel.d.ts.map +1 -1
  16. package/compiled/src/core/progress.d.ts +8 -1
  17. package/compiled/src/core/progress.d.ts.map +1 -1
  18. package/compiled/src/core/progress.js +9 -4
  19. package/compiled/src/core/progress_log.d.ts +1 -0
  20. package/compiled/src/core/progress_log.d.ts.map +1 -1
  21. package/compiled/src/core/progress_log.js +7 -2
  22. package/compiled/src/core/progress_log.test.js +21 -0
  23. package/compiled/src/ifc/ifc_stream_open.test.js +60 -0
  24. package/compiled/src/step/parsing/step_parser.d.ts +2 -2
  25. package/compiled/src/step/parsing/step_parser.d.ts.map +1 -1
  26. package/compiled/src/step/parsing/step_parser.js +8 -2
  27. package/compiled/src/step/parsing/streaming_index_builder.d.ts +4 -4
  28. package/compiled/src/step/parsing/streaming_index_builder.d.ts.map +1 -1
  29. package/compiled/src/step/step_buffer_provider.d.ts +4 -3
  30. package/compiled/src/step/step_buffer_provider.d.ts.map +1 -1
  31. package/compiled/src/step/step_buffer_provider.js +4 -3
  32. package/compiled/src/step/step_entity_base.d.ts.map +1 -1
  33. package/compiled/src/step/step_entity_base.js +9 -0
  34. package/compiled/src/step/step_model_base.d.ts +9 -0
  35. package/compiled/src/step/step_model_base.d.ts.map +1 -1
  36. package/compiled/src/step/step_model_base.js +72 -13
  37. package/compiled/src/version/version.js +1 -1
  38. package/compiled/tsconfig.tsbuildinfo +1 -1
  39. 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.511.1441";
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
- onRecordIndexed?.(topLevelCount, expressID, 0);
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
- onRecordIndexed?.(topLevelCount, expressID, foundItem);
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 stack = [localID];
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
- stack.push(extra);
5745
+ enqueue(extra);
5726
5746
  }
5727
5747
  }
5728
- while (stack.length > 0) {
5729
- const id = stack.pop();
5730
- if (seen.has(id) || id >= this.count_) {
5731
- continue;
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
- seen.add(id);
5734
- await this.ensureResidentByLocalID(id);
5735
- this.pinByLocalID(id);
5736
- for (const expressID of this.scanRecordRefs_(id)) {
5737
- const referenced = this.expressIDMap_.get(expressID);
5738
- if (referenced !== void 0 && !seen.has(referenced)) {
5739
- stack.push(referenced);
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. Preview-during-parse is
257
- * skipped (that channel needs a resident prefix). Deferred opens
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":"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"}
1
+ {"version":3,"file":"ifc_api_proxy_ifc.d.ts","sourceRoot":"","sources":["../../../../src/compat/web-ifc/ifc_api_proxy_ifc.ts"],"names":[],"mappings":"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"}
@@ -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. Preview-during-parse is
598
- * skipped (that channel needs a resident prefix). Deferred opens
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 { result, columns } = await buildColumnarIndexStreamingAsync(new StoreByteSource(store), parser, STORE_PARSE_POOL_BYTES, void 0, parseTick);
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
- for (const product of model.types(IfcProduct)) {
667
- if (aggregateTargets.has(product.localID)) {
668
- continue;
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 = await conwayGeometry.ensureResidentForProductExtract(product.localID);
680
+ const pins = new Set();
671
681
  try {
672
- conwayGeometry.extractProductGeometryByLocalID(product.localID);
673
- }
674
- catch (error) {
675
- Logger.error(`Error extracting product ${product.expressID}: ` +
676
- `${error instanceof Error ? error.message : String(error)}`);
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
- for (; this.demandCursor_ < productEnd; ++this.demandCursor_) {
1287
- const localID = products[this.demandCursor_];
1288
- const pins = await this.conwayGeometry_.ensureResidentForProductExtract(localID);
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
- if (this.conwayGeometry_.extractProductGeometryByLocalID(localID)) {
1291
- ++extracted;
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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=parse_aabb_imposter.test.d.ts.map
@@ -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
+ });