abstract-3d 2.11.2 → 2.12.1

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.
@@ -15,7 +15,15 @@ export declare const point: (p: Vec3) => string;
15
15
  export declare function str(s: string | undefined): string;
16
16
  /** IFC GlobalId, derived from `uuid` when it's a valid uuid not used before in the file so re-exports keep the same ids, otherwise random */
17
17
  export declare function guid(m: MutableIfc, uuid?: string): string;
18
- export declare const header: (fileName: string, date: string) => string;
18
+ /** FILE_NAME header fields, `originatingSystem` is the application that produced the scene */
19
+ export type IfcHeader = {
20
+ readonly fileName: string;
21
+ readonly date: string;
22
+ readonly author: string;
23
+ readonly organization: string;
24
+ readonly originatingSystem: string;
25
+ };
26
+ export declare const header: (h: IfcHeader) => string;
19
27
  export declare const footer: () => string;
20
- export declare const serialize: (m: MutableIfc, fileName: string, date: string) => string;
28
+ export declare const serialize: (m: MutableIfc, h: IfcHeader) => string;
21
29
  //# sourceMappingURL=ifc-encoding.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ifc-encoding.d.ts","sourceRoot":"","sources":["../../../src/renderers/ifc/ifc-encoding.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAEjD,MAAM,MAAM,UAAU,GAAG;IAAE,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;CAAE,CAAC;AAE/F,eAAO,MAAM,OAAO,QAAO,UAAsD,CAAC;AAElF,4CAA4C;AAC5C,eAAO,MAAM,GAAG,MAAO,UAAU,UAAU,MAAM,KAAG,MAAiC,CAAC;AAEtF,eAAO,MAAM,GAAG,OAAQ,MAAM,KAAG,MAAkB,CAAC;AAEpD,eAAO,MAAM,IAAI,QAAS,aAAa,CAAC,MAAM,CAAC,KAAG,MAAuC,CAAC;AAE1F,2FAA2F;AAC3F,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAGxC;AAED,eAAO,MAAM,KAAK,MAAO,IAAI,KAAG,MAAoD,CAAC;AAErF,2EAA2E;AAC3E,wBAAgB,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAoBjD;AAyBD,6IAA6I;AAC7I,wBAAgB,IAAI,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAMzD;AAED,eAAO,MAAM,MAAM,aAAc,MAAM,QAAQ,MAAM,KAAG,MAOvD,CAAC;AAEF,eAAO,MAAM,MAAM,QAAO,MAEzB,CAAC;AAEF,eAAO,MAAM,SAAS,MAAO,UAAU,YAAY,MAAM,QAAQ,MAAM,KAAG,MACkB,CAAC"}
1
+ {"version":3,"file":"ifc-encoding.d.ts","sourceRoot":"","sources":["../../../src/renderers/ifc/ifc-encoding.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAEjD,MAAM,MAAM,UAAU,GAAG;IAAE,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;CAAE,CAAC;AAE/F,eAAO,MAAM,OAAO,QAAO,UAAsD,CAAC;AAElF,4CAA4C;AAC5C,eAAO,MAAM,GAAG,MAAO,UAAU,UAAU,MAAM,KAAG,MAAiC,CAAC;AAEtF,eAAO,MAAM,GAAG,OAAQ,MAAM,KAAG,MAAkB,CAAC;AAEpD,eAAO,MAAM,IAAI,QAAS,aAAa,CAAC,MAAM,CAAC,KAAG,MAAuC,CAAC;AAE1F,2FAA2F;AAC3F,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAGxC;AAED,eAAO,MAAM,KAAK,MAAO,IAAI,KAAG,MAAoD,CAAC;AAErF,2EAA2E;AAC3E,wBAAgB,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAoBjD;AAyBD,6IAA6I;AAC7I,wBAAgB,IAAI,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAMzD;AAED,8FAA8F;AAC9F,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;CACpC,CAAC;AAEF,eAAO,MAAM,MAAM,MAAO,SAAS,KAAG,MAgBrC,CAAC;AAEF,eAAO,MAAM,MAAM,QAAO,MAEzB,CAAC;AAEF,eAAO,MAAM,SAAS,MAAO,UAAU,KAAK,SAAS,KAAG,MAAuF,CAAC"}
@@ -63,16 +63,25 @@ export function guid(m, uuid) {
63
63
  m.usedGuids.add(id);
64
64
  return id;
65
65
  }
66
- export const header = (fileName, date) => `ISO-10303-21;
66
+ export const header = (h) => `ISO-10303-21;
67
67
  HEADER;
68
68
  FILE_DESCRIPTION(('ViewDefinition [ReferenceView_V1.2]'),'2;1');
69
- FILE_NAME(${str(fileName)},${str(date)},(''),('Divid AB'),'Abstract 3D to IFC Exporter','Abstract 3D','');
69
+ FILE_NAME(
70
+ /* name */ ${str(h.fileName)},
71
+ /* time_stamp */ ${str(h.date)},
72
+ /* author */ (${str(h.author)}),
73
+ /* organization */ (${str(h.organization)}),
74
+ /* preprocessor_version */ 'Abstract 3D to IFC Exporter',
75
+ /* originating_system */ ${str(h.originatingSystem)},
76
+ /* authorization */ 'None');
77
+
70
78
  FILE_SCHEMA(('IFC4'));
71
79
  ENDSEC;
80
+
72
81
  DATA;
73
82
  `;
74
83
  export const footer = () => `ENDSEC;
75
84
  END-ISO-10303-21;
76
85
  `;
77
- export const serialize = (m, fileName, date) => header(fileName, date) + m.entities.map((e, i) => `#${i + 1}=${e};\n`).join("") + footer();
86
+ export const serialize = (m, h) => header(h) + m.entities.map((e, i) => `#${i + 1}=${e};\n`).join("") + footer();
78
87
  //# sourceMappingURL=ifc-encoding.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ifc-encoding.js","sourceRoot":"","sources":["../../../src/renderers/ifc/ifc-encoding.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ifc-encoding.js","sourceRoot":"","sources":["../../../src/renderers/ifc/ifc-encoding.ts"],"names":[],"mappings":"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"}
@@ -6,9 +6,21 @@ export type IfcElementClass = {
6
6
  /** The entity's PredefinedType, e.g. "AIRHANDLER" for IfcUnitaryEquipment, defaults to "NOTDEFINED" */
7
7
  readonly predefinedType?: string;
8
8
  };
9
+ export type IfcApplicationInfo = {
10
+ readonly name: string;
11
+ readonly version?: string;
12
+ /** Organization that develops the application, defaults to "Divid AB" */
13
+ readonly developer?: string;
14
+ };
9
15
  export type IfcOptions = {
10
16
  /** Name of the IFC project, defaults to "Abstract 3D" */
11
17
  readonly name?: string;
18
+ /** Person exporting the file, written in the header and as the owner of every object, defaults to " " */
19
+ readonly author?: string;
20
+ /** Organization of the author, defaults to "UNKNOWN" */
21
+ readonly organization?: string;
22
+ /** Application that produced the scene, e.g. `{ name: "airCalc ACOM", version: "10.1" }`, defaults to Abstract 3D by Divid AB */
23
+ readonly application?: IfcApplicationInfo;
12
24
  /**
13
25
  * Wraps the whole scene in one element, e.g. `{ entity: "IfcUnitaryEquipment", predefinedType: "AIRHANDLER", name: "AHU" }`, otherwise the
14
26
  * top-level groups are placed directly in the storey
@@ -16,11 +28,17 @@ export type IfcOptions = {
16
28
  readonly root?: IfcElementClass & {
17
29
  readonly name: string;
18
30
  };
31
+ /**
32
+ * Layer of a group's shapes, from the `data` of every group from the root down to this group, this group last; groups without `data` are skipped
33
+ * and the root element of `root` comes first. Undefined or "" keeps the layer of the group above
34
+ */
35
+ readonly layer?: (path: ReadonlyArray<Record<string, string>>) => string | undefined;
19
36
  };
20
37
  /**
21
- * IFC4 (Reference View) with every mesh as an IfcTriangulatedFaceSet, in millimetres. Every top-level group and every group with `data` becomes an
22
- * IfcBuildingElementProxy placed relative to its parent element and aggregated into it. Groups without `data` are only transforms, so their meshes
23
- * are merged into the parent element
38
+ * IFC4 (Reference View) with every mesh as an IfcTriangulatedFaceSet, in millimetres. Every top-level group and every group with a `data.id` or
39
+ * `data.name` becomes an IfcBuildingElementProxy placed relative to its parent element and aggregated into it. Other groups are only transforms or
40
+ * metadata, so their meshes are merged into the parent element. With `layer`, the face sets are assigned to an IfcPresentationLayerAssignment per
41
+ * layer, the presentation layer of the Reference View
24
42
  */
25
43
  export declare function render(scene: Scene, options?: IfcOptions): string;
26
44
  //# sourceMappingURL=ifc.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ifc.d.ts","sourceRoot":"","sources":["../../../src/renderers/ifc/ifc.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAyB,MAAM,sBAAsB,CAAC;AAOzE,+GAA+G;AAC/G,MAAM,MAAM,gBAAgB,GAAG,yBAAyB,GAAG,qBAAqB,CAAC;AAEjF,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAClC,uGAAuG;IACvG,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,yDAAyD;IACzD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,eAAe,GAAG;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7D,CAAC;AAkBF;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,GAAE,UAAe,GAAG,MAAM,CAsCrE"}
1
+ {"version":3,"file":"ifc.d.ts","sourceRoot":"","sources":["../../../src/renderers/ifc/ifc.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAyB,MAAM,sBAAsB,CAAC;AAOzE,+GAA+G;AAC/G,MAAM,MAAM,gBAAgB,GAAG,yBAAyB,GAAG,qBAAqB,CAAC;AAEjF,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAClC,uGAAuG;IACvG,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,yEAAyE;IACzE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,yDAAyD;IACzD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,yGAAyG;IACzG,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,wDAAwD;IACxD,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,iIAAiI;IACjI,QAAQ,CAAC,WAAW,CAAC,EAAE,kBAAkB,CAAC;IAC1C;;;OAGG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,eAAe,GAAG;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5D;;;OAGG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,KAAK,MAAM,GAAG,SAAS,CAAC;CACtF,CAAC;AAkCF;;;;;GAKG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,GAAE,UAAe,GAAG,MAAM,CAgDrE"}
@@ -4,82 +4,127 @@ import { add, guid, ifcFile, point, real, ref, refs, serialize, str } from "./if
4
4
  import { toIfc, triangulate } from "./ifc-geometry.js";
5
5
  const proxyClass = { entity: "IfcBuildingElementProxy" };
6
6
  /**
7
- * IFC4 (Reference View) with every mesh as an IfcTriangulatedFaceSet, in millimetres. Every top-level group and every group with `data` becomes an
8
- * IfcBuildingElementProxy placed relative to its parent element and aggregated into it. Groups without `data` are only transforms, so their meshes
9
- * are merged into the parent element
7
+ * IFC4 (Reference View) with every mesh as an IfcTriangulatedFaceSet, in millimetres. Every top-level group and every group with a `data.id` or
8
+ * `data.name` becomes an IfcBuildingElementProxy placed relative to its parent element and aggregated into it. Other groups are only transforms or
9
+ * metadata, so their meshes are merged into the parent element. With `layer`, the face sets are assigned to an IfcPresentationLayerAssignment per
10
+ * layer, the presentation layer of the Reference View
10
11
  */
11
12
  export function render(scene, options = {}) {
12
13
  const name = options.name ?? "Abstract 3D";
14
+ const author = options.author ?? " ";
15
+ const organization = options.organization ?? "UNKNOWN";
16
+ const application = options.application ?? { name: "Abstract 3D" };
17
+ const now = new Date();
13
18
  const m = ifcFile();
19
+ const ownerHistory = ownerHistoryEntity(m, author, organization, application, now);
14
20
  const world = axisPlacement(m, vec3Zero, vec3Zero);
15
21
  const context = add(m, `IFCGEOMETRICREPRESENTATIONCONTEXT($,'Model',3,1.E-05,${ref(world)},$)`);
16
22
  const body = add(m, `IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Body','Model',*,*,*,*,${ref(context)},$,.MODEL_VIEW.,$)`);
23
+ const c = { body, owner: (id) => `${str(guid(m, id))},${ref(ownerHistory)}`, styles: new Map(), layers: new Map() };
17
24
  const units = [
18
25
  add(m, "IFCSIUNIT(*,.LENGTHUNIT.,.MILLI.,.METRE.)"),
19
26
  add(m, "IFCSIUNIT(*,.AREAUNIT.,$,.SQUARE_METRE.)"),
20
27
  add(m, "IFCSIUNIT(*,.VOLUMEUNIT.,$,.CUBIC_METRE.)"),
21
28
  add(m, "IFCSIUNIT(*,.PLANEANGLEUNIT.,$,.RADIAN.)"),
22
29
  ];
23
- const project = add(m, `IFCPROJECT(${str(guid(m))},$,${str(name)},$,$,$,$,(${ref(context)}),${ref(add(m, `IFCUNITASSIGNMENT(${refs(units)})`))})`);
30
+ const project = add(m, `IFCPROJECT(${c.owner()},${str(name)},$,$,$,$,(${ref(context)}),${ref(add(m, `IFCUNITASSIGNMENT(${refs(units)})`))})`);
24
31
  const sitePlacement = add(m, `IFCLOCALPLACEMENT($,${ref(world)})`);
25
- const site = add(m, `IFCSITE(${str(guid(m))},$,'Site',$,$,${ref(sitePlacement)},$,$,.ELEMENT.,$,$,$,$,$)`);
32
+ const site = add(m, `IFCSITE(${c.owner()},'Site',$,$,${ref(sitePlacement)},$,$,.ELEMENT.,$,$,$,$,$)`);
26
33
  const buildingPlacement = add(m, `IFCLOCALPLACEMENT(${ref(sitePlacement)},${ref(world)})`);
27
- const building = add(m, `IFCBUILDING(${str(guid(m))},$,'Building',$,$,${ref(buildingPlacement)},$,$,.ELEMENT.,$,$,$)`);
34
+ const building = add(m, `IFCBUILDING(${c.owner()},'Building',$,$,${ref(buildingPlacement)},$,$,.ELEMENT.,$,$,$)`);
28
35
  const storeyPlacement = add(m, `IFCLOCALPLACEMENT(${ref(buildingPlacement)},${ref(world)})`);
29
- const storey = add(m, `IFCBUILDINGSTOREY(${str(guid(m))},$,'Storey',$,$,${ref(storeyPlacement)},$,$,.ELEMENT.,0.)`);
30
- aggregate(m, project, [site]);
31
- aggregate(m, site, [building]);
32
- aggregate(m, building, [storey]);
36
+ const storey = add(m, `IFCBUILDINGSTOREY(${c.owner()},'Storey',$,$,${ref(storeyPlacement)},$,$,.ELEMENT.,0.)`);
37
+ aggregate(m, c, project, [site]);
38
+ aggregate(m, c, site, [building]);
39
+ aggregate(m, c, building, [storey]);
33
40
  const center = scene.center_deprecated ?? vec3Zero;
34
41
  const sceneRot = scene.rotation_deprecated ?? vec3Zero;
35
- const c = { body, styles: new Map() };
36
- const nodes = options.root
37
- ? [elementNode({ pos: center, rot: sceneRot, groups: scene.groups, data: { name: options.root.name } }, center, sceneRot, options.root)]
38
- : scene.groups.map((g) => elementNode(g, vec3TransRot(g.pos, center, sceneRot), vec3RotCombine(sceneRot, g.rot ?? vec3Zero)));
42
+ const top = { layerOf: options.layer, path: [], layer: undefined };
43
+ const rootGroup = options.root && { pos: center, rot: sceneRot, groups: scene.groups, data: { name: options.root.name } };
44
+ const nodes = rootGroup
45
+ ? [elementNode(rootGroup, center, sceneRot, groupLayering(rootGroup, top), options.root)]
46
+ : scene.groups.map((g) => elementNode(g, vec3TransRot(g.pos, center, sceneRot), vec3RotCombine(sceneRot, g.rot ?? vec3Zero), groupLayering(g, top)));
39
47
  const elements = nodes.flatMap((node) => node ?? []).map((node, i) => element(m, node, `${i + 1}`, storeyPlacement, c));
40
48
  if (elements.length > 0) {
41
- add(m, `IFCRELCONTAINEDINSPATIALSTRUCTURE(${str(guid(m))},$,$,$,${refs(elements)},${ref(storey)})`);
49
+ add(m, `IFCRELCONTAINEDINSPATIALSTRUCTURE(${c.owner()},$,$,${refs(elements)},${ref(storey)})`);
42
50
  }
43
- const date = new Date().toISOString().split(".")[0] ?? "1970-01-01T00:00:00";
44
- return serialize(m, `${name}.ifc`, date);
51
+ c.layers.forEach((items, layer) => add(m, `IFCPRESENTATIONLAYERASSIGNMENT(${str(layer)},$,${refs(items)},$)`));
52
+ const date = now.toISOString().split(".")[0] ?? "1970-01-01T00:00:00";
53
+ return serialize(m, { fileName: `${name}.ifc`, date, author, organization, originatingSystem: application.name });
45
54
  }
46
- function elementNode(group, pos, rot, elementClass = proxyClass) {
47
- const { meshes, children } = elementContent(group, vec3Zero, vec3Zero);
55
+ /** The author as the owning user and the application, ADDED requires LastModifiedDate in IFC4 so it's set to the creation date */
56
+ function ownerHistoryEntity(m, author, organization, application, now) {
57
+ const person = add(m, `IFCPERSON(${str(author)},$,$,$,$,$,$,$)`);
58
+ const owningOrganization = add(m, `IFCORGANIZATION($,${str(organization)},$,$,$)`);
59
+ const { name, version = "", developer = "Divid AB" } = application;
60
+ const developerOrganization = developer === organization ? owningOrganization : add(m, `IFCORGANIZATION($,${str(developer)},$,$,$)`);
61
+ const user = add(m, `IFCPERSONANDORGANIZATION(${ref(person)},${ref(owningOrganization)},$)`);
62
+ const app = add(m, `IFCAPPLICATION(${ref(developerOrganization)},${str(version)},${str(name)},${str(name)})`);
63
+ const timestamp = Math.floor(now.getTime() / 1000);
64
+ return add(m, `IFCOWNERHISTORY(${ref(user)},${ref(app)},$,.ADDED.,${timestamp},$,$,${timestamp})`);
65
+ }
66
+ /** `layering` is the group's own, see `groupLayering` */
67
+ function elementNode(group, pos, rot, layering, elementClass = proxyClass) {
68
+ const { meshes, children } = elementContent(group, vec3Zero, vec3Zero, layering);
48
69
  return meshes.length > 0 || children.length > 0 ? { group, elementClass, pos, rot, meshes, children } : undefined;
49
70
  }
50
- /** Meshes of the group and its descendants without data, relative to the element the group is at pos/rot in, and the descendants with data as elements */
51
- function elementContent(group, pos, rot) {
71
+ /**
72
+ * Meshes of the group and its descendants that aren't elements, relative to the element the group is at pos/rot in, and the descendants with a
73
+ * `data.id` or `data.name` as elements
74
+ */
75
+ function elementContent(group, pos, rot, layering) {
52
76
  const meshes = (group.meshes ?? []).flatMap((mesh) => {
53
77
  const triangulation = triangulate(mesh.geometry, pos, rot);
54
- return triangulation ? [{ material: mesh.material, triangulation }] : [];
78
+ return triangulation ? [{ material: mesh.material, triangulation, layer: layering.layer }] : [];
55
79
  });
56
80
  const nested = (group.groups ?? []).map((child) => {
57
81
  const childPos = vec3TransRot(child.pos, pos, rot);
58
82
  const childRot = vec3RotCombine(rot, child.rot ?? vec3Zero);
59
- return Object.keys(child.data ?? {}).length > 0
60
- ? { meshes: [], children: [elementNode(child, childPos, childRot)].flatMap((node) => node ?? []) }
61
- : elementContent(child, childPos, childRot);
83
+ const childLayering = groupLayering(child, layering);
84
+ return child.data?.["id"] !== undefined || child.data?.["name"] !== undefined
85
+ ? { meshes: [], children: [elementNode(child, childPos, childRot, childLayering)].flatMap((node) => node ?? []) }
86
+ : elementContent(child, childPos, childRot, childLayering);
62
87
  });
63
88
  return { meshes: [...meshes, ...nested.flatMap((n) => n.meshes)], children: nested.flatMap((n) => n.children) };
64
89
  }
90
+ /** Groups with `data` are added to the path and get the layer `layerOf` returns for it, if any, otherwise the layer of the parent */
91
+ function groupLayering(group, parent) {
92
+ const data = group.data;
93
+ if (data === undefined || Object.keys(data).length === 0) {
94
+ return parent;
95
+ }
96
+ const path = [...parent.path, data];
97
+ const layer = parent.layerOf?.(path);
98
+ return { ...parent, path, layer: layer === undefined || layer === "" ? parent.layer : layer };
99
+ }
65
100
  /** `path` is the element's position in the tree (e.g. "2.1"), named after it when the group has no `data.name` or `data.id` since IFC requires a name */
66
101
  function element(m, node, path, parentPlacement, c) {
67
102
  const placement = add(m, `IFCLOCALPLACEMENT(${ref(parentPlacement)},${ref(axisPlacement(m, node.pos, node.rot))})`);
68
- const items = node.meshes.map(({ material, triangulation }) => faceSet(m, triangulation, material, c));
103
+ const items = node.meshes.map((mesh) => faceSet(m, mesh, c));
69
104
  const shape = items.length > 0
70
105
  ? ref(add(m, `IFCPRODUCTDEFINITIONSHAPE($,$,(${ref(add(m, `IFCSHAPEREPRESENTATION(${ref(c.body)},'Body','Tessellation',${refs(items)})`))}))`))
71
106
  : "$";
72
107
  const id = node.group.data?.["id"];
73
108
  const name = node.group.data?.["name"] ?? id ?? `Element ${path}`;
74
109
  const { entity, predefinedType = "NOTDEFINED" } = node.elementClass;
75
- const ifcElement = add(m, `${entity.toUpperCase()}(${str(guid(m, id))},$,${str(name)},$,$,${ref(placement)},${shape},${str(id)},.${predefinedType}.)`);
76
- aggregate(m, ifcElement, node.children.map((child, i) => element(m, child, `${path}.${i + 1}`, placement, c)));
110
+ const ifcElement = add(m, `${entity.toUpperCase()}(${c.owner(id)},${str(name)},$,$,${ref(placement)},${shape},${str(id)},.${predefinedType}.)`);
111
+ aggregate(m, c, ifcElement, node.children.map((child, i) => element(m, child, `${path}.${i + 1}`, placement, c)));
77
112
  return ifcElement;
78
113
  }
79
- function faceSet(m, { points, triangles }, material, c) {
114
+ /** One face set per mesh, so meshes on different layers are never in the same item */
115
+ function faceSet(m, { material, triangulation: { points, triangles }, layer }, c) {
80
116
  const pointList = add(m, `IFCCARTESIANPOINTLIST3D((${points.join(",")}))`);
81
117
  const faces = add(m, `IFCTRIANGULATEDFACESET(${ref(pointList)},$,.F.,(${triangles.map((t) => `(${t.join(",")})`).join(",")}),$)`);
82
118
  add(m, `IFCSTYLEDITEM(${ref(faces)},(${ref(surfaceStyle(m, material, c))}),$)`);
119
+ if (layer !== undefined) {
120
+ const items = c.layers.get(layer);
121
+ if (items) {
122
+ items.push(faces);
123
+ }
124
+ else {
125
+ c.layers.set(layer, [faces]);
126
+ }
127
+ }
83
128
  return faces;
84
129
  }
85
130
  function surfaceStyle(m, material, c) {
@@ -91,8 +136,9 @@ function surfaceStyle(m, material, c) {
91
136
  }
92
137
  const { r, g, b } = new Color(material.normal).getRGB({ r: 0, g: 0, b: 0 }, SRGBColorSpace);
93
138
  const colour = add(m, `IFCCOLOURRGB($,${real(r)},${real(g)},${real(b)})`);
94
- const shading = add(m, `IFCSURFACESTYLESHADING(${ref(colour)},${real(1 - opacity)})`);
95
- const style = add(m, `IFCSURFACESTYLE(${str(material.normal)},.BOTH.,(${ref(shading)}))`);
139
+ // Rendering rather than its supertype shading, since many viewers only read the transparency from rendering
140
+ const rendering = add(m, `IFCSURFACESTYLERENDERING(${ref(colour)},${real(1 - opacity)},$,$,$,$,$,$,.NOTDEFINED.)`);
141
+ const style = add(m, `IFCSURFACESTYLE(${str(material.normal)},.BOTH.,(${ref(rendering)}))`);
96
142
  c.styles.set(key, style);
97
143
  return style;
98
144
  }
@@ -103,9 +149,9 @@ function axisPlacement(m, pos, rot) {
103
149
  const refDirection = add(m, `IFCDIRECTION(${point(toIfc(vec3Rot(vec3PosX, vec3Zero, rot)))})`);
104
150
  return add(m, `IFCAXIS2PLACEMENT3D(${ref(location)},${ref(axis)},${ref(refDirection)})`);
105
151
  }
106
- function aggregate(m, parent, children) {
152
+ function aggregate(m, c, parent, children) {
107
153
  if (children.length > 0) {
108
- add(m, `IFCRELAGGREGATES(${str(guid(m))},$,$,$,${ref(parent)},${refs(children)})`);
154
+ add(m, `IFCRELAGGREGATES(${c.owner()},$,$,${ref(parent)},${refs(children)})`);
109
155
  }
110
156
  }
111
157
  //# sourceMappingURL=ifc.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ifc.js","sourceRoot":"","sources":["../../../src/renderers/ifc/ifc.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ifc.js","sourceRoot":"","sources":["../../../src/renderers/ifc/ifc.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "abstract-3d",
3
- "version": "2.11.2",
4
- "gitHead": "19150177f76aac69a7863e4c8258cc30ade77688",
3
+ "version": "2.12.1",
4
+ "gitHead": "60357004c7a11aa81f9e9ae780aad3ce2b295cc2",
5
5
  "description": "Abstract 3D",
6
6
  "license": "MIT",
7
7
  "author": "Divid AB <info@divid.se>",
@@ -57,7 +57,7 @@
57
57
  "@react-three/drei": "^10.7.9",
58
58
  "@react-three/fiber": "^9.8.1",
59
59
  "@react-three/postprocessing": "^3.1.3",
60
- "abstract-image": "^13.3.1",
60
+ "abstract-image": "^13.3.2",
61
61
  "suspend-react": "^0.1.3",
62
62
  "three": "^0.186.1",
63
63
  "ts-exhaustive-check": "^1.0.0"
@@ -74,12 +74,30 @@ export function guid(m: MutableIfc, uuid?: string): string {
74
74
  return id;
75
75
  }
76
76
 
77
- export const header = (fileName: string, date: string): string => `ISO-10303-21;
77
+ /** FILE_NAME header fields, `originatingSystem` is the application that produced the scene */
78
+ export type IfcHeader = {
79
+ readonly fileName: string;
80
+ readonly date: string;
81
+ readonly author: string;
82
+ readonly organization: string;
83
+ readonly originatingSystem: string;
84
+ };
85
+
86
+ export const header = (h: IfcHeader): string => `ISO-10303-21;
78
87
  HEADER;
79
88
  FILE_DESCRIPTION(('ViewDefinition [ReferenceView_V1.2]'),'2;1');
80
- FILE_NAME(${str(fileName)},${str(date)},(''),('Divid AB'),'Abstract 3D to IFC Exporter','Abstract 3D','');
89
+ FILE_NAME(
90
+ /* name */ ${str(h.fileName)},
91
+ /* time_stamp */ ${str(h.date)},
92
+ /* author */ (${str(h.author)}),
93
+ /* organization */ (${str(h.organization)}),
94
+ /* preprocessor_version */ 'Abstract 3D to IFC Exporter',
95
+ /* originating_system */ ${str(h.originatingSystem)},
96
+ /* authorization */ 'None');
97
+
81
98
  FILE_SCHEMA(('IFC4'));
82
99
  ENDSEC;
100
+
83
101
  DATA;
84
102
  `;
85
103
 
@@ -87,5 +105,4 @@ export const footer = (): string => `ENDSEC;
87
105
  END-ISO-10303-21;
88
106
  `;
89
107
 
90
- export const serialize = (m: MutableIfc, fileName: string, date: string): string =>
91
- header(fileName, date) + m.entities.map((e, i) => `#${i + 1}=${e};\n`).join("") + footer();
108
+ export const serialize = (m: MutableIfc, h: IfcHeader): string => header(h) + m.entities.map((e, i) => `#${i + 1}=${e};\n`).join("") + footer();
@@ -1,4 +1,4 @@
1
- import { describe, expect, it } from "vitest";
1
+ import { describe, expect, it, vi } from "vitest";
2
2
  import type { Scene } from "../../abstract-3d.js";
3
3
  import { box, cylinder, group, line, roundHole, sphere, vec2, vec3, vec3Zero } from "../../abstract-3d.js";
4
4
  import { guid, ifcFile, real, str } from "./ifc-encoding.js";
@@ -8,6 +8,38 @@ import { render } from "./ifc.js";
8
8
  const red = { normal: "rgb(255, 0, 0)", opacity: 0.5 };
9
9
  const scene = (groups: Scene["groups"]): Scene => ({ size_deprecated: vec3Zero, groups });
10
10
  const count = (ifc: string, entity: string): number => ifc.split(`=${entity}(`).length - 1;
11
+ const ids = (s: string): ReadonlyArray<string> => Array.from(s.matchAll(/#(\d+)/g), (match) => match[1]);
12
+ /** Random GlobalIds replaced, to compare files */
13
+ const normalize = (ifc: string): string => ifc.replaceAll(/'[0-9A-Za-z_$]{22}'/g, "'guid'");
14
+
15
+ /** The layer of every face set of the element named `name`, in order */
16
+ function elementLayers(ifc: string, name: string): ReadonlyArray<string | undefined> {
17
+ const entities = new Map(Array.from(ifc.matchAll(/^#(\d+)=(.*);$/gm), (match) => [match[1], match[2]]));
18
+ const layers = new Map(
19
+ Array.from(ifc.matchAll(/[=]IFCPRESENTATIONLAYERASSIGNMENT\('([^']*)',\$,\(([^)]*)\),\$\);/g)).flatMap(([, layer, items]) =>
20
+ ids(items).map((item) => [item, layer] as const)
21
+ )
22
+ );
23
+ // The element's owner history, placement and shape, the shape's representation and its context and items
24
+ const [, , shape] = ids(Array.from(entities.values()).find((e) => e.includes(`,'${name}',$,$,#`))!);
25
+ const [, ...items] = ids(entities.get(ids(entities.get(shape)!)[0])!);
26
+ return items.map((item) => layers.get(item));
27
+ }
28
+
29
+ /** An air handler component with a panel and a fan with a motor, the motor's meshes two groups without data down */
30
+ const component = (id: string, key: string): Scene["groups"][number] =>
31
+ group(
32
+ [box(vec3(1, 1, 1), red)],
33
+ vec3Zero,
34
+ vec3Zero,
35
+ [
36
+ group([box(vec3(1, 1, 1), red)], vec3Zero, vec3Zero, [], { type: "panel" }),
37
+ group([sphere(1, red)], vec3Zero, vec3Zero, [group([], vec3Zero, vec3Zero, [group([cylinder(vec3Zero, 1, 2, red)])])], { type: "fan_wall" }),
38
+ ],
39
+ { id, key }
40
+ );
41
+
42
+ const layered = (layer: string, groups: Scene["groups"]): Scene["groups"][number] => group([], vec3Zero, vec3Zero, groups, { layer });
11
43
 
12
44
  describe("ifc encoding", () => {
13
45
  it("writes reals with a decimal point", () => {
@@ -78,7 +110,8 @@ describe("ifc render", () => {
78
110
  // Same material is styled once
79
111
  expect(count(ifc, "IFCSURFACESTYLE")).toBe(1);
80
112
  expect(ifc).toContain("IFCCOLOURRGB($,1.,0.,0.)");
81
- expect(ifc).toContain("IFCSURFACESTYLESHADING(#");
113
+ expect(ifc).toMatch(/[=]IFCSURFACESTYLERENDERING\(#\d+,0\.5,\$,\$,\$,\$,\$,\$,\.NOTDEFINED\.\);/);
114
+ expect(ifc).not.toContain("IFCSURFACESTYLESHADING(");
82
115
  expect(ifc).toContain(",'588c9525-0f1b-4b0b-a3e1-ba10f8a922ff',$,$,#");
83
116
  expect(ifc).toContain(",'588c9525-0f1b-4b0b-a3e1-ba10f8a922ff',.NOTDEFINED.)");
84
117
  expect(ifc).toContain(",'Fan',$,$,#");
@@ -86,6 +119,16 @@ describe("ifc render", () => {
86
119
  expect(ifc).toContain(",'Element 2',$,$,#");
87
120
  });
88
121
 
122
+ it("writes the transparency as one minus the opacity, styling each colour and opacity once", () => {
123
+ const blue = { normal: "rgb(0, 0, 255)", opacity: 0.25 };
124
+ const ifc = render(scene([group([box(vec3(1, 1, 1), blue), sphere(1, blue), box(vec3(1, 1, 1), { normal: "rgb(0, 0, 255)" })])]));
125
+ expect(ifc).toMatch(/[=]IFCSURFACESTYLERENDERING\(#\d+,0\.75,\$,\$,\$,\$,\$,\$,\.NOTDEFINED\.\);/);
126
+ // No opacity is opaque
127
+ expect(ifc).toMatch(/[=]IFCSURFACESTYLERENDERING\(#\d+,0\.,\$,\$,\$,\$,\$,\$,\.NOTDEFINED\.\);/);
128
+ expect(count(ifc, "IFCSURFACESTYLERENDERING")).toBe(2);
129
+ expect(count(ifc, "IFCSURFACESTYLE")).toBe(2);
130
+ });
131
+
89
132
  it("wraps the scene in one root element", () => {
90
133
  const ifc = render(
91
134
  scene([
@@ -94,11 +137,128 @@ describe("ifc render", () => {
94
137
  ]),
95
138
  { root: { entity: "IfcUnitaryEquipment", predefinedType: "AIRHANDLER", name: "AHU" } }
96
139
  );
97
- expect(ifc).toMatch(/[=]IFCUNITARYEQUIPMENT\('[^']{22}',\$,'AHU',\$,\$,#\d+,\$,\$,\.AIRHANDLER\.\);/);
140
+ expect(ifc).toMatch(/[=]IFCUNITARYEQUIPMENT\('[^']{22}',#\d+,'AHU',\$,\$,#\d+,\$,\$,\.AIRHANDLER\.\);/);
98
141
  expect(count(ifc, "IFCBUILDINGELEMENTPROXY")).toBe(2);
99
142
  // Only the root is in the storey, the groups are aggregated into it
100
- expect(ifc).toMatch(/[=]IFCRELCONTAINEDINSPATIALSTRUCTURE\('[^']{22}',\$,\$,\$,\(#\d+\),#\d+\);/);
143
+ expect(ifc).toMatch(/[=]IFCRELCONTAINEDINSPATIALSTRUCTURE\('[^']{22}',#\d+,\$,\$,\(#\d+\),#\d+\);/);
144
+ expect(count(ifc, "IFCRELAGGREGATES")).toBe(4);
145
+ });
146
+
147
+ it("writes the owner history on every rooted entity and the author and application in the header", () => {
148
+ const ifc = render(
149
+ scene([group([box(vec3(1, 1, 1), red)], vec3Zero, vec3Zero, [group([sphere(1, red)], vec3Zero, vec3Zero, [], { name: "Fan" })])]),
150
+ {
151
+ author: "Ivan",
152
+ organization: "Acme",
153
+ application: { name: "airCalc ACOM", version: "10.1" },
154
+ }
155
+ );
156
+ expect(ifc).toContain("/* name */ 'Abstract 3D.ifc',");
157
+ expect(ifc).toContain("/* author */ ('Ivan'),\n/* organization */ ('Acme'),");
158
+ expect(ifc).toContain("/* originating_system */ 'airCalc ACOM',");
159
+ expect(ifc).toMatch(/[=]IFCPERSON\('Ivan',/);
160
+ expect(ifc).toContain("IFCORGANIZATION($,'Acme',$,$,$)");
161
+ expect(ifc).toMatch(/[=]IFCAPPLICATION\(#\d+,'10.1','airCalc ACOM','airCalc ACOM'\);/);
162
+ expect(ifc).toMatch(/[=]IFCOWNERHISTORY\(#\d+,#\d+,\$,\.ADDED\.,\d+,\$,\$,\d+\);/);
163
+ const ownerHistory = /^#(\d+)=IFCOWNERHISTORY\(/m.exec(ifc)![1];
164
+ const rooted = Array.from(ifc.matchAll(/^#\d+=IFC\w+\('[^']{22}',([^,]+),/gm), (match) => match[1]);
165
+ // Project, site, building, storey, 2 elements, 4 aggregates and the containment
166
+ expect(rooted).toHaveLength(11);
167
+ expect(rooted.every((owner) => owner === `#${ownerHistory}`)).toBe(true);
168
+ });
169
+
170
+ it("defaults the owner to an unknown author and organization and the application to Abstract 3D by Divid AB", () => {
171
+ const ifc = render(scene([group([box(vec3(1, 1, 1), red)])]));
172
+ expect(ifc).toContain("/* author */ (' '),\n/* organization */ ('UNKNOWN'),");
173
+ expect(ifc).toContain("/* originating_system */ 'Abstract 3D',");
174
+ expect(ifc).toContain("IFCORGANIZATION($,'UNKNOWN',$,$,$)");
175
+ expect(ifc).toContain("IFCORGANIZATION($,'Divid AB',$,$,$)");
176
+ });
177
+
178
+ it("uses one organization as both owner and application developer when they're the same", () => {
179
+ const ifc = render(scene([group([box(vec3(1, 1, 1), red)])]), { organization: "Divid AB" });
180
+ expect(count(ifc, "IFCORGANIZATION")).toBe(1);
181
+ });
182
+
183
+ it("makes elements only of groups with data.id or data.name, merging groups with other data into their parent", () => {
184
+ const ifc = render(
185
+ scene([
186
+ group([box(vec3(1, 1, 1), red)], vec3Zero, vec3Zero, [
187
+ group([box(vec3(1, 1, 1), red)], vec3Zero, vec3Zero, [group([sphere(1, red)], vec3Zero, vec3Zero, [], { id: "fan" })], { type: "panel" }),
188
+ group([sphere(1, red)], vec3Zero, vec3Zero, [], { name: "Motor", type: "motor" }),
189
+ ]),
190
+ ])
191
+ );
192
+ expect(count(ifc, "IFCBUILDINGELEMENTPROXY")).toBe(3);
193
+ // The panel's box is merged into the top-level element, the element below the panel is aggregated into it
194
+ expect(elementLayers(ifc, "Element 1")).toHaveLength(2);
101
195
  expect(count(ifc, "IFCRELAGGREGATES")).toBe(4);
196
+ expect(ifc).toMatch(/[=]IFCRELAGGREGATES\('[^']{22}',#\d+,\$,\$,#\d+,\(#\d+,#\d+\)\);/);
197
+ });
198
+
199
+ it("puts the meshes on the layer of the nearest group above them with one, from the data path of the root and the groups with data", () => {
200
+ const paths: Array<ReadonlyArray<Record<string, string>>> = [];
201
+ const ifc = render(scene([component("a1", "FAN"), component("a2", "FAN"), component("a3", "DUCTCONNECTORS")]), {
202
+ root: { entity: "IfcUnitaryEquipment", predefinedType: "AIRHANDLER", name: "AHU" },
203
+ layer: (path) => {
204
+ paths.push(path);
205
+ const key = path.filter((d) => "key" in d).at(-1)?.key;
206
+ return path.at(-1)?.type === "panel" ? "acomSECTIONS" : key ? `acom${key}` : undefined;
207
+ },
208
+ });
209
+ // Box, panel, fan and the motor two groups without data further down
210
+ expect(elementLayers(ifc, "a1")).toEqual(["acomFAN", "acomSECTIONS", "acomFAN", "acomFAN"]);
211
+ expect(elementLayers(ifc, "a3")).toEqual(["acomDUCTCONNECTORS", "acomSECTIONS", "acomDUCTCONNECTORS", "acomDUCTCONNECTORS"]);
212
+ // One layer per name across the elements
213
+ expect(count(ifc, "IFCPRESENTATIONLAYERASSIGNMENT")).toBe(3);
214
+ expect(ifc).toMatch(/[=]IFCPRESENTATIONLAYERASSIGNMENT\('acomSECTIONS',\$,\(#\d+,#\d+,#\d+\),\$\);/);
215
+ expect(ifc).toMatch(/[=]IFCPRESENTATIONLAYERASSIGNMENT\('acomFAN',\$,\((#\d+,){5}#\d+\),\$\);/);
216
+ expect(paths).toContainEqual([{ name: "AHU" }, { id: "a1", key: "FAN" }, { type: "panel" }]);
217
+ // The root, 3 components and their panel and fan, groups without data are skipped
218
+ expect(paths).toHaveLength(10);
219
+ });
220
+
221
+ it("inherits the layer through groups without data and groups the layer returns undefined or an empty name for", () => {
222
+ const ifc = render(
223
+ scene([
224
+ group(
225
+ [box(vec3(1, 1, 1), red)],
226
+ vec3Zero,
227
+ vec3Zero,
228
+ [
229
+ group([box(vec3(1, 1, 1), red)], vec3Zero, vec3Zero, [], { type: "panel" }),
230
+ layered("", [group([box(vec3(1, 1, 1), red)])]),
231
+ layered("B", [group([], vec3Zero, vec3Zero, [group([box(vec3(1, 1, 1), red)])])]),
232
+ layered("B", [group([box(vec3(1, 1, 1), red)], vec3Zero, vec3Zero, [], { name: "Inner", type: "fan" })]),
233
+ ],
234
+ { layer: "A" }
235
+ ),
236
+ group([box(vec3(1, 1, 1), red)]),
237
+ ]),
238
+ { layer: (path) => path.at(-1)?.layer }
239
+ );
240
+ expect(elementLayers(ifc, "Element 1")).toEqual(["A", "A", "A", "B"]);
241
+ expect(elementLayers(ifc, "Inner")).toEqual(["B"]);
242
+ // Meshes without a layer above them get none
243
+ expect(elementLayers(ifc, "Element 2")).toEqual([undefined]);
244
+ expect(count(ifc, "IFCPRESENTATIONLAYERASSIGNMENT")).toBe(2);
245
+ });
246
+
247
+ it("only adds the layers to the output", () => {
248
+ vi.useFakeTimers({ now: new Date("2026-10-12T10:00:00Z") });
249
+ const s = scene([
250
+ group([box(vec3(1, 1, 1), red)], vec3(1, 2, 3), vec3(0.1, 0, 0), [
251
+ group([sphere(1, red)], vec3Zero, vec3Zero, [group([cylinder(vec3Zero, 1, 2, red)])], { name: "Fan" }),
252
+ ]),
253
+ ]);
254
+ const plain = normalize(render(s));
255
+ const undefinedLayers = normalize(render(s, { layer: () => undefined }));
256
+ const withLayers = normalize(render(s, { layer: () => "A" }));
257
+ vi.useRealTimers();
258
+ expect(count(plain, "IFCPRESENTATIONLAYERASSIGNMENT")).toBe(0);
259
+ expect(undefinedLayers).toBe(plain);
260
+ // Only the fan's meshes are in a group with data
261
+ expect(withLayers.replace(/^#\d+=IFCPRESENTATIONLAYERASSIGNMENT\('A',\$,\(#\d+,#\d+\),\$\);\n/m, "")).toBe(plain);
102
262
  });
103
263
 
104
264
  it("only references entities that exist", () => {
@@ -15,17 +15,42 @@ export type IfcElementClass = {
15
15
  readonly predefinedType?: string;
16
16
  };
17
17
 
18
+ export type IfcApplicationInfo = {
19
+ readonly name: string;
20
+ readonly version?: string;
21
+ /** Organization that develops the application, defaults to "Divid AB" */
22
+ readonly developer?: string;
23
+ };
24
+
18
25
  export type IfcOptions = {
19
26
  /** Name of the IFC project, defaults to "Abstract 3D" */
20
27
  readonly name?: string;
28
+ /** Person exporting the file, written in the header and as the owner of every object, defaults to " " */
29
+ readonly author?: string;
30
+ /** Organization of the author, defaults to "UNKNOWN" */
31
+ readonly organization?: string;
32
+ /** Application that produced the scene, e.g. `{ name: "airCalc ACOM", version: "10.1" }`, defaults to Abstract 3D by Divid AB */
33
+ readonly application?: IfcApplicationInfo;
21
34
  /**
22
35
  * Wraps the whole scene in one element, e.g. `{ entity: "IfcUnitaryEquipment", predefinedType: "AIRHANDLER", name: "AHU" }`, otherwise the
23
36
  * top-level groups are placed directly in the storey
24
37
  */
25
38
  readonly root?: IfcElementClass & { readonly name: string };
39
+ /**
40
+ * Layer of a group's shapes, from the `data` of every group from the root down to this group, this group last; groups without `data` are skipped
41
+ * and the root element of `root` comes first. Undefined or "" keeps the layer of the group above
42
+ */
43
+ readonly layer?: (path: ReadonlyArray<Record<string, string>>) => string | undefined;
26
44
  };
27
45
 
28
- type NodeMesh = { readonly material: Material; readonly triangulation: Triangulation };
46
+ type NodeMesh = { readonly material: Material; readonly triangulation: Triangulation; readonly layer: string | undefined };
47
+
48
+ /** The `data` of the groups from the root down to a group and the layer its meshes are on */
49
+ type Layering = {
50
+ readonly layerOf: IfcOptions["layer"];
51
+ readonly path: ReadonlyArray<Record<string, string>>;
52
+ readonly layer: string | undefined;
53
+ };
29
54
 
30
55
  /** A group that becomes an element, groups without any triangulated geometry in them are left out */
31
56
  type ElementNode = {
@@ -39,78 +64,126 @@ type ElementNode = {
39
64
 
40
65
  const proxyClass: IfcElementClass = { entity: "IfcBuildingElementProxy" };
41
66
 
42
- type IfcContext = { readonly body: number; readonly styles: Map<string, number> };
67
+ /**
68
+ * `owner` is the encoded GlobalId and OwnerHistory every IfcRoot entity starts with, call it once per entity since the GlobalId must be unique.
69
+ * `layers` are the face sets on each layer
70
+ */
71
+ type IfcContext = {
72
+ readonly body: number;
73
+ readonly owner: (id?: string) => string;
74
+ readonly styles: Map<string, number>;
75
+ readonly layers: Map<string, Array<number>>;
76
+ };
43
77
 
44
78
  /**
45
- * IFC4 (Reference View) with every mesh as an IfcTriangulatedFaceSet, in millimetres. Every top-level group and every group with `data` becomes an
46
- * IfcBuildingElementProxy placed relative to its parent element and aggregated into it. Groups without `data` are only transforms, so their meshes
47
- * are merged into the parent element
79
+ * IFC4 (Reference View) with every mesh as an IfcTriangulatedFaceSet, in millimetres. Every top-level group and every group with a `data.id` or
80
+ * `data.name` becomes an IfcBuildingElementProxy placed relative to its parent element and aggregated into it. Other groups are only transforms or
81
+ * metadata, so their meshes are merged into the parent element. With `layer`, the face sets are assigned to an IfcPresentationLayerAssignment per
82
+ * layer, the presentation layer of the Reference View
48
83
  */
49
84
  export function render(scene: Scene, options: IfcOptions = {}): string {
50
85
  const name = options.name ?? "Abstract 3D";
86
+ const author = options.author ?? " ";
87
+ const organization = options.organization ?? "UNKNOWN";
88
+ const application = options.application ?? { name: "Abstract 3D" };
89
+ const now = new Date();
51
90
  const m = ifcFile();
52
91
 
92
+ const ownerHistory = ownerHistoryEntity(m, author, organization, application, now);
53
93
  const world = axisPlacement(m, vec3Zero, vec3Zero);
54
94
  const context = add(m, `IFCGEOMETRICREPRESENTATIONCONTEXT($,'Model',3,1.E-05,${ref(world)},$)`);
55
95
  const body = add(m, `IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Body','Model',*,*,*,*,${ref(context)},$,.MODEL_VIEW.,$)`);
96
+ const c: IfcContext = { body, owner: (id) => `${str(guid(m, id))},${ref(ownerHistory)}`, styles: new Map(), layers: new Map() };
56
97
  const units = [
57
98
  add(m, "IFCSIUNIT(*,.LENGTHUNIT.,.MILLI.,.METRE.)"),
58
99
  add(m, "IFCSIUNIT(*,.AREAUNIT.,$,.SQUARE_METRE.)"),
59
100
  add(m, "IFCSIUNIT(*,.VOLUMEUNIT.,$,.CUBIC_METRE.)"),
60
101
  add(m, "IFCSIUNIT(*,.PLANEANGLEUNIT.,$,.RADIAN.)"),
61
102
  ];
62
- const project = add(m, `IFCPROJECT(${str(guid(m))},$,${str(name)},$,$,$,$,(${ref(context)}),${ref(add(m, `IFCUNITASSIGNMENT(${refs(units)})`))})`);
103
+ const project = add(m, `IFCPROJECT(${c.owner()},${str(name)},$,$,$,$,(${ref(context)}),${ref(add(m, `IFCUNITASSIGNMENT(${refs(units)})`))})`);
63
104
 
64
105
  const sitePlacement = add(m, `IFCLOCALPLACEMENT($,${ref(world)})`);
65
- const site = add(m, `IFCSITE(${str(guid(m))},$,'Site',$,$,${ref(sitePlacement)},$,$,.ELEMENT.,$,$,$,$,$)`);
106
+ const site = add(m, `IFCSITE(${c.owner()},'Site',$,$,${ref(sitePlacement)},$,$,.ELEMENT.,$,$,$,$,$)`);
66
107
  const buildingPlacement = add(m, `IFCLOCALPLACEMENT(${ref(sitePlacement)},${ref(world)})`);
67
- const building = add(m, `IFCBUILDING(${str(guid(m))},$,'Building',$,$,${ref(buildingPlacement)},$,$,.ELEMENT.,$,$,$)`);
108
+ const building = add(m, `IFCBUILDING(${c.owner()},'Building',$,$,${ref(buildingPlacement)},$,$,.ELEMENT.,$,$,$)`);
68
109
  const storeyPlacement = add(m, `IFCLOCALPLACEMENT(${ref(buildingPlacement)},${ref(world)})`);
69
- const storey = add(m, `IFCBUILDINGSTOREY(${str(guid(m))},$,'Storey',$,$,${ref(storeyPlacement)},$,$,.ELEMENT.,0.)`);
70
- aggregate(m, project, [site]);
71
- aggregate(m, site, [building]);
72
- aggregate(m, building, [storey]);
110
+ const storey = add(m, `IFCBUILDINGSTOREY(${c.owner()},'Storey',$,$,${ref(storeyPlacement)},$,$,.ELEMENT.,0.)`);
111
+ aggregate(m, c, project, [site]);
112
+ aggregate(m, c, site, [building]);
113
+ aggregate(m, c, building, [storey]);
73
114
 
74
115
  const center = scene.center_deprecated ?? vec3Zero;
75
116
  const sceneRot = scene.rotation_deprecated ?? vec3Zero;
76
- const c: IfcContext = { body, styles: new Map() };
77
- const nodes = options.root
78
- ? [elementNode({ pos: center, rot: sceneRot, groups: scene.groups, data: { name: options.root.name } }, center, sceneRot, options.root)]
79
- : scene.groups.map((g) => elementNode(g, vec3TransRot(g.pos, center, sceneRot), vec3RotCombine(sceneRot, g.rot ?? vec3Zero)));
117
+ const top: Layering = { layerOf: options.layer, path: [], layer: undefined };
118
+ const rootGroup: Group | undefined = options.root && { pos: center, rot: sceneRot, groups: scene.groups, data: { name: options.root.name } };
119
+ const nodes = rootGroup
120
+ ? [elementNode(rootGroup, center, sceneRot, groupLayering(rootGroup, top), options.root)]
121
+ : scene.groups.map((g) =>
122
+ elementNode(g, vec3TransRot(g.pos, center, sceneRot), vec3RotCombine(sceneRot, g.rot ?? vec3Zero), groupLayering(g, top))
123
+ );
80
124
  const elements = nodes.flatMap((node) => node ?? []).map((node, i) => element(m, node, `${i + 1}`, storeyPlacement, c));
81
125
  if (elements.length > 0) {
82
- add(m, `IFCRELCONTAINEDINSPATIALSTRUCTURE(${str(guid(m))},$,$,$,${refs(elements)},${ref(storey)})`);
126
+ add(m, `IFCRELCONTAINEDINSPATIALSTRUCTURE(${c.owner()},$,$,${refs(elements)},${ref(storey)})`);
83
127
  }
128
+ c.layers.forEach((items, layer) => add(m, `IFCPRESENTATIONLAYERASSIGNMENT(${str(layer)},$,${refs(items)},$)`));
84
129
 
85
- const date = new Date().toISOString().split(".")[0] ?? "1970-01-01T00:00:00";
86
- return serialize(m, `${name}.ifc`, date);
130
+ const date = now.toISOString().split(".")[0] ?? "1970-01-01T00:00:00";
131
+ return serialize(m, { fileName: `${name}.ifc`, date, author, organization, originatingSystem: application.name });
87
132
  }
88
133
 
89
- function elementNode(group: Group, pos: Vec3, rot: Vec3, elementClass = proxyClass): ElementNode | undefined {
90
- const { meshes, children } = elementContent(group, vec3Zero, vec3Zero);
134
+ /** The author as the owning user and the application, ADDED requires LastModifiedDate in IFC4 so it's set to the creation date */
135
+ function ownerHistoryEntity(m: MutableIfc, author: string, organization: string, application: IfcApplicationInfo, now: Date): number {
136
+ const person = add(m, `IFCPERSON(${str(author)},$,$,$,$,$,$,$)`);
137
+ const owningOrganization = add(m, `IFCORGANIZATION($,${str(organization)},$,$,$)`);
138
+ const { name, version = "", developer = "Divid AB" } = application;
139
+ const developerOrganization = developer === organization ? owningOrganization : add(m, `IFCORGANIZATION($,${str(developer)},$,$,$)`);
140
+ const user = add(m, `IFCPERSONANDORGANIZATION(${ref(person)},${ref(owningOrganization)},$)`);
141
+ const app = add(m, `IFCAPPLICATION(${ref(developerOrganization)},${str(version)},${str(name)},${str(name)})`);
142
+ const timestamp = Math.floor(now.getTime() / 1000);
143
+ return add(m, `IFCOWNERHISTORY(${ref(user)},${ref(app)},$,.ADDED.,${timestamp},$,$,${timestamp})`);
144
+ }
145
+
146
+ /** `layering` is the group's own, see `groupLayering` */
147
+ function elementNode(group: Group, pos: Vec3, rot: Vec3, layering: Layering, elementClass = proxyClass): ElementNode | undefined {
148
+ const { meshes, children } = elementContent(group, vec3Zero, vec3Zero, layering);
91
149
  return meshes.length > 0 || children.length > 0 ? { group, elementClass, pos, rot, meshes, children } : undefined;
92
150
  }
93
151
 
94
- /** Meshes of the group and its descendants without data, relative to the element the group is at pos/rot in, and the descendants with data as elements */
95
- function elementContent(group: Group, pos: Vec3, rot: Vec3): Pick<ElementNode, "meshes" | "children"> {
152
+ /**
153
+ * Meshes of the group and its descendants that aren't elements, relative to the element the group is at pos/rot in, and the descendants with a
154
+ * `data.id` or `data.name` as elements
155
+ */
156
+ function elementContent(group: Group, pos: Vec3, rot: Vec3, layering: Layering): Pick<ElementNode, "meshes" | "children"> {
96
157
  const meshes = (group.meshes ?? []).flatMap((mesh) => {
97
158
  const triangulation = triangulate(mesh.geometry, pos, rot);
98
- return triangulation ? [{ material: mesh.material, triangulation }] : [];
159
+ return triangulation ? [{ material: mesh.material, triangulation, layer: layering.layer }] : [];
99
160
  });
100
161
  const nested = (group.groups ?? []).map((child) => {
101
162
  const childPos = vec3TransRot(child.pos, pos, rot);
102
163
  const childRot = vec3RotCombine(rot, child.rot ?? vec3Zero);
103
- return Object.keys(child.data ?? {}).length > 0
104
- ? { meshes: [], children: [elementNode(child, childPos, childRot)].flatMap((node) => node ?? []) }
105
- : elementContent(child, childPos, childRot);
164
+ const childLayering = groupLayering(child, layering);
165
+ return child.data?.["id"] !== undefined || child.data?.["name"] !== undefined
166
+ ? { meshes: [], children: [elementNode(child, childPos, childRot, childLayering)].flatMap((node) => node ?? []) }
167
+ : elementContent(child, childPos, childRot, childLayering);
106
168
  });
107
169
  return { meshes: [...meshes, ...nested.flatMap((n) => n.meshes)], children: nested.flatMap((n) => n.children) };
108
170
  }
109
171
 
172
+ /** Groups with `data` are added to the path and get the layer `layerOf` returns for it, if any, otherwise the layer of the parent */
173
+ function groupLayering(group: Group, parent: Layering): Layering {
174
+ const data = group.data;
175
+ if (data === undefined || Object.keys(data).length === 0) {
176
+ return parent;
177
+ }
178
+ const path = [...parent.path, data];
179
+ const layer = parent.layerOf?.(path);
180
+ return { ...parent, path, layer: layer === undefined || layer === "" ? parent.layer : layer };
181
+ }
182
+
110
183
  /** `path` is the element's position in the tree (e.g. "2.1"), named after it when the group has no `data.name` or `data.id` since IFC requires a name */
111
184
  function element(m: MutableIfc, node: ElementNode, path: string, parentPlacement: number, c: IfcContext): number {
112
185
  const placement = add(m, `IFCLOCALPLACEMENT(${ref(parentPlacement)},${ref(axisPlacement(m, node.pos, node.rot))})`);
113
- const items = node.meshes.map(({ material, triangulation }) => faceSet(m, triangulation, material, c));
186
+ const items = node.meshes.map((mesh) => faceSet(m, mesh, c));
114
187
  const shape =
115
188
  items.length > 0
116
189
  ? ref(add(m, `IFCPRODUCTDEFINITIONSHAPE($,$,(${ref(add(m, `IFCSHAPEREPRESENTATION(${ref(c.body)},'Body','Tessellation',${refs(items)})`))}))`))
@@ -118,22 +191,29 @@ function element(m: MutableIfc, node: ElementNode, path: string, parentPlacement
118
191
  const id = node.group.data?.["id"];
119
192
  const name = node.group.data?.["name"] ?? id ?? `Element ${path}`;
120
193
  const { entity, predefinedType = "NOTDEFINED" } = node.elementClass;
121
- const ifcElement = add(
122
- m,
123
- `${entity.toUpperCase()}(${str(guid(m, id))},$,${str(name)},$,$,${ref(placement)},${shape},${str(id)},.${predefinedType}.)`
124
- );
194
+ const ifcElement = add(m, `${entity.toUpperCase()}(${c.owner(id)},${str(name)},$,$,${ref(placement)},${shape},${str(id)},.${predefinedType}.)`);
125
195
  aggregate(
126
196
  m,
197
+ c,
127
198
  ifcElement,
128
199
  node.children.map((child, i) => element(m, child, `${path}.${i + 1}`, placement, c))
129
200
  );
130
201
  return ifcElement;
131
202
  }
132
203
 
133
- function faceSet(m: MutableIfc, { points, triangles }: Triangulation, material: Material, c: IfcContext): number {
204
+ /** One face set per mesh, so meshes on different layers are never in the same item */
205
+ function faceSet(m: MutableIfc, { material, triangulation: { points, triangles }, layer }: NodeMesh, c: IfcContext): number {
134
206
  const pointList = add(m, `IFCCARTESIANPOINTLIST3D((${points.join(",")}))`);
135
207
  const faces = add(m, `IFCTRIANGULATEDFACESET(${ref(pointList)},$,.F.,(${triangles.map((t) => `(${t.join(",")})`).join(",")}),$)`);
136
208
  add(m, `IFCSTYLEDITEM(${ref(faces)},(${ref(surfaceStyle(m, material, c))}),$)`);
209
+ if (layer !== undefined) {
210
+ const items = c.layers.get(layer);
211
+ if (items) {
212
+ items.push(faces);
213
+ } else {
214
+ c.layers.set(layer, [faces]);
215
+ }
216
+ }
137
217
  return faces;
138
218
  }
139
219
 
@@ -146,8 +226,9 @@ function surfaceStyle(m: MutableIfc, material: Material, c: IfcContext): number
146
226
  }
147
227
  const { r, g, b } = new Color(material.normal).getRGB({ r: 0, g: 0, b: 0 }, SRGBColorSpace);
148
228
  const colour = add(m, `IFCCOLOURRGB($,${real(r)},${real(g)},${real(b)})`);
149
- const shading = add(m, `IFCSURFACESTYLESHADING(${ref(colour)},${real(1 - opacity)})`);
150
- const style = add(m, `IFCSURFACESTYLE(${str(material.normal)},.BOTH.,(${ref(shading)}))`);
229
+ // Rendering rather than its supertype shading, since many viewers only read the transparency from rendering
230
+ const rendering = add(m, `IFCSURFACESTYLERENDERING(${ref(colour)},${real(1 - opacity)},$,$,$,$,$,$,.NOTDEFINED.)`);
231
+ const style = add(m, `IFCSURFACESTYLE(${str(material.normal)},.BOTH.,(${ref(rendering)}))`);
151
232
  c.styles.set(key, style);
152
233
  return style;
153
234
  }
@@ -160,8 +241,8 @@ function axisPlacement(m: MutableIfc, pos: Vec3, rot: Vec3): number {
160
241
  return add(m, `IFCAXIS2PLACEMENT3D(${ref(location)},${ref(axis)},${ref(refDirection)})`);
161
242
  }
162
243
 
163
- function aggregate(m: MutableIfc, parent: number, children: ReadonlyArray<number>): void {
244
+ function aggregate(m: MutableIfc, c: IfcContext, parent: number, children: ReadonlyArray<number>): void {
164
245
  if (children.length > 0) {
165
- add(m, `IFCRELAGGREGATES(${str(guid(m))},$,$,$,${ref(parent)},${refs(children)})`);
246
+ add(m, `IFCRELAGGREGATES(${c.owner()},$,$,${ref(parent)},${refs(children)})`);
166
247
  }
167
248
  }