brepjs-bim 0.16.1 → 0.17.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.
package/README.md CHANGED
@@ -23,7 +23,8 @@ curtain walls, a panel/mullion grid). Element geometry is **unplaced template ge
23
23
  coordinates — placement (`origin` / `axisX` / `axisZ`) is applied by the IFC layer via
24
24
  `IfcLocalPlacement`, not baked into the brepjs solid. Use `placedSolids(element)` to read an
25
25
  element's geometry already transformed to its world placement as fresh, caller-owned solids
26
- (stairs return one solid per flight) handy for display so the on-screen scene matches the IFC
26
+ (stairs and ramps return one solid per flight, curtain walls their panels and mullions) handy
27
+ for display so the on-screen scene matches the IFC
27
28
  export.
28
29
 
29
30
  - Units default to mm; IFC export emits SI metres.
@@ -35,18 +36,18 @@ export.
35
36
 
36
37
  ## Status
37
38
 
38
- | Area | State |
39
- | ----------------- | -------------------------------------------------------------------------------------------------------- |
40
- | Elements | wall, slab, beam, column, roof, curtain wall, space, footing/pile, stair, ramp, railing, covering, proxy |
41
- | Profiles | rectangular / circular / I-shape cores + extended L/T/U/Z/C, hollow, ellipse, arbitrary-with-voids |
42
- | Openings | door / window / slab openings cut as boolean voids; `FillsOpening` / `Voids*` relationships |
43
- | Spatial structure | project → site → building → storey aggregation; `placeIn` to assign elements to a storey |
44
- | Property sets | IFC pset templates + measure types; quantity sets for takeoff |
45
- | Data layers | materials (layer/profile/simple sets), classification refs, surface styles, zones/systems |
46
- | IFC export | `toIfc` → IFC-SPF (`Uint8Array`); IFC4 / IFC4X3 schema selection; owner history |
47
- | IFC import | `fromIfc` / `SpfReader` → `ImportedModel` (elements, geometry, psets, materials, spatial tree) |
48
- | Validation | referential integrity, schema check, geometry validity, IFC round-trip report |
49
- | Interop | COBie 2.4 export (CSV/JSON), IDS 1.0 checking, BCF 3.0 read/write |
39
+ | Area | State |
40
+ | ----------------- | ---------------------------------------------------------------------------------------------------------- |
41
+ | Elements | wall, slab, beam, column, roof, curtain wall, space, footing/pile, stair, ramp, railing, covering, proxy |
42
+ | Profiles | rectangular / circular / I-shape cores + extended L/T/U/Z/C, hollow, ellipse, arbitrary-with-voids |
43
+ | Openings | door / window / slab openings cut as boolean voids; `FillsOpening` / `Voids*` relationships |
44
+ | Spatial structure | project → site → building → storey aggregation; `placeIn` to assign elements to a storey |
45
+ | Property sets | IFC pset templates + measure types; quantity sets for takeoff |
46
+ | Data layers | materials (layer/profile/simple sets), classification refs, surface styles, zones/systems |
47
+ | IFC export | `toIfc` → IFC-SPF (`Uint8Array`); IFC4 / IFC4X3 schema selection; owner history |
48
+ | IFC import | `fromIfc` / `SpfReader` → `ImportedModel` (elements, geometry, psets, materials, spatial tree) |
49
+ | Validation | referential integrity, schema check, geometry validity, IFC round-trip report, buildingSMART gherkin rules |
50
+ | Interop | COBie 2.4 export (CSV/JSON), IDS 1.0 checking, BCF 3.0 read/write |
50
51
 
51
52
  ### Independent validation
52
53
 
@@ -56,9 +57,13 @@ web-ifc parser used internally), not just self-checked. The committed sample
56
57
  validator and generates geometry for every product. See [VALIDATION.md](./VALIDATION.md)
57
58
  to reproduce, and `examples/sampleBuilding.mjs` for the model it validates.
58
59
 
59
- > **Not yet:** the official buildingSMART Validation Service and desktop-tool
60
- > interop (Revit / Solibri) are unverified the fixtures and per-tool
61
- > checklists are ready in [VALIDATION.md](./VALIDATION.md). This is an
60
+ The buildingSMART Validation Service's complete normative rule catalog also runs
61
+ locally (`scripts/setupGherkinRunner.sh` builds the service's own engine; all three
62
+ committed fixtures pass 950 scenarios with zero failures), so service findings are
63
+ reproducible before upload.
64
+
65
+ > **Not yet:** desktop-tool interop (Revit / Solibri) is unverified. The fixtures
66
+ > and per-tool checklists are ready in [VALIDATION.md](./VALIDATION.md). This is an
62
67
  > experimental pre-1.0 package and the API may change.
63
68
 
64
69
  ## Usage
@@ -98,7 +103,7 @@ if (wall.ok) model.placeIn(wall.value, storeyId);
98
103
  const solid = model.getWalls()[0]?.geometry;
99
104
 
100
105
  // Serialize to an IFC-SPF byte buffer.
101
- const ifc = await toIfc(model, { name: 'Example', author: 'brepjs-bim' });
106
+ const ifc = await toIfc(model, { applicationName: 'brepjs-bim', applicationVersion: '1.0' });
102
107
  // ifc.ok && ifc.value instanceof Uint8Array
103
108
  ```
104
109
 
@@ -7314,6 +7314,65 @@ function stairFlightToSolid(spec) {
7314
7314
  }
7315
7315
  }
7316
7316
  //#endregion
7317
+ //#region src/elementFns/rampFns.ts
7318
+ function buildSilhouette(length, rise, thickness) {
7319
+ return [
7320
+ [
7321
+ 0,
7322
+ 0,
7323
+ -thickness
7324
+ ],
7325
+ [
7326
+ length,
7327
+ 0,
7328
+ rise - thickness
7329
+ ],
7330
+ [
7331
+ length,
7332
+ 0,
7333
+ rise
7334
+ ],
7335
+ [
7336
+ 0,
7337
+ 0,
7338
+ 0
7339
+ ]
7340
+ ];
7341
+ }
7342
+ function rampFlightToSolid(spec) {
7343
+ try {
7344
+ var _usingCtx$4 = _usingCtx();
7345
+ if (spec.width <= 0) return (0, brepjs.err)(specError("RAMP_FLIGHT_ZERO_WIDTH", "Ramp flight width must be positive"));
7346
+ if (spec.length <= 0) return (0, brepjs.err)(specError("RAMP_FLIGHT_ZERO_LENGTH", "Ramp flight length must be positive"));
7347
+ if (spec.slope <= 0) return (0, brepjs.err)(specError("RAMP_FLIGHT_ZERO_SLOPE", "Ramp flight slope must be positive"));
7348
+ if (spec.thickness <= 0) return (0, brepjs.err)(specError("RAMP_FLIGHT_ZERO_THICKNESS", "Ramp flight thickness must be positive"));
7349
+ const rise = spec.length * spec.slope;
7350
+ const silhouette = buildSilhouette(spec.length, rise, spec.thickness);
7351
+ const profileResult = (0, brepjs.polygon)(silhouette);
7352
+ if (!profileResult.ok) return (0, brepjs.err)(fromBrepError(profileResult.error, "RAMP_FLIGHT_PROFILE_FAILED", "Failed to create ramp flight silhouette profile"));
7353
+ const profile = _usingCtx$4.u(profileResult.value);
7354
+ const solidResult = (0, brepjs.extrude)(profile, [
7355
+ 0,
7356
+ spec.width,
7357
+ 0
7358
+ ]);
7359
+ if (!solidResult.ok) return (0, brepjs.err)(fromBrepError(solidResult.error, "RAMP_FLIGHT_EXTRUDE_FAILED", "Failed to extrude ramp flight silhouette"));
7360
+ const solid = solidResult.value;
7361
+ if (!(0, brepjs.isValidSolid)(solid)) {
7362
+ solid[Symbol.dispose]();
7363
+ return (0, brepjs.err)(geometryError("RAMP_FLIGHT_INVALID_SOLID", "Ramp flight solid failed validity check"));
7364
+ }
7365
+ return (0, brepjs.ok)({
7366
+ solid,
7367
+ geometrySimplified: true
7368
+ });
7369
+ } catch (_) {
7370
+ _usingCtx$4.e = _;
7371
+ } finally {
7372
+ _usingCtx$4.d();
7373
+ }
7374
+ }
7375
+ //#endregion
7317
7376
  //#region src/elementFns/placedGeometry.ts
7318
7377
  function place(solid, frame) {
7319
7378
  const result = (0, brepjs.applyMatrix)(solid, placementToMatrix(frame));
@@ -7332,10 +7391,12 @@ function disposeAll(solids) {
7332
7391
  * failure the solids already built for this call are disposed before the error is
7333
7392
  * returned, so no partial array is leaked.
7334
7393
  *
7335
- * Stairs carry no element solid (`.geometry` is null), so flight solids are built
7336
- * from `spec.flights` and placed per flight. Curtain walls return placed panels +
7337
- * mullions. Elements with no solid geometry (doors/windows/ramps/groups/spatial)
7338
- * return an empty array.
7394
+ * Stairs and ramps carry no element solid (`.geometry` is null), so flight
7395
+ * solids are built from `spec.flights` and placed per flight. Curtain walls
7396
+ * return placed panels + mullions. Proxies are authored in world coordinates
7397
+ * (no placement frame), so their solid is returned as a fresh identity-placed
7398
+ * copy. Elements with no solid geometry (doors/windows/groups/spatial) return
7399
+ * an empty array.
7339
7400
  */
7340
7401
  function placedSolids(el) {
7341
7402
  switch (el.category) {
@@ -7347,6 +7408,7 @@ function placedSolids(el) {
7347
7408
  case "ROOF":
7348
7409
  case "FOOTING":
7349
7410
  case "PILE":
7411
+ case "COVERING":
7350
7412
  case "RAILING": {
7351
7413
  const placed = place(el.geometry, el.spec);
7352
7414
  if (!placed.ok) return placed;
@@ -7355,29 +7417,72 @@ function placedSolids(el) {
7355
7417
  case "STAIR": {
7356
7418
  const out = [];
7357
7419
  for (const flight of el.spec.flights) try {
7358
- var _usingCtx$4 = _usingCtx();
7420
+ var _usingCtx$3 = _usingCtx();
7359
7421
  const built = stairFlightToSolid(flight);
7360
7422
  if (!built.ok) {
7361
7423
  disposeAll(out);
7362
7424
  return (0, brepjs.err)(built.error);
7363
7425
  }
7364
- const placed = place(_usingCtx$4.u(built.value.solid), flight);
7426
+ const placed = place(_usingCtx$3.u(built.value.solid), flight);
7427
+ if (!placed.ok) {
7428
+ disposeAll(out);
7429
+ return placed;
7430
+ }
7431
+ out.push(placed.value);
7432
+ } catch (_) {
7433
+ _usingCtx$3.e = _;
7434
+ } finally {
7435
+ _usingCtx$3.d();
7436
+ }
7437
+ return (0, brepjs.ok)(out);
7438
+ }
7439
+ case "RAMP": {
7440
+ const out = [];
7441
+ for (const flight of el.spec.flights) try {
7442
+ var _usingCtx3 = _usingCtx();
7443
+ const built = rampFlightToSolid(flight);
7444
+ if (!built.ok) {
7445
+ disposeAll(out);
7446
+ return (0, brepjs.err)(built.error);
7447
+ }
7448
+ const placed = place(_usingCtx3.u(built.value.solid), flight);
7365
7449
  if (!placed.ok) {
7366
7450
  disposeAll(out);
7367
7451
  return placed;
7368
7452
  }
7369
7453
  out.push(placed.value);
7370
7454
  } catch (_) {
7371
- _usingCtx$4.e = _;
7455
+ _usingCtx3.e = _;
7372
7456
  } finally {
7373
- _usingCtx$4.d();
7457
+ _usingCtx3.d();
7374
7458
  }
7375
7459
  return (0, brepjs.ok)(out);
7376
7460
  }
7461
+ case "PROXY": {
7462
+ const placed = place(el.geometry, {
7463
+ origin: [
7464
+ 0,
7465
+ 0,
7466
+ 0
7467
+ ],
7468
+ axisX: [
7469
+ 1,
7470
+ 0,
7471
+ 0
7472
+ ],
7473
+ axisZ: [
7474
+ 0,
7475
+ 0,
7476
+ 1
7477
+ ]
7478
+ });
7479
+ if (!placed.ok) return placed;
7480
+ return (0, brepjs.ok)([placed.value]);
7481
+ }
7377
7482
  case "CURTAIN_WALL": {
7378
7483
  const out = [];
7379
7484
  for (const c of [...el.geometry.panels, ...el.geometry.mullions]) try {
7380
- var _usingCtx3 = _usingCtx();
7485
+ var _usingCtx4 = _usingCtx();
7381
7486
  const componentLocal = place(c.solid, {
7382
7487
  origin: c.origin,
7383
7488
  axisX: [
@@ -7395,16 +7500,16 @@ function placedSolids(el) {
7395
7500
  disposeAll(out);
7396
7501
  return componentLocal;
7397
7502
  }
7398
- const placed = place(_usingCtx3.u(componentLocal.value), el.spec);
7503
+ const placed = place(_usingCtx4.u(componentLocal.value), el.spec);
7399
7504
  if (!placed.ok) {
7400
7505
  disposeAll(out);
7401
7506
  return placed;
7402
7507
  }
7403
7508
  out.push(placed.value);
7404
7509
  } catch (_) {
7405
- _usingCtx3.e = _;
7510
+ _usingCtx4.e = _;
7406
7511
  } finally {
7407
- _usingCtx3.d();
7512
+ _usingCtx4.d();
7408
7513
  }
7409
7514
  return (0, brepjs.ok)(out);
7410
7515
  }
@@ -9491,65 +9596,6 @@ function writeRelContainedInSpatialStructure(w, guid, ownerHistoryId, relatingSt
9491
9596
  });
9492
9597
  }
9493
9598
  //#endregion
9494
- //#region src/elementFns/rampFns.ts
9495
- function buildSilhouette(length, rise, thickness) {
9496
- return [
9497
- [
9498
- 0,
9499
- 0,
9500
- -thickness
9501
- ],
9502
- [
9503
- length,
9504
- 0,
9505
- rise - thickness
9506
- ],
9507
- [
9508
- length,
9509
- 0,
9510
- rise
9511
- ],
9512
- [
9513
- 0,
9514
- 0,
9515
- 0
9516
- ]
9517
- ];
9518
- }
9519
- function rampFlightToSolid(spec) {
9520
- try {
9521
- var _usingCtx$3 = _usingCtx();
9522
- if (spec.width <= 0) return (0, brepjs.err)(specError("RAMP_FLIGHT_ZERO_WIDTH", "Ramp flight width must be positive"));
9523
- if (spec.length <= 0) return (0, brepjs.err)(specError("RAMP_FLIGHT_ZERO_LENGTH", "Ramp flight length must be positive"));
9524
- if (spec.slope <= 0) return (0, brepjs.err)(specError("RAMP_FLIGHT_ZERO_SLOPE", "Ramp flight slope must be positive"));
9525
- if (spec.thickness <= 0) return (0, brepjs.err)(specError("RAMP_FLIGHT_ZERO_THICKNESS", "Ramp flight thickness must be positive"));
9526
- const rise = spec.length * spec.slope;
9527
- const silhouette = buildSilhouette(spec.length, rise, spec.thickness);
9528
- const profileResult = (0, brepjs.polygon)(silhouette);
9529
- if (!profileResult.ok) return (0, brepjs.err)(fromBrepError(profileResult.error, "RAMP_FLIGHT_PROFILE_FAILED", "Failed to create ramp flight silhouette profile"));
9530
- const profile = _usingCtx$3.u(profileResult.value);
9531
- const solidResult = (0, brepjs.extrude)(profile, [
9532
- 0,
9533
- spec.width,
9534
- 0
9535
- ]);
9536
- if (!solidResult.ok) return (0, brepjs.err)(fromBrepError(solidResult.error, "RAMP_FLIGHT_EXTRUDE_FAILED", "Failed to extrude ramp flight silhouette"));
9537
- const solid = solidResult.value;
9538
- if (!(0, brepjs.isValidSolid)(solid)) {
9539
- solid[Symbol.dispose]();
9540
- return (0, brepjs.err)(geometryError("RAMP_FLIGHT_INVALID_SOLID", "Ramp flight solid failed validity check"));
9541
- }
9542
- return (0, brepjs.ok)({
9543
- solid,
9544
- geometrySimplified: true
9545
- });
9546
- } catch (_) {
9547
- _usingCtx$3.e = _;
9548
- } finally {
9549
- _usingCtx$3.d();
9550
- }
9551
- }
9552
- //#endregion
9553
9599
  //#region src/ifc-writer/stairWriter.ts
9554
9600
  function writeLocalPlacement(w, origin, axisZ, axisX, parentPlacementId) {
9555
9601
  const placement3DId = writeAxis2Placement3D(w, origin.map(toIfcLengthM), axisZ, axisX);
@@ -7291,6 +7291,65 @@ function stairFlightToSolid(spec) {
7291
7291
  }
7292
7292
  }
7293
7293
  //#endregion
7294
+ //#region src/elementFns/rampFns.ts
7295
+ function buildSilhouette(length, rise, thickness) {
7296
+ return [
7297
+ [
7298
+ 0,
7299
+ 0,
7300
+ -thickness
7301
+ ],
7302
+ [
7303
+ length,
7304
+ 0,
7305
+ rise - thickness
7306
+ ],
7307
+ [
7308
+ length,
7309
+ 0,
7310
+ rise
7311
+ ],
7312
+ [
7313
+ 0,
7314
+ 0,
7315
+ 0
7316
+ ]
7317
+ ];
7318
+ }
7319
+ function rampFlightToSolid(spec) {
7320
+ try {
7321
+ var _usingCtx$4 = _usingCtx();
7322
+ if (spec.width <= 0) return err(specError("RAMP_FLIGHT_ZERO_WIDTH", "Ramp flight width must be positive"));
7323
+ if (spec.length <= 0) return err(specError("RAMP_FLIGHT_ZERO_LENGTH", "Ramp flight length must be positive"));
7324
+ if (spec.slope <= 0) return err(specError("RAMP_FLIGHT_ZERO_SLOPE", "Ramp flight slope must be positive"));
7325
+ if (spec.thickness <= 0) return err(specError("RAMP_FLIGHT_ZERO_THICKNESS", "Ramp flight thickness must be positive"));
7326
+ const rise = spec.length * spec.slope;
7327
+ const silhouette = buildSilhouette(spec.length, rise, spec.thickness);
7328
+ const profileResult = polygon(silhouette);
7329
+ if (!profileResult.ok) return err(fromBrepError(profileResult.error, "RAMP_FLIGHT_PROFILE_FAILED", "Failed to create ramp flight silhouette profile"));
7330
+ const profile = _usingCtx$4.u(profileResult.value);
7331
+ const solidResult = extrude(profile, [
7332
+ 0,
7333
+ spec.width,
7334
+ 0
7335
+ ]);
7336
+ if (!solidResult.ok) return err(fromBrepError(solidResult.error, "RAMP_FLIGHT_EXTRUDE_FAILED", "Failed to extrude ramp flight silhouette"));
7337
+ const solid = solidResult.value;
7338
+ if (!isValidSolid(solid)) {
7339
+ solid[Symbol.dispose]();
7340
+ return err(geometryError("RAMP_FLIGHT_INVALID_SOLID", "Ramp flight solid failed validity check"));
7341
+ }
7342
+ return ok({
7343
+ solid,
7344
+ geometrySimplified: true
7345
+ });
7346
+ } catch (_) {
7347
+ _usingCtx$4.e = _;
7348
+ } finally {
7349
+ _usingCtx$4.d();
7350
+ }
7351
+ }
7352
+ //#endregion
7294
7353
  //#region src/elementFns/placedGeometry.ts
7295
7354
  function place(solid, frame) {
7296
7355
  const result = applyMatrix(solid, placementToMatrix(frame));
@@ -7309,10 +7368,12 @@ function disposeAll(solids) {
7309
7368
  * failure the solids already built for this call are disposed before the error is
7310
7369
  * returned, so no partial array is leaked.
7311
7370
  *
7312
- * Stairs carry no element solid (`.geometry` is null), so flight solids are built
7313
- * from `spec.flights` and placed per flight. Curtain walls return placed panels +
7314
- * mullions. Elements with no solid geometry (doors/windows/ramps/groups/spatial)
7315
- * return an empty array.
7371
+ * Stairs and ramps carry no element solid (`.geometry` is null), so flight
7372
+ * solids are built from `spec.flights` and placed per flight. Curtain walls
7373
+ * return placed panels + mullions. Proxies are authored in world coordinates
7374
+ * (no placement frame), so their solid is returned as a fresh identity-placed
7375
+ * copy. Elements with no solid geometry (doors/windows/groups/spatial) return
7376
+ * an empty array.
7316
7377
  */
7317
7378
  function placedSolids(el) {
7318
7379
  switch (el.category) {
@@ -7324,6 +7385,7 @@ function placedSolids(el) {
7324
7385
  case "ROOF":
7325
7386
  case "FOOTING":
7326
7387
  case "PILE":
7388
+ case "COVERING":
7327
7389
  case "RAILING": {
7328
7390
  const placed = place(el.geometry, el.spec);
7329
7391
  if (!placed.ok) return placed;
@@ -7332,29 +7394,72 @@ function placedSolids(el) {
7332
7394
  case "STAIR": {
7333
7395
  const out = [];
7334
7396
  for (const flight of el.spec.flights) try {
7335
- var _usingCtx$4 = _usingCtx();
7397
+ var _usingCtx$3 = _usingCtx();
7336
7398
  const built = stairFlightToSolid(flight);
7337
7399
  if (!built.ok) {
7338
7400
  disposeAll(out);
7339
7401
  return err(built.error);
7340
7402
  }
7341
- const placed = place(_usingCtx$4.u(built.value.solid), flight);
7403
+ const placed = place(_usingCtx$3.u(built.value.solid), flight);
7404
+ if (!placed.ok) {
7405
+ disposeAll(out);
7406
+ return placed;
7407
+ }
7408
+ out.push(placed.value);
7409
+ } catch (_) {
7410
+ _usingCtx$3.e = _;
7411
+ } finally {
7412
+ _usingCtx$3.d();
7413
+ }
7414
+ return ok(out);
7415
+ }
7416
+ case "RAMP": {
7417
+ const out = [];
7418
+ for (const flight of el.spec.flights) try {
7419
+ var _usingCtx3 = _usingCtx();
7420
+ const built = rampFlightToSolid(flight);
7421
+ if (!built.ok) {
7422
+ disposeAll(out);
7423
+ return err(built.error);
7424
+ }
7425
+ const placed = place(_usingCtx3.u(built.value.solid), flight);
7342
7426
  if (!placed.ok) {
7343
7427
  disposeAll(out);
7344
7428
  return placed;
7345
7429
  }
7346
7430
  out.push(placed.value);
7347
7431
  } catch (_) {
7348
- _usingCtx$4.e = _;
7432
+ _usingCtx3.e = _;
7349
7433
  } finally {
7350
- _usingCtx$4.d();
7434
+ _usingCtx3.d();
7351
7435
  }
7352
7436
  return ok(out);
7353
7437
  }
7438
+ case "PROXY": {
7439
+ const placed = place(el.geometry, {
7440
+ origin: [
7441
+ 0,
7442
+ 0,
7443
+ 0
7444
+ ],
7445
+ axisX: [
7446
+ 1,
7447
+ 0,
7448
+ 0
7449
+ ],
7450
+ axisZ: [
7451
+ 0,
7452
+ 0,
7453
+ 1
7454
+ ]
7455
+ });
7456
+ if (!placed.ok) return placed;
7457
+ return ok([placed.value]);
7458
+ }
7354
7459
  case "CURTAIN_WALL": {
7355
7460
  const out = [];
7356
7461
  for (const c of [...el.geometry.panels, ...el.geometry.mullions]) try {
7357
- var _usingCtx3 = _usingCtx();
7462
+ var _usingCtx4 = _usingCtx();
7358
7463
  const componentLocal = place(c.solid, {
7359
7464
  origin: c.origin,
7360
7465
  axisX: [
@@ -7372,16 +7477,16 @@ function placedSolids(el) {
7372
7477
  disposeAll(out);
7373
7478
  return componentLocal;
7374
7479
  }
7375
- const placed = place(_usingCtx3.u(componentLocal.value), el.spec);
7480
+ const placed = place(_usingCtx4.u(componentLocal.value), el.spec);
7376
7481
  if (!placed.ok) {
7377
7482
  disposeAll(out);
7378
7483
  return placed;
7379
7484
  }
7380
7485
  out.push(placed.value);
7381
7486
  } catch (_) {
7382
- _usingCtx3.e = _;
7487
+ _usingCtx4.e = _;
7383
7488
  } finally {
7384
- _usingCtx3.d();
7489
+ _usingCtx4.d();
7385
7490
  }
7386
7491
  return ok(out);
7387
7492
  }
@@ -9468,65 +9573,6 @@ function writeRelContainedInSpatialStructure(w, guid, ownerHistoryId, relatingSt
9468
9573
  });
9469
9574
  }
9470
9575
  //#endregion
9471
- //#region src/elementFns/rampFns.ts
9472
- function buildSilhouette(length, rise, thickness) {
9473
- return [
9474
- [
9475
- 0,
9476
- 0,
9477
- -thickness
9478
- ],
9479
- [
9480
- length,
9481
- 0,
9482
- rise - thickness
9483
- ],
9484
- [
9485
- length,
9486
- 0,
9487
- rise
9488
- ],
9489
- [
9490
- 0,
9491
- 0,
9492
- 0
9493
- ]
9494
- ];
9495
- }
9496
- function rampFlightToSolid(spec) {
9497
- try {
9498
- var _usingCtx$3 = _usingCtx();
9499
- if (spec.width <= 0) return err(specError("RAMP_FLIGHT_ZERO_WIDTH", "Ramp flight width must be positive"));
9500
- if (spec.length <= 0) return err(specError("RAMP_FLIGHT_ZERO_LENGTH", "Ramp flight length must be positive"));
9501
- if (spec.slope <= 0) return err(specError("RAMP_FLIGHT_ZERO_SLOPE", "Ramp flight slope must be positive"));
9502
- if (spec.thickness <= 0) return err(specError("RAMP_FLIGHT_ZERO_THICKNESS", "Ramp flight thickness must be positive"));
9503
- const rise = spec.length * spec.slope;
9504
- const silhouette = buildSilhouette(spec.length, rise, spec.thickness);
9505
- const profileResult = polygon(silhouette);
9506
- if (!profileResult.ok) return err(fromBrepError(profileResult.error, "RAMP_FLIGHT_PROFILE_FAILED", "Failed to create ramp flight silhouette profile"));
9507
- const profile = _usingCtx$3.u(profileResult.value);
9508
- const solidResult = extrude(profile, [
9509
- 0,
9510
- spec.width,
9511
- 0
9512
- ]);
9513
- if (!solidResult.ok) return err(fromBrepError(solidResult.error, "RAMP_FLIGHT_EXTRUDE_FAILED", "Failed to extrude ramp flight silhouette"));
9514
- const solid = solidResult.value;
9515
- if (!isValidSolid(solid)) {
9516
- solid[Symbol.dispose]();
9517
- return err(geometryError("RAMP_FLIGHT_INVALID_SOLID", "Ramp flight solid failed validity check"));
9518
- }
9519
- return ok({
9520
- solid,
9521
- geometrySimplified: true
9522
- });
9523
- } catch (_) {
9524
- _usingCtx$3.e = _;
9525
- } finally {
9526
- _usingCtx$3.d();
9527
- }
9528
- }
9529
- //#endregion
9530
9576
  //#region src/ifc-writer/stairWriter.ts
9531
9577
  function writeLocalPlacement(w, origin, axisZ, axisX, parentPlacementId) {
9532
9578
  const placement3DId = writeAxis2Placement3D(w, origin.map(toIfcLengthM), axisZ, axisX);
@@ -10,9 +10,11 @@ import { BimError } from '../errors/bimError.js';
10
10
  * failure the solids already built for this call are disposed before the error is
11
11
  * returned, so no partial array is leaked.
12
12
  *
13
- * Stairs carry no element solid (`.geometry` is null), so flight solids are built
14
- * from `spec.flights` and placed per flight. Curtain walls return placed panels +
15
- * mullions. Elements with no solid geometry (doors/windows/ramps/groups/spatial)
16
- * return an empty array.
13
+ * Stairs and ramps carry no element solid (`.geometry` is null), so flight
14
+ * solids are built from `spec.flights` and placed per flight. Curtain walls
15
+ * return placed panels + mullions. Proxies are authored in world coordinates
16
+ * (no placement frame), so their solid is returned as a fresh identity-placed
17
+ * copy. Elements with no solid geometry (doors/windows/groups/spatial) return
18
+ * an empty array.
17
19
  */
18
20
  export declare function placedSolids(el: AnyBimElement): Result<readonly ValidSolid[], BimError>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brepjs-bim",
3
- "version": "0.16.1",
3
+ "version": "0.17.1",
4
4
  "description": "BIM layer for brepjs — IFC4-aligned parametric building elements",
5
5
  "keywords": [
6
6
  "bim",