@ifc-lite/create 2.7.0 → 2.9.2

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 (171) hide show
  1. package/README.md +7 -0
  2. package/dist/ifc-creator-alignment.d.ts +30 -0
  3. package/dist/ifc-creator-alignment.d.ts.map +1 -0
  4. package/dist/ifc-creator-alignment.js +174 -0
  5. package/dist/ifc-creator-alignment.js.map +1 -0
  6. package/dist/ifc-creator-header.d.ts +2 -0
  7. package/dist/ifc-creator-header.d.ts.map +1 -0
  8. package/dist/ifc-creator-header.js +22 -0
  9. package/dist/ifc-creator-header.js.map +1 -0
  10. package/dist/ifc-creator-math.d.ts +15 -5
  11. package/dist/ifc-creator-math.d.ts.map +1 -1
  12. package/dist/ifc-creator-math.js +25 -2
  13. package/dist/ifc-creator-math.js.map +1 -1
  14. package/dist/ifc-creator-relationships.d.ts +43 -0
  15. package/dist/ifc-creator-relationships.d.ts.map +1 -0
  16. package/dist/ifc-creator-relationships.js +38 -0
  17. package/dist/ifc-creator-relationships.js.map +1 -0
  18. package/dist/ifc-creator-styles.d.ts +22 -0
  19. package/dist/ifc-creator-styles.d.ts.map +1 -0
  20. package/dist/ifc-creator-styles.js +50 -0
  21. package/dist/ifc-creator-styles.js.map +1 -0
  22. package/dist/ifc-creator-terrain.d.ts +170 -0
  23. package/dist/ifc-creator-terrain.d.ts.map +1 -0
  24. package/dist/ifc-creator-terrain.js +180 -0
  25. package/dist/ifc-creator-terrain.js.map +1 -0
  26. package/dist/ifc-creator.d.ts +21 -7
  27. package/dist/ifc-creator.d.ts.map +1 -1
  28. package/dist/ifc-creator.js +95 -95
  29. package/dist/ifc-creator.js.map +1 -1
  30. package/dist/in-store/_emit-helpers.d.ts +10 -0
  31. package/dist/in-store/_emit-helpers.d.ts.map +1 -1
  32. package/dist/in-store/_emit-helpers.js +15 -2
  33. package/dist/in-store/_emit-helpers.js.map +1 -1
  34. package/dist/in-store/anchor.d.ts +2 -0
  35. package/dist/in-store/anchor.d.ts.map +1 -1
  36. package/dist/in-store/anchor.js.map +1 -1
  37. package/dist/in-store/apply-style.d.ts +3 -6
  38. package/dist/in-store/apply-style.d.ts.map +1 -1
  39. package/dist/in-store/apply-style.js +3 -77
  40. package/dist/in-store/apply-style.js.map +1 -1
  41. package/dist/in-store/beam.d.ts +2 -0
  42. package/dist/in-store/beam.d.ts.map +1 -1
  43. package/dist/in-store/beam.js +2 -2
  44. package/dist/in-store/beam.js.map +1 -1
  45. package/dist/in-store/column.d.ts +2 -0
  46. package/dist/in-store/column.d.ts.map +1 -1
  47. package/dist/in-store/column.js +4 -2
  48. package/dist/in-store/column.js.map +1 -1
  49. package/dist/in-store/door.d.ts +2 -0
  50. package/dist/in-store/door.d.ts.map +1 -1
  51. package/dist/in-store/door.js +2 -0
  52. package/dist/in-store/door.js.map +1 -1
  53. package/dist/in-store/extract-walls.d.ts +1 -1
  54. package/dist/in-store/extract-walls.d.ts.map +1 -1
  55. package/dist/in-store/extract-walls.js +28 -54
  56. package/dist/in-store/extract-walls.js.map +1 -1
  57. package/dist/in-store/generate-spaces-all.d.ts +6 -2
  58. package/dist/in-store/generate-spaces-all.d.ts.map +1 -1
  59. package/dist/in-store/generate-spaces-all.js +33 -9
  60. package/dist/in-store/generate-spaces-all.js.map +1 -1
  61. package/dist/in-store/generate-spaces.js +1 -1
  62. package/dist/in-store/generate-spaces.js.map +1 -1
  63. package/dist/in-store/member.d.ts +2 -0
  64. package/dist/in-store/member.d.ts.map +1 -1
  65. package/dist/in-store/member.js.map +1 -1
  66. package/dist/in-store/placement-frame.d.ts +8 -0
  67. package/dist/in-store/placement-frame.d.ts.map +1 -1
  68. package/dist/in-store/placement-frame.js.map +1 -1
  69. package/dist/in-store/plate.d.ts +4 -0
  70. package/dist/in-store/plate.d.ts.map +1 -1
  71. package/dist/in-store/plate.js +4 -0
  72. package/dist/in-store/plate.js.map +1 -1
  73. package/dist/in-store/resolve-anchor.d.ts +4 -2
  74. package/dist/in-store/resolve-anchor.d.ts.map +1 -1
  75. package/dist/in-store/resolve-anchor.js +79 -92
  76. package/dist/in-store/resolve-anchor.js.map +1 -1
  77. package/dist/in-store/resolve-source.d.ts +2 -1
  78. package/dist/in-store/resolve-source.d.ts.map +1 -1
  79. package/dist/in-store/resolve-source.js +49 -49
  80. package/dist/in-store/resolve-source.js.map +1 -1
  81. package/dist/in-store/roof.d.ts +4 -0
  82. package/dist/in-store/roof.d.ts.map +1 -1
  83. package/dist/in-store/roof.js +4 -0
  84. package/dist/in-store/roof.js.map +1 -1
  85. package/dist/in-store/slab.d.ts +4 -0
  86. package/dist/in-store/slab.d.ts.map +1 -1
  87. package/dist/in-store/slab.js +6 -2
  88. package/dist/in-store/slab.js.map +1 -1
  89. package/dist/in-store/space.d.ts +4 -0
  90. package/dist/in-store/space.d.ts.map +1 -1
  91. package/dist/in-store/space.js +6 -2
  92. package/dist/in-store/space.js.map +1 -1
  93. package/dist/in-store/spatial-children.d.ts +52 -0
  94. package/dist/in-store/spatial-children.d.ts.map +1 -0
  95. package/dist/in-store/spatial-children.js +112 -0
  96. package/dist/in-store/spatial-children.js.map +1 -0
  97. package/dist/in-store/structural-action.d.ts +85 -0
  98. package/dist/in-store/structural-action.d.ts.map +1 -0
  99. package/dist/in-store/structural-action.js +83 -0
  100. package/dist/in-store/structural-action.js.map +1 -0
  101. package/dist/in-store/structural-analysis-model.d.ts +49 -0
  102. package/dist/in-store/structural-analysis-model.d.ts.map +1 -0
  103. package/dist/in-store/structural-analysis-model.js +29 -0
  104. package/dist/in-store/structural-analysis-model.js.map +1 -0
  105. package/dist/in-store/structural-curve-member.d.ts +90 -0
  106. package/dist/in-store/structural-curve-member.d.ts.map +1 -0
  107. package/dist/in-store/structural-curve-member.js +83 -0
  108. package/dist/in-store/structural-curve-member.js.map +1 -0
  109. package/dist/in-store/structural-load-group.d.ts +61 -0
  110. package/dist/in-store/structural-load-group.d.ts.map +1 -0
  111. package/dist/in-store/structural-load-group.js +38 -0
  112. package/dist/in-store/structural-load-group.js.map +1 -0
  113. package/dist/in-store/structural-point-connection.d.ts +75 -0
  114. package/dist/in-store/structural-point-connection.d.ts.map +1 -0
  115. package/dist/in-store/structural-point-connection.js +41 -0
  116. package/dist/in-store/structural-point-connection.js.map +1 -0
  117. package/dist/in-store/structural-relationships.d.ts +47 -0
  118. package/dist/in-store/structural-relationships.d.ts.map +1 -0
  119. package/dist/in-store/structural-relationships.js +85 -0
  120. package/dist/in-store/structural-relationships.js.map +1 -0
  121. package/dist/in-store/style-entity-reader.d.ts +14 -0
  122. package/dist/in-store/style-entity-reader.d.ts.map +1 -0
  123. package/dist/in-store/style-entity-reader.js +58 -0
  124. package/dist/in-store/style-entity-reader.js.map +1 -0
  125. package/dist/in-store/wall.d.ts +2 -0
  126. package/dist/in-store/wall.d.ts.map +1 -1
  127. package/dist/in-store/wall.js +2 -2
  128. package/dist/in-store/wall.js.map +1 -1
  129. package/dist/in-store/window.d.ts +2 -0
  130. package/dist/in-store/window.d.ts.map +1 -1
  131. package/dist/in-store/window.js +2 -0
  132. package/dist/in-store/window.js.map +1 -1
  133. package/dist/index.d.ts +14 -0
  134. package/dist/index.d.ts.map +1 -1
  135. package/dist/index.js +13 -0
  136. package/dist/index.js.map +1 -1
  137. package/dist/landxml/alignment-mapping.d.ts +98 -0
  138. package/dist/landxml/alignment-mapping.d.ts.map +1 -0
  139. package/dist/landxml/alignment-mapping.js +282 -0
  140. package/dist/landxml/alignment-mapping.js.map +1 -0
  141. package/dist/landxml/alignment-record.d.ts +18 -0
  142. package/dist/landxml/alignment-record.d.ts.map +1 -0
  143. package/dist/landxml/alignment-record.js +63 -0
  144. package/dist/landxml/alignment-record.js.map +1 -0
  145. package/dist/landxml/coordinate-plausibility.d.ts +54 -0
  146. package/dist/landxml/coordinate-plausibility.d.ts.map +1 -0
  147. package/dist/landxml/coordinate-plausibility.js +59 -0
  148. package/dist/landxml/coordinate-plausibility.js.map +1 -0
  149. package/dist/landxml/landxml-to-ifc.d.ts +45 -0
  150. package/dist/landxml/landxml-to-ifc.d.ts.map +1 -0
  151. package/dist/landxml/landxml-to-ifc.js +197 -0
  152. package/dist/landxml/landxml-to-ifc.js.map +1 -0
  153. package/dist/landxml/refusals.d.ts +41 -0
  154. package/dist/landxml/refusals.d.ts.map +1 -0
  155. package/dist/landxml/refusals.js +118 -0
  156. package/dist/landxml/refusals.js.map +1 -0
  157. package/dist/landxml/result-types.d.ts +73 -0
  158. package/dist/landxml/result-types.d.ts.map +1 -0
  159. package/dist/landxml/result-types.js +5 -0
  160. package/dist/landxml/result-types.js.map +1 -0
  161. package/dist/landxml/source-types.d.ts +169 -0
  162. package/dist/landxml/source-types.d.ts.map +1 -0
  163. package/dist/landxml/source-types.js +5 -0
  164. package/dist/landxml/source-types.js.map +1 -0
  165. package/dist/landxml/writers.d.ts +31 -0
  166. package/dist/landxml/writers.d.ts.map +1 -0
  167. package/dist/landxml/writers.js +143 -0
  168. package/dist/landxml/writers.js.map +1 -0
  169. package/dist/types.d.ts +7 -0
  170. package/dist/types.d.ts.map +1 -1
  171. package/package.json +6 -6
@@ -5,7 +5,12 @@ import { esc, stepLine, num, vecLen, vecNorm, vecCross, optStr, optEnum, NON_ELE
5
5
  import { emitWorkCalendar, emitTaskTime } from './ifc-creator-scheduling.js';
6
6
  import { assertCostSchema, emitCostItem, emitCostSchedule, emitCostValue, emitMeasureWithUnit, emitMonetaryUnit, emitPhysicalQuantity, emitRelAssignsToProduct, emitSIUnit, } from './ifc-creator-cost.js';
7
7
  import { emitElementQuantity, emitPropertySet } from './ifc-creator-definitions.js';
8
+ import { createTerrainWriter } from './ifc-creator-terrain.js';
9
+ import { emitRelFillsElement, emitSpatialRelationships } from './ifc-creator-relationships.js';
10
+ import { emitDefaultStyle, emitStyledItems } from './ifc-creator-styles.js';
11
+ import { buildStepHeader } from './ifc-creator-header.js';
8
12
  import { generateIfcGuid, isValidIfcGuid } from '@ifc-lite/encoding';
13
+ import { fileSchemaIdentifier } from '@ifc-lite/data';
9
14
  // ============================================================================
10
15
  // IfcCreator
11
16
  // ============================================================================
@@ -50,6 +55,15 @@ export class IfcCreator {
50
55
  dirX = 0;
51
56
  worldPlacementId = 0;
52
57
  unitAssignmentId = 0;
58
+ // Products contained directly in the site rather than a storey: terrain and
59
+ // survey annotations have no storey, and inventing one would put them on a
60
+ // datum the source never declared.
61
+ siteElements = [];
62
+ /** Products aggregated by the project itself — `IfcAlignment` (§11 of the LandXML mapping). */
63
+ projectElements = [];
64
+ georeferenced = false;
65
+ /** The length `IfcNamedUnit` `IfcProjectedCRS.MapUnit` points at. */
66
+ lengthUnitId = 0;
53
67
  // Guard against repeated toIfc() calls (relationships are not idempotent)
54
68
  finalized = false;
55
69
  // Default surface style (applied to elements without custom color)
@@ -79,6 +93,9 @@ export class IfcCreator {
79
93
  constructor(params = {}) {
80
94
  this.projectParams = params;
81
95
  this.schema = params.Schema ?? 'IFC4';
96
+ if (params.FileSchemaIdentifier !== undefined && this.schema !== 'IFC4X3') {
97
+ throw new Error(`IfcCreator: FileSchemaIdentifier '${params.FileSchemaIdentifier}' requires Schema 'IFC4X3', not '${this.schema}'`);
98
+ }
82
99
  this.fixedTimestampMs = params.Timestamp === undefined
83
100
  ? null
84
101
  : typeof params.Timestamp === 'number' ? params.Timestamp : params.Timestamp.getTime();
@@ -1177,6 +1194,53 @@ export class IfcCreator {
1177
1194
  return beamId;
1178
1195
  }
1179
1196
  // ============================================================================
1197
+ // Public API — Terrain & survey (IFC4X3, LandXML→IFC mapping)
1198
+ // ============================================================================
1199
+ /**
1200
+ * The terrain/survey authoring surface: TIN surfaces, survey points, their
1201
+ * property sets and the file's georeferencing.
1202
+ *
1203
+ * One accessor rather than four methods: each needs the same creator
1204
+ * internals and nothing else. `ifc-creator-terrain.ts` documents each call.
1205
+ */
1206
+ terrain() {
1207
+ return createTerrainWriter(this.terrainContext(), {
1208
+ trackSiteProduct: (expressId, type, name) => {
1209
+ this.siteElements.push(expressId);
1210
+ this.entities.push({ expressId, type, Name: name });
1211
+ },
1212
+ lengthUnitRef: () => `#${this.lengthUnitId}`,
1213
+ siteId: () => this.siteId,
1214
+ trackProjectProduct: (expressId, type, name) => {
1215
+ this.projectElements.push(expressId);
1216
+ this.entities.push({ expressId, type, Name: name });
1217
+ },
1218
+ claimGeoreferencing: () => {
1219
+ if (this.georeferenced) {
1220
+ throw new Error('setGeoreferencing: already called — a file has at most one IfcMapConversion for its model context');
1221
+ }
1222
+ this.georeferenced = true;
1223
+ },
1224
+ });
1225
+ }
1226
+ /** The creator hooks `ifc-creator-terrain.ts`'s emitters need. */
1227
+ terrainContext() {
1228
+ return {
1229
+ emit: this.emitEntity,
1230
+ newGlobalId: () => this.newGlobalId(),
1231
+ ownerRef: `#${this.ownerHistoryId}`,
1232
+ modelContextRef: `#${this.contextId}`,
1233
+ bodyContextRef: `#${this.subContextBody}`,
1234
+ axisContextRef: `#${this.subContextAxis}`,
1235
+ sitePlacementRef: `#${this.worldPlacementId}`,
1236
+ assertSchema: (feature) => {
1237
+ if (this.schema !== 'IFC4X3') {
1238
+ throw new Error(`${feature} requires the IFC4X3 schema — IfcTriangulatedIrregularNetwork and the survey/terrain predefined types do not exist in ${this.schema}`);
1239
+ }
1240
+ },
1241
+ };
1242
+ }
1243
+ // ============================================================================
1180
1244
  // Public API — Properties & Quantities
1181
1245
  // ============================================================================
1182
1246
  /** Attach a property set to an element */
@@ -1533,19 +1597,7 @@ export class IfcCreator {
1533
1597
  };
1534
1598
  }
1535
1599
  buildHeader() {
1536
- const now = new Date(this.nowMs()).toISOString().replace(/\.\d{3}Z$/, ''); // ISO 8601 time_stamp: keep '-'/':', drop only ms+'Z'
1537
- const desc = 'Created by ifc-lite';
1538
- const author = this.projectParams.Author ?? '';
1539
- const org = this.projectParams.Organization ?? '';
1540
- const app = 'ifc-lite';
1541
- const filename = 'created.ifc';
1542
- return `ISO-10303-21;
1543
- HEADER;
1544
- FILE_DESCRIPTION(('${esc(desc)}'),'2;1');
1545
- FILE_NAME('${filename}','${now}',('${esc(author)}'),('${esc(org)}'),'${app}','${app}','');
1546
- FILE_SCHEMA(('${this.schema}'));
1547
- ENDSEC;
1548
- `;
1600
+ return buildStepHeader(this.nowMs(), this.projectParams.Author ?? '', this.projectParams.Organization ?? '', fileSchemaIdentifier(this.schema));
1549
1601
  }
1550
1602
  // ============================================================================
1551
1603
  // Internal — Preamble (project, site, building, contexts, units, style)
@@ -1581,7 +1633,7 @@ ENDSEC;
1581
1633
  // Units
1582
1634
  this.unitAssignmentId = this.buildUnits(params.LengthUnit ?? 'METRE', params.Currency);
1583
1635
  // Default surface style — light grey with some specularity
1584
- this.defaultStyleId = this.buildDefaultStyle();
1636
+ this.defaultStyleId = emitDefaultStyle({ emit: this.emitEntity });
1585
1637
  // IfcProject
1586
1638
  this.projectId = this.id();
1587
1639
  const projectGlobalId = this.newGlobalId();
@@ -1624,59 +1676,19 @@ ENDSEC;
1624
1676
  assertCostSchema(this.schema, 'ProjectParams.Currency'); // IFC2X3 Currency is an enum
1625
1677
  units.push(emitMonetaryUnit(currency, this.emitEntity));
1626
1678
  }
1679
+ this.lengthUnitId = lengthUnitId;
1627
1680
  const assignmentId = this.id();
1628
1681
  this.line(assignmentId, 'IFCUNITASSIGNMENT', `(${units.map(id => `#${id}`).join(',')})`);
1629
1682
  return assignmentId;
1630
1683
  }
1631
- /** Create a default IfcSurfaceStyle with a neutral colour (RGB 0.75, 0.73, 0.68) */
1632
- buildDefaultStyle() {
1633
- // IfcColourRgb — warm concrete grey
1634
- const colourId = this.id();
1635
- this.line(colourId, 'IFCCOLOURRGB', `$,0.75,0.73,0.68`);
1636
- // IfcSurfaceStyleRendering — surface + specular
1637
- const renderingId = this.id();
1638
- this.line(renderingId, 'IFCSURFACESTYLERENDERING', `#${colourId},0.,$,$,$,$,IFCNORMALISEDRATIOMEASURE(0.5),IFCSPECULAREXPONENT(64.),.NOTDEFINED.`);
1639
- // IfcSurfaceStyle
1640
- const styleId = this.id();
1641
- this.line(styleId, 'IFCSURFACESTYLE', `'Default',.BOTH.,(#${renderingId})`);
1642
- return styleId;
1643
- }
1644
- /** Create all IfcStyledItem entities — custom colour or default per element */
1684
+ /**
1685
+ * Create all `IfcStyledItem` rows — a custom colour where one was assigned,
1686
+ * the default grey otherwise. See `ifc-creator-styles.ts`.
1687
+ */
1645
1688
  finalizeStyles() {
1646
- // Cache: colour key → styleId so identical colours share one style entity
1647
- const styleCache = new Map();
1648
- for (const [elementId, solidIds] of this.elementSolids) {
1649
- const color = this.elementColors.get(elementId);
1650
- let styleId;
1651
- if (color) {
1652
- const key = `${color.name}|${color.rgb.join(',')}`;
1653
- const cached = styleCache.get(key);
1654
- if (cached !== undefined) {
1655
- styleId = cached;
1656
- }
1657
- else {
1658
- styleId = this.buildColorStyle(color.name, color.rgb);
1659
- styleCache.set(key, styleId);
1660
- }
1661
- }
1662
- else {
1663
- styleId = this.defaultStyleId;
1664
- }
1665
- for (const solidId of solidIds) {
1666
- const styledItemId = this.id();
1667
- this.line(styledItemId, 'IFCSTYLEDITEM', `#${solidId},(#${styleId}),$`);
1668
- }
1669
- }
1670
- }
1671
- /** Create a named IfcSurfaceStyle with the given RGB colour */
1672
- buildColorStyle(name, rgb) {
1673
- const colourId = this.id();
1674
- this.line(colourId, 'IFCCOLOURRGB', `$,${num(rgb[0])},${num(rgb[1])},${num(rgb[2])}`);
1675
- const renderingId = this.id();
1676
- this.line(renderingId, 'IFCSURFACESTYLERENDERING', `#${colourId},0.,$,$,$,$,IFCNORMALISEDRATIOMEASURE(0.5),IFCSPECULAREXPONENT(64.),.NOTDEFINED.`);
1677
- const styleId = this.id();
1678
- this.line(styleId, 'IFCSURFACESTYLE', `'${esc(name)}',.BOTH.,(#${renderingId})`);
1679
- return styleId;
1689
+ emitStyledItems(this.elementSolids, this.elementColors, this.defaultStyleId, {
1690
+ emit: this.emitEntity,
1691
+ });
1680
1692
  }
1681
1693
  // ============================================================================
1682
1694
  // Internal — Material helpers
@@ -1713,12 +1725,16 @@ ENDSEC;
1713
1725
  // ============================================================================
1714
1726
  // Internal — Geometry helpers
1715
1727
  // ============================================================================
1728
+ // Every builder's Position/Start/opening point is written here (#5217).
1716
1729
  addCartesianPoint(p) {
1730
+ assertFinitePoint3({ IfcCartesianPoint: p }, 'IfcCreator');
1717
1731
  const id = this.id();
1718
1732
  this.line(id, 'IFCCARTESIANPOINT', `(${num(p[0])},${num(p[1])},${num(p[2])})`);
1719
1733
  return id;
1720
1734
  }
1721
1735
  addCartesianPoint2D(p) {
1736
+ if (!p.every(Number.isFinite))
1737
+ throw new Error('IfcCreator: IfcCartesianPoint must have finite coordinates');
1722
1738
  const id = this.id();
1723
1739
  this.line(id, 'IFCCARTESIANPOINT', `(${num(p[0])},${num(p[1])})`);
1724
1740
  return id;
@@ -1742,14 +1758,8 @@ ENDSEC;
1742
1758
  */
1743
1759
  addLocalPlacement(relativeTo, placement) {
1744
1760
  const originId = this.addCartesianPoint(placement.Location);
1745
- let axisId;
1746
- let refDirId;
1747
- if (placement.Axis) {
1748
- axisId = this.addDirection(placement.Axis);
1749
- }
1750
- if (placement.RefDirection) {
1751
- refDirId = this.addDirection(placement.RefDirection);
1752
- }
1761
+ const axisId = placement.Axis ? this.addDirection(placement.Axis) : undefined;
1762
+ const refDirId = placement.RefDirection ? this.addDirection(placement.RefDirection) : undefined;
1753
1763
  const axis2Id = this.addAxis2Placement3D(originId, axisId, refDirId);
1754
1764
  const id = this.id();
1755
1765
  this.line(id, 'IFCLOCALPLACEMENT', `#${relativeTo},#${axis2Id}`);
@@ -2171,33 +2181,23 @@ ENDSEC;
2171
2181
  // Internal — Relationship finalization
2172
2182
  // ============================================================================
2173
2183
  finalizeRelationships() {
2174
- this.addIfcRelAggregates(this.projectId, [this.siteId]);
2175
- this.addIfcRelAggregates(this.siteId, [this.buildingId]);
2176
- if (this.storeyIds.length > 0) {
2177
- this.addIfcRelAggregates(this.buildingId, this.storeyIds);
2178
- }
2179
- for (const [storeyId, elementIds] of this.storeyElements) {
2180
- if (elementIds.length > 0) {
2181
- this.addIfcRelContainedInSpatialStructure(storeyId, elementIds);
2182
- }
2183
- }
2184
- }
2185
- addIfcRelAggregates(relatingId, relatedIds) {
2186
- const relId = this.id();
2187
- const globalId = this.newGlobalId();
2188
- const refs = relatedIds.map(id => `#${id}`).join(',');
2189
- this.line(relId, 'IFCRELAGGREGATES', `'${globalId}',#${this.ownerHistoryId},$,$,#${relatingId},(${refs})`);
2190
- }
2191
- addIfcRelContainedInSpatialStructure(storeyId, elementIds) {
2192
- const relId = this.id();
2193
- const globalId = this.newGlobalId();
2194
- const refs = elementIds.map(id => `#${id}`).join(',');
2195
- this.line(relId, 'IFCRELCONTAINEDINSPATIALSTRUCTURE', `'${globalId}',#${this.ownerHistoryId},$,$,(${refs}),#${storeyId}`);
2184
+ emitSpatialRelationships({
2185
+ emit: this.emitEntity,
2186
+ newGlobalId: () => this.newGlobalId(),
2187
+ ownerRef: `#${this.ownerHistoryId}`,
2188
+ projectId: this.projectId,
2189
+ siteId: this.siteId,
2190
+ buildingId: this.buildingId,
2191
+ storeyIds: this.storeyIds,
2192
+ storeyElements: this.storeyElements,
2193
+ siteElements: this.siteElements,
2194
+ projectElements: this.projectElements,
2195
+ });
2196
2196
  }
2197
2197
  addIfcRelFillsElement(openingId, fillingId) {
2198
- const relId = this.id();
2199
- const globalId = this.newGlobalId();
2200
- this.line(relId, 'IFCRELFILLSELEMENT', `'${globalId}',#${this.ownerHistoryId},$,$,#${openingId},#${fillingId}`);
2198
+ emitRelFillsElement(openingId, fillingId, {
2199
+ emit: this.emitEntity, newGlobalId: () => this.newGlobalId(), ownerRef: `#${this.ownerHistoryId}`,
2200
+ });
2201
2201
  }
2202
2202
  // ============================================================================
2203
2203
  // Internal — Utilities