brepjs-bim 0.17.0 → 0.17.2
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/dist/brepjs-bim.cjs +65 -10
- package/dist/brepjs-bim.js +65 -10
- package/dist/elementFns/placedGeometry.d.ts +4 -2
- package/package.json +1 -1
package/dist/brepjs-bim.cjs
CHANGED
|
@@ -7393,8 +7393,10 @@ function disposeAll(solids) {
|
|
|
7393
7393
|
*
|
|
7394
7394
|
* Stairs and ramps carry no element solid (`.geometry` is null), so flight
|
|
7395
7395
|
* solids are built from `spec.flights` and placed per flight. Curtain walls
|
|
7396
|
-
* return placed panels + mullions.
|
|
7397
|
-
* (
|
|
7396
|
+
* return placed panels + mullions. Proxies are authored in world coordinates
|
|
7397
|
+
* (no placement frame), so their solid is returned as a fresh identity-placed
|
|
7398
|
+
* copy. Elements with no solid geometry (doors/windows/groups/spatial) return
|
|
7399
|
+
* an empty array.
|
|
7398
7400
|
*/
|
|
7399
7401
|
function placedSolids(el) {
|
|
7400
7402
|
switch (el.category) {
|
|
@@ -7456,6 +7458,27 @@ function placedSolids(el) {
|
|
|
7456
7458
|
}
|
|
7457
7459
|
return (0, brepjs.ok)(out);
|
|
7458
7460
|
}
|
|
7461
|
+
case "PROXY": {
|
|
7462
|
+
const placed = place(el.geometry, {
|
|
7463
|
+
origin: [
|
|
7464
|
+
0,
|
|
7465
|
+
0,
|
|
7466
|
+
0
|
|
7467
|
+
],
|
|
7468
|
+
axisX: [
|
|
7469
|
+
1,
|
|
7470
|
+
0,
|
|
7471
|
+
0
|
|
7472
|
+
],
|
|
7473
|
+
axisZ: [
|
|
7474
|
+
0,
|
|
7475
|
+
0,
|
|
7476
|
+
1
|
|
7477
|
+
]
|
|
7478
|
+
});
|
|
7479
|
+
if (!placed.ok) return placed;
|
|
7480
|
+
return (0, brepjs.ok)([placed.value]);
|
|
7481
|
+
}
|
|
7459
7482
|
case "CURTAIN_WALL": {
|
|
7460
7483
|
const out = [];
|
|
7461
7484
|
for (const c of [...el.geometry.panels, ...el.geometry.mullions]) try {
|
|
@@ -27601,7 +27624,8 @@ function assignNum(target, key, value) {
|
|
|
27601
27624
|
* fill-role void (Door/Window family) maps onto addDoor/addWindow, which cut
|
|
27602
27625
|
* the wall and wire IfcRelVoidsElement + IfcRelFillsElement; the opening and
|
|
27603
27626
|
* filler GlobalIds derive from the synthesized key paths. Anonymous (non-fill)
|
|
27604
|
-
* voids
|
|
27627
|
+
* voids are rejected: they cut only the IR/viewport geometry, and exporting
|
|
27628
|
+
* the uncut spec body would silently diverge from what the user sees.
|
|
27605
27629
|
*/
|
|
27606
27630
|
var SPEC_DEFAULTS = {
|
|
27607
27631
|
origin: [
|
|
@@ -27742,18 +27766,43 @@ function specInput(el) {
|
|
|
27742
27766
|
...collectSpecProps(el)
|
|
27743
27767
|
};
|
|
27744
27768
|
}
|
|
27769
|
+
/** `Pset_<Type>Common` fields the specs model first-class: mapped onto their
|
|
27770
|
+
* spec names so the writer emits them in the element's own common pset. */
|
|
27771
|
+
var COMMON_PSET_FIELDS = {
|
|
27772
|
+
IsExternal: "isExternal",
|
|
27773
|
+
FireRating: "fireRating",
|
|
27774
|
+
AcousticRating: "acousticRating",
|
|
27775
|
+
ThermalTransmittance: "thermalTransmittance",
|
|
27776
|
+
LoadBearing: "loadBearing",
|
|
27777
|
+
Status: "status"
|
|
27778
|
+
};
|
|
27745
27779
|
function collectSpecProps(el) {
|
|
27746
|
-
const psets = el.attributes["psets"];
|
|
27747
27780
|
const out = {};
|
|
27781
|
+
const material = el.attributes["material"];
|
|
27782
|
+
if (typeof material === "string" && el.props["materialName"] === void 0) out["materialName"] = material;
|
|
27783
|
+
const psets = el.attributes["psets"];
|
|
27748
27784
|
if (psets && typeof psets === "object") {
|
|
27749
|
-
const
|
|
27750
|
-
|
|
27751
|
-
|
|
27752
|
-
if (typeof
|
|
27753
|
-
|
|
27785
|
+
const custom = {};
|
|
27786
|
+
const ownCommonPset = `Pset_${el.type}Common`;
|
|
27787
|
+
for (const [psetName, fields] of Object.entries(psets)) {
|
|
27788
|
+
if (!fields || typeof fields !== "object") continue;
|
|
27789
|
+
const record = fields;
|
|
27790
|
+
if (psetName === ownCommonPset) {
|
|
27791
|
+
for (const [field, specKey] of Object.entries(COMMON_PSET_FIELDS)) if (record[field] !== void 0) out[specKey] = record[field];
|
|
27792
|
+
} else {
|
|
27793
|
+
const values = {};
|
|
27794
|
+
for (const [field, value] of Object.entries(record)) if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") values[field] = value;
|
|
27795
|
+
if (Object.keys(values).length > 0) custom[psetName] = values;
|
|
27796
|
+
}
|
|
27797
|
+
}
|
|
27798
|
+
if (Object.keys(custom).length > 0) {
|
|
27799
|
+
const declared = el.props["customProperties"];
|
|
27800
|
+
out["customProperties"] = declared && typeof declared === "object" ? {
|
|
27801
|
+
...custom,
|
|
27802
|
+
...declared
|
|
27803
|
+
} : custom;
|
|
27754
27804
|
}
|
|
27755
27805
|
}
|
|
27756
|
-
delete out["psets"];
|
|
27757
27806
|
return out;
|
|
27758
27807
|
}
|
|
27759
27808
|
function addFill(model, fill, input, identity) {
|
|
@@ -27794,6 +27843,7 @@ function addOpenings(model, host, wallId, containerId, idByKeyPath) {
|
|
|
27794
27843
|
const added = addFill(model, fill, {
|
|
27795
27844
|
materialName: SPEC_DEFAULTS.materialName,
|
|
27796
27845
|
...stripGeometryProps(fill.props),
|
|
27846
|
+
...collectSpecProps(fill),
|
|
27797
27847
|
wallLocalId: wallId,
|
|
27798
27848
|
offsetAlongWall: delta[0] * axisX[0] + delta[1] * axisX[1] + delta[2] * axisX[2],
|
|
27799
27849
|
offsetFromFloor: delta[2]
|
|
@@ -27857,6 +27907,11 @@ function familiesToBim(root, options) {
|
|
|
27857
27907
|
} else if (route !== void 0) {
|
|
27858
27908
|
const keyed = requireKeyed(el);
|
|
27859
27909
|
if (!keyed.ok) return keyed;
|
|
27910
|
+
const voids = el.props["voids"];
|
|
27911
|
+
if (Array.isArray(voids)) {
|
|
27912
|
+
const openings = el.children.filter((c) => c.type === "Opening").length;
|
|
27913
|
+
if (voids.length > openings) return (0, brepjs.err)(specError("FAMILIES_ANONYMOUS_VOID", `familiesToBim: '${el.keyPath}' has ${voids.length - openings} anonymous void(s) the IFC body cannot carry — use a fill-role family (Door/Window) for each void`));
|
|
27914
|
+
}
|
|
27860
27915
|
const parsed = route.parse(("input" in route ? route.input : specInput)(el));
|
|
27861
27916
|
if (!parsed.ok) return parsed;
|
|
27862
27917
|
const added = route.add(model, parsed.value, el.keyPath);
|
package/dist/brepjs-bim.js
CHANGED
|
@@ -7370,8 +7370,10 @@ function disposeAll(solids) {
|
|
|
7370
7370
|
*
|
|
7371
7371
|
* Stairs and ramps carry no element solid (`.geometry` is null), so flight
|
|
7372
7372
|
* solids are built from `spec.flights` and placed per flight. Curtain walls
|
|
7373
|
-
* return placed panels + mullions.
|
|
7374
|
-
* (
|
|
7373
|
+
* return placed panels + mullions. Proxies are authored in world coordinates
|
|
7374
|
+
* (no placement frame), so their solid is returned as a fresh identity-placed
|
|
7375
|
+
* copy. Elements with no solid geometry (doors/windows/groups/spatial) return
|
|
7376
|
+
* an empty array.
|
|
7375
7377
|
*/
|
|
7376
7378
|
function placedSolids(el) {
|
|
7377
7379
|
switch (el.category) {
|
|
@@ -7433,6 +7435,27 @@ function placedSolids(el) {
|
|
|
7433
7435
|
}
|
|
7434
7436
|
return ok(out);
|
|
7435
7437
|
}
|
|
7438
|
+
case "PROXY": {
|
|
7439
|
+
const placed = place(el.geometry, {
|
|
7440
|
+
origin: [
|
|
7441
|
+
0,
|
|
7442
|
+
0,
|
|
7443
|
+
0
|
|
7444
|
+
],
|
|
7445
|
+
axisX: [
|
|
7446
|
+
1,
|
|
7447
|
+
0,
|
|
7448
|
+
0
|
|
7449
|
+
],
|
|
7450
|
+
axisZ: [
|
|
7451
|
+
0,
|
|
7452
|
+
0,
|
|
7453
|
+
1
|
|
7454
|
+
]
|
|
7455
|
+
});
|
|
7456
|
+
if (!placed.ok) return placed;
|
|
7457
|
+
return ok([placed.value]);
|
|
7458
|
+
}
|
|
7436
7459
|
case "CURTAIN_WALL": {
|
|
7437
7460
|
const out = [];
|
|
7438
7461
|
for (const c of [...el.geometry.panels, ...el.geometry.mullions]) try {
|
|
@@ -27578,7 +27601,8 @@ function assignNum(target, key, value) {
|
|
|
27578
27601
|
* fill-role void (Door/Window family) maps onto addDoor/addWindow, which cut
|
|
27579
27602
|
* the wall and wire IfcRelVoidsElement + IfcRelFillsElement; the opening and
|
|
27580
27603
|
* filler GlobalIds derive from the synthesized key paths. Anonymous (non-fill)
|
|
27581
|
-
* voids
|
|
27604
|
+
* voids are rejected: they cut only the IR/viewport geometry, and exporting
|
|
27605
|
+
* the uncut spec body would silently diverge from what the user sees.
|
|
27582
27606
|
*/
|
|
27583
27607
|
var SPEC_DEFAULTS = {
|
|
27584
27608
|
origin: [
|
|
@@ -27719,18 +27743,43 @@ function specInput(el) {
|
|
|
27719
27743
|
...collectSpecProps(el)
|
|
27720
27744
|
};
|
|
27721
27745
|
}
|
|
27746
|
+
/** `Pset_<Type>Common` fields the specs model first-class: mapped onto their
|
|
27747
|
+
* spec names so the writer emits them in the element's own common pset. */
|
|
27748
|
+
var COMMON_PSET_FIELDS = {
|
|
27749
|
+
IsExternal: "isExternal",
|
|
27750
|
+
FireRating: "fireRating",
|
|
27751
|
+
AcousticRating: "acousticRating",
|
|
27752
|
+
ThermalTransmittance: "thermalTransmittance",
|
|
27753
|
+
LoadBearing: "loadBearing",
|
|
27754
|
+
Status: "status"
|
|
27755
|
+
};
|
|
27722
27756
|
function collectSpecProps(el) {
|
|
27723
|
-
const psets = el.attributes["psets"];
|
|
27724
27757
|
const out = {};
|
|
27758
|
+
const material = el.attributes["material"];
|
|
27759
|
+
if (typeof material === "string" && el.props["materialName"] === void 0) out["materialName"] = material;
|
|
27760
|
+
const psets = el.attributes["psets"];
|
|
27725
27761
|
if (psets && typeof psets === "object") {
|
|
27726
|
-
const
|
|
27727
|
-
|
|
27728
|
-
|
|
27729
|
-
if (typeof
|
|
27730
|
-
|
|
27762
|
+
const custom = {};
|
|
27763
|
+
const ownCommonPset = `Pset_${el.type}Common`;
|
|
27764
|
+
for (const [psetName, fields] of Object.entries(psets)) {
|
|
27765
|
+
if (!fields || typeof fields !== "object") continue;
|
|
27766
|
+
const record = fields;
|
|
27767
|
+
if (psetName === ownCommonPset) {
|
|
27768
|
+
for (const [field, specKey] of Object.entries(COMMON_PSET_FIELDS)) if (record[field] !== void 0) out[specKey] = record[field];
|
|
27769
|
+
} else {
|
|
27770
|
+
const values = {};
|
|
27771
|
+
for (const [field, value] of Object.entries(record)) if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") values[field] = value;
|
|
27772
|
+
if (Object.keys(values).length > 0) custom[psetName] = values;
|
|
27773
|
+
}
|
|
27774
|
+
}
|
|
27775
|
+
if (Object.keys(custom).length > 0) {
|
|
27776
|
+
const declared = el.props["customProperties"];
|
|
27777
|
+
out["customProperties"] = declared && typeof declared === "object" ? {
|
|
27778
|
+
...custom,
|
|
27779
|
+
...declared
|
|
27780
|
+
} : custom;
|
|
27731
27781
|
}
|
|
27732
27782
|
}
|
|
27733
|
-
delete out["psets"];
|
|
27734
27783
|
return out;
|
|
27735
27784
|
}
|
|
27736
27785
|
function addFill(model, fill, input, identity) {
|
|
@@ -27771,6 +27820,7 @@ function addOpenings(model, host, wallId, containerId, idByKeyPath) {
|
|
|
27771
27820
|
const added = addFill(model, fill, {
|
|
27772
27821
|
materialName: SPEC_DEFAULTS.materialName,
|
|
27773
27822
|
...stripGeometryProps(fill.props),
|
|
27823
|
+
...collectSpecProps(fill),
|
|
27774
27824
|
wallLocalId: wallId,
|
|
27775
27825
|
offsetAlongWall: delta[0] * axisX[0] + delta[1] * axisX[1] + delta[2] * axisX[2],
|
|
27776
27826
|
offsetFromFloor: delta[2]
|
|
@@ -27834,6 +27884,11 @@ function familiesToBim(root, options) {
|
|
|
27834
27884
|
} else if (route !== void 0) {
|
|
27835
27885
|
const keyed = requireKeyed(el);
|
|
27836
27886
|
if (!keyed.ok) return keyed;
|
|
27887
|
+
const voids = el.props["voids"];
|
|
27888
|
+
if (Array.isArray(voids)) {
|
|
27889
|
+
const openings = el.children.filter((c) => c.type === "Opening").length;
|
|
27890
|
+
if (voids.length > openings) return err(specError("FAMILIES_ANONYMOUS_VOID", `familiesToBim: '${el.keyPath}' has ${voids.length - openings} anonymous void(s) the IFC body cannot carry — use a fill-role family (Door/Window) for each void`));
|
|
27891
|
+
}
|
|
27837
27892
|
const parsed = route.parse(("input" in route ? route.input : specInput)(el));
|
|
27838
27893
|
if (!parsed.ok) return parsed;
|
|
27839
27894
|
const added = route.add(model, parsed.value, el.keyPath);
|
|
@@ -12,7 +12,9 @@ import { BimError } from '../errors/bimError.js';
|
|
|
12
12
|
*
|
|
13
13
|
* Stairs and ramps carry no element solid (`.geometry` is null), so flight
|
|
14
14
|
* solids are built from `spec.flights` and placed per flight. Curtain walls
|
|
15
|
-
* return placed panels + mullions.
|
|
16
|
-
* (
|
|
15
|
+
* return placed panels + mullions. Proxies are authored in world coordinates
|
|
16
|
+
* (no placement frame), so their solid is returned as a fresh identity-placed
|
|
17
|
+
* copy. Elements with no solid geometry (doors/windows/groups/spatial) return
|
|
18
|
+
* an empty array.
|
|
17
19
|
*/
|
|
18
20
|
export declare function placedSolids(el: AnyBimElement): Result<readonly ValidSolid[], BimError>;
|