brepjs-bim 0.19.0 → 0.20.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/dist/brepjs-bim.cjs +50 -21
- package/dist/brepjs-bim.js +50 -21
- package/dist/familiesAdapter.d.ts +14 -0
- package/dist/index.d.ts +1 -1
- package/package.json +1 -1
package/dist/brepjs-bim.cjs
CHANGED
|
@@ -27652,27 +27652,27 @@ var GEOMETRY_PROPS = /* @__PURE__ */ new Set([
|
|
|
27652
27652
|
"psets"
|
|
27653
27653
|
]);
|
|
27654
27654
|
var SPEC_ROUTES = {
|
|
27655
|
-
|
|
27655
|
+
wall: {
|
|
27656
27656
|
parse: parseWallSpec,
|
|
27657
27657
|
add: (m, spec, key) => m.addWall(spec, { stableKey: key })
|
|
27658
27658
|
},
|
|
27659
|
-
|
|
27659
|
+
slab: {
|
|
27660
27660
|
parse: parseSlabSpec,
|
|
27661
27661
|
add: (m, spec, key) => m.addSlab(spec, { stableKey: key })
|
|
27662
27662
|
},
|
|
27663
|
-
|
|
27663
|
+
column: {
|
|
27664
27664
|
parse: parseColumnSpec,
|
|
27665
27665
|
add: (m, spec, key) => m.addColumn(spec, { stableKey: key })
|
|
27666
27666
|
},
|
|
27667
|
-
|
|
27667
|
+
beam: {
|
|
27668
27668
|
parse: parseBeamSpec,
|
|
27669
27669
|
add: (m, spec, key) => m.addBeam(spec, { stableKey: key })
|
|
27670
27670
|
},
|
|
27671
|
-
|
|
27671
|
+
roof: {
|
|
27672
27672
|
parse: parseRoofSpec,
|
|
27673
27673
|
add: (m, spec, key) => m.addRoof(spec, { stableKey: key })
|
|
27674
27674
|
},
|
|
27675
|
-
|
|
27675
|
+
stair: {
|
|
27676
27676
|
parse: parseStairSpec,
|
|
27677
27677
|
add: (m, spec, key) => m.addStair(spec, { stableKey: key }),
|
|
27678
27678
|
input: stairSpecInput
|
|
@@ -27707,8 +27707,28 @@ function stairSpecInput(el) {
|
|
|
27707
27707
|
})
|
|
27708
27708
|
};
|
|
27709
27709
|
}
|
|
27710
|
-
|
|
27711
|
-
|
|
27710
|
+
/**
|
|
27711
|
+
* Families predating `archetype` are routed by their display name. Keeping
|
|
27712
|
+
* this fallback makes the declaration purely additive, at the cost of the
|
|
27713
|
+
* original trap surviving for undeclared families: rename one and it stops
|
|
27714
|
+
* routing.
|
|
27715
|
+
*/
|
|
27716
|
+
var NAME_ARCHETYPES = {
|
|
27717
|
+
Storey: "storey",
|
|
27718
|
+
Wall: "wall",
|
|
27719
|
+
Slab: "slab",
|
|
27720
|
+
Column: "column",
|
|
27721
|
+
Beam: "beam",
|
|
27722
|
+
Roof: "roof",
|
|
27723
|
+
Stair: "stair",
|
|
27724
|
+
Door: "door",
|
|
27725
|
+
Window: "window"
|
|
27726
|
+
};
|
|
27727
|
+
function archetypeFor(el) {
|
|
27728
|
+
return el.archetype ?? NAME_ARCHETYPES[el.type];
|
|
27729
|
+
}
|
|
27730
|
+
function specRoute(archetype) {
|
|
27731
|
+
return archetype !== void 0 && Object.hasOwn(SPEC_ROUTES, archetype) ? SPEC_ROUTES[archetype] : void 0;
|
|
27712
27732
|
}
|
|
27713
27733
|
/** Total of the resolved geometry's OUTER literal translate chain. The
|
|
27714
27734
|
* transform vocabulary is translate-only, so frame differences are exact
|
|
@@ -27816,17 +27836,18 @@ function collectSpecProps(el) {
|
|
|
27816
27836
|
return out;
|
|
27817
27837
|
}
|
|
27818
27838
|
function addFill(model, fill, input, identity) {
|
|
27819
|
-
|
|
27839
|
+
const archetype = archetypeFor(fill);
|
|
27840
|
+
if (archetype === "door") {
|
|
27820
27841
|
const parsed = parseDoorSpec(input);
|
|
27821
27842
|
if (!parsed.ok) return parsed;
|
|
27822
27843
|
return model.addDoor(parsed.value, identity);
|
|
27823
27844
|
}
|
|
27824
|
-
if (
|
|
27845
|
+
if (archetype === "window") {
|
|
27825
27846
|
const parsed = parseWindowSpec(input);
|
|
27826
27847
|
if (!parsed.ok) return parsed;
|
|
27827
27848
|
return model.addWindow(parsed.value, identity);
|
|
27828
27849
|
}
|
|
27829
|
-
return (0, brepjs.err)(specError("FAMILIES_UNSUPPORTED_FILL", `familiesToBim: no fill mapping for element type '${fill.type}' at '${fill.keyPath}'`));
|
|
27850
|
+
return (0, brepjs.err)(specError("FAMILIES_UNSUPPORTED_FILL", `familiesToBim: no fill mapping for element type '${fill.type}' at '${fill.keyPath}' (archetype: ${archetype ?? "none"}) — a filler needs archetype: 'door' or 'window'`));
|
|
27830
27851
|
}
|
|
27831
27852
|
/** Materialize an unrouted element's IR and add it as a proxy. The body is
|
|
27832
27853
|
* authoritative for a proxy (no parametric spec to diverge from), so baked
|
|
@@ -27930,12 +27951,14 @@ function familiesToBim(root, options) {
|
|
|
27930
27951
|
if (project !== null) model.aggregate(project.localId, siteResult.value);
|
|
27931
27952
|
model.aggregate(siteResult.value, buildingId);
|
|
27932
27953
|
const idByKeyPath = /* @__PURE__ */ new Map();
|
|
27954
|
+
const proxied = [];
|
|
27933
27955
|
const walk = (el, storeyId, rotated) => {
|
|
27934
27956
|
const rotatedHere = rotated || hasRotateOp(el);
|
|
27935
|
-
let
|
|
27957
|
+
let proxiedHere = false;
|
|
27936
27958
|
let containerId = storeyId;
|
|
27937
|
-
const
|
|
27938
|
-
|
|
27959
|
+
const archetype = archetypeFor(el);
|
|
27960
|
+
const route = specRoute(archetype);
|
|
27961
|
+
if (archetype === "storey") {
|
|
27939
27962
|
const keyed = requireKeyed(el);
|
|
27940
27963
|
if (!keyed.ok) return keyed;
|
|
27941
27964
|
const storeyResult = model.addStorey({
|
|
@@ -27960,26 +27983,31 @@ function familiesToBim(root, options) {
|
|
|
27960
27983
|
const added = route.add(model, parsed.value, el.keyPath);
|
|
27961
27984
|
if (!added.ok) return added;
|
|
27962
27985
|
idByKeyPath.set(el.keyPath, added.value);
|
|
27963
|
-
if (containerId === null) return (0, brepjs.err)(specError("FAMILIES_NO_STOREY", `familiesToBim: '${el.keyPath}' has no Storey ancestor — IFC elements need spatial containment`));
|
|
27986
|
+
if (containerId === null) return (0, brepjs.err)(specError("FAMILIES_NO_STOREY", `familiesToBim: '${el.keyPath}' has no Storey ancestor — IFC elements need spatial containment; a container family needs archetype: 'storey' to be recognised under any name`));
|
|
27964
27987
|
model.placeIn(added.value, containerId);
|
|
27965
|
-
if (
|
|
27988
|
+
if (archetype === "wall") {
|
|
27966
27989
|
const opened = addOpenings(model, el, added.value, containerId, idByKeyPath);
|
|
27967
27990
|
if (!opened.ok) return opened;
|
|
27968
27991
|
}
|
|
27969
27992
|
} else if (el.type === "Opening") return (0, brepjs.err)(specError("FAMILIES_OPENING_OUTSIDE_WALL", `familiesToBim: opening '${el.keyPath}' is not hosted by a Wall — only wall openings are mapped`));
|
|
27970
27993
|
else if (el.type !== "Group" && el.geometry.kind !== "Empty") {
|
|
27971
|
-
if (options.proxyEvaluator === void 0) return (0, brepjs.err)(specError("FAMILIES_UNSUPPORTED_TYPE", `familiesToBim: no spec mapping for element type '${el.type}' at '${el.keyPath}' — add a spec route, or pass proxyEvaluator to export it as an IfcBuildingElementProxy`));
|
|
27994
|
+
if (options.proxyEvaluator === void 0) return (0, brepjs.err)(specError("FAMILIES_UNSUPPORTED_TYPE", `familiesToBim: no spec mapping for element type '${el.type}' at '${el.keyPath}' (archetype: ${el.archetype ?? "none"}) — routing is by archetype, so declare one on the family, add a spec route, or pass proxyEvaluator to export it as an IfcBuildingElementProxy`));
|
|
27972
27995
|
const keyed = requireKeyed(el);
|
|
27973
27996
|
if (!keyed.ok) return keyed;
|
|
27974
|
-
if (containerId === null) return (0, brepjs.err)(specError("FAMILIES_NO_STOREY", `familiesToBim: '${el.keyPath}' has no Storey ancestor — IFC elements need spatial containment`));
|
|
27997
|
+
if (containerId === null) return (0, brepjs.err)(specError("FAMILIES_NO_STOREY", `familiesToBim: '${el.keyPath}' has no Storey ancestor — IFC elements need spatial containment; a container family needs archetype: 'storey' to be recognised under any name`));
|
|
27975
27998
|
const added = addProxyElement(model, el, options.proxyEvaluator);
|
|
27976
27999
|
if (!added.ok) return added;
|
|
27977
28000
|
model.placeIn(added.value, containerId);
|
|
27978
28001
|
idByKeyPath.set(el.keyPath, added.value);
|
|
27979
|
-
proxied
|
|
28002
|
+
proxied.push({
|
|
28003
|
+
keyPath: el.keyPath,
|
|
28004
|
+
type: el.type,
|
|
28005
|
+
archetype: el.archetype
|
|
28006
|
+
});
|
|
28007
|
+
proxiedHere = true;
|
|
27980
28008
|
}
|
|
27981
28009
|
for (const child of el.children) {
|
|
27982
|
-
if ((
|
|
28010
|
+
if ((archetype === "wall" || proxiedHere) && child.type === "Opening") continue;
|
|
27983
28011
|
const r = walk(child, containerId, rotatedHere);
|
|
27984
28012
|
if (!r.ok) return r;
|
|
27985
28013
|
}
|
|
@@ -27992,7 +28020,8 @@ function familiesToBim(root, options) {
|
|
|
27992
28020
|
}
|
|
27993
28021
|
return (0, brepjs.ok)({
|
|
27994
28022
|
model,
|
|
27995
|
-
idByKeyPath
|
|
28023
|
+
idByKeyPath,
|
|
28024
|
+
proxied
|
|
27996
28025
|
});
|
|
27997
28026
|
}
|
|
27998
28027
|
//#endregion
|
package/dist/brepjs-bim.js
CHANGED
|
@@ -27629,27 +27629,27 @@ var GEOMETRY_PROPS = /* @__PURE__ */ new Set([
|
|
|
27629
27629
|
"psets"
|
|
27630
27630
|
]);
|
|
27631
27631
|
var SPEC_ROUTES = {
|
|
27632
|
-
|
|
27632
|
+
wall: {
|
|
27633
27633
|
parse: parseWallSpec,
|
|
27634
27634
|
add: (m, spec, key) => m.addWall(spec, { stableKey: key })
|
|
27635
27635
|
},
|
|
27636
|
-
|
|
27636
|
+
slab: {
|
|
27637
27637
|
parse: parseSlabSpec,
|
|
27638
27638
|
add: (m, spec, key) => m.addSlab(spec, { stableKey: key })
|
|
27639
27639
|
},
|
|
27640
|
-
|
|
27640
|
+
column: {
|
|
27641
27641
|
parse: parseColumnSpec,
|
|
27642
27642
|
add: (m, spec, key) => m.addColumn(spec, { stableKey: key })
|
|
27643
27643
|
},
|
|
27644
|
-
|
|
27644
|
+
beam: {
|
|
27645
27645
|
parse: parseBeamSpec,
|
|
27646
27646
|
add: (m, spec, key) => m.addBeam(spec, { stableKey: key })
|
|
27647
27647
|
},
|
|
27648
|
-
|
|
27648
|
+
roof: {
|
|
27649
27649
|
parse: parseRoofSpec,
|
|
27650
27650
|
add: (m, spec, key) => m.addRoof(spec, { stableKey: key })
|
|
27651
27651
|
},
|
|
27652
|
-
|
|
27652
|
+
stair: {
|
|
27653
27653
|
parse: parseStairSpec,
|
|
27654
27654
|
add: (m, spec, key) => m.addStair(spec, { stableKey: key }),
|
|
27655
27655
|
input: stairSpecInput
|
|
@@ -27684,8 +27684,28 @@ function stairSpecInput(el) {
|
|
|
27684
27684
|
})
|
|
27685
27685
|
};
|
|
27686
27686
|
}
|
|
27687
|
-
|
|
27688
|
-
|
|
27687
|
+
/**
|
|
27688
|
+
* Families predating `archetype` are routed by their display name. Keeping
|
|
27689
|
+
* this fallback makes the declaration purely additive, at the cost of the
|
|
27690
|
+
* original trap surviving for undeclared families: rename one and it stops
|
|
27691
|
+
* routing.
|
|
27692
|
+
*/
|
|
27693
|
+
var NAME_ARCHETYPES = {
|
|
27694
|
+
Storey: "storey",
|
|
27695
|
+
Wall: "wall",
|
|
27696
|
+
Slab: "slab",
|
|
27697
|
+
Column: "column",
|
|
27698
|
+
Beam: "beam",
|
|
27699
|
+
Roof: "roof",
|
|
27700
|
+
Stair: "stair",
|
|
27701
|
+
Door: "door",
|
|
27702
|
+
Window: "window"
|
|
27703
|
+
};
|
|
27704
|
+
function archetypeFor(el) {
|
|
27705
|
+
return el.archetype ?? NAME_ARCHETYPES[el.type];
|
|
27706
|
+
}
|
|
27707
|
+
function specRoute(archetype) {
|
|
27708
|
+
return archetype !== void 0 && Object.hasOwn(SPEC_ROUTES, archetype) ? SPEC_ROUTES[archetype] : void 0;
|
|
27689
27709
|
}
|
|
27690
27710
|
/** Total of the resolved geometry's OUTER literal translate chain. The
|
|
27691
27711
|
* transform vocabulary is translate-only, so frame differences are exact
|
|
@@ -27793,17 +27813,18 @@ function collectSpecProps(el) {
|
|
|
27793
27813
|
return out;
|
|
27794
27814
|
}
|
|
27795
27815
|
function addFill(model, fill, input, identity) {
|
|
27796
|
-
|
|
27816
|
+
const archetype = archetypeFor(fill);
|
|
27817
|
+
if (archetype === "door") {
|
|
27797
27818
|
const parsed = parseDoorSpec(input);
|
|
27798
27819
|
if (!parsed.ok) return parsed;
|
|
27799
27820
|
return model.addDoor(parsed.value, identity);
|
|
27800
27821
|
}
|
|
27801
|
-
if (
|
|
27822
|
+
if (archetype === "window") {
|
|
27802
27823
|
const parsed = parseWindowSpec(input);
|
|
27803
27824
|
if (!parsed.ok) return parsed;
|
|
27804
27825
|
return model.addWindow(parsed.value, identity);
|
|
27805
27826
|
}
|
|
27806
|
-
return err(specError("FAMILIES_UNSUPPORTED_FILL", `familiesToBim: no fill mapping for element type '${fill.type}' at '${fill.keyPath}'`));
|
|
27827
|
+
return err(specError("FAMILIES_UNSUPPORTED_FILL", `familiesToBim: no fill mapping for element type '${fill.type}' at '${fill.keyPath}' (archetype: ${archetype ?? "none"}) — a filler needs archetype: 'door' or 'window'`));
|
|
27807
27828
|
}
|
|
27808
27829
|
/** Materialize an unrouted element's IR and add it as a proxy. The body is
|
|
27809
27830
|
* authoritative for a proxy (no parametric spec to diverge from), so baked
|
|
@@ -27907,12 +27928,14 @@ function familiesToBim(root, options) {
|
|
|
27907
27928
|
if (project !== null) model.aggregate(project.localId, siteResult.value);
|
|
27908
27929
|
model.aggregate(siteResult.value, buildingId);
|
|
27909
27930
|
const idByKeyPath = /* @__PURE__ */ new Map();
|
|
27931
|
+
const proxied = [];
|
|
27910
27932
|
const walk = (el, storeyId, rotated) => {
|
|
27911
27933
|
const rotatedHere = rotated || hasRotateOp(el);
|
|
27912
|
-
let
|
|
27934
|
+
let proxiedHere = false;
|
|
27913
27935
|
let containerId = storeyId;
|
|
27914
|
-
const
|
|
27915
|
-
|
|
27936
|
+
const archetype = archetypeFor(el);
|
|
27937
|
+
const route = specRoute(archetype);
|
|
27938
|
+
if (archetype === "storey") {
|
|
27916
27939
|
const keyed = requireKeyed(el);
|
|
27917
27940
|
if (!keyed.ok) return keyed;
|
|
27918
27941
|
const storeyResult = model.addStorey({
|
|
@@ -27937,26 +27960,31 @@ function familiesToBim(root, options) {
|
|
|
27937
27960
|
const added = route.add(model, parsed.value, el.keyPath);
|
|
27938
27961
|
if (!added.ok) return added;
|
|
27939
27962
|
idByKeyPath.set(el.keyPath, added.value);
|
|
27940
|
-
if (containerId === null) return err(specError("FAMILIES_NO_STOREY", `familiesToBim: '${el.keyPath}' has no Storey ancestor — IFC elements need spatial containment`));
|
|
27963
|
+
if (containerId === null) return err(specError("FAMILIES_NO_STOREY", `familiesToBim: '${el.keyPath}' has no Storey ancestor — IFC elements need spatial containment; a container family needs archetype: 'storey' to be recognised under any name`));
|
|
27941
27964
|
model.placeIn(added.value, containerId);
|
|
27942
|
-
if (
|
|
27965
|
+
if (archetype === "wall") {
|
|
27943
27966
|
const opened = addOpenings(model, el, added.value, containerId, idByKeyPath);
|
|
27944
27967
|
if (!opened.ok) return opened;
|
|
27945
27968
|
}
|
|
27946
27969
|
} else if (el.type === "Opening") return err(specError("FAMILIES_OPENING_OUTSIDE_WALL", `familiesToBim: opening '${el.keyPath}' is not hosted by a Wall — only wall openings are mapped`));
|
|
27947
27970
|
else if (el.type !== "Group" && el.geometry.kind !== "Empty") {
|
|
27948
|
-
if (options.proxyEvaluator === void 0) return err(specError("FAMILIES_UNSUPPORTED_TYPE", `familiesToBim: no spec mapping for element type '${el.type}' at '${el.keyPath}' — add a spec route, or pass proxyEvaluator to export it as an IfcBuildingElementProxy`));
|
|
27971
|
+
if (options.proxyEvaluator === void 0) return err(specError("FAMILIES_UNSUPPORTED_TYPE", `familiesToBim: no spec mapping for element type '${el.type}' at '${el.keyPath}' (archetype: ${el.archetype ?? "none"}) — routing is by archetype, so declare one on the family, add a spec route, or pass proxyEvaluator to export it as an IfcBuildingElementProxy`));
|
|
27949
27972
|
const keyed = requireKeyed(el);
|
|
27950
27973
|
if (!keyed.ok) return keyed;
|
|
27951
|
-
if (containerId === null) return err(specError("FAMILIES_NO_STOREY", `familiesToBim: '${el.keyPath}' has no Storey ancestor — IFC elements need spatial containment`));
|
|
27974
|
+
if (containerId === null) return err(specError("FAMILIES_NO_STOREY", `familiesToBim: '${el.keyPath}' has no Storey ancestor — IFC elements need spatial containment; a container family needs archetype: 'storey' to be recognised under any name`));
|
|
27952
27975
|
const added = addProxyElement(model, el, options.proxyEvaluator);
|
|
27953
27976
|
if (!added.ok) return added;
|
|
27954
27977
|
model.placeIn(added.value, containerId);
|
|
27955
27978
|
idByKeyPath.set(el.keyPath, added.value);
|
|
27956
|
-
proxied
|
|
27979
|
+
proxied.push({
|
|
27980
|
+
keyPath: el.keyPath,
|
|
27981
|
+
type: el.type,
|
|
27982
|
+
archetype: el.archetype
|
|
27983
|
+
});
|
|
27984
|
+
proxiedHere = true;
|
|
27957
27985
|
}
|
|
27958
27986
|
for (const child of el.children) {
|
|
27959
|
-
if ((
|
|
27987
|
+
if ((archetype === "wall" || proxiedHere) && child.type === "Opening") continue;
|
|
27960
27988
|
const r = walk(child, containerId, rotatedHere);
|
|
27961
27989
|
if (!r.ok) return r;
|
|
27962
27990
|
}
|
|
@@ -27969,7 +27997,8 @@ function familiesToBim(root, options) {
|
|
|
27969
27997
|
}
|
|
27970
27998
|
return ok({
|
|
27971
27999
|
model,
|
|
27972
|
-
idByKeyPath
|
|
28000
|
+
idByKeyPath,
|
|
28001
|
+
proxied
|
|
27973
28002
|
});
|
|
27974
28003
|
}
|
|
27975
28004
|
//#endregion
|
|
@@ -18,10 +18,24 @@ export interface FamiliesToBimOptions {
|
|
|
18
18
|
*/
|
|
19
19
|
readonly proxyEvaluator?: csg.Evaluator | undefined;
|
|
20
20
|
}
|
|
21
|
+
export interface ProxiedElement {
|
|
22
|
+
readonly keyPath: string;
|
|
23
|
+
/** The family's display name, as resolved. */
|
|
24
|
+
readonly type: string;
|
|
25
|
+
readonly archetype: string | undefined;
|
|
26
|
+
}
|
|
21
27
|
export interface FamiliesBimResult {
|
|
22
28
|
readonly model: BimModel;
|
|
23
29
|
/** LocalId per geometry-bearing families key path. */
|
|
24
30
|
readonly idByKeyPath: ReadonlyMap<string, LocalId>;
|
|
31
|
+
/**
|
|
32
|
+
* Elements exported as IfcBuildingElementProxy because no spec route
|
|
33
|
+
* matched, in walk order. Only ever non-empty when `proxyEvaluator` is set:
|
|
34
|
+
* without it an unrouted element is a hard error instead. A renamed family
|
|
35
|
+
* that has lost its routing lands here rather than in the file as the type
|
|
36
|
+
* you meant, so check this before trusting an export.
|
|
37
|
+
*/
|
|
38
|
+
readonly proxied: readonly ProxiedElement[];
|
|
25
39
|
}
|
|
26
40
|
/**
|
|
27
41
|
* Project a resolved families tree into an eager BimModel. The caller owns
|
package/dist/index.d.ts
CHANGED
|
@@ -97,4 +97,4 @@ export type { IdsDocument, IdsSpecification, IdsFacet, IdsRestriction, IdsCardin
|
|
|
97
97
|
export { serializeBcfFiles, parseBcfFiles } from './bcf/index.js';
|
|
98
98
|
export type { BcfColoring, BcfComment, BcfComponent, BcfComponents, BcfContainerData, BcfFiles, BcfProject, BcfTopic, BcfVersion, BcfViewpoint, BcfVisibility, } from './bcf/index.js';
|
|
99
99
|
export { bcfError, idsError } from './errors/bimError.js';
|
|
100
|
-
export { familiesToBim, type FamiliesToBimOptions, type FamiliesBimResult, } from './familiesAdapter.js';
|
|
100
|
+
export { familiesToBim, type FamiliesToBimOptions, type FamiliesBimResult, type ProxiedElement, } from './familiesAdapter.js';
|