brepjs-bim 0.23.2 → 0.24.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 +31 -11
- package/dist/brepjs-bim.cjs +1263 -734
- package/dist/brepjs-bim.js +1255 -727
- package/dist/elementFns/placedGeometry.d.ts +5 -0
- package/dist/errors/bimError.d.ts +1 -1
- package/dist/familiesAdapter.d.ts +15 -3
- package/dist/familiesProductBody.d.ts +40 -0
- package/dist/ifc-writer/ifcWriter.d.ts +16 -0
- package/dist/ifc-writer/psetWriter.d.ts +6 -0
- package/dist/ifc-writer/tessellationWriter.d.ts +26 -0
- package/dist/index.d.ts +2 -0
- package/dist/model/bimModel.d.ts +9 -0
- package/dist/rigidPlacement.d.ts +4 -0
- package/dist/serialize/exactBodyPreflight.d.ts +15 -0
- package/dist/serialize/exactWallQuantities.d.ts +20 -0
- package/dist/types/bimTypes.d.ts +2 -1
- package/dist/types/productBody.d.ts +13 -0
- package/package.json +1 -1
package/dist/brepjs-bim.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { addHoles, applyMatrix, autoHeal, box, castShape, clone, convexHull, cut, err, extrude, fuse, getBounds, getKernel, getSolids, isClosedWire, isOk, isPlanarWire, isSolid, isValid, isValidSolid, measureVolume, mesh, ok, outerWire, polygon, revolve, rotate, translate, validSolid } from "brepjs";
|
|
1
|
+
import { addHoles, applyMatrix, autoHeal, box, castShape, clone, convexHull, cut, err, extrude, fuse, fuseAll, getBounds, getKernel, getSolids, isClosedWire, isOk, isPlanarWire, isSolid, isValid, isValidSolid, locate, measureVolume, mesh, ok, outerWire, polygon, revolve, rotate, translate, validSolid } from "brepjs";
|
|
2
2
|
import * as WebIFC from "web-ifc";
|
|
3
3
|
import { Handle, IfcAPI } from "web-ifc";
|
|
4
4
|
//#region src/identity/ifcGuid.ts
|
|
@@ -111,12 +111,13 @@ function specError(code, message, cause) {
|
|
|
111
111
|
cause
|
|
112
112
|
};
|
|
113
113
|
}
|
|
114
|
-
function ifcError(code, message, cause) {
|
|
114
|
+
function ifcError(code, message, cause, metadata) {
|
|
115
115
|
return {
|
|
116
116
|
kind: "BIM_IFC",
|
|
117
117
|
code,
|
|
118
118
|
message,
|
|
119
|
-
cause
|
|
119
|
+
cause,
|
|
120
|
+
...metadata !== void 0 ? { metadata } : {}
|
|
120
121
|
};
|
|
121
122
|
}
|
|
122
123
|
function geometryError(code, message, cause) {
|
|
@@ -242,7 +243,7 @@ function _usingCtx() {
|
|
|
242
243
|
//#region src/elementFns/wallFns.ts
|
|
243
244
|
function wallToSolid(spec) {
|
|
244
245
|
try {
|
|
245
|
-
var _usingCtx$
|
|
246
|
+
var _usingCtx$20 = _usingCtx();
|
|
246
247
|
if (spec.length <= 0) return err(specError("WALL_ZERO_LENGTH", "Wall length must be positive"));
|
|
247
248
|
if (spec.height <= 0) return err(specError("WALL_ZERO_HEIGHT", "Wall height must be positive"));
|
|
248
249
|
if (spec.thickness <= 0) return err(specError("WALL_ZERO_THICKNESS", "Wall thickness must be positive"));
|
|
@@ -270,7 +271,7 @@ function wallToSolid(spec) {
|
|
|
270
271
|
]
|
|
271
272
|
]);
|
|
272
273
|
if (!profileResult.ok) return err(fromBrepError(profileResult.error, "WALL_PROFILE_FAILED", "Failed to create wall profile"));
|
|
273
|
-
const profile = _usingCtx$
|
|
274
|
+
const profile = _usingCtx$20.u(profileResult.value);
|
|
274
275
|
const solidResult = extrude(profile, [
|
|
275
276
|
length,
|
|
276
277
|
0,
|
|
@@ -284,16 +285,16 @@ function wallToSolid(spec) {
|
|
|
284
285
|
}
|
|
285
286
|
return ok(solid);
|
|
286
287
|
} catch (_) {
|
|
287
|
-
_usingCtx$
|
|
288
|
+
_usingCtx$20.e = _;
|
|
288
289
|
} finally {
|
|
289
|
-
_usingCtx$
|
|
290
|
+
_usingCtx$20.d();
|
|
290
291
|
}
|
|
291
292
|
}
|
|
292
293
|
//#endregion
|
|
293
294
|
//#region src/elementFns/slabFns.ts
|
|
294
295
|
function slabToSolid(spec) {
|
|
295
296
|
try {
|
|
296
|
-
var _usingCtx$
|
|
297
|
+
var _usingCtx$19 = _usingCtx();
|
|
297
298
|
if (spec.length <= 0) return err(specError("SLAB_ZERO_LENGTH", "Slab length must be positive"));
|
|
298
299
|
if (spec.width <= 0) return err(specError("SLAB_ZERO_WIDTH", "Slab width must be positive"));
|
|
299
300
|
if (spec.thickness <= 0) return err(specError("SLAB_ZERO_THICKNESS", "Slab thickness must be positive"));
|
|
@@ -321,7 +322,7 @@ function slabToSolid(spec) {
|
|
|
321
322
|
]
|
|
322
323
|
]);
|
|
323
324
|
if (!profileResult.ok) return err(fromBrepError(profileResult.error, "SLAB_PROFILE_FAILED", "Failed to create slab profile"));
|
|
324
|
-
const profile = _usingCtx$
|
|
325
|
+
const profile = _usingCtx$19.u(profileResult.value);
|
|
325
326
|
const solidResult = extrude(profile, [
|
|
326
327
|
0,
|
|
327
328
|
0,
|
|
@@ -335,9 +336,9 @@ function slabToSolid(spec) {
|
|
|
335
336
|
}
|
|
336
337
|
return ok(solid);
|
|
337
338
|
} catch (_) {
|
|
338
|
-
_usingCtx$
|
|
339
|
+
_usingCtx$19.e = _;
|
|
339
340
|
} finally {
|
|
340
|
-
_usingCtx$
|
|
341
|
+
_usingCtx$19.d();
|
|
341
342
|
}
|
|
342
343
|
}
|
|
343
344
|
//#endregion
|
|
@@ -5025,14 +5026,14 @@ function to3D(points) {
|
|
|
5025
5026
|
}
|
|
5026
5027
|
function extendedProfileToFace(profile) {
|
|
5027
5028
|
try {
|
|
5028
|
-
var _usingCtx$
|
|
5029
|
+
var _usingCtx$18 = _usingCtx();
|
|
5029
5030
|
const invalid = validateProfile(profile);
|
|
5030
5031
|
if (invalid !== null) return err(invalid);
|
|
5031
5032
|
const outerResult = polygon(to3D(outerLoop(profile)));
|
|
5032
5033
|
if (!outerResult.ok) return err(fromBrepError(outerResult.error, "PROFILE_FACE_FAILED", "Failed to build profile outer face"));
|
|
5033
5034
|
const holes = holeLoops(profile);
|
|
5034
5035
|
if (holes.length === 0) return ok(outerResult.value);
|
|
5035
|
-
const outerFace = _usingCtx$
|
|
5036
|
+
const outerFace = _usingCtx$18.u(outerResult.value);
|
|
5036
5037
|
const holeFaces = [];
|
|
5037
5038
|
const holeWires = [];
|
|
5038
5039
|
const disposeHoleFaces = () => {
|
|
@@ -5057,9 +5058,9 @@ function extendedProfileToFace(profile) {
|
|
|
5057
5058
|
disposeHoleFaces();
|
|
5058
5059
|
return ok(faceWithHoles);
|
|
5059
5060
|
} catch (_) {
|
|
5060
|
-
_usingCtx$
|
|
5061
|
+
_usingCtx$18.e = _;
|
|
5061
5062
|
} finally {
|
|
5062
|
-
_usingCtx$
|
|
5063
|
+
_usingCtx$18.d();
|
|
5063
5064
|
}
|
|
5064
5065
|
}
|
|
5065
5066
|
//#endregion
|
|
@@ -5381,7 +5382,7 @@ function profileToPolygon(profile, circleSegments = 32) {
|
|
|
5381
5382
|
//#region src/elementFns/beamFns.ts
|
|
5382
5383
|
function beamToSolid(spec) {
|
|
5383
5384
|
try {
|
|
5384
|
-
var _usingCtx$
|
|
5385
|
+
var _usingCtx$17 = _usingCtx();
|
|
5385
5386
|
if (spec.length <= 0) return err(specError("BEAM_ZERO_LENGTH", "Beam length must be positive"));
|
|
5386
5387
|
if (isExtendedProfile(spec.profile)) try {
|
|
5387
5388
|
var _usingCtx3 = _usingCtx();
|
|
@@ -5419,7 +5420,7 @@ function beamToSolid(spec) {
|
|
|
5419
5420
|
]);
|
|
5420
5421
|
const profileResult = polygon(profilePts);
|
|
5421
5422
|
if (!profileResult.ok) return err(fromBrepError(profileResult.error, "BEAM_PROFILE_FAILED", "Failed to create beam profile"));
|
|
5422
|
-
const profile = _usingCtx$
|
|
5423
|
+
const profile = _usingCtx$17.u(profileResult.value);
|
|
5423
5424
|
const solidResult = extrude(profile, [
|
|
5424
5425
|
spec.length,
|
|
5425
5426
|
0,
|
|
@@ -5433,16 +5434,16 @@ function beamToSolid(spec) {
|
|
|
5433
5434
|
}
|
|
5434
5435
|
return ok(solid);
|
|
5435
5436
|
} catch (_) {
|
|
5436
|
-
_usingCtx$
|
|
5437
|
+
_usingCtx$17.e = _;
|
|
5437
5438
|
} finally {
|
|
5438
|
-
_usingCtx$
|
|
5439
|
+
_usingCtx$17.d();
|
|
5439
5440
|
}
|
|
5440
5441
|
}
|
|
5441
5442
|
//#endregion
|
|
5442
5443
|
//#region src/elementFns/columnFns.ts
|
|
5443
5444
|
function columnToSolid(spec) {
|
|
5444
5445
|
try {
|
|
5445
|
-
var _usingCtx$
|
|
5446
|
+
var _usingCtx$16 = _usingCtx();
|
|
5446
5447
|
if (spec.height <= 0) return err(specError("COLUMN_ZERO_HEIGHT", "Column height must be positive"));
|
|
5447
5448
|
if (isExtendedProfile(spec.profile)) try {
|
|
5448
5449
|
var _usingCtx3 = _usingCtx();
|
|
@@ -5471,7 +5472,7 @@ function columnToSolid(spec) {
|
|
|
5471
5472
|
const profilePts = profilePtsResult.value;
|
|
5472
5473
|
const profileResult = polygon(profilePts);
|
|
5473
5474
|
if (!profileResult.ok) return err(fromBrepError(profileResult.error, "COLUMN_PROFILE_FAILED", "Failed to create column profile"));
|
|
5474
|
-
const profile = _usingCtx$
|
|
5475
|
+
const profile = _usingCtx$16.u(profileResult.value);
|
|
5475
5476
|
const solidResult = extrude(profile, [
|
|
5476
5477
|
0,
|
|
5477
5478
|
0,
|
|
@@ -5485,9 +5486,9 @@ function columnToSolid(spec) {
|
|
|
5485
5486
|
}
|
|
5486
5487
|
return ok(solid);
|
|
5487
5488
|
} catch (_) {
|
|
5488
|
-
_usingCtx$
|
|
5489
|
+
_usingCtx$16.e = _;
|
|
5489
5490
|
} finally {
|
|
5490
|
-
_usingCtx$
|
|
5491
|
+
_usingCtx$16.d();
|
|
5491
5492
|
}
|
|
5492
5493
|
}
|
|
5493
5494
|
//#endregion
|
|
@@ -5495,7 +5496,7 @@ function columnToSolid(spec) {
|
|
|
5495
5496
|
var EPSILON_MM = 1;
|
|
5496
5497
|
function openingToSolid(spec, wallThickness) {
|
|
5497
5498
|
try {
|
|
5498
|
-
var _usingCtx$
|
|
5499
|
+
var _usingCtx$15 = _usingCtx();
|
|
5499
5500
|
if (spec.width <= 0) return err(specError("OPENING_ZERO_WIDTH", "Opening width must be positive"));
|
|
5500
5501
|
if (spec.height <= 0) return err(specError("OPENING_ZERO_HEIGHT", "Opening height must be positive"));
|
|
5501
5502
|
if (wallThickness <= 0) return err(specError("OPENING_ZERO_WALL_THICKNESS", "Wall thickness must be positive"));
|
|
@@ -5527,7 +5528,7 @@ function openingToSolid(spec, wallThickness) {
|
|
|
5527
5528
|
]
|
|
5528
5529
|
]);
|
|
5529
5530
|
if (!profileResult.ok) return err(fromBrepError(profileResult.error, "OPENING_PROFILE_FAILED", "Failed to create opening profile"));
|
|
5530
|
-
const profile = _usingCtx$
|
|
5531
|
+
const profile = _usingCtx$15.u(profileResult.value);
|
|
5531
5532
|
const solidResult = extrude(profile, [
|
|
5532
5533
|
spec.width,
|
|
5533
5534
|
0,
|
|
@@ -5541,16 +5542,16 @@ function openingToSolid(spec, wallThickness) {
|
|
|
5541
5542
|
}
|
|
5542
5543
|
return ok(solid);
|
|
5543
5544
|
} catch (_) {
|
|
5544
|
-
_usingCtx$
|
|
5545
|
+
_usingCtx$15.e = _;
|
|
5545
5546
|
} finally {
|
|
5546
|
-
_usingCtx$
|
|
5547
|
+
_usingCtx$15.d();
|
|
5547
5548
|
}
|
|
5548
5549
|
}
|
|
5549
5550
|
//#endregion
|
|
5550
5551
|
//#region src/elementFns/slabOpeningFns.ts
|
|
5551
5552
|
function slabOpeningToSolid(spec, slabThickness) {
|
|
5552
5553
|
try {
|
|
5553
|
-
var _usingCtx$
|
|
5554
|
+
var _usingCtx$14 = _usingCtx();
|
|
5554
5555
|
if (spec.sizeX <= 0) return err(specError("SLAB_OPENING_ZERO_SIZE_X", "Slab opening sizeX must be positive"));
|
|
5555
5556
|
if (spec.sizeY <= 0) return err(specError("SLAB_OPENING_ZERO_SIZE_Y", "Slab opening sizeY must be positive"));
|
|
5556
5557
|
if (slabThickness <= 0) return err(specError("SLAB_OPENING_ZERO_SLAB_THICKNESS", "Slab thickness must be positive"));
|
|
@@ -5582,7 +5583,7 @@ function slabOpeningToSolid(spec, slabThickness) {
|
|
|
5582
5583
|
]
|
|
5583
5584
|
]);
|
|
5584
5585
|
if (!profileResult.ok) return err(fromBrepError(profileResult.error, "SLAB_OPENING_PROFILE_FAILED", "Failed to create slab opening profile"));
|
|
5585
|
-
const profile = _usingCtx$
|
|
5586
|
+
const profile = _usingCtx$14.u(profileResult.value);
|
|
5586
5587
|
const solidResult = extrude(profile, [
|
|
5587
5588
|
0,
|
|
5588
5589
|
0,
|
|
@@ -5596,16 +5597,16 @@ function slabOpeningToSolid(spec, slabThickness) {
|
|
|
5596
5597
|
}
|
|
5597
5598
|
return ok(solid);
|
|
5598
5599
|
} catch (_) {
|
|
5599
|
-
_usingCtx$
|
|
5600
|
+
_usingCtx$14.e = _;
|
|
5600
5601
|
} finally {
|
|
5601
|
-
_usingCtx$
|
|
5602
|
+
_usingCtx$14.d();
|
|
5602
5603
|
}
|
|
5603
5604
|
}
|
|
5604
5605
|
//#endregion
|
|
5605
5606
|
//#region src/elementFns/spaceFns.ts
|
|
5606
5607
|
function spaceToSolid(spec) {
|
|
5607
5608
|
try {
|
|
5608
|
-
var _usingCtx$
|
|
5609
|
+
var _usingCtx$13 = _usingCtx();
|
|
5609
5610
|
if (spec.length <= 0) return err(specError("SPACE_ZERO_LENGTH", "Space length must be positive"));
|
|
5610
5611
|
if (spec.width <= 0) return err(specError("SPACE_ZERO_WIDTH", "Space width must be positive"));
|
|
5611
5612
|
if (spec.height <= 0) return err(specError("SPACE_ZERO_HEIGHT", "Space height must be positive"));
|
|
@@ -5633,7 +5634,7 @@ function spaceToSolid(spec) {
|
|
|
5633
5634
|
]
|
|
5634
5635
|
]);
|
|
5635
5636
|
if (!profileResult.ok) return err(fromBrepError(profileResult.error, "SPACE_PROFILE_FAILED", "Failed to create space footprint"));
|
|
5636
|
-
const profile = _usingCtx$
|
|
5637
|
+
const profile = _usingCtx$13.u(profileResult.value);
|
|
5637
5638
|
const solidResult = extrude(profile, [
|
|
5638
5639
|
0,
|
|
5639
5640
|
0,
|
|
@@ -5647,9 +5648,9 @@ function spaceToSolid(spec) {
|
|
|
5647
5648
|
}
|
|
5648
5649
|
return ok(solid);
|
|
5649
5650
|
} catch (_) {
|
|
5650
|
-
_usingCtx$
|
|
5651
|
+
_usingCtx$13.e = _;
|
|
5651
5652
|
} finally {
|
|
5652
|
-
_usingCtx$
|
|
5653
|
+
_usingCtx$13.d();
|
|
5653
5654
|
}
|
|
5654
5655
|
}
|
|
5655
5656
|
//#endregion
|
|
@@ -5664,7 +5665,7 @@ function gate(solid, code) {
|
|
|
5664
5665
|
}
|
|
5665
5666
|
function flatRoof(spec) {
|
|
5666
5667
|
try {
|
|
5667
|
-
var _usingCtx$
|
|
5668
|
+
var _usingCtx$12 = _usingCtx();
|
|
5668
5669
|
const { length, width, thickness } = spec;
|
|
5669
5670
|
const face = polygon([
|
|
5670
5671
|
[
|
|
@@ -5689,7 +5690,7 @@ function flatRoof(spec) {
|
|
|
5689
5690
|
]
|
|
5690
5691
|
]);
|
|
5691
5692
|
if (!face.ok) return err(fromBrepError(face.error, "ROOF_PROFILE_FAILED", "Failed to create roof profile"));
|
|
5692
|
-
const profile = _usingCtx$
|
|
5693
|
+
const profile = _usingCtx$12.u(face.value);
|
|
5693
5694
|
const solid = extrude(profile, [
|
|
5694
5695
|
0,
|
|
5695
5696
|
0,
|
|
@@ -5698,9 +5699,9 @@ function flatRoof(spec) {
|
|
|
5698
5699
|
if (!solid.ok) return err(fromBrepError(solid.error, "ROOF_EXTRUDE_FAILED", "Failed to extrude roof profile"));
|
|
5699
5700
|
return gate(solid.value, "ROOF_INVALID_SOLID");
|
|
5700
5701
|
} catch (_) {
|
|
5701
|
-
_usingCtx$
|
|
5702
|
+
_usingCtx$12.e = _;
|
|
5702
5703
|
} finally {
|
|
5703
|
-
_usingCtx$
|
|
5704
|
+
_usingCtx$12.d();
|
|
5704
5705
|
}
|
|
5705
5706
|
}
|
|
5706
5707
|
function shedRoof(spec, pitch) {
|
|
@@ -5896,7 +5897,7 @@ function roofToSolid(spec) {
|
|
|
5896
5897
|
//#region src/elementFns/curtainWallFns.ts
|
|
5897
5898
|
function boxSolid(sizeX, sizeY, sizeZ) {
|
|
5898
5899
|
try {
|
|
5899
|
-
var _usingCtx$
|
|
5900
|
+
var _usingCtx$11 = _usingCtx();
|
|
5900
5901
|
const profileResult = polygon([
|
|
5901
5902
|
[
|
|
5902
5903
|
0,
|
|
@@ -5920,7 +5921,7 @@ function boxSolid(sizeX, sizeY, sizeZ) {
|
|
|
5920
5921
|
]
|
|
5921
5922
|
]);
|
|
5922
5923
|
if (!profileResult.ok) return err(fromBrepError(profileResult.error, "CURTAIN_WALL_PROFILE_FAILED", "Failed to create component profile"));
|
|
5923
|
-
const profile = _usingCtx$
|
|
5924
|
+
const profile = _usingCtx$11.u(profileResult.value);
|
|
5924
5925
|
const solidResult = extrude(profile, [
|
|
5925
5926
|
0,
|
|
5926
5927
|
0,
|
|
@@ -5934,9 +5935,9 @@ function boxSolid(sizeX, sizeY, sizeZ) {
|
|
|
5934
5935
|
}
|
|
5935
5936
|
return ok(solid);
|
|
5936
5937
|
} catch (_) {
|
|
5937
|
-
_usingCtx$
|
|
5938
|
+
_usingCtx$11.e = _;
|
|
5938
5939
|
} finally {
|
|
5939
|
-
_usingCtx$
|
|
5940
|
+
_usingCtx$11.d();
|
|
5940
5941
|
}
|
|
5941
5942
|
}
|
|
5942
5943
|
function disposeComponents(components) {
|
|
@@ -6035,7 +6036,7 @@ function curtainWallToGrid(spec) {
|
|
|
6035
6036
|
//#region src/elementFns/foundationFns.ts
|
|
6036
6037
|
function footingToSolid(spec) {
|
|
6037
6038
|
try {
|
|
6038
|
-
var _usingCtx$
|
|
6039
|
+
var _usingCtx$10 = _usingCtx();
|
|
6039
6040
|
if (spec.length <= 0) return err(specError("FOOTING_ZERO_LENGTH", "Footing length must be positive"));
|
|
6040
6041
|
if (spec.width <= 0) return err(specError("FOOTING_ZERO_WIDTH", "Footing width must be positive"));
|
|
6041
6042
|
if (spec.thickness <= 0) return err(specError("FOOTING_ZERO_THICKNESS", "Footing thickness must be positive"));
|
|
@@ -6063,7 +6064,7 @@ function footingToSolid(spec) {
|
|
|
6063
6064
|
]
|
|
6064
6065
|
]);
|
|
6065
6066
|
if (!profileResult.ok) return err(fromBrepError(profileResult.error, "FOOTING_PROFILE_FAILED", "Failed to create footing profile"));
|
|
6066
|
-
const profile = _usingCtx$
|
|
6067
|
+
const profile = _usingCtx$10.u(profileResult.value);
|
|
6067
6068
|
const solidResult = extrude(profile, [
|
|
6068
6069
|
0,
|
|
6069
6070
|
0,
|
|
@@ -6077,9 +6078,9 @@ function footingToSolid(spec) {
|
|
|
6077
6078
|
}
|
|
6078
6079
|
return ok(solid);
|
|
6079
6080
|
} catch (_) {
|
|
6080
|
-
_usingCtx$
|
|
6081
|
+
_usingCtx$10.e = _;
|
|
6081
6082
|
} finally {
|
|
6082
|
-
_usingCtx$
|
|
6083
|
+
_usingCtx$10.d();
|
|
6083
6084
|
}
|
|
6084
6085
|
}
|
|
6085
6086
|
function pileToSolid(spec) {
|
|
@@ -6136,7 +6137,7 @@ function pileToSolid(spec) {
|
|
|
6136
6137
|
//#region src/elementFns/railingFns.ts
|
|
6137
6138
|
function panelRailing(spec) {
|
|
6138
6139
|
try {
|
|
6139
|
-
var _usingCtx$
|
|
6140
|
+
var _usingCtx$9 = _usingCtx();
|
|
6140
6141
|
const { length, height, thickness } = spec;
|
|
6141
6142
|
const profileResult = polygon([
|
|
6142
6143
|
[
|
|
@@ -6161,7 +6162,7 @@ function panelRailing(spec) {
|
|
|
6161
6162
|
]
|
|
6162
6163
|
]);
|
|
6163
6164
|
if (!profileResult.ok) return err(fromBrepError(profileResult.error, "RAILING_PROFILE_FAILED", "Failed to create railing profile"));
|
|
6164
|
-
const profile = _usingCtx$
|
|
6165
|
+
const profile = _usingCtx$9.u(profileResult.value);
|
|
6165
6166
|
const solidResult = extrude(profile, [
|
|
6166
6167
|
length,
|
|
6167
6168
|
0,
|
|
@@ -6175,9 +6176,9 @@ function panelRailing(spec) {
|
|
|
6175
6176
|
}
|
|
6176
6177
|
return ok(solid);
|
|
6177
6178
|
} catch (_) {
|
|
6178
|
-
_usingCtx$
|
|
6179
|
+
_usingCtx$9.e = _;
|
|
6179
6180
|
} finally {
|
|
6180
|
-
_usingCtx$
|
|
6181
|
+
_usingCtx$9.d();
|
|
6181
6182
|
}
|
|
6182
6183
|
}
|
|
6183
6184
|
function postedRailing(spec) {
|
|
@@ -6240,7 +6241,7 @@ function railingToSolid(spec) {
|
|
|
6240
6241
|
//#region src/elementFns/coveringFns.ts
|
|
6241
6242
|
function coveringToSolid(spec) {
|
|
6242
6243
|
try {
|
|
6243
|
-
var _usingCtx$
|
|
6244
|
+
var _usingCtx$8 = _usingCtx();
|
|
6244
6245
|
if (spec.length <= 0) return err(specError("COVERING_ZERO_LENGTH", "Covering length must be positive"));
|
|
6245
6246
|
if (spec.width <= 0) return err(specError("COVERING_ZERO_WIDTH", "Covering width must be positive"));
|
|
6246
6247
|
if (spec.thickness <= 0) return err(specError("COVERING_ZERO_THICKNESS", "Covering thickness must be positive"));
|
|
@@ -6268,7 +6269,7 @@ function coveringToSolid(spec) {
|
|
|
6268
6269
|
]
|
|
6269
6270
|
]);
|
|
6270
6271
|
if (!profileResult.ok) return err(fromBrepError(profileResult.error, "COVERING_PROFILE_FAILED", "Failed to create covering profile"));
|
|
6271
|
-
const profile = _usingCtx$
|
|
6272
|
+
const profile = _usingCtx$8.u(profileResult.value);
|
|
6272
6273
|
const solidResult = extrude(profile, [
|
|
6273
6274
|
0,
|
|
6274
6275
|
0,
|
|
@@ -6282,13 +6283,29 @@ function coveringToSolid(spec) {
|
|
|
6282
6283
|
}
|
|
6283
6284
|
return ok(solid);
|
|
6284
6285
|
} catch (_) {
|
|
6285
|
-
_usingCtx$
|
|
6286
|
+
_usingCtx$8.e = _;
|
|
6286
6287
|
} finally {
|
|
6287
|
-
_usingCtx$
|
|
6288
|
+
_usingCtx$8.d();
|
|
6289
|
+
}
|
|
6290
|
+
}
|
|
6291
|
+
//#endregion
|
|
6292
|
+
//#region src/types/productBody.ts
|
|
6293
|
+
/** Returns borrowed Product-local solids. The model retains ownership. */
|
|
6294
|
+
function bodySolids(body) {
|
|
6295
|
+
switch (body.kind) {
|
|
6296
|
+
case "PARAMETRIC": return [body.solid];
|
|
6297
|
+
case "EXACT": return body.solids;
|
|
6288
6298
|
}
|
|
6289
6299
|
}
|
|
6300
|
+
/** Model-owner cleanup. Borrowers must use {@link bodySolids} without disposing its items. */
|
|
6301
|
+
function disposeProductBody(body) {
|
|
6302
|
+
for (const solid of bodySolids(body)) solid[Symbol.dispose]();
|
|
6303
|
+
}
|
|
6290
6304
|
//#endregion
|
|
6291
6305
|
//#region src/model/bimModel.ts
|
|
6306
|
+
function exactWallBodyImmutable() {
|
|
6307
|
+
return err(specError("EXACT_WALL_BODY_IMMUTABLE", "Cannot add an opening after a wall has taken an exact Product Body"));
|
|
6308
|
+
}
|
|
6292
6309
|
var BimModel = class {
|
|
6293
6310
|
#elements = /* @__PURE__ */ new Map();
|
|
6294
6311
|
#relationships = /* @__PURE__ */ new Map();
|
|
@@ -6307,7 +6324,8 @@ var BimModel = class {
|
|
|
6307
6324
|
return ok(id);
|
|
6308
6325
|
}
|
|
6309
6326
|
[Symbol.dispose]() {
|
|
6310
|
-
for (const el of this.#elements.values()) if (el.category === "
|
|
6327
|
+
for (const el of this.#elements.values()) if (el.category === "SLAB" || el.category === "BEAM" || el.category === "COLUMN" || el.category === "PROXY" || el.category === "EARTHWORKS_FILL" || el.category === "SPACE" || el.category === "ROOF" || el.category === "FOOTING" || el.category === "PILE" || el.category === "COVERING") el.geometry[Symbol.dispose]();
|
|
6328
|
+
else if (el.category === "WALL" || el.category === "RAILING") disposeProductBody(el.geometry);
|
|
6311
6329
|
else if (el.category === "CURTAIN_WALL") {
|
|
6312
6330
|
for (const panel of el.geometry.panels) panel.solid[Symbol.dispose]();
|
|
6313
6331
|
for (const mullion of el.geometry.mullions) mullion.solid[Symbol.dispose]();
|
|
@@ -6368,7 +6386,10 @@ var BimModel = class {
|
|
|
6368
6386
|
if (!keyCheck.ok) return keyCheck;
|
|
6369
6387
|
const geomResult = wallToSolid(spec);
|
|
6370
6388
|
if (!geomResult.ok) return err(geomResult.error);
|
|
6371
|
-
const id = this.#makeElement("WALL", spec,
|
|
6389
|
+
const id = this.#makeElement("WALL", spec, {
|
|
6390
|
+
kind: "PARAMETRIC",
|
|
6391
|
+
solid: geomResult.value
|
|
6392
|
+
}, options?.stableKey);
|
|
6372
6393
|
this.#associateMaterial(id, spec);
|
|
6373
6394
|
this.#associateClassification(id, spec);
|
|
6374
6395
|
return ok(id);
|
|
@@ -6483,12 +6504,47 @@ var BimModel = class {
|
|
|
6483
6504
|
if (!keyCheck.ok) return keyCheck;
|
|
6484
6505
|
const geomResult = railingToSolid(spec);
|
|
6485
6506
|
if (!geomResult.ok) return err(geomResult.error);
|
|
6486
|
-
const id = this.#makeElement("RAILING", spec,
|
|
6507
|
+
const id = this.#makeElement("RAILING", spec, {
|
|
6508
|
+
kind: "PARAMETRIC",
|
|
6509
|
+
solid: geomResult.value
|
|
6510
|
+
}, options?.stableKey);
|
|
6487
6511
|
this.#associateMaterial(id, spec);
|
|
6488
6512
|
this.#associateClassification(id, spec);
|
|
6489
6513
|
return ok(id);
|
|
6490
6514
|
}
|
|
6491
6515
|
/**
|
|
6516
|
+
* Atomically replaces a parametric wall or railing Body with authoritative,
|
|
6517
|
+
* caller-owned exact solids. Success transfers every supplied handle to this
|
|
6518
|
+
* model. Failure leaves both the model and all supplied handles unchanged.
|
|
6519
|
+
*/
|
|
6520
|
+
takeExactProductBody(localId, body) {
|
|
6521
|
+
const target = this.#elements.get(localId);
|
|
6522
|
+
if (target === void 0) return err(specError("EXACT_BODY_TARGET_NOT_FOUND", `No element found for localId ${localId}`));
|
|
6523
|
+
if (target.category !== "WALL" && target.category !== "RAILING") return err(specError("EXACT_BODY_UNSUPPORTED_CATEGORY", `Exact Product Bodies are supported only for walls and railings, not ${target.category}`));
|
|
6524
|
+
if (target.geometry.kind === "EXACT") return err(specError("EXACT_BODY_ALREADY_EXACT", `Element ${localId} already has an exact Product Body`));
|
|
6525
|
+
const solids = body.solids;
|
|
6526
|
+
if (solids.length === 0) return err(specError("EXACT_BODY_EMPTY", "An exact Product Body must contain at least one solid"));
|
|
6527
|
+
if (solids.includes(target.geometry.solid)) return err(specError("EXACT_BODY_SOLID_OWNERSHIP_CONFLICT", `Exact Product Body for ${localId} reuses the target parametric solid`));
|
|
6528
|
+
const identities = /* @__PURE__ */ new Set();
|
|
6529
|
+
for (const [itemIndex, solid] of solids.entries()) {
|
|
6530
|
+
if (identities.has(solid)) return err(specError("EXACT_BODY_DUPLICATE_SOLID", `Exact Product Body item ${itemIndex} duplicates an earlier handle`));
|
|
6531
|
+
identities.add(solid);
|
|
6532
|
+
if (solid.disposed) return err(specError("EXACT_BODY_SOLID_DISPOSED", `Exact Product Body item ${itemIndex} is already disposed`));
|
|
6533
|
+
try {
|
|
6534
|
+
if (!isValidSolid(solid)) return err(specError("EXACT_BODY_SOLID_INVALID", `Exact Product Body item ${itemIndex} is not a valid solid`));
|
|
6535
|
+
} catch (cause) {
|
|
6536
|
+
return err(specError("EXACT_BODY_SOLID_INVALID", `Exact Product Body item ${itemIndex} could not be validated`, cause));
|
|
6537
|
+
}
|
|
6538
|
+
}
|
|
6539
|
+
const replaced = {
|
|
6540
|
+
...target,
|
|
6541
|
+
geometry: body
|
|
6542
|
+
};
|
|
6543
|
+
this.#elements.set(localId, replaced);
|
|
6544
|
+
disposeProductBody(target.geometry);
|
|
6545
|
+
return ok(void 0);
|
|
6546
|
+
}
|
|
6547
|
+
/**
|
|
6492
6548
|
* Adds an IfcCovering. When `hostLocalId` is supplied, an
|
|
6493
6549
|
* IfcRelCoversBldgElements linking the covering to its host (e.g. a slab it
|
|
6494
6550
|
* finishes) is recorded for export.
|
|
@@ -6685,10 +6741,11 @@ var BimModel = class {
|
|
|
6685
6741
|
return ok(id);
|
|
6686
6742
|
}
|
|
6687
6743
|
addDoor(spec, options) {
|
|
6688
|
-
const keyCheck = this.#checkOpeningKeys(options);
|
|
6689
|
-
if (!keyCheck.ok) return keyCheck;
|
|
6690
6744
|
const wall = this.#elements.get(spec.wallLocalId);
|
|
6691
6745
|
if (wall === void 0 || wall.category !== "WALL") return err(specError("DOOR_WALL_NOT_FOUND", `No wall found for localId ${spec.wallLocalId}`));
|
|
6746
|
+
if (wall.geometry.kind === "EXACT") return exactWallBodyImmutable();
|
|
6747
|
+
const keyCheck = this.#checkOpeningKeys(options);
|
|
6748
|
+
if (!keyCheck.ok) return keyCheck;
|
|
6692
6749
|
if (spec.offsetAlongWall + spec.width > wall.spec.length) return err(specError("DOOR_EXCEEDS_WALL_BOUNDS", "Door (offsetAlongWall + width) exceeds wall length"));
|
|
6693
6750
|
if (spec.offsetFromFloor + spec.height > wall.spec.height) return err(specError("DOOR_EXCEEDS_WALL_BOUNDS", "Door (offsetFromFloor + height) exceeds wall height"));
|
|
6694
6751
|
const openingSpec = {
|
|
@@ -6721,10 +6778,11 @@ var BimModel = class {
|
|
|
6721
6778
|
return ok(doorId);
|
|
6722
6779
|
}
|
|
6723
6780
|
addWindow(spec, options) {
|
|
6724
|
-
const keyCheck = this.#checkOpeningKeys(options);
|
|
6725
|
-
if (!keyCheck.ok) return keyCheck;
|
|
6726
6781
|
const wall = this.#elements.get(spec.wallLocalId);
|
|
6727
6782
|
if (wall === void 0 || wall.category !== "WALL") return err(specError("WINDOW_WALL_NOT_FOUND", `No wall found for localId ${spec.wallLocalId}`));
|
|
6783
|
+
if (wall.geometry.kind === "EXACT") return exactWallBodyImmutable();
|
|
6784
|
+
const keyCheck = this.#checkOpeningKeys(options);
|
|
6785
|
+
if (!keyCheck.ok) return keyCheck;
|
|
6728
6786
|
if (spec.offsetAlongWall + spec.width > wall.spec.length) return err(specError("WINDOW_EXCEEDS_WALL_BOUNDS", "Window (offsetAlongWall + width) exceeds wall length"));
|
|
6729
6787
|
if (spec.offsetFromFloor + spec.height > wall.spec.height) return err(specError("WINDOW_EXCEEDS_WALL_BOUNDS", "Window (offsetFromFloor + height) exceeds wall height"));
|
|
6730
6788
|
const openingSpec = {
|
|
@@ -6798,27 +6856,31 @@ var BimModel = class {
|
|
|
6798
6856
|
}
|
|
6799
6857
|
#cutWallGeometry(wall, openingSpec) {
|
|
6800
6858
|
try {
|
|
6801
|
-
var _usingCtx$
|
|
6859
|
+
var _usingCtx$7 = _usingCtx();
|
|
6860
|
+
if (wall.geometry.kind === "EXACT") return exactWallBodyImmutable();
|
|
6802
6861
|
const toolResult = openingToSolid(openingSpec, wall.spec.thickness);
|
|
6803
6862
|
if (!toolResult.ok) return err(toolResult.error);
|
|
6804
|
-
const tool = _usingCtx$
|
|
6805
|
-
const cutResult = cut(wall.geometry, tool);
|
|
6863
|
+
const tool = _usingCtx$7.u(toolResult.value);
|
|
6864
|
+
const cutResult = cut(wall.geometry.solid, tool);
|
|
6806
6865
|
if (!cutResult.ok) return err(fromBrepError(cutResult.error, "WALL_CUT_FAILED", "Boolean cut of wall with opening failed"));
|
|
6807
6866
|
return ok(cutResult.value);
|
|
6808
6867
|
} catch (_) {
|
|
6809
|
-
_usingCtx$
|
|
6868
|
+
_usingCtx$7.e = _;
|
|
6810
6869
|
} finally {
|
|
6811
|
-
_usingCtx$
|
|
6870
|
+
_usingCtx$7.d();
|
|
6812
6871
|
}
|
|
6813
6872
|
}
|
|
6814
6873
|
#replaceWallGeometry(wall, newGeometry) {
|
|
6815
6874
|
const oldGeometry = wall.geometry;
|
|
6816
6875
|
const replaced = {
|
|
6817
6876
|
...wall,
|
|
6818
|
-
geometry:
|
|
6877
|
+
geometry: {
|
|
6878
|
+
kind: "PARAMETRIC",
|
|
6879
|
+
solid: newGeometry
|
|
6880
|
+
}
|
|
6819
6881
|
};
|
|
6820
6882
|
this.#elements.set(wall.localId, replaced);
|
|
6821
|
-
oldGeometry
|
|
6883
|
+
disposeProductBody(oldGeometry);
|
|
6822
6884
|
}
|
|
6823
6885
|
#cutSlabGeometry(slab, openingSpec) {
|
|
6824
6886
|
try {
|
|
@@ -7077,6 +7139,129 @@ var BimModel = class {
|
|
|
7077
7139
|
}
|
|
7078
7140
|
};
|
|
7079
7141
|
//#endregion
|
|
7142
|
+
//#region src/elementFns/stairFns.ts
|
|
7143
|
+
function buildSilhouette$1(numberOfRisers, riserHeight, treadLength) {
|
|
7144
|
+
const pts = [];
|
|
7145
|
+
pts.push([
|
|
7146
|
+
0,
|
|
7147
|
+
0,
|
|
7148
|
+
0
|
|
7149
|
+
]);
|
|
7150
|
+
let x = 0;
|
|
7151
|
+
let z = 0;
|
|
7152
|
+
for (let i = 0; i < numberOfRisers; i++) {
|
|
7153
|
+
z += riserHeight;
|
|
7154
|
+
pts.push([
|
|
7155
|
+
x,
|
|
7156
|
+
0,
|
|
7157
|
+
z
|
|
7158
|
+
]);
|
|
7159
|
+
x += treadLength;
|
|
7160
|
+
pts.push([
|
|
7161
|
+
x,
|
|
7162
|
+
0,
|
|
7163
|
+
z
|
|
7164
|
+
]);
|
|
7165
|
+
}
|
|
7166
|
+
pts.push([
|
|
7167
|
+
x,
|
|
7168
|
+
0,
|
|
7169
|
+
0
|
|
7170
|
+
]);
|
|
7171
|
+
return pts;
|
|
7172
|
+
}
|
|
7173
|
+
function stairFlightToSolid(spec) {
|
|
7174
|
+
try {
|
|
7175
|
+
var _usingCtx$6 = _usingCtx();
|
|
7176
|
+
if (spec.width <= 0) return err(specError("STAIR_FLIGHT_ZERO_WIDTH", "Stair flight width must be positive"));
|
|
7177
|
+
if (spec.riserHeight <= 0) return err(specError("STAIR_FLIGHT_ZERO_RISER", "Stair flight riserHeight must be positive"));
|
|
7178
|
+
if (spec.treadLength <= 0) return err(specError("STAIR_FLIGHT_ZERO_TREAD", "Stair flight treadLength must be positive"));
|
|
7179
|
+
if (!Number.isInteger(spec.numberOfRisers) || spec.numberOfRisers < 1) return err(specError("STAIR_FLIGHT_BAD_RISERS", "Stair flight numberOfRisers must be a positive integer"));
|
|
7180
|
+
const silhouette = buildSilhouette$1(spec.numberOfRisers, spec.riserHeight, spec.treadLength);
|
|
7181
|
+
const profileResult = polygon(silhouette);
|
|
7182
|
+
if (!profileResult.ok) return err(fromBrepError(profileResult.error, "STAIR_FLIGHT_PROFILE_FAILED", "Failed to create stair flight silhouette profile"));
|
|
7183
|
+
const profile = _usingCtx$6.u(profileResult.value);
|
|
7184
|
+
const solidResult = extrude(profile, [
|
|
7185
|
+
0,
|
|
7186
|
+
spec.width,
|
|
7187
|
+
0
|
|
7188
|
+
]);
|
|
7189
|
+
if (!solidResult.ok) return err(fromBrepError(solidResult.error, "STAIR_FLIGHT_EXTRUDE_FAILED", "Failed to extrude stair flight silhouette"));
|
|
7190
|
+
const solid = solidResult.value;
|
|
7191
|
+
if (!isValidSolid(solid)) {
|
|
7192
|
+
solid[Symbol.dispose]();
|
|
7193
|
+
return err(geometryError("STAIR_FLIGHT_INVALID_SOLID", "Stair flight solid failed validity check"));
|
|
7194
|
+
}
|
|
7195
|
+
return ok({
|
|
7196
|
+
solid,
|
|
7197
|
+
geometrySimplified: false
|
|
7198
|
+
});
|
|
7199
|
+
} catch (_) {
|
|
7200
|
+
_usingCtx$6.e = _;
|
|
7201
|
+
} finally {
|
|
7202
|
+
_usingCtx$6.d();
|
|
7203
|
+
}
|
|
7204
|
+
}
|
|
7205
|
+
//#endregion
|
|
7206
|
+
//#region src/elementFns/rampFns.ts
|
|
7207
|
+
function buildSilhouette(length, rise, thickness) {
|
|
7208
|
+
return [
|
|
7209
|
+
[
|
|
7210
|
+
0,
|
|
7211
|
+
0,
|
|
7212
|
+
-thickness
|
|
7213
|
+
],
|
|
7214
|
+
[
|
|
7215
|
+
length,
|
|
7216
|
+
0,
|
|
7217
|
+
rise - thickness
|
|
7218
|
+
],
|
|
7219
|
+
[
|
|
7220
|
+
length,
|
|
7221
|
+
0,
|
|
7222
|
+
rise
|
|
7223
|
+
],
|
|
7224
|
+
[
|
|
7225
|
+
0,
|
|
7226
|
+
0,
|
|
7227
|
+
0
|
|
7228
|
+
]
|
|
7229
|
+
];
|
|
7230
|
+
}
|
|
7231
|
+
function rampFlightToSolid(spec) {
|
|
7232
|
+
try {
|
|
7233
|
+
var _usingCtx$5 = _usingCtx();
|
|
7234
|
+
if (spec.width <= 0) return err(specError("RAMP_FLIGHT_ZERO_WIDTH", "Ramp flight width must be positive"));
|
|
7235
|
+
if (spec.length <= 0) return err(specError("RAMP_FLIGHT_ZERO_LENGTH", "Ramp flight length must be positive"));
|
|
7236
|
+
if (spec.slope <= 0) return err(specError("RAMP_FLIGHT_ZERO_SLOPE", "Ramp flight slope must be positive"));
|
|
7237
|
+
if (spec.thickness <= 0) return err(specError("RAMP_FLIGHT_ZERO_THICKNESS", "Ramp flight thickness must be positive"));
|
|
7238
|
+
const rise = spec.length * spec.slope;
|
|
7239
|
+
const silhouette = buildSilhouette(spec.length, rise, spec.thickness);
|
|
7240
|
+
const profileResult = polygon(silhouette);
|
|
7241
|
+
if (!profileResult.ok) return err(fromBrepError(profileResult.error, "RAMP_FLIGHT_PROFILE_FAILED", "Failed to create ramp flight silhouette profile"));
|
|
7242
|
+
const profile = _usingCtx$5.u(profileResult.value);
|
|
7243
|
+
const solidResult = extrude(profile, [
|
|
7244
|
+
0,
|
|
7245
|
+
spec.width,
|
|
7246
|
+
0
|
|
7247
|
+
]);
|
|
7248
|
+
if (!solidResult.ok) return err(fromBrepError(solidResult.error, "RAMP_FLIGHT_EXTRUDE_FAILED", "Failed to extrude ramp flight silhouette"));
|
|
7249
|
+
const solid = solidResult.value;
|
|
7250
|
+
if (!isValidSolid(solid)) {
|
|
7251
|
+
solid[Symbol.dispose]();
|
|
7252
|
+
return err(geometryError("RAMP_FLIGHT_INVALID_SOLID", "Ramp flight solid failed validity check"));
|
|
7253
|
+
}
|
|
7254
|
+
return ok({
|
|
7255
|
+
solid,
|
|
7256
|
+
geometrySimplified: true
|
|
7257
|
+
});
|
|
7258
|
+
} catch (_) {
|
|
7259
|
+
_usingCtx$5.e = _;
|
|
7260
|
+
} finally {
|
|
7261
|
+
_usingCtx$5.d();
|
|
7262
|
+
}
|
|
7263
|
+
}
|
|
7264
|
+
//#endregion
|
|
7080
7265
|
//#region src/import/placement.ts
|
|
7081
7266
|
/**
|
|
7082
7267
|
* Metres-per-file-unit length scale read from the IfcUnitAssignment's
|
|
@@ -7284,148 +7469,100 @@ function enumValue(v) {
|
|
|
7284
7469
|
return typeof value === "string" ? value : null;
|
|
7285
7470
|
}
|
|
7286
7471
|
//#endregion
|
|
7287
|
-
//#region src/
|
|
7288
|
-
|
|
7289
|
-
|
|
7290
|
-
|
|
7291
|
-
|
|
7292
|
-
|
|
7293
|
-
|
|
7294
|
-
|
|
7295
|
-
|
|
7296
|
-
|
|
7297
|
-
|
|
7298
|
-
|
|
7299
|
-
|
|
7300
|
-
|
|
7301
|
-
|
|
7302
|
-
|
|
7303
|
-
|
|
7304
|
-
|
|
7305
|
-
|
|
7306
|
-
|
|
7307
|
-
|
|
7308
|
-
|
|
7309
|
-
|
|
7310
|
-
|
|
7311
|
-
|
|
7312
|
-
|
|
7313
|
-
|
|
7314
|
-
|
|
7315
|
-
|
|
7316
|
-
|
|
7317
|
-
|
|
7318
|
-
|
|
7319
|
-
|
|
7320
|
-
|
|
7321
|
-
|
|
7322
|
-
|
|
7323
|
-
|
|
7324
|
-
|
|
7325
|
-
|
|
7326
|
-
|
|
7327
|
-
|
|
7328
|
-
|
|
7329
|
-
const
|
|
7330
|
-
|
|
7331
|
-
|
|
7332
|
-
|
|
7333
|
-
|
|
7334
|
-
|
|
7335
|
-
|
|
7336
|
-
|
|
7337
|
-
|
|
7338
|
-
|
|
7339
|
-
|
|
7340
|
-
|
|
7341
|
-
|
|
7342
|
-
|
|
7343
|
-
|
|
7344
|
-
|
|
7345
|
-
|
|
7346
|
-
|
|
7347
|
-
_usingCtx$5.d();
|
|
7348
|
-
}
|
|
7349
|
-
}
|
|
7350
|
-
//#endregion
|
|
7351
|
-
//#region src/elementFns/rampFns.ts
|
|
7352
|
-
function buildSilhouette(length, rise, thickness) {
|
|
7353
|
-
return [
|
|
7354
|
-
[
|
|
7355
|
-
0,
|
|
7356
|
-
0,
|
|
7357
|
-
-thickness
|
|
7358
|
-
],
|
|
7359
|
-
[
|
|
7360
|
-
length,
|
|
7361
|
-
0,
|
|
7362
|
-
rise - thickness
|
|
7363
|
-
],
|
|
7364
|
-
[
|
|
7365
|
-
length,
|
|
7366
|
-
0,
|
|
7367
|
-
rise
|
|
7368
|
-
],
|
|
7369
|
-
[
|
|
7370
|
-
0,
|
|
7371
|
-
0,
|
|
7372
|
-
0
|
|
7373
|
-
]
|
|
7472
|
+
//#region src/rigidPlacement.ts
|
|
7473
|
+
var RAD_TO_DEG = 180 / Math.PI;
|
|
7474
|
+
var ROTATION_EPSILON = 1e-12;
|
|
7475
|
+
/** Applies a rigid placement as a location so the source BRep is not rebuilt. */
|
|
7476
|
+
function locateShapeInFrame(shape, frame) {
|
|
7477
|
+
return locate(shape, placementOps(frame));
|
|
7478
|
+
}
|
|
7479
|
+
function placementOps(frame) {
|
|
7480
|
+
const matrix = placementToMatrix(frame);
|
|
7481
|
+
const rotation = rotationOp(matrix.linear);
|
|
7482
|
+
const translation = {
|
|
7483
|
+
type: "translate",
|
|
7484
|
+
v: matrix.translation
|
|
7485
|
+
};
|
|
7486
|
+
return rotation === null ? [translation] : [rotation, translation];
|
|
7487
|
+
}
|
|
7488
|
+
function rotationOp(matrix) {
|
|
7489
|
+
const [m00, m01, m02, m10, m11, m12, m20, m21, m22] = matrix;
|
|
7490
|
+
const trace = m00 + m11 + m22;
|
|
7491
|
+
let w;
|
|
7492
|
+
let x;
|
|
7493
|
+
let y;
|
|
7494
|
+
let z;
|
|
7495
|
+
if (trace > 0) {
|
|
7496
|
+
const scale = 2 * Math.sqrt(trace + 1);
|
|
7497
|
+
w = scale / 4;
|
|
7498
|
+
x = (m21 - m12) / scale;
|
|
7499
|
+
y = (m02 - m20) / scale;
|
|
7500
|
+
z = (m10 - m01) / scale;
|
|
7501
|
+
} else if (m00 > m11 && m00 > m22) {
|
|
7502
|
+
const scale = 2 * Math.sqrt(1 + m00 - m11 - m22);
|
|
7503
|
+
w = (m21 - m12) / scale;
|
|
7504
|
+
x = scale / 4;
|
|
7505
|
+
y = (m01 + m10) / scale;
|
|
7506
|
+
z = (m02 + m20) / scale;
|
|
7507
|
+
} else if (m11 > m22) {
|
|
7508
|
+
const scale = 2 * Math.sqrt(1 + m11 - m00 - m22);
|
|
7509
|
+
w = (m02 - m20) / scale;
|
|
7510
|
+
x = (m01 + m10) / scale;
|
|
7511
|
+
y = scale / 4;
|
|
7512
|
+
z = (m12 + m21) / scale;
|
|
7513
|
+
} else {
|
|
7514
|
+
const scale = 2 * Math.sqrt(1 + m22 - m00 - m11);
|
|
7515
|
+
w = (m10 - m01) / scale;
|
|
7516
|
+
x = (m02 + m20) / scale;
|
|
7517
|
+
y = (m12 + m21) / scale;
|
|
7518
|
+
z = scale / 4;
|
|
7519
|
+
}
|
|
7520
|
+
const length = Math.hypot(w, x, y, z);
|
|
7521
|
+
const sign = w < 0 ? -1 : 1;
|
|
7522
|
+
const normalizedW = sign * w / length;
|
|
7523
|
+
const normalizedX = sign * x / length;
|
|
7524
|
+
const normalizedY = sign * y / length;
|
|
7525
|
+
const normalizedZ = sign * z / length;
|
|
7526
|
+
const sinHalfAngle = Math.hypot(normalizedX, normalizedY, normalizedZ);
|
|
7527
|
+
if (sinHalfAngle < ROTATION_EPSILON) return null;
|
|
7528
|
+
const axis = [
|
|
7529
|
+
normalizedX / sinHalfAngle,
|
|
7530
|
+
normalizedY / sinHalfAngle,
|
|
7531
|
+
normalizedZ / sinHalfAngle
|
|
7374
7532
|
];
|
|
7375
|
-
|
|
7376
|
-
|
|
7377
|
-
|
|
7378
|
-
|
|
7379
|
-
|
|
7380
|
-
if (spec.length <= 0) return err(specError("RAMP_FLIGHT_ZERO_LENGTH", "Ramp flight length must be positive"));
|
|
7381
|
-
if (spec.slope <= 0) return err(specError("RAMP_FLIGHT_ZERO_SLOPE", "Ramp flight slope must be positive"));
|
|
7382
|
-
if (spec.thickness <= 0) return err(specError("RAMP_FLIGHT_ZERO_THICKNESS", "Ramp flight thickness must be positive"));
|
|
7383
|
-
const rise = spec.length * spec.slope;
|
|
7384
|
-
const silhouette = buildSilhouette(spec.length, rise, spec.thickness);
|
|
7385
|
-
const profileResult = polygon(silhouette);
|
|
7386
|
-
if (!profileResult.ok) return err(fromBrepError(profileResult.error, "RAMP_FLIGHT_PROFILE_FAILED", "Failed to create ramp flight silhouette profile"));
|
|
7387
|
-
const profile = _usingCtx$4.u(profileResult.value);
|
|
7388
|
-
const solidResult = extrude(profile, [
|
|
7389
|
-
0,
|
|
7390
|
-
spec.width,
|
|
7391
|
-
0
|
|
7392
|
-
]);
|
|
7393
|
-
if (!solidResult.ok) return err(fromBrepError(solidResult.error, "RAMP_FLIGHT_EXTRUDE_FAILED", "Failed to extrude ramp flight silhouette"));
|
|
7394
|
-
const solid = solidResult.value;
|
|
7395
|
-
if (!isValidSolid(solid)) {
|
|
7396
|
-
solid[Symbol.dispose]();
|
|
7397
|
-
return err(geometryError("RAMP_FLIGHT_INVALID_SOLID", "Ramp flight solid failed validity check"));
|
|
7398
|
-
}
|
|
7399
|
-
return ok({
|
|
7400
|
-
solid,
|
|
7401
|
-
geometrySimplified: true
|
|
7402
|
-
});
|
|
7403
|
-
} catch (_) {
|
|
7404
|
-
_usingCtx$4.e = _;
|
|
7405
|
-
} finally {
|
|
7406
|
-
_usingCtx$4.d();
|
|
7407
|
-
}
|
|
7533
|
+
return {
|
|
7534
|
+
type: "rotate",
|
|
7535
|
+
angle: 2 * Math.atan2(sinHalfAngle, normalizedW) * RAD_TO_DEG,
|
|
7536
|
+
axis
|
|
7537
|
+
};
|
|
7408
7538
|
}
|
|
7409
7539
|
//#endregion
|
|
7410
7540
|
//#region src/elementFns/placedGeometry.ts
|
|
7541
|
+
var testHooks$5 = null;
|
|
7411
7542
|
function place(solid, frame) {
|
|
7412
|
-
|
|
7413
|
-
|
|
7414
|
-
|
|
7543
|
+
let placed = null;
|
|
7544
|
+
try {
|
|
7545
|
+
placed = locateShapeInFrame(solid, frame);
|
|
7546
|
+
testHooks$5?.afterPlaced?.(placed);
|
|
7547
|
+
return ok(placed);
|
|
7548
|
+
} catch (cause) {
|
|
7549
|
+
placed?.[Symbol.dispose]();
|
|
7550
|
+
return err(geometryError("PLACED_GEOMETRY_FAILED", "Element placement threw while transforming geometry", cause));
|
|
7551
|
+
}
|
|
7415
7552
|
}
|
|
7416
|
-
function disposeAll(solids) {
|
|
7553
|
+
function disposeAll$1(solids) {
|
|
7417
7554
|
for (const s of solids) s[Symbol.dispose]();
|
|
7418
7555
|
}
|
|
7419
7556
|
function placeWithinParent(solid, localFrame, parentFrame) {
|
|
7420
7557
|
try {
|
|
7421
|
-
var _usingCtx$
|
|
7558
|
+
var _usingCtx$4 = _usingCtx();
|
|
7422
7559
|
const local = place(solid, localFrame);
|
|
7423
7560
|
if (!local.ok || parentFrame === void 0) return local;
|
|
7424
|
-
return place(_usingCtx$
|
|
7561
|
+
return place(_usingCtx$4.u(local.value), parentFrame);
|
|
7425
7562
|
} catch (_) {
|
|
7426
|
-
_usingCtx$
|
|
7563
|
+
_usingCtx$4.e = _;
|
|
7427
7564
|
} finally {
|
|
7428
|
-
_usingCtx$
|
|
7565
|
+
_usingCtx$4.d();
|
|
7429
7566
|
}
|
|
7430
7567
|
}
|
|
7431
7568
|
/**
|
|
@@ -7450,6 +7587,18 @@ function placedSolids(el, options = {}) {
|
|
|
7450
7587
|
const parentFrame = options.parentFrame;
|
|
7451
7588
|
switch (el.category) {
|
|
7452
7589
|
case "WALL":
|
|
7590
|
+
case "RAILING": {
|
|
7591
|
+
const out = [];
|
|
7592
|
+
for (const solid of bodySolids(el.geometry)) {
|
|
7593
|
+
const placed = placeWithinParent(solid, el.spec, parentFrame);
|
|
7594
|
+
if (!placed.ok) {
|
|
7595
|
+
disposeAll$1(out);
|
|
7596
|
+
return placed;
|
|
7597
|
+
}
|
|
7598
|
+
out.push(placed.value);
|
|
7599
|
+
}
|
|
7600
|
+
return ok(out);
|
|
7601
|
+
}
|
|
7453
7602
|
case "SLAB":
|
|
7454
7603
|
case "BEAM":
|
|
7455
7604
|
case "COLUMN":
|
|
@@ -7457,8 +7606,7 @@ function placedSolids(el, options = {}) {
|
|
|
7457
7606
|
case "ROOF":
|
|
7458
7607
|
case "FOOTING":
|
|
7459
7608
|
case "PILE":
|
|
7460
|
-
case "COVERING":
|
|
7461
|
-
case "RAILING": {
|
|
7609
|
+
case "COVERING": {
|
|
7462
7610
|
const placed = placeWithinParent(el.geometry, el.spec, parentFrame);
|
|
7463
7611
|
if (!placed.ok) return placed;
|
|
7464
7612
|
return ok([placed.value]);
|
|
@@ -7469,12 +7617,12 @@ function placedSolids(el, options = {}) {
|
|
|
7469
7617
|
var _usingCtx3 = _usingCtx();
|
|
7470
7618
|
const built = stairFlightToSolid(flight);
|
|
7471
7619
|
if (!built.ok) {
|
|
7472
|
-
disposeAll(out);
|
|
7620
|
+
disposeAll$1(out);
|
|
7473
7621
|
return err(built.error);
|
|
7474
7622
|
}
|
|
7475
7623
|
const placed = placeWithinParent(_usingCtx3.u(built.value.solid), flight, parentFrame);
|
|
7476
7624
|
if (!placed.ok) {
|
|
7477
|
-
disposeAll(out);
|
|
7625
|
+
disposeAll$1(out);
|
|
7478
7626
|
return placed;
|
|
7479
7627
|
}
|
|
7480
7628
|
out.push(placed.value);
|
|
@@ -7491,12 +7639,12 @@ function placedSolids(el, options = {}) {
|
|
|
7491
7639
|
var _usingCtx4 = _usingCtx();
|
|
7492
7640
|
const built = rampFlightToSolid(flight);
|
|
7493
7641
|
if (!built.ok) {
|
|
7494
|
-
disposeAll(out);
|
|
7642
|
+
disposeAll$1(out);
|
|
7495
7643
|
return err(built.error);
|
|
7496
7644
|
}
|
|
7497
7645
|
const placed = placeWithinParent(_usingCtx4.u(built.value.solid), flight, parentFrame);
|
|
7498
7646
|
if (!placed.ok) {
|
|
7499
|
-
disposeAll(out);
|
|
7647
|
+
disposeAll$1(out);
|
|
7500
7648
|
return placed;
|
|
7501
7649
|
}
|
|
7502
7650
|
out.push(placed.value);
|
|
@@ -7547,12 +7695,12 @@ function placedSolids(el, options = {}) {
|
|
|
7547
7695
|
]
|
|
7548
7696
|
});
|
|
7549
7697
|
if (!componentLocal.ok) {
|
|
7550
|
-
disposeAll(out);
|
|
7698
|
+
disposeAll$1(out);
|
|
7551
7699
|
return componentLocal;
|
|
7552
7700
|
}
|
|
7553
7701
|
const placed = placeWithinParent(_usingCtx5.u(componentLocal.value), el.spec, parentFrame);
|
|
7554
7702
|
if (!placed.ok) {
|
|
7555
|
-
disposeAll(out);
|
|
7703
|
+
disposeAll$1(out);
|
|
7556
7704
|
return placed;
|
|
7557
7705
|
}
|
|
7558
7706
|
out.push(placed.value);
|
|
@@ -7657,6 +7805,7 @@ async function initIfcApi(api) {
|
|
|
7657
7805
|
}
|
|
7658
7806
|
//#endregion
|
|
7659
7807
|
//#region src/ifc-writer/ifcWriter.ts
|
|
7808
|
+
var testHooks$4 = null;
|
|
7660
7809
|
/** Default MVD ViewDefinition declared in the STEP FILE_DESCRIPTION header. */
|
|
7661
7810
|
var DEFAULT_MVD_VIEW_DEFINITION = "ReferenceView_v1.2";
|
|
7662
7811
|
var VIEW_DEFINITION_RE = /ViewDefinition \[[^\]]*\]/;
|
|
@@ -7697,6 +7846,10 @@ var IfcWriter = class IfcWriter {
|
|
|
7697
7846
|
return err(ifcError("IFC_INIT_FAILED", "Failed to initialize web-ifc", e));
|
|
7698
7847
|
}
|
|
7699
7848
|
}
|
|
7849
|
+
/** Package-internal lifecycle seam for deterministic writer cleanup tests. */
|
|
7850
|
+
static fromApiForTesting(api, modelId = 0) {
|
|
7851
|
+
return new IfcWriter(api, modelId, DEFAULT_MVD_VIEW_DEFINITION, {});
|
|
7852
|
+
}
|
|
7700
7853
|
nextId() {
|
|
7701
7854
|
return this.#nextExpressId++;
|
|
7702
7855
|
}
|
|
@@ -7714,6 +7867,7 @@ var IfcWriter = class IfcWriter {
|
|
|
7714
7867
|
}
|
|
7715
7868
|
writeLine(entity) {
|
|
7716
7869
|
this.#api.WriteLine(this.#modelId, entity);
|
|
7870
|
+
testHooks$4?.afterWriteLine?.();
|
|
7717
7871
|
return entity.expressID;
|
|
7718
7872
|
}
|
|
7719
7873
|
ref(id) {
|
|
@@ -7722,6 +7876,15 @@ var IfcWriter = class IfcWriter {
|
|
|
7722
7876
|
mkType(type, value) {
|
|
7723
7877
|
return this.#api.CreateIfcType(this.#modelId, type, value);
|
|
7724
7878
|
}
|
|
7879
|
+
close() {
|
|
7880
|
+
if (this.#closed) return;
|
|
7881
|
+
this.#closed = true;
|
|
7882
|
+
this.#api.CloseModel(this.#modelId);
|
|
7883
|
+
testHooks$4?.afterClose?.();
|
|
7884
|
+
}
|
|
7885
|
+
[Symbol.dispose]() {
|
|
7886
|
+
this.close();
|
|
7887
|
+
}
|
|
7725
7888
|
save() {
|
|
7726
7889
|
if (this.#closed) return err(ifcError("IFC_ALREADY_SAVED", "Model has already been saved and closed"));
|
|
7727
7890
|
try {
|
|
@@ -7730,8 +7893,7 @@ var IfcWriter = class IfcWriter {
|
|
|
7730
7893
|
} catch (e) {
|
|
7731
7894
|
return err(ifcError("IFC_SAVE_FAILED", "Failed to serialize IFC model", e));
|
|
7732
7895
|
} finally {
|
|
7733
|
-
this
|
|
7734
|
-
this.#closed = true;
|
|
7896
|
+
this.close();
|
|
7735
7897
|
}
|
|
7736
7898
|
}
|
|
7737
7899
|
/**
|
|
@@ -8274,10 +8436,49 @@ function writeColumnEntity(w, guid, name, _predefinedType, ownerHistoryId, local
|
|
|
8274
8436
|
});
|
|
8275
8437
|
return id;
|
|
8276
8438
|
}
|
|
8277
|
-
//#endregion
|
|
8278
|
-
//#region src/ifc-writer/tessellationWriter.ts
|
|
8279
|
-
var IFC_MESH_TOLERANCE_MM = 5;
|
|
8280
|
-
var IFC_MESH_ANGULAR_TOLERANCE_RAD = .3;
|
|
8439
|
+
//#endregion
|
|
8440
|
+
//#region src/ifc-writer/tessellationWriter.ts
|
|
8441
|
+
var IFC_MESH_TOLERANCE_MM = 5;
|
|
8442
|
+
var IFC_MESH_ANGULAR_TOLERANCE_RAD = .3;
|
|
8443
|
+
function prepareTessellation(solid, toleranceMm = IFC_MESH_TOLERANCE_MM) {
|
|
8444
|
+
let meshData;
|
|
8445
|
+
try {
|
|
8446
|
+
meshData = mesh(solid, {
|
|
8447
|
+
tolerance: toleranceMm,
|
|
8448
|
+
angularTolerance: IFC_MESH_ANGULAR_TOLERANCE_RAD
|
|
8449
|
+
});
|
|
8450
|
+
} catch (cause) {
|
|
8451
|
+
return {
|
|
8452
|
+
ok: false,
|
|
8453
|
+
reason: cause instanceof Error ? cause.message : String(cause),
|
|
8454
|
+
cause
|
|
8455
|
+
};
|
|
8456
|
+
}
|
|
8457
|
+
const { vertices, triangles } = meshData;
|
|
8458
|
+
if (vertices.length === 0 || triangles.length === 0) return {
|
|
8459
|
+
ok: false,
|
|
8460
|
+
reason: "mesh() returned an empty triangle set"
|
|
8461
|
+
};
|
|
8462
|
+
const coordList = [];
|
|
8463
|
+
for (let i = 0; i + 2 < vertices.length; i += 3) coordList.push([
|
|
8464
|
+
toIfcLengthM(vertices[i] ?? 0),
|
|
8465
|
+
toIfcLengthM(vertices[i + 1] ?? 0),
|
|
8466
|
+
toIfcLengthM(vertices[i + 2] ?? 0)
|
|
8467
|
+
]);
|
|
8468
|
+
const coordIndex = [];
|
|
8469
|
+
for (let i = 0; i + 2 < triangles.length; i += 3) coordIndex.push([
|
|
8470
|
+
(triangles[i] ?? 0) + 1,
|
|
8471
|
+
(triangles[i + 1] ?? 0) + 1,
|
|
8472
|
+
(triangles[i + 2] ?? 0) + 1
|
|
8473
|
+
]);
|
|
8474
|
+
return {
|
|
8475
|
+
ok: true,
|
|
8476
|
+
value: {
|
|
8477
|
+
coordList,
|
|
8478
|
+
coordIndex
|
|
8479
|
+
}
|
|
8480
|
+
};
|
|
8481
|
+
}
|
|
8281
8482
|
/**
|
|
8282
8483
|
* Writes an IfcTriangulatedFaceSet (preferred IFC4 tessellation) from a brepjs
|
|
8283
8484
|
* ValidSolid, wrapped in an IfcShapeRepresentation (Body/Tessellation) and an
|
|
@@ -8296,52 +8497,20 @@ var IFC_MESH_ANGULAR_TOLERANCE_RAD = .3;
|
|
|
8296
8497
|
* shape representation, so it is not referenced here.
|
|
8297
8498
|
*/
|
|
8298
8499
|
function writeTessellation(w, solid, geomSubContextId, _localPlacementId, toleranceMm = IFC_MESH_TOLERANCE_MM) {
|
|
8299
|
-
|
|
8300
|
-
|
|
8301
|
-
|
|
8302
|
-
tolerance: toleranceMm,
|
|
8303
|
-
angularTolerance: IFC_MESH_ANGULAR_TOLERANCE_RAD
|
|
8304
|
-
});
|
|
8305
|
-
} catch (e) {
|
|
8306
|
-
const reason = e instanceof Error ? e.message : String(e);
|
|
8500
|
+
const prepared = prepareTessellation(solid, toleranceMm);
|
|
8501
|
+
if (!prepared.ok) {
|
|
8502
|
+
const reason = prepared.reason;
|
|
8307
8503
|
console.warn(`writeTessellation: mesh() failed, using IfcFacetedBrep fallback: ${reason}`);
|
|
8308
8504
|
return writeFacetedBrepFallback(w, geomSubContextId, reason);
|
|
8309
8505
|
}
|
|
8310
|
-
const {
|
|
8311
|
-
|
|
8312
|
-
|
|
8313
|
-
|
|
8314
|
-
|
|
8315
|
-
|
|
8316
|
-
|
|
8317
|
-
|
|
8318
|
-
toIfcLengthM(vertices[i] ?? 0),
|
|
8319
|
-
toIfcLengthM(vertices[i + 1] ?? 0),
|
|
8320
|
-
toIfcLengthM(vertices[i + 2] ?? 0)
|
|
8321
|
-
]);
|
|
8322
|
-
const pointListId = w.nextId();
|
|
8323
|
-
w.writeLine({
|
|
8324
|
-
expressID: pointListId,
|
|
8325
|
-
type: WebIFC.IFCCARTESIANPOINTLIST3D,
|
|
8326
|
-
CoordList: coordList.map((pt) => pt.map((v) => w.mkType(WebIFC.IFCLENGTHMEASURE, v))),
|
|
8327
|
-
TagList: null
|
|
8328
|
-
});
|
|
8329
|
-
const coordIndex = [];
|
|
8330
|
-
for (let i = 0; i + 2 < triangles.length; i += 3) coordIndex.push([
|
|
8331
|
-
(triangles[i] ?? 0) + 1,
|
|
8332
|
-
(triangles[i + 1] ?? 0) + 1,
|
|
8333
|
-
(triangles[i + 2] ?? 0) + 1
|
|
8334
|
-
]);
|
|
8335
|
-
const faceSetId = w.nextId();
|
|
8336
|
-
w.writeLine({
|
|
8337
|
-
expressID: faceSetId,
|
|
8338
|
-
type: WebIFC.IFCTRIANGULATEDFACESET,
|
|
8339
|
-
Coordinates: w.ref(pointListId),
|
|
8340
|
-
Normals: null,
|
|
8341
|
-
Closed: w.mkType(WebIFC.IFCBOOLEAN, true),
|
|
8342
|
-
CoordIndex: coordIndex.map((tri) => tri.map((idx) => w.mkType(WebIFC.IFCPOSITIVEINTEGER, idx))),
|
|
8343
|
-
PnIndex: null
|
|
8344
|
-
});
|
|
8506
|
+
const { productDefinitionShapeId } = writePreparedTessellationBody(w, [prepared.value], geomSubContextId);
|
|
8507
|
+
return {
|
|
8508
|
+
productDefinitionShapeId,
|
|
8509
|
+
usedFallback: false
|
|
8510
|
+
};
|
|
8511
|
+
}
|
|
8512
|
+
function writePreparedTessellationBody(w, items, geomSubContextId) {
|
|
8513
|
+
const bodyItemIds = items.map((item) => writePreparedTessellationItem(w, item));
|
|
8345
8514
|
const shapeRepId = w.nextId();
|
|
8346
8515
|
w.writeLine({
|
|
8347
8516
|
expressID: shapeRepId,
|
|
@@ -8349,7 +8518,7 @@ function writeTessellation(w, solid, geomSubContextId, _localPlacementId, tolera
|
|
|
8349
8518
|
ContextOfItems: w.ref(geomSubContextId),
|
|
8350
8519
|
RepresentationIdentifier: w.mkType(WebIFC.IFCLABEL, "Body"),
|
|
8351
8520
|
RepresentationType: w.mkType(WebIFC.IFCLABEL, "Tessellation"),
|
|
8352
|
-
Items:
|
|
8521
|
+
Items: bodyItemIds.map((id) => w.ref(id))
|
|
8353
8522
|
});
|
|
8354
8523
|
const productDefinitionShapeId = w.nextId();
|
|
8355
8524
|
w.writeLine({
|
|
@@ -8361,9 +8530,55 @@ function writeTessellation(w, solid, geomSubContextId, _localPlacementId, tolera
|
|
|
8361
8530
|
});
|
|
8362
8531
|
return {
|
|
8363
8532
|
productDefinitionShapeId,
|
|
8364
|
-
|
|
8533
|
+
bodyItemIds
|
|
8534
|
+
};
|
|
8535
|
+
}
|
|
8536
|
+
function writeExactBodyGeometry(w, placement, items, geomSubContextId, parentPlacementId) {
|
|
8537
|
+
const placement3DId = writeAxis2Placement3D(w, [
|
|
8538
|
+
toIfcLengthM(placement.origin[0]),
|
|
8539
|
+
toIfcLengthM(placement.origin[1]),
|
|
8540
|
+
toIfcLengthM(placement.origin[2])
|
|
8541
|
+
], [
|
|
8542
|
+
placement.axisZ[0],
|
|
8543
|
+
placement.axisZ[1],
|
|
8544
|
+
placement.axisZ[2]
|
|
8545
|
+
], [
|
|
8546
|
+
placement.axisX[0],
|
|
8547
|
+
placement.axisX[1],
|
|
8548
|
+
placement.axisX[2]
|
|
8549
|
+
]);
|
|
8550
|
+
const localPlacementId = w.nextId();
|
|
8551
|
+
w.writeLine({
|
|
8552
|
+
expressID: localPlacementId,
|
|
8553
|
+
type: WebIFC.IFCLOCALPLACEMENT,
|
|
8554
|
+
PlacementRelTo: parentPlacementId === null ? null : w.ref(parentPlacementId),
|
|
8555
|
+
RelativePlacement: w.ref(placement3DId)
|
|
8556
|
+
});
|
|
8557
|
+
return {
|
|
8558
|
+
localPlacementId,
|
|
8559
|
+
...writePreparedTessellationBody(w, items, geomSubContextId)
|
|
8365
8560
|
};
|
|
8366
8561
|
}
|
|
8562
|
+
function writePreparedTessellationItem(w, prepared) {
|
|
8563
|
+
const pointListId = w.nextId();
|
|
8564
|
+
w.writeLine({
|
|
8565
|
+
expressID: pointListId,
|
|
8566
|
+
type: WebIFC.IFCCARTESIANPOINTLIST3D,
|
|
8567
|
+
CoordList: prepared.coordList.map((point) => point.map((value) => w.mkType(WebIFC.IFCLENGTHMEASURE, value))),
|
|
8568
|
+
TagList: null
|
|
8569
|
+
});
|
|
8570
|
+
const faceSetId = w.nextId();
|
|
8571
|
+
w.writeLine({
|
|
8572
|
+
expressID: faceSetId,
|
|
8573
|
+
type: WebIFC.IFCTRIANGULATEDFACESET,
|
|
8574
|
+
Coordinates: w.ref(pointListId),
|
|
8575
|
+
Normals: null,
|
|
8576
|
+
Closed: w.mkType(WebIFC.IFCBOOLEAN, true),
|
|
8577
|
+
CoordIndex: prepared.coordIndex.map((triangle) => triangle.map((index) => w.mkType(WebIFC.IFCPOSITIVEINTEGER, index))),
|
|
8578
|
+
PnIndex: null
|
|
8579
|
+
});
|
|
8580
|
+
return faceSetId;
|
|
8581
|
+
}
|
|
8367
8582
|
/**
|
|
8368
8583
|
* Builds a wall 'Axis' IfcShapeRepresentation: an IfcPolyline from (0,0) to
|
|
8369
8584
|
* (lengthM, 0) in the wall's local XY plane, wrapped in an IfcShapeRepresentation
|
|
@@ -9860,22 +10075,22 @@ function writeStairAssembly(w, spec, stairKey, assemblyGuid, ownerHistoryId, geo
|
|
|
9860
10075
|
const flightExpressIds = [];
|
|
9861
10076
|
let geometrySimplified = false;
|
|
9862
10077
|
for (const [i, flight] of spec.flights.entries()) try {
|
|
9863
|
-
var _usingCtx$
|
|
10078
|
+
var _usingCtx$3 = _usingCtx();
|
|
9864
10079
|
const built = stairFlightToSolid(flight);
|
|
9865
10080
|
if (!built.ok) return {
|
|
9866
10081
|
ok: false,
|
|
9867
10082
|
error: built.error
|
|
9868
10083
|
};
|
|
9869
|
-
const flightSolid = _usingCtx$
|
|
10084
|
+
const flightSolid = _usingCtx$3.u(built.value.solid);
|
|
9870
10085
|
const flightPlacementId = writeLocalPlacement(w, flight.origin, flight.axisZ, flight.axisX, stairPlacementId);
|
|
9871
10086
|
const tess = writeTessellation(w, flightSolid, geomSubContextId, flightPlacementId);
|
|
9872
10087
|
if (tess.usedFallback) geometrySimplified = true;
|
|
9873
10088
|
const flightExpressId = writeStairFlightEntity(w, deriveIfcGuidSync(`elem:STAIR_FLIGHT:${stairKey}:${i}`), `${stairName} Flight ${i + 1}`, flight, ownerHistoryId, flightPlacementId, tess.productDefinitionShapeId);
|
|
9874
10089
|
flightExpressIds.push(flightExpressId);
|
|
9875
10090
|
} catch (_) {
|
|
9876
|
-
_usingCtx$
|
|
10091
|
+
_usingCtx$3.e = _;
|
|
9877
10092
|
} finally {
|
|
9878
|
-
_usingCtx$
|
|
10093
|
+
_usingCtx$3.d();
|
|
9879
10094
|
}
|
|
9880
10095
|
writeRelAggregates(w, deriveIfcGuidSync(`rel:AGGREGATES:STAIR:${stairKey}`), ownerHistoryId, assemblyExpressId, flightExpressIds);
|
|
9881
10096
|
writeAssemblyType(w, WebIFC.IFCSTAIRTYPE, "Stair Type", deriveIfcGuidSync(`type:STAIR:${stairKey}`), deriveIfcGuidSync(`rel-type:STAIR:${stairKey}`), predefinedType, ownerHistoryId, [assemblyExpressId]);
|
|
@@ -11270,6 +11485,14 @@ function writeWallBaseQuantities(w, ownerHistoryId, wallExpressId, spec, opening
|
|
|
11270
11485
|
pushWeightQuantity(w, qtyIds, netVolumeM3, densityKgM3);
|
|
11271
11486
|
writeRelDefinesByProperties(w, ownerHistoryId, wallExpressId, writeElementQuantity(w, ownerHistoryId, "Qto_WallBaseQuantities", qtyIds));
|
|
11272
11487
|
}
|
|
11488
|
+
function writeExactWallBaseQuantities(w, ownerHistoryId, wallExpressId, values) {
|
|
11489
|
+
writeRelDefinesByProperties(w, ownerHistoryId, wallExpressId, writeElementQuantity(w, ownerHistoryId, "Qto_WallBaseQuantities", [
|
|
11490
|
+
writeQtyLength(w, "Length", values.lengthM),
|
|
11491
|
+
writeQtyLength(w, "Width", values.widthM),
|
|
11492
|
+
writeQtyLength(w, "Height", values.heightM),
|
|
11493
|
+
writeQtyVolume(w, "NetVolume", values.netVolumeM3)
|
|
11494
|
+
]));
|
|
11495
|
+
}
|
|
11273
11496
|
function writeSlabCommonPset(w, ownerHistoryId, slabExpressId, spec) {
|
|
11274
11497
|
const values = {};
|
|
11275
11498
|
if (spec.isExternal !== void 0) values["IsExternal"] = spec.isExternal;
|
|
@@ -13282,457 +13505,580 @@ function checkGeoreferencing(reader) {
|
|
|
13282
13505
|
return [issue("warning", "NO_GEOREFERENCING", "Model contains a facility but no IfcProjectedCRS/IfcGeographicCRS (GRF003) — set ProjectSpec.crs")];
|
|
13283
13506
|
}
|
|
13284
13507
|
//#endregion
|
|
13285
|
-
//#region src/serialize/
|
|
13286
|
-
|
|
13287
|
-
|
|
13288
|
-
|
|
13289
|
-
|
|
13290
|
-
const
|
|
13291
|
-
|
|
13292
|
-
|
|
13293
|
-
|
|
13294
|
-
|
|
13295
|
-
|
|
13296
|
-
|
|
13297
|
-
|
|
13298
|
-
const
|
|
13299
|
-
const
|
|
13300
|
-
|
|
13301
|
-
const
|
|
13302
|
-
const
|
|
13303
|
-
|
|
13304
|
-
|
|
13305
|
-
|
|
13306
|
-
const columns = model.getColumns();
|
|
13307
|
-
const doors = model.getDoors();
|
|
13308
|
-
const windows = model.getWindows();
|
|
13309
|
-
const proxies = model.getProxies();
|
|
13310
|
-
const spaces = model.getSpaces();
|
|
13311
|
-
const roofs = model.getRoofs();
|
|
13312
|
-
const curtainWalls = model.getCurtainWalls();
|
|
13313
|
-
const footings = model.getFootings();
|
|
13314
|
-
const piles = model.getPiles();
|
|
13315
|
-
const stairs = model.getStairs();
|
|
13316
|
-
const ramps = model.getRamps();
|
|
13317
|
-
const railings = model.getRailings();
|
|
13318
|
-
const coverings = model.getCoverings();
|
|
13319
|
-
const assemblies = model.getElementAssemblies();
|
|
13320
|
-
const zones = model.getZones();
|
|
13321
|
-
const systems = model.getSystems();
|
|
13322
|
-
const { ownerHistoryId, geomContextId, geomSubContextId, unitAssignmentId, lengthUnitId } = writeHeader(w, meta);
|
|
13323
|
-
if (project.spec.crs !== void 0) writeMapConversion(w, project.spec.crs, geomContextId, lengthUnitId);
|
|
13324
|
-
const densityByElement = buildDensityMap(relationships);
|
|
13325
|
-
const idMap = /* @__PURE__ */ new Map();
|
|
13326
|
-
const placementMap = /* @__PURE__ */ new Map();
|
|
13327
|
-
const projectExpressId = writeProject$1(w, project.guid, project.spec.name, ownerHistoryId, unitAssignmentId, geomContextId);
|
|
13328
|
-
idMap.set(project.localId, projectExpressId);
|
|
13329
|
-
for (const el of elements) {
|
|
13330
|
-
if (el.category !== "SITE") continue;
|
|
13331
|
-
const parentId = findParentOf(el.localId, relationships);
|
|
13332
|
-
const parentPlacementId = parentId !== null ? placementMap.get(parentId) ?? null : null;
|
|
13333
|
-
const { entityId, placementId } = writeSite(w, el.guid, el.spec, ownerHistoryId, parentPlacementId);
|
|
13334
|
-
idMap.set(el.localId, entityId);
|
|
13335
|
-
placementMap.set(el.localId, placementId);
|
|
13336
|
-
}
|
|
13337
|
-
for (const bridge of bridges) {
|
|
13338
|
-
const parentId = findParentOf(bridge.localId, relationships);
|
|
13339
|
-
const parentPlacementId = parentId !== null ? placementMap.get(parentId) ?? null : null;
|
|
13340
|
-
const { entityId, placementId } = writeBridge(w, bridge.guid, bridge.spec, ownerHistoryId, parentPlacementId);
|
|
13341
|
-
idMap.set(bridge.localId, entityId);
|
|
13342
|
-
placementMap.set(bridge.localId, placementId);
|
|
13343
|
-
}
|
|
13344
|
-
const pendingParts = [...bridgeParts];
|
|
13345
|
-
while (pendingParts.length > 0) {
|
|
13346
|
-
const readyIndex = pendingParts.findIndex((candidate) => {
|
|
13347
|
-
const candidateParentId = findParentOf(candidate.localId, relationships);
|
|
13348
|
-
return candidateParentId === null || placementMap.has(candidateParentId);
|
|
13349
|
-
});
|
|
13350
|
-
const [part] = pendingParts.splice(readyIndex === -1 ? 0 : readyIndex, 1);
|
|
13351
|
-
if (part === void 0) break;
|
|
13352
|
-
const parentId = findParentOf(part.localId, relationships);
|
|
13353
|
-
const parentPlacementId = parentId !== null ? placementMap.get(parentId) ?? null : null;
|
|
13354
|
-
const { entityId, placementId } = writeBridgePart(w, part.guid, part.spec, ownerHistoryId, parentPlacementId);
|
|
13355
|
-
idMap.set(part.localId, entityId);
|
|
13356
|
-
placementMap.set(part.localId, placementId);
|
|
13357
|
-
}
|
|
13358
|
-
for (const el of elements) {
|
|
13359
|
-
if (el.category !== "BUILDING") continue;
|
|
13360
|
-
const parentSiteId = findParentOf(el.localId, relationships);
|
|
13361
|
-
const parentPlacementId = parentSiteId !== null ? placementMap.get(parentSiteId) ?? null : null;
|
|
13362
|
-
const { entityId, placementId } = writeBuilding(w, el.guid, el.spec.name, ownerHistoryId, parentPlacementId);
|
|
13363
|
-
idMap.set(el.localId, entityId);
|
|
13364
|
-
placementMap.set(el.localId, placementId);
|
|
13365
|
-
}
|
|
13366
|
-
for (const el of elements) {
|
|
13367
|
-
if (el.category !== "STOREY") continue;
|
|
13368
|
-
const parentBuildingId = findParentOf(el.localId, relationships);
|
|
13369
|
-
const parentPlacementId = parentBuildingId !== null ? placementMap.get(parentBuildingId) ?? null : null;
|
|
13370
|
-
const { entityId, placementId } = writeStorey(w, el.guid, el.spec.name, el.spec.elevation, ownerHistoryId, parentPlacementId);
|
|
13371
|
-
idMap.set(el.localId, entityId);
|
|
13372
|
-
placementMap.set(el.localId, placementId);
|
|
13373
|
-
}
|
|
13374
|
-
const openingsByWall = /* @__PURE__ */ new Map();
|
|
13375
|
-
for (const rel of relationships) {
|
|
13376
|
-
if (rel.kind !== "VOIDS_WALL") continue;
|
|
13377
|
-
const opening = elements.find((el) => el.localId === rel.openingLocalId);
|
|
13378
|
-
if (opening === void 0 || opening.category !== "OPENING") continue;
|
|
13379
|
-
if (!isWallOpening(opening.spec)) continue;
|
|
13380
|
-
const list = openingsByWall.get(rel.wallLocalId) ?? [];
|
|
13381
|
-
list.push(opening.spec);
|
|
13382
|
-
openingsByWall.set(rel.wallLocalId, list);
|
|
13383
|
-
}
|
|
13384
|
-
const openingsBySlab = /* @__PURE__ */ new Map();
|
|
13385
|
-
for (const rel of relationships) {
|
|
13386
|
-
if (rel.kind !== "VOIDS_SLAB") continue;
|
|
13387
|
-
const opening = elements.find((el) => el.localId === rel.openingLocalId);
|
|
13388
|
-
if (opening === void 0 || opening.category !== "OPENING") continue;
|
|
13389
|
-
if (!isSlabOpening(opening.spec)) continue;
|
|
13390
|
-
const list = openingsBySlab.get(rel.slabLocalId) ?? [];
|
|
13391
|
-
list.push(opening.spec);
|
|
13392
|
-
openingsBySlab.set(rel.slabLocalId, list);
|
|
13393
|
-
}
|
|
13394
|
-
for (const [i, wall] of walls.entries()) {
|
|
13395
|
-
const containingId = findContainerOf(wall.localId, relationships);
|
|
13396
|
-
const storeyPlacementId = containingId !== null ? placementMap.get(containingId) ?? null : null;
|
|
13397
|
-
const { localPlacementId, productDefinitionShapeId } = writeWallGeometry(w, wall.spec, geomSubContextId, storeyPlacementId);
|
|
13398
|
-
const wallExpressId = writeWallEntity(w, wall.guid, `Wall ${i + 1}`, ownerHistoryId, localPlacementId, productDefinitionShapeId);
|
|
13399
|
-
idMap.set(wall.localId, wallExpressId);
|
|
13400
|
-
placementMap.set(wall.localId, localPlacementId);
|
|
13401
|
-
writeWallCommonPset(w, ownerHistoryId, wallExpressId, wall.spec);
|
|
13402
|
-
writeManufacturerPset(w, ownerHistoryId, wallExpressId, wall.spec);
|
|
13403
|
-
if (wall.spec.customProperties !== void 0) writeCustomPsets(w, ownerHistoryId, wallExpressId, wall.spec.customProperties);
|
|
13404
|
-
writeWallBaseQuantities(w, ownerHistoryId, wallExpressId, wall.spec, openingsByWall.get(wall.localId) ?? [], densityByElement.get(wall.localId));
|
|
13405
|
-
}
|
|
13406
|
-
for (const [i, slab] of slabs.entries()) {
|
|
13407
|
-
const containingId = findContainerOf(slab.localId, relationships);
|
|
13408
|
-
const storeyPlacementId = containingId !== null ? placementMap.get(containingId) ?? null : null;
|
|
13409
|
-
const { localPlacementId, productDefinitionShapeId } = writeSlabGeometry(w, slab.spec, geomSubContextId, storeyPlacementId);
|
|
13410
|
-
const slabExpressId = writeSlabEntity(w, slab.guid, `Slab ${i + 1}`, slab.spec.predefinedType, ownerHistoryId, localPlacementId, productDefinitionShapeId);
|
|
13411
|
-
idMap.set(slab.localId, slabExpressId);
|
|
13412
|
-
placementMap.set(slab.localId, localPlacementId);
|
|
13413
|
-
writeSlabCommonPset(w, ownerHistoryId, slabExpressId, slab.spec);
|
|
13414
|
-
writeManufacturerPset(w, ownerHistoryId, slabExpressId, slab.spec);
|
|
13415
|
-
if (slab.spec.customProperties !== void 0) writeCustomPsets(w, ownerHistoryId, slabExpressId, slab.spec.customProperties);
|
|
13416
|
-
writeSlabBaseQuantities(w, ownerHistoryId, slabExpressId, slab.spec, openingsBySlab.get(slab.localId) ?? [], densityByElement.get(slab.localId));
|
|
13417
|
-
}
|
|
13418
|
-
for (const [i, beam] of beams.entries()) {
|
|
13419
|
-
const containingId = findContainerOf(beam.localId, relationships);
|
|
13420
|
-
const storeyPlacementId = containingId !== null ? placementMap.get(containingId) ?? null : null;
|
|
13421
|
-
const { localPlacementId, productDefinitionShapeId } = writeBeamGeometry(w, beam.spec, geomSubContextId, storeyPlacementId);
|
|
13422
|
-
const beamExpressId = writeBeamEntity(w, beam.guid, `Beam ${i + 1}`, beam.spec.predefinedType ?? "NOTDEFINED", ownerHistoryId, localPlacementId, productDefinitionShapeId);
|
|
13423
|
-
idMap.set(beam.localId, beamExpressId);
|
|
13424
|
-
placementMap.set(beam.localId, localPlacementId);
|
|
13425
|
-
writeBeamCommonPset(w, ownerHistoryId, beamExpressId, beam.spec);
|
|
13426
|
-
writeManufacturerPset(w, ownerHistoryId, beamExpressId, beam.spec);
|
|
13427
|
-
if (beam.spec.customProperties !== void 0) writeCustomPsets(w, ownerHistoryId, beamExpressId, beam.spec.customProperties);
|
|
13428
|
-
writeBeamBaseQuantities(w, ownerHistoryId, beamExpressId, beam.spec);
|
|
13429
|
-
}
|
|
13430
|
-
for (const [i, column] of columns.entries()) {
|
|
13431
|
-
const containingId = findContainerOf(column.localId, relationships);
|
|
13432
|
-
const storeyPlacementId = containingId !== null ? placementMap.get(containingId) ?? null : null;
|
|
13433
|
-
const { localPlacementId, productDefinitionShapeId } = writeColumnGeometry(w, column.spec, geomSubContextId, storeyPlacementId);
|
|
13434
|
-
const columnExpressId = writeColumnEntity(w, column.guid, `Column ${i + 1}`, column.spec.predefinedType ?? "NOTDEFINED", ownerHistoryId, localPlacementId, productDefinitionShapeId);
|
|
13435
|
-
idMap.set(column.localId, columnExpressId);
|
|
13436
|
-
placementMap.set(column.localId, localPlacementId);
|
|
13437
|
-
writeColumnCommonPset(w, ownerHistoryId, columnExpressId, column.spec);
|
|
13438
|
-
writeManufacturerPset(w, ownerHistoryId, columnExpressId, column.spec);
|
|
13439
|
-
if (column.spec.customProperties !== void 0) writeCustomPsets(w, ownerHistoryId, columnExpressId, column.spec.customProperties);
|
|
13440
|
-
writeColumnBaseQuantities(w, ownerHistoryId, columnExpressId, column.spec);
|
|
13441
|
-
}
|
|
13442
|
-
for (const [i, proxy] of proxies.entries()) {
|
|
13443
|
-
const containingId = findContainerOf(proxy.localId, relationships);
|
|
13444
|
-
const storeyPlacementId = containingId !== null ? placementMap.get(containingId) ?? null : null;
|
|
13445
|
-
const { localPlacementId, productDefinitionShapeId } = writeProxyGeometry(w, proxy.spec, geomSubContextId, storeyPlacementId);
|
|
13446
|
-
const proxyExpressId = writeProxyEntity(w, proxy.guid, proxy.spec.name || `Proxy ${i + 1}`, proxy.spec.predefinedType ?? "NOTDEFINED", ownerHistoryId, localPlacementId, productDefinitionShapeId);
|
|
13447
|
-
idMap.set(proxy.localId, proxyExpressId);
|
|
13448
|
-
placementMap.set(proxy.localId, localPlacementId);
|
|
13449
|
-
if (proxy.spec.customProperties !== void 0) writeCustomPsets(w, ownerHistoryId, proxyExpressId, proxy.spec.customProperties);
|
|
13450
|
-
}
|
|
13451
|
-
for (const fill of earthworksFills) {
|
|
13452
|
-
const containingId = findContainerOf(fill.localId, relationships);
|
|
13453
|
-
const parentPlacementId = containingId !== null ? placementMap.get(containingId) ?? null : null;
|
|
13454
|
-
const { localPlacementId, productDefinitionShapeId } = writeTessellatedProductGeometry(w, fill.geometry, geomSubContextId, parentPlacementId);
|
|
13455
|
-
const expressId = writeEarthworksFillEntity(w, fill.guid, fill.spec, ownerHistoryId, localPlacementId, productDefinitionShapeId);
|
|
13456
|
-
idMap.set(fill.localId, expressId);
|
|
13457
|
-
placementMap.set(fill.localId, localPlacementId);
|
|
13458
|
-
if (fill.spec.customProperties !== void 0) writeCustomPsets(w, ownerHistoryId, expressId, fill.spec.customProperties);
|
|
13459
|
-
}
|
|
13460
|
-
for (const [i, space] of spaces.entries()) {
|
|
13461
|
-
const containingId = findContainerOf(space.localId, relationships);
|
|
13462
|
-
const storeyPlacementId = containingId !== null ? placementMap.get(containingId) ?? null : null;
|
|
13463
|
-
const { localPlacementId, productDefinitionShapeId } = writeSpaceGeometry(w, space.spec, geomSubContextId, storeyPlacementId);
|
|
13464
|
-
const spaceExpressId = writeSpaceEntity(w, space.guid, space.spec.name || `Space ${i + 1}`, space.spec.longName ?? null, space.spec.predefinedType ?? "NOTDEFINED", ownerHistoryId, localPlacementId, productDefinitionShapeId);
|
|
13465
|
-
idMap.set(space.localId, spaceExpressId);
|
|
13466
|
-
placementMap.set(space.localId, localPlacementId);
|
|
13467
|
-
writeSpaceCommonPset(w, ownerHistoryId, spaceExpressId, space.spec);
|
|
13468
|
-
if (space.spec.customProperties !== void 0) writeCustomPsets(w, ownerHistoryId, spaceExpressId, space.spec.customProperties);
|
|
13469
|
-
writeSpaceBaseQuantities(w, ownerHistoryId, spaceExpressId, space.spec);
|
|
13470
|
-
}
|
|
13471
|
-
for (const [i, roof] of roofs.entries()) {
|
|
13472
|
-
const containingId = findContainerOf(roof.localId, relationships);
|
|
13473
|
-
const storeyPlacementId = containingId !== null ? placementMap.get(containingId) ?? null : null;
|
|
13474
|
-
const { localPlacementId, productDefinitionShapeId, usedFallback } = writeRoofGeometry(w, roof.spec, roof.geometry, geomSubContextId, storeyPlacementId);
|
|
13475
|
-
if (usedFallback) console.warn(`Roof ${i + 1} tessellation failed; IFC body is a degenerate fallback.`);
|
|
13476
|
-
const roofExpressId = writeRoofEntity(w, roof.guid, `Roof ${i + 1}`, roof.spec.predefinedType, ownerHistoryId, localPlacementId, productDefinitionShapeId);
|
|
13477
|
-
idMap.set(roof.localId, roofExpressId);
|
|
13478
|
-
placementMap.set(roof.localId, localPlacementId);
|
|
13479
|
-
writeRoofCommonPset(w, ownerHistoryId, roofExpressId, roof.spec);
|
|
13480
|
-
writeManufacturerPset(w, ownerHistoryId, roofExpressId, roof.spec);
|
|
13481
|
-
if (roof.spec.customProperties !== void 0) writeCustomPsets(w, ownerHistoryId, roofExpressId, roof.spec.customProperties);
|
|
13482
|
-
writeRoofBaseQuantities(w, ownerHistoryId, roofExpressId, roof.spec);
|
|
13483
|
-
}
|
|
13484
|
-
for (const [i, curtainWall] of curtainWalls.entries()) {
|
|
13485
|
-
const containingId = findContainerOf(curtainWall.localId, relationships);
|
|
13486
|
-
const storeyPlacementId = containingId !== null ? placementMap.get(containingId) ?? null : null;
|
|
13487
|
-
const { curtainWallId } = writeCurtainWall(w, curtainWall.spec, curtainWall.geometry, `elem:CURTAIN_WALL:${curtainWall.localId}`, `Curtain Wall ${i + 1}`, ownerHistoryId, geomSubContextId, storeyPlacementId);
|
|
13488
|
-
idMap.set(curtainWall.localId, curtainWallId);
|
|
13489
|
-
writeCurtainWallCommonPset(w, ownerHistoryId, curtainWallId, curtainWall.spec);
|
|
13490
|
-
if (curtainWall.spec.customProperties !== void 0) writeCustomPsets(w, ownerHistoryId, curtainWallId, curtainWall.spec.customProperties);
|
|
13491
|
-
}
|
|
13492
|
-
for (const [i, footing] of footings.entries()) {
|
|
13493
|
-
const containingId = findContainerOf(footing.localId, relationships);
|
|
13494
|
-
const storeyPlacementId = containingId !== null ? placementMap.get(containingId) ?? null : null;
|
|
13495
|
-
const { localPlacementId, productDefinitionShapeId } = writeFootingGeometry(w, footing.spec, geomSubContextId, storeyPlacementId);
|
|
13496
|
-
const footingExpressId = writeFootingEntity(w, footing.guid, `Footing ${i + 1}`, footing.spec.predefinedType ?? "NOTDEFINED", ownerHistoryId, localPlacementId, productDefinitionShapeId);
|
|
13497
|
-
idMap.set(footing.localId, footingExpressId);
|
|
13498
|
-
placementMap.set(footing.localId, localPlacementId);
|
|
13499
|
-
writeFootingCommonPset(w, ownerHistoryId, footingExpressId, footing.spec);
|
|
13500
|
-
if (footing.spec.customProperties !== void 0) writeCustomPsets(w, ownerHistoryId, footingExpressId, footing.spec.customProperties);
|
|
13501
|
-
writeFootingBaseQuantities(w, ownerHistoryId, footingExpressId, footing.spec);
|
|
13502
|
-
}
|
|
13503
|
-
for (const [i, pile] of piles.entries()) {
|
|
13504
|
-
const containingId = findContainerOf(pile.localId, relationships);
|
|
13505
|
-
const storeyPlacementId = containingId !== null ? placementMap.get(containingId) ?? null : null;
|
|
13506
|
-
const { localPlacementId, productDefinitionShapeId } = writePileGeometry(w, pile.spec, geomSubContextId, storeyPlacementId);
|
|
13507
|
-
const pileExpressId = writePileEntity(w, pile.guid, `Pile ${i + 1}`, pile.spec.predefinedType ?? "NOTDEFINED", pile.spec.constructionType ?? null, ownerHistoryId, localPlacementId, productDefinitionShapeId);
|
|
13508
|
-
idMap.set(pile.localId, pileExpressId);
|
|
13509
|
-
placementMap.set(pile.localId, localPlacementId);
|
|
13510
|
-
writePileCommonPset(w, ownerHistoryId, pileExpressId, pile.spec);
|
|
13511
|
-
if (pile.spec.customProperties !== void 0) writeCustomPsets(w, ownerHistoryId, pileExpressId, pile.spec.customProperties);
|
|
13512
|
-
writePileBaseQuantities(w, ownerHistoryId, pileExpressId, pile.spec);
|
|
13513
|
-
}
|
|
13514
|
-
for (const [i, assembly] of assemblies.entries()) {
|
|
13515
|
-
const containingId = findContainerOf(assembly.localId, relationships);
|
|
13516
|
-
const storeyPlacementId = containingId !== null ? placementMap.get(containingId) ?? null : null;
|
|
13517
|
-
const assemblyExpressId = writeElementAssemblyEntity(w, assembly.guid, assembly.spec.name ?? `Assembly ${i + 1}`, assembly.spec.predefinedType ?? "NOTDEFINED", ownerHistoryId, storeyPlacementId, null, assembly.spec.assemblyPlace ?? "NOTDEFINED");
|
|
13518
|
-
idMap.set(assembly.localId, assemblyExpressId);
|
|
13519
|
-
}
|
|
13520
|
-
for (const zone of zones) {
|
|
13521
|
-
const zoneExpressId = writeZoneEntity(w, zone.guid, zone.spec.name, zone.spec.longName ?? null, zone.spec.objectType ?? null, ownerHistoryId);
|
|
13522
|
-
idMap.set(zone.localId, zoneExpressId);
|
|
13523
|
-
}
|
|
13524
|
-
for (const system of systems) {
|
|
13525
|
-
const systemExpressId = writeSystemEntity(w, system.guid, system.spec.name, system.spec.longName ?? null, system.spec.objectType ?? null, ownerHistoryId);
|
|
13526
|
-
idMap.set(system.localId, systemExpressId);
|
|
13527
|
-
}
|
|
13528
|
-
for (const stair of stairs) {
|
|
13529
|
-
const containingId = findContainerOf(stair.localId, relationships);
|
|
13530
|
-
const storeyPlacementId = containingId !== null ? placementMap.get(containingId) ?? null : null;
|
|
13531
|
-
const result = writeStairAssembly(w, stair.spec, `${stair.localId}`, stair.guid, ownerHistoryId, geomSubContextId, storeyPlacementId);
|
|
13532
|
-
if (!result.ok) return err(result.error);
|
|
13533
|
-
idMap.set(stair.localId, result.value.assemblyExpressId);
|
|
13534
|
-
writeStairCommonPset(w, ownerHistoryId, result.value.assemblyExpressId, stair.spec);
|
|
13535
|
-
}
|
|
13536
|
-
for (const ramp of ramps) {
|
|
13537
|
-
const containingId = findContainerOf(ramp.localId, relationships);
|
|
13538
|
-
const storeyPlacementId = containingId !== null ? placementMap.get(containingId) ?? null : null;
|
|
13539
|
-
const result = writeRampAssembly(w, ramp.spec, `${ramp.localId}`, ramp.guid, ownerHistoryId, geomSubContextId, storeyPlacementId);
|
|
13540
|
-
if (!result.ok) return err(result.error);
|
|
13541
|
-
idMap.set(ramp.localId, result.value.assemblyExpressId);
|
|
13542
|
-
writeRampCommonPset(w, ownerHistoryId, result.value.assemblyExpressId, ramp.spec);
|
|
13543
|
-
}
|
|
13544
|
-
for (const [i, railing] of railings.entries()) {
|
|
13545
|
-
const containingId = findContainerOf(railing.localId, relationships);
|
|
13546
|
-
const storeyPlacementId = containingId !== null ? placementMap.get(containingId) ?? null : null;
|
|
13547
|
-
const { localPlacementId, productDefinitionShapeId, bodyItemId, usedFallback } = writeRailingGeometry(w, railing.spec, railing.geometry, geomSubContextId, storeyPlacementId);
|
|
13548
|
-
if (usedFallback) console.warn(`Railing ${i + 1} tessellation failed; IFC body is a degenerate fallback.`);
|
|
13549
|
-
const railingExpressId = writeRailingEntity(w, railing.guid, `Railing ${i + 1}`, railing.spec.predefinedType ?? "NOTDEFINED", ownerHistoryId, localPlacementId, productDefinitionShapeId);
|
|
13550
|
-
idMap.set(railing.localId, railingExpressId);
|
|
13551
|
-
placementMap.set(railing.localId, localPlacementId);
|
|
13552
|
-
writeRailingCommonPset(w, ownerHistoryId, railingExpressId, railing.spec);
|
|
13553
|
-
writeManufacturerPset(w, ownerHistoryId, railingExpressId, railing.spec);
|
|
13554
|
-
if (railing.spec.customProperties !== void 0) writeCustomPsets(w, ownerHistoryId, railingExpressId, railing.spec.customProperties);
|
|
13555
|
-
if (bodyItemId !== null) applySurfaceStyle(w, model, railing.localId, bodyItemId);
|
|
13556
|
-
}
|
|
13557
|
-
for (const [i, covering] of coverings.entries()) {
|
|
13558
|
-
const containingId = findContainerOf(covering.localId, relationships);
|
|
13559
|
-
const storeyPlacementId = containingId !== null ? placementMap.get(containingId) ?? null : null;
|
|
13560
|
-
const { localPlacementId, productDefinitionShapeId, bodyItemId } = writeCoveringGeometry(w, covering.spec, geomSubContextId, storeyPlacementId);
|
|
13561
|
-
const coveringExpressId = writeCoveringEntity(w, covering.guid, `Covering ${i + 1}`, covering.spec.predefinedType ?? "NOTDEFINED", ownerHistoryId, localPlacementId, productDefinitionShapeId);
|
|
13562
|
-
idMap.set(covering.localId, coveringExpressId);
|
|
13563
|
-
placementMap.set(covering.localId, localPlacementId);
|
|
13564
|
-
writeCoveringCommonPset(w, ownerHistoryId, coveringExpressId, covering.spec);
|
|
13565
|
-
writeManufacturerPset(w, ownerHistoryId, coveringExpressId, covering.spec);
|
|
13566
|
-
if (covering.spec.customProperties !== void 0) writeCustomPsets(w, ownerHistoryId, coveringExpressId, covering.spec.customProperties);
|
|
13567
|
-
applySurfaceStyle(w, model, covering.localId, bodyItemId);
|
|
13568
|
-
}
|
|
13569
|
-
const openingPlacementMap = /* @__PURE__ */ new Map();
|
|
13570
|
-
const openingEntityMap = /* @__PURE__ */ new Map();
|
|
13571
|
-
for (const rel of relationships) {
|
|
13572
|
-
if (rel.kind !== "VOIDS_WALL") continue;
|
|
13573
|
-
const wallElement = elements.find((el) => el.category === "WALL" && el.localId === rel.wallLocalId);
|
|
13574
|
-
if (wallElement === void 0) continue;
|
|
13575
|
-
const wallExpressId = idMap.get(rel.wallLocalId);
|
|
13576
|
-
const wallPlacementId = placementMap.get(rel.wallLocalId);
|
|
13577
|
-
if (wallExpressId === void 0 || wallPlacementId === void 0) continue;
|
|
13578
|
-
const openingElement = elements.find((el) => el.localId === rel.openingLocalId);
|
|
13579
|
-
if (openingElement === void 0 || openingElement.category !== "OPENING") continue;
|
|
13580
|
-
if (!isWallOpening(openingElement.spec)) continue;
|
|
13581
|
-
const { openingEntityId, openingPlacementId } = writeOpeningGeometry(w, openingElement.guid, openingElement.spec, wallElement.spec, wallPlacementId, geomSubContextId, ownerHistoryId);
|
|
13582
|
-
idMap.set(rel.openingLocalId, openingEntityId);
|
|
13583
|
-
openingPlacementMap.set(rel.openingLocalId, openingPlacementId);
|
|
13584
|
-
openingEntityMap.set(rel.openingLocalId, openingEntityId);
|
|
13585
|
-
writeRelVoidsElement(w, rel.guid, ownerHistoryId, wallExpressId, openingEntityId);
|
|
13586
|
-
}
|
|
13587
|
-
for (const rel of relationships) {
|
|
13588
|
-
if (rel.kind !== "VOIDS_SLAB") continue;
|
|
13589
|
-
const slabElement = elements.find((el) => el.category === "SLAB" && el.localId === rel.slabLocalId);
|
|
13590
|
-
if (slabElement === void 0) continue;
|
|
13591
|
-
const slabExpressId = idMap.get(rel.slabLocalId);
|
|
13592
|
-
const slabPlacementId = placementMap.get(rel.slabLocalId);
|
|
13593
|
-
if (slabExpressId === void 0 || slabPlacementId === void 0) continue;
|
|
13594
|
-
const openingElement = elements.find((el) => el.localId === rel.openingLocalId);
|
|
13595
|
-
if (openingElement === void 0 || openingElement.category !== "OPENING") continue;
|
|
13596
|
-
if (!isSlabOpening(openingElement.spec)) continue;
|
|
13597
|
-
const { openingEntityId } = writeSlabOpeningGeometry(w, openingElement.guid, openingElement.spec, slabElement.spec, slabPlacementId, geomSubContextId, ownerHistoryId);
|
|
13598
|
-
idMap.set(rel.openingLocalId, openingEntityId);
|
|
13599
|
-
writeRelVoidsElement(w, rel.guid, ownerHistoryId, slabExpressId, openingEntityId);
|
|
13600
|
-
}
|
|
13601
|
-
for (const [i, door] of doors.entries()) {
|
|
13602
|
-
const fillsRel = relationships.find((rel) => rel.kind === "FILLS_OPENING" && rel.fillerLocalId === door.localId);
|
|
13603
|
-
if (fillsRel === void 0 || fillsRel.kind !== "FILLS_OPENING") continue;
|
|
13604
|
-
const openingPlacementId = openingPlacementMap.get(fillsRel.openingLocalId);
|
|
13605
|
-
const openingEntityId = openingEntityMap.get(fillsRel.openingLocalId);
|
|
13606
|
-
if (openingPlacementId === void 0 || openingEntityId === void 0) continue;
|
|
13607
|
-
const doorExpressId = writeDoorEntity(w, door.guid, `Door ${i + 1}`, ownerHistoryId, openingPlacementId, geomSubContextId, toIfcLengthM(door.spec.width), toIfcLengthM(door.spec.height));
|
|
13608
|
-
idMap.set(door.localId, doorExpressId);
|
|
13609
|
-
writeRelFillsElement(w, fillsRel.guid, ownerHistoryId, openingEntityId, doorExpressId);
|
|
13610
|
-
writeDoorCommonPset(w, ownerHistoryId, doorExpressId, door.spec);
|
|
13611
|
-
}
|
|
13612
|
-
for (const [i, win] of windows.entries()) {
|
|
13613
|
-
const fillsRel = relationships.find((rel) => rel.kind === "FILLS_OPENING" && rel.fillerLocalId === win.localId);
|
|
13614
|
-
if (fillsRel === void 0 || fillsRel.kind !== "FILLS_OPENING") continue;
|
|
13615
|
-
const openingPlacementId = openingPlacementMap.get(fillsRel.openingLocalId);
|
|
13616
|
-
const openingEntityId = openingEntityMap.get(fillsRel.openingLocalId);
|
|
13617
|
-
if (openingPlacementId === void 0 || openingEntityId === void 0) continue;
|
|
13618
|
-
const windowExpressId = writeWindowEntity(w, win.guid, `Window ${i + 1}`, ownerHistoryId, openingPlacementId, geomSubContextId, toIfcLengthM(win.spec.width), toIfcLengthM(win.spec.height));
|
|
13619
|
-
idMap.set(win.localId, windowExpressId);
|
|
13620
|
-
writeRelFillsElement(w, fillsRel.guid, ownerHistoryId, openingEntityId, windowExpressId);
|
|
13621
|
-
writeWindowCommonPset(w, ownerHistoryId, windowExpressId, win.spec);
|
|
13622
|
-
}
|
|
13623
|
-
for (const rel of relationships) {
|
|
13624
|
-
if (rel.kind !== "AGGREGATES") continue;
|
|
13625
|
-
const parentExpressId = idMap.get(rel.relatingObject);
|
|
13626
|
-
const childExpressIds = rel.relatedObjects.map((id) => idMap.get(id)).filter((id) => id !== void 0);
|
|
13627
|
-
if (parentExpressId === void 0 || childExpressIds.length === 0) continue;
|
|
13628
|
-
writeRelAggregates(w, rel.guid, ownerHistoryId, parentExpressId, childExpressIds);
|
|
13629
|
-
}
|
|
13630
|
-
for (const rel of relationships) {
|
|
13631
|
-
if (rel.kind !== "CONTAINED_IN") continue;
|
|
13632
|
-
const structureExpressId = idMap.get(rel.relatingStructure);
|
|
13633
|
-
const elementExpressIds = rel.relatedElements.map((id) => idMap.get(id)).filter((id) => id !== void 0);
|
|
13634
|
-
if (structureExpressId === void 0 || elementExpressIds.length === 0) continue;
|
|
13635
|
-
writeRelContainedInSpatialStructure(w, rel.guid, ownerHistoryId, structureExpressId, elementExpressIds);
|
|
13636
|
-
}
|
|
13637
|
-
for (const rel of relationships) {
|
|
13638
|
-
if (rel.kind !== "SPACE_BOUNDARY") continue;
|
|
13639
|
-
const spaceExpressId = idMap.get(rel.spaceLocalId);
|
|
13640
|
-
const elementExpressId = idMap.get(rel.elementLocalId);
|
|
13641
|
-
if (spaceExpressId === void 0 || elementExpressId === void 0) continue;
|
|
13642
|
-
writeRelSpaceBoundary(w, rel.guid, ownerHistoryId, spaceExpressId, elementExpressId, rel.connectionType);
|
|
13643
|
-
}
|
|
13644
|
-
for (const rel of relationships) {
|
|
13645
|
-
if (rel.kind !== "NESTS") continue;
|
|
13646
|
-
const parentExpressId = idMap.get(rel.relatingObject);
|
|
13647
|
-
const childExpressIds = rel.relatedObjects.map((id) => idMap.get(id)).filter((id) => id !== void 0);
|
|
13648
|
-
if (parentExpressId === void 0 || childExpressIds.length === 0) continue;
|
|
13649
|
-
writeRelNests(w, rel.guid, ownerHistoryId, parentExpressId, childExpressIds);
|
|
13650
|
-
}
|
|
13651
|
-
for (const rel of relationships) {
|
|
13652
|
-
if (rel.kind !== "COVERS_ELEMENT") continue;
|
|
13653
|
-
const hostExpressId = idMap.get(rel.hostLocalId);
|
|
13654
|
-
const coveringExpressId = idMap.get(rel.coveringLocalId);
|
|
13655
|
-
if (hostExpressId === void 0 || coveringExpressId === void 0) continue;
|
|
13656
|
-
writeRelCoversBldgElements(w, rel.guid, ownerHistoryId, hostExpressId, [coveringExpressId]);
|
|
13508
|
+
//#region src/serialize/exactBodyPreflight.ts
|
|
13509
|
+
var testItemPreparer = null;
|
|
13510
|
+
/** Prepares every exact Body item without writing IFC lines. Source solids remain borrowed. */
|
|
13511
|
+
function preflightExactBody(input) {
|
|
13512
|
+
const prepareItem = input.prepareItem ?? testItemPreparer ?? prepareTessellation;
|
|
13513
|
+
const prepareAt = (solid, itemIndex) => {
|
|
13514
|
+
const item = prepareItem(solid);
|
|
13515
|
+
if (!item.ok) return err(ifcError("EXACT_BODY_TESSELLATION_FAILED", `Exact Product Body item ${itemIndex} for ${input.localId} could not be tessellated: ${item.reason}`, item.cause, {
|
|
13516
|
+
localId: input.localId,
|
|
13517
|
+
itemIndex
|
|
13518
|
+
}));
|
|
13519
|
+
return ok(item.value);
|
|
13520
|
+
};
|
|
13521
|
+
const [firstSolid, ...remainingSolids] = input.solids;
|
|
13522
|
+
const first = prepareAt(firstSolid, 0);
|
|
13523
|
+
if (!first.ok) return first;
|
|
13524
|
+
const remainingPrepared = [];
|
|
13525
|
+
for (const [remainingIndex, solid] of remainingSolids.entries()) {
|
|
13526
|
+
const item = prepareAt(solid, remainingIndex + 1);
|
|
13527
|
+
if (!item.ok) return item;
|
|
13528
|
+
remainingPrepared.push(item.value);
|
|
13657
13529
|
}
|
|
13658
|
-
|
|
13659
|
-
|
|
13660
|
-
|
|
13661
|
-
|
|
13662
|
-
|
|
13663
|
-
|
|
13530
|
+
return ok([first.value, ...remainingPrepared]);
|
|
13531
|
+
}
|
|
13532
|
+
//#endregion
|
|
13533
|
+
//#region src/serialize/exactWallQuantities.ts
|
|
13534
|
+
function deriveExactWallQuantities(input) {
|
|
13535
|
+
const measure = input.dependencies?.measure ?? measureVolume;
|
|
13536
|
+
let volumeMm3;
|
|
13537
|
+
if (input.solids.length === 1) try {
|
|
13538
|
+
const measured = measure(input.solids[0]);
|
|
13539
|
+
if (!measured.ok) return exactVolumeError(measured.error);
|
|
13540
|
+
volumeMm3 = measured.value;
|
|
13541
|
+
} catch (cause) {
|
|
13542
|
+
return exactVolumeError(cause);
|
|
13664
13543
|
}
|
|
13665
|
-
|
|
13666
|
-
|
|
13667
|
-
|
|
13668
|
-
|
|
13669
|
-
|
|
13670
|
-
|
|
13544
|
+
else {
|
|
13545
|
+
const fuse = input.dependencies?.fuse ?? fuseAll;
|
|
13546
|
+
let union = null;
|
|
13547
|
+
try {
|
|
13548
|
+
const fused = fuse([...input.solids]);
|
|
13549
|
+
if (!fused.ok) return exactVolumeError(fused.error);
|
|
13550
|
+
union = fused.value;
|
|
13551
|
+
const measured = measure(union);
|
|
13552
|
+
if (!measured.ok) return exactVolumeError(measured.error);
|
|
13553
|
+
volumeMm3 = measured.value;
|
|
13554
|
+
} catch (cause) {
|
|
13555
|
+
return exactVolumeError(cause);
|
|
13556
|
+
} finally {
|
|
13557
|
+
union?.[Symbol.dispose]();
|
|
13558
|
+
}
|
|
13671
13559
|
}
|
|
13672
|
-
|
|
13673
|
-
|
|
13674
|
-
|
|
13675
|
-
|
|
13676
|
-
|
|
13677
|
-
|
|
13678
|
-
}
|
|
13679
|
-
|
|
13680
|
-
|
|
13681
|
-
|
|
13682
|
-
|
|
13683
|
-
|
|
13684
|
-
|
|
13685
|
-
|
|
13686
|
-
|
|
13687
|
-
|
|
13688
|
-
|
|
13689
|
-
|
|
13690
|
-
|
|
13691
|
-
|
|
13692
|
-
|
|
13693
|
-
|
|
13694
|
-
ids: objectExpressIds,
|
|
13695
|
-
direction
|
|
13560
|
+
if (!Number.isFinite(volumeMm3) || volumeMm3 <= 0) return exactVolumeError(/* @__PURE__ */ new Error(`Measured exact wall volume was ${volumeMm3}`));
|
|
13561
|
+
return ok({
|
|
13562
|
+
lengthM: toIfcLengthM(input.spec.length),
|
|
13563
|
+
widthM: toIfcLengthM(input.spec.thickness),
|
|
13564
|
+
heightM: toIfcLengthM(input.spec.height),
|
|
13565
|
+
netVolumeM3: volumeMm3 / 1e9
|
|
13566
|
+
});
|
|
13567
|
+
}
|
|
13568
|
+
function exactVolumeError(cause) {
|
|
13569
|
+
return err(ifcError("IFC_EXACT_WALL_QUANTITY_DERIVATION_FAILED", "Failed to derive a positive finite NetVolume for an exact wall Product Body", cause));
|
|
13570
|
+
}
|
|
13571
|
+
//#endregion
|
|
13572
|
+
//#region src/serialize/toIfc.ts
|
|
13573
|
+
function preflightProductBodies(elements) {
|
|
13574
|
+
const preflighted = [];
|
|
13575
|
+
for (const element of elements) {
|
|
13576
|
+
const body = element.geometry;
|
|
13577
|
+
if (body.kind === "PARAMETRIC") {
|
|
13578
|
+
preflighted.push({
|
|
13579
|
+
kind: "PARAMETRIC",
|
|
13580
|
+
element,
|
|
13581
|
+
solid: body.solid
|
|
13696
13582
|
});
|
|
13697
13583
|
continue;
|
|
13698
13584
|
}
|
|
13699
|
-
const
|
|
13700
|
-
|
|
13701
|
-
|
|
13702
|
-
ids: [...existing.ids, ...objectExpressIds]
|
|
13585
|
+
const prepared = preflightExactBody({
|
|
13586
|
+
localId: element.localId,
|
|
13587
|
+
solids: body.solids
|
|
13703
13588
|
});
|
|
13704
|
-
|
|
13705
|
-
|
|
13706
|
-
|
|
13589
|
+
if (!prepared.ok) return err(prepared.error);
|
|
13590
|
+
preflighted.push({
|
|
13591
|
+
kind: "EXACT",
|
|
13592
|
+
element,
|
|
13593
|
+
solids: body.solids,
|
|
13594
|
+
items: prepared.value
|
|
13707
13595
|
});
|
|
13708
13596
|
}
|
|
13709
|
-
|
|
13710
|
-
|
|
13711
|
-
|
|
13712
|
-
|
|
13713
|
-
|
|
13714
|
-
|
|
13715
|
-
|
|
13716
|
-
|
|
13717
|
-
|
|
13718
|
-
|
|
13719
|
-
|
|
13720
|
-
|
|
13721
|
-
const objectExpressIds = rel.relatedObjects.map((id) => idMap.get(id)).filter((id) => id !== void 0);
|
|
13722
|
-
if (objectExpressIds.length === 0) continue;
|
|
13723
|
-
const key = `${rel.ref.system}:${rel.ref.code}`;
|
|
13724
|
-
const entry = classByKey.get(key);
|
|
13725
|
-
if (entry === void 0) classByKey.set(key, {
|
|
13726
|
-
ref: rel.ref,
|
|
13727
|
-
ids: [...objectExpressIds]
|
|
13597
|
+
return ok(preflighted);
|
|
13598
|
+
}
|
|
13599
|
+
async function toIfc(model, meta) {
|
|
13600
|
+
try {
|
|
13601
|
+
var _usingCtx$2 = _usingCtx();
|
|
13602
|
+
const project = model.getProject();
|
|
13603
|
+
if (!project) return err(ifcError("NO_PROJECT", "BimModel has no project — call model.init() first"));
|
|
13604
|
+
if ((model.getBridges().length > 0 || model.getBridgeParts().length > 0 || model.getEarthworksFills().length > 0) && (meta.ifcSchema ?? "IFC4") !== "IFC4X3") return err(ifcError("IFC4X3_REQUIRED", "Bridge, Bridge Part, and Earthworks Fill entities require IFC4X3 serialization"));
|
|
13605
|
+
const authorName = [meta.author?.givenName, meta.author?.familyName].filter((p) => Boolean(p)).join(" ");
|
|
13606
|
+
const writerResult = await IfcWriter.create(meta.mvdViewDefinition, meta.ifcSchema, {
|
|
13607
|
+
author: authorName,
|
|
13608
|
+
organization: meta.organizationName
|
|
13728
13609
|
});
|
|
13729
|
-
|
|
13610
|
+
if (!writerResult.ok) return writerResult;
|
|
13611
|
+
const w = _usingCtx$2.u(writerResult.value);
|
|
13612
|
+
w.setModelScope(project.guid);
|
|
13613
|
+
const elements = model.getAllElements();
|
|
13614
|
+
const relationships = model.getAllRelationships();
|
|
13615
|
+
const walls = model.getWalls();
|
|
13616
|
+
const slabs = model.getSlabs();
|
|
13617
|
+
const beams = model.getBeams();
|
|
13618
|
+
const bridges = model.getBridges();
|
|
13619
|
+
const bridgeParts = model.getBridgeParts();
|
|
13620
|
+
const earthworksFills = model.getEarthworksFills();
|
|
13621
|
+
const columns = model.getColumns();
|
|
13622
|
+
const doors = model.getDoors();
|
|
13623
|
+
const windows = model.getWindows();
|
|
13624
|
+
const proxies = model.getProxies();
|
|
13625
|
+
const spaces = model.getSpaces();
|
|
13626
|
+
const roofs = model.getRoofs();
|
|
13627
|
+
const curtainWalls = model.getCurtainWalls();
|
|
13628
|
+
const footings = model.getFootings();
|
|
13629
|
+
const piles = model.getPiles();
|
|
13630
|
+
const stairs = model.getStairs();
|
|
13631
|
+
const ramps = model.getRamps();
|
|
13632
|
+
const railings = model.getRailings();
|
|
13633
|
+
const coverings = model.getCoverings();
|
|
13634
|
+
const assemblies = model.getElementAssemblies();
|
|
13635
|
+
const zones = model.getZones();
|
|
13636
|
+
const systems = model.getSystems();
|
|
13637
|
+
const preflightedWallsResult = preflightProductBodies(walls);
|
|
13638
|
+
if (!preflightedWallsResult.ok) return err(preflightedWallsResult.error);
|
|
13639
|
+
const preflightedRailingsResult = preflightProductBodies(railings);
|
|
13640
|
+
if (!preflightedRailingsResult.ok) return err(preflightedRailingsResult.error);
|
|
13641
|
+
const preflightedWalls = preflightedWallsResult.value;
|
|
13642
|
+
const preflightedRailings = preflightedRailingsResult.value;
|
|
13643
|
+
const { ownerHistoryId, geomContextId, geomSubContextId, unitAssignmentId, lengthUnitId } = writeHeader(w, meta);
|
|
13644
|
+
if (project.spec.crs !== void 0) writeMapConversion(w, project.spec.crs, geomContextId, lengthUnitId);
|
|
13645
|
+
const densityByElement = buildDensityMap(relationships);
|
|
13646
|
+
const idMap = /* @__PURE__ */ new Map();
|
|
13647
|
+
const placementMap = /* @__PURE__ */ new Map();
|
|
13648
|
+
const projectExpressId = writeProject$1(w, project.guid, project.spec.name, ownerHistoryId, unitAssignmentId, geomContextId);
|
|
13649
|
+
idMap.set(project.localId, projectExpressId);
|
|
13650
|
+
for (const el of elements) {
|
|
13651
|
+
if (el.category !== "SITE") continue;
|
|
13652
|
+
const parentId = findParentOf(el.localId, relationships);
|
|
13653
|
+
const parentPlacementId = parentId !== null ? placementMap.get(parentId) ?? null : null;
|
|
13654
|
+
const { entityId, placementId } = writeSite(w, el.guid, el.spec, ownerHistoryId, parentPlacementId);
|
|
13655
|
+
idMap.set(el.localId, entityId);
|
|
13656
|
+
placementMap.set(el.localId, placementId);
|
|
13657
|
+
}
|
|
13658
|
+
for (const bridge of bridges) {
|
|
13659
|
+
const parentId = findParentOf(bridge.localId, relationships);
|
|
13660
|
+
const parentPlacementId = parentId !== null ? placementMap.get(parentId) ?? null : null;
|
|
13661
|
+
const { entityId, placementId } = writeBridge(w, bridge.guid, bridge.spec, ownerHistoryId, parentPlacementId);
|
|
13662
|
+
idMap.set(bridge.localId, entityId);
|
|
13663
|
+
placementMap.set(bridge.localId, placementId);
|
|
13664
|
+
}
|
|
13665
|
+
const pendingParts = [...bridgeParts];
|
|
13666
|
+
while (pendingParts.length > 0) {
|
|
13667
|
+
const readyIndex = pendingParts.findIndex((candidate) => {
|
|
13668
|
+
const candidateParentId = findParentOf(candidate.localId, relationships);
|
|
13669
|
+
return candidateParentId === null || placementMap.has(candidateParentId);
|
|
13670
|
+
});
|
|
13671
|
+
const [part] = pendingParts.splice(readyIndex === -1 ? 0 : readyIndex, 1);
|
|
13672
|
+
if (part === void 0) break;
|
|
13673
|
+
const parentId = findParentOf(part.localId, relationships);
|
|
13674
|
+
const parentPlacementId = parentId !== null ? placementMap.get(parentId) ?? null : null;
|
|
13675
|
+
const { entityId, placementId } = writeBridgePart(w, part.guid, part.spec, ownerHistoryId, parentPlacementId);
|
|
13676
|
+
idMap.set(part.localId, entityId);
|
|
13677
|
+
placementMap.set(part.localId, placementId);
|
|
13678
|
+
}
|
|
13679
|
+
for (const el of elements) {
|
|
13680
|
+
if (el.category !== "BUILDING") continue;
|
|
13681
|
+
const parentSiteId = findParentOf(el.localId, relationships);
|
|
13682
|
+
const parentPlacementId = parentSiteId !== null ? placementMap.get(parentSiteId) ?? null : null;
|
|
13683
|
+
const { entityId, placementId } = writeBuilding(w, el.guid, el.spec.name, ownerHistoryId, parentPlacementId);
|
|
13684
|
+
idMap.set(el.localId, entityId);
|
|
13685
|
+
placementMap.set(el.localId, placementId);
|
|
13686
|
+
}
|
|
13687
|
+
for (const el of elements) {
|
|
13688
|
+
if (el.category !== "STOREY") continue;
|
|
13689
|
+
const parentBuildingId = findParentOf(el.localId, relationships);
|
|
13690
|
+
const parentPlacementId = parentBuildingId !== null ? placementMap.get(parentBuildingId) ?? null : null;
|
|
13691
|
+
const { entityId, placementId } = writeStorey(w, el.guid, el.spec.name, el.spec.elevation, ownerHistoryId, parentPlacementId);
|
|
13692
|
+
idMap.set(el.localId, entityId);
|
|
13693
|
+
placementMap.set(el.localId, placementId);
|
|
13694
|
+
}
|
|
13695
|
+
const openingsByWall = /* @__PURE__ */ new Map();
|
|
13696
|
+
for (const rel of relationships) {
|
|
13697
|
+
if (rel.kind !== "VOIDS_WALL") continue;
|
|
13698
|
+
const opening = elements.find((el) => el.localId === rel.openingLocalId);
|
|
13699
|
+
if (opening === void 0 || opening.category !== "OPENING") continue;
|
|
13700
|
+
if (!isWallOpening(opening.spec)) continue;
|
|
13701
|
+
const list = openingsByWall.get(rel.wallLocalId) ?? [];
|
|
13702
|
+
list.push(opening.spec);
|
|
13703
|
+
openingsByWall.set(rel.wallLocalId, list);
|
|
13704
|
+
}
|
|
13705
|
+
const openingsBySlab = /* @__PURE__ */ new Map();
|
|
13706
|
+
for (const rel of relationships) {
|
|
13707
|
+
if (rel.kind !== "VOIDS_SLAB") continue;
|
|
13708
|
+
const opening = elements.find((el) => el.localId === rel.openingLocalId);
|
|
13709
|
+
if (opening === void 0 || opening.category !== "OPENING") continue;
|
|
13710
|
+
if (!isSlabOpening(opening.spec)) continue;
|
|
13711
|
+
const list = openingsBySlab.get(rel.slabLocalId) ?? [];
|
|
13712
|
+
list.push(opening.spec);
|
|
13713
|
+
openingsBySlab.set(rel.slabLocalId, list);
|
|
13714
|
+
}
|
|
13715
|
+
for (const [i, preflighted] of preflightedWalls.entries()) {
|
|
13716
|
+
const wall = preflighted.element;
|
|
13717
|
+
const containingId = findContainerOf(wall.localId, relationships);
|
|
13718
|
+
const storeyPlacementId = containingId !== null ? placementMap.get(containingId) ?? null : null;
|
|
13719
|
+
const exactQuantities = preflighted.kind === "EXACT" ? deriveExactWallQuantities({
|
|
13720
|
+
spec: wall.spec,
|
|
13721
|
+
solids: preflighted.solids
|
|
13722
|
+
}) : null;
|
|
13723
|
+
const { localPlacementId, productDefinitionShapeId } = preflighted.kind === "EXACT" ? writeExactBodyGeometry(w, wall.spec, preflighted.items, geomSubContextId, storeyPlacementId) : writeWallGeometry(w, wall.spec, geomSubContextId, storeyPlacementId);
|
|
13724
|
+
const wallExpressId = writeWallEntity(w, wall.guid, `Wall ${i + 1}`, ownerHistoryId, localPlacementId, productDefinitionShapeId);
|
|
13725
|
+
idMap.set(wall.localId, wallExpressId);
|
|
13726
|
+
placementMap.set(wall.localId, localPlacementId);
|
|
13727
|
+
writeWallCommonPset(w, ownerHistoryId, wallExpressId, wall.spec);
|
|
13728
|
+
writeManufacturerPset(w, ownerHistoryId, wallExpressId, wall.spec);
|
|
13729
|
+
if (wall.spec.customProperties !== void 0) writeCustomPsets(w, ownerHistoryId, wallExpressId, wall.spec.customProperties);
|
|
13730
|
+
if (preflighted.kind === "EXACT") {
|
|
13731
|
+
if (exactQuantities !== null && exactQuantities.ok) writeExactWallBaseQuantities(w, ownerHistoryId, wallExpressId, exactQuantities.value);
|
|
13732
|
+
} else writeWallBaseQuantities(w, ownerHistoryId, wallExpressId, wall.spec, openingsByWall.get(wall.localId) ?? [], densityByElement.get(wall.localId));
|
|
13733
|
+
}
|
|
13734
|
+
for (const [i, slab] of slabs.entries()) {
|
|
13735
|
+
const containingId = findContainerOf(slab.localId, relationships);
|
|
13736
|
+
const storeyPlacementId = containingId !== null ? placementMap.get(containingId) ?? null : null;
|
|
13737
|
+
const { localPlacementId, productDefinitionShapeId } = writeSlabGeometry(w, slab.spec, geomSubContextId, storeyPlacementId);
|
|
13738
|
+
const slabExpressId = writeSlabEntity(w, slab.guid, `Slab ${i + 1}`, slab.spec.predefinedType, ownerHistoryId, localPlacementId, productDefinitionShapeId);
|
|
13739
|
+
idMap.set(slab.localId, slabExpressId);
|
|
13740
|
+
placementMap.set(slab.localId, localPlacementId);
|
|
13741
|
+
writeSlabCommonPset(w, ownerHistoryId, slabExpressId, slab.spec);
|
|
13742
|
+
writeManufacturerPset(w, ownerHistoryId, slabExpressId, slab.spec);
|
|
13743
|
+
if (slab.spec.customProperties !== void 0) writeCustomPsets(w, ownerHistoryId, slabExpressId, slab.spec.customProperties);
|
|
13744
|
+
writeSlabBaseQuantities(w, ownerHistoryId, slabExpressId, slab.spec, openingsBySlab.get(slab.localId) ?? [], densityByElement.get(slab.localId));
|
|
13745
|
+
}
|
|
13746
|
+
for (const [i, beam] of beams.entries()) {
|
|
13747
|
+
const containingId = findContainerOf(beam.localId, relationships);
|
|
13748
|
+
const storeyPlacementId = containingId !== null ? placementMap.get(containingId) ?? null : null;
|
|
13749
|
+
const { localPlacementId, productDefinitionShapeId } = writeBeamGeometry(w, beam.spec, geomSubContextId, storeyPlacementId);
|
|
13750
|
+
const beamExpressId = writeBeamEntity(w, beam.guid, `Beam ${i + 1}`, beam.spec.predefinedType ?? "NOTDEFINED", ownerHistoryId, localPlacementId, productDefinitionShapeId);
|
|
13751
|
+
idMap.set(beam.localId, beamExpressId);
|
|
13752
|
+
placementMap.set(beam.localId, localPlacementId);
|
|
13753
|
+
writeBeamCommonPset(w, ownerHistoryId, beamExpressId, beam.spec);
|
|
13754
|
+
writeManufacturerPset(w, ownerHistoryId, beamExpressId, beam.spec);
|
|
13755
|
+
if (beam.spec.customProperties !== void 0) writeCustomPsets(w, ownerHistoryId, beamExpressId, beam.spec.customProperties);
|
|
13756
|
+
writeBeamBaseQuantities(w, ownerHistoryId, beamExpressId, beam.spec);
|
|
13757
|
+
}
|
|
13758
|
+
for (const [i, column] of columns.entries()) {
|
|
13759
|
+
const containingId = findContainerOf(column.localId, relationships);
|
|
13760
|
+
const storeyPlacementId = containingId !== null ? placementMap.get(containingId) ?? null : null;
|
|
13761
|
+
const { localPlacementId, productDefinitionShapeId } = writeColumnGeometry(w, column.spec, geomSubContextId, storeyPlacementId);
|
|
13762
|
+
const columnExpressId = writeColumnEntity(w, column.guid, `Column ${i + 1}`, column.spec.predefinedType ?? "NOTDEFINED", ownerHistoryId, localPlacementId, productDefinitionShapeId);
|
|
13763
|
+
idMap.set(column.localId, columnExpressId);
|
|
13764
|
+
placementMap.set(column.localId, localPlacementId);
|
|
13765
|
+
writeColumnCommonPset(w, ownerHistoryId, columnExpressId, column.spec);
|
|
13766
|
+
writeManufacturerPset(w, ownerHistoryId, columnExpressId, column.spec);
|
|
13767
|
+
if (column.spec.customProperties !== void 0) writeCustomPsets(w, ownerHistoryId, columnExpressId, column.spec.customProperties);
|
|
13768
|
+
writeColumnBaseQuantities(w, ownerHistoryId, columnExpressId, column.spec);
|
|
13769
|
+
}
|
|
13770
|
+
for (const [i, proxy] of proxies.entries()) {
|
|
13771
|
+
const containingId = findContainerOf(proxy.localId, relationships);
|
|
13772
|
+
const storeyPlacementId = containingId !== null ? placementMap.get(containingId) ?? null : null;
|
|
13773
|
+
const { localPlacementId, productDefinitionShapeId } = writeProxyGeometry(w, proxy.spec, geomSubContextId, storeyPlacementId);
|
|
13774
|
+
const proxyExpressId = writeProxyEntity(w, proxy.guid, proxy.spec.name || `Proxy ${i + 1}`, proxy.spec.predefinedType ?? "NOTDEFINED", ownerHistoryId, localPlacementId, productDefinitionShapeId);
|
|
13775
|
+
idMap.set(proxy.localId, proxyExpressId);
|
|
13776
|
+
placementMap.set(proxy.localId, localPlacementId);
|
|
13777
|
+
if (proxy.spec.customProperties !== void 0) writeCustomPsets(w, ownerHistoryId, proxyExpressId, proxy.spec.customProperties);
|
|
13778
|
+
}
|
|
13779
|
+
for (const fill of earthworksFills) {
|
|
13780
|
+
const containingId = findContainerOf(fill.localId, relationships);
|
|
13781
|
+
const parentPlacementId = containingId !== null ? placementMap.get(containingId) ?? null : null;
|
|
13782
|
+
const { localPlacementId, productDefinitionShapeId } = writeTessellatedProductGeometry(w, fill.geometry, geomSubContextId, parentPlacementId);
|
|
13783
|
+
const expressId = writeEarthworksFillEntity(w, fill.guid, fill.spec, ownerHistoryId, localPlacementId, productDefinitionShapeId);
|
|
13784
|
+
idMap.set(fill.localId, expressId);
|
|
13785
|
+
placementMap.set(fill.localId, localPlacementId);
|
|
13786
|
+
if (fill.spec.customProperties !== void 0) writeCustomPsets(w, ownerHistoryId, expressId, fill.spec.customProperties);
|
|
13787
|
+
}
|
|
13788
|
+
for (const [i, space] of spaces.entries()) {
|
|
13789
|
+
const containingId = findContainerOf(space.localId, relationships);
|
|
13790
|
+
const storeyPlacementId = containingId !== null ? placementMap.get(containingId) ?? null : null;
|
|
13791
|
+
const { localPlacementId, productDefinitionShapeId } = writeSpaceGeometry(w, space.spec, geomSubContextId, storeyPlacementId);
|
|
13792
|
+
const spaceExpressId = writeSpaceEntity(w, space.guid, space.spec.name || `Space ${i + 1}`, space.spec.longName ?? null, space.spec.predefinedType ?? "NOTDEFINED", ownerHistoryId, localPlacementId, productDefinitionShapeId);
|
|
13793
|
+
idMap.set(space.localId, spaceExpressId);
|
|
13794
|
+
placementMap.set(space.localId, localPlacementId);
|
|
13795
|
+
writeSpaceCommonPset(w, ownerHistoryId, spaceExpressId, space.spec);
|
|
13796
|
+
if (space.spec.customProperties !== void 0) writeCustomPsets(w, ownerHistoryId, spaceExpressId, space.spec.customProperties);
|
|
13797
|
+
writeSpaceBaseQuantities(w, ownerHistoryId, spaceExpressId, space.spec);
|
|
13798
|
+
}
|
|
13799
|
+
for (const [i, roof] of roofs.entries()) {
|
|
13800
|
+
const containingId = findContainerOf(roof.localId, relationships);
|
|
13801
|
+
const storeyPlacementId = containingId !== null ? placementMap.get(containingId) ?? null : null;
|
|
13802
|
+
const { localPlacementId, productDefinitionShapeId, usedFallback } = writeRoofGeometry(w, roof.spec, roof.geometry, geomSubContextId, storeyPlacementId);
|
|
13803
|
+
if (usedFallback) console.warn(`Roof ${i + 1} tessellation failed; IFC body is a degenerate fallback.`);
|
|
13804
|
+
const roofExpressId = writeRoofEntity(w, roof.guid, `Roof ${i + 1}`, roof.spec.predefinedType, ownerHistoryId, localPlacementId, productDefinitionShapeId);
|
|
13805
|
+
idMap.set(roof.localId, roofExpressId);
|
|
13806
|
+
placementMap.set(roof.localId, localPlacementId);
|
|
13807
|
+
writeRoofCommonPset(w, ownerHistoryId, roofExpressId, roof.spec);
|
|
13808
|
+
writeManufacturerPset(w, ownerHistoryId, roofExpressId, roof.spec);
|
|
13809
|
+
if (roof.spec.customProperties !== void 0) writeCustomPsets(w, ownerHistoryId, roofExpressId, roof.spec.customProperties);
|
|
13810
|
+
writeRoofBaseQuantities(w, ownerHistoryId, roofExpressId, roof.spec);
|
|
13811
|
+
}
|
|
13812
|
+
for (const [i, curtainWall] of curtainWalls.entries()) {
|
|
13813
|
+
const containingId = findContainerOf(curtainWall.localId, relationships);
|
|
13814
|
+
const storeyPlacementId = containingId !== null ? placementMap.get(containingId) ?? null : null;
|
|
13815
|
+
const { curtainWallId } = writeCurtainWall(w, curtainWall.spec, curtainWall.geometry, `elem:CURTAIN_WALL:${curtainWall.localId}`, `Curtain Wall ${i + 1}`, ownerHistoryId, geomSubContextId, storeyPlacementId);
|
|
13816
|
+
idMap.set(curtainWall.localId, curtainWallId);
|
|
13817
|
+
writeCurtainWallCommonPset(w, ownerHistoryId, curtainWallId, curtainWall.spec);
|
|
13818
|
+
if (curtainWall.spec.customProperties !== void 0) writeCustomPsets(w, ownerHistoryId, curtainWallId, curtainWall.spec.customProperties);
|
|
13819
|
+
}
|
|
13820
|
+
for (const [i, footing] of footings.entries()) {
|
|
13821
|
+
const containingId = findContainerOf(footing.localId, relationships);
|
|
13822
|
+
const storeyPlacementId = containingId !== null ? placementMap.get(containingId) ?? null : null;
|
|
13823
|
+
const { localPlacementId, productDefinitionShapeId } = writeFootingGeometry(w, footing.spec, geomSubContextId, storeyPlacementId);
|
|
13824
|
+
const footingExpressId = writeFootingEntity(w, footing.guid, `Footing ${i + 1}`, footing.spec.predefinedType ?? "NOTDEFINED", ownerHistoryId, localPlacementId, productDefinitionShapeId);
|
|
13825
|
+
idMap.set(footing.localId, footingExpressId);
|
|
13826
|
+
placementMap.set(footing.localId, localPlacementId);
|
|
13827
|
+
writeFootingCommonPset(w, ownerHistoryId, footingExpressId, footing.spec);
|
|
13828
|
+
if (footing.spec.customProperties !== void 0) writeCustomPsets(w, ownerHistoryId, footingExpressId, footing.spec.customProperties);
|
|
13829
|
+
writeFootingBaseQuantities(w, ownerHistoryId, footingExpressId, footing.spec);
|
|
13830
|
+
}
|
|
13831
|
+
for (const [i, pile] of piles.entries()) {
|
|
13832
|
+
const containingId = findContainerOf(pile.localId, relationships);
|
|
13833
|
+
const storeyPlacementId = containingId !== null ? placementMap.get(containingId) ?? null : null;
|
|
13834
|
+
const { localPlacementId, productDefinitionShapeId } = writePileGeometry(w, pile.spec, geomSubContextId, storeyPlacementId);
|
|
13835
|
+
const pileExpressId = writePileEntity(w, pile.guid, `Pile ${i + 1}`, pile.spec.predefinedType ?? "NOTDEFINED", pile.spec.constructionType ?? null, ownerHistoryId, localPlacementId, productDefinitionShapeId);
|
|
13836
|
+
idMap.set(pile.localId, pileExpressId);
|
|
13837
|
+
placementMap.set(pile.localId, localPlacementId);
|
|
13838
|
+
writePileCommonPset(w, ownerHistoryId, pileExpressId, pile.spec);
|
|
13839
|
+
if (pile.spec.customProperties !== void 0) writeCustomPsets(w, ownerHistoryId, pileExpressId, pile.spec.customProperties);
|
|
13840
|
+
writePileBaseQuantities(w, ownerHistoryId, pileExpressId, pile.spec);
|
|
13841
|
+
}
|
|
13842
|
+
for (const [i, assembly] of assemblies.entries()) {
|
|
13843
|
+
const containingId = findContainerOf(assembly.localId, relationships);
|
|
13844
|
+
const storeyPlacementId = containingId !== null ? placementMap.get(containingId) ?? null : null;
|
|
13845
|
+
const assemblyExpressId = writeElementAssemblyEntity(w, assembly.guid, assembly.spec.name ?? `Assembly ${i + 1}`, assembly.spec.predefinedType ?? "NOTDEFINED", ownerHistoryId, storeyPlacementId, null, assembly.spec.assemblyPlace ?? "NOTDEFINED");
|
|
13846
|
+
idMap.set(assembly.localId, assemblyExpressId);
|
|
13847
|
+
}
|
|
13848
|
+
for (const zone of zones) {
|
|
13849
|
+
const zoneExpressId = writeZoneEntity(w, zone.guid, zone.spec.name, zone.spec.longName ?? null, zone.spec.objectType ?? null, ownerHistoryId);
|
|
13850
|
+
idMap.set(zone.localId, zoneExpressId);
|
|
13851
|
+
}
|
|
13852
|
+
for (const system of systems) {
|
|
13853
|
+
const systemExpressId = writeSystemEntity(w, system.guid, system.spec.name, system.spec.longName ?? null, system.spec.objectType ?? null, ownerHistoryId);
|
|
13854
|
+
idMap.set(system.localId, systemExpressId);
|
|
13855
|
+
}
|
|
13856
|
+
for (const stair of stairs) {
|
|
13857
|
+
const containingId = findContainerOf(stair.localId, relationships);
|
|
13858
|
+
const storeyPlacementId = containingId !== null ? placementMap.get(containingId) ?? null : null;
|
|
13859
|
+
const result = writeStairAssembly(w, stair.spec, `${stair.localId}`, stair.guid, ownerHistoryId, geomSubContextId, storeyPlacementId);
|
|
13860
|
+
if (!result.ok) return err(result.error);
|
|
13861
|
+
idMap.set(stair.localId, result.value.assemblyExpressId);
|
|
13862
|
+
writeStairCommonPset(w, ownerHistoryId, result.value.assemblyExpressId, stair.spec);
|
|
13863
|
+
}
|
|
13864
|
+
for (const ramp of ramps) {
|
|
13865
|
+
const containingId = findContainerOf(ramp.localId, relationships);
|
|
13866
|
+
const storeyPlacementId = containingId !== null ? placementMap.get(containingId) ?? null : null;
|
|
13867
|
+
const result = writeRampAssembly(w, ramp.spec, `${ramp.localId}`, ramp.guid, ownerHistoryId, geomSubContextId, storeyPlacementId);
|
|
13868
|
+
if (!result.ok) return err(result.error);
|
|
13869
|
+
idMap.set(ramp.localId, result.value.assemblyExpressId);
|
|
13870
|
+
writeRampCommonPset(w, ownerHistoryId, result.value.assemblyExpressId, ramp.spec);
|
|
13871
|
+
}
|
|
13872
|
+
for (const [i, preflighted] of preflightedRailings.entries()) {
|
|
13873
|
+
const railing = preflighted.element;
|
|
13874
|
+
const containingId = findContainerOf(railing.localId, relationships);
|
|
13875
|
+
const storeyPlacementId = containingId !== null ? placementMap.get(containingId) ?? null : null;
|
|
13876
|
+
let representation;
|
|
13877
|
+
let exactBodyItemIds = [];
|
|
13878
|
+
if (preflighted.kind === "EXACT") {
|
|
13879
|
+
const exact = writeExactBodyGeometry(w, railing.spec, preflighted.items, geomSubContextId, storeyPlacementId);
|
|
13880
|
+
exactBodyItemIds = exact.bodyItemIds;
|
|
13881
|
+
representation = {
|
|
13882
|
+
...exact,
|
|
13883
|
+
bodyItemId: null,
|
|
13884
|
+
usedFallback: false
|
|
13885
|
+
};
|
|
13886
|
+
} else representation = writeRailingGeometry(w, railing.spec, preflighted.solid, geomSubContextId, storeyPlacementId);
|
|
13887
|
+
const { localPlacementId, productDefinitionShapeId, bodyItemId, usedFallback } = representation;
|
|
13888
|
+
if (usedFallback) console.warn(`Railing ${i + 1} tessellation failed; IFC body is a degenerate fallback.`);
|
|
13889
|
+
const railingExpressId = writeRailingEntity(w, railing.guid, `Railing ${i + 1}`, railing.spec.predefinedType ?? "NOTDEFINED", ownerHistoryId, localPlacementId, productDefinitionShapeId);
|
|
13890
|
+
idMap.set(railing.localId, railingExpressId);
|
|
13891
|
+
placementMap.set(railing.localId, localPlacementId);
|
|
13892
|
+
writeRailingCommonPset(w, ownerHistoryId, railingExpressId, railing.spec);
|
|
13893
|
+
writeManufacturerPset(w, ownerHistoryId, railingExpressId, railing.spec);
|
|
13894
|
+
if (railing.spec.customProperties !== void 0) writeCustomPsets(w, ownerHistoryId, railingExpressId, railing.spec.customProperties);
|
|
13895
|
+
if (preflighted.kind === "EXACT") for (const itemId of exactBodyItemIds) applySurfaceStyle(w, model, railing.localId, itemId);
|
|
13896
|
+
else if (bodyItemId !== null) applySurfaceStyle(w, model, railing.localId, bodyItemId);
|
|
13897
|
+
}
|
|
13898
|
+
for (const [i, covering] of coverings.entries()) {
|
|
13899
|
+
const containingId = findContainerOf(covering.localId, relationships);
|
|
13900
|
+
const storeyPlacementId = containingId !== null ? placementMap.get(containingId) ?? null : null;
|
|
13901
|
+
const { localPlacementId, productDefinitionShapeId, bodyItemId } = writeCoveringGeometry(w, covering.spec, geomSubContextId, storeyPlacementId);
|
|
13902
|
+
const coveringExpressId = writeCoveringEntity(w, covering.guid, `Covering ${i + 1}`, covering.spec.predefinedType ?? "NOTDEFINED", ownerHistoryId, localPlacementId, productDefinitionShapeId);
|
|
13903
|
+
idMap.set(covering.localId, coveringExpressId);
|
|
13904
|
+
placementMap.set(covering.localId, localPlacementId);
|
|
13905
|
+
writeCoveringCommonPset(w, ownerHistoryId, coveringExpressId, covering.spec);
|
|
13906
|
+
writeManufacturerPset(w, ownerHistoryId, coveringExpressId, covering.spec);
|
|
13907
|
+
if (covering.spec.customProperties !== void 0) writeCustomPsets(w, ownerHistoryId, coveringExpressId, covering.spec.customProperties);
|
|
13908
|
+
applySurfaceStyle(w, model, covering.localId, bodyItemId);
|
|
13909
|
+
}
|
|
13910
|
+
const openingPlacementMap = /* @__PURE__ */ new Map();
|
|
13911
|
+
const openingEntityMap = /* @__PURE__ */ new Map();
|
|
13912
|
+
for (const rel of relationships) {
|
|
13913
|
+
if (rel.kind !== "VOIDS_WALL") continue;
|
|
13914
|
+
const wallElement = elements.find((el) => el.category === "WALL" && el.localId === rel.wallLocalId);
|
|
13915
|
+
if (wallElement === void 0) continue;
|
|
13916
|
+
const wallExpressId = idMap.get(rel.wallLocalId);
|
|
13917
|
+
const wallPlacementId = placementMap.get(rel.wallLocalId);
|
|
13918
|
+
if (wallExpressId === void 0 || wallPlacementId === void 0) continue;
|
|
13919
|
+
const openingElement = elements.find((el) => el.localId === rel.openingLocalId);
|
|
13920
|
+
if (openingElement === void 0 || openingElement.category !== "OPENING") continue;
|
|
13921
|
+
if (!isWallOpening(openingElement.spec)) continue;
|
|
13922
|
+
const { openingEntityId, openingPlacementId } = writeOpeningGeometry(w, openingElement.guid, openingElement.spec, wallElement.spec, wallPlacementId, geomSubContextId, ownerHistoryId);
|
|
13923
|
+
idMap.set(rel.openingLocalId, openingEntityId);
|
|
13924
|
+
openingPlacementMap.set(rel.openingLocalId, openingPlacementId);
|
|
13925
|
+
openingEntityMap.set(rel.openingLocalId, openingEntityId);
|
|
13926
|
+
writeRelVoidsElement(w, rel.guid, ownerHistoryId, wallExpressId, openingEntityId);
|
|
13927
|
+
}
|
|
13928
|
+
for (const rel of relationships) {
|
|
13929
|
+
if (rel.kind !== "VOIDS_SLAB") continue;
|
|
13930
|
+
const slabElement = elements.find((el) => el.category === "SLAB" && el.localId === rel.slabLocalId);
|
|
13931
|
+
if (slabElement === void 0) continue;
|
|
13932
|
+
const slabExpressId = idMap.get(rel.slabLocalId);
|
|
13933
|
+
const slabPlacementId = placementMap.get(rel.slabLocalId);
|
|
13934
|
+
if (slabExpressId === void 0 || slabPlacementId === void 0) continue;
|
|
13935
|
+
const openingElement = elements.find((el) => el.localId === rel.openingLocalId);
|
|
13936
|
+
if (openingElement === void 0 || openingElement.category !== "OPENING") continue;
|
|
13937
|
+
if (!isSlabOpening(openingElement.spec)) continue;
|
|
13938
|
+
const { openingEntityId } = writeSlabOpeningGeometry(w, openingElement.guid, openingElement.spec, slabElement.spec, slabPlacementId, geomSubContextId, ownerHistoryId);
|
|
13939
|
+
idMap.set(rel.openingLocalId, openingEntityId);
|
|
13940
|
+
writeRelVoidsElement(w, rel.guid, ownerHistoryId, slabExpressId, openingEntityId);
|
|
13941
|
+
}
|
|
13942
|
+
for (const [i, door] of doors.entries()) {
|
|
13943
|
+
const fillsRel = relationships.find((rel) => rel.kind === "FILLS_OPENING" && rel.fillerLocalId === door.localId);
|
|
13944
|
+
if (fillsRel === void 0 || fillsRel.kind !== "FILLS_OPENING") continue;
|
|
13945
|
+
const openingPlacementId = openingPlacementMap.get(fillsRel.openingLocalId);
|
|
13946
|
+
const openingEntityId = openingEntityMap.get(fillsRel.openingLocalId);
|
|
13947
|
+
if (openingPlacementId === void 0 || openingEntityId === void 0) continue;
|
|
13948
|
+
const doorExpressId = writeDoorEntity(w, door.guid, `Door ${i + 1}`, ownerHistoryId, openingPlacementId, geomSubContextId, toIfcLengthM(door.spec.width), toIfcLengthM(door.spec.height));
|
|
13949
|
+
idMap.set(door.localId, doorExpressId);
|
|
13950
|
+
writeRelFillsElement(w, fillsRel.guid, ownerHistoryId, openingEntityId, doorExpressId);
|
|
13951
|
+
writeDoorCommonPset(w, ownerHistoryId, doorExpressId, door.spec);
|
|
13952
|
+
}
|
|
13953
|
+
for (const [i, win] of windows.entries()) {
|
|
13954
|
+
const fillsRel = relationships.find((rel) => rel.kind === "FILLS_OPENING" && rel.fillerLocalId === win.localId);
|
|
13955
|
+
if (fillsRel === void 0 || fillsRel.kind !== "FILLS_OPENING") continue;
|
|
13956
|
+
const openingPlacementId = openingPlacementMap.get(fillsRel.openingLocalId);
|
|
13957
|
+
const openingEntityId = openingEntityMap.get(fillsRel.openingLocalId);
|
|
13958
|
+
if (openingPlacementId === void 0 || openingEntityId === void 0) continue;
|
|
13959
|
+
const windowExpressId = writeWindowEntity(w, win.guid, `Window ${i + 1}`, ownerHistoryId, openingPlacementId, geomSubContextId, toIfcLengthM(win.spec.width), toIfcLengthM(win.spec.height));
|
|
13960
|
+
idMap.set(win.localId, windowExpressId);
|
|
13961
|
+
writeRelFillsElement(w, fillsRel.guid, ownerHistoryId, openingEntityId, windowExpressId);
|
|
13962
|
+
writeWindowCommonPset(w, ownerHistoryId, windowExpressId, win.spec);
|
|
13963
|
+
}
|
|
13964
|
+
for (const rel of relationships) {
|
|
13965
|
+
if (rel.kind !== "AGGREGATES") continue;
|
|
13966
|
+
const parentExpressId = idMap.get(rel.relatingObject);
|
|
13967
|
+
const childExpressIds = rel.relatedObjects.map((id) => idMap.get(id)).filter((id) => id !== void 0);
|
|
13968
|
+
if (parentExpressId === void 0 || childExpressIds.length === 0) continue;
|
|
13969
|
+
writeRelAggregates(w, rel.guid, ownerHistoryId, parentExpressId, childExpressIds);
|
|
13970
|
+
}
|
|
13971
|
+
for (const rel of relationships) {
|
|
13972
|
+
if (rel.kind !== "CONTAINED_IN") continue;
|
|
13973
|
+
const structureExpressId = idMap.get(rel.relatingStructure);
|
|
13974
|
+
const elementExpressIds = rel.relatedElements.map((id) => idMap.get(id)).filter((id) => id !== void 0);
|
|
13975
|
+
if (structureExpressId === void 0 || elementExpressIds.length === 0) continue;
|
|
13976
|
+
writeRelContainedInSpatialStructure(w, rel.guid, ownerHistoryId, structureExpressId, elementExpressIds);
|
|
13977
|
+
}
|
|
13978
|
+
for (const rel of relationships) {
|
|
13979
|
+
if (rel.kind !== "SPACE_BOUNDARY") continue;
|
|
13980
|
+
const spaceExpressId = idMap.get(rel.spaceLocalId);
|
|
13981
|
+
const elementExpressId = idMap.get(rel.elementLocalId);
|
|
13982
|
+
if (spaceExpressId === void 0 || elementExpressId === void 0) continue;
|
|
13983
|
+
writeRelSpaceBoundary(w, rel.guid, ownerHistoryId, spaceExpressId, elementExpressId, rel.connectionType);
|
|
13984
|
+
}
|
|
13985
|
+
for (const rel of relationships) {
|
|
13986
|
+
if (rel.kind !== "NESTS") continue;
|
|
13987
|
+
const parentExpressId = idMap.get(rel.relatingObject);
|
|
13988
|
+
const childExpressIds = rel.relatedObjects.map((id) => idMap.get(id)).filter((id) => id !== void 0);
|
|
13989
|
+
if (parentExpressId === void 0 || childExpressIds.length === 0) continue;
|
|
13990
|
+
writeRelNests(w, rel.guid, ownerHistoryId, parentExpressId, childExpressIds);
|
|
13991
|
+
}
|
|
13992
|
+
for (const rel of relationships) {
|
|
13993
|
+
if (rel.kind !== "COVERS_ELEMENT") continue;
|
|
13994
|
+
const hostExpressId = idMap.get(rel.hostLocalId);
|
|
13995
|
+
const coveringExpressId = idMap.get(rel.coveringLocalId);
|
|
13996
|
+
if (hostExpressId === void 0 || coveringExpressId === void 0) continue;
|
|
13997
|
+
writeRelCoversBldgElements(w, rel.guid, ownerHistoryId, hostExpressId, [coveringExpressId]);
|
|
13998
|
+
}
|
|
13999
|
+
for (const rel of relationships) {
|
|
14000
|
+
if (rel.kind !== "ASSIGNS_TO_GROUP") continue;
|
|
14001
|
+
const groupExpressId = idMap.get(rel.groupLocalId);
|
|
14002
|
+
const memberExpressIds = rel.memberLocalIds.map((id) => idMap.get(id)).filter((id) => id !== void 0);
|
|
14003
|
+
if (groupExpressId === void 0 || memberExpressIds.length === 0) continue;
|
|
14004
|
+
writeRelAssignsToGroup(w, rel.guid, ownerHistoryId, groupExpressId, memberExpressIds);
|
|
14005
|
+
}
|
|
14006
|
+
for (const rel of relationships) {
|
|
14007
|
+
if (rel.kind !== "CONNECTS_ELEMENTS") continue;
|
|
14008
|
+
const relatingExpressId = idMap.get(rel.relatingElementLocalId);
|
|
14009
|
+
const relatedExpressId = idMap.get(rel.relatedElementLocalId);
|
|
14010
|
+
if (relatingExpressId === void 0 || relatedExpressId === void 0) continue;
|
|
14011
|
+
writeRelConnectsElements(w, rel.guid, ownerHistoryId, relatingExpressId, relatedExpressId, rel.description ?? null);
|
|
14012
|
+
}
|
|
14013
|
+
for (const rel of relationships) {
|
|
14014
|
+
if (rel.kind !== "CONNECTS_PATH_ELEMENTS") continue;
|
|
14015
|
+
const relatingExpressId = idMap.get(rel.relatingElementLocalId);
|
|
14016
|
+
const relatedExpressId = idMap.get(rel.relatedElementLocalId);
|
|
14017
|
+
if (relatingExpressId === void 0 || relatedExpressId === void 0) continue;
|
|
14018
|
+
writeRelConnectsPathElements(w, rel.guid, ownerHistoryId, relatingExpressId, relatedExpressId, rel.relatingConnectionType, rel.relatedConnectionType, rel.description ?? null);
|
|
14019
|
+
}
|
|
14020
|
+
const bySimpleMaterial = /* @__PURE__ */ new Map();
|
|
14021
|
+
const layeredAssociations = [];
|
|
14022
|
+
const categoryById = new Map(elements.map((e) => [e.localId, e.category]));
|
|
14023
|
+
for (const rel of relationships) {
|
|
14024
|
+
if (rel.kind !== "ASSOCIATES_MATERIAL") continue;
|
|
14025
|
+
const objectExpressIds = rel.relatedObjects.map((id) => idMap.get(id)).filter((id) => id !== void 0);
|
|
14026
|
+
if (objectExpressIds.length === 0) continue;
|
|
14027
|
+
if (rel.materialLayers !== void 0 && rel.materialLayers.length > 0) {
|
|
14028
|
+
const firstObj = rel.relatedObjects[0];
|
|
14029
|
+
const hostCat = firstObj !== void 0 ? categoryById.get(firstObj) : void 0;
|
|
14030
|
+
const direction = hostCat === "SLAB" || hostCat === "ROOF" || hostCat === "COVERING" ? "AXIS3" : "AXIS2";
|
|
14031
|
+
layeredAssociations.push({
|
|
14032
|
+
guid: rel.guid,
|
|
14033
|
+
layerSetName: rel.layerSetName ?? rel.materialName,
|
|
14034
|
+
layers: rel.materialLayers,
|
|
14035
|
+
ids: objectExpressIds,
|
|
14036
|
+
direction
|
|
14037
|
+
});
|
|
14038
|
+
continue;
|
|
14039
|
+
}
|
|
14040
|
+
const existing = bySimpleMaterial.get(rel.materialName);
|
|
14041
|
+
if (existing !== void 0) bySimpleMaterial.set(rel.materialName, {
|
|
14042
|
+
guid: existing.guid,
|
|
14043
|
+
ids: [...existing.ids, ...objectExpressIds]
|
|
14044
|
+
});
|
|
14045
|
+
else bySimpleMaterial.set(rel.materialName, {
|
|
14046
|
+
guid: rel.guid,
|
|
14047
|
+
ids: objectExpressIds
|
|
14048
|
+
});
|
|
14049
|
+
}
|
|
14050
|
+
for (const [materialName, { guid, ids }] of bySimpleMaterial) {
|
|
14051
|
+
if (ids.length === 0) continue;
|
|
14052
|
+
writeMaterialSimple(w, guid, ownerHistoryId, materialName, ids);
|
|
14053
|
+
}
|
|
14054
|
+
for (const assoc of layeredAssociations) writeMaterialLayerSet(w, assoc.guid, ownerHistoryId, {
|
|
14055
|
+
kind: "LAYER_SET",
|
|
14056
|
+
layerSetName: assoc.layerSetName,
|
|
14057
|
+
layers: assoc.layers
|
|
14058
|
+
}, assoc.ids, assoc.direction);
|
|
14059
|
+
const classByKey = /* @__PURE__ */ new Map();
|
|
14060
|
+
for (const rel of relationships) {
|
|
14061
|
+
if (rel.kind !== "ASSOCIATES_CLASSIFICATION") continue;
|
|
14062
|
+
const objectExpressIds = rel.relatedObjects.map((id) => idMap.get(id)).filter((id) => id !== void 0);
|
|
14063
|
+
if (objectExpressIds.length === 0) continue;
|
|
14064
|
+
const key = `${rel.ref.system}:${rel.ref.code}`;
|
|
14065
|
+
const entry = classByKey.get(key);
|
|
14066
|
+
if (entry === void 0) classByKey.set(key, {
|
|
14067
|
+
ref: rel.ref,
|
|
14068
|
+
ids: [...objectExpressIds]
|
|
14069
|
+
});
|
|
14070
|
+
else entry.ids.push(...objectExpressIds);
|
|
14071
|
+
}
|
|
14072
|
+
const byClassification = /* @__PURE__ */ new Map();
|
|
14073
|
+
for (const { ref, ids } of classByKey.values()) byClassification.set(ref, ids);
|
|
14074
|
+
if (byClassification.size > 0) writeClassificationRefs(w, ownerHistoryId, byClassification);
|
|
14075
|
+
writeTypeLayer(w, ownerHistoryId, model, idMap);
|
|
14076
|
+
return w.save();
|
|
14077
|
+
} catch (_) {
|
|
14078
|
+
_usingCtx$2.e = _;
|
|
14079
|
+
} finally {
|
|
14080
|
+
_usingCtx$2.d();
|
|
13730
14081
|
}
|
|
13731
|
-
const byClassification = /* @__PURE__ */ new Map();
|
|
13732
|
-
for (const { ref, ids } of classByKey.values()) byClassification.set(ref, ids);
|
|
13733
|
-
if (byClassification.size > 0) writeClassificationRefs(w, ownerHistoryId, byClassification);
|
|
13734
|
-
writeTypeLayer(w, ownerHistoryId, model, idMap);
|
|
13735
|
-
return w.save();
|
|
13736
14082
|
}
|
|
13737
14083
|
/**
|
|
13738
14084
|
* Auto-derives one IfcType per (category, predefinedType) group of occurrences
|
|
@@ -13874,7 +14220,6 @@ async function toIfcValidated(model, meta) {
|
|
|
13874
14220
|
function collectGeometryIssues(model) {
|
|
13875
14221
|
const issues = [];
|
|
13876
14222
|
const groups = [
|
|
13877
|
-
["Wall", model.getWalls()],
|
|
13878
14223
|
["Slab", model.getSlabs()],
|
|
13879
14224
|
["Beam", model.getBeams()],
|
|
13880
14225
|
["Column", model.getColumns()],
|
|
@@ -13884,13 +14229,19 @@ function collectGeometryIssues(model) {
|
|
|
13884
14229
|
["Roof", model.getRoofs()],
|
|
13885
14230
|
["Footing", model.getFootings()],
|
|
13886
14231
|
["Pile", model.getPiles()],
|
|
13887
|
-
["Railing", model.getRailings()],
|
|
13888
14232
|
["Covering", model.getCoverings()]
|
|
13889
14233
|
];
|
|
13890
14234
|
for (const [label, elements] of groups) elements.forEach((el, index) => {
|
|
13891
14235
|
const report = checkGeometryValidity(el.geometry, `${label} ${index + 1}`);
|
|
13892
14236
|
issues.push(...report.issues);
|
|
13893
14237
|
});
|
|
14238
|
+
const productGroups = [["Wall", model.getWalls()], ["Railing", model.getRailings()]];
|
|
14239
|
+
for (const [label, elements] of productGroups) elements.forEach((el, index) => {
|
|
14240
|
+
bodySolids(el.geometry).forEach((solid, itemIndex) => {
|
|
14241
|
+
const report = checkGeometryValidity(solid, `${label} ${index + 1} Body item ${itemIndex + 1}`);
|
|
14242
|
+
issues.push(...report.issues);
|
|
14243
|
+
});
|
|
14244
|
+
});
|
|
13894
14245
|
model.getRamps().forEach((ramp, index) => {
|
|
13895
14246
|
if (ramp.spec.flights.length === 0) return;
|
|
13896
14247
|
issues.push(issue("info", "SIMPLIFIED_GEOMETRY", `Ramp ${index + 1} uses simplified inclined-slab flight geometry`));
|
|
@@ -14065,7 +14416,7 @@ function buildElementContainmentMap(reader) {
|
|
|
14065
14416
|
//#endregion
|
|
14066
14417
|
//#region src/import/geometryRead.ts
|
|
14067
14418
|
var NONE = { kind: "NONE" };
|
|
14068
|
-
var testHooks$
|
|
14419
|
+
var testHooks$3 = null;
|
|
14069
14420
|
/**
|
|
14070
14421
|
* Reconstructs the `Body` (SweptSolid) representation of a product into a brepjs
|
|
14071
14422
|
* solid, falling back to tessellated mesh import when no parametric path exists.
|
|
@@ -14309,7 +14660,7 @@ function reconstructTessellatedMesh(mesh, scaleToMm, itemExpressId, diagnostics)
|
|
|
14309
14660
|
}
|
|
14310
14661
|
if (solid !== null) {
|
|
14311
14662
|
try {
|
|
14312
|
-
testHooks$
|
|
14663
|
+
testHooks$3?.afterItemSolid?.(itemExpressId, solid);
|
|
14313
14664
|
} catch (cause) {
|
|
14314
14665
|
solid[Symbol.dispose]();
|
|
14315
14666
|
throw cause;
|
|
@@ -15270,7 +15621,7 @@ function readOwnerHistory(reader, ownerHistoryExpressId) {
|
|
|
15270
15621
|
}
|
|
15271
15622
|
//#endregion
|
|
15272
15623
|
//#region src/import/fromIfc.ts
|
|
15273
|
-
var testHooks = null;
|
|
15624
|
+
var testHooks$2 = null;
|
|
15274
15625
|
/**
|
|
15275
15626
|
* Each enumerated physical-element IFC type and the {@link ImportedElementCategory}
|
|
15276
15627
|
* it maps to. Curtain-wall sub-components (IfcPlate/IfcMember) and stair/ramp
|
|
@@ -15334,7 +15685,7 @@ async function fromIfc(bytes, options = {}) {
|
|
|
15334
15685
|
if (element === null) continue;
|
|
15335
15686
|
elements.push(element);
|
|
15336
15687
|
byExpressId.set(element.expressId, element);
|
|
15337
|
-
testHooks?.afterElement?.(element, elements.length);
|
|
15688
|
+
testHooks$2?.afterElement?.(element, elements.length);
|
|
15338
15689
|
}
|
|
15339
15690
|
const report = appendIssues(emptyReport(), diagnostics);
|
|
15340
15691
|
const applicationName = readApplicationName(reader);
|
|
@@ -15380,7 +15731,7 @@ function readElement(reader, expressId, category, scale, containment, typeEnums,
|
|
|
15380
15731
|
bounds: null,
|
|
15381
15732
|
volumeMm3: null
|
|
15382
15733
|
} : reconstructGeometry(reader, expressId, scale, voidedBy, diagnostics);
|
|
15383
|
-
testHooks?.afterGeometry?.(expressId, geometry);
|
|
15734
|
+
testHooks$2?.afterGeometry?.(expressId, geometry);
|
|
15384
15735
|
const psets = readPsets(reader, expressId).map(toImportedPset);
|
|
15385
15736
|
const material = readMaterial(reader, expressId, scale);
|
|
15386
15737
|
const classification = readClassification(reader, expressId);
|
|
@@ -28521,13 +28872,151 @@ function isPureTranslation(f, eps = 1e-9) {
|
|
|
28521
28872
|
return Math.abs((f[0] ?? 1) - 1) < eps && Math.abs((f[5] ?? 1) - 1) < eps && Math.abs((f[10] ?? 1) - 1) < eps && Math.abs(f[1] ?? 0) < eps && Math.abs(f[2] ?? 0) < eps && Math.abs(f[4] ?? 0) < eps && Math.abs(f[6] ?? 0) < eps && Math.abs(f[8] ?? 0) < eps && Math.abs(f[9] ?? 0) < eps;
|
|
28522
28873
|
}
|
|
28523
28874
|
//#endregion
|
|
28875
|
+
//#region src/familiesProductBody.ts
|
|
28876
|
+
var RELATIVE_VOLUME_TOLERANCE = 1e-6;
|
|
28877
|
+
var testHooks$1 = null;
|
|
28878
|
+
/**
|
|
28879
|
+
* Evaluates a civil Product Body, clones and localizes every borrowed source,
|
|
28880
|
+
* then proves whether the registered-opening parametric Body is coincident.
|
|
28881
|
+
* An EXACT result is caller-owned until takeExactProductBody() succeeds.
|
|
28882
|
+
*/
|
|
28883
|
+
function selectCivilProductBody(input) {
|
|
28884
|
+
const evaluated = evaluateBody(input);
|
|
28885
|
+
if (!evaluated.ok) return evaluated;
|
|
28886
|
+
const sources = evaluated.value;
|
|
28887
|
+
if (sources.length === 0) return err(productBodyError(input, "FAMILIES_PRODUCT_BODY_EMPTY", `evaluated to no solid Body items`));
|
|
28888
|
+
const localized = [];
|
|
28889
|
+
const inverse = decomposeFrame(frameInverse(input.productWorldFrame));
|
|
28890
|
+
for (const [itemIndex, source] of sources.entries()) {
|
|
28891
|
+
const copied = clone(source);
|
|
28892
|
+
if (!copied.ok) {
|
|
28893
|
+
disposeAll(localized);
|
|
28894
|
+
return err(productBodyError(input, "FAMILIES_PRODUCT_BODY_COPY_FAILED", `Body item ${itemIndex} could not be copied`, copied.error, itemIndex));
|
|
28895
|
+
}
|
|
28896
|
+
try {
|
|
28897
|
+
testHooks$1?.afterCopy?.(itemIndex, copied.value, source);
|
|
28898
|
+
} catch (cause) {
|
|
28899
|
+
copied.value[Symbol.dispose]();
|
|
28900
|
+
disposeAll(localized);
|
|
28901
|
+
return err(productBodyError(input, "FAMILIES_PRODUCT_BODY_COPY_FAILED", `Body item ${itemIndex} could not be copied`, cause, itemIndex));
|
|
28902
|
+
}
|
|
28903
|
+
let valid;
|
|
28904
|
+
try {
|
|
28905
|
+
valid = validSolid(copied.value);
|
|
28906
|
+
} catch (cause) {
|
|
28907
|
+
copied.value[Symbol.dispose]();
|
|
28908
|
+
disposeAll(localized);
|
|
28909
|
+
return err(productBodyError(input, "FAMILIES_PRODUCT_BODY_INVALID", `Body item ${itemIndex} could not be validated as a solid`, cause, itemIndex));
|
|
28910
|
+
}
|
|
28911
|
+
if (!valid.ok) {
|
|
28912
|
+
copied.value[Symbol.dispose]();
|
|
28913
|
+
disposeAll(localized);
|
|
28914
|
+
return err(productBodyError(input, "FAMILIES_PRODUCT_BODY_INVALID", `Body item ${itemIndex} is not a valid solid: ${valid.error}`, void 0, itemIndex));
|
|
28915
|
+
}
|
|
28916
|
+
let local = null;
|
|
28917
|
+
try {
|
|
28918
|
+
testHooks$1?.beforeLocalize?.(itemIndex, valid.value);
|
|
28919
|
+
local = locateShapeInFrame(valid.value, inverse);
|
|
28920
|
+
testHooks$1?.afterLocalized?.(itemIndex, local);
|
|
28921
|
+
localized.push(local);
|
|
28922
|
+
} catch (cause) {
|
|
28923
|
+
local?.[Symbol.dispose]();
|
|
28924
|
+
valid.value[Symbol.dispose]();
|
|
28925
|
+
disposeAll(localized);
|
|
28926
|
+
return err(productBodyError(input, "FAMILIES_PRODUCT_BODY_LOCALIZE_FAILED", `Body item ${itemIndex} could not be moved into the Product-local frame`, cause, itemIndex));
|
|
28927
|
+
}
|
|
28928
|
+
valid.value[Symbol.dispose]();
|
|
28929
|
+
}
|
|
28930
|
+
const exactBody = {
|
|
28931
|
+
kind: "EXACT",
|
|
28932
|
+
solids: asNonEmpty(localized)
|
|
28933
|
+
};
|
|
28934
|
+
try {
|
|
28935
|
+
testHooks$1?.beforeCoincidence?.(exactBody, input.parametricBody);
|
|
28936
|
+
} catch (cause) {
|
|
28937
|
+
disposeAll(exactBody.solids);
|
|
28938
|
+
return err(productBodyError(input, "FAMILIES_PRODUCT_BODY_COMPARISON_FAILED", `authored and parametric Bodies could not be compared`, cause));
|
|
28939
|
+
}
|
|
28940
|
+
if (!bodiesCoincident(exactBody, input.parametricBody)) return ok({
|
|
28941
|
+
kind: "EXACT",
|
|
28942
|
+
body: exactBody
|
|
28943
|
+
});
|
|
28944
|
+
disposeAll(exactBody.solids);
|
|
28945
|
+
return ok({ kind: "PARAMETRIC" });
|
|
28946
|
+
}
|
|
28947
|
+
function evaluateBody(input) {
|
|
28948
|
+
try {
|
|
28949
|
+
const evaluated = input.evaluator.evaluate(input.element.geometry);
|
|
28950
|
+
if (!evaluated.ok) return err(productBodyError(input, "FAMILIES_PRODUCT_BODY_EVALUATION_FAILED", `authored Body evaluation failed: ${evaluated.error.message}`, evaluated.error));
|
|
28951
|
+
return ok(isSolid(evaluated.value) ? [evaluated.value] : getSolids(evaluated.value));
|
|
28952
|
+
} catch (cause) {
|
|
28953
|
+
return err(productBodyError(input, "FAMILIES_PRODUCT_BODY_EVALUATION_FAILED", `authored Body evaluation threw`, cause));
|
|
28954
|
+
}
|
|
28955
|
+
}
|
|
28956
|
+
function bodiesCoincident(exact, parametric) {
|
|
28957
|
+
const exactVolume = measureBody(exact);
|
|
28958
|
+
const parametricVolume = measureBody(parametric);
|
|
28959
|
+
if (exactVolume === null || parametricVolume === null || !volumesClose(exactVolume, parametricVolume)) return false;
|
|
28960
|
+
let union = null;
|
|
28961
|
+
try {
|
|
28962
|
+
const fused = fuseAll([...bodySolids(exact), ...bodySolids(parametric)], {
|
|
28963
|
+
optimisation: "sameFace",
|
|
28964
|
+
simplify: true,
|
|
28965
|
+
strategy: "pairwise",
|
|
28966
|
+
trackEvolution: false
|
|
28967
|
+
});
|
|
28968
|
+
if (!fused.ok) return false;
|
|
28969
|
+
union = fused.value;
|
|
28970
|
+
const measured = measureVolume(union);
|
|
28971
|
+
return measured.ok && volumesClose(measured.value, exactVolume) && volumesClose(measured.value, parametricVolume);
|
|
28972
|
+
} catch {
|
|
28973
|
+
return false;
|
|
28974
|
+
} finally {
|
|
28975
|
+
union?.[Symbol.dispose]();
|
|
28976
|
+
}
|
|
28977
|
+
}
|
|
28978
|
+
function measureBody(body) {
|
|
28979
|
+
let total = 0;
|
|
28980
|
+
try {
|
|
28981
|
+
for (const solid of bodySolids(body)) {
|
|
28982
|
+
const measured = measureVolume(solid);
|
|
28983
|
+
if (!measured.ok || !Number.isFinite(measured.value) || measured.value <= 0) return null;
|
|
28984
|
+
total += measured.value;
|
|
28985
|
+
}
|
|
28986
|
+
return total;
|
|
28987
|
+
} catch {
|
|
28988
|
+
return null;
|
|
28989
|
+
}
|
|
28990
|
+
}
|
|
28991
|
+
function volumesClose(a, b) {
|
|
28992
|
+
return Math.abs(a - b) <= RELATIVE_VOLUME_TOLERANCE * Math.max(Math.abs(a), Math.abs(b), Number.EPSILON);
|
|
28993
|
+
}
|
|
28994
|
+
function asNonEmpty(solids) {
|
|
28995
|
+
const first = solids[0];
|
|
28996
|
+
if (first === void 0) throw new Error("Expected a non-empty exact Product Body");
|
|
28997
|
+
return [first, ...solids.slice(1)];
|
|
28998
|
+
}
|
|
28999
|
+
function disposeAll(solids) {
|
|
29000
|
+
for (const solid of solids) solid[Symbol.dispose]();
|
|
29001
|
+
}
|
|
29002
|
+
function productBodyError(input, code, detail, cause, itemIndex) {
|
|
29003
|
+
return {
|
|
29004
|
+
...specError(code, `familiesToBim: '${input.element.keyPath}' (${input.category}) ${detail}`, cause),
|
|
29005
|
+
metadata: {
|
|
29006
|
+
keyPath: input.element.keyPath,
|
|
29007
|
+
category: input.category,
|
|
29008
|
+
...itemIndex !== void 0 ? { itemIndex } : {}
|
|
29009
|
+
}
|
|
29010
|
+
};
|
|
29011
|
+
}
|
|
29012
|
+
//#endregion
|
|
28524
29013
|
//#region src/familiesAdapter.ts
|
|
28525
29014
|
/**
|
|
28526
29015
|
* brepjs-families -> BimModel adapter. Consumes a resolved element tree and
|
|
28527
|
-
* feeds each element's PRE-DESUGARED props into
|
|
28528
|
-
*
|
|
28529
|
-
*
|
|
28530
|
-
* families key paths (stable under reordering), not insertion order.
|
|
29016
|
+
* feeds each element's PRE-DESUGARED props into parametric specs. Civil wall
|
|
29017
|
+
* and railing Products additionally compare the evaluated authored Body with
|
|
29018
|
+
* that spec Body and retain an exact Body when they diverge. GlobalIds derive
|
|
29019
|
+
* from families key paths (stable under reordering), not insertion order.
|
|
28531
29020
|
*
|
|
28532
29021
|
* Scope: building Storey containers; civil Site/Bridge/recursive Bridge Part
|
|
28533
29022
|
* structure and Earthworks Fill bodies; Wall/Slab/Column/Beam/Roof/Stair,
|
|
@@ -28539,6 +29028,7 @@ function isPureTranslation(f, eps = 1e-9) {
|
|
|
28539
29028
|
* voids are rejected: they cut only the IR/viewport geometry, and exporting
|
|
28540
29029
|
* the uncut spec body would silently diverge from what the user sees.
|
|
28541
29030
|
*/
|
|
29031
|
+
var testHooks = null;
|
|
28542
29032
|
var SPEC_DEFAULTS = {
|
|
28543
29033
|
origin: [
|
|
28544
29034
|
0,
|
|
@@ -28719,6 +29209,12 @@ function civilProductArchetype(el) {
|
|
|
28719
29209
|
if (definition === void 0 || !definition.roles.includes(el.semantics.role)) return void 0;
|
|
28720
29210
|
return definition.archetype;
|
|
28721
29211
|
}
|
|
29212
|
+
function civilProductBodyCategory(el, archetype) {
|
|
29213
|
+
if (el.semantics?.kind !== "product") return null;
|
|
29214
|
+
if (archetype === "wall") return "WALL";
|
|
29215
|
+
if (archetype === "railing") return "RAILING";
|
|
29216
|
+
return null;
|
|
29217
|
+
}
|
|
28722
29218
|
function semanticDimension(el, ...names) {
|
|
28723
29219
|
if (el.semantics?.kind !== "product") return void 0;
|
|
28724
29220
|
for (const name of names) {
|
|
@@ -29424,33 +29920,55 @@ function addEarthworksFillElement(model, el, evaluator, spatialFrame) {
|
|
|
29424
29920
|
if (!added.ok) localized.value[Symbol.dispose]();
|
|
29425
29921
|
return added;
|
|
29426
29922
|
}
|
|
29923
|
+
function installCivilProductBody(model, el, localId, category, evaluator, productWorldFrame) {
|
|
29924
|
+
const target = model.getElement(localId);
|
|
29925
|
+
if (target === null || target.category !== category || target.geometry.kind !== "PARAMETRIC") return err(specError("FAMILIES_PRODUCT_BODY_TARGET_INVALID", `familiesToBim: '${el.keyPath}' could not find its parametric ${category} Body after projection`));
|
|
29926
|
+
const selected = selectCivilProductBody({
|
|
29927
|
+
element: el,
|
|
29928
|
+
category,
|
|
29929
|
+
evaluator,
|
|
29930
|
+
productWorldFrame,
|
|
29931
|
+
parametricBody: target.geometry
|
|
29932
|
+
});
|
|
29933
|
+
if (!selected.ok) return selected;
|
|
29934
|
+
if (selected.value.kind === "PARAMETRIC") return ok(void 0);
|
|
29935
|
+
const takeover = model.takeExactProductBody(localId, selected.value.body);
|
|
29936
|
+
if (!takeover.ok) disposeProductBody(selected.value.body);
|
|
29937
|
+
return takeover;
|
|
29938
|
+
}
|
|
29427
29939
|
/**
|
|
29428
29940
|
* Project a resolved families tree into an eager BimModel. The caller owns
|
|
29429
29941
|
* the returned model (`using`); families stays domain-neutral — this adapter
|
|
29430
29942
|
* is where families types meet the IFC vocabulary.
|
|
29431
29943
|
*/
|
|
29432
29944
|
function familiesToBim(root, options) {
|
|
29945
|
+
const model = new BimModel();
|
|
29946
|
+
let transferred = false;
|
|
29947
|
+
try {
|
|
29948
|
+
const projected = projectFamiliesToBim(root, options, model);
|
|
29949
|
+
transferred = projected.ok;
|
|
29950
|
+
return projected;
|
|
29951
|
+
} catch (cause) {
|
|
29952
|
+
return err(specError("FAMILIES_PROJECTION_FAILED", `familiesToBim: unexpected projection failure at '${root.keyPath}'`, cause));
|
|
29953
|
+
} finally {
|
|
29954
|
+
if (!transferred) model[Symbol.dispose]();
|
|
29955
|
+
}
|
|
29956
|
+
}
|
|
29957
|
+
function projectFamiliesToBim(root, options, model) {
|
|
29433
29958
|
const usesAuthoredCivilHierarchy = hasCivilSpatialIntent(root);
|
|
29434
29959
|
if (usesAuthoredCivilHierarchy) {
|
|
29435
29960
|
const keyed = requireKeyed(root);
|
|
29436
29961
|
if (!keyed.ok) return keyed;
|
|
29437
29962
|
}
|
|
29438
|
-
const model = new BimModel();
|
|
29439
29963
|
const initResult = model.init(options.project, usesAuthoredCivilHierarchy ? { stableKey: civilSpatialKind(root) !== void 0 ? `${root.keyPath}#project` : root.keyPath } : void 0);
|
|
29440
29964
|
if (!initResult.ok) return initResult;
|
|
29441
29965
|
const projectId = initResult.value;
|
|
29442
29966
|
let buildingId = null;
|
|
29443
29967
|
if (!usesAuthoredCivilHierarchy) {
|
|
29444
29968
|
const siteResult = model.addSite({ name: options.siteName ?? "Site" });
|
|
29445
|
-
if (!siteResult.ok)
|
|
29446
|
-
model[Symbol.dispose]();
|
|
29447
|
-
return siteResult;
|
|
29448
|
-
}
|
|
29969
|
+
if (!siteResult.ok) return siteResult;
|
|
29449
29970
|
const buildingResult = model.addBuilding({ name: options.buildingName ?? "Building" });
|
|
29450
|
-
if (!buildingResult.ok)
|
|
29451
|
-
model[Symbol.dispose]();
|
|
29452
|
-
return buildingResult;
|
|
29453
|
-
}
|
|
29971
|
+
if (!buildingResult.ok) return buildingResult;
|
|
29454
29972
|
buildingId = buildingResult.value;
|
|
29455
29973
|
model.aggregate(projectId, siteResult.value);
|
|
29456
29974
|
model.aggregate(siteResult.value, buildingId);
|
|
@@ -29480,8 +29998,7 @@ function familiesToBim(root, options) {
|
|
|
29480
29998
|
if (el.geometry.kind !== "Empty") return err(specError("FAMILIES_UNSUPPORTED_CIVIL_SEMANTICS", `familiesToBim: civil spatial element '${el.keyPath}' carries its own geometry — Site/Bridge/Bridge Part export no body, so author it as a child Product (e.g. Earthworks Fill)`));
|
|
29481
29999
|
const nodeFrame = civilNodeFrame(el, cumulativeFrameHere);
|
|
29482
30000
|
const rotatedFrame = rotatedHere || hasRotatedAxes(el);
|
|
29483
|
-
const
|
|
29484
|
-
const added = addCivilSpatialOccurrence(model, el, civilKind, input);
|
|
30001
|
+
const added = addCivilSpatialOccurrence(model, el, civilKind, rotatedFrame ? civilSpatialFrameInput(el, nodeFrame, state.spatialFrame) : civilSpatialInput(el, subtractTranslation(cumulativeTranslationHere, state.projectedSpatialTranslation)));
|
|
29485
30002
|
if (!added.ok) return added;
|
|
29486
30003
|
model.aggregate(state.spatialStructureId, added.value);
|
|
29487
30004
|
idByKeyPath.set(el.keyPath, added.value);
|
|
@@ -29517,6 +30034,15 @@ function familiesToBim(root, options) {
|
|
|
29517
30034
|
} else if (route !== void 0) {
|
|
29518
30035
|
const keyed = requireKeyed(el);
|
|
29519
30036
|
if (!keyed.ok) return keyed;
|
|
30037
|
+
const productBodyCategory = civilProductBodyCategory(el, effectiveArchetype);
|
|
30038
|
+
const productBodyEvaluator = productBodyCategory === null ? void 0 : options.bodyEvaluator ?? options.proxyEvaluator;
|
|
30039
|
+
if (productBodyCategory !== null && productBodyEvaluator === void 0) return err({
|
|
30040
|
+
...specError("FAMILIES_PRODUCT_BODY_EVALUATOR_REQUIRED", `familiesToBim: civil Product '${el.keyPath}' mapped to ${productBodyCategory} needs bodyEvaluator or proxyEvaluator to verify its authoritative Body`),
|
|
30041
|
+
metadata: {
|
|
30042
|
+
keyPath: el.keyPath,
|
|
30043
|
+
category: productBodyCategory
|
|
30044
|
+
}
|
|
30045
|
+
});
|
|
29520
30046
|
const voids = el.props["voids"];
|
|
29521
30047
|
if (Array.isArray(voids)) {
|
|
29522
30048
|
const openings = el.children.filter((c) => c.type === "Opening").length;
|
|
@@ -29536,6 +30062,11 @@ function familiesToBim(root, options) {
|
|
|
29536
30062
|
const opened = addOpenings(model, el, added.value, nextSpatialStructureId, idByKeyPath);
|
|
29537
30063
|
if (!opened.ok) return opened;
|
|
29538
30064
|
}
|
|
30065
|
+
if (productBodyCategory !== null && productBodyEvaluator !== void 0) {
|
|
30066
|
+
const installed = installCivilProductBody(model, el, added.value, productBodyCategory, productBodyEvaluator, elementBodyFrame(el, cumulativeFrameHere, occurrenceTransformDepthHere));
|
|
30067
|
+
if (!installed.ok) return installed;
|
|
30068
|
+
testHooks?.afterCivilProductBody?.(model, added.value, el);
|
|
30069
|
+
}
|
|
29539
30070
|
} else if (el.type === "Opening") return err(specError("FAMILIES_OPENING_OUTSIDE_WALL", `familiesToBim: opening '${el.keyPath}' is not hosted by a Wall — only wall openings are mapped`));
|
|
29540
30071
|
else if (el.type !== "Group" && el.geometry.kind !== "Empty") {
|
|
29541
30072
|
if (options.proxyEvaluator === void 0) return err(specError("FAMILIES_UNSUPPORTED_TYPE", `familiesToBim: no supported spec mapping for element type '${el.type}' at '${el.keyPath}' (archetype: ${el.archetype ?? "none"}) — declare a recognized archetype or civil Product category/role, add a spec route, or pass proxyEvaluator to export it as an IfcBuildingElementProxy`));
|
|
@@ -29579,10 +30110,7 @@ function familiesToBim(root, options) {
|
|
|
29579
30110
|
cumulativeFrame: IDENTITY_FRAME,
|
|
29580
30111
|
spatialFrame: IDENTITY_FRAME
|
|
29581
30112
|
});
|
|
29582
|
-
if (!walked.ok)
|
|
29583
|
-
model[Symbol.dispose]();
|
|
29584
|
-
return walked;
|
|
29585
|
-
}
|
|
30113
|
+
if (!walked.ok) return walked;
|
|
29586
30114
|
return ok({
|
|
29587
30115
|
model,
|
|
29588
30116
|
idByKeyPath,
|
|
@@ -29590,4 +30118,4 @@ function familiesToBim(root, options) {
|
|
|
29590
30118
|
});
|
|
29591
30119
|
}
|
|
29592
30120
|
//#endregion
|
|
29593
|
-
export { BimModel, DEFAULT_IFC_SCHEMA, DEFAULT_UNITS, IFC_SCHEMAS, PSET_PROPERTY_TYPE_TABLE, PSET_TEMPLATES, SpfReader, bcfError, checkGeometryValidity, checkGherkinRules, checkIdsData as checkIds, checkIdsData, checkReferentialIntegrity, checkRoundTrip, checkSchema, countBySeverity, deriveCobieModel, deriveCobieModel as exportCobie, deriveIfcGuid, deriveIfcGuidSync, disposeImportedModel, emptyReport, extendedProfileArea, extendedProfileToFace, familiesToBim, fileSchemaString, fromBrepError, fromIfc, geometryError, hasErrors, idsError, ifcError, importError, isExtendedProfile, isIfcSchema, isSlabOpening, isValidIfcGuid, isWallOpening, issue, makeLocalIdCounter, measureTypeFor, newIfcGuid, parseBcfFiles, parseBeamSpec, parseBridgePartSpec, parseBridgeSpec, parseColumnSpec, parseCoveringSpec, parseCurtainWallSpec, parseDoorSpec, parseElementAssemblySpec, parseFootingSpec, parseIdsXml, parsePileSpec, parseProfile, parseRailingSpec, parseRampFlightSpec, parseRampSpec, parseRoofSpec, parseSlabOpeningInput, parseSlabSpec, parseSpaceSpec, parseStairFlightSpec, parseStairSpec, parseSurfaceStyleSpec, parseSystemSpec, parseWallSpec, parseWindowSpec, parseZoneSpec, placedSolids, schemaSupports, serializeBcfFiles, serializeCobieToCsv, serializeCobieToJson, setIfcWasmLocateFile, specError, templateFor, toIfc, toIfcLengthM, toIfcValidated, toLengthMm, writeClassificationRefs, writeElementAssemblyEntity, writeIfcType, writeMaterialLayerSet, writeMaterialProfileSet, writeMaterialSimple, writePresentationLayer, writeRelAggregatesElements, writeRelAssignsToGroup, writeRelConnectsElements, writeRelConnectsPathElements, writeRelNests, writeStyledItem, writeSurfaceStyle, writeSystemEntity, writeZoneEntity };
|
|
30121
|
+
export { BimModel, DEFAULT_IFC_SCHEMA, DEFAULT_UNITS, IFC_SCHEMAS, PSET_PROPERTY_TYPE_TABLE, PSET_TEMPLATES, SpfReader, bcfError, bodySolids, checkGeometryValidity, checkGherkinRules, checkIdsData as checkIds, checkIdsData, checkReferentialIntegrity, checkRoundTrip, checkSchema, countBySeverity, deriveCobieModel, deriveCobieModel as exportCobie, deriveIfcGuid, deriveIfcGuidSync, disposeImportedModel, emptyReport, extendedProfileArea, extendedProfileToFace, familiesToBim, fileSchemaString, fromBrepError, fromIfc, geometryError, hasErrors, idsError, ifcError, importError, isExtendedProfile, isIfcSchema, isSlabOpening, isValidIfcGuid, isWallOpening, issue, makeLocalIdCounter, measureTypeFor, newIfcGuid, parseBcfFiles, parseBeamSpec, parseBridgePartSpec, parseBridgeSpec, parseColumnSpec, parseCoveringSpec, parseCurtainWallSpec, parseDoorSpec, parseElementAssemblySpec, parseFootingSpec, parseIdsXml, parsePileSpec, parseProfile, parseRailingSpec, parseRampFlightSpec, parseRampSpec, parseRoofSpec, parseSlabOpeningInput, parseSlabSpec, parseSpaceSpec, parseStairFlightSpec, parseStairSpec, parseSurfaceStyleSpec, parseSystemSpec, parseWallSpec, parseWindowSpec, parseZoneSpec, placedSolids, schemaSupports, serializeBcfFiles, serializeCobieToCsv, serializeCobieToJson, setIfcWasmLocateFile, specError, templateFor, toIfc, toIfcLengthM, toIfcValidated, toLengthMm, writeClassificationRefs, writeElementAssemblyEntity, writeIfcType, writeMaterialLayerSet, writeMaterialProfileSet, writeMaterialSimple, writePresentationLayer, writeRelAggregatesElements, writeRelAssignsToGroup, writeRelConnectsElements, writeRelConnectsPathElements, writeRelNests, writeStyledItem, writeSurfaceStyle, writeSystemEntity, writeZoneEntity };
|