brepjs-bim 0.17.2 → 0.18.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 +7 -0
- package/dist/brepjs-bim.cjs +15 -3
- package/dist/brepjs-bim.js +15 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -14,6 +14,13 @@ and serializes the result to a valid **IFC-SPF** file — with a matching import
|
|
|
14
14
|
Pipeline: **author spec → `BimModel` (typed element + brepjs geometry) → spatial structure +
|
|
15
15
|
property sets + classification → export IFC / COBie, validate, round-trip.**
|
|
16
16
|
|
|
17
|
+
The declarative entry point is
|
|
18
|
+
[`brepjs-families`](https://www.npmjs.com/package/brepjs-families): author the building as a tree of
|
|
19
|
+
prop-driven components, then `familiesToBim(tree, { project })` projects it onto a `BimModel` with
|
|
20
|
+
stable GlobalIds derived from component key paths. Hand-authoring specs against `BimModel` remains
|
|
21
|
+
the low-level path (and covers elements the declarative route doesn't yet). See the
|
|
22
|
+
[Declarative Models guide](https://brepjs.dev/families/overview).
|
|
23
|
+
|
|
17
24
|
## Scope
|
|
18
25
|
|
|
19
26
|
Parametric authoring of the common IFC4 building elements plus the data layers that make a model
|
package/dist/brepjs-bim.cjs
CHANGED
|
@@ -27735,6 +27735,16 @@ function peelTranslates(node) {
|
|
|
27735
27735
|
moved
|
|
27736
27736
|
};
|
|
27737
27737
|
}
|
|
27738
|
+
/** True when the element's transform PROP carries a rotation. The spec path
|
|
27739
|
+
* folds only translations into IfcLocalPlacement (walls orient via `axisX`),
|
|
27740
|
+
* so a tRotate placement would export un-rotated while the viewport shows it
|
|
27741
|
+
* rotated — reject instead of diverging. Rotations a family render bakes
|
|
27742
|
+
* into its own body geometry (e.g. a circular beam oriented along axisX) are
|
|
27743
|
+
* fine: the spec rebuilds that body parametrically from props. */
|
|
27744
|
+
function hasRotateOp(el) {
|
|
27745
|
+
const ops = el.props["transform"];
|
|
27746
|
+
return Array.isArray(ops) && ops.some((op) => typeof op === "object" && op !== null && op.op === "rotate");
|
|
27747
|
+
}
|
|
27738
27748
|
/** Fold the resolved geometry's outer translate chain into the spec placement
|
|
27739
27749
|
* origin, so IfcLocalPlacement matches the IR world frame no matter where the
|
|
27740
27750
|
* transform came from (family-internal or prop-level). */
|
|
@@ -27890,7 +27900,8 @@ function familiesToBim(root, options) {
|
|
|
27890
27900
|
if (project !== null) model.aggregate(project.localId, siteResult.value);
|
|
27891
27901
|
model.aggregate(siteResult.value, buildingId);
|
|
27892
27902
|
const idByKeyPath = /* @__PURE__ */ new Map();
|
|
27893
|
-
const walk = (el, storeyId) => {
|
|
27903
|
+
const walk = (el, storeyId, rotated) => {
|
|
27904
|
+
const rotatedHere = rotated || hasRotateOp(el);
|
|
27894
27905
|
let containerId = storeyId;
|
|
27895
27906
|
const route = specRoute(el.type);
|
|
27896
27907
|
if (el.type === "Storey") {
|
|
@@ -27907,6 +27918,7 @@ function familiesToBim(root, options) {
|
|
|
27907
27918
|
} else if (route !== void 0) {
|
|
27908
27919
|
const keyed = requireKeyed(el);
|
|
27909
27920
|
if (!keyed.ok) return keyed;
|
|
27921
|
+
if (rotatedHere) return (0, brepjs.err)(specError("FAMILIES_UNSUPPORTED_TRANSFORM", `familiesToBim: '${el.keyPath}' carries a rotated placement — the spec path folds only translations into IfcLocalPlacement; orient walls via axisX instead of tRotate`));
|
|
27910
27922
|
const voids = el.props["voids"];
|
|
27911
27923
|
if (Array.isArray(voids)) {
|
|
27912
27924
|
const openings = el.children.filter((c) => c.type === "Opening").length;
|
|
@@ -27927,12 +27939,12 @@ function familiesToBim(root, options) {
|
|
|
27927
27939
|
else if (el.type !== "Group" && el.geometry.kind !== "Empty") return (0, brepjs.err)(specError("FAMILIES_UNSUPPORTED_TYPE", `familiesToBim: no spec mapping for element type '${el.type}' at '${el.keyPath}'`));
|
|
27928
27940
|
for (const child of el.children) {
|
|
27929
27941
|
if (el.type === "Wall" && child.type === "Opening") continue;
|
|
27930
|
-
const r = walk(child, containerId);
|
|
27942
|
+
const r = walk(child, containerId, rotatedHere);
|
|
27931
27943
|
if (!r.ok) return r;
|
|
27932
27944
|
}
|
|
27933
27945
|
return (0, brepjs.ok)(void 0);
|
|
27934
27946
|
};
|
|
27935
|
-
const walked = walk(root, null);
|
|
27947
|
+
const walked = walk(root, null, false);
|
|
27936
27948
|
if (!walked.ok) {
|
|
27937
27949
|
model[Symbol.dispose]();
|
|
27938
27950
|
return walked;
|
package/dist/brepjs-bim.js
CHANGED
|
@@ -27712,6 +27712,16 @@ function peelTranslates(node) {
|
|
|
27712
27712
|
moved
|
|
27713
27713
|
};
|
|
27714
27714
|
}
|
|
27715
|
+
/** True when the element's transform PROP carries a rotation. The spec path
|
|
27716
|
+
* folds only translations into IfcLocalPlacement (walls orient via `axisX`),
|
|
27717
|
+
* so a tRotate placement would export un-rotated while the viewport shows it
|
|
27718
|
+
* rotated — reject instead of diverging. Rotations a family render bakes
|
|
27719
|
+
* into its own body geometry (e.g. a circular beam oriented along axisX) are
|
|
27720
|
+
* fine: the spec rebuilds that body parametrically from props. */
|
|
27721
|
+
function hasRotateOp(el) {
|
|
27722
|
+
const ops = el.props["transform"];
|
|
27723
|
+
return Array.isArray(ops) && ops.some((op) => typeof op === "object" && op !== null && op.op === "rotate");
|
|
27724
|
+
}
|
|
27715
27725
|
/** Fold the resolved geometry's outer translate chain into the spec placement
|
|
27716
27726
|
* origin, so IfcLocalPlacement matches the IR world frame no matter where the
|
|
27717
27727
|
* transform came from (family-internal or prop-level). */
|
|
@@ -27867,7 +27877,8 @@ function familiesToBim(root, options) {
|
|
|
27867
27877
|
if (project !== null) model.aggregate(project.localId, siteResult.value);
|
|
27868
27878
|
model.aggregate(siteResult.value, buildingId);
|
|
27869
27879
|
const idByKeyPath = /* @__PURE__ */ new Map();
|
|
27870
|
-
const walk = (el, storeyId) => {
|
|
27880
|
+
const walk = (el, storeyId, rotated) => {
|
|
27881
|
+
const rotatedHere = rotated || hasRotateOp(el);
|
|
27871
27882
|
let containerId = storeyId;
|
|
27872
27883
|
const route = specRoute(el.type);
|
|
27873
27884
|
if (el.type === "Storey") {
|
|
@@ -27884,6 +27895,7 @@ function familiesToBim(root, options) {
|
|
|
27884
27895
|
} else if (route !== void 0) {
|
|
27885
27896
|
const keyed = requireKeyed(el);
|
|
27886
27897
|
if (!keyed.ok) return keyed;
|
|
27898
|
+
if (rotatedHere) return err(specError("FAMILIES_UNSUPPORTED_TRANSFORM", `familiesToBim: '${el.keyPath}' carries a rotated placement — the spec path folds only translations into IfcLocalPlacement; orient walls via axisX instead of tRotate`));
|
|
27887
27899
|
const voids = el.props["voids"];
|
|
27888
27900
|
if (Array.isArray(voids)) {
|
|
27889
27901
|
const openings = el.children.filter((c) => c.type === "Opening").length;
|
|
@@ -27904,12 +27916,12 @@ function familiesToBim(root, options) {
|
|
|
27904
27916
|
else if (el.type !== "Group" && el.geometry.kind !== "Empty") return err(specError("FAMILIES_UNSUPPORTED_TYPE", `familiesToBim: no spec mapping for element type '${el.type}' at '${el.keyPath}'`));
|
|
27905
27917
|
for (const child of el.children) {
|
|
27906
27918
|
if (el.type === "Wall" && child.type === "Opening") continue;
|
|
27907
|
-
const r = walk(child, containerId);
|
|
27919
|
+
const r = walk(child, containerId, rotatedHere);
|
|
27908
27920
|
if (!r.ok) return r;
|
|
27909
27921
|
}
|
|
27910
27922
|
return ok(void 0);
|
|
27911
27923
|
};
|
|
27912
|
-
const walked = walk(root, null);
|
|
27924
|
+
const walked = walk(root, null, false);
|
|
27913
27925
|
if (!walked.ok) {
|
|
27914
27926
|
model[Symbol.dispose]();
|
|
27915
27927
|
return walked;
|