brepjs-bim 0.11.0 → 0.13.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.
@@ -6406,10 +6406,12 @@ var BimModel = class {
6406
6406
  this.#associateClassification(id, spec);
6407
6407
  return (0, brepjs.ok)(id);
6408
6408
  }
6409
- addRoof(spec) {
6409
+ addRoof(spec, options) {
6410
+ const keyCheck = this.#checkStableKey(options);
6411
+ if (!keyCheck.ok) return keyCheck;
6410
6412
  const geomResult = roofToSolid(spec);
6411
6413
  if (!geomResult.ok) return (0, brepjs.err)(geomResult.error);
6412
- const id = this.#makeElement("ROOF", spec, geomResult.value);
6414
+ const id = this.#makeElement("ROOF", spec, geomResult.value, options?.stableKey);
6413
6415
  this.#associateMaterial(id, spec);
6414
6416
  this.#associateClassification(id, spec);
6415
6417
  return (0, brepjs.ok)(id);
@@ -6443,8 +6445,10 @@ var BimModel = class {
6443
6445
  * the IFC layer from `spec.flights`; the STAIR element itself carries no solid
6444
6446
  * (the assembly container's Representation is null, valid per IFC4).
6445
6447
  */
6446
- addStair(spec) {
6447
- const id = this.#makeElement("STAIR", spec, null);
6448
+ addStair(spec, options) {
6449
+ const keyCheck = this.#checkStableKey(options);
6450
+ if (!keyCheck.ok) return keyCheck;
6451
+ const id = this.#makeElement("STAIR", spec, null, options?.stableKey);
6448
6452
  this.#associateMaterial(id, spec);
6449
6453
  this.#associateClassification(id, spec);
6450
6454
  return (0, brepjs.ok)(id);
@@ -6453,8 +6457,10 @@ var BimModel = class {
6453
6457
  * Adds an IfcRamp assembly. Geometry for each flight is built and written by the
6454
6458
  * IFC layer from `spec.flights`; the RAMP element carries no solid of its own.
6455
6459
  */
6456
- addRamp(spec) {
6457
- const id = this.#makeElement("RAMP", spec, null);
6460
+ addRamp(spec, options) {
6461
+ const keyCheck = this.#checkStableKey(options);
6462
+ if (!keyCheck.ok) return keyCheck;
6463
+ const id = this.#makeElement("RAMP", spec, null, options?.stableKey);
6458
6464
  this.#associateMaterial(id, spec);
6459
6465
  this.#associateClassification(id, spec);
6460
6466
  return (0, brepjs.ok)(id);
@@ -8101,7 +8107,7 @@ function writeTessellation(w, solid, geomSubContextId, _localPlacementId, tolera
8101
8107
  type: web_ifc.IFCTRIANGULATEDFACESET,
8102
8108
  Coordinates: w.ref(pointListId),
8103
8109
  Normals: null,
8104
- Closed: true,
8110
+ Closed: w.mkType(web_ifc.IFCBOOLEAN, true),
8105
8111
  CoordIndex: coordIndex.map((tri) => tri.map((idx) => w.mkType(web_ifc.IFCPOSITIVEINTEGER, idx))),
8106
8112
  PnIndex: null
8107
8113
  });
@@ -8205,7 +8211,7 @@ function writeFacetedBrepFallback(w, geomSubContextId, reason) {
8205
8211
  expressID: faceOuterBoundId,
8206
8212
  type: web_ifc.IFCFACEOUTERBOUND,
8207
8213
  Bound: w.ref(loopId),
8208
- Orientation: true
8214
+ Orientation: w.mkType(web_ifc.IFCBOOLEAN, true)
8209
8215
  });
8210
8216
  const faceId = w.nextId();
8211
8217
  w.writeLine({
@@ -9630,13 +9636,15 @@ function writeRampEntity(w, guid, name, predefinedType, ownerHistoryId, localPla
9630
9636
  * per `spec.flights[i]` (each with a tessellated stepped-solid body), and a single
9631
9637
  * IfcRelAggregates linking the flights to the stair. Flight placements are
9632
9638
  * relative to the stair placement, which is relative to `parentPlacementId`
9633
- * (typically the storey). GUIDs are deterministic, keyed on `stairKey`/index so
9639
+ * (typically the storey). The assembly's GlobalId is the element's stored guid
9640
+ * (stableKey-derived when the caller provided one); flight, type, and
9641
+ * relationship GUIDs are deterministic, keyed on `stairKey`/index so
9634
9642
  * re-serializing an identical model is byte-stable.
9635
9643
  *
9636
9644
  * Returns a BimError if any flight solid cannot be built. Stair flights are real
9637
9645
  * stepped solids; tessellation failure is flagged via `geometrySimplified`.
9638
9646
  */
9639
- function writeStairAssembly(w, spec, stairKey, ownerHistoryId, geomSubContextId, parentPlacementId) {
9647
+ function writeStairAssembly(w, spec, stairKey, assemblyGuid, ownerHistoryId, geomSubContextId, parentPlacementId) {
9640
9648
  const predefinedType = spec.predefinedType ?? "NOTDEFINED";
9641
9649
  const stairName = spec.name ?? "Stair";
9642
9650
  if (spec.flights[0] === void 0) return {
@@ -9656,7 +9664,7 @@ function writeStairAssembly(w, spec, stairKey, ownerHistoryId, geomSubContextId,
9656
9664
  0,
9657
9665
  0
9658
9666
  ], parentPlacementId);
9659
- const assemblyExpressId = writeStairEntity(w, deriveIfcGuidSync(`elem:STAIR:${stairKey}`), stairName, predefinedType, ownerHistoryId, stairPlacementId);
9667
+ const assemblyExpressId = writeStairEntity(w, assemblyGuid, stairName, predefinedType, ownerHistoryId, stairPlacementId);
9660
9668
  const flightExpressIds = [];
9661
9669
  let geometrySimplified = false;
9662
9670
  for (const [i, flight] of spec.flights.entries()) try {
@@ -9696,7 +9704,7 @@ function writeStairAssembly(w, spec, stairKey, ownerHistoryId, geomSubContextId,
9696
9704
  * inclined-slab solids, so `geometrySimplified` is always true. GUIDs are
9697
9705
  * deterministic keyed on `rampKey`.
9698
9706
  */
9699
- function writeRampAssembly(w, spec, rampKey, ownerHistoryId, geomSubContextId, parentPlacementId) {
9707
+ function writeRampAssembly(w, spec, rampKey, assemblyGuid, ownerHistoryId, geomSubContextId, parentPlacementId) {
9700
9708
  const predefinedType = spec.predefinedType ?? "NOTDEFINED";
9701
9709
  const rampName = spec.name ?? "Ramp";
9702
9710
  if (spec.flights[0] === void 0) return {
@@ -9716,7 +9724,7 @@ function writeRampAssembly(w, spec, rampKey, ownerHistoryId, geomSubContextId, p
9716
9724
  0,
9717
9725
  0
9718
9726
  ], parentPlacementId);
9719
- const assemblyExpressId = writeRampEntity(w, deriveIfcGuidSync(`elem:RAMP:${rampKey}`), rampName, predefinedType, ownerHistoryId, rampPlacementId);
9727
+ const assemblyExpressId = writeRampEntity(w, assemblyGuid, rampName, predefinedType, ownerHistoryId, rampPlacementId);
9720
9728
  const flightExpressIds = [];
9721
9729
  const geometrySimplified = true;
9722
9730
  for (const [i, flight] of spec.flights.entries()) try {
@@ -12275,7 +12283,7 @@ async function toIfc(model, meta) {
12275
12283
  for (const stair of stairs) {
12276
12284
  const containingId = findContainerOf(stair.localId, relationships);
12277
12285
  const storeyPlacementId = containingId !== null ? placementMap.get(containingId) ?? null : null;
12278
- const result = writeStairAssembly(w, stair.spec, `${stair.localId}`, ownerHistoryId, geomSubContextId, storeyPlacementId);
12286
+ const result = writeStairAssembly(w, stair.spec, `${stair.localId}`, stair.guid, ownerHistoryId, geomSubContextId, storeyPlacementId);
12279
12287
  if (!result.ok) return (0, brepjs.err)(result.error);
12280
12288
  idMap.set(stair.localId, result.value.assemblyExpressId);
12281
12289
  writeStairCommonPset(w, ownerHistoryId, result.value.assemblyExpressId, stair.spec);
@@ -12283,7 +12291,7 @@ async function toIfc(model, meta) {
12283
12291
  for (const ramp of ramps) {
12284
12292
  const containingId = findContainerOf(ramp.localId, relationships);
12285
12293
  const storeyPlacementId = containingId !== null ? placementMap.get(containingId) ?? null : null;
12286
- const result = writeRampAssembly(w, ramp.spec, `${ramp.localId}`, ownerHistoryId, geomSubContextId, storeyPlacementId);
12294
+ const result = writeRampAssembly(w, ramp.spec, `${ramp.localId}`, ramp.guid, ownerHistoryId, geomSubContextId, storeyPlacementId);
12287
12295
  if (!result.ok) return (0, brepjs.err)(result.error);
12288
12296
  idMap.set(ramp.localId, result.value.assemblyExpressId);
12289
12297
  writeRampCommonPset(w, ownerHistoryId, result.value.assemblyExpressId, ramp.spec);
@@ -16497,7 +16505,7 @@ function assignNum(target, key, value) {
16497
16505
  * while the IR path serves the viewport and dedup. GlobalIds derive from
16498
16506
  * families key paths (stable under reordering), not insertion order.
16499
16507
  *
16500
- * Scope: Storey containers, Wall/Slab/Column/Beam elements, and wall openings — a
16508
+ * Scope: Storey containers, Wall/Slab/Column/Beam/Roof/Stair elements, and wall openings — a
16501
16509
  * fill-role void (Door/Window family) maps onto addDoor/addWindow, which cut
16502
16510
  * the wall and wire IfcRelVoidsElement + IfcRelFillsElement; the opening and
16503
16511
  * filler GlobalIds derive from the synthesized key paths. Anonymous (non-fill)
@@ -16543,8 +16551,46 @@ var SPEC_ROUTES = {
16543
16551
  Beam: {
16544
16552
  parse: parseBeamSpec,
16545
16553
  add: (m, spec, key) => m.addBeam(spec, { stableKey: key })
16554
+ },
16555
+ Roof: {
16556
+ parse: parseRoofSpec,
16557
+ add: (m, spec, key) => m.addRoof(spec, { stableKey: key })
16558
+ },
16559
+ Stair: {
16560
+ parse: parseStairSpec,
16561
+ add: (m, spec, key) => m.addStair(spec, { stableKey: key }),
16562
+ input: stairSpecInput
16546
16563
  }
16547
16564
  };
16565
+ /** StairSpec has no top-level origin — placement lives per flight — so the
16566
+ * element's folded translate lands on every flight's origin instead. */
16567
+ function stairSpecInput(el) {
16568
+ const base = specInput(el);
16569
+ const fold = base["origin"] ?? [
16570
+ 0,
16571
+ 0,
16572
+ 0
16573
+ ];
16574
+ const flights = Array.isArray(base["flights"]) ? base["flights"] : [];
16575
+ return {
16576
+ ...base,
16577
+ flights: flights.map((f) => {
16578
+ const fo = f["origin"] ?? [
16579
+ 0,
16580
+ 0,
16581
+ 0
16582
+ ];
16583
+ return {
16584
+ ...f,
16585
+ origin: [
16586
+ fo[0] + fold[0],
16587
+ fo[1] + fold[1],
16588
+ fo[2] + fold[2]
16589
+ ]
16590
+ };
16591
+ })
16592
+ };
16593
+ }
16548
16594
  function specRoute(type) {
16549
16595
  return Object.hasOwn(SPEC_ROUTES, type) ? SPEC_ROUTES[type] : void 0;
16550
16596
  }
@@ -16707,7 +16753,7 @@ function familiesToBim(root, options) {
16707
16753
  } else if (route !== void 0) {
16708
16754
  const keyed = requireKeyed(el);
16709
16755
  if (!keyed.ok) return keyed;
16710
- const parsed = route.parse(specInput(el));
16756
+ const parsed = route.parse(("input" in route ? route.input : specInput)(el));
16711
16757
  if (!parsed.ok) return parsed;
16712
16758
  const added = route.add(model, parsed.value, el.keyPath);
16713
16759
  if (!added.ok) return added;
@@ -6383,10 +6383,12 @@ var BimModel = class {
6383
6383
  this.#associateClassification(id, spec);
6384
6384
  return ok(id);
6385
6385
  }
6386
- addRoof(spec) {
6386
+ addRoof(spec, options) {
6387
+ const keyCheck = this.#checkStableKey(options);
6388
+ if (!keyCheck.ok) return keyCheck;
6387
6389
  const geomResult = roofToSolid(spec);
6388
6390
  if (!geomResult.ok) return err(geomResult.error);
6389
- const id = this.#makeElement("ROOF", spec, geomResult.value);
6391
+ const id = this.#makeElement("ROOF", spec, geomResult.value, options?.stableKey);
6390
6392
  this.#associateMaterial(id, spec);
6391
6393
  this.#associateClassification(id, spec);
6392
6394
  return ok(id);
@@ -6420,8 +6422,10 @@ var BimModel = class {
6420
6422
  * the IFC layer from `spec.flights`; the STAIR element itself carries no solid
6421
6423
  * (the assembly container's Representation is null, valid per IFC4).
6422
6424
  */
6423
- addStair(spec) {
6424
- const id = this.#makeElement("STAIR", spec, null);
6425
+ addStair(spec, options) {
6426
+ const keyCheck = this.#checkStableKey(options);
6427
+ if (!keyCheck.ok) return keyCheck;
6428
+ const id = this.#makeElement("STAIR", spec, null, options?.stableKey);
6425
6429
  this.#associateMaterial(id, spec);
6426
6430
  this.#associateClassification(id, spec);
6427
6431
  return ok(id);
@@ -6430,8 +6434,10 @@ var BimModel = class {
6430
6434
  * Adds an IfcRamp assembly. Geometry for each flight is built and written by the
6431
6435
  * IFC layer from `spec.flights`; the RAMP element carries no solid of its own.
6432
6436
  */
6433
- addRamp(spec) {
6434
- const id = this.#makeElement("RAMP", spec, null);
6437
+ addRamp(spec, options) {
6438
+ const keyCheck = this.#checkStableKey(options);
6439
+ if (!keyCheck.ok) return keyCheck;
6440
+ const id = this.#makeElement("RAMP", spec, null, options?.stableKey);
6435
6441
  this.#associateMaterial(id, spec);
6436
6442
  this.#associateClassification(id, spec);
6437
6443
  return ok(id);
@@ -8078,7 +8084,7 @@ function writeTessellation(w, solid, geomSubContextId, _localPlacementId, tolera
8078
8084
  type: WebIFC.IFCTRIANGULATEDFACESET,
8079
8085
  Coordinates: w.ref(pointListId),
8080
8086
  Normals: null,
8081
- Closed: true,
8087
+ Closed: w.mkType(WebIFC.IFCBOOLEAN, true),
8082
8088
  CoordIndex: coordIndex.map((tri) => tri.map((idx) => w.mkType(WebIFC.IFCPOSITIVEINTEGER, idx))),
8083
8089
  PnIndex: null
8084
8090
  });
@@ -8182,7 +8188,7 @@ function writeFacetedBrepFallback(w, geomSubContextId, reason) {
8182
8188
  expressID: faceOuterBoundId,
8183
8189
  type: WebIFC.IFCFACEOUTERBOUND,
8184
8190
  Bound: w.ref(loopId),
8185
- Orientation: true
8191
+ Orientation: w.mkType(WebIFC.IFCBOOLEAN, true)
8186
8192
  });
8187
8193
  const faceId = w.nextId();
8188
8194
  w.writeLine({
@@ -9607,13 +9613,15 @@ function writeRampEntity(w, guid, name, predefinedType, ownerHistoryId, localPla
9607
9613
  * per `spec.flights[i]` (each with a tessellated stepped-solid body), and a single
9608
9614
  * IfcRelAggregates linking the flights to the stair. Flight placements are
9609
9615
  * relative to the stair placement, which is relative to `parentPlacementId`
9610
- * (typically the storey). GUIDs are deterministic, keyed on `stairKey`/index so
9616
+ * (typically the storey). The assembly's GlobalId is the element's stored guid
9617
+ * (stableKey-derived when the caller provided one); flight, type, and
9618
+ * relationship GUIDs are deterministic, keyed on `stairKey`/index so
9611
9619
  * re-serializing an identical model is byte-stable.
9612
9620
  *
9613
9621
  * Returns a BimError if any flight solid cannot be built. Stair flights are real
9614
9622
  * stepped solids; tessellation failure is flagged via `geometrySimplified`.
9615
9623
  */
9616
- function writeStairAssembly(w, spec, stairKey, ownerHistoryId, geomSubContextId, parentPlacementId) {
9624
+ function writeStairAssembly(w, spec, stairKey, assemblyGuid, ownerHistoryId, geomSubContextId, parentPlacementId) {
9617
9625
  const predefinedType = spec.predefinedType ?? "NOTDEFINED";
9618
9626
  const stairName = spec.name ?? "Stair";
9619
9627
  if (spec.flights[0] === void 0) return {
@@ -9633,7 +9641,7 @@ function writeStairAssembly(w, spec, stairKey, ownerHistoryId, geomSubContextId,
9633
9641
  0,
9634
9642
  0
9635
9643
  ], parentPlacementId);
9636
- const assemblyExpressId = writeStairEntity(w, deriveIfcGuidSync(`elem:STAIR:${stairKey}`), stairName, predefinedType, ownerHistoryId, stairPlacementId);
9644
+ const assemblyExpressId = writeStairEntity(w, assemblyGuid, stairName, predefinedType, ownerHistoryId, stairPlacementId);
9637
9645
  const flightExpressIds = [];
9638
9646
  let geometrySimplified = false;
9639
9647
  for (const [i, flight] of spec.flights.entries()) try {
@@ -9673,7 +9681,7 @@ function writeStairAssembly(w, spec, stairKey, ownerHistoryId, geomSubContextId,
9673
9681
  * inclined-slab solids, so `geometrySimplified` is always true. GUIDs are
9674
9682
  * deterministic keyed on `rampKey`.
9675
9683
  */
9676
- function writeRampAssembly(w, spec, rampKey, ownerHistoryId, geomSubContextId, parentPlacementId) {
9684
+ function writeRampAssembly(w, spec, rampKey, assemblyGuid, ownerHistoryId, geomSubContextId, parentPlacementId) {
9677
9685
  const predefinedType = spec.predefinedType ?? "NOTDEFINED";
9678
9686
  const rampName = spec.name ?? "Ramp";
9679
9687
  if (spec.flights[0] === void 0) return {
@@ -9693,7 +9701,7 @@ function writeRampAssembly(w, spec, rampKey, ownerHistoryId, geomSubContextId, p
9693
9701
  0,
9694
9702
  0
9695
9703
  ], parentPlacementId);
9696
- const assemblyExpressId = writeRampEntity(w, deriveIfcGuidSync(`elem:RAMP:${rampKey}`), rampName, predefinedType, ownerHistoryId, rampPlacementId);
9704
+ const assemblyExpressId = writeRampEntity(w, assemblyGuid, rampName, predefinedType, ownerHistoryId, rampPlacementId);
9697
9705
  const flightExpressIds = [];
9698
9706
  const geometrySimplified = true;
9699
9707
  for (const [i, flight] of spec.flights.entries()) try {
@@ -12252,7 +12260,7 @@ async function toIfc(model, meta) {
12252
12260
  for (const stair of stairs) {
12253
12261
  const containingId = findContainerOf(stair.localId, relationships);
12254
12262
  const storeyPlacementId = containingId !== null ? placementMap.get(containingId) ?? null : null;
12255
- const result = writeStairAssembly(w, stair.spec, `${stair.localId}`, ownerHistoryId, geomSubContextId, storeyPlacementId);
12263
+ const result = writeStairAssembly(w, stair.spec, `${stair.localId}`, stair.guid, ownerHistoryId, geomSubContextId, storeyPlacementId);
12256
12264
  if (!result.ok) return err(result.error);
12257
12265
  idMap.set(stair.localId, result.value.assemblyExpressId);
12258
12266
  writeStairCommonPset(w, ownerHistoryId, result.value.assemblyExpressId, stair.spec);
@@ -12260,7 +12268,7 @@ async function toIfc(model, meta) {
12260
12268
  for (const ramp of ramps) {
12261
12269
  const containingId = findContainerOf(ramp.localId, relationships);
12262
12270
  const storeyPlacementId = containingId !== null ? placementMap.get(containingId) ?? null : null;
12263
- const result = writeRampAssembly(w, ramp.spec, `${ramp.localId}`, ownerHistoryId, geomSubContextId, storeyPlacementId);
12271
+ const result = writeRampAssembly(w, ramp.spec, `${ramp.localId}`, ramp.guid, ownerHistoryId, geomSubContextId, storeyPlacementId);
12264
12272
  if (!result.ok) return err(result.error);
12265
12273
  idMap.set(ramp.localId, result.value.assemblyExpressId);
12266
12274
  writeRampCommonPset(w, ownerHistoryId, result.value.assemblyExpressId, ramp.spec);
@@ -16474,7 +16482,7 @@ function assignNum(target, key, value) {
16474
16482
  * while the IR path serves the viewport and dedup. GlobalIds derive from
16475
16483
  * families key paths (stable under reordering), not insertion order.
16476
16484
  *
16477
- * Scope: Storey containers, Wall/Slab/Column/Beam elements, and wall openings — a
16485
+ * Scope: Storey containers, Wall/Slab/Column/Beam/Roof/Stair elements, and wall openings — a
16478
16486
  * fill-role void (Door/Window family) maps onto addDoor/addWindow, which cut
16479
16487
  * the wall and wire IfcRelVoidsElement + IfcRelFillsElement; the opening and
16480
16488
  * filler GlobalIds derive from the synthesized key paths. Anonymous (non-fill)
@@ -16520,8 +16528,46 @@ var SPEC_ROUTES = {
16520
16528
  Beam: {
16521
16529
  parse: parseBeamSpec,
16522
16530
  add: (m, spec, key) => m.addBeam(spec, { stableKey: key })
16531
+ },
16532
+ Roof: {
16533
+ parse: parseRoofSpec,
16534
+ add: (m, spec, key) => m.addRoof(spec, { stableKey: key })
16535
+ },
16536
+ Stair: {
16537
+ parse: parseStairSpec,
16538
+ add: (m, spec, key) => m.addStair(spec, { stableKey: key }),
16539
+ input: stairSpecInput
16523
16540
  }
16524
16541
  };
16542
+ /** StairSpec has no top-level origin — placement lives per flight — so the
16543
+ * element's folded translate lands on every flight's origin instead. */
16544
+ function stairSpecInput(el) {
16545
+ const base = specInput(el);
16546
+ const fold = base["origin"] ?? [
16547
+ 0,
16548
+ 0,
16549
+ 0
16550
+ ];
16551
+ const flights = Array.isArray(base["flights"]) ? base["flights"] : [];
16552
+ return {
16553
+ ...base,
16554
+ flights: flights.map((f) => {
16555
+ const fo = f["origin"] ?? [
16556
+ 0,
16557
+ 0,
16558
+ 0
16559
+ ];
16560
+ return {
16561
+ ...f,
16562
+ origin: [
16563
+ fo[0] + fold[0],
16564
+ fo[1] + fold[1],
16565
+ fo[2] + fold[2]
16566
+ ]
16567
+ };
16568
+ })
16569
+ };
16570
+ }
16525
16571
  function specRoute(type) {
16526
16572
  return Object.hasOwn(SPEC_ROUTES, type) ? SPEC_ROUTES[type] : void 0;
16527
16573
  }
@@ -16684,7 +16730,7 @@ function familiesToBim(root, options) {
16684
16730
  } else if (route !== void 0) {
16685
16731
  const keyed = requireKeyed(el);
16686
16732
  if (!keyed.ok) return keyed;
16687
- const parsed = route.parse(specInput(el));
16733
+ const parsed = route.parse(("input" in route ? route.input : specInput)(el));
16688
16734
  if (!parsed.ok) return parsed;
16689
16735
  const added = route.add(model, parsed.value, el.keyPath);
16690
16736
  if (!added.ok) return added;
@@ -20,13 +20,15 @@ export interface AssemblyWriteResult {
20
20
  * per `spec.flights[i]` (each with a tessellated stepped-solid body), and a single
21
21
  * IfcRelAggregates linking the flights to the stair. Flight placements are
22
22
  * relative to the stair placement, which is relative to `parentPlacementId`
23
- * (typically the storey). GUIDs are deterministic, keyed on `stairKey`/index so
23
+ * (typically the storey). The assembly's GlobalId is the element's stored guid
24
+ * (stableKey-derived when the caller provided one); flight, type, and
25
+ * relationship GUIDs are deterministic, keyed on `stairKey`/index so
24
26
  * re-serializing an identical model is byte-stable.
25
27
  *
26
28
  * Returns a BimError if any flight solid cannot be built. Stair flights are real
27
29
  * stepped solids; tessellation failure is flagged via `geometrySimplified`.
28
30
  */
29
- export declare function writeStairAssembly(w: IfcWriter, spec: StairSpec, stairKey: string, ownerHistoryId: number, geomSubContextId: number, parentPlacementId: number | null): {
31
+ export declare function writeStairAssembly(w: IfcWriter, spec: StairSpec, stairKey: string, assemblyGuid: string, ownerHistoryId: number, geomSubContextId: number, parentPlacementId: number | null): {
30
32
  ok: true;
31
33
  value: AssemblyWriteResult;
32
34
  } | {
@@ -40,7 +42,7 @@ export declare function writeStairAssembly(w: IfcWriter, spec: StairSpec, stairK
40
42
  * inclined-slab solids, so `geometrySimplified` is always true. GUIDs are
41
43
  * deterministic keyed on `rampKey`.
42
44
  */
43
- export declare function writeRampAssembly(w: IfcWriter, spec: RampSpec, rampKey: string, ownerHistoryId: number, geomSubContextId: number, parentPlacementId: number | null): {
45
+ export declare function writeRampAssembly(w: IfcWriter, spec: RampSpec, rampKey: string, assemblyGuid: string, ownerHistoryId: number, geomSubContextId: number, parentPlacementId: number | null): {
44
46
  ok: true;
45
47
  value: AssemblyWriteResult;
46
48
  } | {
@@ -45,7 +45,7 @@ export declare class BimModel {
45
45
  addBeam(spec: BeamSpec, options?: ElementIdentityOptions): Result<LocalId, BimError>;
46
46
  addColumn(spec: ColumnSpec, options?: ElementIdentityOptions): Result<LocalId, BimError>;
47
47
  addSpace(spec: SpaceSpec): Result<LocalId, BimError>;
48
- addRoof(spec: RoofSpec): Result<LocalId, BimError>;
48
+ addRoof(spec: RoofSpec, options?: ElementIdentityOptions): Result<LocalId, BimError>;
49
49
  addCurtainWall(spec: CurtainWallSpec): Result<LocalId, BimError>;
50
50
  addFooting(spec: FootingSpec): Result<LocalId, BimError>;
51
51
  addPile(spec: PileSpec): Result<LocalId, BimError>;
@@ -54,12 +54,12 @@ export declare class BimModel {
54
54
  * the IFC layer from `spec.flights`; the STAIR element itself carries no solid
55
55
  * (the assembly container's Representation is null, valid per IFC4).
56
56
  */
57
- addStair(spec: StairSpec): Result<LocalId, BimError>;
57
+ addStair(spec: StairSpec, options?: ElementIdentityOptions): Result<LocalId, BimError>;
58
58
  /**
59
59
  * Adds an IfcRamp assembly. Geometry for each flight is built and written by the
60
60
  * IFC layer from `spec.flights`; the RAMP element carries no solid of its own.
61
61
  */
62
- addRamp(spec: RampSpec): Result<LocalId, BimError>;
62
+ addRamp(spec: RampSpec, options?: ElementIdentityOptions): Result<LocalId, BimError>;
63
63
  addRailing(spec: RailingSpec): Result<LocalId, BimError>;
64
64
  /**
65
65
  * Adds an IfcCovering. When `hostLocalId` is supplied, an
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brepjs-bim",
3
- "version": "0.11.0",
3
+ "version": "0.13.0",
4
4
  "description": "BIM layer for brepjs — IFC4-aligned parametric building elements",
5
5
  "keywords": [
6
6
  "bim",
@@ -43,6 +43,7 @@
43
43
  "build": "vite build",
44
44
  "typecheck": "tsgo --noEmit",
45
45
  "test": "vitest run",
46
+ "test:coverage": "vitest run --coverage",
46
47
  "lint": "eslint src tests"
47
48
  },
48
49
  "peerDependencies": {