brepjs-bim 0.24.4 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -0
- package/dist/brepjs-bim.cjs +409 -415
- package/dist/brepjs-bim.js +401 -407
- package/dist/geometryCleanupDiagnostics.d.ts +6 -0
- package/dist/ifc-writer/geometryWriter.d.ts +0 -6
- package/dist/ifc-writer/headerWriter.d.ts +2 -0
- package/dist/ifc-writer/openingWriter.d.ts +1 -1
- package/dist/ifc-writer/tessellationWriter.d.ts +2 -2
- package/dist/import/cutImportedSolids.d.ts +4 -0
- package/dist/import/fromIfc.d.ts +1 -1
- package/dist/import/importedModel.d.ts +6 -3
- package/dist/serialize/productBodyPreflight.d.ts +15 -0
- package/package.json +2 -2
- package/dist/serialize/exactBodyPreflight.d.ts +0 -15
package/dist/brepjs-bim.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { GeometryCleanupError, 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";
|
|
1
|
+
import { GeometryCleanupError, addHoles, applyMatrix, autoHeal, box, castShape, clone, convexHull, createSolid, 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, IFCROOT, IfcAPI } from "web-ifc";
|
|
4
4
|
//#region src/identity/ifcGuid.ts
|
|
@@ -243,7 +243,7 @@ function _usingCtx() {
|
|
|
243
243
|
//#region src/elementFns/wallFns.ts
|
|
244
244
|
function wallToSolid(spec) {
|
|
245
245
|
try {
|
|
246
|
-
var _usingCtx$
|
|
246
|
+
var _usingCtx$21 = _usingCtx();
|
|
247
247
|
if (spec.length <= 0) return err(specError("WALL_ZERO_LENGTH", "Wall length must be positive"));
|
|
248
248
|
if (spec.height <= 0) return err(specError("WALL_ZERO_HEIGHT", "Wall height must be positive"));
|
|
249
249
|
if (spec.thickness <= 0) return err(specError("WALL_ZERO_THICKNESS", "Wall thickness must be positive"));
|
|
@@ -271,7 +271,7 @@ function wallToSolid(spec) {
|
|
|
271
271
|
]
|
|
272
272
|
]);
|
|
273
273
|
if (!profileResult.ok) return err(fromBrepError(profileResult.error, "WALL_PROFILE_FAILED", "Failed to create wall profile"));
|
|
274
|
-
const profile = _usingCtx$
|
|
274
|
+
const profile = _usingCtx$21.u(profileResult.value);
|
|
275
275
|
const solidResult = extrude(profile, [
|
|
276
276
|
length,
|
|
277
277
|
0,
|
|
@@ -285,16 +285,16 @@ function wallToSolid(spec) {
|
|
|
285
285
|
}
|
|
286
286
|
return ok(solid);
|
|
287
287
|
} catch (_) {
|
|
288
|
-
_usingCtx$
|
|
288
|
+
_usingCtx$21.e = _;
|
|
289
289
|
} finally {
|
|
290
|
-
_usingCtx$
|
|
290
|
+
_usingCtx$21.d();
|
|
291
291
|
}
|
|
292
292
|
}
|
|
293
293
|
//#endregion
|
|
294
294
|
//#region src/elementFns/slabFns.ts
|
|
295
295
|
function slabToSolid(spec) {
|
|
296
296
|
try {
|
|
297
|
-
var _usingCtx$
|
|
297
|
+
var _usingCtx$20 = _usingCtx();
|
|
298
298
|
if (spec.length <= 0) return err(specError("SLAB_ZERO_LENGTH", "Slab length must be positive"));
|
|
299
299
|
if (spec.width <= 0) return err(specError("SLAB_ZERO_WIDTH", "Slab width must be positive"));
|
|
300
300
|
if (spec.thickness <= 0) return err(specError("SLAB_ZERO_THICKNESS", "Slab thickness must be positive"));
|
|
@@ -322,7 +322,7 @@ function slabToSolid(spec) {
|
|
|
322
322
|
]
|
|
323
323
|
]);
|
|
324
324
|
if (!profileResult.ok) return err(fromBrepError(profileResult.error, "SLAB_PROFILE_FAILED", "Failed to create slab profile"));
|
|
325
|
-
const profile = _usingCtx$
|
|
325
|
+
const profile = _usingCtx$20.u(profileResult.value);
|
|
326
326
|
const solidResult = extrude(profile, [
|
|
327
327
|
0,
|
|
328
328
|
0,
|
|
@@ -336,9 +336,9 @@ function slabToSolid(spec) {
|
|
|
336
336
|
}
|
|
337
337
|
return ok(solid);
|
|
338
338
|
} catch (_) {
|
|
339
|
-
_usingCtx$
|
|
339
|
+
_usingCtx$20.e = _;
|
|
340
340
|
} finally {
|
|
341
|
-
_usingCtx$
|
|
341
|
+
_usingCtx$20.d();
|
|
342
342
|
}
|
|
343
343
|
}
|
|
344
344
|
//#endregion
|
|
@@ -1696,7 +1696,7 @@ var Doc = class {
|
|
|
1696
1696
|
var version = {
|
|
1697
1697
|
major: 4,
|
|
1698
1698
|
minor: 6,
|
|
1699
|
-
patch:
|
|
1699
|
+
patch: 5
|
|
1700
1700
|
};
|
|
1701
1701
|
//#endregion
|
|
1702
1702
|
//#region ../../node_modules/zod/v4/core/schemas.js
|
|
@@ -6335,14 +6335,14 @@ function to3D(points) {
|
|
|
6335
6335
|
}
|
|
6336
6336
|
function extendedProfileToFace(profile) {
|
|
6337
6337
|
try {
|
|
6338
|
-
var _usingCtx$
|
|
6338
|
+
var _usingCtx$19 = _usingCtx();
|
|
6339
6339
|
const invalid = validateProfile(profile);
|
|
6340
6340
|
if (invalid !== null) return err(invalid);
|
|
6341
6341
|
const outerResult = polygon(to3D(outerLoop(profile)));
|
|
6342
6342
|
if (!outerResult.ok) return err(fromBrepError(outerResult.error, "PROFILE_FACE_FAILED", "Failed to build profile outer face"));
|
|
6343
6343
|
const holes = holeLoops(profile);
|
|
6344
6344
|
if (holes.length === 0) return ok(outerResult.value);
|
|
6345
|
-
const outerFace = _usingCtx$
|
|
6345
|
+
const outerFace = _usingCtx$19.u(outerResult.value);
|
|
6346
6346
|
const holeFaces = [];
|
|
6347
6347
|
const holeWires = [];
|
|
6348
6348
|
const disposeHoleFaces = () => {
|
|
@@ -6367,9 +6367,9 @@ function extendedProfileToFace(profile) {
|
|
|
6367
6367
|
disposeHoleFaces();
|
|
6368
6368
|
return ok(faceWithHoles);
|
|
6369
6369
|
} catch (_) {
|
|
6370
|
-
_usingCtx$
|
|
6370
|
+
_usingCtx$19.e = _;
|
|
6371
6371
|
} finally {
|
|
6372
|
-
_usingCtx$
|
|
6372
|
+
_usingCtx$19.d();
|
|
6373
6373
|
}
|
|
6374
6374
|
}
|
|
6375
6375
|
//#endregion
|
|
@@ -6691,7 +6691,7 @@ function profileToPolygon(profile, circleSegments = 32) {
|
|
|
6691
6691
|
//#region src/elementFns/beamFns.ts
|
|
6692
6692
|
function beamToSolid(spec) {
|
|
6693
6693
|
try {
|
|
6694
|
-
var _usingCtx$
|
|
6694
|
+
var _usingCtx$18 = _usingCtx();
|
|
6695
6695
|
if (spec.length <= 0) return err(specError("BEAM_ZERO_LENGTH", "Beam length must be positive"));
|
|
6696
6696
|
if (isExtendedProfile(spec.profile)) try {
|
|
6697
6697
|
var _usingCtx3 = _usingCtx();
|
|
@@ -6729,7 +6729,7 @@ function beamToSolid(spec) {
|
|
|
6729
6729
|
]);
|
|
6730
6730
|
const profileResult = polygon(profilePts);
|
|
6731
6731
|
if (!profileResult.ok) return err(fromBrepError(profileResult.error, "BEAM_PROFILE_FAILED", "Failed to create beam profile"));
|
|
6732
|
-
const profile = _usingCtx$
|
|
6732
|
+
const profile = _usingCtx$18.u(profileResult.value);
|
|
6733
6733
|
const solidResult = extrude(profile, [
|
|
6734
6734
|
spec.length,
|
|
6735
6735
|
0,
|
|
@@ -6743,16 +6743,16 @@ function beamToSolid(spec) {
|
|
|
6743
6743
|
}
|
|
6744
6744
|
return ok(solid);
|
|
6745
6745
|
} catch (_) {
|
|
6746
|
-
_usingCtx$
|
|
6746
|
+
_usingCtx$18.e = _;
|
|
6747
6747
|
} finally {
|
|
6748
|
-
_usingCtx$
|
|
6748
|
+
_usingCtx$18.d();
|
|
6749
6749
|
}
|
|
6750
6750
|
}
|
|
6751
6751
|
//#endregion
|
|
6752
6752
|
//#region src/elementFns/columnFns.ts
|
|
6753
6753
|
function columnToSolid(spec) {
|
|
6754
6754
|
try {
|
|
6755
|
-
var _usingCtx$
|
|
6755
|
+
var _usingCtx$17 = _usingCtx();
|
|
6756
6756
|
if (spec.height <= 0) return err(specError("COLUMN_ZERO_HEIGHT", "Column height must be positive"));
|
|
6757
6757
|
if (isExtendedProfile(spec.profile)) try {
|
|
6758
6758
|
var _usingCtx3 = _usingCtx();
|
|
@@ -6781,7 +6781,7 @@ function columnToSolid(spec) {
|
|
|
6781
6781
|
const profilePts = profilePtsResult.value;
|
|
6782
6782
|
const profileResult = polygon(profilePts);
|
|
6783
6783
|
if (!profileResult.ok) return err(fromBrepError(profileResult.error, "COLUMN_PROFILE_FAILED", "Failed to create column profile"));
|
|
6784
|
-
const profile = _usingCtx$
|
|
6784
|
+
const profile = _usingCtx$17.u(profileResult.value);
|
|
6785
6785
|
const solidResult = extrude(profile, [
|
|
6786
6786
|
0,
|
|
6787
6787
|
0,
|
|
@@ -6795,9 +6795,9 @@ function columnToSolid(spec) {
|
|
|
6795
6795
|
}
|
|
6796
6796
|
return ok(solid);
|
|
6797
6797
|
} catch (_) {
|
|
6798
|
-
_usingCtx$
|
|
6798
|
+
_usingCtx$17.e = _;
|
|
6799
6799
|
} finally {
|
|
6800
|
-
_usingCtx$
|
|
6800
|
+
_usingCtx$17.d();
|
|
6801
6801
|
}
|
|
6802
6802
|
}
|
|
6803
6803
|
//#endregion
|
|
@@ -6805,7 +6805,7 @@ function columnToSolid(spec) {
|
|
|
6805
6805
|
var EPSILON_MM = 1;
|
|
6806
6806
|
function openingToSolid(spec, wallThickness) {
|
|
6807
6807
|
try {
|
|
6808
|
-
var _usingCtx$
|
|
6808
|
+
var _usingCtx$16 = _usingCtx();
|
|
6809
6809
|
if (spec.width <= 0) return err(specError("OPENING_ZERO_WIDTH", "Opening width must be positive"));
|
|
6810
6810
|
if (spec.height <= 0) return err(specError("OPENING_ZERO_HEIGHT", "Opening height must be positive"));
|
|
6811
6811
|
if (wallThickness <= 0) return err(specError("OPENING_ZERO_WALL_THICKNESS", "Wall thickness must be positive"));
|
|
@@ -6837,7 +6837,7 @@ function openingToSolid(spec, wallThickness) {
|
|
|
6837
6837
|
]
|
|
6838
6838
|
]);
|
|
6839
6839
|
if (!profileResult.ok) return err(fromBrepError(profileResult.error, "OPENING_PROFILE_FAILED", "Failed to create opening profile"));
|
|
6840
|
-
const profile = _usingCtx$
|
|
6840
|
+
const profile = _usingCtx$16.u(profileResult.value);
|
|
6841
6841
|
const solidResult = extrude(profile, [
|
|
6842
6842
|
spec.width,
|
|
6843
6843
|
0,
|
|
@@ -6851,16 +6851,16 @@ function openingToSolid(spec, wallThickness) {
|
|
|
6851
6851
|
}
|
|
6852
6852
|
return ok(solid);
|
|
6853
6853
|
} catch (_) {
|
|
6854
|
-
_usingCtx$
|
|
6854
|
+
_usingCtx$16.e = _;
|
|
6855
6855
|
} finally {
|
|
6856
|
-
_usingCtx$
|
|
6856
|
+
_usingCtx$16.d();
|
|
6857
6857
|
}
|
|
6858
6858
|
}
|
|
6859
6859
|
//#endregion
|
|
6860
6860
|
//#region src/elementFns/slabOpeningFns.ts
|
|
6861
6861
|
function slabOpeningToSolid(spec, slabThickness) {
|
|
6862
6862
|
try {
|
|
6863
|
-
var _usingCtx$
|
|
6863
|
+
var _usingCtx$15 = _usingCtx();
|
|
6864
6864
|
if (spec.sizeX <= 0) return err(specError("SLAB_OPENING_ZERO_SIZE_X", "Slab opening sizeX must be positive"));
|
|
6865
6865
|
if (spec.sizeY <= 0) return err(specError("SLAB_OPENING_ZERO_SIZE_Y", "Slab opening sizeY must be positive"));
|
|
6866
6866
|
if (slabThickness <= 0) return err(specError("SLAB_OPENING_ZERO_SLAB_THICKNESS", "Slab thickness must be positive"));
|
|
@@ -6892,7 +6892,7 @@ function slabOpeningToSolid(spec, slabThickness) {
|
|
|
6892
6892
|
]
|
|
6893
6893
|
]);
|
|
6894
6894
|
if (!profileResult.ok) return err(fromBrepError(profileResult.error, "SLAB_OPENING_PROFILE_FAILED", "Failed to create slab opening profile"));
|
|
6895
|
-
const profile = _usingCtx$
|
|
6895
|
+
const profile = _usingCtx$15.u(profileResult.value);
|
|
6896
6896
|
const solidResult = extrude(profile, [
|
|
6897
6897
|
0,
|
|
6898
6898
|
0,
|
|
@@ -6906,16 +6906,16 @@ function slabOpeningToSolid(spec, slabThickness) {
|
|
|
6906
6906
|
}
|
|
6907
6907
|
return ok(solid);
|
|
6908
6908
|
} catch (_) {
|
|
6909
|
-
_usingCtx$
|
|
6909
|
+
_usingCtx$15.e = _;
|
|
6910
6910
|
} finally {
|
|
6911
|
-
_usingCtx$
|
|
6911
|
+
_usingCtx$15.d();
|
|
6912
6912
|
}
|
|
6913
6913
|
}
|
|
6914
6914
|
//#endregion
|
|
6915
6915
|
//#region src/elementFns/spaceFns.ts
|
|
6916
6916
|
function spaceToSolid(spec) {
|
|
6917
6917
|
try {
|
|
6918
|
-
var _usingCtx$
|
|
6918
|
+
var _usingCtx$14 = _usingCtx();
|
|
6919
6919
|
if (spec.length <= 0) return err(specError("SPACE_ZERO_LENGTH", "Space length must be positive"));
|
|
6920
6920
|
if (spec.width <= 0) return err(specError("SPACE_ZERO_WIDTH", "Space width must be positive"));
|
|
6921
6921
|
if (spec.height <= 0) return err(specError("SPACE_ZERO_HEIGHT", "Space height must be positive"));
|
|
@@ -6943,7 +6943,7 @@ function spaceToSolid(spec) {
|
|
|
6943
6943
|
]
|
|
6944
6944
|
]);
|
|
6945
6945
|
if (!profileResult.ok) return err(fromBrepError(profileResult.error, "SPACE_PROFILE_FAILED", "Failed to create space footprint"));
|
|
6946
|
-
const profile = _usingCtx$
|
|
6946
|
+
const profile = _usingCtx$14.u(profileResult.value);
|
|
6947
6947
|
const solidResult = extrude(profile, [
|
|
6948
6948
|
0,
|
|
6949
6949
|
0,
|
|
@@ -6957,9 +6957,9 @@ function spaceToSolid(spec) {
|
|
|
6957
6957
|
}
|
|
6958
6958
|
return ok(solid);
|
|
6959
6959
|
} catch (_) {
|
|
6960
|
-
_usingCtx$
|
|
6960
|
+
_usingCtx$14.e = _;
|
|
6961
6961
|
} finally {
|
|
6962
|
-
_usingCtx$
|
|
6962
|
+
_usingCtx$14.d();
|
|
6963
6963
|
}
|
|
6964
6964
|
}
|
|
6965
6965
|
//#endregion
|
|
@@ -6974,7 +6974,7 @@ function gate(solid, code) {
|
|
|
6974
6974
|
}
|
|
6975
6975
|
function flatRoof(spec) {
|
|
6976
6976
|
try {
|
|
6977
|
-
var _usingCtx$
|
|
6977
|
+
var _usingCtx$13 = _usingCtx();
|
|
6978
6978
|
const { length, width, thickness } = spec;
|
|
6979
6979
|
const face = polygon([
|
|
6980
6980
|
[
|
|
@@ -6999,7 +6999,7 @@ function flatRoof(spec) {
|
|
|
6999
6999
|
]
|
|
7000
7000
|
]);
|
|
7001
7001
|
if (!face.ok) return err(fromBrepError(face.error, "ROOF_PROFILE_FAILED", "Failed to create roof profile"));
|
|
7002
|
-
const profile = _usingCtx$
|
|
7002
|
+
const profile = _usingCtx$13.u(face.value);
|
|
7003
7003
|
const solid = extrude(profile, [
|
|
7004
7004
|
0,
|
|
7005
7005
|
0,
|
|
@@ -7008,9 +7008,9 @@ function flatRoof(spec) {
|
|
|
7008
7008
|
if (!solid.ok) return err(fromBrepError(solid.error, "ROOF_EXTRUDE_FAILED", "Failed to extrude roof profile"));
|
|
7009
7009
|
return gate(solid.value, "ROOF_INVALID_SOLID");
|
|
7010
7010
|
} catch (_) {
|
|
7011
|
-
_usingCtx$
|
|
7011
|
+
_usingCtx$13.e = _;
|
|
7012
7012
|
} finally {
|
|
7013
|
-
_usingCtx$
|
|
7013
|
+
_usingCtx$13.d();
|
|
7014
7014
|
}
|
|
7015
7015
|
}
|
|
7016
7016
|
function shedRoof(spec, pitch) {
|
|
@@ -7206,7 +7206,7 @@ function roofToSolid(spec) {
|
|
|
7206
7206
|
//#region src/elementFns/curtainWallFns.ts
|
|
7207
7207
|
function boxSolid(sizeX, sizeY, sizeZ) {
|
|
7208
7208
|
try {
|
|
7209
|
-
var _usingCtx$
|
|
7209
|
+
var _usingCtx$12 = _usingCtx();
|
|
7210
7210
|
const profileResult = polygon([
|
|
7211
7211
|
[
|
|
7212
7212
|
0,
|
|
@@ -7230,7 +7230,7 @@ function boxSolid(sizeX, sizeY, sizeZ) {
|
|
|
7230
7230
|
]
|
|
7231
7231
|
]);
|
|
7232
7232
|
if (!profileResult.ok) return err(fromBrepError(profileResult.error, "CURTAIN_WALL_PROFILE_FAILED", "Failed to create component profile"));
|
|
7233
|
-
const profile = _usingCtx$
|
|
7233
|
+
const profile = _usingCtx$12.u(profileResult.value);
|
|
7234
7234
|
const solidResult = extrude(profile, [
|
|
7235
7235
|
0,
|
|
7236
7236
|
0,
|
|
@@ -7244,9 +7244,9 @@ function boxSolid(sizeX, sizeY, sizeZ) {
|
|
|
7244
7244
|
}
|
|
7245
7245
|
return ok(solid);
|
|
7246
7246
|
} catch (_) {
|
|
7247
|
-
_usingCtx$
|
|
7247
|
+
_usingCtx$12.e = _;
|
|
7248
7248
|
} finally {
|
|
7249
|
-
_usingCtx$
|
|
7249
|
+
_usingCtx$12.d();
|
|
7250
7250
|
}
|
|
7251
7251
|
}
|
|
7252
7252
|
function disposeComponents(components) {
|
|
@@ -7345,7 +7345,7 @@ function curtainWallToGrid(spec) {
|
|
|
7345
7345
|
//#region src/elementFns/foundationFns.ts
|
|
7346
7346
|
function footingToSolid(spec) {
|
|
7347
7347
|
try {
|
|
7348
|
-
var _usingCtx$
|
|
7348
|
+
var _usingCtx$11 = _usingCtx();
|
|
7349
7349
|
if (spec.length <= 0) return err(specError("FOOTING_ZERO_LENGTH", "Footing length must be positive"));
|
|
7350
7350
|
if (spec.width <= 0) return err(specError("FOOTING_ZERO_WIDTH", "Footing width must be positive"));
|
|
7351
7351
|
if (spec.thickness <= 0) return err(specError("FOOTING_ZERO_THICKNESS", "Footing thickness must be positive"));
|
|
@@ -7373,7 +7373,7 @@ function footingToSolid(spec) {
|
|
|
7373
7373
|
]
|
|
7374
7374
|
]);
|
|
7375
7375
|
if (!profileResult.ok) return err(fromBrepError(profileResult.error, "FOOTING_PROFILE_FAILED", "Failed to create footing profile"));
|
|
7376
|
-
const profile = _usingCtx$
|
|
7376
|
+
const profile = _usingCtx$11.u(profileResult.value);
|
|
7377
7377
|
const solidResult = extrude(profile, [
|
|
7378
7378
|
0,
|
|
7379
7379
|
0,
|
|
@@ -7387,9 +7387,9 @@ function footingToSolid(spec) {
|
|
|
7387
7387
|
}
|
|
7388
7388
|
return ok(solid);
|
|
7389
7389
|
} catch (_) {
|
|
7390
|
-
_usingCtx$
|
|
7390
|
+
_usingCtx$11.e = _;
|
|
7391
7391
|
} finally {
|
|
7392
|
-
_usingCtx$
|
|
7392
|
+
_usingCtx$11.d();
|
|
7393
7393
|
}
|
|
7394
7394
|
}
|
|
7395
7395
|
function pileToSolid(spec) {
|
|
@@ -7446,7 +7446,7 @@ function pileToSolid(spec) {
|
|
|
7446
7446
|
//#region src/elementFns/railingFns.ts
|
|
7447
7447
|
function panelRailing(spec) {
|
|
7448
7448
|
try {
|
|
7449
|
-
var _usingCtx$
|
|
7449
|
+
var _usingCtx$10 = _usingCtx();
|
|
7450
7450
|
const { length, height, thickness } = spec;
|
|
7451
7451
|
const profileResult = polygon([
|
|
7452
7452
|
[
|
|
@@ -7471,7 +7471,7 @@ function panelRailing(spec) {
|
|
|
7471
7471
|
]
|
|
7472
7472
|
]);
|
|
7473
7473
|
if (!profileResult.ok) return err(fromBrepError(profileResult.error, "RAILING_PROFILE_FAILED", "Failed to create railing profile"));
|
|
7474
|
-
const profile = _usingCtx$
|
|
7474
|
+
const profile = _usingCtx$10.u(profileResult.value);
|
|
7475
7475
|
const solidResult = extrude(profile, [
|
|
7476
7476
|
length,
|
|
7477
7477
|
0,
|
|
@@ -7485,9 +7485,9 @@ function panelRailing(spec) {
|
|
|
7485
7485
|
}
|
|
7486
7486
|
return ok(solid);
|
|
7487
7487
|
} catch (_) {
|
|
7488
|
-
_usingCtx$
|
|
7488
|
+
_usingCtx$10.e = _;
|
|
7489
7489
|
} finally {
|
|
7490
|
-
_usingCtx$
|
|
7490
|
+
_usingCtx$10.d();
|
|
7491
7491
|
}
|
|
7492
7492
|
}
|
|
7493
7493
|
function postedRailing(spec) {
|
|
@@ -7550,7 +7550,7 @@ function railingToSolid(spec) {
|
|
|
7550
7550
|
//#region src/elementFns/coveringFns.ts
|
|
7551
7551
|
function coveringToSolid(spec) {
|
|
7552
7552
|
try {
|
|
7553
|
-
var _usingCtx$
|
|
7553
|
+
var _usingCtx$9 = _usingCtx();
|
|
7554
7554
|
if (spec.length <= 0) return err(specError("COVERING_ZERO_LENGTH", "Covering length must be positive"));
|
|
7555
7555
|
if (spec.width <= 0) return err(specError("COVERING_ZERO_WIDTH", "Covering width must be positive"));
|
|
7556
7556
|
if (spec.thickness <= 0) return err(specError("COVERING_ZERO_THICKNESS", "Covering thickness must be positive"));
|
|
@@ -7578,7 +7578,7 @@ function coveringToSolid(spec) {
|
|
|
7578
7578
|
]
|
|
7579
7579
|
]);
|
|
7580
7580
|
if (!profileResult.ok) return err(fromBrepError(profileResult.error, "COVERING_PROFILE_FAILED", "Failed to create covering profile"));
|
|
7581
|
-
const profile = _usingCtx$
|
|
7581
|
+
const profile = _usingCtx$9.u(profileResult.value);
|
|
7582
7582
|
const solidResult = extrude(profile, [
|
|
7583
7583
|
0,
|
|
7584
7584
|
0,
|
|
@@ -7592,9 +7592,9 @@ function coveringToSolid(spec) {
|
|
|
7592
7592
|
}
|
|
7593
7593
|
return ok(solid);
|
|
7594
7594
|
} catch (_) {
|
|
7595
|
-
_usingCtx$
|
|
7595
|
+
_usingCtx$9.e = _;
|
|
7596
7596
|
} finally {
|
|
7597
|
-
_usingCtx$
|
|
7597
|
+
_usingCtx$9.d();
|
|
7598
7598
|
}
|
|
7599
7599
|
}
|
|
7600
7600
|
//#endregion
|
|
@@ -7782,6 +7782,31 @@ function measureProductBodyMaterial(solids) {
|
|
|
7782
7782
|
return measured;
|
|
7783
7783
|
});
|
|
7784
7784
|
}
|
|
7785
|
+
/** Borrow all items and query their tight bounds in their existing coordinates. */
|
|
7786
|
+
function productBodyBounds(solids) {
|
|
7787
|
+
const items = validateItems(solids, "productBodyBounds");
|
|
7788
|
+
if (!items.ok) return items;
|
|
7789
|
+
return ownedOperation("productBodyBounds", (scope) => {
|
|
7790
|
+
let bounds;
|
|
7791
|
+
for (const [itemIndex, solid] of items.value.entries()) {
|
|
7792
|
+
scope.itemIndex = itemIndex;
|
|
7793
|
+
const ready = before("bounds", itemIndex);
|
|
7794
|
+
if (!ready.ok) return ready;
|
|
7795
|
+
const current = (productBodyTestHooks()?.bounds ?? getBounds)(solid);
|
|
7796
|
+
if (!Object.values(current).every(Number.isFinite) || current.xMin > current.xMax || current.yMin > current.yMax || current.zMin > current.zMax) return err(bodyError("productBodyBounds", "BODY_INVALID_BOUNDS", "Expected finite ordered bounds", current, itemIndex));
|
|
7797
|
+
bounds = bounds === void 0 ? { ...current } : {
|
|
7798
|
+
xMin: Math.min(bounds.xMin, current.xMin),
|
|
7799
|
+
xMax: Math.max(bounds.xMax, current.xMax),
|
|
7800
|
+
yMin: Math.min(bounds.yMin, current.yMin),
|
|
7801
|
+
yMax: Math.max(bounds.yMax, current.yMax),
|
|
7802
|
+
zMin: Math.min(bounds.zMin, current.zMin),
|
|
7803
|
+
zMax: Math.max(bounds.zMax, current.zMax)
|
|
7804
|
+
};
|
|
7805
|
+
}
|
|
7806
|
+
if (bounds === void 0) throw new Error("Validated Body produced no bounds");
|
|
7807
|
+
return ok(Object.freeze({ bounds: Object.freeze(bounds) }));
|
|
7808
|
+
});
|
|
7809
|
+
}
|
|
7785
7810
|
//#endregion
|
|
7786
7811
|
//#region src/model/bimModel.ts
|
|
7787
7812
|
function exactWallBodyImmutable() {
|
|
@@ -8337,18 +8362,18 @@ var BimModel = class {
|
|
|
8337
8362
|
}
|
|
8338
8363
|
#cutWallGeometry(wall, openingSpec) {
|
|
8339
8364
|
try {
|
|
8340
|
-
var _usingCtx$
|
|
8365
|
+
var _usingCtx$8 = _usingCtx();
|
|
8341
8366
|
if (wall.geometry.kind === "EXACT") return exactWallBodyImmutable();
|
|
8342
8367
|
const toolResult = openingToSolid(openingSpec, wall.spec.thickness);
|
|
8343
8368
|
if (!toolResult.ok) return err(toolResult.error);
|
|
8344
|
-
const tool = _usingCtx$
|
|
8369
|
+
const tool = _usingCtx$8.u(toolResult.value);
|
|
8345
8370
|
const cutResult = cut(wall.geometry.solid, tool);
|
|
8346
8371
|
if (!cutResult.ok) return err(fromBrepError(cutResult.error, "WALL_CUT_FAILED", "Boolean cut of wall with opening failed"));
|
|
8347
8372
|
return ok(cutResult.value);
|
|
8348
8373
|
} catch (_) {
|
|
8349
|
-
_usingCtx$
|
|
8374
|
+
_usingCtx$8.e = _;
|
|
8350
8375
|
} finally {
|
|
8351
|
-
_usingCtx$
|
|
8376
|
+
_usingCtx$8.d();
|
|
8352
8377
|
}
|
|
8353
8378
|
}
|
|
8354
8379
|
#replaceWallGeometry(wall, newGeometry) {
|
|
@@ -8963,7 +8988,7 @@ function buildSilhouette$1(numberOfRisers, riserHeight, treadLength) {
|
|
|
8963
8988
|
}
|
|
8964
8989
|
function stairFlightToSolid(spec) {
|
|
8965
8990
|
try {
|
|
8966
|
-
var _usingCtx$
|
|
8991
|
+
var _usingCtx$7 = _usingCtx();
|
|
8967
8992
|
if (spec.width <= 0) return err(specError("STAIR_FLIGHT_ZERO_WIDTH", "Stair flight width must be positive"));
|
|
8968
8993
|
if (spec.riserHeight <= 0) return err(specError("STAIR_FLIGHT_ZERO_RISER", "Stair flight riserHeight must be positive"));
|
|
8969
8994
|
if (spec.treadLength <= 0) return err(specError("STAIR_FLIGHT_ZERO_TREAD", "Stair flight treadLength must be positive"));
|
|
@@ -8971,7 +8996,7 @@ function stairFlightToSolid(spec) {
|
|
|
8971
8996
|
const silhouette = buildSilhouette$1(spec.numberOfRisers, spec.riserHeight, spec.treadLength);
|
|
8972
8997
|
const profileResult = polygon(silhouette);
|
|
8973
8998
|
if (!profileResult.ok) return err(fromBrepError(profileResult.error, "STAIR_FLIGHT_PROFILE_FAILED", "Failed to create stair flight silhouette profile"));
|
|
8974
|
-
const profile = _usingCtx$
|
|
8999
|
+
const profile = _usingCtx$7.u(profileResult.value);
|
|
8975
9000
|
const solidResult = extrude(profile, [
|
|
8976
9001
|
0,
|
|
8977
9002
|
spec.width,
|
|
@@ -8988,9 +9013,9 @@ function stairFlightToSolid(spec) {
|
|
|
8988
9013
|
geometrySimplified: false
|
|
8989
9014
|
});
|
|
8990
9015
|
} catch (_) {
|
|
8991
|
-
_usingCtx$
|
|
9016
|
+
_usingCtx$7.e = _;
|
|
8992
9017
|
} finally {
|
|
8993
|
-
_usingCtx$
|
|
9018
|
+
_usingCtx$7.d();
|
|
8994
9019
|
}
|
|
8995
9020
|
}
|
|
8996
9021
|
//#endregion
|
|
@@ -9021,7 +9046,7 @@ function buildSilhouette(length, rise, thickness) {
|
|
|
9021
9046
|
}
|
|
9022
9047
|
function rampFlightToSolid(spec) {
|
|
9023
9048
|
try {
|
|
9024
|
-
var _usingCtx$
|
|
9049
|
+
var _usingCtx$6 = _usingCtx();
|
|
9025
9050
|
if (spec.width <= 0) return err(specError("RAMP_FLIGHT_ZERO_WIDTH", "Ramp flight width must be positive"));
|
|
9026
9051
|
if (spec.length <= 0) return err(specError("RAMP_FLIGHT_ZERO_LENGTH", "Ramp flight length must be positive"));
|
|
9027
9052
|
if (spec.slope <= 0) return err(specError("RAMP_FLIGHT_ZERO_SLOPE", "Ramp flight slope must be positive"));
|
|
@@ -9030,7 +9055,7 @@ function rampFlightToSolid(spec) {
|
|
|
9030
9055
|
const silhouette = buildSilhouette(spec.length, rise, spec.thickness);
|
|
9031
9056
|
const profileResult = polygon(silhouette);
|
|
9032
9057
|
if (!profileResult.ok) return err(fromBrepError(profileResult.error, "RAMP_FLIGHT_PROFILE_FAILED", "Failed to create ramp flight silhouette profile"));
|
|
9033
|
-
const profile = _usingCtx$
|
|
9058
|
+
const profile = _usingCtx$6.u(profileResult.value);
|
|
9034
9059
|
const solidResult = extrude(profile, [
|
|
9035
9060
|
0,
|
|
9036
9061
|
spec.width,
|
|
@@ -9047,9 +9072,9 @@ function rampFlightToSolid(spec) {
|
|
|
9047
9072
|
geometrySimplified: true
|
|
9048
9073
|
});
|
|
9049
9074
|
} catch (_) {
|
|
9050
|
-
_usingCtx$
|
|
9075
|
+
_usingCtx$6.e = _;
|
|
9051
9076
|
} finally {
|
|
9052
|
-
_usingCtx$
|
|
9077
|
+
_usingCtx$6.d();
|
|
9053
9078
|
}
|
|
9054
9079
|
}
|
|
9055
9080
|
//#endregion
|
|
@@ -9192,22 +9217,22 @@ function placedSolids(el, options = {}) {
|
|
|
9192
9217
|
case "STAIR": {
|
|
9193
9218
|
const out = [];
|
|
9194
9219
|
for (const flight of el.spec.flights) try {
|
|
9195
|
-
var _usingCtx$
|
|
9220
|
+
var _usingCtx$5 = _usingCtx();
|
|
9196
9221
|
const built = stairFlightToSolid(flight);
|
|
9197
9222
|
if (!built.ok) {
|
|
9198
9223
|
disposeAll$1(out);
|
|
9199
9224
|
return err(built.error);
|
|
9200
9225
|
}
|
|
9201
|
-
const placed = placeWithinParent(_usingCtx$
|
|
9226
|
+
const placed = placeWithinParent(_usingCtx$5.u(built.value.solid), flight, parentFrame);
|
|
9202
9227
|
if (!placed.ok) {
|
|
9203
9228
|
disposeAll$1(out);
|
|
9204
9229
|
return placed;
|
|
9205
9230
|
}
|
|
9206
9231
|
out.push(placed.value);
|
|
9207
9232
|
} catch (_) {
|
|
9208
|
-
_usingCtx$
|
|
9233
|
+
_usingCtx$5.e = _;
|
|
9209
9234
|
} finally {
|
|
9210
|
-
_usingCtx$
|
|
9235
|
+
_usingCtx$5.d();
|
|
9211
9236
|
}
|
|
9212
9237
|
return ok(out);
|
|
9213
9238
|
}
|
|
@@ -9717,11 +9742,21 @@ function writeHeader(w, meta) {
|
|
|
9717
9742
|
WorldCoordinateSystem: w.ref(writeAxis2Placement3D(w)),
|
|
9718
9743
|
TrueNorth: null
|
|
9719
9744
|
});
|
|
9745
|
+
return {
|
|
9746
|
+
ownerHistoryId,
|
|
9747
|
+
geomContextId,
|
|
9748
|
+
geomSubContextId: writeGeometricSubContext(w, geomContextId, "Body"),
|
|
9749
|
+
unitAssignmentId,
|
|
9750
|
+
lengthUnitId
|
|
9751
|
+
};
|
|
9752
|
+
}
|
|
9753
|
+
/** Separates display Body geometry from non-subtractive Reference geometry. */
|
|
9754
|
+
function writeGeometricSubContext(w, geomContextId, identifier) {
|
|
9720
9755
|
const geomSubContextId = w.nextId();
|
|
9721
9756
|
w.writeLine({
|
|
9722
9757
|
expressID: geomSubContextId,
|
|
9723
9758
|
type: WebIFC.IFCGEOMETRICREPRESENTATIONSUBCONTEXT,
|
|
9724
|
-
ContextIdentifier: w.mkType(WebIFC.IFCLABEL,
|
|
9759
|
+
ContextIdentifier: w.mkType(WebIFC.IFCLABEL, identifier),
|
|
9725
9760
|
ContextType: w.mkType(WebIFC.IFCLABEL, "Model"),
|
|
9726
9761
|
CoordinateSpaceDimension: null,
|
|
9727
9762
|
Precision: null,
|
|
@@ -9735,13 +9770,7 @@ function writeHeader(w, meta) {
|
|
|
9735
9770
|
},
|
|
9736
9771
|
UserDefinedTargetView: null
|
|
9737
9772
|
});
|
|
9738
|
-
return
|
|
9739
|
-
ownerHistoryId,
|
|
9740
|
-
geomContextId,
|
|
9741
|
-
geomSubContextId,
|
|
9742
|
-
unitAssignmentId,
|
|
9743
|
-
lengthUnitId
|
|
9744
|
-
};
|
|
9773
|
+
return geomSubContextId;
|
|
9745
9774
|
}
|
|
9746
9775
|
/**
|
|
9747
9776
|
* Writes IfcProjectedCRS + IfcMapConversion georeferencing the model context
|
|
@@ -10149,7 +10178,7 @@ function writePreparedTessellationBody(w, items, geomSubContextId) {
|
|
|
10149
10178
|
bodyItemIds
|
|
10150
10179
|
};
|
|
10151
10180
|
}
|
|
10152
|
-
function
|
|
10181
|
+
function writeProductBodyGeometry(w, placement, items, geomSubContextId, parentPlacementId) {
|
|
10153
10182
|
const placement3DId = writeAxis2Placement3D(w, [
|
|
10154
10183
|
toIfcLengthM(placement.origin[0]),
|
|
10155
10184
|
toIfcLengthM(placement.origin[1]),
|
|
@@ -10195,47 +10224,6 @@ function writePreparedTessellationItem(w, prepared) {
|
|
|
10195
10224
|
});
|
|
10196
10225
|
return faceSetId;
|
|
10197
10226
|
}
|
|
10198
|
-
/**
|
|
10199
|
-
* Builds a wall 'Axis' IfcShapeRepresentation: an IfcPolyline from (0,0) to
|
|
10200
|
-
* (lengthM, 0) in the wall's local XY plane, wrapped in an IfcShapeRepresentation
|
|
10201
|
-
* with RepresentationIdentifier='Axis', RepresentationType='Curve2D'. Returns
|
|
10202
|
-
* the IfcShapeRepresentation express ID so callers can add it alongside the Body
|
|
10203
|
-
* representation in an IfcProductDefinitionShape.
|
|
10204
|
-
*
|
|
10205
|
-
* wallLengthMm is the wall length in mm (brepjs native units); it is converted
|
|
10206
|
-
* to metres for IFC.
|
|
10207
|
-
*/
|
|
10208
|
-
function writeWallAxisRepresentation(w, wallLengthMm, geomSubContextId) {
|
|
10209
|
-
const lengthM = toIfcLengthM(wallLengthMm);
|
|
10210
|
-
const startId = w.nextId();
|
|
10211
|
-
w.writeLine({
|
|
10212
|
-
expressID: startId,
|
|
10213
|
-
type: WebIFC.IFCCARTESIANPOINT,
|
|
10214
|
-
Coordinates: [w.mkType(WebIFC.IFCLENGTHMEASURE, 0), w.mkType(WebIFC.IFCLENGTHMEASURE, 0)]
|
|
10215
|
-
});
|
|
10216
|
-
const endId = w.nextId();
|
|
10217
|
-
w.writeLine({
|
|
10218
|
-
expressID: endId,
|
|
10219
|
-
type: WebIFC.IFCCARTESIANPOINT,
|
|
10220
|
-
Coordinates: [w.mkType(WebIFC.IFCLENGTHMEASURE, lengthM), w.mkType(WebIFC.IFCLENGTHMEASURE, 0)]
|
|
10221
|
-
});
|
|
10222
|
-
const polylineId = w.nextId();
|
|
10223
|
-
w.writeLine({
|
|
10224
|
-
expressID: polylineId,
|
|
10225
|
-
type: WebIFC.IFCPOLYLINE,
|
|
10226
|
-
Points: [w.ref(startId), w.ref(endId)]
|
|
10227
|
-
});
|
|
10228
|
-
const shapeRepId = w.nextId();
|
|
10229
|
-
w.writeLine({
|
|
10230
|
-
expressID: shapeRepId,
|
|
10231
|
-
type: WebIFC.IFCSHAPEREPRESENTATION,
|
|
10232
|
-
ContextOfItems: w.ref(geomSubContextId),
|
|
10233
|
-
RepresentationIdentifier: w.mkType(WebIFC.IFCLABEL, "Axis"),
|
|
10234
|
-
RepresentationType: w.mkType(WebIFC.IFCLABEL, "Curve2D"),
|
|
10235
|
-
Items: [w.ref(polylineId)]
|
|
10236
|
-
});
|
|
10237
|
-
return shapeRepId;
|
|
10238
|
-
}
|
|
10239
10227
|
function writeFacetedBrepFallback(w, geomSubContextId, reason) {
|
|
10240
10228
|
const originId = w.nextId();
|
|
10241
10229
|
w.writeLine({
|
|
@@ -10566,81 +10554,6 @@ function writePolyline(w, points) {
|
|
|
10566
10554
|
}
|
|
10567
10555
|
//#endregion
|
|
10568
10556
|
//#region src/ifc-writer/geometryWriter.ts
|
|
10569
|
-
function writeWallGeometry(w, spec, geomSubContextId, parentPlacementId) {
|
|
10570
|
-
const placement3DId = writeAxis2Placement3D(w, spec.origin.map(toIfcLengthM), spec.axisZ, spec.axisX);
|
|
10571
|
-
const localPlacementId = w.nextId();
|
|
10572
|
-
w.writeLine({
|
|
10573
|
-
expressID: localPlacementId,
|
|
10574
|
-
type: WebIFC.IFCLOCALPLACEMENT,
|
|
10575
|
-
PlacementRelTo: parentPlacementId !== null ? w.ref(parentPlacementId) : null,
|
|
10576
|
-
RelativePlacement: w.ref(placement3DId)
|
|
10577
|
-
});
|
|
10578
|
-
const thicknessM = toIfcLengthM(spec.thickness);
|
|
10579
|
-
const heightM = toIfcLengthM(spec.height);
|
|
10580
|
-
const lengthM = toIfcLengthM(spec.length);
|
|
10581
|
-
const profileId = w.nextId();
|
|
10582
|
-
w.writeLine({
|
|
10583
|
-
expressID: profileId,
|
|
10584
|
-
type: WebIFC.IFCRECTANGLEPROFILEDEF,
|
|
10585
|
-
ProfileType: {
|
|
10586
|
-
type: 3,
|
|
10587
|
-
value: "AREA"
|
|
10588
|
-
},
|
|
10589
|
-
ProfileName: null,
|
|
10590
|
-
Position: w.ref(writeAxis2Placement2D$1(w, [thicknessM / 2, heightM / 2])),
|
|
10591
|
-
XDim: w.mkType(WebIFC.IFCPOSITIVELENGTHMEASURE, thicknessM),
|
|
10592
|
-
YDim: w.mkType(WebIFC.IFCPOSITIVELENGTHMEASURE, heightM)
|
|
10593
|
-
});
|
|
10594
|
-
const extrusionPosId = writeAxis2Placement3D(w, [
|
|
10595
|
-
0,
|
|
10596
|
-
0,
|
|
10597
|
-
0
|
|
10598
|
-
], [
|
|
10599
|
-
1,
|
|
10600
|
-
0,
|
|
10601
|
-
0
|
|
10602
|
-
], [
|
|
10603
|
-
0,
|
|
10604
|
-
1,
|
|
10605
|
-
0
|
|
10606
|
-
]);
|
|
10607
|
-
const extrusionDirId = writeDirection(w, [
|
|
10608
|
-
0,
|
|
10609
|
-
0,
|
|
10610
|
-
1
|
|
10611
|
-
]);
|
|
10612
|
-
const extrusionId = w.nextId();
|
|
10613
|
-
w.writeLine({
|
|
10614
|
-
expressID: extrusionId,
|
|
10615
|
-
type: WebIFC.IFCEXTRUDEDAREASOLID,
|
|
10616
|
-
SweptArea: w.ref(profileId),
|
|
10617
|
-
Position: w.ref(extrusionPosId),
|
|
10618
|
-
ExtrudedDirection: w.ref(extrusionDirId),
|
|
10619
|
-
Depth: w.mkType(WebIFC.IFCPOSITIVELENGTHMEASURE, lengthM)
|
|
10620
|
-
});
|
|
10621
|
-
const shapeRepId = w.nextId();
|
|
10622
|
-
w.writeLine({
|
|
10623
|
-
expressID: shapeRepId,
|
|
10624
|
-
type: WebIFC.IFCSHAPEREPRESENTATION,
|
|
10625
|
-
ContextOfItems: w.ref(geomSubContextId),
|
|
10626
|
-
RepresentationIdentifier: w.mkType(WebIFC.IFCLABEL, "Body"),
|
|
10627
|
-
RepresentationType: w.mkType(WebIFC.IFCLABEL, "SweptSolid"),
|
|
10628
|
-
Items: [w.ref(extrusionId)]
|
|
10629
|
-
});
|
|
10630
|
-
const axisRepId = writeWallAxisRepresentation(w, spec.length, geomSubContextId);
|
|
10631
|
-
const productDefinitionShapeId = w.nextId();
|
|
10632
|
-
w.writeLine({
|
|
10633
|
-
expressID: productDefinitionShapeId,
|
|
10634
|
-
type: WebIFC.IFCPRODUCTDEFINITIONSHAPE,
|
|
10635
|
-
Name: null,
|
|
10636
|
-
Description: null,
|
|
10637
|
-
Representations: [w.ref(axisRepId), w.ref(shapeRepId)]
|
|
10638
|
-
});
|
|
10639
|
-
return {
|
|
10640
|
-
localPlacementId,
|
|
10641
|
-
productDefinitionShapeId
|
|
10642
|
-
};
|
|
10643
|
-
}
|
|
10644
10557
|
function writeSlabGeometry(w, spec, geomSubContextId, parentPlacementId) {
|
|
10645
10558
|
const placement3DId = writeAxis2Placement3D(w, spec.origin.map(toIfcLengthM), spec.axisZ, spec.axisX);
|
|
10646
10559
|
const localPlacementId = w.nextId();
|
|
@@ -11691,22 +11604,22 @@ function writeStairAssembly(w, spec, stairKey, assemblyGuid, ownerHistoryId, geo
|
|
|
11691
11604
|
const flightExpressIds = [];
|
|
11692
11605
|
let geometrySimplified = false;
|
|
11693
11606
|
for (const [i, flight] of spec.flights.entries()) try {
|
|
11694
|
-
var _usingCtx$
|
|
11607
|
+
var _usingCtx$4 = _usingCtx();
|
|
11695
11608
|
const built = stairFlightToSolid(flight);
|
|
11696
11609
|
if (!built.ok) return {
|
|
11697
11610
|
ok: false,
|
|
11698
11611
|
error: built.error
|
|
11699
11612
|
};
|
|
11700
|
-
const flightSolid = _usingCtx$
|
|
11613
|
+
const flightSolid = _usingCtx$4.u(built.value.solid);
|
|
11701
11614
|
const flightPlacementId = writeLocalPlacement(w, flight.origin, flight.axisZ, flight.axisX, stairPlacementId);
|
|
11702
11615
|
const tess = writeTessellation(w, flightSolid, geomSubContextId, flightPlacementId);
|
|
11703
11616
|
if (tess.usedFallback) geometrySimplified = true;
|
|
11704
11617
|
const flightExpressId = writeStairFlightEntity(w, deriveIfcGuidSync(`elem:STAIR_FLIGHT:${stairKey}:${i}`), `${stairName} Flight ${i + 1}`, flight, ownerHistoryId, flightPlacementId, tess.productDefinitionShapeId);
|
|
11705
11618
|
flightExpressIds.push(flightExpressId);
|
|
11706
11619
|
} catch (_) {
|
|
11707
|
-
_usingCtx$
|
|
11620
|
+
_usingCtx$4.e = _;
|
|
11708
11621
|
} finally {
|
|
11709
|
-
_usingCtx$
|
|
11622
|
+
_usingCtx$4.d();
|
|
11710
11623
|
}
|
|
11711
11624
|
writeRelAggregates(w, deriveIfcGuidSync(`rel:AGGREGATES:STAIR:${stairKey}`), ownerHistoryId, assemblyExpressId, flightExpressIds);
|
|
11712
11625
|
writeAssemblyType(w, WebIFC.IFCSTAIRTYPE, "Stair Type", deriveIfcGuidSync(`type:STAIR:${stairKey}`), deriveIfcGuidSync(`rel-type:STAIR:${stairKey}`), predefinedType, ownerHistoryId, [assemblyExpressId]);
|
|
@@ -11783,104 +11696,6 @@ function writeRampAssembly(w, spec, rampKey, assemblyGuid, ownerHistoryId, geomS
|
|
|
11783
11696
|
}
|
|
11784
11697
|
//#endregion
|
|
11785
11698
|
//#region src/ifc-writer/railingWriter.ts
|
|
11786
|
-
function writeRailingGeometry(w, spec, solid, geomSubContextId, parentPlacementId) {
|
|
11787
|
-
const placement3DId = writeAxis2Placement3D(w, spec.origin.map(toIfcLengthM), spec.axisZ, spec.axisX);
|
|
11788
|
-
const localPlacementId = w.nextId();
|
|
11789
|
-
w.writeLine({
|
|
11790
|
-
expressID: localPlacementId,
|
|
11791
|
-
type: WebIFC.IFCLOCALPLACEMENT,
|
|
11792
|
-
PlacementRelTo: parentPlacementId !== null ? w.ref(parentPlacementId) : null,
|
|
11793
|
-
RelativePlacement: w.ref(placement3DId)
|
|
11794
|
-
});
|
|
11795
|
-
if (spec.infill === "POSTED") {
|
|
11796
|
-
const tess = writeTessellation(w, solid, geomSubContextId, localPlacementId);
|
|
11797
|
-
return {
|
|
11798
|
-
localPlacementId,
|
|
11799
|
-
productDefinitionShapeId: tess.productDefinitionShapeId,
|
|
11800
|
-
bodyItemId: null,
|
|
11801
|
-
usedFallback: tess.usedFallback
|
|
11802
|
-
};
|
|
11803
|
-
}
|
|
11804
|
-
const thicknessM = toIfcLengthM(spec.thickness);
|
|
11805
|
-
const heightM = toIfcLengthM(spec.height);
|
|
11806
|
-
const lengthM = toIfcLengthM(spec.length);
|
|
11807
|
-
const profileOriginId = w.nextId();
|
|
11808
|
-
w.writeLine({
|
|
11809
|
-
expressID: profileOriginId,
|
|
11810
|
-
type: WebIFC.IFCCARTESIANPOINT,
|
|
11811
|
-
Coordinates: [w.mkType(WebIFC.IFCLENGTHMEASURE, thicknessM / 2), w.mkType(WebIFC.IFCLENGTHMEASURE, heightM / 2)]
|
|
11812
|
-
});
|
|
11813
|
-
const profilePosId = w.nextId();
|
|
11814
|
-
w.writeLine({
|
|
11815
|
-
expressID: profilePosId,
|
|
11816
|
-
type: WebIFC.IFCAXIS2PLACEMENT2D,
|
|
11817
|
-
Location: w.ref(profileOriginId),
|
|
11818
|
-
RefDirection: null
|
|
11819
|
-
});
|
|
11820
|
-
const profileId = w.nextId();
|
|
11821
|
-
w.writeLine({
|
|
11822
|
-
expressID: profileId,
|
|
11823
|
-
type: WebIFC.IFCRECTANGLEPROFILEDEF,
|
|
11824
|
-
ProfileType: {
|
|
11825
|
-
type: 3,
|
|
11826
|
-
value: "AREA"
|
|
11827
|
-
},
|
|
11828
|
-
ProfileName: null,
|
|
11829
|
-
Position: w.ref(profilePosId),
|
|
11830
|
-
XDim: w.mkType(WebIFC.IFCPOSITIVELENGTHMEASURE, thicknessM),
|
|
11831
|
-
YDim: w.mkType(WebIFC.IFCPOSITIVELENGTHMEASURE, heightM)
|
|
11832
|
-
});
|
|
11833
|
-
const extrusionPosId = writeAxis2Placement3D(w, [
|
|
11834
|
-
0,
|
|
11835
|
-
0,
|
|
11836
|
-
0
|
|
11837
|
-
], [
|
|
11838
|
-
1,
|
|
11839
|
-
0,
|
|
11840
|
-
0
|
|
11841
|
-
], [
|
|
11842
|
-
0,
|
|
11843
|
-
1,
|
|
11844
|
-
0
|
|
11845
|
-
]);
|
|
11846
|
-
const extrusionDirId = writeDirection(w, [
|
|
11847
|
-
0,
|
|
11848
|
-
0,
|
|
11849
|
-
1
|
|
11850
|
-
]);
|
|
11851
|
-
const extrusionId = w.nextId();
|
|
11852
|
-
w.writeLine({
|
|
11853
|
-
expressID: extrusionId,
|
|
11854
|
-
type: WebIFC.IFCEXTRUDEDAREASOLID,
|
|
11855
|
-
SweptArea: w.ref(profileId),
|
|
11856
|
-
Position: w.ref(extrusionPosId),
|
|
11857
|
-
ExtrudedDirection: w.ref(extrusionDirId),
|
|
11858
|
-
Depth: w.mkType(WebIFC.IFCPOSITIVELENGTHMEASURE, lengthM)
|
|
11859
|
-
});
|
|
11860
|
-
const shapeRepId = w.nextId();
|
|
11861
|
-
w.writeLine({
|
|
11862
|
-
expressID: shapeRepId,
|
|
11863
|
-
type: WebIFC.IFCSHAPEREPRESENTATION,
|
|
11864
|
-
ContextOfItems: w.ref(geomSubContextId),
|
|
11865
|
-
RepresentationIdentifier: w.mkType(WebIFC.IFCLABEL, "Body"),
|
|
11866
|
-
RepresentationType: w.mkType(WebIFC.IFCLABEL, "SweptSolid"),
|
|
11867
|
-
Items: [w.ref(extrusionId)]
|
|
11868
|
-
});
|
|
11869
|
-
const productDefinitionShapeId = w.nextId();
|
|
11870
|
-
w.writeLine({
|
|
11871
|
-
expressID: productDefinitionShapeId,
|
|
11872
|
-
type: WebIFC.IFCPRODUCTDEFINITIONSHAPE,
|
|
11873
|
-
Name: null,
|
|
11874
|
-
Description: null,
|
|
11875
|
-
Representations: [w.ref(shapeRepId)]
|
|
11876
|
-
});
|
|
11877
|
-
return {
|
|
11878
|
-
localPlacementId,
|
|
11879
|
-
productDefinitionShapeId,
|
|
11880
|
-
bodyItemId: extrusionId,
|
|
11881
|
-
usedFallback: false
|
|
11882
|
-
};
|
|
11883
|
-
}
|
|
11884
11699
|
function writeRailingEntity(w, guid, name, _predefinedType, ownerHistoryId, localPlacementId, productDefinitionShapeId) {
|
|
11885
11700
|
const id = w.nextId();
|
|
11886
11701
|
w.writeLine({
|
|
@@ -13319,7 +13134,7 @@ function writeAxis2Placement2D(w) {
|
|
|
13319
13134
|
});
|
|
13320
13135
|
return id;
|
|
13321
13136
|
}
|
|
13322
|
-
function writeOpeningGeometry(w, guid, openingSpec, wallSpec, wallPlacementId, geomSubContextId, ownerHistoryId) {
|
|
13137
|
+
function writeOpeningGeometry(w, guid, openingSpec, wallSpec, wallPlacementId, geomSubContextId, ownerHistoryId, representationIdentifier) {
|
|
13323
13138
|
const widthM = toIfcLengthM(openingSpec.width);
|
|
13324
13139
|
const heightM = toIfcLengthM(openingSpec.height);
|
|
13325
13140
|
const offsetAlongWallM = toIfcLengthM(openingSpec.offsetAlongWall);
|
|
@@ -13382,7 +13197,7 @@ function writeOpeningGeometry(w, guid, openingSpec, wallSpec, wallPlacementId, g
|
|
|
13382
13197
|
expressID: shapeRepId,
|
|
13383
13198
|
type: WebIFC.IFCSHAPEREPRESENTATION,
|
|
13384
13199
|
ContextOfItems: w.ref(geomSubContextId),
|
|
13385
|
-
RepresentationIdentifier: w.mkType(WebIFC.IFCLABEL,
|
|
13200
|
+
RepresentationIdentifier: w.mkType(WebIFC.IFCLABEL, representationIdentifier),
|
|
13386
13201
|
RepresentationType: w.mkType(WebIFC.IFCLABEL, "SweptSolid"),
|
|
13387
13202
|
Items: [w.ref(extrusionId)]
|
|
13388
13203
|
});
|
|
@@ -15139,18 +14954,22 @@ function checkGeoreferencing(reader) {
|
|
|
15139
14954
|
return [issue("warning", "NO_GEOREFERENCING", "Model contains a facility but no IfcProjectedCRS/IfcGeographicCRS (GRF003) — set ProjectSpec.crs")];
|
|
15140
14955
|
}
|
|
15141
14956
|
//#endregion
|
|
15142
|
-
//#region src/serialize/
|
|
14957
|
+
//#region src/serialize/productBodyPreflight.ts
|
|
15143
14958
|
var testItemPreparer = null;
|
|
15144
|
-
/** Prepares every
|
|
15145
|
-
function
|
|
14959
|
+
/** Prepares every retained Body item without writing IFC lines. Source solids remain borrowed. */
|
|
14960
|
+
function preflightProductBody(input) {
|
|
15146
14961
|
const prepareItem = input.prepareItem ?? testItemPreparer ?? prepareTessellation;
|
|
14962
|
+
const failed = (itemIndex, reason, cause) => err(ifcError("BODY_TESSELLATION_FAILED", `Product Body item ${itemIndex} for ${input.localId} could not be tessellated: ${reason}`, cause, {
|
|
14963
|
+
localId: input.localId,
|
|
14964
|
+
itemIndex
|
|
14965
|
+
}));
|
|
15147
14966
|
const prepareAt = (solid, itemIndex) => {
|
|
15148
|
-
|
|
15149
|
-
|
|
15150
|
-
|
|
15151
|
-
|
|
15152
|
-
|
|
15153
|
-
|
|
14967
|
+
try {
|
|
14968
|
+
const item = prepareItem(solid);
|
|
14969
|
+
return item.ok ? ok(item.value) : failed(itemIndex, item.reason, item.cause);
|
|
14970
|
+
} catch (cause) {
|
|
14971
|
+
return failed(itemIndex, cause instanceof Error ? cause.message : String(cause), cause);
|
|
14972
|
+
}
|
|
15154
14973
|
};
|
|
15155
14974
|
const [firstSolid, ...remainingSolids] = input.solids;
|
|
15156
14975
|
const first = prepareAt(firstSolid, 0);
|
|
@@ -15218,24 +15037,13 @@ function wallVolumeError(cause) {
|
|
|
15218
15037
|
function preflightProductBodies(elements) {
|
|
15219
15038
|
const preflighted = [];
|
|
15220
15039
|
for (const element of elements) {
|
|
15221
|
-
const
|
|
15222
|
-
if (body.kind === "PARAMETRIC") {
|
|
15223
|
-
preflighted.push({
|
|
15224
|
-
kind: "PARAMETRIC",
|
|
15225
|
-
element,
|
|
15226
|
-
solid: body.solid
|
|
15227
|
-
});
|
|
15228
|
-
continue;
|
|
15229
|
-
}
|
|
15230
|
-
const prepared = preflightExactBody({
|
|
15040
|
+
const prepared = preflightProductBody({
|
|
15231
15041
|
localId: element.localId,
|
|
15232
|
-
solids:
|
|
15042
|
+
solids: bodySolids(element.geometry)
|
|
15233
15043
|
});
|
|
15234
15044
|
if (!prepared.ok) return err(prepared.error);
|
|
15235
15045
|
preflighted.push({
|
|
15236
|
-
kind: "EXACT",
|
|
15237
15046
|
element,
|
|
15238
|
-
solids: body.solids,
|
|
15239
15047
|
items: prepared.value
|
|
15240
15048
|
});
|
|
15241
15049
|
}
|
|
@@ -15247,7 +15055,7 @@ async function toIfc(model, meta) {
|
|
|
15247
15055
|
}
|
|
15248
15056
|
async function serializeIfc(model, meta) {
|
|
15249
15057
|
try {
|
|
15250
|
-
var _usingCtx$
|
|
15058
|
+
var _usingCtx$3 = _usingCtx();
|
|
15251
15059
|
const issues = [];
|
|
15252
15060
|
const project = model.getProject();
|
|
15253
15061
|
if (!project) return err(ifcError("NO_PROJECT", "BimModel has no project — call model.init() first"));
|
|
@@ -15258,7 +15066,7 @@ async function serializeIfc(model, meta) {
|
|
|
15258
15066
|
organization: meta.organizationName
|
|
15259
15067
|
});
|
|
15260
15068
|
if (!writerResult.ok) return writerResult;
|
|
15261
|
-
const w = _usingCtx$
|
|
15069
|
+
const w = _usingCtx$3.u(writerResult.value);
|
|
15262
15070
|
w.setModelScope(project.guid);
|
|
15263
15071
|
const elements = model.getAllElements();
|
|
15264
15072
|
const relationships = model.getAllRelationships();
|
|
@@ -15370,13 +15178,14 @@ async function serializeIfc(model, meta) {
|
|
|
15370
15178
|
spec: wall.spec,
|
|
15371
15179
|
solids: bodySolids(wall.geometry)
|
|
15372
15180
|
});
|
|
15373
|
-
const { localPlacementId, productDefinitionShapeId } =
|
|
15181
|
+
const { localPlacementId, productDefinitionShapeId, bodyItemIds } = writeProductBodyGeometry(w, wall.spec, preflighted.items, geomSubContextId, storeyPlacementId);
|
|
15374
15182
|
const wallExpressId = writeWallEntity(w, wall.guid, `Wall ${i + 1}`, ownerHistoryId, localPlacementId, productDefinitionShapeId);
|
|
15375
15183
|
idMap.set(wall.localId, wallExpressId);
|
|
15376
15184
|
placementMap.set(wall.localId, localPlacementId);
|
|
15377
15185
|
writeWallCommonPset(w, ownerHistoryId, wallExpressId, wall.spec);
|
|
15378
15186
|
writeManufacturerPset(w, ownerHistoryId, wallExpressId, wall.spec);
|
|
15379
15187
|
if (wall.spec.customProperties !== void 0) writeCustomPsets(w, ownerHistoryId, wallExpressId, wall.spec.customProperties);
|
|
15188
|
+
for (const itemId of bodyItemIds) applySurfaceStyle(w, model, wall.localId, itemId);
|
|
15380
15189
|
if (!bodyQuantities.ok) issues.push(issue("warning", "WALL_QUANTITY_OMITTED", "Wall quantities omitted because occupied material volume could not be measured", wall.localId, {
|
|
15381
15190
|
guid: wall.guid,
|
|
15382
15191
|
cause: bodyQuantities.error
|
|
@@ -15526,27 +15335,14 @@ async function serializeIfc(model, meta) {
|
|
|
15526
15335
|
const railing = preflighted.element;
|
|
15527
15336
|
const containingId = findContainerOf(railing.localId, relationships);
|
|
15528
15337
|
const storeyPlacementId = containingId !== null ? placementMap.get(containingId) ?? null : null;
|
|
15529
|
-
|
|
15530
|
-
let exactBodyItemIds = [];
|
|
15531
|
-
if (preflighted.kind === "EXACT") {
|
|
15532
|
-
const exact = writeExactBodyGeometry(w, railing.spec, preflighted.items, geomSubContextId, storeyPlacementId);
|
|
15533
|
-
exactBodyItemIds = exact.bodyItemIds;
|
|
15534
|
-
representation = {
|
|
15535
|
-
...exact,
|
|
15536
|
-
bodyItemId: null,
|
|
15537
|
-
usedFallback: false
|
|
15538
|
-
};
|
|
15539
|
-
} else representation = writeRailingGeometry(w, railing.spec, preflighted.solid, geomSubContextId, storeyPlacementId);
|
|
15540
|
-
const { localPlacementId, productDefinitionShapeId, bodyItemId, usedFallback } = representation;
|
|
15541
|
-
if (usedFallback) console.warn(`Railing ${i + 1} tessellation failed; IFC body is a degenerate fallback.`);
|
|
15338
|
+
const { localPlacementId, productDefinitionShapeId, bodyItemIds } = writeProductBodyGeometry(w, railing.spec, preflighted.items, geomSubContextId, storeyPlacementId);
|
|
15542
15339
|
const railingExpressId = writeRailingEntity(w, railing.guid, `Railing ${i + 1}`, railing.spec.predefinedType ?? "NOTDEFINED", ownerHistoryId, localPlacementId, productDefinitionShapeId);
|
|
15543
15340
|
idMap.set(railing.localId, railingExpressId);
|
|
15544
15341
|
placementMap.set(railing.localId, localPlacementId);
|
|
15545
15342
|
writeRailingCommonPset(w, ownerHistoryId, railingExpressId, railing.spec);
|
|
15546
15343
|
writeManufacturerPset(w, ownerHistoryId, railingExpressId, railing.spec);
|
|
15547
15344
|
if (railing.spec.customProperties !== void 0) writeCustomPsets(w, ownerHistoryId, railingExpressId, railing.spec.customProperties);
|
|
15548
|
-
|
|
15549
|
-
else if (bodyItemId !== null) applySurfaceStyle(w, model, railing.localId, bodyItemId);
|
|
15345
|
+
for (const itemId of bodyItemIds) applySurfaceStyle(w, model, railing.localId, itemId);
|
|
15550
15346
|
}
|
|
15551
15347
|
for (const [i, covering] of coverings.entries()) {
|
|
15552
15348
|
const containingId = findContainerOf(covering.localId, relationships);
|
|
@@ -15562,6 +15358,7 @@ async function serializeIfc(model, meta) {
|
|
|
15562
15358
|
}
|
|
15563
15359
|
const openingPlacementMap = /* @__PURE__ */ new Map();
|
|
15564
15360
|
const openingEntityMap = /* @__PURE__ */ new Map();
|
|
15361
|
+
let referenceContextId;
|
|
15565
15362
|
for (const rel of relationships) {
|
|
15566
15363
|
if (rel.kind !== "VOIDS_WALL") continue;
|
|
15567
15364
|
const wallElement = elements.find((el) => el.category === "WALL" && el.localId === rel.wallLocalId);
|
|
@@ -15572,7 +15369,8 @@ async function serializeIfc(model, meta) {
|
|
|
15572
15369
|
const openingElement = elements.find((el) => el.localId === rel.openingLocalId);
|
|
15573
15370
|
if (openingElement === void 0 || openingElement.category !== "OPENING") continue;
|
|
15574
15371
|
if (!isWallOpening(openingElement.spec)) continue;
|
|
15575
|
-
|
|
15372
|
+
referenceContextId ??= writeGeometricSubContext(w, geomContextId, "Reference");
|
|
15373
|
+
const { openingEntityId, openingPlacementId } = writeOpeningGeometry(w, openingElement.guid, openingElement.spec, wallElement.spec, wallPlacementId, referenceContextId, ownerHistoryId, "Reference");
|
|
15576
15374
|
idMap.set(rel.openingLocalId, openingEntityId);
|
|
15577
15375
|
openingPlacementMap.set(rel.openingLocalId, openingPlacementId);
|
|
15578
15376
|
openingEntityMap.set(rel.openingLocalId, openingEntityId);
|
|
@@ -15732,9 +15530,9 @@ async function serializeIfc(model, meta) {
|
|
|
15732
15530
|
issues
|
|
15733
15531
|
}) : saved;
|
|
15734
15532
|
} catch (_) {
|
|
15735
|
-
_usingCtx$
|
|
15533
|
+
_usingCtx$3.e = _;
|
|
15736
15534
|
} finally {
|
|
15737
|
-
_usingCtx$
|
|
15535
|
+
_usingCtx$3.d();
|
|
15738
15536
|
}
|
|
15739
15537
|
}
|
|
15740
15538
|
/**
|
|
@@ -16452,13 +16250,13 @@ function reconstructExtrusion(reader, extrusionId, scale, worldTransform, diagno
|
|
|
16452
16250
|
];
|
|
16453
16251
|
const solidResult = (() => {
|
|
16454
16252
|
try {
|
|
16455
|
-
var _usingCtx$
|
|
16456
|
-
const face = _usingCtx$
|
|
16253
|
+
var _usingCtx$2 = _usingCtx();
|
|
16254
|
+
const face = _usingCtx$2.u(faceResult.value);
|
|
16457
16255
|
return extrude(face, extrudeVec);
|
|
16458
16256
|
} catch (_) {
|
|
16459
|
-
_usingCtx$
|
|
16257
|
+
_usingCtx$2.e = _;
|
|
16460
16258
|
} finally {
|
|
16461
|
-
_usingCtx$
|
|
16259
|
+
_usingCtx$2.d();
|
|
16462
16260
|
}
|
|
16463
16261
|
})();
|
|
16464
16262
|
if (!solidResult.ok) {
|
|
@@ -17180,6 +16978,161 @@ function errMsg$1(e) {
|
|
|
17180
16978
|
return e instanceof Error ? e.message : String(e);
|
|
17181
16979
|
}
|
|
17182
16980
|
//#endregion
|
|
16981
|
+
//#region src/geometryCleanupDiagnostics.ts
|
|
16982
|
+
var diagnosticSchema = object({
|
|
16983
|
+
operation: string(),
|
|
16984
|
+
itemIndex: number().int().nonnegative(),
|
|
16985
|
+
resourceKind: _enum(["SHAPE", "TRANSFORM"]),
|
|
16986
|
+
localId: number().optional(),
|
|
16987
|
+
cause: unknown()
|
|
16988
|
+
});
|
|
16989
|
+
var failedCleanup = object({
|
|
16990
|
+
kind: literal("FAILED"),
|
|
16991
|
+
diagnostics: array(unknown()).nonempty()
|
|
16992
|
+
});
|
|
16993
|
+
var errorMetadata = object({ cleanup: unknown().optional() });
|
|
16994
|
+
var cleanupAttempt = Symbol("geometryCleanupAttempt");
|
|
16995
|
+
var bodyOperation = _enum(["productBodyBounds", "measureProductBodyMaterial"]);
|
|
16996
|
+
function attemptIdentity(source) {
|
|
16997
|
+
const identity = cleanupAttempt in source ? source[cleanupAttempt] : source;
|
|
16998
|
+
return typeof identity === "object" && identity !== null ? identity : source;
|
|
16999
|
+
}
|
|
17000
|
+
function errorChildren(value) {
|
|
17001
|
+
const children = [];
|
|
17002
|
+
if (value instanceof AggregateError) {
|
|
17003
|
+
const errors = value.errors;
|
|
17004
|
+
children.push(...errors);
|
|
17005
|
+
}
|
|
17006
|
+
if ("cause" in value) children.push(value.cause);
|
|
17007
|
+
if ("error" in value && "suppressed" in value) children.push(value.error, value.suppressed);
|
|
17008
|
+
return children;
|
|
17009
|
+
}
|
|
17010
|
+
/** Keep the actual failed-attempt markers; their causes need not be unique. */
|
|
17011
|
+
function nativeCleanupAttempts(error) {
|
|
17012
|
+
const attempts = [];
|
|
17013
|
+
const seen = /* @__PURE__ */ new Set();
|
|
17014
|
+
const visit = (value) => {
|
|
17015
|
+
if (typeof value !== "object" || value === null || seen.has(value)) return;
|
|
17016
|
+
seen.add(value);
|
|
17017
|
+
if (value instanceof GeometryCleanupError) attempts.push(value);
|
|
17018
|
+
else errorChildren(value).forEach(visit);
|
|
17019
|
+
};
|
|
17020
|
+
visit(error);
|
|
17021
|
+
return attempts;
|
|
17022
|
+
}
|
|
17023
|
+
/** Read prior owner attempts without retrying releases or merging distinct failures. */
|
|
17024
|
+
function reportedGeometryCleanup(error, operation, context = {}) {
|
|
17025
|
+
const diagnostics = [];
|
|
17026
|
+
const seenErrors = /* @__PURE__ */ new Set();
|
|
17027
|
+
const seenAttempts = /* @__PURE__ */ new Set();
|
|
17028
|
+
const add = (diagnostic, identity) => {
|
|
17029
|
+
if (seenAttempts.has(identity)) return;
|
|
17030
|
+
seenAttempts.add(identity);
|
|
17031
|
+
diagnostics.push(Object.freeze({
|
|
17032
|
+
operation: diagnostic.operation,
|
|
17033
|
+
itemIndex: diagnostic.itemIndex,
|
|
17034
|
+
resourceKind: diagnostic.resourceKind,
|
|
17035
|
+
cause: diagnostic.cause,
|
|
17036
|
+
...diagnostic.localId === void 0 ? {} : { localId: diagnostic.localId },
|
|
17037
|
+
[cleanupAttempt]: identity
|
|
17038
|
+
}));
|
|
17039
|
+
};
|
|
17040
|
+
const visit = (value) => {
|
|
17041
|
+
if (typeof value !== "object" || value === null || seenErrors.has(value)) return;
|
|
17042
|
+
seenErrors.add(value);
|
|
17043
|
+
const metadata = errorMetadata.safeParse("metadata" in value ? value.metadata : void 0);
|
|
17044
|
+
const reports = [metadata.success ? metadata.data.cleanup : void 0, "cleanup" in value ? value.cleanup : void 0];
|
|
17045
|
+
const nativeAttempts = bodyOperation.safeParse("operation" in value ? value.operation : void 0).success ? nativeCleanupAttempts(value) : [];
|
|
17046
|
+
const matched = /* @__PURE__ */ new Set();
|
|
17047
|
+
const seenEntries = /* @__PURE__ */ new Set();
|
|
17048
|
+
for (const report of reports) {
|
|
17049
|
+
const parsed = failedCleanup.safeParse(report);
|
|
17050
|
+
if (!parsed.success) continue;
|
|
17051
|
+
for (const source of parsed.data.diagnostics) {
|
|
17052
|
+
if (typeof source !== "object" || source === null || seenEntries.has(source)) continue;
|
|
17053
|
+
const diagnostic = diagnosticSchema.safeParse(source);
|
|
17054
|
+
if (!diagnostic.success) continue;
|
|
17055
|
+
seenEntries.add(source);
|
|
17056
|
+
let identity = attemptIdentity(source);
|
|
17057
|
+
if (identity === source) {
|
|
17058
|
+
const native = nativeAttempts.find((attempt) => !matched.has(attempt) && attempt.resourceKind === diagnostic.data.resourceKind && attempt.cause === diagnostic.data.cause);
|
|
17059
|
+
if (native !== void 0) identity = native;
|
|
17060
|
+
}
|
|
17061
|
+
if (identity instanceof GeometryCleanupError) matched.add(identity);
|
|
17062
|
+
add(diagnostic.data, identity);
|
|
17063
|
+
}
|
|
17064
|
+
}
|
|
17065
|
+
if (value instanceof GeometryCleanupError) add({
|
|
17066
|
+
operation,
|
|
17067
|
+
itemIndex: context.itemIndex ?? 0,
|
|
17068
|
+
resourceKind: value.resourceKind,
|
|
17069
|
+
cause: value.cause
|
|
17070
|
+
}, value);
|
|
17071
|
+
else errorChildren(value).forEach(visit);
|
|
17072
|
+
};
|
|
17073
|
+
visit(error);
|
|
17074
|
+
return diagnostics;
|
|
17075
|
+
}
|
|
17076
|
+
//#endregion
|
|
17077
|
+
//#region src/import/cutImportedSolids.ts
|
|
17078
|
+
/** Borrow World-placed inputs; own every disconnected result independently of the cut's cache. */
|
|
17079
|
+
function cutImportedSolids(host, opening) {
|
|
17080
|
+
const context = { operation: "cutImportedSolids" };
|
|
17081
|
+
const temporaries = [];
|
|
17082
|
+
const outputs = [];
|
|
17083
|
+
const build = () => {
|
|
17084
|
+
const cutResult = cut(host, opening);
|
|
17085
|
+
if (!cutResult.ok) return err(fromBrepError(cutResult.error, "VOID_CUT_FAILED", "Opening cut failed"));
|
|
17086
|
+
temporaries.push({
|
|
17087
|
+
resource: cutResult.value,
|
|
17088
|
+
itemIndex: 0
|
|
17089
|
+
});
|
|
17090
|
+
const children = getKernel().iterShapes(cutResult.value.wrapped, "solid").map(createSolid);
|
|
17091
|
+
temporaries.push(...children.map((resource, itemIndex) => ({
|
|
17092
|
+
resource,
|
|
17093
|
+
itemIndex
|
|
17094
|
+
})));
|
|
17095
|
+
for (const solid of children) {
|
|
17096
|
+
const copied = clone(solid);
|
|
17097
|
+
if (!copied.ok) return err(fromBrepError(copied.error, "VOID_COPY_FAILED", "Could not retain opening result"));
|
|
17098
|
+
const candidate = copied.value;
|
|
17099
|
+
temporaries.push({
|
|
17100
|
+
resource: candidate,
|
|
17101
|
+
itemIndex: temporaries.length
|
|
17102
|
+
});
|
|
17103
|
+
const validated = validSolid(candidate);
|
|
17104
|
+
if (!validated.ok) return err(importError("VOID_INVALID_SOLID", "Opening result is not valid", validated.error));
|
|
17105
|
+
outputs.push(validated.value);
|
|
17106
|
+
}
|
|
17107
|
+
return ok(outputs);
|
|
17108
|
+
};
|
|
17109
|
+
let result;
|
|
17110
|
+
try {
|
|
17111
|
+
result = build();
|
|
17112
|
+
} catch (cause) {
|
|
17113
|
+
result = err(importError("VOID_CUT_FAILED", "Opening cut failed", cause));
|
|
17114
|
+
}
|
|
17115
|
+
const survivors = new Set(result.ok ? outputs : []);
|
|
17116
|
+
const cleanup = cleanupOwnedResources(temporaries.filter(({ resource }) => !survivors.has(resource)).reverse(), context);
|
|
17117
|
+
const diagnostics = [...result.ok ? [] : reportedGeometryCleanup(result.error, context.operation), ...cleanup.kind === "FAILED" ? cleanup.diagnostics : []];
|
|
17118
|
+
if (result.ok && diagnostics.length === 0) return result;
|
|
17119
|
+
if (result.ok) {
|
|
17120
|
+
const outputCleanup = cleanupOwnedResources(outputs.map((resource, itemIndex) => ({
|
|
17121
|
+
resource,
|
|
17122
|
+
itemIndex
|
|
17123
|
+
})), context);
|
|
17124
|
+
if (outputCleanup.kind === "FAILED") diagnostics.push(...outputCleanup.diagnostics);
|
|
17125
|
+
}
|
|
17126
|
+
const failure = result.ok ? importError("VOID_CLEANUP_FAILED", "Opening result cleanup failed") : result.error;
|
|
17127
|
+
return err({
|
|
17128
|
+
...failure,
|
|
17129
|
+
metadata: {
|
|
17130
|
+
...failure.metadata,
|
|
17131
|
+
cleanup: cleanupReport(diagnostics)
|
|
17132
|
+
}
|
|
17133
|
+
});
|
|
17134
|
+
}
|
|
17135
|
+
//#endregion
|
|
17183
17136
|
//#region src/import/dataRead.ts
|
|
17184
17137
|
/** Narrows an unknown line attribute to the `{ type, value }` wrapper shape. */
|
|
17185
17138
|
function asTyped(v) {
|
|
@@ -17535,7 +17488,7 @@ var ELEMENT_TYPES = [
|
|
|
17535
17488
|
* fatal failures — bad bytes, unsupported schema, WASM open failure — return
|
|
17536
17489
|
* `err`. Inspect {@link ImportedModel.diagnostics} for per-element quality.
|
|
17537
17490
|
*
|
|
17538
|
-
* The web-ifc model handle is
|
|
17491
|
+
* The web-ifc model handle is closed before handing reconstructed owners to the caller.
|
|
17539
17492
|
*/
|
|
17540
17493
|
async function fromIfc(bytes, options = {}) {
|
|
17541
17494
|
const settings = { coordinateToOrigin: options.coordinateToOrigin ?? false };
|
|
@@ -17543,6 +17496,7 @@ async function fromIfc(bytes, options = {}) {
|
|
|
17543
17496
|
if (!readerResult.ok) return err(readerResult.error);
|
|
17544
17497
|
const reader = readerResult.value;
|
|
17545
17498
|
const elements = [];
|
|
17499
|
+
let result;
|
|
17546
17500
|
try {
|
|
17547
17501
|
reader.buildGuidMap();
|
|
17548
17502
|
const diagnostics = [];
|
|
@@ -17569,13 +17523,23 @@ async function fromIfc(bytes, options = {}) {
|
|
|
17569
17523
|
diagnostics: report,
|
|
17570
17524
|
...applicationName !== void 0 ? { applicationName } : {}
|
|
17571
17525
|
};
|
|
17572
|
-
|
|
17526
|
+
result = ok(model);
|
|
17573
17527
|
} catch (e) {
|
|
17574
|
-
|
|
17575
|
-
|
|
17576
|
-
|
|
17528
|
+
result = err(importError("IMPORT_FAILED", "Unexpected failure during IFC import", e));
|
|
17529
|
+
}
|
|
17530
|
+
try {
|
|
17577
17531
|
reader.close();
|
|
17532
|
+
} catch (cause) {
|
|
17533
|
+
result = err(result.ok ? importError("IMPORT_CLOSE_FAILED", "Failed to close IFC reader", cause) : {
|
|
17534
|
+
...result.error,
|
|
17535
|
+
metadata: {
|
|
17536
|
+
...result.error.metadata,
|
|
17537
|
+
readerCloseCause: cause
|
|
17538
|
+
}
|
|
17539
|
+
});
|
|
17578
17540
|
}
|
|
17541
|
+
if (!result.ok) return err(withCleanup(result.error, disposeElements(elements), "fromIfc"));
|
|
17542
|
+
return result;
|
|
17579
17543
|
}
|
|
17580
17544
|
/**
|
|
17581
17545
|
* Reads one product into an {@link ImportedElement}. Returns null only when the
|
|
@@ -17626,8 +17590,8 @@ function readElement(reader, expressId, category, scale, containment, typeEnums,
|
|
|
17626
17590
|
...fills !== void 0 ? { fills } : {}
|
|
17627
17591
|
};
|
|
17628
17592
|
} catch (e) {
|
|
17629
|
-
|
|
17630
|
-
diagnostics.push(issue("error", "ELEMENT_READ_FAILED", `Element ${expressId} reconstruction threw: ${errMsg(e)}`, expressId));
|
|
17593
|
+
const failure = geometry === null ? e : withCleanup(importError("ELEMENT_READ_FAILED", "Element read failed", e), disposeGeometry(geometry), "readElement");
|
|
17594
|
+
diagnostics.push(issue("error", "ELEMENT_READ_FAILED", `Element ${expressId} reconstruction threw: ${errMsg(e)}`, expressId, { cause: failure }));
|
|
17631
17595
|
return null;
|
|
17632
17596
|
}
|
|
17633
17597
|
}
|
|
@@ -17643,36 +17607,79 @@ function findFills(reader, elementExpressId) {
|
|
|
17643
17607
|
}
|
|
17644
17608
|
/**
|
|
17645
17609
|
* Reconstructs a host element's body geometry and, per IFC `IfcRelVoidsElement`
|
|
17646
|
-
* semantics, subtracts
|
|
17610
|
+
* semantics, subtracts each opening's Body representation from a parametric host —
|
|
17647
17611
|
* so a wall with a door hole comes back as the cut solid, matching the source
|
|
17648
17612
|
* model. Falls back to the uncut solid (with a diagnostic) if a cut fails.
|
|
17649
17613
|
*/
|
|
17650
17614
|
function reconstructGeometry(reader, expressId, scale, voidedBy, diagnostics) {
|
|
17651
17615
|
const base = toImportedGeometry(reader, expressId, scale, diagnostics);
|
|
17652
17616
|
if (base.fidelity !== "PARAMETRIC" || base.completeness !== "COMPLETE" || voidedBy.length === 0) return base;
|
|
17653
|
-
|
|
17654
|
-
|
|
17655
|
-
|
|
17656
|
-
|
|
17657
|
-
|
|
17658
|
-
|
|
17659
|
-
|
|
17660
|
-
|
|
17617
|
+
if (base.solids[0] === void 0) return base;
|
|
17618
|
+
const hosts = [...base.solids];
|
|
17619
|
+
try {
|
|
17620
|
+
for (const openingId of voidedBy) try {
|
|
17621
|
+
var _usingCtx$1 = _usingCtx();
|
|
17622
|
+
const opening = readBodyGeometry(reader, openingId, scale, diagnostics);
|
|
17623
|
+
if (opening.kind !== "SOLID") continue;
|
|
17624
|
+
const openingOwner = _usingCtx$1.u(ownOpening(opening.solid, openingId));
|
|
17625
|
+
for (let hostIndex = 0; hostIndex < hosts.length;) {
|
|
17661
17626
|
const host = hosts[hostIndex];
|
|
17662
|
-
if (host === void 0)
|
|
17663
|
-
const cutResult =
|
|
17627
|
+
if (host === void 0) break;
|
|
17628
|
+
const cutResult = cutImportedSolids(host, openingOwner.solid);
|
|
17664
17629
|
if (!cutResult.ok) {
|
|
17665
|
-
diagnostics.push(issue("warning", "VOID_SUBTRACTION_FAILED", `Opening ${openingId} could not be subtracted from element ${expressId}: ${cutResult.error.message}`, expressId));
|
|
17630
|
+
diagnostics.push(issue("warning", "VOID_SUBTRACTION_FAILED", `Opening ${openingId} could not be subtracted from element ${expressId}: ${cutResult.error.message}`, expressId, { cause: cutResult.error }));
|
|
17631
|
+
hostIndex++;
|
|
17666
17632
|
continue;
|
|
17667
17633
|
}
|
|
17668
|
-
|
|
17669
|
-
|
|
17634
|
+
hosts.splice(hostIndex, 1, ...cutResult.value);
|
|
17635
|
+
const cleanup = cleanupOwnedResources([{
|
|
17636
|
+
resource: host,
|
|
17637
|
+
itemIndex: hostIndex
|
|
17638
|
+
}], { operation: "importOpening" });
|
|
17639
|
+
if (cleanup.kind === "FAILED") diagnostics.push(issue("warning", "VOID_HOST_CLEANUP_FAILED", "Opening result retained, but previous host release failed", expressId, { cleanup }));
|
|
17640
|
+
hostIndex += cutResult.value.length;
|
|
17670
17641
|
}
|
|
17642
|
+
} catch (_) {
|
|
17643
|
+
_usingCtx$1.e = _;
|
|
17671
17644
|
} finally {
|
|
17672
|
-
|
|
17645
|
+
_usingCtx$1.d();
|
|
17673
17646
|
}
|
|
17647
|
+
return completeImportedGeometry("PARAMETRIC", hosts, expressId, diagnostics);
|
|
17648
|
+
} catch (cause) {
|
|
17649
|
+
const failure = importError("GEOMETRY_RECONSTRUCTION_FAILED", "Opening reconstruction failed", cause);
|
|
17650
|
+
const cleanup = cleanupOwnedResources(hosts.map((resource, itemIndex) => ({
|
|
17651
|
+
resource,
|
|
17652
|
+
itemIndex
|
|
17653
|
+
})), { operation: "reconstructGeometry" });
|
|
17654
|
+
throw Object.assign(new Error(failure.message, { cause }), {
|
|
17655
|
+
code: failure.code,
|
|
17656
|
+
metadata: withCleanup(failure, cleanup, "reconstructGeometry").metadata
|
|
17657
|
+
});
|
|
17674
17658
|
}
|
|
17675
|
-
|
|
17659
|
+
}
|
|
17660
|
+
function ownOpening(solid, openingId) {
|
|
17661
|
+
return {
|
|
17662
|
+
solid,
|
|
17663
|
+
[Symbol.dispose]() {
|
|
17664
|
+
const cleanup = cleanupOwnedResources([{
|
|
17665
|
+
resource: solid,
|
|
17666
|
+
itemIndex: 0
|
|
17667
|
+
}], { operation: "importOpeningTool" });
|
|
17668
|
+
if (cleanup.kind === "FAILED") throw new Error(`Opening ${openingId} cleanup failed`, { cause: {
|
|
17669
|
+
...importError("OPENING_CLEANUP_FAILED", "Temporary opening release failed"),
|
|
17670
|
+
metadata: { cleanup }
|
|
17671
|
+
} });
|
|
17672
|
+
}
|
|
17673
|
+
};
|
|
17674
|
+
}
|
|
17675
|
+
function withCleanup(error, cleanup, operation) {
|
|
17676
|
+
return {
|
|
17677
|
+
...error,
|
|
17678
|
+
metadata: {
|
|
17679
|
+
...error.metadata,
|
|
17680
|
+
cleanup: cleanupReport([...reportedGeometryCleanup(error, operation), ...cleanup.kind === "FAILED" ? cleanup.diagnostics : []])
|
|
17681
|
+
}
|
|
17682
|
+
};
|
|
17676
17683
|
}
|
|
17677
17684
|
function toImportedGeometry(reader, expressId, scale, diagnostics) {
|
|
17678
17685
|
const body = readBodyItems(reader, expressId, scale, diagnostics);
|
|
@@ -17720,61 +17727,48 @@ function completeImportedGeometry(fidelity, solids, expressId, diagnostics) {
|
|
|
17720
17727
|
fidelity,
|
|
17721
17728
|
completeness: "COMPLETE",
|
|
17722
17729
|
solids,
|
|
17723
|
-
solid: solids.length === 1 ? solids[0] : null,
|
|
17730
|
+
solid: solids.length === 1 ? solids[0] ?? null : null,
|
|
17724
17731
|
...measureCompleteBody(solids, expressId, diagnostics)
|
|
17725
17732
|
};
|
|
17726
17733
|
}
|
|
17727
17734
|
function measureCompleteBody(solids, expressId, diagnostics) {
|
|
17735
|
+
const unavailable = (cause, message = errMsg(cause)) => {
|
|
17736
|
+
diagnostics.push(issue("warning", "BODY_AGGREGATE_MEASUREMENT_FAILED", `Complete Body aggregate measurement failed: ${message}`, expressId, { cause }));
|
|
17737
|
+
return {
|
|
17738
|
+
bounds: null,
|
|
17739
|
+
volumeMm3: null
|
|
17740
|
+
};
|
|
17741
|
+
};
|
|
17728
17742
|
try {
|
|
17729
|
-
const first = solids
|
|
17743
|
+
const [first, ...rest] = solids;
|
|
17730
17744
|
if (first === void 0) return {
|
|
17731
17745
|
bounds: null,
|
|
17732
17746
|
volumeMm3: null
|
|
17733
17747
|
};
|
|
17734
|
-
const
|
|
17735
|
-
|
|
17736
|
-
|
|
17737
|
-
|
|
17738
|
-
|
|
17739
|
-
let zMin = initial.zMin;
|
|
17740
|
-
let zMax = initial.zMax;
|
|
17741
|
-
let volumeMm3 = 0;
|
|
17742
|
-
for (const solid of solids) {
|
|
17743
|
-
const measured = measureVolume(solid);
|
|
17744
|
-
if (!measured.ok) throw new Error(measured.error.message);
|
|
17745
|
-
volumeMm3 += measured.value;
|
|
17746
|
-
const itemBounds = getBounds(solid);
|
|
17747
|
-
xMin = Math.min(xMin, itemBounds.xMin);
|
|
17748
|
-
xMax = Math.max(xMax, itemBounds.xMax);
|
|
17749
|
-
yMin = Math.min(yMin, itemBounds.yMin);
|
|
17750
|
-
yMax = Math.max(yMax, itemBounds.yMax);
|
|
17751
|
-
zMin = Math.min(zMin, itemBounds.zMin);
|
|
17752
|
-
zMax = Math.max(zMax, itemBounds.zMax);
|
|
17753
|
-
}
|
|
17748
|
+
const items = [first, ...rest];
|
|
17749
|
+
const bounds = productBodyBounds(items);
|
|
17750
|
+
if (!bounds.ok) return unavailable(bounds.error, bounds.error.message);
|
|
17751
|
+
const volume = measureProductBodyMaterial(items);
|
|
17752
|
+
if (!volume.ok) return unavailable(volume.error, volume.error.message);
|
|
17754
17753
|
return {
|
|
17755
|
-
bounds:
|
|
17756
|
-
|
|
17757
|
-
xMax,
|
|
17758
|
-
yMin,
|
|
17759
|
-
yMax,
|
|
17760
|
-
zMin,
|
|
17761
|
-
zMax
|
|
17762
|
-
},
|
|
17763
|
-
volumeMm3
|
|
17754
|
+
bounds: bounds.value.bounds,
|
|
17755
|
+
volumeMm3: volume.value
|
|
17764
17756
|
};
|
|
17765
17757
|
} catch (cause) {
|
|
17766
|
-
|
|
17767
|
-
return {
|
|
17768
|
-
bounds: null,
|
|
17769
|
-
volumeMm3: null
|
|
17770
|
-
};
|
|
17758
|
+
return unavailable(cause);
|
|
17771
17759
|
}
|
|
17772
17760
|
}
|
|
17773
17761
|
function disposeGeometry(geometry) {
|
|
17774
|
-
|
|
17762
|
+
return cleanupOwnedResources(geometry.solids.map((resource, itemIndex) => ({
|
|
17763
|
+
resource,
|
|
17764
|
+
itemIndex
|
|
17765
|
+
})), { operation: "disposeImportedGeometry" });
|
|
17775
17766
|
}
|
|
17776
17767
|
function disposeElements(elements) {
|
|
17777
|
-
|
|
17768
|
+
return cleanupOwnedResources(elements.flatMap(({ geometry }) => geometry.solids).map((resource, itemIndex) => ({
|
|
17769
|
+
resource,
|
|
17770
|
+
itemIndex
|
|
17771
|
+
})), { operation: "disposeImportedElements" });
|
|
17778
17772
|
}
|
|
17779
17773
|
function toImportedPset(pset) {
|
|
17780
17774
|
return {
|