@ifc-lite/export 4.0.1 → 4.3.1

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 (123) hide show
  1. package/README.md +7 -0
  2. package/dist/anonymize-export.d.ts.map +1 -1
  3. package/dist/anonymize-export.js +10 -4
  4. package/dist/anonymize-export.js.map +1 -1
  5. package/dist/anonymize-placement.d.ts.map +1 -1
  6. package/dist/anonymize-placement.js +5 -6
  7. package/dist/anonymize-placement.js.map +1 -1
  8. package/dist/appearance-dependencies.d.ts +12 -0
  9. package/dist/appearance-dependencies.d.ts.map +1 -0
  10. package/dist/appearance-dependencies.js +195 -0
  11. package/dist/appearance-dependencies.js.map +1 -0
  12. package/dist/authored-resource-cleanup.d.ts +14 -0
  13. package/dist/authored-resource-cleanup.d.ts.map +1 -0
  14. package/dist/authored-resource-cleanup.js +156 -0
  15. package/dist/authored-resource-cleanup.js.map +1 -0
  16. package/dist/csv-table.d.ts +10 -0
  17. package/dist/csv-table.d.ts.map +1 -0
  18. package/dist/csv-table.js +39 -0
  19. package/dist/csv-table.js.map +1 -0
  20. package/dist/effective-appearance-record.d.ts +8 -0
  21. package/dist/effective-appearance-record.d.ts.map +1 -0
  22. package/dist/effective-appearance-record.js +49 -0
  23. package/dist/effective-appearance-record.js.map +1 -0
  24. package/dist/ifc5-appearance.d.ts +20 -0
  25. package/dist/ifc5-appearance.d.ts.map +1 -0
  26. package/dist/ifc5-appearance.js +106 -0
  27. package/dist/ifc5-appearance.js.map +1 -0
  28. package/dist/ifc5-export-helpers.d.ts +19 -0
  29. package/dist/ifc5-export-helpers.d.ts.map +1 -1
  30. package/dist/ifc5-export-helpers.js +41 -0
  31. package/dist/ifc5-export-helpers.js.map +1 -1
  32. package/dist/ifc5-exporter.d.ts +12 -10
  33. package/dist/ifc5-exporter.d.ts.map +1 -1
  34. package/dist/ifc5-exporter.js +24 -41
  35. package/dist/ifc5-exporter.js.map +1 -1
  36. package/dist/index.d.ts +6 -1
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +7 -1
  39. package/dist/index.js.map +1 -1
  40. package/dist/lod0-generator.js +1 -1
  41. package/dist/lod0-generator.js.map +1 -1
  42. package/dist/merged-context.d.ts.map +1 -1
  43. package/dist/merged-context.js +15 -1
  44. package/dist/merged-context.js.map +1 -1
  45. package/dist/merged-empty-containers.d.ts.map +1 -1
  46. package/dist/merged-empty-containers.js +9 -11
  47. package/dist/merged-empty-containers.js.map +1 -1
  48. package/dist/merged-subcontext.d.ts.map +1 -1
  49. package/dist/merged-subcontext.js +19 -1
  50. package/dist/merged-subcontext.js.map +1 -1
  51. package/dist/obj.d.ts +20 -0
  52. package/dist/obj.d.ts.map +1 -0
  53. package/dist/obj.js +40 -0
  54. package/dist/obj.js.map +1 -0
  55. package/dist/parquet-exporter.d.ts.map +1 -1
  56. package/dist/parquet-exporter.js +5 -5
  57. package/dist/parquet-exporter.js.map +1 -1
  58. package/dist/reference-collector.d.ts +21 -8
  59. package/dist/reference-collector.d.ts.map +1 -1
  60. package/dist/reference-collector.js +38 -45
  61. package/dist/reference-collector.js.map +1 -1
  62. package/dist/retype.d.ts +1 -1
  63. package/dist/retype.d.ts.map +1 -1
  64. package/dist/retype.js +13 -3
  65. package/dist/retype.js.map +1 -1
  66. package/dist/schema-converter-attr-remap.d.ts +18 -7
  67. package/dist/schema-converter-attr-remap.d.ts.map +1 -1
  68. package/dist/schema-converter-attr-remap.js +42 -48
  69. package/dist/schema-converter-attr-remap.js.map +1 -1
  70. package/dist/schema-converter.d.ts.map +1 -1
  71. package/dist/schema-converter.js +16 -78
  72. package/dist/schema-converter.js.map +1 -1
  73. package/dist/step-argument-parser.d.ts +20 -3
  74. package/dist/step-argument-parser.d.ts.map +1 -1
  75. package/dist/step-argument-parser.js +60 -11
  76. package/dist/step-argument-parser.js.map +1 -1
  77. package/dist/step-attribute-mutations.d.ts +32 -2
  78. package/dist/step-attribute-mutations.d.ts.map +1 -1
  79. package/dist/step-attribute-mutations.js +87 -6
  80. package/dist/step-attribute-mutations.js.map +1 -1
  81. package/dist/step-comment-skip.d.ts +13 -0
  82. package/dist/step-comment-skip.d.ts.map +1 -0
  83. package/dist/step-comment-skip.js +19 -0
  84. package/dist/step-comment-skip.js.map +1 -0
  85. package/dist/step-export-types.d.ts +51 -0
  86. package/dist/step-export-types.d.ts.map +1 -1
  87. package/dist/step-export-types.js +38 -0
  88. package/dist/step-export-types.js.map +1 -1
  89. package/dist/step-outer-args.d.ts +27 -0
  90. package/dist/step-outer-args.d.ts.map +1 -0
  91. package/dist/step-outer-args.js +64 -0
  92. package/dist/step-outer-args.js.map +1 -0
  93. package/dist/step-overlay-attribute-overrides.d.ts.map +1 -1
  94. package/dist/step-overlay-attribute-overrides.js +6 -2
  95. package/dist/step-overlay-attribute-overrides.js.map +1 -1
  96. package/dist/step-property-sets.d.ts.map +1 -1
  97. package/dist/step-property-sets.js +8 -2
  98. package/dist/step-property-sets.js.map +1 -1
  99. package/dist/step-serialization.d.ts +1 -1
  100. package/dist/step-serialization.js +1 -1
  101. package/dist/step-slot-grammar.d.ts +24 -0
  102. package/dist/step-slot-grammar.d.ts.map +1 -0
  103. package/dist/step-slot-grammar.js +201 -0
  104. package/dist/step-slot-grammar.js.map +1 -0
  105. package/dist/step-source-iteration.d.ts.map +1 -1
  106. package/dist/step-source-iteration.js +26 -2
  107. package/dist/step-source-iteration.js.map +1 -1
  108. package/dist/style-closure.d.ts +3 -1
  109. package/dist/style-closure.d.ts.map +1 -1
  110. package/dist/style-closure.js +16 -1
  111. package/dist/style-closure.js.map +1 -1
  112. package/dist/subset-entity-reader.d.ts +12 -4
  113. package/dist/subset-entity-reader.d.ts.map +1 -1
  114. package/dist/subset-entity-reader.js +4 -16
  115. package/dist/subset-entity-reader.js.map +1 -1
  116. package/dist/texture-map-closure.d.ts +10 -0
  117. package/dist/texture-map-closure.d.ts.map +1 -0
  118. package/dist/texture-map-closure.js +22 -0
  119. package/dist/texture-map-closure.js.map +1 -0
  120. package/dist/unit-normalize.d.ts.map +1 -1
  121. package/dist/unit-normalize.js +12 -49
  122. package/dist/unit-normalize.js.map +1 -1
  123. package/package.json +8 -8
@@ -0,0 +1,39 @@
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
+ * RFC 4180 CSV for a table of row OBJECTS — one header row from `columns`, then
6
+ * one line per row reading exactly those keys, in that order.
7
+ *
8
+ * Every table export in this repo (zones, clashes, …) had grown its own copy of
9
+ * the same 15-line loop around `escapeCsvCell`. The loop is not where the
10
+ * security lives — that is the escaper — but three copies of "null → empty,
11
+ * boolean → `true`/`false`, trailing newline" still drift (one forgot the
12
+ * trailing newline, so `cat a.csv b.csv` joined two rows). One writer, one set
13
+ * of rules:
14
+ *
15
+ * - `null` / `undefined` → empty cell (a spreadsheet reads `null` as text).
16
+ * - booleans → `true` / `false` (not `1`/`0`, which sum).
17
+ * - every other value → `String(value)` through {@link escapeCsvCell}, which
18
+ * applies RFC 4180 quoting and the CWE-1236 formula-injection guard. A cell
19
+ * whose first or last character is whitespace is quoted so an importer cannot
20
+ * trim the padding away (`quoteWhitespacePadded`).
21
+ * - lines end with `\n` and the file ends with one.
22
+ */
23
+ import { escapeCsvCell } from './csv-cell.js';
24
+ /** Serialise one cell value under the rules documented on {@link tableToCsv}. */
25
+ export function csvCellOf(value, delimiter = ',') {
26
+ if (value === null || value === undefined)
27
+ return '';
28
+ const raw = typeof value === 'boolean' ? (value ? 'true' : 'false') : String(value);
29
+ return escapeCsvCell(raw, { delimiter, quoteWhitespacePadded: true });
30
+ }
31
+ export function tableToCsv(columns, rows, options = {}) {
32
+ const delimiter = options.delimiter ?? ',';
33
+ const lines = [columns.map((column) => csvCellOf(column, delimiter)).join(delimiter)];
34
+ for (const row of rows) {
35
+ lines.push(columns.map((column) => csvCellOf(row[column], delimiter)).join(delimiter));
36
+ }
37
+ return `${lines.join('\n')}\n`;
38
+ }
39
+ //# sourceMappingURL=csv-table.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"csv-table.js","sourceRoot":"","sources":["../src/csv-table.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAU9C,iFAAiF;AACjF,MAAM,UAAU,SAAS,CAAC,KAAc,EAAE,SAAS,GAAG,GAAG;IACvD,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IACrD,MAAM,GAAG,GAAG,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACpF,OAAO,aAAa,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,qBAAqB,EAAE,IAAI,EAAE,CAAC,CAAC;AACxE,CAAC;AAED,MAAM,UAAU,UAAU,CACxB,OAAoC,EACpC,IAAoB,EACpB,UAA6B,EAAE;IAE/B,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,GAAG,CAAC;IAC3C,MAAM,KAAK,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;IACtF,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;IACzF,CAAC;IACD,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;AACjC,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { type IfcDataStore } from '@ifc-lite/parser';
2
+ import type { MutablePropertyView } from '@ifc-lite/mutations';
3
+ import type { EffectiveEntityIndex } from './effective-index.js';
4
+ /** Compose the existing STEP writers; never invent a second override policy. */
5
+ export declare function effectiveAppearanceRecord(store: IfcDataStore, view: MutablePropertyView, index: EffectiveEntityIndex, id: number): string;
6
+ /** URLReference occupies slot 5 after the inherited IfcSurfaceTexture fields. */
7
+ export declare function effectiveImageUri(line: string): string | undefined;
8
+ //# sourceMappingURL=effective-appearance-record.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"effective-appearance-record.d.ts","sourceRoot":"","sources":["../src/effective-appearance-record.ts"],"names":[],"mappings":"AAGA,OAAO,EAAiC,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACpF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAQjE,gFAAgF;AAChF,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,mBAAmB,EAAE,KAAK,EAAE,oBAAoB,EAAE,EAAE,EAAE,MAAM,GACtF,MAAM,CAuBR;AAED,iFAAiF;AACjF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAOlE"}
@@ -0,0 +1,49 @@
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
+ import { asSourceBytes, parseStepValue } from '@ifc-lite/parser';
5
+ import { serializeEntityArgs } from './attribute-real-slots.js';
6
+ import { applyOverlayEntityOverrides } from './step-overlay-attribute-overrides.js';
7
+ import { applySourceLineMutations } from './step-attribute-mutations.js';
8
+ import { readStepSlots, splitTopLevelStepArguments } from './step-argument-parser.js';
9
+ import { retypeArgTokens } from './retype.js';
10
+ /** Compose the existing STEP writers; never invent a second override policy. */
11
+ export function effectiveAppearanceRecord(store, view, index, id) {
12
+ const record = index.get(id);
13
+ if (!record)
14
+ throw new Error('Missing IFC entity during appearance cleanup; resources were retained.');
15
+ const schema = store.schemaVersion || 'IFC4';
16
+ const named = new Map(view.getAttributeMutationsForEntity(id).map(({ name, value }) => [name, value]));
17
+ const created = view.getNewEntity(id);
18
+ if (created) {
19
+ const retype = view.getEntityTypeMutation(id);
20
+ const type = retype?.newType ?? created.type;
21
+ let args = serializeEntityArgs(created.type, created.attributes, schema);
22
+ if (retype) {
23
+ const slots = splitTopLevelStepArguments(args);
24
+ if (slots === null)
25
+ throw new Error('Invalid authored IFC entity during appearance cleanup; resources were retained.');
26
+ args = retypeArgTokens(slots, created.type, type, retype.predefinedType, schema).tokens.join(',');
27
+ }
28
+ args = applyOverlayEntityOverrides(args, type, named, view.getPositionalMutationsForEntity(id), schema);
29
+ return `#${id}=${type.toUpperCase()}(${args});`;
30
+ }
31
+ const source = asSourceBytes(store.source);
32
+ const original = source.decodeUtf8(record.byteOffset, record.byteOffset + record.byteLength);
33
+ const result = applySourceLineMutations(view, id, original, record.type, named, schema, true);
34
+ if (result.unreadable)
35
+ throw new Error('Unreadable edited IFC entity during appearance cleanup; resources were retained.');
36
+ return result.text;
37
+ }
38
+ /** URLReference occupies slot 5 after the inherited IfcSurfaceTexture fields. */
39
+ export function effectiveImageUri(line) {
40
+ const record = readStepSlots(line);
41
+ if (record === null)
42
+ throw new Error('Unreadable IFC image during appearance cleanup; resources were retained.');
43
+ const argument = record.slots[5];
44
+ if (argument === undefined)
45
+ return undefined;
46
+ const value = parseStepValue(argument.trim());
47
+ return typeof value === 'string' ? value : undefined;
48
+ }
49
+ //# sourceMappingURL=effective-appearance-record.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"effective-appearance-record.js","sourceRoot":"","sources":["../src/effective-appearance-record.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAC/D,OAAO,EAAE,aAAa,EAAE,cAAc,EAAqB,MAAM,kBAAkB,CAAC;AAGpF,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,2BAA2B,EAAE,MAAM,uCAAuC,CAAC;AACpF,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AACtF,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAG9C,gFAAgF;AAChF,MAAM,UAAU,yBAAyB,CACvC,KAAmB,EAAE,IAAyB,EAAE,KAA2B,EAAE,EAAU;IAEvF,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC7B,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,wEAAwE,CAAC,CAAC;IACvG,MAAM,MAAM,GAAI,KAAK,CAAC,aAAkC,IAAI,MAAM,CAAC;IACnE,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,8BAA8B,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IACvG,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;IACtC,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,MAAM,GAAG,IAAI,CAAC,qBAAqB,CAAC,EAAE,CAAC,CAAC;QAC9C,MAAM,IAAI,GAAG,MAAM,EAAE,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;QAC7C,IAAI,IAAI,GAAG,mBAAmB,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QACzE,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,KAAK,GAAG,0BAA0B,CAAC,IAAI,CAAC,CAAC;YAC/C,IAAI,KAAK,KAAK,IAAI;gBAAE,MAAM,IAAI,KAAK,CAAC,iFAAiF,CAAC,CAAC;YACvH,IAAI,GAAG,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACpG,CAAC;QACD,IAAI,GAAG,2BAA2B,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,+BAA+B,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;QACxG,OAAO,IAAI,EAAE,IAAI,IAAI,CAAC,WAAW,EAAE,IAAI,IAAI,IAAI,CAAC;IAClD,CAAC;IACD,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC3C,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;IAC7F,MAAM,MAAM,GAAG,wBAAwB,CAAC,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;IAC9F,IAAI,MAAM,CAAC,UAAU;QAAE,MAAM,IAAI,KAAK,CAAC,kFAAkF,CAAC,CAAC;IAC3H,OAAO,MAAM,CAAC,IAAI,CAAC;AACrB,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IACnC,IAAI,MAAM,KAAK,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,0EAA0E,CAAC,CAAC;IACjH,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACjC,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC7C,MAAM,KAAK,GAAG,cAAc,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IAC9C,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACvD,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { MeshData } from '@ifc-lite/geometry';
2
+ import { type IfcxNode, type IfcxEncodedImage } from '@ifc-lite/ifcx';
3
+ /** Packs canonical mesh fragments without evaluating styles or changing UV mappings. */
4
+ export declare class Ifc5AppearanceWriter {
5
+ private readonly occupiedPaths;
6
+ private readonly originals?;
7
+ readonly images: IfcxNode[];
8
+ private readonly imagePaths;
9
+ private readonly sourcePaths;
10
+ private imageBytes;
11
+ private nextFragment;
12
+ constructor(occupiedPaths: Set<string>, originals?: ReadonlyMap<string, IfcxEncodedImage> | undefined);
13
+ private uniquePath;
14
+ private image;
15
+ fragments(owner: IfcxNode, meshes: MeshData[], convert: (mesh: MeshData) => {
16
+ points: number[][];
17
+ faceVertexIndices: number[];
18
+ }): IfcxNode[];
19
+ }
20
+ //# sourceMappingURL=ifc5-appearance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ifc5-appearance.d.ts","sourceRoot":"","sources":["../src/ifc5-appearance.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAgD,KAAK,QAAQ,EAAmB,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAErI,wFAAwF;AACxF,qBAAa,oBAAoB;IAOnB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAAe,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC;IANpF,QAAQ,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAM;IACjC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA6B;IACxD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA8C;IAC1E,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,YAAY,CAAK;gBAEI,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,EAAmB,SAAS,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,gBAAgB,CAAC,YAAA;IAE3H,OAAO,CAAC,UAAU;IAOlB,OAAO,CAAC,KAAK;IA2Cb,SAAS,CACP,KAAK,EAAE,QAAQ,EACf,MAAM,EAAE,QAAQ,EAAE,EAClB,OAAO,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK;QAAE,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC;QAAC,iBAAiB,EAAE,MAAM,EAAE,CAAA;KAAE,GAC/E,QAAQ,EAAE;CA0Bd"}
@@ -0,0 +1,106 @@
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
+ import { encodeIfcxImage, IFCX_APPEARANCE, IFCX_IMAGE } from '@ifc-lite/ifcx';
5
+ /** Packs canonical mesh fragments without evaluating styles or changing UV mappings. */
6
+ export class Ifc5AppearanceWriter {
7
+ occupiedPaths;
8
+ originals;
9
+ images = [];
10
+ imagePaths = new Map();
11
+ sourcePaths = new WeakMap();
12
+ imageBytes = 0;
13
+ nextFragment = 0;
14
+ constructor(occupiedPaths, originals) {
15
+ this.occupiedPaths = occupiedPaths;
16
+ this.originals = originals;
17
+ }
18
+ uniquePath(proposed) {
19
+ let path = proposed;
20
+ for (let suffix = 1; this.occupiedPaths.has(path); suffix++)
21
+ path = `${proposed}-${suffix}`;
22
+ this.occupiedPaths.add(path);
23
+ return path;
24
+ }
25
+ image(mesh) {
26
+ const source = mesh.texture?.rgba ?? mesh.textureBitmap;
27
+ if (!source)
28
+ throw new Error('Cannot export an unresolved IFCX texture. Load its image before exporting.');
29
+ const dimensions = mesh.texture ?? mesh.textureBitmap;
30
+ const dimensionKey = `${dimensions.width}x${dimensions.height}`;
31
+ const original = (mesh.textureRef ? this.originals?.get(mesh.textureRef.url) : undefined)
32
+ ?? mesh.texture?.original;
33
+ const cached = !original && this.sourcePaths.get(source)?.get(dimensionKey);
34
+ if (cached)
35
+ return cached;
36
+ let pixels;
37
+ if (mesh.texture) {
38
+ pixels = mesh.texture;
39
+ }
40
+ else {
41
+ const bitmap = mesh.textureBitmap;
42
+ if (typeof OffscreenCanvas === 'undefined') {
43
+ throw new Error('IFCX bitmap export requires OffscreenCanvas; headless callers can supply decoded MeshData.texture pixels.');
44
+ }
45
+ if (bitmap.width < 1 || bitmap.height < 1 || bitmap.width > 16_384 || bitmap.height > 16_384
46
+ || bitmap.width * bitmap.height * 4 > 512 * 1024 * 1024)
47
+ throw new Error('IFCX texture exceeds the image budget.');
48
+ const canvas = new OffscreenCanvas(bitmap.width, bitmap.height);
49
+ const context = canvas.getContext('2d');
50
+ if (!context)
51
+ throw new Error('Unable to read the IFCX texture bitmap.');
52
+ context.drawImage(bitmap, 0, 0);
53
+ const data = context.getImageData(0, 0, bitmap.width, bitmap.height).data;
54
+ pixels = { width: bitmap.width, height: bitmap.height,
55
+ rgba: new Uint8Array(data.buffer, data.byteOffset, data.byteLength), repeatS: false, repeatT: false };
56
+ }
57
+ if (original)
58
+ pixels = { ...pixels, original };
59
+ const encoded = encodeIfcxImage(pixels);
60
+ let path = this.imagePaths.get(encoded.key);
61
+ if (!path) {
62
+ if (this.imageBytes + (pixels.rgba.length + (pixels.original?.bytes.length ?? 0)) > 512 * 1024 * 1024)
63
+ throw new Error('IFCX images exceed the 512 MiB file pixel budget.');
64
+ this.imageBytes += pixels.rgba.length + (pixels.original?.bytes.length ?? 0);
65
+ path = this.uniquePath(`ifclite-image-${encoded.key}`);
66
+ this.imagePaths.set(encoded.key, path);
67
+ this.images.push({ path, attributes: { [IFCX_IMAGE]: encoded.value } });
68
+ }
69
+ let sourcePaths = this.sourcePaths.get(source);
70
+ if (!sourcePaths)
71
+ this.sourcePaths.set(source, sourcePaths = new Map());
72
+ if (!original)
73
+ sourcePaths.set(dimensionKey, path);
74
+ return path;
75
+ }
76
+ fragments(owner, meshes, convert) {
77
+ const children = owner.children ??= {};
78
+ return meshes.map((mesh, index) => {
79
+ const path = this.uniquePath(`ifclite-mesh-${this.nextFragment++}`);
80
+ let name = `Appearance ${index + 1}`;
81
+ while (Object.hasOwn(children, name))
82
+ name += '_';
83
+ children[name] = path;
84
+ const [r, g, b, a] = mesh.color;
85
+ const attributes = {
86
+ 'usd::usdgeom::mesh': convert(mesh),
87
+ 'bsi::ifc::presentation::diffuseColor': [r, g, b],
88
+ 'bsi::ifc::presentation::opacity': a,
89
+ };
90
+ const sampler = mesh.texture ?? mesh.textureRef;
91
+ if (sampler) {
92
+ if (typeof sampler.repeatS !== 'boolean' || typeof sampler.repeatT !== 'boolean')
93
+ throw new Error('IFCX texture sampler wraps must be boolean.');
94
+ if (!mesh.uvs || mesh.uvs.length !== mesh.positions.length / 3 * 2
95
+ || !mesh.uvs.every(Number.isFinite))
96
+ throw new Error('Cannot export IFCX texture without a finite UV pair per vertex.');
97
+ attributes[IFCX_APPEARANCE] = {
98
+ image: { ref: this.image(mesh) }, uvs: Array.from(mesh.uvs),
99
+ repeatS: sampler.repeatS, repeatT: sampler.repeatT,
100
+ };
101
+ }
102
+ return { path, attributes };
103
+ });
104
+ }
105
+ }
106
+ //# sourceMappingURL=ifc5-appearance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ifc5-appearance.js","sourceRoot":"","sources":["../src/ifc5-appearance.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,13 @@
1
+ /**
2
+ * Property names that have official IFC5 schema definitions in prop@v5a.ifcx.
3
+ * Source: https://github.com/buildingSMART/ifcx.dev/blob/main/@standards.buildingsmart.org/ifc/core/prop@v5a.ifcx
4
+ *
5
+ * IFC4 properties NOT in this set (e.g. Reference, LoadBearing, ExtendToStructure)
6
+ * must be omitted from IFC5 export — the viewer reports "Missing schema" errors for them.
7
+ *
8
+ * Name and Description are handled separately (always exported), so they're excluded here.
9
+ */
10
+ export declare const IFC5_KNOWN_PROP_NAMES: Set<string>;
1
11
  /** IFCX node in output, matching the shape `collectRequiredImports` scans. */
2
12
  interface IfcxNodeOutputLike {
3
13
  attributes?: Record<string, unknown>;
@@ -28,5 +38,14 @@ export declare function generateUuid(id: number): string;
28
38
  * Uses the IFC type enum lookup for canonical casing (e.g. "IfcRelAggregates", not "Ifcrelaggregates").
29
39
  */
30
40
  export declare function stepTypeToClassName(stepType: string): string;
41
+ /**
42
+ * The exported node path of an entity whose GlobalId is a namespaced path
43
+ * (#4444): a store reconstructed from a shared room keys its entities by room
44
+ * path, `/<slotId>/<GlobalId>`, and an exported file must not carry the
45
+ * room-internal slot. Removes `prefix` when the GlobalId is under it
46
+ * (`/m1/<GlobalId>` → `/<GlobalId>`); any other GlobalId is returned verbatim,
47
+ * so an owner's own STEP-parsed store (bare GlobalIds) is unaffected.
48
+ */
49
+ export declare function stripNodePathPrefix(globalId: string, prefix: string | undefined): string;
31
50
  export {};
32
51
  //# sourceMappingURL=ifc5-export-helpers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ifc5-export-helpers.d.ts","sourceRoot":"","sources":["../src/ifc5-export-helpers.ts"],"names":[],"mappings":"AAWA,8EAA8E;AAC9E,UAAU,kBAAkB;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,qFAAqF;AACrF,eAAO,MAAM,mBAAmB;IAC9B,wGAAwG;;IAExG,wCAAwC;;IAExC,mFAAmF;;CAE3E,CAAC;AAEX;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,kBAAkB,EAAE,GAAG;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,EAAE,CAmCrF;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAG/C;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAU5D"}
1
+ {"version":3,"file":"ifc5-export-helpers.d.ts","sourceRoot":"","sources":["../src/ifc5-export-helpers.ts"],"names":[],"mappings":"AAWA;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB,aAkBhC,CAAC;AAEH,8EAA8E;AAC9E,UAAU,kBAAkB;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,qFAAqF;AACrF,eAAO,MAAM,mBAAmB;IAC9B,wGAAwG;;IAExG,wCAAwC;;IAExC,mFAAmF;;CAE3E,CAAC;AAEX;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,kBAAkB,EAAE,GAAG;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,EAAE,CAmCrF;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAG/C;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAU5D;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAGxF"}
@@ -6,6 +6,34 @@
6
6
  * keep ifc5-exporter.ts under its module-size budget; no behavior change.
7
7
  */
8
8
  import { IfcTypeEnumToString, IfcTypeEnumFromString } from '@ifc-lite/data';
9
+ /**
10
+ * Property names that have official IFC5 schema definitions in prop@v5a.ifcx.
11
+ * Source: https://github.com/buildingSMART/ifcx.dev/blob/main/@standards.buildingsmart.org/ifc/core/prop@v5a.ifcx
12
+ *
13
+ * IFC4 properties NOT in this set (e.g. Reference, LoadBearing, ExtendToStructure)
14
+ * must be omitted from IFC5 export — the viewer reports "Missing schema" errors for them.
15
+ *
16
+ * Name and Description are handled separately (always exported), so they're excluded here.
17
+ */
18
+ export const IFC5_KNOWN_PROP_NAMES = new Set([
19
+ 'UsageType',
20
+ 'TypeName',
21
+ 'IsExternal',
22
+ 'RefElevation',
23
+ 'ElevationOfRefHeight',
24
+ 'ElevationOfTerrain',
25
+ 'NumberOfStoreys',
26
+ 'Height',
27
+ 'Width',
28
+ 'Length',
29
+ 'Depth',
30
+ 'Volume',
31
+ 'NetVolume',
32
+ 'NetArea',
33
+ 'NetSideArea',
34
+ 'CrossSectionArea',
35
+ 'Station',
36
+ ]);
9
37
  /** Standard IFC5 schema package URIs, keyed by the attribute prefix they provide. */
10
38
  export const IFCX_SCHEMA_IMPORTS = {
11
39
  /** Core IFC: bsi::ifc::class, bsi::ifc::presentation::*, bsi::ifc::material, bsi::ifc::spaceBoundary */
@@ -81,4 +109,17 @@ export function stepTypeToClassName(stepType) {
81
109
  }
82
110
  return stepType;
83
111
  }
112
+ /**
113
+ * The exported node path of an entity whose GlobalId is a namespaced path
114
+ * (#4444): a store reconstructed from a shared room keys its entities by room
115
+ * path, `/<slotId>/<GlobalId>`, and an exported file must not carry the
116
+ * room-internal slot. Removes `prefix` when the GlobalId is under it
117
+ * (`/m1/<GlobalId>` → `/<GlobalId>`); any other GlobalId is returned verbatim,
118
+ * so an owner's own STEP-parsed store (bare GlobalIds) is unaffected.
119
+ */
120
+ export function stripNodePathPrefix(globalId, prefix) {
121
+ if (!prefix || !globalId.startsWith(`${prefix}/`))
122
+ return globalId;
123
+ return globalId.slice(prefix.length);
124
+ }
84
125
  //# sourceMappingURL=ifc5-export-helpers.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ifc5-export-helpers.js","sourceRoot":"","sources":["../src/ifc5-export-helpers.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ifc5-export-helpers.js","sourceRoot":"","sources":["../src/ifc5-export-helpers.ts"],"names":[],"mappings":"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"}
@@ -13,18 +13,11 @@
13
13
  import type { IfcDataStore } from '@ifc-lite/parser';
14
14
  import type { MutablePropertyView } from '@ifc-lite/mutations';
15
15
  import type { GeometryResult } from '@ifc-lite/geometry';
16
- /**
17
- * Property names that have official IFC5 schema definitions in prop@v5a.ifcx.
18
- * Source: https://github.com/buildingSMART/ifcx.dev/blob/main/@standards.buildingsmart.org/ifc/core/prop@v5a.ifcx
19
- *
20
- * IFC4 properties NOT in this set (e.g. Reference, LoadBearing, ExtendToStructure)
21
- * must be omitted from IFC5 export — the viewer reports "Missing schema" errors for them.
22
- *
23
- * Name and Description are handled separately (always exported), so they're excluded here.
24
- */
25
- export declare const IFC5_KNOWN_PROP_NAMES: Set<string>;
16
+ import { type IfcxEncodedImage } from '@ifc-lite/ifcx';
26
17
  /** Options for IFC5 export */
27
18
  export interface Ifc5ExportOptions {
19
+ /** Original image bytes keyed by exact MeshTextureRef.url; retained in IFCX without recompression. */
20
+ textureSources?: ReadonlyMap<string, IfcxEncodedImage>;
28
21
  /** Author name */
29
22
  author?: string;
30
23
  /** Data version identifier */
@@ -51,6 +44,14 @@ export interface Ifc5ExportOptions {
51
44
  * When true, relationship entities (IfcRel*), type objects, materials,
52
45
  * and other non-spatial entities are excluded from the output. */
53
46
  onlyTreeEntities?: boolean;
47
+ /**
48
+ * A namespace prefix to remove from GlobalId-derived node paths (#4444). A
49
+ * store reconstructed from a shared room keys its entities by room path,
50
+ * `/<slotId>/<GlobalId>`; the slot is the room's namespace, not the
51
+ * model's, so the exported file carries `/<GlobalId>` — the same paths a
52
+ * single-model room exports. GlobalIds outside the prefix are untouched.
53
+ */
54
+ stripPathPrefix?: string;
54
55
  }
55
56
  /** Result of IFC5 export */
56
57
  export interface Ifc5ExportResult {
@@ -121,6 +122,7 @@ export declare class Ifc5Exporter {
121
122
  * will NOT be emitted as a node (deleted, hidden, or outside the exported
122
123
  * tree). Every step below is driven by it rather than by the deletion
123
124
  * check alone, so the maps can never describe a node `export` never wrote.
125
+ * @param stripPathPrefix see {@link Ifc5ExportOptions.stripPathPrefix}.
124
126
  */
125
127
  private buildEntityMaps;
126
128
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"ifc5-exporter.d.ts","sourceRoot":"","sources":["../src/ifc5-exporter.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,KAAK,EAAY,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAoBnE;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB,aAkBhC,CAAC;AAMH,8BAA8B;AAC9B,MAAM,WAAW,iBAAiB;IAChC,kBAAkB;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8BAA8B;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qDAAqD;IACrD,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,yCAAyC;IACzC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,gEAAgE;IAChE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,wCAAwC;IACxC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,mCAAmC;IACnC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,2CAA2C;IAC3C,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9B,kEAAkE;IAClE,iBAAiB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;IACvC;;yEAEqE;IACrE,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;uEAEmE;IACnE,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,4BAA4B;AAC5B,MAAM,WAAW,gBAAgB;IAC/B,wBAAwB;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB;IACjB,KAAK,EAAE;QACL,SAAS,EAAE,MAAM,CAAC;QAClB,aAAa,EAAE,MAAM,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AA4BD;;GAEG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,SAAS,CAAe;IAChC,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,cAAc,CAAwB;IAC9C,OAAO,CAAC,QAAQ,CAAS;IACzB,6EAA6E;IAC7E,OAAO,CAAC,UAAU,CAA6B;IAC/C,yEAAyE;IACzE,OAAO,CAAC,gBAAgB,CAA6B;IACrD,0CAA0C;IAC1C,OAAO,CAAC,WAAW,CAA6B;IAChD;;;;;;OAMG;IACH,OAAO,CAAC,UAAU,CAA2C;IAC7D;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,iBAAiB,CAAqB;gBAG5C,SAAS,EAAE,YAAY,EACvB,cAAc,CAAC,EAAE,cAAc,GAAG,IAAI,EACtC,YAAY,CAAC,EAAE,mBAAmB,EAClC,QAAQ,CAAC,EAAE,MAAM;IAQnB;;OAEG;IACH,MAAM,CAAC,OAAO,GAAE,iBAAsB,GAAG,gBAAgB;IA2NzD,yDAAyD;IACzD,OAAO,CAAC,eAAe;IAYvB;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,eAAe;IAqJvB;;OAEG;IACH,OAAO,CAAC,sBAAsB;IA8B9B;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAoB5B;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAiC5B;;OAEG;IACH,OAAO,CAAC,eAAe;IAkBvB;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IA+CxB;;;OAGG;IACH,OAAO,CAAC,kBAAkB;IA2B1B;;OAEG;IACH,OAAO,CAAC,eAAe;CAsBxB"}
1
+ {"version":3,"file":"ifc5-exporter.d.ts","sourceRoot":"","sources":["../src/ifc5-exporter.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,KAAK,EAAY,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAUnE,OAAO,EAA2B,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAsBhF,8BAA8B;AAC9B,MAAM,WAAW,iBAAiB;IAChC,sGAAsG;IACtG,cAAc,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IACvD,kBAAkB;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8BAA8B;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qDAAqD;IACrD,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,yCAAyC;IACzC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,gEAAgE;IAChE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,wCAAwC;IACxC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,mCAAmC;IACnC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,2CAA2C;IAC3C,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9B,kEAAkE;IAClE,iBAAiB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;IACvC;;yEAEqE;IACrE,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;uEAEmE;IACnE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,4BAA4B;AAC5B,MAAM,WAAW,gBAAgB;IAC/B,wBAAwB;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB;IACjB,KAAK,EAAE;QACL,SAAS,EAAE,MAAM,CAAC;QAClB,aAAa,EAAE,MAAM,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AA4BD;;GAEG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,SAAS,CAAe;IAChC,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,cAAc,CAAwB;IAC9C,OAAO,CAAC,QAAQ,CAAS;IACzB,6EAA6E;IAC7E,OAAO,CAAC,UAAU,CAA6B;IAC/C,yEAAyE;IACzE,OAAO,CAAC,gBAAgB,CAA6B;IACrD,0CAA0C;IAC1C,OAAO,CAAC,WAAW,CAA6B;IAChD;;;;;;OAMG;IACH,OAAO,CAAC,UAAU,CAA2C;IAC7D;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,iBAAiB,CAAqB;gBAG5C,SAAS,EAAE,YAAY,EACvB,cAAc,CAAC,EAAE,cAAc,GAAG,IAAI,EACtC,YAAY,CAAC,EAAE,mBAAmB,EAClC,QAAQ,CAAC,EAAE,MAAM;IAQnB;;OAEG;IACH,MAAM,CAAC,OAAO,GAAE,iBAAsB,GAAG,gBAAgB;IAmOzD,yDAAyD;IACzD,OAAO,CAAC,eAAe;IAYvB;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,eAAe;IAqJvB;;OAEG;IACH,OAAO,CAAC,sBAAsB;IA8B9B;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAoB5B;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAiC5B;;OAEG;IACH,OAAO,CAAC,eAAe;IAkBvB;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IA+CxB;;;OAGG;IACH,OAAO,CAAC,kBAAkB;IA2B1B;;OAEG;IACH,OAAO,CAAC,eAAe;CAsBxB"}
@@ -4,37 +4,11 @@
4
4
  import { IfcTypeEnumToString, PropertyValueType, IFCX_VERSION, } from '@ifc-lite/data';
5
5
  import { convertEntityType } from './schema-converter.js';
6
6
  import { getEffectiveEntityIndex } from './effective-index.js';
7
+ import { Ifc5AppearanceWriter } from './ifc5-appearance.js';
8
+ import { IFCX_APPEARANCE_SCHEMAS } from '@ifc-lite/ifcx';
7
9
  import { buildMaterialAttribute } from './ifc5-material.js';
8
- import { collectRequiredImports, generateUuid, stepTypeToClassName } from './ifc5-export-helpers.js';
10
+ import { collectRequiredImports, generateUuid, IFC5_KNOWN_PROP_NAMES, stepTypeToClassName, stripNodePathPrefix, } from './ifc5-export-helpers.js';
9
11
  import { addClassificationAttribute } from './ifc5-classification.js';
10
- /**
11
- * Property names that have official IFC5 schema definitions in prop@v5a.ifcx.
12
- * Source: https://github.com/buildingSMART/ifcx.dev/blob/main/@standards.buildingsmart.org/ifc/core/prop@v5a.ifcx
13
- *
14
- * IFC4 properties NOT in this set (e.g. Reference, LoadBearing, ExtendToStructure)
15
- * must be omitted from IFC5 export — the viewer reports "Missing schema" errors for them.
16
- *
17
- * Name and Description are handled separately (always exported), so they're excluded here.
18
- */
19
- export const IFC5_KNOWN_PROP_NAMES = new Set([
20
- 'UsageType',
21
- 'TypeName',
22
- 'IsExternal',
23
- 'RefElevation',
24
- 'ElevationOfRefHeight',
25
- 'ElevationOfTerrain',
26
- 'NumberOfStoreys',
27
- 'Height',
28
- 'Width',
29
- 'Length',
30
- 'Depth',
31
- 'Volume',
32
- 'NetVolume',
33
- 'NetArea',
34
- 'NetSideArea',
35
- 'CrossSectionArea',
36
- 'Station',
37
- ]);
38
12
  // ============================================================================
39
13
  // Exporter
40
14
  // ============================================================================
@@ -111,9 +85,10 @@ export class Ifc5Exporter {
111
85
  || (visibleIds !== null && !visibleIds.has(id))
112
86
  || (treeIds !== null && !treeIds.has(id));
113
87
  // Build UUID paths and child-name maps from spatial hierarchy
114
- this.buildEntityMaps(isOmitted);
88
+ this.buildEntityMaps(isOmitted, options.stripPathPrefix);
115
89
  // Build mesh lookup by expressId
116
90
  const meshByEntity = this.buildMeshLookup(options);
91
+ const appearance = new Ifc5AppearanceWriter(new Set(this.entityUuids.values()), options.textureSources);
117
92
  // Collect nodes
118
93
  const nodes = [];
119
94
  /** expressIds that actually became nodes — the root node may only point at these. */
@@ -184,15 +159,21 @@ export class Ifc5Exporter {
184
159
  if (options.includeGeometry !== false) {
185
160
  const meshes = meshByEntity.get(expressId);
186
161
  if (meshes && meshes.length > 0) {
187
- const usdMesh = this.convertToUsdMesh(meshes);
188
- attributes['usd::usdgeom::mesh'] = usdMesh;
189
- // Color/presentation
190
- const [r, g, b, a] = meshes[0].color;
191
- attributes['bsi::ifc::presentation::diffuseColor'] = [r, g, b];
192
- if (a < 1.0) {
193
- attributes['bsi::ifc::presentation::opacity'] = a;
162
+ if (meshes.some((mesh) => mesh.texture || mesh.textureRef)) {
163
+ nodes.push(...appearance.fragments(node, meshes, (mesh) => this.convertToUsdMesh([mesh])));
164
+ meshCount += meshes.length;
165
+ }
166
+ else {
167
+ const usdMesh = this.convertToUsdMesh(meshes);
168
+ attributes['usd::usdgeom::mesh'] = usdMesh;
169
+ // Color/presentation
170
+ const [r, g, b, a] = meshes[0].color;
171
+ attributes['bsi::ifc::presentation::diffuseColor'] = [r, g, b];
172
+ if (a < 1.0) {
173
+ attributes['bsi::ifc::presentation::opacity'] = a;
174
+ }
175
+ meshCount++;
194
176
  }
195
- meshCount++;
196
177
  }
197
178
  }
198
179
  if (Object.keys(attributes).length > 0)
@@ -238,6 +219,7 @@ export class Ifc5Exporter {
238
219
  attributes: {},
239
220
  });
240
221
  }
222
+ nodes.push(...appearance.images);
241
223
  // Determine required imports by scanning which attribute namespaces are used
242
224
  const imports = collectRequiredImports(nodes);
243
225
  // Assemble IFCX file
@@ -250,7 +232,7 @@ export class Ifc5Exporter {
250
232
  timestamp: new Date().toISOString(),
251
233
  },
252
234
  imports,
253
- schemas: {},
235
+ schemas: appearance.images.length ? IFCX_APPEARANCE_SCHEMAS : {},
254
236
  data: nodes,
255
237
  };
256
238
  const content = options.prettyPrint !== false
@@ -291,8 +273,9 @@ export class Ifc5Exporter {
291
273
  * will NOT be emitted as a node (deleted, hidden, or outside the exported
292
274
  * tree). Every step below is driven by it rather than by the deletion
293
275
  * check alone, so the maps can never describe a node `export` never wrote.
276
+ * @param stripPathPrefix see {@link Ifc5ExportOptions.stripPathPrefix}.
294
277
  */
295
- buildEntityMaps(isOmitted) {
278
+ buildEntityMaps(isOmitted, stripPathPrefix) {
296
279
  const { spatialHierarchy, entities, strings } = this.dataStore;
297
280
  // --- 1. Assign UUID paths ---
298
281
  // An omitted entity gets no UUID entry. `getChildrenForEntity`'s `addChild`
@@ -308,7 +291,7 @@ export class Ifc5Exporter {
308
291
  continue;
309
292
  // Use IFC GlobalId if available, otherwise generate a deterministic UUID
310
293
  const globalId = strings.get(entities.globalId[i]);
311
- this.entityUuids.set(id, globalId || generateUuid(id));
294
+ this.entityUuids.set(id, globalId ? stripNodePathPrefix(globalId, stripPathPrefix) : generateUuid(id));
312
295
  }
313
296
  // --- 2. Build parent→children and spatial maps ---
314
297
  const parentOf = new Map();