@bitbybit-dev/ifc 0.0.0-stage → 1.5.0-rc.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.
Files changed (242) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +42 -0
  3. package/README.md +92 -2
  4. package/index.d.ts +1 -0
  5. package/index.js +1 -0
  6. package/lib/api/dto-registry.d.ts +8 -0
  7. package/lib/api/dto-registry.js +109 -0
  8. package/lib/api/ifc-service.d.ts +109 -0
  9. package/lib/api/ifc-service.js +55 -0
  10. package/lib/api/inputs/base-inputs.d.ts +5 -0
  11. package/lib/api/inputs/base-inputs.js +5 -0
  12. package/lib/api/inputs/ifc-inputs.d.ts +2727 -0
  13. package/lib/api/inputs/ifc-inputs.js +2498 -0
  14. package/lib/api/inputs/index.d.ts +3 -0
  15. package/lib/api/inputs/index.js +3 -0
  16. package/lib/api/resolved-inputs/index.d.ts +70 -0
  17. package/lib/api/resolved-inputs/index.js +1 -0
  18. package/lib/api/services/assemblies.d.ts +28 -0
  19. package/lib/api/services/assemblies.js +49 -0
  20. package/lib/api/services/beams.d.ts +33 -0
  21. package/lib/api/services/beams.js +59 -0
  22. package/lib/api/services/columns.d.ts +26 -0
  23. package/lib/api/services/columns.js +56 -0
  24. package/lib/api/services/defaults.constants.d.ts +44 -0
  25. package/lib/api/services/defaults.constants.js +44 -0
  26. package/lib/api/services/doors.d.ts +45 -0
  27. package/lib/api/services/doors.js +94 -0
  28. package/lib/api/services/geometry.d.ts +51 -0
  29. package/lib/api/services/geometry.js +87 -0
  30. package/lib/api/services/index.d.ts +17 -0
  31. package/lib/api/services/index.js +17 -0
  32. package/lib/api/services/materials.d.ts +46 -0
  33. package/lib/api/services/materials.js +86 -0
  34. package/lib/api/services/member-support.d.ts +7 -0
  35. package/lib/api/services/member-support.js +29 -0
  36. package/lib/api/services/members.d.ts +24 -0
  37. package/lib/api/services/members.js +51 -0
  38. package/lib/api/services/model.d.ts +244 -0
  39. package/lib/api/services/model.js +409 -0
  40. package/lib/api/services/openings.d.ts +57 -0
  41. package/lib/api/services/openings.js +102 -0
  42. package/lib/api/services/properties.d.ts +89 -0
  43. package/lib/api/services/properties.js +142 -0
  44. package/lib/api/services/quantities.d.ts +38 -0
  45. package/lib/api/services/quantities.js +51 -0
  46. package/lib/api/services/roofs.d.ts +24 -0
  47. package/lib/api/services/roofs.js +52 -0
  48. package/lib/api/services/service-support.d.ts +8 -0
  49. package/lib/api/services/service-support.js +37 -0
  50. package/lib/api/services/service-types.d.ts +3 -0
  51. package/lib/api/services/service-types.js +1 -0
  52. package/lib/api/services/site.d.ts +37 -0
  53. package/lib/api/services/site.js +80 -0
  54. package/lib/api/services/slabs.d.ts +31 -0
  55. package/lib/api/services/slabs.js +59 -0
  56. package/lib/api/services/spaces.d.ts +36 -0
  57. package/lib/api/services/spaces.js +64 -0
  58. package/lib/api/services/spatial.d.ts +54 -0
  59. package/lib/api/services/spatial.js +75 -0
  60. package/lib/api/services/walls.d.ts +140 -0
  61. package/lib/api/services/walls.js +268 -0
  62. package/lib/api/services/windows.d.ts +46 -0
  63. package/lib/api/services/windows.js +76 -0
  64. package/lib/build/assemblies.d.ts +4 -0
  65. package/lib/build/assemblies.js +45 -0
  66. package/lib/build/build-types.d.ts +345 -0
  67. package/lib/build/build-types.js +1 -0
  68. package/lib/build/checks.d.ts +6 -0
  69. package/lib/build/checks.js +32 -0
  70. package/lib/build/constants.d.ts +27 -0
  71. package/lib/build/constants.js +43 -0
  72. package/lib/build/contexts.d.ts +9 -0
  73. package/lib/build/contexts.js +52 -0
  74. package/lib/build/curves.d.ts +3 -0
  75. package/lib/build/curves.js +23 -0
  76. package/lib/build/entity-writer.d.ts +23 -0
  77. package/lib/build/entity-writer.js +97 -0
  78. package/lib/build/fillings.d.ts +7 -0
  79. package/lib/build/fillings.js +182 -0
  80. package/lib/build/georeference.d.ts +5 -0
  81. package/lib/build/georeference.js +44 -0
  82. package/lib/build/materials.d.ts +18 -0
  83. package/lib/build/materials.js +166 -0
  84. package/lib/build/math.d.ts +10 -0
  85. package/lib/build/math.js +47 -0
  86. package/lib/build/measure.d.ts +9 -0
  87. package/lib/build/measure.js +195 -0
  88. package/lib/build/moving.d.ts +4 -0
  89. package/lib/build/moving.js +61 -0
  90. package/lib/build/openings.d.ts +12 -0
  91. package/lib/build/openings.js +156 -0
  92. package/lib/build/outlines.d.ts +4 -0
  93. package/lib/build/outlines.js +40 -0
  94. package/lib/build/placement.d.ts +16 -0
  95. package/lib/build/placement.js +106 -0
  96. package/lib/build/profiles.d.ts +4 -0
  97. package/lib/build/profiles.js +35 -0
  98. package/lib/build/project.d.ts +11 -0
  99. package/lib/build/project.js +134 -0
  100. package/lib/build/properties.d.ts +10 -0
  101. package/lib/build/properties.js +182 -0
  102. package/lib/build/quantities.d.ts +7 -0
  103. package/lib/build/quantities.js +262 -0
  104. package/lib/build/relationships.d.ts +9 -0
  105. package/lib/build/relationships.js +67 -0
  106. package/lib/build/removal.d.ts +3 -0
  107. package/lib/build/removal.js +106 -0
  108. package/lib/build/representations.d.ts +6 -0
  109. package/lib/build/representations.js +46 -0
  110. package/lib/build/roof-clipping.d.ts +5 -0
  111. package/lib/build/roof-clipping.js +79 -0
  112. package/lib/build/roofs.d.ts +4 -0
  113. package/lib/build/roofs.js +131 -0
  114. package/lib/build/site.d.ts +7 -0
  115. package/lib/build/site.js +112 -0
  116. package/lib/build/slab-openings.d.ts +4 -0
  117. package/lib/build/slab-openings.js +71 -0
  118. package/lib/build/slabs-columns-beams.d.ts +8 -0
  119. package/lib/build/slabs-columns-beams.js +73 -0
  120. package/lib/build/solids.d.ts +5 -0
  121. package/lib/build/solids.js +33 -0
  122. package/lib/build/spaces.d.ts +6 -0
  123. package/lib/build/spaces.js +55 -0
  124. package/lib/build/spatial.d.ts +17 -0
  125. package/lib/build/spatial.js +111 -0
  126. package/lib/build/type-objects.d.ts +4 -0
  127. package/lib/build/type-objects.js +9 -0
  128. package/lib/build/wall-edits.d.ts +5 -0
  129. package/lib/build/wall-edits.js +138 -0
  130. package/lib/build/wall-geometry.d.ts +15 -0
  131. package/lib/build/wall-geometry.js +159 -0
  132. package/lib/build/wall-parameters.d.ts +3 -0
  133. package/lib/build/wall-parameters.js +47 -0
  134. package/lib/build/walls.d.ts +12 -0
  135. package/lib/build/walls.js +238 -0
  136. package/lib/geometry/advanced.d.ts +27 -0
  137. package/lib/geometry/advanced.js +292 -0
  138. package/lib/geometry/colours.d.ts +3 -0
  139. package/lib/geometry/colours.js +109 -0
  140. package/lib/geometry/curves.d.ts +32 -0
  141. package/lib/geometry/curves.js +370 -0
  142. package/lib/geometry/edges.constants.d.ts +5 -0
  143. package/lib/geometry/edges.constants.js +5 -0
  144. package/lib/geometry/edges.d.ts +21 -0
  145. package/lib/geometry/edges.js +164 -0
  146. package/lib/geometry/elements.d.ts +3 -0
  147. package/lib/geometry/elements.js +152 -0
  148. package/lib/geometry/errors.d.ts +3 -0
  149. package/lib/geometry/errors.js +6 -0
  150. package/lib/geometry/faceted.d.ts +31 -0
  151. package/lib/geometry/faceted.js +214 -0
  152. package/lib/geometry/geometry-types.d.ts +103 -0
  153. package/lib/geometry/geometry-types.js +1 -0
  154. package/lib/geometry/groups.d.ts +21 -0
  155. package/lib/geometry/groups.js +106 -0
  156. package/lib/geometry/items.d.ts +34 -0
  157. package/lib/geometry/items.js +313 -0
  158. package/lib/geometry/operators.d.ts +3 -0
  159. package/lib/geometry/operators.js +65 -0
  160. package/lib/geometry/profiles.d.ts +4 -0
  161. package/lib/geometry/profiles.js +277 -0
  162. package/lib/geometry/recipe-builder.d.ts +14 -0
  163. package/lib/geometry/recipe-builder.js +48 -0
  164. package/lib/geometry/references.d.ts +4 -0
  165. package/lib/geometry/references.js +17 -0
  166. package/lib/geometry/regions.d.ts +4 -0
  167. package/lib/geometry/regions.js +26 -0
  168. package/lib/geometry/surfaces.constants.d.ts +17 -0
  169. package/lib/geometry/surfaces.constants.js +17 -0
  170. package/lib/geometry/surfaces.d.ts +6 -0
  171. package/lib/geometry/surfaces.js +306 -0
  172. package/lib/geometry/swept-solids.constants.d.ts +7 -0
  173. package/lib/geometry/swept-solids.constants.js +6 -0
  174. package/lib/geometry/swept-solids.d.ts +25 -0
  175. package/lib/geometry/swept-solids.js +243 -0
  176. package/lib/index.d.ts +6 -0
  177. package/lib/index.js +6 -0
  178. package/lib/model/constants.d.ts +30 -0
  179. package/lib/model/constants.js +30 -0
  180. package/lib/model/entity-lookup.d.ts +9 -0
  181. package/lib/model/entity-lookup.js +20 -0
  182. package/lib/model/guid.d.ts +7 -0
  183. package/lib/model/guid.js +60 -0
  184. package/lib/model/id-map.d.ts +10 -0
  185. package/lib/model/id-map.js +80 -0
  186. package/lib/model/index.d.ts +4 -0
  187. package/lib/model/index.js +2 -0
  188. package/lib/model/io.d.ts +6 -0
  189. package/lib/model/io.js +136 -0
  190. package/lib/model/is-model.d.ts +9 -0
  191. package/lib/model/is-model.js +11 -0
  192. package/lib/model/model-types.d.ts +111 -0
  193. package/lib/model/model-types.js +1 -0
  194. package/lib/model/overlay-indexes.d.ts +17 -0
  195. package/lib/model/overlay-indexes.js +69 -0
  196. package/lib/model/references.d.ts +2 -0
  197. package/lib/model/references.js +51 -0
  198. package/lib/model/rows-by-id.d.ts +8 -0
  199. package/lib/model/rows-by-id.js +39 -0
  200. package/lib/model/snapshot.d.ts +36 -0
  201. package/lib/model/snapshot.js +144 -0
  202. package/lib/model/source.d.ts +29 -0
  203. package/lib/model/source.js +172 -0
  204. package/lib/model/transaction.d.ts +39 -0
  205. package/lib/model/transaction.js +250 -0
  206. package/lib/model/upgrade.d.ts +2 -0
  207. package/lib/model/upgrade.js +78 -0
  208. package/lib/schema/constants.d.ts +3 -0
  209. package/lib/schema/constants.js +3 -0
  210. package/lib/schema/generated/ifc4.d.ts +2 -0
  211. package/lib/schema/generated/ifc4.js +1204 -0
  212. package/lib/schema/generated/ifc4x3.d.ts +2 -0
  213. package/lib/schema/generated/ifc4x3.js +1325 -0
  214. package/lib/schema/registry.d.ts +7 -0
  215. package/lib/schema/registry.js +37 -0
  216. package/lib/schema/schema-types.d.ts +45 -0
  217. package/lib/schema/schema-types.js +1 -0
  218. package/lib/schema/schema.d.ts +23 -0
  219. package/lib/schema/schema.js +136 -0
  220. package/lib/step/constants.d.ts +48 -0
  221. package/lib/step/constants.js +48 -0
  222. package/lib/step/encoder.d.ts +21 -0
  223. package/lib/step/encoder.js +321 -0
  224. package/lib/step/errors.d.ts +39 -0
  225. package/lib/step/errors.js +45 -0
  226. package/lib/step/file-index.d.ts +2 -0
  227. package/lib/step/file-index.js +221 -0
  228. package/lib/step/header.d.ts +4 -0
  229. package/lib/step/header.js +52 -0
  230. package/lib/step/numbers.d.ts +3 -0
  231. package/lib/step/numbers.js +73 -0
  232. package/lib/step/reader.d.ts +2 -0
  233. package/lib/step/reader.js +160 -0
  234. package/lib/step/scanner.d.ts +13 -0
  235. package/lib/step/scanner.js +203 -0
  236. package/lib/step/step-types.d.ts +170 -0
  237. package/lib/step/step-types.js +1 -0
  238. package/lib/step/strings.d.ts +2 -0
  239. package/lib/step/strings.js +150 -0
  240. package/lib/step/values.d.ts +13 -0
  241. package/lib/step/values.js +51 -0
  242. package/package.json +51 -5
@@ -0,0 +1,8 @@
1
+ import type { Base } from "@bitbybit-dev/base";
2
+ import type { IfcTransaction } from "../model/transaction";
3
+ import type { MemberSpec, SlabSpec } from "./build-types";
4
+ import type { EntityWriter } from "./entity-writer";
5
+ import type { Frame3 } from "./build-types";
6
+ export declare function createSlab(tx: IfcTransaction, writer: EntityWriter, spec: SlabSpec, tolerance: number): number;
7
+ export declare function memberFrame(start: Base.Point3, end: Base.Point3, rotationDegrees: number): Frame3;
8
+ export declare function createMember(tx: IfcTransaction, writer: EntityWriter, kind: "IfcColumn" | "IfcBeam" | "IfcMember", spec: MemberSpec): number;
@@ -0,0 +1,73 @@
1
+ import { WORLD_AXES } from "@bitbybit-dev/base/lib/api/services/helpers/frame-axes";
2
+ import { cross3, length3, subtract3 } from "@bitbybit-dev/base/lib/api/services/helpers/vectors";
3
+ import { isInsidePolygon2, wound2 } from "@bitbybit-dev/base/lib/api/services/helpers/polygons";
4
+ import { enumValue, ref } from "../step/values";
5
+ import { DEGREES_TO_RADIANS, VERTICAL_COSINE } from "./constants";
6
+ import { bodyContext } from "./contexts";
7
+ import { associateMaterial, associateNewMaterial, layerSetThickness, layerSetUsage } from "./materials";
8
+ import { frameFrom, normalize3 } from "./math";
9
+ import { objectPlacementOf } from "./placement";
10
+ import { writeProfile } from "./profiles";
11
+ import { containIn } from "./spatial";
12
+ import { cleanOutline } from "./outlines";
13
+ export function createSlab(tx, writer, spec, tolerance) {
14
+ var _a;
15
+ const thickness = layerSetThickness(tx, spec.layerSet);
16
+ if (!(thickness > 0)) {
17
+ throw new Error("A slab's layers must add up to more than zero thickness");
18
+ }
19
+ const outer = wound2(cleanOutline(spec.outline, tolerance, "outline"), true);
20
+ const holes = spec.holes.map((hole, index) => {
21
+ const cleaned = cleanOutline(hole, tolerance, `hole ${index}`);
22
+ if (!cleaned.every((point) => isInsidePolygon2(point, outer))) {
23
+ throw new Error(`Hole ${index} reaches outside the slab's outline`);
24
+ }
25
+ return wound2(cleaned, false);
26
+ });
27
+ const placement = writer.localPlacement(objectPlacementOf(tx, spec.storey), Object.assign(Object.assign({}, WORLD_AXES), { origin: [0, 0, spec.topOffset] }));
28
+ const solid = writer.extrusion(writer.profile({ outer, holes }), WORLD_AXES, thickness, [0, 0, -1]);
29
+ const body = writer.shapeRepresentation(bodyContext(tx, writer), "Body", "SweptSolid", [solid]);
30
+ const slab = writer.create("IfcSlab", {
31
+ GlobalId: tx.globalId(spec.id),
32
+ Name: (_a = spec.name) !== null && _a !== void 0 ? _a : null,
33
+ ObjectPlacement: ref(placement),
34
+ Representation: ref(writer.productShape([body])),
35
+ PredefinedType: enumValue(spec.predefinedType),
36
+ });
37
+ containIn(tx, writer, spec.storey, slab);
38
+ associateNewMaterial(tx, writer, [slab], layerSetUsage(writer, spec.layerSet, "AXIS3", "NEGATIVE", 0));
39
+ return slab;
40
+ }
41
+ export function memberFrame(start, end, rotationDegrees) {
42
+ const along = subtract3(end, start);
43
+ if (!(length3(along) > 0)) {
44
+ throw new Error("A member's start and end must be apart");
45
+ }
46
+ const z = normalize3(along);
47
+ const horizontal = Math.abs(z[2]) >= VERTICAL_COSINE ? [1, 0, 0] : normalize3(cross3([0, 0, 1], z));
48
+ const base = frameFrom(start, z, horizontal);
49
+ const angle = rotationDegrees * DEGREES_TO_RADIANS;
50
+ const cos = Math.cos(angle);
51
+ const sin = Math.sin(angle);
52
+ const x = [base.x[0] * cos + base.y[0] * sin, base.x[1] * cos + base.y[1] * sin, base.x[2] * cos + base.y[2] * sin];
53
+ return frameFrom(start, z, x);
54
+ }
55
+ export function createMember(tx, writer, kind, spec) {
56
+ var _a;
57
+ const frame = memberFrame(spec.start, spec.end, spec.rotation);
58
+ const placement = writer.localPlacement(objectPlacementOf(tx, spec.storey), frame);
59
+ const solid = writer.extrusion(writeProfile(writer, spec.profile, undefined), WORLD_AXES, length3(subtract3(spec.end, spec.start)));
60
+ const body = writer.shapeRepresentation(bodyContext(tx, writer), "Body", "SweptSolid", [solid]);
61
+ const member = writer.create(kind, {
62
+ GlobalId: tx.globalId(spec.id),
63
+ Name: (_a = spec.name) !== null && _a !== void 0 ? _a : null,
64
+ ObjectPlacement: ref(placement),
65
+ Representation: ref(writer.productShape([body])),
66
+ PredefinedType: enumValue(spec.predefinedType),
67
+ });
68
+ containIn(tx, writer, spec.storey, member);
69
+ if (spec.material !== undefined) {
70
+ associateMaterial(tx, writer, [member], spec.material);
71
+ }
72
+ return member;
73
+ }
@@ -0,0 +1,5 @@
1
+ import type { Base } from "@bitbybit-dev/base";
2
+ import type { IfcValue } from "../step/step-types";
3
+ import type { Frame3, ModelReader } from "./build-types";
4
+ export declare function frameOf(reader: ModelReader, placement: IfcValue): Frame3;
5
+ export declare function extrusionCorners(reader: ModelReader, item: number): Base.Point3[];
@@ -0,0 +1,33 @@
1
+ import { WORLD_AXES, pointToWorld } from "@bitbybit-dev/base/lib/api/services/helpers/frame-axes";
2
+ import { isReference } from "../step/values";
3
+ import { axisPlacementFrame, directionOf } from "./placement";
4
+ export function frameOf(reader, placement) {
5
+ return isReference(placement) ? axisPlacementFrame(reader, placement.ref) : WORLD_AXES;
6
+ }
7
+ export function extrusionCorners(reader, item) {
8
+ if (reader.entity(item).type !== "IfcExtrudedAreaSolid") {
9
+ return [];
10
+ }
11
+ const profile = reader.attribute(item, "SweptArea");
12
+ const depth = reader.attribute(item, "Depth");
13
+ if (!isReference(profile) || reader.entity(profile.ref).type !== "IfcRectangleProfileDef" || typeof depth !== "number") {
14
+ return [];
15
+ }
16
+ const xDim = reader.attribute(profile.ref, "XDim");
17
+ const yDim = reader.attribute(profile.ref, "YDim");
18
+ if (typeof xDim !== "number" || typeof yDim !== "number") {
19
+ return [];
20
+ }
21
+ const profileFrame = frameOf(reader, reader.attribute(profile.ref, "Position"));
22
+ const solidFrame = frameOf(reader, reader.attribute(item, "Position"));
23
+ const direction = directionOf(reader, reader.attribute(item, "ExtrudedDirection"), [0, 0, 1]);
24
+ const scale = depth / Math.hypot(direction[0], direction[1], direction[2]);
25
+ const corners = [];
26
+ for (const x of [-xDim / 2, xDim / 2]) {
27
+ for (const y of [-yDim / 2, yDim / 2]) {
28
+ const base = pointToWorld(profileFrame, [x, y, 0]);
29
+ corners.push(pointToWorld(solidFrame, base), pointToWorld(solidFrame, [base[0] + direction[0] * scale, base[1] + direction[1] * scale, direction[2] * scale]));
30
+ }
31
+ }
32
+ return corners;
33
+ }
@@ -0,0 +1,6 @@
1
+ import type * as Inputs from "../api/inputs";
2
+ import type { IfcTransaction } from "../model/transaction";
3
+ import type { ModelReader, SpaceSpec } from "./build-types";
4
+ import type { EntityWriter } from "./entity-writer";
5
+ export declare function createSpace(tx: IfcTransaction, writer: EntityWriter, spec: SpaceSpec, tolerance: number): number;
6
+ export declare function spacesOf(reader: ModelReader, storey: number | undefined): Inputs.IFC.SpaceInfoDto[];
@@ -0,0 +1,55 @@
1
+ import { WORLD_AXES, composeAxes } from "@bitbybit-dev/base/lib/api/services/helpers/frame-axes";
2
+ import { wound2 } from "@bitbybit-dev/base/lib/api/services/helpers/polygons";
3
+ import { enumValue, ref, textValue } from "../step/values";
4
+ import { AGGREGATION, VERTICAL_COSINE } from "./constants";
5
+ import { bodyContext } from "./contexts";
6
+ import { extrudedBodyOf } from "./measure";
7
+ import { cleanOutline } from "./outlines";
8
+ import { absoluteFrame, directionOf, objectPlacementOf } from "./placement";
9
+ import { appendToRelationship, relatingOf } from "./relationships";
10
+ const SPACE = "IfcSpace";
11
+ export function createSpace(tx, writer, spec, tolerance) {
12
+ var _a, _b;
13
+ if (!(spec.height > 0)) {
14
+ throw new Error(`A space's height must be more than zero, got ${spec.height}`);
15
+ }
16
+ const outline = wound2(cleanOutline(spec.outline, tolerance, "outline"), true);
17
+ const placement = writer.localPlacement(objectPlacementOf(tx, spec.storey), Object.assign(Object.assign({}, WORLD_AXES), { origin: [0, 0, spec.baseOffset] }));
18
+ const solid = writer.extrusion(writer.profile({ outer: outline, holes: [] }), WORLD_AXES, spec.height);
19
+ const body = writer.shapeRepresentation(bodyContext(tx, writer), "Body", "SweptSolid", [solid]);
20
+ const space = writer.create(SPACE, {
21
+ GlobalId: tx.globalId(spec.id),
22
+ Name: (_a = spec.name) !== null && _a !== void 0 ? _a : null,
23
+ ObjectPlacement: ref(placement),
24
+ Representation: ref(writer.productShape([body])),
25
+ LongName: (_b = spec.longName) !== null && _b !== void 0 ? _b : null,
26
+ CompositionType: enumValue("ELEMENT"),
27
+ PredefinedType: enumValue(spec.predefinedType),
28
+ });
29
+ appendToRelationship(tx, writer, AGGREGATION, spec.storey, [space]);
30
+ return space;
31
+ }
32
+ function extentOf(reader, space) {
33
+ const extruded = extrudedBodyOf(reader, space);
34
+ const frame = extruded === undefined ? undefined : composeAxes(absoluteFrame(reader, objectPlacementOf(reader, space)), extruded.frame);
35
+ const direction = extruded === undefined ? undefined : directionOf(reader, reader.attribute(extruded.solid, "ExtrudedDirection"), [0, 0, 1]);
36
+ const upright = frame !== undefined && direction !== undefined && frame.z[2] >= VERTICAL_COSINE && direction[2] / Math.hypot(direction[0], direction[1], direction[2]) >= VERTICAL_COSINE;
37
+ return extruded && upright ? [extruded.shape.area, extruded.depth] : [0, 0];
38
+ }
39
+ export function spacesOf(reader, storey) {
40
+ return reader.byType(SPACE)
41
+ .map((entity) => ({ id: entity.id, storey: relatingOf(reader, AGGREGATION, entity.id) }))
42
+ .filter((space) => storey === undefined || space.storey === storey)
43
+ .map(({ id, storey: holder }) => {
44
+ var _a, _b, _c, _d;
45
+ const [area, height] = extentOf(reader, id);
46
+ return {
47
+ globalId: (_a = textValue(reader.attribute(id, "GlobalId"))) !== null && _a !== void 0 ? _a : "",
48
+ name: (_b = textValue(reader.attribute(id, "Name"))) !== null && _b !== void 0 ? _b : "",
49
+ longName: (_c = textValue(reader.attribute(id, "LongName"))) !== null && _c !== void 0 ? _c : "",
50
+ storey: holder === undefined ? "" : (_d = textValue(reader.attribute(holder, "GlobalId"))) !== null && _d !== void 0 ? _d : "",
51
+ area,
52
+ height,
53
+ };
54
+ });
55
+ }
@@ -0,0 +1,17 @@
1
+ import type * as Inputs from "../api/inputs";
2
+ import type { ModelSnapshot } from "../model/snapshot";
3
+ import type { IfcTransaction } from "../model/transaction";
4
+ import type { ModelReader } from "./build-types";
5
+ import type { EntityWriter } from "./entity-writer";
6
+ import type { Frame3 } from "./build-types";
7
+ export declare function resolveObject(model: ModelSnapshot, idOrGlobalId: string, type: string, what: string): number;
8
+ export declare function describeObject(reader: ModelReader, id: number): string;
9
+ export declare function onlyBuilding(model: ModelSnapshot): number;
10
+ export declare function containIn(tx: IfcTransaction, writer: EntityWriter, structure: number, element: number): void;
11
+ export declare function containerOf(reader: ModelReader, element: number): number | undefined;
12
+ export declare function standingIn(reader: ModelReader, element: number): number | undefined;
13
+ export declare function storeysOf(model: ModelSnapshot): Inputs.IFC.StoreyInfoDto[];
14
+ export declare function addStorey(tx: IfcTransaction, writer: EntityWriter, building: number, id: string | undefined, name: string, elevation: number): number;
15
+ export declare function storeyFrame(reader: ModelReader, storey: number): Frame3;
16
+ export declare function storeyOf(reader: ModelReader, element: number): number | undefined;
17
+ export declare function setStoreyElevation(tx: IfcTransaction, writer: EntityWriter, storey: number, elevation: number): void;
@@ -0,0 +1,111 @@
1
+ import { WORLD_AXES } from "@bitbybit-dev/base/lib/api/services/helpers/frame-axes";
2
+ import { keyGlobalId } from "../model/guid";
3
+ import { enumValue, ref, textValue } from "../step/values";
4
+ import { AGGREGATION, CONTAINMENT } from "./constants";
5
+ import { absoluteFrame, movePlacement, objectPlacementOf, productsPlacedBy, relativeFrame } from "./placement";
6
+ import { appendToRelationship, relatingOf } from "./relationships";
7
+ const STOREY = "IfcBuildingStorey";
8
+ const SPATIAL_ELEMENT = "IfcSpatialElement";
9
+ const MAX_STRUCTURE_DEPTH = 32;
10
+ function article(word) {
11
+ return /^[aeiou]/i.test(word) ? "an" : "a";
12
+ }
13
+ export function resolveObject(model, idOrGlobalId, type, what) {
14
+ const owners = model.globalIdOwners(idOrGlobalId);
15
+ if (owners.length > 1) {
16
+ throw new Error(`The GlobalId '${idOrGlobalId}' belongs to ${owners.length} entities (${owners.map((owner) => `#${owner}`).join(", ")}), so it names no single ${what}`);
17
+ }
18
+ const held = owners[0];
19
+ const id = held !== null && held !== void 0 ? held : model.byGlobalId(keyGlobalId(model.keySeed, idOrGlobalId));
20
+ if (id === undefined) {
21
+ throw new Error(`The model has no ${what} '${idOrGlobalId}'`);
22
+ }
23
+ const actual = model.typeOf(id);
24
+ if (!model.schema.isSubtypeOf(actual, type)) {
25
+ throw new Error(`'${idOrGlobalId}' is ${article(actual)} ${actual}, not ${article(what)} ${what}`);
26
+ }
27
+ return id;
28
+ }
29
+ export function describeObject(reader, id) {
30
+ var _a, _b, _c, _d;
31
+ const entity = reader.entity(id);
32
+ const name = (_b = textValue((_a = entity.args[2]) !== null && _a !== void 0 ? _a : null)) !== null && _b !== void 0 ? _b : "";
33
+ const globalId = (_d = textValue((_c = entity.args[0]) !== null && _c !== void 0 ? _c : null)) !== null && _d !== void 0 ? _d : "";
34
+ return name ? `the ${entity.type} '${name}'` : globalId ? `the ${entity.type} ${globalId}` : `#${id}`;
35
+ }
36
+ export function onlyBuilding(model) {
37
+ const buildings = model.byType("IfcBuilding");
38
+ if (buildings.length !== 1) {
39
+ throw new Error(`Storeys are added to the model's one building, and it has ${buildings.length}`);
40
+ }
41
+ return buildings[0].id;
42
+ }
43
+ export function containIn(tx, writer, structure, element) {
44
+ appendToRelationship(tx, writer, CONTAINMENT, structure, [element]);
45
+ }
46
+ export function containerOf(reader, element) {
47
+ return relatingOf(reader, CONTAINMENT, element);
48
+ }
49
+ export function standingIn(reader, element) {
50
+ let current = element;
51
+ for (let step = 0; current !== undefined && step < MAX_STRUCTURE_DEPTH; step++) {
52
+ const container = containerOf(reader, current);
53
+ if (container !== undefined) {
54
+ return container;
55
+ }
56
+ const whole = relatingOf(reader, AGGREGATION, current);
57
+ current = whole !== undefined && !reader.schema.isSubtypeOf(reader.entity(whole).type, SPATIAL_ELEMENT) ? whole : undefined;
58
+ }
59
+ return undefined;
60
+ }
61
+ export function storeysOf(model) {
62
+ return model.byType("IfcBuildingStorey")
63
+ .map((storey) => {
64
+ var _a, _b;
65
+ const elevation = model.attribute(storey.id, "Elevation");
66
+ return {
67
+ globalId: (_a = textValue(model.attribute(storey.id, "GlobalId"))) !== null && _a !== void 0 ? _a : "",
68
+ name: (_b = textValue(model.attribute(storey.id, "Name"))) !== null && _b !== void 0 ? _b : "",
69
+ elevation: typeof elevation === "number" ? elevation : 0,
70
+ };
71
+ })
72
+ .sort((a, b) => a.elevation - b.elevation);
73
+ }
74
+ export function addStorey(tx, writer, building, id, name, elevation) {
75
+ const storey = writer.create("IfcBuildingStorey", {
76
+ GlobalId: tx.globalId(id),
77
+ Name: name,
78
+ ObjectPlacement: ref(writer.localPlacement(objectPlacementOf(tx, building), Object.assign(Object.assign({}, WORLD_AXES), { origin: [0, 0, elevation] }))),
79
+ CompositionType: enumValue("ELEMENT"),
80
+ Elevation: elevation,
81
+ });
82
+ appendToRelationship(tx, writer, AGGREGATION, building, [storey]);
83
+ return storey;
84
+ }
85
+ export function storeyFrame(reader, storey) {
86
+ return absoluteFrame(reader, objectPlacementOf(reader, storey));
87
+ }
88
+ export function storeyOf(reader, element) {
89
+ var _a;
90
+ let current = element;
91
+ for (let step = 0; current !== undefined && step < MAX_STRUCTURE_DEPTH; step++) {
92
+ const holder = (_a = containerOf(reader, current)) !== null && _a !== void 0 ? _a : relatingOf(reader, AGGREGATION, current);
93
+ if (holder !== undefined && reader.schema.isSubtypeOf(reader.entity(holder).type, STOREY)) {
94
+ return holder;
95
+ }
96
+ current = holder;
97
+ }
98
+ return undefined;
99
+ }
100
+ export function setStoreyElevation(tx, writer, storey, elevation) {
101
+ const placement = objectPlacementOf(tx, storey);
102
+ const sharer = productsPlacedBy(tx, placement).find((product) => product !== storey);
103
+ if (sharer !== undefined) {
104
+ throw new Error(`${describeObject(tx, storey)} shares its placement with ${describeObject(tx, sharer)}, so it cannot move on its own`);
105
+ }
106
+ const frame = relativeFrame(tx, placement);
107
+ const recorded = tx.attribute(storey, "Elevation");
108
+ const rise = elevation - (typeof recorded === "number" ? recorded : frame.origin[2]);
109
+ movePlacement(tx, writer, placement, Object.assign(Object.assign({}, frame), { origin: [frame.origin[0], frame.origin[1], frame.origin[2] + rise] }));
110
+ tx.update(storey, { Elevation: elevation });
111
+ }
@@ -0,0 +1,4 @@
1
+ import type { IfcTransaction } from "../model/transaction";
2
+ import type { EntityWriter } from "./entity-writer";
3
+ export declare function defineByType(tx: IfcTransaction, writer: EntityWriter, occurrence: number, type: number): void;
4
+ export declare function declareInProject(tx: IfcTransaction, writer: EntityWriter, definition: number): void;
@@ -0,0 +1,9 @@
1
+ import { DECLARATION, TYPE_DEFINITION } from "./constants";
2
+ import { projectOf } from "./project";
3
+ import { appendToRelationship } from "./relationships";
4
+ export function defineByType(tx, writer, occurrence, type) {
5
+ appendToRelationship(tx, writer, TYPE_DEFINITION, type, [occurrence]);
6
+ }
7
+ export function declareInProject(tx, writer, definition) {
8
+ appendToRelationship(tx, writer, DECLARATION, projectOf(tx.base), [definition]);
9
+ }
@@ -0,0 +1,5 @@
1
+ import type { IfcTransaction } from "../model/transaction";
2
+ import type { WallChange } from "./build-types";
3
+ import type { EntityWriter } from "./entity-writer";
4
+ export declare function editWall(tx: IfcTransaction, writer: EntityWriter, wall: number, change: WallChange, tolerance: number, parallelTolerance: number): void;
5
+ export declare function disconnectWalls(tx: IfcTransaction, writer: EntityWriter, first: number, second: number, tolerance: number, parallelTolerance: number): void;
@@ -0,0 +1,138 @@
1
+ import { WORLD_AXES, composeAxes, pointToWorld, relativeAxes } from "@bitbybit-dev/base/lib/api/services/helpers/frame-axes";
2
+ import { length2, length3, subtract2, subtract3 } from "@bitbybit-dev/base/lib/api/services/helpers/vectors";
3
+ import { isReference, ref } from "../step/values";
4
+ import { MATERIAL_ASSOCIATION, TYPE_DEFINITION } from "./constants";
5
+ import { axisContext } from "./contexts";
6
+ import { requiredReference } from "./checks";
7
+ import { associateNewMaterial, layerSetThickness, layerSetUsage, materialOf } from "./materials";
8
+ import { normalize2 } from "./math";
9
+ import { carriedWith, carryOpening, openingsOf, readWallOpening } from "./openings";
10
+ import { absoluteFrame, axisPlacementFrame, movePlacement, objectPlacementOf } from "./placement";
11
+ import { detach, relatingOf } from "./relationships";
12
+ import { describeObject } from "./spatial";
13
+ import { alignmentOf, axisFrame, layerSetOf, readWall } from "./wall-geometry";
14
+ import { joinsOf, offsetFor, regenerateWall, stillMeet } from "./walls";
15
+ import { firstItem, replaceRepresentation, representationOf, unwrapClippings } from "./representations";
16
+ function movesAny(from, to, points, tolerance) {
17
+ return points.some((point) => length3(subtract3(pointToWorld(to, point), pointToWorld(from, point))) > tolerance);
18
+ }
19
+ function wallFrame(start, end, bottom) {
20
+ const direction = normalize2(subtract2(end, start));
21
+ return {
22
+ origin: [start[0], start[1], bottom],
23
+ x: [direction[0], direction[1], 0],
24
+ y: [-direction[1], direction[0], 0],
25
+ z: [0, 0, 1],
26
+ };
27
+ }
28
+ function rebasedHalfSpace(tx, writer, halfSpace, from, to) {
29
+ const type = tx.entity(halfSpace).type;
30
+ const surface = tx.attribute(halfSpace, "BaseSurface");
31
+ if ((type !== "IfcHalfSpaceSolid" && type !== "IfcPolygonalBoundedHalfSpace") || !isReference(surface) || tx.entity(surface.ref).type !== "IfcPlane") {
32
+ throw new Error(`The wall is clipped by an ${type} this library does not move with a wall`);
33
+ }
34
+ const moved = (owner) => writer.placement3(relativeAxes(to, composeAxes(from, axisPlacementFrame(tx, requiredReference(tx, owner, "Position")))));
35
+ const plane = writer.create("IfcPlane", { Position: ref(moved(surface.ref)) });
36
+ const agreement = tx.attribute(halfSpace, "AgreementFlag");
37
+ if (type === "IfcHalfSpaceSolid") {
38
+ return writer.create(type, { BaseSurface: ref(plane), AgreementFlag: agreement });
39
+ }
40
+ return writer.create(type, { BaseSurface: ref(plane), AgreementFlag: agreement, Position: ref(moved(halfSpace)), PolygonalBoundary: tx.attribute(halfSpace, "PolygonalBoundary") });
41
+ }
42
+ function refuseTypedLayers(tx, wall) {
43
+ const type = relatingOf(tx, TYPE_DEFINITION, wall);
44
+ if (type !== undefined && materialOf(tx, type) !== undefined) {
45
+ throw new Error(`${describeObject(tx, wall)} takes its layers from ${describeObject(tx, type)}, so its layer set cannot change on its own`);
46
+ }
47
+ }
48
+ function placeOpenings(tx, before, after, moves, tolerance) {
49
+ const placement = objectPlacementOf(tx, before.wall);
50
+ const facesMove = Math.abs(after.low - before.low) > tolerance || Math.abs(after.high - before.high) > tolerance;
51
+ const places = [];
52
+ for (const opening of openingsOf(tx, before.wall)) {
53
+ const place = readWallOpening(tx, before, placement, opening, tolerance);
54
+ if ((facesMove && place === undefined) || ((facesMove || moves) && !carriedWith(tx, opening, placement))) {
55
+ throw new Error(`${describeObject(tx, opening)} is not an opening this library can carry with the wall, so the wall cannot change this way`);
56
+ }
57
+ if (place !== undefined && (place.offset < -tolerance || place.offset + place.width > after.length + tolerance)) {
58
+ throw new Error(`${describeObject(tx, opening)}, from ${place.offset} to ${place.offset + place.width} along the wall, would not fit on a wall ${after.length} long; move it first with openings.edit`);
59
+ }
60
+ if (place !== undefined && facesMove) {
61
+ places.push(place);
62
+ }
63
+ }
64
+ return places;
65
+ }
66
+ export function editWall(tx, writer, wall, change, tolerance, parallelTolerance) {
67
+ var _a, _b, _c, _d, _e, _f;
68
+ const before = readWall(tx, wall);
69
+ if (before.body === undefined) {
70
+ throw new Error(`${describeObject(tx, wall)} has no Body representation, so this library cannot rebuild it`);
71
+ }
72
+ const start = (_a = change.start) !== null && _a !== void 0 ? _a : before.start;
73
+ const end = (_b = change.end) !== null && _b !== void 0 ? _b : before.end;
74
+ const height = (_c = change.height) !== null && _c !== void 0 ? _c : before.height;
75
+ const length = length2(subtract2(end, start));
76
+ if (!(length > tolerance)) {
77
+ throw new Error("A wall's start and end must be apart");
78
+ }
79
+ if (!(height > 0)) {
80
+ throw new Error(`A wall's height must be more than zero, got ${height}`);
81
+ }
82
+ const layerSet = (_d = change.layerSet) !== null && _d !== void 0 ? _d : layerSetOf(tx, before);
83
+ const layersChange = layerSet !== layerSetOf(tx, before);
84
+ if (layersChange) {
85
+ refuseTypedLayers(tx, wall);
86
+ }
87
+ const thickness = layerSetThickness(tx, layerSet);
88
+ if (!(thickness > 0)) {
89
+ throw new Error("A wall's layers must add up to more than zero thickness");
90
+ }
91
+ const alignment = (_e = change.alignment) !== null && _e !== void 0 ? _e : alignmentOf(before, tolerance);
92
+ const low = alignment === undefined ? before.low : offsetFor(alignment, thickness);
93
+ const axis = axisFrame(before);
94
+ const target = wallFrame(start, end, (_f = change.bottom) !== null && _f !== void 0 ? _f : pointToWorld(before.frame, axis.origin)[2]);
95
+ const frame = composeAxes(target, relativeAxes(axis, WORLD_AXES));
96
+ const after = Object.assign(Object.assign({}, before), { frame, start, end, direction: [target.x[0], target.x[1]], length, low, high: low + thickness, height });
97
+ for (const join of joinsOf(tx, wall)) {
98
+ if (!stillMeet(after, join.mine, readWall(tx, join.other), join.theirs, tolerance, parallelTolerance)) {
99
+ throw new Error(`The change takes ${describeObject(tx, wall)} away from ${describeObject(tx, join.other)}, which it is joined to; disconnect them first with walls.disconnect`);
100
+ }
101
+ }
102
+ const reach = Math.max(before.length, length);
103
+ const top = Math.max(before.height, height);
104
+ const corners = [0, reach].flatMap((along) => [before.low, before.high].flatMap((across) => [0, top].map((up) => [along, across, up])));
105
+ const moves = movesAny(composeAxes(before.frame, axis), target, corners, tolerance);
106
+ const places = placeOpenings(tx, before, after, moves, tolerance);
107
+ const halfSpaces = unwrapClippings(tx, firstItem(tx, before.body))[1].map((halfSpace) => (moves ? rebasedHalfSpace(tx, writer, halfSpace, before.frame, frame) : halfSpace));
108
+ const placement = objectPlacementOf(tx, wall);
109
+ const parent = tx.attribute(placement, "PlacementRelTo");
110
+ movePlacement(tx, writer, placement, relativeAxes(isReference(parent) ? absoluteFrame(tx, parent.ref) : WORLD_AXES, frame));
111
+ const axisEnd = pointToWorld(axis, [length, 0, 0]);
112
+ const axisCurve = writer.polyCurve2([[axis.origin[0], axis.origin[1]], [axisEnd[0], axisEnd[1]]], false);
113
+ replaceRepresentation(tx, wall, representationOf(tx, wall, "Axis"), writer.shapeRepresentation(axisContext(tx, writer), "Axis", "Curve2D", [axisCurve]));
114
+ if (layersChange || Math.abs(low - before.low) > tolerance) {
115
+ tx.dropIfUnused(detach(tx, MATERIAL_ASSOCIATION, wall));
116
+ associateNewMaterial(tx, writer, [wall], layerSetUsage(writer, layerSet, "AXIS2", "POSITIVE", low));
117
+ }
118
+ places.forEach((place) => carryOpening(tx, writer, place, place, before, after));
119
+ regenerateWall(tx, writer, wall, tolerance, parallelTolerance, { height, base: before.base, halfSpaces });
120
+ for (const join of joinsOf(tx, wall)) {
121
+ if (join.theirs !== "ATPATH") {
122
+ regenerateWall(tx, writer, join.other, tolerance, parallelTolerance);
123
+ }
124
+ }
125
+ }
126
+ export function disconnectWalls(tx, writer, first, second, tolerance, parallelTolerance) {
127
+ const joins = joinsOf(tx, first).filter((join) => join.other === second);
128
+ if (!joins.length) {
129
+ throw new Error(`${describeObject(tx, first)} and ${describeObject(tx, second)} are not joined`);
130
+ }
131
+ joins.forEach((join) => tx.delete(join.relationship));
132
+ if (joins.some((join) => join.mine !== "ATPATH")) {
133
+ regenerateWall(tx, writer, first, tolerance, parallelTolerance);
134
+ }
135
+ if (joins.some((join) => join.theirs !== "ATPATH")) {
136
+ regenerateWall(tx, writer, second, tolerance, parallelTolerance);
137
+ }
138
+ }
@@ -0,0 +1,15 @@
1
+ import type { Base } from "@bitbybit-dev/base";
2
+ import * as Inputs from "../api/inputs";
3
+ import type { ModelReader, WallCuts, WallEnd, WallGeometry } from "./build-types";
4
+ import type { Frame3, Line2 } from "./build-types";
5
+ export declare function readWall(reader: ModelReader, wall: number): WallGeometry;
6
+ export declare function axisFrame(geometry: WallGeometry): Frame3;
7
+ export declare function alignmentOf(geometry: WallGeometry, tolerance: number): Inputs.IFC.wallAlignmentEnum | undefined;
8
+ export declare function layerSetOf(reader: ModelReader, geometry: WallGeometry): number;
9
+ export declare function sideLine(geometry: WallGeometry, across: number): Line2;
10
+ export declare function axisLine(geometry: WallGeometry): Line2;
11
+ export declare function endPoint(geometry: WallGeometry, end: WallEnd): Base.Point2;
12
+ export declare function mitreCut(wall: WallGeometry, wallEnd: WallEnd, other: WallGeometry, otherEnd: WallEnd, tolerance: number, parallelTolerance: number): Line2 | undefined;
13
+ export declare function buttCut(stem: WallGeometry, stemEnd: WallEnd, through: WallGeometry): Line2;
14
+ export declare function footprintOf(geometry: WallGeometry, cuts: WallCuts, tolerance: number, parallelTolerance: number): Base.Point2[];
15
+ export declare function readableWall(reader: ModelReader, wall: number): WallGeometry | undefined;