brepjs-bim 0.24.3 → 0.24.5
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 +12 -0
- package/dist/brepjs-bim.cjs +431 -167
- package/dist/brepjs-bim.js +423 -159
- package/dist/geometryCleanupDiagnostics.d.ts +6 -0
- package/dist/ifc-writer/psetWriter.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/{exactWallQuantities.d.ts → wallQuantities.d.ts} +3 -3
- package/package.json +1 -1
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
|
|
@@ -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
|
}
|
|
@@ -11691,22 +11716,22 @@ function writeStairAssembly(w, spec, stairKey, assemblyGuid, ownerHistoryId, geo
|
|
|
11691
11716
|
const flightExpressIds = [];
|
|
11692
11717
|
let geometrySimplified = false;
|
|
11693
11718
|
for (const [i, flight] of spec.flights.entries()) try {
|
|
11694
|
-
var _usingCtx$
|
|
11719
|
+
var _usingCtx$4 = _usingCtx();
|
|
11695
11720
|
const built = stairFlightToSolid(flight);
|
|
11696
11721
|
if (!built.ok) return {
|
|
11697
11722
|
ok: false,
|
|
11698
11723
|
error: built.error
|
|
11699
11724
|
};
|
|
11700
|
-
const flightSolid = _usingCtx$
|
|
11725
|
+
const flightSolid = _usingCtx$4.u(built.value.solid);
|
|
11701
11726
|
const flightPlacementId = writeLocalPlacement(w, flight.origin, flight.axisZ, flight.axisX, stairPlacementId);
|
|
11702
11727
|
const tess = writeTessellation(w, flightSolid, geomSubContextId, flightPlacementId);
|
|
11703
11728
|
if (tess.usedFallback) geometrySimplified = true;
|
|
11704
11729
|
const flightExpressId = writeStairFlightEntity(w, deriveIfcGuidSync(`elem:STAIR_FLIGHT:${stairKey}:${i}`), `${stairName} Flight ${i + 1}`, flight, ownerHistoryId, flightPlacementId, tess.productDefinitionShapeId);
|
|
11705
11730
|
flightExpressIds.push(flightExpressId);
|
|
11706
11731
|
} catch (_) {
|
|
11707
|
-
_usingCtx$
|
|
11732
|
+
_usingCtx$4.e = _;
|
|
11708
11733
|
} finally {
|
|
11709
|
-
_usingCtx$
|
|
11734
|
+
_usingCtx$4.d();
|
|
11710
11735
|
}
|
|
11711
11736
|
writeRelAggregates(w, deriveIfcGuidSync(`rel:AGGREGATES:STAIR:${stairKey}`), ownerHistoryId, assemblyExpressId, flightExpressIds);
|
|
11712
11737
|
writeAssemblyType(w, WebIFC.IFCSTAIRTYPE, "Stair Type", deriveIfcGuidSync(`type:STAIR:${stairKey}`), deriveIfcGuidSync(`rel-type:STAIR:${stairKey}`), predefinedType, ownerHistoryId, [assemblyExpressId]);
|
|
@@ -13069,7 +13094,7 @@ function pushWeightQuantity(w, qtyIds, volumeM3, densityKgM3) {
|
|
|
13069
13094
|
if (densityKgM3 === void 0) return;
|
|
13070
13095
|
qtyIds.push(writeWeightQuantity(w, "GrossWeight", volumeM3, densityKgM3));
|
|
13071
13096
|
}
|
|
13072
|
-
function writeWallBaseQuantities(w, ownerHistoryId, wallExpressId, spec, openings, densityKgM3) {
|
|
13097
|
+
function writeWallBaseQuantities(w, ownerHistoryId, wallExpressId, spec, openings, netVolumeM3, densityKgM3) {
|
|
13073
13098
|
const lengthM = toIfcLengthM(spec.length);
|
|
13074
13099
|
const widthM = toIfcLengthM(spec.thickness);
|
|
13075
13100
|
const heightM = toIfcLengthM(spec.height);
|
|
@@ -13085,7 +13110,6 @@ function writeWallBaseQuantities(w, ownerHistoryId, wallExpressId, spec, opening
|
|
|
13085
13110
|
if (toIfcLengthM(op.offsetFromFloor) < FLOOR_TOUCH_EPSILON_M) sumFloorTouchingFootprintM2 += opWidthM * widthM;
|
|
13086
13111
|
}
|
|
13087
13112
|
const netSideAreaM2 = grossSideAreaM2 - sumOpeningAreaM2;
|
|
13088
|
-
const netVolumeM3 = grossVolumeM3 - sumOpeningAreaM2 * widthM;
|
|
13089
13113
|
const netFootprintM2 = grossFootprintM2 - sumFloorTouchingFootprintM2;
|
|
13090
13114
|
const qtyIds = [
|
|
13091
13115
|
writeQtyLength(w, "Length", lengthM),
|
|
@@ -13101,7 +13125,7 @@ function writeWallBaseQuantities(w, ownerHistoryId, wallExpressId, spec, opening
|
|
|
13101
13125
|
pushWeightQuantity(w, qtyIds, netVolumeM3, densityKgM3);
|
|
13102
13126
|
writeRelDefinesByProperties(w, ownerHistoryId, wallExpressId, writeElementQuantity(w, ownerHistoryId, "Qto_WallBaseQuantities", qtyIds));
|
|
13103
13127
|
}
|
|
13104
|
-
function
|
|
13128
|
+
function writeWallBodyQuantities(w, ownerHistoryId, wallExpressId, values) {
|
|
13105
13129
|
writeRelDefinesByProperties(w, ownerHistoryId, wallExpressId, writeElementQuantity(w, ownerHistoryId, "Qto_WallBaseQuantities", [
|
|
13106
13130
|
writeQtyLength(w, "Length", values.lengthM),
|
|
13107
13131
|
writeQtyLength(w, "Width", values.widthM),
|
|
@@ -15165,10 +15189,25 @@ function preflightExactBody(input) {
|
|
|
15165
15189
|
return ok([first.value, ...remainingPrepared]);
|
|
15166
15190
|
}
|
|
15167
15191
|
//#endregion
|
|
15168
|
-
//#region src/serialize/
|
|
15169
|
-
function
|
|
15192
|
+
//#region src/serialize/wallQuantities.ts
|
|
15193
|
+
function deriveWallQuantities(input) {
|
|
15170
15194
|
try {
|
|
15171
|
-
const
|
|
15195
|
+
const items = [];
|
|
15196
|
+
for (const retained of input.solids) {
|
|
15197
|
+
if (getKernel().shapeType(retained.wrapped) !== "compound") {
|
|
15198
|
+
items.push(retained);
|
|
15199
|
+
continue;
|
|
15200
|
+
}
|
|
15201
|
+
const cardinality = singleWrapperChild(retained);
|
|
15202
|
+
if (!cardinality.ok) return cardinality;
|
|
15203
|
+
const children = getSolids(retained);
|
|
15204
|
+
const [child] = children;
|
|
15205
|
+
if (children.length !== 1 || child === void 0 || !isValidSolid(child)) return wallVolumeError(/* @__PURE__ */ new Error("Expected one valid solid in a retained recipe wrapper"));
|
|
15206
|
+
items.push(child);
|
|
15207
|
+
}
|
|
15208
|
+
const [first, ...rest] = items;
|
|
15209
|
+
if (first === void 0) return wallVolumeError(/* @__PURE__ */ new Error("Expected retained Wall material"));
|
|
15210
|
+
const measured = measureProductBodyMaterial([first, ...rest]);
|
|
15172
15211
|
if (!measured.ok) return wallVolumeError(measured.error);
|
|
15173
15212
|
return ok({
|
|
15174
15213
|
lengthM: toIfcLengthM(input.spec.length),
|
|
@@ -15180,8 +15219,24 @@ function deriveExactWallQuantities(input) {
|
|
|
15180
15219
|
return wallVolumeError(cause);
|
|
15181
15220
|
}
|
|
15182
15221
|
}
|
|
15222
|
+
/** Count before cached extraction: a failed later cast cannot strand earlier children. */
|
|
15223
|
+
function singleWrapperChild(retained) {
|
|
15224
|
+
const kernel = getKernel();
|
|
15225
|
+
let count;
|
|
15226
|
+
if (kernel.subShapeCount !== void 0) count = kernel.subShapeCount(retained.wrapped, "solid");
|
|
15227
|
+
else {
|
|
15228
|
+
const rawChildren = kernel.iterShapes(retained.wrapped, "solid");
|
|
15229
|
+
const cleanup = cleanupOwnedResources(rawChildren.map((raw, itemIndex) => ({
|
|
15230
|
+
resource: { [Symbol.dispose]: () => kernel.dispose(raw) },
|
|
15231
|
+
itemIndex
|
|
15232
|
+
})), { operation: "wallQuantityWrapperCount" });
|
|
15233
|
+
if (cleanup.kind === "FAILED") return wallVolumeError({ cleanup });
|
|
15234
|
+
count = rawChildren.length;
|
|
15235
|
+
}
|
|
15236
|
+
return count === 1 ? ok(void 0) : wallVolumeError(/* @__PURE__ */ new Error("Expected one valid solid in a retained recipe wrapper"));
|
|
15237
|
+
}
|
|
15183
15238
|
function wallVolumeError(cause) {
|
|
15184
|
-
return err(ifcError("
|
|
15239
|
+
return err(ifcError("IFC_WALL_QUANTITY_DERIVATION_FAILED", "Failed to derive a positive finite NetVolume for the retained Wall Body", cause));
|
|
15185
15240
|
}
|
|
15186
15241
|
//#endregion
|
|
15187
15242
|
//#region src/serialize/toIfc.ts
|
|
@@ -15212,8 +15267,13 @@ function preflightProductBodies(elements) {
|
|
|
15212
15267
|
return ok(preflighted);
|
|
15213
15268
|
}
|
|
15214
15269
|
async function toIfc(model, meta) {
|
|
15270
|
+
const serialized = await serializeIfc(model, meta);
|
|
15271
|
+
return serialized.ok ? ok(serialized.value.bytes) : serialized;
|
|
15272
|
+
}
|
|
15273
|
+
async function serializeIfc(model, meta) {
|
|
15215
15274
|
try {
|
|
15216
|
-
var _usingCtx$
|
|
15275
|
+
var _usingCtx$3 = _usingCtx();
|
|
15276
|
+
const issues = [];
|
|
15217
15277
|
const project = model.getProject();
|
|
15218
15278
|
if (!project) return err(ifcError("NO_PROJECT", "BimModel has no project — call model.init() first"));
|
|
15219
15279
|
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"));
|
|
@@ -15223,7 +15283,7 @@ async function toIfc(model, meta) {
|
|
|
15223
15283
|
organization: meta.organizationName
|
|
15224
15284
|
});
|
|
15225
15285
|
if (!writerResult.ok) return writerResult;
|
|
15226
|
-
const w = _usingCtx$
|
|
15286
|
+
const w = _usingCtx$3.u(writerResult.value);
|
|
15227
15287
|
w.setModelScope(project.guid);
|
|
15228
15288
|
const elements = model.getAllElements();
|
|
15229
15289
|
const relationships = model.getAllRelationships();
|
|
@@ -15331,10 +15391,10 @@ async function toIfc(model, meta) {
|
|
|
15331
15391
|
const wall = preflighted.element;
|
|
15332
15392
|
const containingId = findContainerOf(wall.localId, relationships);
|
|
15333
15393
|
const storeyPlacementId = containingId !== null ? placementMap.get(containingId) ?? null : null;
|
|
15334
|
-
const
|
|
15394
|
+
const bodyQuantities = deriveWallQuantities({
|
|
15335
15395
|
spec: wall.spec,
|
|
15336
|
-
solids:
|
|
15337
|
-
})
|
|
15396
|
+
solids: bodySolids(wall.geometry)
|
|
15397
|
+
});
|
|
15338
15398
|
const { localPlacementId, productDefinitionShapeId } = preflighted.kind === "EXACT" ? writeExactBodyGeometry(w, wall.spec, preflighted.items, geomSubContextId, storeyPlacementId) : writeWallGeometry(w, wall.spec, geomSubContextId, storeyPlacementId);
|
|
15339
15399
|
const wallExpressId = writeWallEntity(w, wall.guid, `Wall ${i + 1}`, ownerHistoryId, localPlacementId, productDefinitionShapeId);
|
|
15340
15400
|
idMap.set(wall.localId, wallExpressId);
|
|
@@ -15342,9 +15402,12 @@ async function toIfc(model, meta) {
|
|
|
15342
15402
|
writeWallCommonPset(w, ownerHistoryId, wallExpressId, wall.spec);
|
|
15343
15403
|
writeManufacturerPset(w, ownerHistoryId, wallExpressId, wall.spec);
|
|
15344
15404
|
if (wall.spec.customProperties !== void 0) writeCustomPsets(w, ownerHistoryId, wallExpressId, wall.spec.customProperties);
|
|
15345
|
-
if (
|
|
15346
|
-
|
|
15347
|
-
|
|
15405
|
+
if (!bodyQuantities.ok) issues.push(issue("warning", "WALL_QUANTITY_OMITTED", "Wall quantities omitted because occupied material volume could not be measured", wall.localId, {
|
|
15406
|
+
guid: wall.guid,
|
|
15407
|
+
cause: bodyQuantities.error
|
|
15408
|
+
}));
|
|
15409
|
+
else if (wall.geometry.kind === "PARAMETRIC") writeWallBaseQuantities(w, ownerHistoryId, wallExpressId, wall.spec, openingsByWall.get(wall.localId) ?? [], bodyQuantities.value.netVolumeM3, densityByElement.get(wall.localId));
|
|
15410
|
+
else writeWallBodyQuantities(w, ownerHistoryId, wallExpressId, bodyQuantities.value);
|
|
15348
15411
|
}
|
|
15349
15412
|
for (const [i, slab] of slabs.entries()) {
|
|
15350
15413
|
const containingId = findContainerOf(slab.localId, relationships);
|
|
@@ -15688,11 +15751,15 @@ async function toIfc(model, meta) {
|
|
|
15688
15751
|
for (const { ref, ids } of classByKey.values()) byClassification.set(ref, ids);
|
|
15689
15752
|
if (byClassification.size > 0) writeClassificationRefs(w, ownerHistoryId, byClassification);
|
|
15690
15753
|
writeTypeLayer(w, ownerHistoryId, model, idMap);
|
|
15691
|
-
|
|
15754
|
+
const saved = w.save();
|
|
15755
|
+
return saved.ok ? ok({
|
|
15756
|
+
bytes: saved.value,
|
|
15757
|
+
issues
|
|
15758
|
+
}) : saved;
|
|
15692
15759
|
} catch (_) {
|
|
15693
|
-
_usingCtx$
|
|
15760
|
+
_usingCtx$3.e = _;
|
|
15694
15761
|
} finally {
|
|
15695
|
-
_usingCtx$
|
|
15762
|
+
_usingCtx$3.d();
|
|
15696
15763
|
}
|
|
15697
15764
|
}
|
|
15698
15765
|
/**
|
|
@@ -15808,15 +15875,16 @@ function toOccurrences(elements, predefined) {
|
|
|
15808
15875
|
async function toIfcValidated(model, meta) {
|
|
15809
15876
|
const integrity = checkReferentialIntegrity(model);
|
|
15810
15877
|
if (hasErrors(integrity)) return err(ifcError("INTEGRITY_FAILURE", "Model failed referential integrity check", integrity.issues.filter((i) => i.severity === "error")));
|
|
15811
|
-
const
|
|
15812
|
-
if (!
|
|
15813
|
-
const bytes =
|
|
15878
|
+
const serialized = await serializeIfc(model, meta);
|
|
15879
|
+
if (!serialized.ok) return serialized;
|
|
15880
|
+
const { bytes } = serialized.value;
|
|
15814
15881
|
const geometry = collectGeometryIssues(model);
|
|
15815
15882
|
const schema = await checkSchema(bytes);
|
|
15816
15883
|
const roundTrip = await checkRoundTrip(bytes);
|
|
15817
15884
|
const gherkin = await checkGherkinRules(bytes);
|
|
15818
15885
|
const report = { issues: [
|
|
15819
15886
|
...integrity.issues,
|
|
15887
|
+
...serialized.value.issues,
|
|
15820
15888
|
...geometry.issues,
|
|
15821
15889
|
...schema.issues,
|
|
15822
15890
|
...roundTrip.issues,
|
|
@@ -16409,13 +16477,13 @@ function reconstructExtrusion(reader, extrusionId, scale, worldTransform, diagno
|
|
|
16409
16477
|
];
|
|
16410
16478
|
const solidResult = (() => {
|
|
16411
16479
|
try {
|
|
16412
|
-
var _usingCtx$
|
|
16413
|
-
const face = _usingCtx$
|
|
16480
|
+
var _usingCtx$2 = _usingCtx();
|
|
16481
|
+
const face = _usingCtx$2.u(faceResult.value);
|
|
16414
16482
|
return extrude(face, extrudeVec);
|
|
16415
16483
|
} catch (_) {
|
|
16416
|
-
_usingCtx$
|
|
16484
|
+
_usingCtx$2.e = _;
|
|
16417
16485
|
} finally {
|
|
16418
|
-
_usingCtx$
|
|
16486
|
+
_usingCtx$2.d();
|
|
16419
16487
|
}
|
|
16420
16488
|
})();
|
|
16421
16489
|
if (!solidResult.ok) {
|
|
@@ -17137,6 +17205,161 @@ function errMsg$1(e) {
|
|
|
17137
17205
|
return e instanceof Error ? e.message : String(e);
|
|
17138
17206
|
}
|
|
17139
17207
|
//#endregion
|
|
17208
|
+
//#region src/geometryCleanupDiagnostics.ts
|
|
17209
|
+
var diagnosticSchema = object({
|
|
17210
|
+
operation: string(),
|
|
17211
|
+
itemIndex: number().int().nonnegative(),
|
|
17212
|
+
resourceKind: _enum(["SHAPE", "TRANSFORM"]),
|
|
17213
|
+
localId: number().optional(),
|
|
17214
|
+
cause: unknown()
|
|
17215
|
+
});
|
|
17216
|
+
var failedCleanup = object({
|
|
17217
|
+
kind: literal("FAILED"),
|
|
17218
|
+
diagnostics: array(unknown()).nonempty()
|
|
17219
|
+
});
|
|
17220
|
+
var errorMetadata = object({ cleanup: unknown().optional() });
|
|
17221
|
+
var cleanupAttempt = Symbol("geometryCleanupAttempt");
|
|
17222
|
+
var bodyOperation = _enum(["productBodyBounds", "measureProductBodyMaterial"]);
|
|
17223
|
+
function attemptIdentity(source) {
|
|
17224
|
+
const identity = cleanupAttempt in source ? source[cleanupAttempt] : source;
|
|
17225
|
+
return typeof identity === "object" && identity !== null ? identity : source;
|
|
17226
|
+
}
|
|
17227
|
+
function errorChildren(value) {
|
|
17228
|
+
const children = [];
|
|
17229
|
+
if (value instanceof AggregateError) {
|
|
17230
|
+
const errors = value.errors;
|
|
17231
|
+
children.push(...errors);
|
|
17232
|
+
}
|
|
17233
|
+
if ("cause" in value) children.push(value.cause);
|
|
17234
|
+
if ("error" in value && "suppressed" in value) children.push(value.error, value.suppressed);
|
|
17235
|
+
return children;
|
|
17236
|
+
}
|
|
17237
|
+
/** Keep the actual failed-attempt markers; their causes need not be unique. */
|
|
17238
|
+
function nativeCleanupAttempts(error) {
|
|
17239
|
+
const attempts = [];
|
|
17240
|
+
const seen = /* @__PURE__ */ new Set();
|
|
17241
|
+
const visit = (value) => {
|
|
17242
|
+
if (typeof value !== "object" || value === null || seen.has(value)) return;
|
|
17243
|
+
seen.add(value);
|
|
17244
|
+
if (value instanceof GeometryCleanupError) attempts.push(value);
|
|
17245
|
+
else errorChildren(value).forEach(visit);
|
|
17246
|
+
};
|
|
17247
|
+
visit(error);
|
|
17248
|
+
return attempts;
|
|
17249
|
+
}
|
|
17250
|
+
/** Read prior owner attempts without retrying releases or merging distinct failures. */
|
|
17251
|
+
function reportedGeometryCleanup(error, operation, context = {}) {
|
|
17252
|
+
const diagnostics = [];
|
|
17253
|
+
const seenErrors = /* @__PURE__ */ new Set();
|
|
17254
|
+
const seenAttempts = /* @__PURE__ */ new Set();
|
|
17255
|
+
const add = (diagnostic, identity) => {
|
|
17256
|
+
if (seenAttempts.has(identity)) return;
|
|
17257
|
+
seenAttempts.add(identity);
|
|
17258
|
+
diagnostics.push(Object.freeze({
|
|
17259
|
+
operation: diagnostic.operation,
|
|
17260
|
+
itemIndex: diagnostic.itemIndex,
|
|
17261
|
+
resourceKind: diagnostic.resourceKind,
|
|
17262
|
+
cause: diagnostic.cause,
|
|
17263
|
+
...diagnostic.localId === void 0 ? {} : { localId: diagnostic.localId },
|
|
17264
|
+
[cleanupAttempt]: identity
|
|
17265
|
+
}));
|
|
17266
|
+
};
|
|
17267
|
+
const visit = (value) => {
|
|
17268
|
+
if (typeof value !== "object" || value === null || seenErrors.has(value)) return;
|
|
17269
|
+
seenErrors.add(value);
|
|
17270
|
+
const metadata = errorMetadata.safeParse("metadata" in value ? value.metadata : void 0);
|
|
17271
|
+
const reports = [metadata.success ? metadata.data.cleanup : void 0, "cleanup" in value ? value.cleanup : void 0];
|
|
17272
|
+
const nativeAttempts = bodyOperation.safeParse("operation" in value ? value.operation : void 0).success ? nativeCleanupAttempts(value) : [];
|
|
17273
|
+
const matched = /* @__PURE__ */ new Set();
|
|
17274
|
+
const seenEntries = /* @__PURE__ */ new Set();
|
|
17275
|
+
for (const report of reports) {
|
|
17276
|
+
const parsed = failedCleanup.safeParse(report);
|
|
17277
|
+
if (!parsed.success) continue;
|
|
17278
|
+
for (const source of parsed.data.diagnostics) {
|
|
17279
|
+
if (typeof source !== "object" || source === null || seenEntries.has(source)) continue;
|
|
17280
|
+
const diagnostic = diagnosticSchema.safeParse(source);
|
|
17281
|
+
if (!diagnostic.success) continue;
|
|
17282
|
+
seenEntries.add(source);
|
|
17283
|
+
let identity = attemptIdentity(source);
|
|
17284
|
+
if (identity === source) {
|
|
17285
|
+
const native = nativeAttempts.find((attempt) => !matched.has(attempt) && attempt.resourceKind === diagnostic.data.resourceKind && attempt.cause === diagnostic.data.cause);
|
|
17286
|
+
if (native !== void 0) identity = native;
|
|
17287
|
+
}
|
|
17288
|
+
if (identity instanceof GeometryCleanupError) matched.add(identity);
|
|
17289
|
+
add(diagnostic.data, identity);
|
|
17290
|
+
}
|
|
17291
|
+
}
|
|
17292
|
+
if (value instanceof GeometryCleanupError) add({
|
|
17293
|
+
operation,
|
|
17294
|
+
itemIndex: context.itemIndex ?? 0,
|
|
17295
|
+
resourceKind: value.resourceKind,
|
|
17296
|
+
cause: value.cause
|
|
17297
|
+
}, value);
|
|
17298
|
+
else errorChildren(value).forEach(visit);
|
|
17299
|
+
};
|
|
17300
|
+
visit(error);
|
|
17301
|
+
return diagnostics;
|
|
17302
|
+
}
|
|
17303
|
+
//#endregion
|
|
17304
|
+
//#region src/import/cutImportedSolids.ts
|
|
17305
|
+
/** Borrow World-placed inputs; own every disconnected result independently of the cut's cache. */
|
|
17306
|
+
function cutImportedSolids(host, opening) {
|
|
17307
|
+
const context = { operation: "cutImportedSolids" };
|
|
17308
|
+
const temporaries = [];
|
|
17309
|
+
const outputs = [];
|
|
17310
|
+
const build = () => {
|
|
17311
|
+
const cutResult = cut(host, opening);
|
|
17312
|
+
if (!cutResult.ok) return err(fromBrepError(cutResult.error, "VOID_CUT_FAILED", "Opening cut failed"));
|
|
17313
|
+
temporaries.push({
|
|
17314
|
+
resource: cutResult.value,
|
|
17315
|
+
itemIndex: 0
|
|
17316
|
+
});
|
|
17317
|
+
const children = getKernel().iterShapes(cutResult.value.wrapped, "solid").map(createSolid);
|
|
17318
|
+
temporaries.push(...children.map((resource, itemIndex) => ({
|
|
17319
|
+
resource,
|
|
17320
|
+
itemIndex
|
|
17321
|
+
})));
|
|
17322
|
+
for (const solid of children) {
|
|
17323
|
+
const copied = clone(solid);
|
|
17324
|
+
if (!copied.ok) return err(fromBrepError(copied.error, "VOID_COPY_FAILED", "Could not retain opening result"));
|
|
17325
|
+
const candidate = copied.value;
|
|
17326
|
+
temporaries.push({
|
|
17327
|
+
resource: candidate,
|
|
17328
|
+
itemIndex: temporaries.length
|
|
17329
|
+
});
|
|
17330
|
+
const validated = validSolid(candidate);
|
|
17331
|
+
if (!validated.ok) return err(importError("VOID_INVALID_SOLID", "Opening result is not valid", validated.error));
|
|
17332
|
+
outputs.push(validated.value);
|
|
17333
|
+
}
|
|
17334
|
+
return ok(outputs);
|
|
17335
|
+
};
|
|
17336
|
+
let result;
|
|
17337
|
+
try {
|
|
17338
|
+
result = build();
|
|
17339
|
+
} catch (cause) {
|
|
17340
|
+
result = err(importError("VOID_CUT_FAILED", "Opening cut failed", cause));
|
|
17341
|
+
}
|
|
17342
|
+
const survivors = new Set(result.ok ? outputs : []);
|
|
17343
|
+
const cleanup = cleanupOwnedResources(temporaries.filter(({ resource }) => !survivors.has(resource)).reverse(), context);
|
|
17344
|
+
const diagnostics = [...result.ok ? [] : reportedGeometryCleanup(result.error, context.operation), ...cleanup.kind === "FAILED" ? cleanup.diagnostics : []];
|
|
17345
|
+
if (result.ok && diagnostics.length === 0) return result;
|
|
17346
|
+
if (result.ok) {
|
|
17347
|
+
const outputCleanup = cleanupOwnedResources(outputs.map((resource, itemIndex) => ({
|
|
17348
|
+
resource,
|
|
17349
|
+
itemIndex
|
|
17350
|
+
})), context);
|
|
17351
|
+
if (outputCleanup.kind === "FAILED") diagnostics.push(...outputCleanup.diagnostics);
|
|
17352
|
+
}
|
|
17353
|
+
const failure = result.ok ? importError("VOID_CLEANUP_FAILED", "Opening result cleanup failed") : result.error;
|
|
17354
|
+
return err({
|
|
17355
|
+
...failure,
|
|
17356
|
+
metadata: {
|
|
17357
|
+
...failure.metadata,
|
|
17358
|
+
cleanup: cleanupReport(diagnostics)
|
|
17359
|
+
}
|
|
17360
|
+
});
|
|
17361
|
+
}
|
|
17362
|
+
//#endregion
|
|
17140
17363
|
//#region src/import/dataRead.ts
|
|
17141
17364
|
/** Narrows an unknown line attribute to the `{ type, value }` wrapper shape. */
|
|
17142
17365
|
function asTyped(v) {
|
|
@@ -17492,7 +17715,7 @@ var ELEMENT_TYPES = [
|
|
|
17492
17715
|
* fatal failures — bad bytes, unsupported schema, WASM open failure — return
|
|
17493
17716
|
* `err`. Inspect {@link ImportedModel.diagnostics} for per-element quality.
|
|
17494
17717
|
*
|
|
17495
|
-
* The web-ifc model handle is
|
|
17718
|
+
* The web-ifc model handle is closed before handing reconstructed owners to the caller.
|
|
17496
17719
|
*/
|
|
17497
17720
|
async function fromIfc(bytes, options = {}) {
|
|
17498
17721
|
const settings = { coordinateToOrigin: options.coordinateToOrigin ?? false };
|
|
@@ -17500,6 +17723,7 @@ async function fromIfc(bytes, options = {}) {
|
|
|
17500
17723
|
if (!readerResult.ok) return err(readerResult.error);
|
|
17501
17724
|
const reader = readerResult.value;
|
|
17502
17725
|
const elements = [];
|
|
17726
|
+
let result;
|
|
17503
17727
|
try {
|
|
17504
17728
|
reader.buildGuidMap();
|
|
17505
17729
|
const diagnostics = [];
|
|
@@ -17526,13 +17750,23 @@ async function fromIfc(bytes, options = {}) {
|
|
|
17526
17750
|
diagnostics: report,
|
|
17527
17751
|
...applicationName !== void 0 ? { applicationName } : {}
|
|
17528
17752
|
};
|
|
17529
|
-
|
|
17753
|
+
result = ok(model);
|
|
17530
17754
|
} catch (e) {
|
|
17531
|
-
|
|
17532
|
-
|
|
17533
|
-
|
|
17755
|
+
result = err(importError("IMPORT_FAILED", "Unexpected failure during IFC import", e));
|
|
17756
|
+
}
|
|
17757
|
+
try {
|
|
17534
17758
|
reader.close();
|
|
17759
|
+
} catch (cause) {
|
|
17760
|
+
result = err(result.ok ? importError("IMPORT_CLOSE_FAILED", "Failed to close IFC reader", cause) : {
|
|
17761
|
+
...result.error,
|
|
17762
|
+
metadata: {
|
|
17763
|
+
...result.error.metadata,
|
|
17764
|
+
readerCloseCause: cause
|
|
17765
|
+
}
|
|
17766
|
+
});
|
|
17535
17767
|
}
|
|
17768
|
+
if (!result.ok) return err(withCleanup(result.error, disposeElements(elements), "fromIfc"));
|
|
17769
|
+
return result;
|
|
17536
17770
|
}
|
|
17537
17771
|
/**
|
|
17538
17772
|
* Reads one product into an {@link ImportedElement}. Returns null only when the
|
|
@@ -17583,8 +17817,8 @@ function readElement(reader, expressId, category, scale, containment, typeEnums,
|
|
|
17583
17817
|
...fills !== void 0 ? { fills } : {}
|
|
17584
17818
|
};
|
|
17585
17819
|
} catch (e) {
|
|
17586
|
-
|
|
17587
|
-
diagnostics.push(issue("error", "ELEMENT_READ_FAILED", `Element ${expressId} reconstruction threw: ${errMsg(e)}`, expressId));
|
|
17820
|
+
const failure = geometry === null ? e : withCleanup(importError("ELEMENT_READ_FAILED", "Element read failed", e), disposeGeometry(geometry), "readElement");
|
|
17821
|
+
diagnostics.push(issue("error", "ELEMENT_READ_FAILED", `Element ${expressId} reconstruction threw: ${errMsg(e)}`, expressId, { cause: failure }));
|
|
17588
17822
|
return null;
|
|
17589
17823
|
}
|
|
17590
17824
|
}
|
|
@@ -17600,36 +17834,79 @@ function findFills(reader, elementExpressId) {
|
|
|
17600
17834
|
}
|
|
17601
17835
|
/**
|
|
17602
17836
|
* Reconstructs a host element's body geometry and, per IFC `IfcRelVoidsElement`
|
|
17603
|
-
* semantics, subtracts
|
|
17837
|
+
* semantics, subtracts each opening's Body representation from a parametric host —
|
|
17604
17838
|
* so a wall with a door hole comes back as the cut solid, matching the source
|
|
17605
17839
|
* model. Falls back to the uncut solid (with a diagnostic) if a cut fails.
|
|
17606
17840
|
*/
|
|
17607
17841
|
function reconstructGeometry(reader, expressId, scale, voidedBy, diagnostics) {
|
|
17608
17842
|
const base = toImportedGeometry(reader, expressId, scale, diagnostics);
|
|
17609
17843
|
if (base.fidelity !== "PARAMETRIC" || base.completeness !== "COMPLETE" || voidedBy.length === 0) return base;
|
|
17610
|
-
|
|
17611
|
-
|
|
17612
|
-
|
|
17613
|
-
|
|
17614
|
-
|
|
17615
|
-
|
|
17616
|
-
|
|
17617
|
-
|
|
17844
|
+
if (base.solids[0] === void 0) return base;
|
|
17845
|
+
const hosts = [...base.solids];
|
|
17846
|
+
try {
|
|
17847
|
+
for (const openingId of voidedBy) try {
|
|
17848
|
+
var _usingCtx$1 = _usingCtx();
|
|
17849
|
+
const opening = readBodyGeometry(reader, openingId, scale, diagnostics);
|
|
17850
|
+
if (opening.kind !== "SOLID") continue;
|
|
17851
|
+
const openingOwner = _usingCtx$1.u(ownOpening(opening.solid, openingId));
|
|
17852
|
+
for (let hostIndex = 0; hostIndex < hosts.length;) {
|
|
17618
17853
|
const host = hosts[hostIndex];
|
|
17619
|
-
if (host === void 0)
|
|
17620
|
-
const cutResult =
|
|
17854
|
+
if (host === void 0) break;
|
|
17855
|
+
const cutResult = cutImportedSolids(host, openingOwner.solid);
|
|
17621
17856
|
if (!cutResult.ok) {
|
|
17622
|
-
diagnostics.push(issue("warning", "VOID_SUBTRACTION_FAILED", `Opening ${openingId} could not be subtracted from element ${expressId}: ${cutResult.error.message}`, expressId));
|
|
17857
|
+
diagnostics.push(issue("warning", "VOID_SUBTRACTION_FAILED", `Opening ${openingId} could not be subtracted from element ${expressId}: ${cutResult.error.message}`, expressId, { cause: cutResult.error }));
|
|
17858
|
+
hostIndex++;
|
|
17623
17859
|
continue;
|
|
17624
17860
|
}
|
|
17625
|
-
|
|
17626
|
-
|
|
17861
|
+
hosts.splice(hostIndex, 1, ...cutResult.value);
|
|
17862
|
+
const cleanup = cleanupOwnedResources([{
|
|
17863
|
+
resource: host,
|
|
17864
|
+
itemIndex: hostIndex
|
|
17865
|
+
}], { operation: "importOpening" });
|
|
17866
|
+
if (cleanup.kind === "FAILED") diagnostics.push(issue("warning", "VOID_HOST_CLEANUP_FAILED", "Opening result retained, but previous host release failed", expressId, { cleanup }));
|
|
17867
|
+
hostIndex += cutResult.value.length;
|
|
17627
17868
|
}
|
|
17869
|
+
} catch (_) {
|
|
17870
|
+
_usingCtx$1.e = _;
|
|
17628
17871
|
} finally {
|
|
17629
|
-
|
|
17872
|
+
_usingCtx$1.d();
|
|
17630
17873
|
}
|
|
17874
|
+
return completeImportedGeometry("PARAMETRIC", hosts, expressId, diagnostics);
|
|
17875
|
+
} catch (cause) {
|
|
17876
|
+
const failure = importError("GEOMETRY_RECONSTRUCTION_FAILED", "Opening reconstruction failed", cause);
|
|
17877
|
+
const cleanup = cleanupOwnedResources(hosts.map((resource, itemIndex) => ({
|
|
17878
|
+
resource,
|
|
17879
|
+
itemIndex
|
|
17880
|
+
})), { operation: "reconstructGeometry" });
|
|
17881
|
+
throw Object.assign(new Error(failure.message, { cause }), {
|
|
17882
|
+
code: failure.code,
|
|
17883
|
+
metadata: withCleanup(failure, cleanup, "reconstructGeometry").metadata
|
|
17884
|
+
});
|
|
17631
17885
|
}
|
|
17632
|
-
|
|
17886
|
+
}
|
|
17887
|
+
function ownOpening(solid, openingId) {
|
|
17888
|
+
return {
|
|
17889
|
+
solid,
|
|
17890
|
+
[Symbol.dispose]() {
|
|
17891
|
+
const cleanup = cleanupOwnedResources([{
|
|
17892
|
+
resource: solid,
|
|
17893
|
+
itemIndex: 0
|
|
17894
|
+
}], { operation: "importOpeningTool" });
|
|
17895
|
+
if (cleanup.kind === "FAILED") throw new Error(`Opening ${openingId} cleanup failed`, { cause: {
|
|
17896
|
+
...importError("OPENING_CLEANUP_FAILED", "Temporary opening release failed"),
|
|
17897
|
+
metadata: { cleanup }
|
|
17898
|
+
} });
|
|
17899
|
+
}
|
|
17900
|
+
};
|
|
17901
|
+
}
|
|
17902
|
+
function withCleanup(error, cleanup, operation) {
|
|
17903
|
+
return {
|
|
17904
|
+
...error,
|
|
17905
|
+
metadata: {
|
|
17906
|
+
...error.metadata,
|
|
17907
|
+
cleanup: cleanupReport([...reportedGeometryCleanup(error, operation), ...cleanup.kind === "FAILED" ? cleanup.diagnostics : []])
|
|
17908
|
+
}
|
|
17909
|
+
};
|
|
17633
17910
|
}
|
|
17634
17911
|
function toImportedGeometry(reader, expressId, scale, diagnostics) {
|
|
17635
17912
|
const body = readBodyItems(reader, expressId, scale, diagnostics);
|
|
@@ -17677,61 +17954,48 @@ function completeImportedGeometry(fidelity, solids, expressId, diagnostics) {
|
|
|
17677
17954
|
fidelity,
|
|
17678
17955
|
completeness: "COMPLETE",
|
|
17679
17956
|
solids,
|
|
17680
|
-
solid: solids.length === 1 ? solids[0] : null,
|
|
17957
|
+
solid: solids.length === 1 ? solids[0] ?? null : null,
|
|
17681
17958
|
...measureCompleteBody(solids, expressId, diagnostics)
|
|
17682
17959
|
};
|
|
17683
17960
|
}
|
|
17684
17961
|
function measureCompleteBody(solids, expressId, diagnostics) {
|
|
17962
|
+
const unavailable = (cause, message = errMsg(cause)) => {
|
|
17963
|
+
diagnostics.push(issue("warning", "BODY_AGGREGATE_MEASUREMENT_FAILED", `Complete Body aggregate measurement failed: ${message}`, expressId, { cause }));
|
|
17964
|
+
return {
|
|
17965
|
+
bounds: null,
|
|
17966
|
+
volumeMm3: null
|
|
17967
|
+
};
|
|
17968
|
+
};
|
|
17685
17969
|
try {
|
|
17686
|
-
const first = solids
|
|
17970
|
+
const [first, ...rest] = solids;
|
|
17687
17971
|
if (first === void 0) return {
|
|
17688
17972
|
bounds: null,
|
|
17689
17973
|
volumeMm3: null
|
|
17690
17974
|
};
|
|
17691
|
-
const
|
|
17692
|
-
|
|
17693
|
-
|
|
17694
|
-
|
|
17695
|
-
|
|
17696
|
-
let zMin = initial.zMin;
|
|
17697
|
-
let zMax = initial.zMax;
|
|
17698
|
-
let volumeMm3 = 0;
|
|
17699
|
-
for (const solid of solids) {
|
|
17700
|
-
const measured = measureVolume(solid);
|
|
17701
|
-
if (!measured.ok) throw new Error(measured.error.message);
|
|
17702
|
-
volumeMm3 += measured.value;
|
|
17703
|
-
const itemBounds = getBounds(solid);
|
|
17704
|
-
xMin = Math.min(xMin, itemBounds.xMin);
|
|
17705
|
-
xMax = Math.max(xMax, itemBounds.xMax);
|
|
17706
|
-
yMin = Math.min(yMin, itemBounds.yMin);
|
|
17707
|
-
yMax = Math.max(yMax, itemBounds.yMax);
|
|
17708
|
-
zMin = Math.min(zMin, itemBounds.zMin);
|
|
17709
|
-
zMax = Math.max(zMax, itemBounds.zMax);
|
|
17710
|
-
}
|
|
17975
|
+
const items = [first, ...rest];
|
|
17976
|
+
const bounds = productBodyBounds(items);
|
|
17977
|
+
if (!bounds.ok) return unavailable(bounds.error, bounds.error.message);
|
|
17978
|
+
const volume = measureProductBodyMaterial(items);
|
|
17979
|
+
if (!volume.ok) return unavailable(volume.error, volume.error.message);
|
|
17711
17980
|
return {
|
|
17712
|
-
bounds:
|
|
17713
|
-
|
|
17714
|
-
xMax,
|
|
17715
|
-
yMin,
|
|
17716
|
-
yMax,
|
|
17717
|
-
zMin,
|
|
17718
|
-
zMax
|
|
17719
|
-
},
|
|
17720
|
-
volumeMm3
|
|
17981
|
+
bounds: bounds.value.bounds,
|
|
17982
|
+
volumeMm3: volume.value
|
|
17721
17983
|
};
|
|
17722
17984
|
} catch (cause) {
|
|
17723
|
-
|
|
17724
|
-
return {
|
|
17725
|
-
bounds: null,
|
|
17726
|
-
volumeMm3: null
|
|
17727
|
-
};
|
|
17985
|
+
return unavailable(cause);
|
|
17728
17986
|
}
|
|
17729
17987
|
}
|
|
17730
17988
|
function disposeGeometry(geometry) {
|
|
17731
|
-
|
|
17989
|
+
return cleanupOwnedResources(geometry.solids.map((resource, itemIndex) => ({
|
|
17990
|
+
resource,
|
|
17991
|
+
itemIndex
|
|
17992
|
+
})), { operation: "disposeImportedGeometry" });
|
|
17732
17993
|
}
|
|
17733
17994
|
function disposeElements(elements) {
|
|
17734
|
-
|
|
17995
|
+
return cleanupOwnedResources(elements.flatMap(({ geometry }) => geometry.solids).map((resource, itemIndex) => ({
|
|
17996
|
+
resource,
|
|
17997
|
+
itemIndex
|
|
17998
|
+
})), { operation: "disposeImportedElements" });
|
|
17735
17999
|
}
|
|
17736
18000
|
function toImportedPset(pset) {
|
|
17737
18001
|
return {
|