@ifc-lite/export 3.0.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/README.md +34 -0
  2. package/dist/anonymize-export.d.ts +60 -0
  3. package/dist/anonymize-export.d.ts.map +1 -0
  4. package/dist/anonymize-export.js +117 -0
  5. package/dist/anonymize-export.js.map +1 -0
  6. package/dist/anonymize-placement.d.ts +71 -0
  7. package/dist/anonymize-placement.d.ts.map +1 -0
  8. package/dist/anonymize-placement.js +266 -0
  9. package/dist/anonymize-placement.js.map +1 -0
  10. package/dist/anonymize-scrub.d.ts +64 -0
  11. package/dist/anonymize-scrub.d.ts.map +1 -0
  12. package/dist/anonymize-scrub.js +312 -0
  13. package/dist/anonymize-scrub.js.map +1 -0
  14. package/dist/anonymize-types.d.ts +212 -0
  15. package/dist/anonymize-types.d.ts.map +1 -0
  16. package/dist/anonymize-types.js +5 -0
  17. package/dist/anonymize-types.js.map +1 -0
  18. package/dist/declared-property-type.d.ts +19 -8
  19. package/dist/declared-property-type.d.ts.map +1 -1
  20. package/dist/declared-property-type.js +31 -9
  21. package/dist/declared-property-type.js.map +1 -1
  22. package/dist/entity-type-sets.d.ts +47 -0
  23. package/dist/entity-type-sets.d.ts.map +1 -0
  24. package/dist/entity-type-sets.js +91 -0
  25. package/dist/entity-type-sets.js.map +1 -0
  26. package/dist/index.d.ts +3 -0
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +5 -0
  29. package/dist/index.js.map +1 -1
  30. package/dist/merged-exporter.d.ts +19 -0
  31. package/dist/merged-exporter.d.ts.map +1 -1
  32. package/dist/merged-exporter.js +1 -1
  33. package/dist/merged-exporter.js.map +1 -1
  34. package/dist/parquet-exporter.d.ts +1 -3
  35. package/dist/parquet-exporter.d.ts.map +1 -1
  36. package/dist/parquet-exporter.js +11 -10
  37. package/dist/parquet-exporter.js.map +1 -1
  38. package/dist/property-value-serialization.d.ts +54 -0
  39. package/dist/property-value-serialization.d.ts.map +1 -0
  40. package/dist/property-value-serialization.js +134 -0
  41. package/dist/property-value-serialization.js.map +1 -0
  42. package/dist/reference-collector.d.ts +47 -0
  43. package/dist/reference-collector.d.ts.map +1 -1
  44. package/dist/reference-collector.js +88 -156
  45. package/dist/reference-collector.js.map +1 -1
  46. package/dist/related-entities.d.ts +10 -0
  47. package/dist/related-entities.d.ts.map +1 -0
  48. package/dist/related-entities.js +259 -0
  49. package/dist/related-entities.js.map +1 -0
  50. package/dist/schema-converter.d.ts.map +1 -1
  51. package/dist/schema-converter.js +46 -96
  52. package/dist/schema-converter.js.map +1 -1
  53. package/dist/source-ref-bounds.d.ts +3 -3
  54. package/dist/source-ref-bounds.js +3 -3
  55. package/dist/step-attribute-mutations.d.ts +0 -42
  56. package/dist/step-attribute-mutations.d.ts.map +1 -1
  57. package/dist/step-attribute-mutations.js +17 -147
  58. package/dist/step-attribute-mutations.js.map +1 -1
  59. package/dist/step-attribute-serializers.d.ts +41 -0
  60. package/dist/step-attribute-serializers.d.ts.map +1 -0
  61. package/dist/step-attribute-serializers.js +74 -0
  62. package/dist/step-attribute-serializers.js.map +1 -0
  63. package/dist/step-collection.d.ts +2 -2
  64. package/dist/step-collection.d.ts.map +1 -1
  65. package/dist/step-collection.js +38 -8
  66. package/dist/step-collection.js.map +1 -1
  67. package/dist/step-export-contexts.d.ts +5 -7
  68. package/dist/step-export-contexts.d.ts.map +1 -1
  69. package/dist/step-export-contexts.js +6 -7
  70. package/dist/step-export-contexts.js.map +1 -1
  71. package/dist/step-export-types.d.ts +27 -0
  72. package/dist/step-export-types.d.ts.map +1 -1
  73. package/dist/step-export-types.js.map +1 -1
  74. package/dist/step-exporter.d.ts +3 -3
  75. package/dist/step-exporter.js +4 -4
  76. package/dist/step-exporter.js.map +1 -1
  77. package/dist/step-geometry-types.d.ts +1 -17
  78. package/dist/step-geometry-types.d.ts.map +1 -1
  79. package/dist/step-geometry-types.js +51 -35
  80. package/dist/step-geometry-types.js.map +1 -1
  81. package/dist/step-georeferencing.d.ts +0 -10
  82. package/dist/step-georeferencing.d.ts.map +1 -1
  83. package/dist/step-georeferencing.js +46 -94
  84. package/dist/step-georeferencing.js.map +1 -1
  85. package/dist/step-header.d.ts +11 -1
  86. package/dist/step-header.d.ts.map +1 -1
  87. package/dist/step-header.js +2 -9
  88. package/dist/step-header.js.map +1 -1
  89. package/dist/step-map-unit.d.ts +90 -0
  90. package/dist/step-map-unit.d.ts.map +1 -0
  91. package/dist/step-map-unit.js +277 -0
  92. package/dist/step-map-unit.js.map +1 -0
  93. package/dist/step-overlay-attribute-overrides.d.ts +32 -0
  94. package/dist/step-overlay-attribute-overrides.d.ts.map +1 -0
  95. package/dist/step-overlay-attribute-overrides.js +83 -0
  96. package/dist/step-overlay-attribute-overrides.js.map +1 -0
  97. package/dist/step-overlay-entities.d.ts +3 -3
  98. package/dist/step-pass-builder.d.ts +4 -3
  99. package/dist/step-pass-builder.d.ts.map +1 -1
  100. package/dist/step-pass-builder.js.map +1 -1
  101. package/dist/step-property-set-collection.d.ts +24 -0
  102. package/dist/step-property-set-collection.d.ts.map +1 -0
  103. package/dist/step-property-set-collection.js +286 -0
  104. package/dist/step-property-set-collection.js.map +1 -0
  105. package/dist/step-property-set-generators.d.ts +20 -0
  106. package/dist/step-property-set-generators.d.ts.map +1 -0
  107. package/dist/step-property-set-generators.js +98 -0
  108. package/dist/step-property-set-generators.js.map +1 -0
  109. package/dist/step-property-set-index.d.ts +25 -0
  110. package/dist/step-property-set-index.d.ts.map +1 -0
  111. package/dist/step-property-set-index.js +69 -0
  112. package/dist/step-property-set-index.js.map +1 -0
  113. package/dist/step-property-set-readers.d.ts +158 -0
  114. package/dist/step-property-set-readers.d.ts.map +1 -0
  115. package/dist/step-property-set-readers.js +251 -0
  116. package/dist/step-property-set-readers.js.map +1 -0
  117. package/dist/step-property-sets.d.ts +2 -186
  118. package/dist/step-property-sets.d.ts.map +1 -1
  119. package/dist/step-property-sets.js +22 -674
  120. package/dist/step-property-sets.js.map +1 -1
  121. package/dist/step-serialization.d.ts +17 -51
  122. package/dist/step-serialization.d.ts.map +1 -1
  123. package/dist/step-serialization.js +19 -128
  124. package/dist/step-serialization.js.map +1 -1
  125. package/dist/step-source-iteration.d.ts +7 -5
  126. package/dist/step-source-iteration.d.ts.map +1 -1
  127. package/dist/step-source-iteration.js +3 -3
  128. package/dist/step-source-iteration.js.map +1 -1
  129. package/dist/subset-entity-reader.d.ts +103 -0
  130. package/dist/subset-entity-reader.d.ts.map +1 -0
  131. package/dist/subset-entity-reader.js +102 -0
  132. package/dist/subset-entity-reader.js.map +1 -0
  133. package/dist/subset-roots.d.ts +58 -0
  134. package/dist/subset-roots.d.ts.map +1 -0
  135. package/dist/subset-roots.js +103 -0
  136. package/dist/subset-roots.js.map +1 -0
  137. package/package.json +7 -7
@@ -0,0 +1,286 @@
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 { extractQuantitiesOnDemand } from '@ifc-lite/parser';
5
+ import { isTypeClass } from './type-owned-psets.js';
6
+ import { getPropertySetName, getPropertyIdsInSet, getTypeOwnedHasPropertySetIds, getElementQuantityName, } from './step-property-set-readers.js';
7
+ /**
8
+ * The store the extractor THIS class installed on a view currently reads
9
+ * (#2487). The extractor is installed once per view and closes over this box
10
+ * rather than over a store directly, so a later export of the same view against
11
+ * a different store re-points it instead of answering from the first file.
12
+ *
13
+ * A box, and not a `WeakSet` of views, because ownership has to reflect the
14
+ * CURRENT state and not the historical fact that an export once installed
15
+ * something. `setQuantityExtractor` is public: a caller may install its own
16
+ * afterwards, and a marker saying "the exporter owns this view" would then keep
17
+ * overwriting a caller-supplied base forever. With a box, the second export
18
+ * writes to a box nothing reads any more and never calls the setter again, so
19
+ * the caller's extractor stands. Weak, so it never keeps a session alive.
20
+ */
21
+ const exporterQuantityBase = new WeakMap();
22
+ /**
23
+ * Collect what the overlay's property-set and quantity-set edits mean for this
24
+ * export: which sets to regenerate (`pass.newPropertySets` /
25
+ * `pass.newQuantitySets`), which source records to withhold
26
+ * (`pass.skipPropertySetIds` / `pass.skipRelationshipIds`), and which type
27
+ * objects need their `HasPropertySets` resolved later
28
+ * (`pass.typeOwnedPsetNamesByEntity`, `…IdsByEntity`, `pass.rewrittenEntityIds`).
29
+ *
30
+ * The caller owns the `mutationView && options.applyMutations !== false` gate;
31
+ * reaching here means overlay edits were both present and enabled.
32
+ */
33
+ export function collectPropertyAndQuantitySetMutations(pass, options, groups, ctx) {
34
+ const { entityPropMutations, entityQuantMutations, relDefinesByEntity } = groups;
35
+ // `export()` narrowed this through the enclosing `if`, and the caller still
36
+ // owns that gate: reaching here means the view exists and mutations are
37
+ // enabled. Named once here rather than asserted at each of the six reads.
38
+ const mutationView = ctx.mutationView;
39
+ // Collect modified property sets and find original psets to skip
40
+ for (const [entityId, psetNames] of entityPropMutations) {
41
+ // A deleted entity must not cause the exporter to REMOVE anything.
42
+ //
43
+ // This is the other half of the dangling-reference class, and the half
44
+ // `willBeEmitted` cannot reach: that predicate guards what gets ADDED,
45
+ // and this loop's real work is deciding what gets SKIPPED. An edited
46
+ // pset is replaced wholesale, so its original id goes into
47
+ // `skipPropertySetIds` — but IFC exporters share one IfcPropertySet
48
+ // between entities, and once the host is deleted there is no
49
+ // replacement to take its place. The surviving entity's relation then
50
+ // points at a container nobody wrote. Verified against main at
51
+ // e6516991 (#2030's own merge): edit `Pset_WallCommon` on one of two
52
+ // walls sharing it, delete that wall, and the export drops #11 while
53
+ // #12 still names it. `retainSharedAtoms` rescues a shared ATOM one
54
+ // level down; nothing rescues the shared container.
55
+ //
56
+ // Leaving the pset alone makes it an orphan when nothing else
57
+ // references it, which is valid IFC. Its relation is dropped by the
58
+ // sweep above, which handles a plain delete too — no pset edit needed.
59
+ if (pass.effective.isDeleted(entityId))
60
+ continue;
61
+ pass.modifiedEntities.add(entityId);
62
+ // Same rule as the attribute loop below: an overlay-CREATED entity is
63
+ // emitted once, by the new-entities pass, and already counted in
64
+ // `newEntityCount` — as are the pset entities this loop goes on to
65
+ // generate. Only the COUNT is guarded; the entity still records its
66
+ // pset edits and still emits them.
67
+ //
68
+ // A NOMINATION, in both modes, never a count on its own: this site sees
69
+ // a pset NAME the session touched, not whether that name resolves to
70
+ // anything. `deletePropertySet(id, 'AName')` on a host that owns no such
71
+ // set reaches here and changes nothing at all, and used to put "1
72
+ // modification" in the header of a byte-identical file (#2474). What
73
+ // settles it is the generator's `recordEmitted` and the skip branches'
74
+ // `recordWithheld` below.
75
+ if (!pass.isOverlayCreated(entityId) && pass.hasEmittableHostBytes(entityId)) {
76
+ pass.modifications.nominate(entityId, 'property-set');
77
+ }
78
+ // Get the FULL mutated property sets for this entity (merged base + mutations)
79
+ const allPsets = mutationView.getForEntity(entityId);
80
+ const relevantPsets = allPsets.filter((pset) => psetNames.has(pset.name));
81
+ const relDefinedPsetNames = new Set();
82
+ if (relevantPsets.length > 0) {
83
+ pass.newPropertySets.push({ entityId, psets: relevantPsets });
84
+ }
85
+ // Find original property set IDs and relationship IDs to skip — look
86
+ // up only the IfcRelDefinesByProperties rels that reference this entity.
87
+ const rels = relDefinesByEntity.get(entityId);
88
+ if (rels) {
89
+ for (const { relId, psetId: relatedPsetId } of rels) {
90
+ // Check if this pset is one we're modifying
91
+ const psetName = getPropertySetName(ctx, relatedPsetId);
92
+ if (psetName) {
93
+ relDefinedPsetNames.add(psetName);
94
+ }
95
+ if (psetName && psetNames.has(psetName)) {
96
+ pass.skipRelationshipIds.add(relId);
97
+ pass.skipPropertySetIds.add(relatedPsetId);
98
+ // Also skip the individual properties in this pset
99
+ const propIds = getPropertyIdsInSet(ctx, relatedPsetId);
100
+ for (const propId of propIds) {
101
+ pass.skipPropertySetIds.add(propId);
102
+ }
103
+ // The other half of "did this edit change the file": a full export
104
+ // applies a set DELETION by leaving these lines out, and produces
105
+ // no replacement content to record an emission for. Without this
106
+ // the count would settle from the generator alone and a real
107
+ // deletion would stop counting along with the no-op one (#2474).
108
+ pass.modifications.recordWithheld(entityId, 'property-set');
109
+ }
110
+ }
111
+ }
112
+ if (isTypeClass(pass.effective.typeOf(entityId))) {
113
+ const typeOwnedPsetIds = getTypeOwnedHasPropertySetIds(ctx, entityId, pass.effective);
114
+ const typeOwnedAffected = new Set();
115
+ for (const psetId of typeOwnedPsetIds) {
116
+ const psetName = getPropertySetName(ctx, psetId);
117
+ if (!psetName || !psetNames.has(psetName))
118
+ continue;
119
+ typeOwnedAffected.add(psetName);
120
+ pass.skipPropertySetIds.add(psetId);
121
+ const propIds = getPropertyIdsInSet(ctx, psetId);
122
+ for (const propId of propIds) {
123
+ pass.skipPropertySetIds.add(propId);
124
+ }
125
+ // No `recordWithheld` twin of the rel-defined branch above, and
126
+ // deliberately: a name that matches an OWNED pset is either dropped
127
+ // from the resolved list or swapped for the replacement this export
128
+ // generated, so slot 5 always comes back different and the repoint
129
+ // below records the emission for it. A second record here would be
130
+ // one no mutation can kill.
131
+ }
132
+ for (const psetName of psetNames) {
133
+ if (!relDefinedPsetNames.has(psetName)) {
134
+ typeOwnedAffected.add(psetName);
135
+ }
136
+ }
137
+ if (typeOwnedAffected.size > 0) {
138
+ pass.typeOwnedPsetNamesByEntity.set(entityId, typeOwnedAffected);
139
+ pass.typeOwnedPsetIdsByEntity.set(entityId, typeOwnedPsetIds);
140
+ pass.rewrittenEntityIds.add(entityId);
141
+ }
142
+ }
143
+ }
144
+ // Collect modified quantity sets (only if quantities are included)
145
+ if (options.includeQuantities === false)
146
+ entityQuantMutations.clear();
147
+ // A quantity overlay with nothing under it regenerates a source quantity
148
+ // set from the edited quantity ALONE, and the skip loop below then
149
+ // withholds the source lines that held its siblings (#2487). Unlike
150
+ // properties — whose base falls back to the `baseTable` the view was
151
+ // constructed with — quantities have only the opt-in
152
+ // `setQuantityExtractor`, so the default really is an empty base, and
153
+ // four in-tree callers plus every external embedder never set it.
154
+ //
155
+ // The exporter is the one place that always holds the missing half: it
156
+ // was handed the very store the view is an overlay ON. Supplying it here
157
+ // makes the loss impossible for every caller rather than for the callers
158
+ // we happened to find, and a view that resolves its own quantities (the
159
+ // viewer, MCP, the CLI headless backend) is never overwritten.
160
+ //
161
+ // The extractor closes over ONE store, and the view outlives this export.
162
+ // So it closes over a BOX this class owns instead: a second export of the
163
+ // same view against a DIFFERENT store re-points that box rather than
164
+ // reading the first store's quantities, which is the one way "install only
165
+ // when absent" could have answered from the wrong file. The setter is
166
+ // called at most once per view, so a caller that installs its own
167
+ // extractor at any point — before the first export or after it — keeps it.
168
+ //
169
+ // `hasQuantityBase` and `setQuantityExtractor` are probed, like every other
170
+ // optional view capability this class reaches for (`peekNextExpressId`,
171
+ // `getNewEntities`, `getEntityTypeMutation`): `MutablePropertyView` is
172
+ // published API arriving from a separately versioned package, and callers
173
+ // pass partial and duck-typed views. `hasQuantityBase` is newer than
174
+ // `setQuantityExtractor`, and without it there is no way to tell an empty
175
+ // base from a caller-supplied one — so an older view falls back to the
176
+ // pre-#2487 behaviour (no base supplied) rather than risk overwriting one.
177
+ const quantityView = mutationView;
178
+ if (entityQuantMutations.size > 0 &&
179
+ typeof quantityView.setQuantityExtractor === 'function' &&
180
+ typeof quantityView.hasQuantityBase === 'function') {
181
+ const installed = exporterQuantityBase.get(quantityView);
182
+ if (installed) {
183
+ // Ours, or a caller's that replaced ours: re-pointing the box is a
184
+ // no-op in the second case, and calling the setter again is what
185
+ // would not be.
186
+ installed.store = ctx.dataStore;
187
+ }
188
+ else if (!quantityView.hasQuantityBase()) {
189
+ const box = { store: ctx.dataStore };
190
+ exporterQuantityBase.set(quantityView, box);
191
+ quantityView.setQuantityExtractor((id) => extractQuantitiesOnDemand(box.store, id));
192
+ }
193
+ }
194
+ for (const [entityId, qsetNames] of entityQuantMutations) {
195
+ // Same rule as the property loop above: a deleted entity removes nothing.
196
+ if (pass.effective.isDeleted(entityId))
197
+ continue;
198
+ pass.modifiedEntities.add(entityId);
199
+ // See the property loop above — an overlay-created entity is counted as
200
+ // new, not modified. The pset loop's own nomination no longer has to be
201
+ // excluded to avoid a double count: the ledger settles per ENTITY, so a
202
+ // host with both a pset and a qset edit counts once whatever is
203
+ // nominated. Nominating both buys the opposite — an accurate warning
204
+ // when the qset half is the half a delta cannot carry.
205
+ //
206
+ // Settled from effect like its property-set twin (#2474). The reachable
207
+ // no-op here is an UNDONE quantity-set creation whose name matches NO
208
+ // source set: `getMutations()` is append-only, so the `CREATE_QUANTITY`
209
+ // record still names the qset after `removeQuantityMutation` has taken
210
+ // it out of the overlay, and the generator below then finds nothing to
211
+ // write. The same undo against a COLLIDING name is not a no-op — it
212
+ // withholds the source set's lines — which is what the skip loop's
213
+ // `recordWithheld` below settles.
214
+ if (!pass.isOverlayCreated(entityId) && pass.hasEmittableHostBytes(entityId)) {
215
+ pass.modifications.nominate(entityId, 'quantity-set');
216
+ }
217
+ const allQsets = mutationView.getQuantitiesForEntity(entityId);
218
+ const relevantQsets = allQsets.filter((qset) => qsetNames.has(qset.name));
219
+ if (relevantQsets.length > 0) {
220
+ pass.newQuantitySets.push({ entityId, qsets: relevantQsets });
221
+ }
222
+ // The names this export is actually WRITING a replacement for. The
223
+ // affected-name set is not the same thing: it comes from the session's
224
+ // append-only mutation history, which keeps naming a quantity set after
225
+ // an undo has taken it back out of the overlay, so a Ctrl+Z used to
226
+ // withhold a source `IfcElementQuantity` that nothing regenerated.
227
+ //
228
+ // A quantity-set REMOVAL is the one case where withholding WITHOUT a
229
+ // replacement is the intent rather than the bug. It had no public
230
+ // populator when #2487 wrote that rule, so the rule read "always the
231
+ // bug"; `MutablePropertyView.deleteQuantitySet` (#2508) gives it one,
232
+ // and the deleted set is now asked for by name below. Without that, the
233
+ // panel hid a base quantity set the exported file still carried.
234
+ const regeneratedQsetNames = new Set(relevantQsets.map((qset) => qset.name));
235
+ // Skip original quantity set entities (IfcElementQuantity).
236
+ // Same per-entity index lookup as the property branch above.
237
+ const rels = relDefinesByEntity.get(entityId);
238
+ if (rels) {
239
+ for (const { relId, psetId: relatedPsetId } of rels) {
240
+ const qsetName = getElementQuantityName(ctx, relatedPsetId);
241
+ const deleted = qsetName !== null
242
+ && mutationView.isQuantitySetDeleted?.(entityId, qsetName) === true;
243
+ if (qsetName && (regeneratedQsetNames.has(qsetName) || deleted)) {
244
+ pass.skipRelationshipIds.add(relId);
245
+ pass.skipPropertySetIds.add(relatedPsetId);
246
+ const quantIds = getPropertyIdsInSet(ctx, relatedPsetId);
247
+ for (const quantId of quantIds) {
248
+ pass.skipPropertySetIds.add(quantId);
249
+ }
250
+ // The withheld half, exactly as the rel-defined property branch
251
+ // above. This loop has just decided that #`relatedPsetId`, its
252
+ // quantity atoms and the relationship that attached them do NOT
253
+ // go into the file; whether anything is generated to take their
254
+ // place is decided elsewhere, and is not this branch's to assume.
255
+ //
256
+ // It IS assumable for the pset side and not here, and the
257
+ // difference is where the two read their base from.
258
+ // `getForEntity` merges the overlay over the base pset walk, so a
259
+ // name the session touched but did not change still resolves to
260
+ // source content and is regenerated.
261
+ // `getQuantitiesForEntity` merges the overlay over
262
+ // `quantityExtractor`, which is OPT-IN: it defaults to null, and
263
+ // several in-tree callers wire the property extractor beside it
264
+ // and not it (`cli/commands/mutate.ts`, `gym.ts`,
265
+ // `generate-spaces.ts`, `export/demesh-session.ts`), as does any
266
+ // external embedder of these two published packages. With no
267
+ // extractor the base is empty and the overlay is the only source,
268
+ // so a qset the overlay no longer holds resolves to nothing.
269
+ //
270
+ // Which makes this reachable through an UNDONE quantity-set
271
+ // creation whose name COLLIDES with a source set:
272
+ // `setQuantity(id, 'Qto_WallBaseQuantities', ...)` followed by the
273
+ // `removeQuantityMutation` that mutationSlice runs on Ctrl+Z. The
274
+ // append-only history still names the qset, so this branch
275
+ // withholds the source lines; the overlay is empty again, so
276
+ // nothing is regenerated. The export drops the source quantity set
277
+ // — a real change to the file, and a data-loss bug of its own
278
+ // (#2487) — and this call is what stops the count from calling it
279
+ // nothing.
280
+ pass.modifications.recordWithheld(entityId, 'quantity-set');
281
+ }
282
+ }
283
+ }
284
+ }
285
+ }
286
+ //# sourceMappingURL=step-property-set-collection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"step-property-set-collection.js","sourceRoot":"","sources":["../src/step-property-set-collection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { PropertySet, QuantitySet } from '@ifc-lite/data';
2
+ import type { RandomSource } from '@ifc-lite/encoding';
3
+ import type { EffectiveEntityIndex } from './effective-index.js';
4
+ import { type PropertySetContext } from './step-property-set-readers.js';
5
+ /**
6
+ * Generate STEP entities for property sets
7
+ */
8
+ export declare function generatePropertySetEntities(ctx: PropertySetContext, entityId: number, psets: PropertySet[], willBeEmitted: (id: number) => boolean, effective: EffectiveEntityIndex, typeOwnedPsetNames?: Set<string>, random?: RandomSource): {
9
+ lines: string[];
10
+ count: number;
11
+ generatedTypeOwnedPsetIds: Map<string, number>;
12
+ };
13
+ /**
14
+ * Generate STEP entities for quantity sets (IfcElementQuantity)
15
+ */
16
+ export declare function generateQuantitySetEntities(ctx: PropertySetContext, entityId: number, qsets: QuantitySet[], willBeEmitted: (id: number) => boolean, random?: RandomSource): {
17
+ lines: string[];
18
+ count: number;
19
+ };
20
+ //# sourceMappingURL=step-property-set-generators.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"step-property-set-generators.d.ts","sourceRoot":"","sources":["../src/step-property-set-generators.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC/D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAGjE,OAAO,EACL,KAAK,kBAAkB,EAIxB,MAAM,gCAAgC,CAAC;AAExC;;GAEG;AACH,wBAAgB,2BAA2B,CACzC,GAAG,EAAE,kBAAkB,EACvB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,WAAW,EAAE,EACpB,aAAa,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,EACtC,SAAS,EAAE,oBAAoB,EAC/B,kBAAkB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,EAChC,MAAM,CAAC,EAAE,YAAY,GACpB;IAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,yBAAyB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CAsDpF;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CACzC,GAAG,EAAE,kBAAkB,EACvB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,WAAW,EAAE,EACpB,aAAa,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,EACtC,MAAM,CAAC,EAAE,YAAY,GACpB;IAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAwCpC"}
@@ -0,0 +1,98 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ /**
5
+ * The STEP-entity generators for property sets and quantity sets: the two
6
+ * loops the property-set/quantity-set collection phase's output
7
+ * (`pass.newPropertySets` / `pass.newQuantitySets`) is fed through. Split
8
+ * out of `step-property-sets.ts` (#3184).
9
+ */
10
+ import { serializeValue, ref } from '@ifc-lite/parser';
11
+ import { escapeStepString, toStepReal, quantityTypeToIfcType } from './step-serialization.js';
12
+ import { serializeNominalValue } from './declared-property-type.js';
13
+ import { findUnitId, generateGlobalId, resolveOwnerHistoryRef, } from './step-property-set-readers.js';
14
+ /**
15
+ * Generate STEP entities for property sets
16
+ */
17
+ export function generatePropertySetEntities(ctx, entityId, psets, willBeEmitted, effective, typeOwnedPsetNames, random) {
18
+ const lines = [];
19
+ let count = 0;
20
+ const generatedTypeOwnedPsetIds = new Map();
21
+ for (const pset of psets) {
22
+ const propertyIds = [];
23
+ // Create IfcPropertySingleValue for each property
24
+ for (const prop of pset.properties) {
25
+ const propId = ctx.allocateExpressId();
26
+ count++;
27
+ // `prop.dataType`, not `prop.type` alone: regenerating the set rewrites
28
+ // every property in it, and the shape-derived primitive would re-declare
29
+ // the ones nobody edited (`IFCTEXT` → `IFCLABEL`, `IFCLENGTHMEASURE` →
30
+ // `IFCREAL`). See `declared-property-type.ts` for when the source token
31
+ // is trusted (#2482).
32
+ const valueStr = serializeNominalValue(prop.value, prop.type, prop.dataType);
33
+ const unitId = prop.unit ? findUnitId(ctx, prop.unit, effective) : null;
34
+ const unitStr = unitId !== null ? ref(unitId) : null;
35
+ // #ID=IFCPROPERTYSINGLEVALUE('Name',$,Value,Unit);
36
+ const line = `#${propId}=IFCPROPERTYSINGLEVALUE('${escapeStepString(prop.name)}',$,${valueStr},${unitStr ? serializeValue(unitStr) : '$'});`;
37
+ lines.push(line);
38
+ propertyIds.push(propId);
39
+ }
40
+ // Create IfcPropertySet
41
+ const psetId = ctx.allocateExpressId();
42
+ count++;
43
+ const propRefs = propertyIds.map(id => `#${id}`).join(',');
44
+ const globalId = generateGlobalId(random);
45
+ // #ID=IFCPROPERTYSET('GlobalId',#ownerHistory,'Name',$,(#props));
46
+ const psetLine = `#${psetId}=IFCPROPERTYSET('${globalId}',${resolveOwnerHistoryRef(ctx, entityId, willBeEmitted)},'${escapeStepString(pset.name)}',$,(${propRefs}));`;
47
+ lines.push(psetLine);
48
+ if (typeOwnedPsetNames?.has(pset.name)) {
49
+ generatedTypeOwnedPsetIds.set(pset.name, psetId);
50
+ }
51
+ else {
52
+ // Create IfcRelDefinesByProperties to link pset to entity
53
+ const relId = ctx.allocateExpressId();
54
+ count++;
55
+ const relGlobalId = generateGlobalId(random);
56
+ // #ID=IFCRELDEFINESBYPROPERTIES('GlobalId',#ownerHistory,$,$,(#entity),#pset);
57
+ const relLine = `#${relId}=IFCRELDEFINESBYPROPERTIES('${relGlobalId}',${resolveOwnerHistoryRef(ctx, entityId, willBeEmitted)},$,$,(#${entityId}),#${psetId});`;
58
+ lines.push(relLine);
59
+ }
60
+ }
61
+ return { lines, count, generatedTypeOwnedPsetIds };
62
+ }
63
+ /**
64
+ * Generate STEP entities for quantity sets (IfcElementQuantity)
65
+ */
66
+ export function generateQuantitySetEntities(ctx, entityId, qsets, willBeEmitted, random) {
67
+ const lines = [];
68
+ let count = 0;
69
+ for (const qset of qsets) {
70
+ const quantityIds = [];
71
+ for (const q of qset.quantities) {
72
+ const qId = ctx.allocateExpressId();
73
+ count++;
74
+ const ifcType = quantityTypeToIfcType(q.type);
75
+ // #ID=IFCQUANTITYLENGTH('Name',$,$,Value,$);
76
+ const val = toStepReal(q.value);
77
+ const line = `#${qId}=${ifcType}('${escapeStepString(q.name)}',$,$,${val},$);`;
78
+ lines.push(line);
79
+ quantityIds.push(qId);
80
+ }
81
+ // Create IfcElementQuantity
82
+ const qsetId = ctx.allocateExpressId();
83
+ count++;
84
+ const quantRefs = quantityIds.map(id => `#${id}`).join(',');
85
+ const globalId = generateGlobalId(random);
86
+ // #ID=IFCELEMENTQUANTITY('GlobalId',#ownerHistory,'Name',$,$,(#quants));
87
+ const qsetLine = `#${qsetId}=IFCELEMENTQUANTITY('${globalId}',${resolveOwnerHistoryRef(ctx, entityId, willBeEmitted)},'${escapeStepString(qset.name)}',$,$,(${quantRefs}));`;
88
+ lines.push(qsetLine);
89
+ // Create IfcRelDefinesByProperties to link qset to entity
90
+ const relId = ctx.allocateExpressId();
91
+ count++;
92
+ const relGlobalId = generateGlobalId(random);
93
+ const relLine = `#${relId}=IFCRELDEFINESBYPROPERTIES('${relGlobalId}',${resolveOwnerHistoryRef(ctx, entityId, willBeEmitted)},$,$,(#${entityId}),#${qsetId});`;
94
+ lines.push(relLine);
95
+ }
96
+ return { lines, count };
97
+ }
98
+ //# sourceMappingURL=step-property-set-generators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"step-property-set-generators.js","sourceRoot":"","sources":["../src/step-property-set-generators.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * The reverse index the property-set/quantity-set collection phase
3
+ * (`step-property-set-collection.ts`) pre-computes over
4
+ * IfcRelDefinesByProperties, so the per-entity "find owning rels" step is
5
+ * O(K) rather than O(N) per modified entity. Split out of
6
+ * `step-property-sets.ts` (#3184).
7
+ */
8
+ import type { PropertySetContext } from './step-property-set-readers.js';
9
+ /**
10
+ * Build a one-shot reverse index of every IfcRelDefinesByProperties in
11
+ * the source: for each related entity, list the rels and property/quantity
12
+ * sets that reference it. Used by the export pre-pass so the per-entity
13
+ * "find owning rels" step is O(K) rather than O(N) per modified entity.
14
+ *
15
+ * `relatedByRel` is the same walk read the other way round, so the deleted-host
16
+ * sweep costs nothing extra.
17
+ */
18
+ export declare function buildRelDefinesByPropertiesIndex(ctx: PropertySetContext): {
19
+ byEntity: Map<number, Array<{
20
+ relId: number;
21
+ psetId: number;
22
+ }>>;
23
+ relatedByRel: Map<number, number[]>;
24
+ };
25
+ //# sourceMappingURL=step-property-set-index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"step-property-set-index.d.ts","sourceRoot":"","sources":["../src/step-property-set-index.ts"],"names":[],"mappings":"AAIA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAGzE;;;;;;;;GAQG;AACH,wBAAgB,gCAAgC,CAAC,GAAG,EAAE,kBAAkB,GAAG;IACzE,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC;IAChE,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CACrC,CAmBA"}
@@ -0,0 +1,69 @@
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 { entityLineText } from './step-property-set-readers.js';
5
+ /**
6
+ * Build a one-shot reverse index of every IfcRelDefinesByProperties in
7
+ * the source: for each related entity, list the rels and property/quantity
8
+ * sets that reference it. Used by the export pre-pass so the per-entity
9
+ * "find owning rels" step is O(K) rather than O(N) per modified entity.
10
+ *
11
+ * `relatedByRel` is the same walk read the other way round, so the deleted-host
12
+ * sweep costs nothing extra.
13
+ */
14
+ export function buildRelDefinesByPropertiesIndex(ctx) {
15
+ const byEntity = new Map();
16
+ const relatedByRel = new Map();
17
+ for (const [relId, relRef] of ctx.dataStore.entityIndex.byId) {
18
+ if (relRef.type.toUpperCase() !== 'IFCRELDEFINESBYPROPERTIES')
19
+ continue;
20
+ const psetId = getRelatedPropertySet(ctx, relId);
21
+ if (!psetId)
22
+ continue;
23
+ const related = getRelatedEntities(ctx, relId);
24
+ relatedByRel.set(relId, related);
25
+ for (const entityId of related) {
26
+ let bucket = byEntity.get(entityId);
27
+ if (!bucket) {
28
+ bucket = [];
29
+ byEntity.set(entityId, bucket);
30
+ }
31
+ bucket.push({ relId, psetId });
32
+ }
33
+ }
34
+ return { byEntity, relatedByRel };
35
+ }
36
+ /**
37
+ * Get entity IDs related by IfcRelDefinesByProperties (the related objects)
38
+ */
39
+ function getRelatedEntities(ctx, relId) {
40
+ const entityText = entityLineText(ctx, relId);
41
+ if (entityText === null)
42
+ return [];
43
+ // Parse IfcRelDefinesByProperties: #ID=IFCRELDEFINESBYPROPERTIES('guid',$,$,$,(#objects),#pset);
44
+ // The 5th argument (index 4) is the list of related objects
45
+ const match = entityText.match(/\(([^)]+)\)\s*,\s*#(\d+)\s*\)\s*;/);
46
+ if (!match)
47
+ return [];
48
+ const objectsList = match[1];
49
+ const refs = [];
50
+ const refMatches = objectsList.matchAll(/#(\d+)/g);
51
+ for (const m of refMatches) {
52
+ refs.push(parseInt(m[1], 10));
53
+ }
54
+ return refs;
55
+ }
56
+ /**
57
+ * Get the property set ID from IfcRelDefinesByProperties
58
+ */
59
+ function getRelatedPropertySet(ctx, relId) {
60
+ const entityText = entityLineText(ctx, relId);
61
+ if (entityText === null)
62
+ return null;
63
+ // Last #ID before the closing );
64
+ const match = entityText.match(/,\s*#(\d+)\s*\)\s*;$/);
65
+ if (!match)
66
+ return null;
67
+ return parseInt(match[1], 10);
68
+ }
69
+ //# sourceMappingURL=step-property-set-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"step-property-set-index.js","sourceRoot":"","sources":["../src/step-property-set-index.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAW/D,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAEhE;;;;;;;;GAQG;AACH,MAAM,UAAU,gCAAgC,CAAC,GAAuB;IAItE,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAoD,CAAC;IAC7E,MAAM,YAAY,GAAG,IAAI,GAAG,EAAoB,CAAC;IACjD,KAAK,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,GAAG,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;QAC7D,IAAI,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,2BAA2B;YAAE,SAAS;QACxE,MAAM,MAAM,GAAG,qBAAqB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACjD,IAAI,CAAC,MAAM;YAAE,SAAS;QACtB,MAAM,OAAO,GAAG,kBAAkB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC/C,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACjC,KAAK,MAAM,QAAQ,IAAI,OAAO,EAAE,CAAC;YAC/B,IAAI,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YACpC,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,MAAM,GAAG,EAAE,CAAC;gBACZ,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YACjC,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC;AACpC,CAAC;AAED;;GAEG;AACH,SAAS,kBAAkB,CAAC,GAAuB,EAAE,KAAa;IAChE,MAAM,UAAU,GAAG,cAAc,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC9C,IAAI,UAAU,KAAK,IAAI;QAAE,OAAO,EAAE,CAAC;IAEnC,iGAAiG;IACjG,4DAA4D;IAC5D,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC;IACpE,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IAEtB,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IAC7B,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,MAAM,UAAU,GAAG,WAAW,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;IACnD,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,SAAS,qBAAqB,CAAC,GAAuB,EAAE,KAAa;IACnE,MAAM,UAAU,GAAG,cAAc,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC9C,IAAI,UAAU,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAErC,iCAAiC;IACjC,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;IACvD,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAChC,CAAC"}