@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,136 @@
1
+ import { isZip, zipEntries, zipEntryData } from "@bitbybit-dev/base/lib/api/services/helpers/zip";
2
+ import { describeSupportedSchemas, readingSchemaFor, schemaNamed } from "../schema/registry";
3
+ import { StepSyntaxError } from "../step/errors";
4
+ import { encoderFor } from "../step/encoder";
5
+ import { indexStep } from "../step/file-index";
6
+ import { encodeHeader, headerFromEntities, otherHeaderEntities } from "../step/header";
7
+ import { textOf } from "../step/scanner";
8
+ import { ARCHIVE_RESOURCE_FOLDER, CARRIAGE_RETURN, IFC_EXTENSION, LINE_BREAK, LINE_FEED, LONGEST_STRING, TEXT_PER_CHUNK, WINDOWS_LINE_BREAK } from "./constants";
9
+ import { IdMap } from "./id-map";
10
+ import { ModelSnapshot } from "./snapshot";
11
+ import { IfcSource } from "./source";
12
+ const encoder = new TextEncoder();
13
+ const FILE_SCHEMA = "FILE_SCHEMA";
14
+ function ifcInArchive(archive) {
15
+ const files = zipEntries(archive).filter((entry) => !entry.name.endsWith("/") && !entry.name.startsWith(ARCHIVE_RESOURCE_FOLDER));
16
+ const models = files.filter((entry) => entry.name.toLowerCase().endsWith(IFC_EXTENSION));
17
+ if (models.length !== 1) {
18
+ const held = (models.length ? models : files).map((entry) => entry.name).join(", ");
19
+ throw new StepSyntaxError(models.length ? `The .ifczip archive holds ${models.length} .ifc files (${held}), not one` : `The .ifczip archive holds no .ifc file${held ? `, only ${held}` : ""}`, 0);
20
+ }
21
+ return zipEntryData(archive, models[0]);
22
+ }
23
+ function bytesOf(input) {
24
+ if (typeof input === "string") {
25
+ return encoder.encode(input);
26
+ }
27
+ const bytes = input instanceof Uint8Array ? input : new Uint8Array(input);
28
+ return isZip(bytes) ? ifcInArchive(bytes) : bytes;
29
+ }
30
+ export function readModel(input) {
31
+ var _a, _b;
32
+ const index = indexStep(bytesOf(input));
33
+ const header = headerFromEntities(index.header);
34
+ const schemaName = header.schemaIdentifiers[0];
35
+ const named = (_b = (_a = index.header.find((entity) => entity.type === FILE_SCHEMA)) === null || _a === void 0 ? void 0 : _a.offset) !== null && _b !== void 0 ? _b : index.headerEnd;
36
+ if (schemaName === undefined) {
37
+ throw new StepSyntaxError("The file names no schema in FILE_SCHEMA", named);
38
+ }
39
+ const schema = readingSchemaFor(schemaName);
40
+ if (schema === undefined) {
41
+ throw new StepSyntaxError(`The file's schema ${schemaName} is not supported; supported: ${describeSupportedSchemas()}`, named);
42
+ }
43
+ const source = new IfcSource(index, schema);
44
+ return new ModelSnapshot({ schema, header, headerExtras: otherHeaderEntities(index.header), source, overlay: IdMap.empty(), nextId: source.maxId + 1, seededIds: false });
45
+ }
46
+ export function emptyModel(schemaName, header) {
47
+ return new ModelSnapshot({ schema: schemaNamed(schemaName), header, headerExtras: [], source: undefined, overlay: IdMap.empty(), nextId: 1, seededIds: true });
48
+ }
49
+ function lineBreakOf(bytes) {
50
+ const feed = bytes.indexOf(LINE_FEED);
51
+ return feed > 0 && bytes[feed - 1] === CARRIAGE_RETURN ? WINDOWS_LINE_BREAK : LINE_BREAK;
52
+ }
53
+ function rowsOf(model) {
54
+ const rows = [];
55
+ const encode = encoderFor(model.schema);
56
+ const source = model.source;
57
+ if (source) {
58
+ const { bytes, ids, rowStart, rowEnd, count, sectionStarts } = source.index;
59
+ const breaks = new Set(sectionStarts);
60
+ let runStart = -1;
61
+ const flush = (endRow) => {
62
+ if (runStart >= 0) {
63
+ rows.push(bytes.subarray(rowStart[runStart], rowEnd[endRow - 1]));
64
+ runStart = -1;
65
+ }
66
+ };
67
+ for (let row = 0; row < count; row++) {
68
+ const changed = model.overlay.get(ids[row]);
69
+ if (breaks.has(row)) {
70
+ flush(row);
71
+ }
72
+ if (changed === undefined) {
73
+ runStart = runStart < 0 ? row : runStart;
74
+ continue;
75
+ }
76
+ flush(row);
77
+ if (changed !== null) {
78
+ rows.push(encode.encodeEntity(changed));
79
+ }
80
+ }
81
+ flush(count);
82
+ }
83
+ model.overlay.forEach((entity, id) => {
84
+ if (entity && !(source === null || source === void 0 ? void 0 : source.has(id))) {
85
+ rows.push(encode.encodeEntity(entity));
86
+ }
87
+ });
88
+ return rows;
89
+ }
90
+ function partsOf(model, header) {
91
+ const source = model.source;
92
+ const index = source && source.index.count > 0 ? source.index : undefined;
93
+ const lineBreak = source ? lineBreakOf(source.index.bytes) : LINE_BREAK;
94
+ const rows = rowsOf(model);
95
+ const sameHeader = source !== undefined && JSON.stringify(header) === JSON.stringify(headerFromEntities(source.index.header));
96
+ const encodedHeader = () => encodeHeader(header, model.headerExtras).split(LINE_BREAK).join(lineBreak);
97
+ const head = !index
98
+ ? [`${encodedHeader()}${lineBreak}DATA;${lineBreak}`]
99
+ : sameHeader
100
+ ? [index.bytes.subarray(0, index.rowStart[0])]
101
+ : [encodedHeader(), index.bytes.subarray(index.afterHeader, index.rowStart[0])];
102
+ const tail = index ? index.bytes.subarray(index.rowEnd[index.count - 1]) : `${rows.length ? lineBreak : ""}ENDSEC;${lineBreak}END-ISO-10303-21;${lineBreak}`;
103
+ return [...head, ...rows.flatMap((row, at) => (at === 0 ? [row] : [lineBreak, row])), tail];
104
+ }
105
+ export function writeModel(model, header = model.header, longest = LONGEST_STRING) {
106
+ const parts = partsOf(model, header);
107
+ const length = parts.reduce((sum, part) => sum + part.length, 0);
108
+ if (length > longest) {
109
+ throw new Error(`The file is about ${length} bytes, more than one JavaScript string holds; write it with model.writeBytes`);
110
+ }
111
+ return parts.map((part) => (typeof part === "string" ? part : textOf(part, 0, part.length))).join("");
112
+ }
113
+ export function writeModelBytes(model, header = model.header, textPerChunk = TEXT_PER_CHUNK) {
114
+ const chunks = [];
115
+ let text = "";
116
+ for (const part of partsOf(model, header)) {
117
+ if (typeof part === "string") {
118
+ text += part;
119
+ }
120
+ if (typeof part !== "string" || text.length > textPerChunk) {
121
+ chunks.push(encoder.encode(text));
122
+ text = "";
123
+ }
124
+ if (typeof part !== "string") {
125
+ chunks.push(part);
126
+ }
127
+ }
128
+ chunks.push(encoder.encode(text));
129
+ const bytes = new Uint8Array(chunks.reduce((sum, chunk) => sum + chunk.length, 0));
130
+ let at = 0;
131
+ for (const chunk of chunks) {
132
+ bytes.set(chunk, at);
133
+ at += chunk.length;
134
+ }
135
+ return bytes;
136
+ }
@@ -0,0 +1,9 @@
1
+ import type { IfcModel } from "./model-types";
2
+ /**
3
+ * Whether a value is a model this library made, as `model.create`, `model.read` and every method
4
+ * that changes a model return one.
5
+ * @param value - The value to test
6
+ * @returns True for a model
7
+ * @beta
8
+ */
9
+ export declare function isIfcModel(value: unknown): value is IfcModel;
@@ -0,0 +1,11 @@
1
+ import { ModelSnapshot } from "./snapshot";
2
+ /**
3
+ * Whether a value is a model this library made, as `model.create`, `model.read` and every method
4
+ * that changes a model return one.
5
+ * @param value - The value to test
6
+ * @returns True for a model
7
+ * @beta
8
+ */
9
+ export function isIfcModel(value) {
10
+ return value instanceof ModelSnapshot;
11
+ }
@@ -0,0 +1,111 @@
1
+ import type { IfcSchema } from "../schema/schema";
2
+ import type { IfcEntity, IfcFileHeader, IfcValue } from "../step/step-types";
3
+ import type { IdMap } from "./id-map";
4
+ import type { IfcSource } from "./source";
5
+ /**
6
+ * An IFC model at one moment: a schema, a file header and its entities. A model never changes:
7
+ * every method that edits one returns a new model, which shares with the old one everything the
8
+ * edit did not touch, so the old model can still be read, written or edited another way.
9
+ * @beta
10
+ */
11
+ export interface IfcModel {
12
+ /**
13
+ * The schema the model's file names, such as `IFC4`.
14
+ */
15
+ readonly schemaName: string;
16
+ /**
17
+ * Whether the model can be changed: false for a file whose schema is read through another's,
18
+ * such as an `IFC2X3` file read through `IFC4`, which can be shown and queried but not edited.
19
+ */
20
+ readonly editable: boolean;
21
+ /**
22
+ * The file header the model was read or created with.
23
+ */
24
+ readonly header: IfcFileHeader;
25
+ /**
26
+ * How many entities the model holds.
27
+ */
28
+ readonly size: number;
29
+ /**
30
+ * Whether the model holds an entity with this express id.
31
+ * @param id - The express id
32
+ * @returns True when the entity is there
33
+ */
34
+ has(id: number): boolean;
35
+ /**
36
+ * The entity with this express id.
37
+ * @param id - The express id
38
+ * @returns The entity, or undefined when the model holds none with this id
39
+ */
40
+ get(id: number): IfcEntity | undefined;
41
+ /**
42
+ * The entity with this express id, which must be there.
43
+ * @param id - The express id
44
+ * @returns The entity
45
+ */
46
+ entity(id: number): IfcEntity;
47
+ /**
48
+ * The type of the entity with this express id, in the schema's spelling.
49
+ * @param id - The express id
50
+ * @returns The type, or undefined when there is no such entity or its type is one the schema
51
+ * does not define
52
+ */
53
+ typeOf(id: number): string | undefined;
54
+ /**
55
+ * One attribute of an entity, by the attribute's name in the schema.
56
+ * @param id - The express id of the entity
57
+ * @param name - The attribute name, such as `Name`
58
+ * @returns The value, or null when the attribute is unset
59
+ */
60
+ attribute(id: number, name: string): IfcValue;
61
+ /**
62
+ * The express ids of every entity: those of the file the model was read from in file order,
63
+ * then those created since, in ascending order.
64
+ * @returns The ids
65
+ */
66
+ ids(): readonly number[];
67
+ /**
68
+ * Every entity of a type, in ascending order of express id.
69
+ * @param type - The entity type, such as `IfcWall`, in any case
70
+ * @param includeSubtypes - Whether entities of its subtypes count too; true when left out
71
+ * @returns The entities
72
+ */
73
+ byType(type: string, includeSubtypes?: boolean): IfcEntity[];
74
+ /**
75
+ * The object with this GlobalId.
76
+ * @param globalId - The GlobalId
77
+ * @returns The express id of the object, or undefined when the model holds none with it
78
+ */
79
+ byGlobalId(globalId: string): number | undefined;
80
+ /**
81
+ * The entities that refer to an entity.
82
+ * @param id - The express id of the entity referred to
83
+ * @returns The express ids of the entities that refer to it, in ascending order
84
+ */
85
+ referencesTo(id: number): readonly number[];
86
+ }
87
+ export type IfcOverlay = IdMap<IfcEntity | null>;
88
+ export type IfcAttributes = Readonly<Record<string, IfcValue | undefined>>;
89
+ export interface SnapshotParts {
90
+ readonly schema: IfcSchema;
91
+ readonly header: IfcFileHeader;
92
+ readonly headerExtras: readonly string[];
93
+ readonly source: IfcSource | undefined;
94
+ readonly overlay: IfcOverlay;
95
+ readonly nextId: number;
96
+ readonly seededIds: boolean;
97
+ }
98
+ export interface TrieNode<V> {
99
+ owner: object | undefined;
100
+ readonly children: (TrieNode<V> | undefined)[];
101
+ readonly values: (V | undefined)[];
102
+ }
103
+ export type FilePart = string | Uint8Array;
104
+ export interface GlobalIdOwners {
105
+ readonly first: Map<string, number>;
106
+ readonly more: Map<string, number[]>;
107
+ }
108
+ export interface SourceUsers {
109
+ readonly offsets: Int32Array;
110
+ readonly users: Int32Array;
111
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,17 @@
1
+ import type { IfcSchema } from "../schema/schema";
2
+ import type { IfcEntity } from "../step/step-types";
3
+ import type { IfcOverlay } from "./model-types";
4
+ export declare class OverlayIndexes {
5
+ private readonly schema;
6
+ private readonly types;
7
+ private readonly globalIds;
8
+ private readonly users;
9
+ private readonly rooted;
10
+ constructor(schema: IfcSchema, overlay: IfcOverlay);
11
+ globalIdOf(entity: IfcEntity): string | undefined;
12
+ add(entity: IfcEntity): void;
13
+ remove(entity: IfcEntity): void;
14
+ idsOfType(type: string): ReadonlySet<number> | undefined;
15
+ ownersOfGlobalId(globalId: string): ReadonlySet<number> | undefined;
16
+ usersOf(id: number): ReadonlySet<number> | undefined;
17
+ }
@@ -0,0 +1,69 @@
1
+ import { ROOT_ENTITY } from "../schema/constants";
2
+ import { referencesIn } from "../step/values";
3
+ function addTo(map, key, id) {
4
+ const set = map.get(key);
5
+ if (set) {
6
+ set.add(id);
7
+ }
8
+ else {
9
+ map.set(key, new Set([id]));
10
+ }
11
+ }
12
+ function removeFrom(map, key, id) {
13
+ const set = map.get(key);
14
+ if ((set === null || set === void 0 ? void 0 : set.delete(id)) && set.size === 0) {
15
+ map.delete(key);
16
+ }
17
+ }
18
+ export class OverlayIndexes {
19
+ constructor(schema, overlay) {
20
+ this.types = new Map();
21
+ this.globalIds = new Map();
22
+ this.users = new Map();
23
+ this.rooted = new Map();
24
+ this.schema = schema;
25
+ overlay.forEach((entity) => {
26
+ if (entity) {
27
+ this.add(entity);
28
+ }
29
+ });
30
+ }
31
+ globalIdOf(entity) {
32
+ let isRoot = this.rooted.get(entity.type);
33
+ if (isRoot === undefined) {
34
+ isRoot = this.schema.isSubtypeOf(entity.type, ROOT_ENTITY);
35
+ this.rooted.set(entity.type, isRoot);
36
+ }
37
+ const globalId = entity.args[0];
38
+ return isRoot && typeof globalId === "string" ? globalId : undefined;
39
+ }
40
+ add(entity) {
41
+ addTo(this.types, entity.type, entity.id);
42
+ const globalId = this.globalIdOf(entity);
43
+ if (globalId !== undefined) {
44
+ addTo(this.globalIds, globalId, entity.id);
45
+ }
46
+ for (const target of new Set(entity.args.flatMap((arg) => referencesIn(arg)))) {
47
+ addTo(this.users, target, entity.id);
48
+ }
49
+ }
50
+ remove(entity) {
51
+ removeFrom(this.types, entity.type, entity.id);
52
+ const globalId = this.globalIdOf(entity);
53
+ if (globalId !== undefined) {
54
+ removeFrom(this.globalIds, globalId, entity.id);
55
+ }
56
+ for (const target of new Set(entity.args.flatMap((arg) => referencesIn(arg)))) {
57
+ removeFrom(this.users, target, entity.id);
58
+ }
59
+ }
60
+ idsOfType(type) {
61
+ return this.types.get(type);
62
+ }
63
+ ownersOfGlobalId(globalId) {
64
+ return this.globalIds.get(globalId);
65
+ }
66
+ usersOf(id) {
67
+ return this.users.get(id);
68
+ }
69
+ }
@@ -0,0 +1,2 @@
1
+ import type { ModelSnapshot } from "./snapshot";
2
+ export declare function checkReferences(model: ModelSnapshot, changed: readonly number[], deleted: readonly number[]): void;
@@ -0,0 +1,51 @@
1
+ import { isList, isReference, isTyped } from "../step/values";
2
+ function checkReference(model, spec, id, path) {
3
+ var _a, _b;
4
+ const target = model.typeOf(id);
5
+ if (target === undefined) {
6
+ const what = model.has(id) ? `a ${(_b = (_a = model.source) === null || _a === void 0 ? void 0 : _a.rawTypeOf(id)) !== null && _b !== void 0 ? _b : "type"}, which ${model.schema.name} does not define` : "which the model does not hold";
7
+ throw new Error(`${path} refers to #${id}, ${what}`);
8
+ }
9
+ const accepted = model.schema.hasEntity(spec) ? [spec] : model.schema.selectContents(spec).entities;
10
+ if (!accepted.some((name) => model.schema.isSubtypeOf(target, name))) {
11
+ throw new Error(`${path} refers to #${id}, an ${target}, where ${spec} is expected`);
12
+ }
13
+ }
14
+ function checkValue(model, spec, value, path) {
15
+ if (typeof spec !== "string") {
16
+ if (isList(value)) {
17
+ value.forEach((item, index) => checkValue(model, spec[3], item, `${path}[${index}]`));
18
+ }
19
+ return;
20
+ }
21
+ if (isReference(value)) {
22
+ checkReference(model, spec, value.ref, path);
23
+ return;
24
+ }
25
+ const type = model.schema.type(spec);
26
+ if (!type) {
27
+ return;
28
+ }
29
+ if ("t" in type) {
30
+ checkValue(model, type.t, value, path);
31
+ }
32
+ else if ("s" in type && isTyped(value)) {
33
+ checkValue(model, value.type, value.value, path);
34
+ }
35
+ }
36
+ export function checkReferences(model, changed, deleted) {
37
+ for (const id of changed) {
38
+ const entity = model.entity(id);
39
+ const info = model.schema.entity(entity.type);
40
+ info.attributes.forEach((attribute, index) => {
41
+ var _a;
42
+ checkValue(model, attribute.type, (_a = entity.args[index]) !== null && _a !== void 0 ? _a : null, `#${id} ${info.name}.${attribute.name}`);
43
+ });
44
+ }
45
+ for (const id of deleted) {
46
+ const users = model.referencesTo(id);
47
+ if (users.length) {
48
+ throw new Error(`#${id} cannot be deleted while ${users.map((user) => `#${user}`).join(", ")} still refer to it`);
49
+ }
50
+ }
51
+ }
@@ -0,0 +1,8 @@
1
+ import type { StepIndex } from "../step/step-types";
2
+ export declare class RowsById {
3
+ readonly maxId: number;
4
+ private readonly dense;
5
+ private readonly sparse;
6
+ constructor(index: StepIndex);
7
+ rowOf(id: number): number;
8
+ }
@@ -0,0 +1,39 @@
1
+ import { StepSyntaxError } from "../step/errors";
2
+ const ABSENT = -1;
3
+ const DENSE_IDS_PER_ROW = 4;
4
+ const DENSE_SLACK = 1024;
5
+ export class RowsById {
6
+ constructor(index) {
7
+ let maxId = 0;
8
+ for (let row = 0; row < index.count; row++) {
9
+ maxId = Math.max(maxId, index.ids[row]);
10
+ }
11
+ this.maxId = maxId;
12
+ if (maxId <= DENSE_IDS_PER_ROW * index.count + DENSE_SLACK) {
13
+ const dense = new Int32Array(maxId + 1).fill(ABSENT);
14
+ for (let row = 0; row < index.count; row++) {
15
+ const id = index.ids[row];
16
+ if (dense[id] !== ABSENT) {
17
+ throw new StepSyntaxError(`The file holds entity #${id} twice`, index.rowStart[row]);
18
+ }
19
+ dense[id] = row;
20
+ }
21
+ this.dense = dense;
22
+ }
23
+ else {
24
+ const sparse = new Map();
25
+ for (let row = 0; row < index.count; row++) {
26
+ const id = index.ids[row];
27
+ if (sparse.has(id)) {
28
+ throw new StepSyntaxError(`The file holds entity #${id} twice`, index.rowStart[row]);
29
+ }
30
+ sparse.set(id, row);
31
+ }
32
+ this.sparse = sparse;
33
+ }
34
+ }
35
+ rowOf(id) {
36
+ var _a, _b;
37
+ return (_b = (this.dense ? this.dense[id] : (_a = this.sparse) === null || _a === void 0 ? void 0 : _a.get(id))) !== null && _b !== void 0 ? _b : ABSENT;
38
+ }
39
+ }
@@ -0,0 +1,36 @@
1
+ import type { IfcSchema } from "../schema/schema";
2
+ import type { IfcEntity, IfcFileHeader } from "../step/step-types";
3
+ import { EntityLookup } from "./entity-lookup";
4
+ import type { IfcModel, IfcOverlay, SnapshotParts } from "./model-types";
5
+ import { OverlayIndexes } from "./overlay-indexes";
6
+ import type { IfcSource } from "./source";
7
+ export declare class ModelSnapshot extends EntityLookup implements IfcModel {
8
+ readonly schema: IfcSchema;
9
+ readonly header: IfcFileHeader;
10
+ readonly headerExtras: readonly string[];
11
+ readonly source: IfcSource | undefined;
12
+ readonly overlay: IfcOverlay;
13
+ readonly nextId: number;
14
+ readonly seededIds: boolean;
15
+ private indexes;
16
+ private projectGlobalId;
17
+ constructor(parts: SnapshotParts);
18
+ get parts(): SnapshotParts;
19
+ get schemaName(): string;
20
+ get editable(): boolean;
21
+ get size(): number;
22
+ get keySeed(): string;
23
+ has(id: number): boolean;
24
+ get(id: number): IfcEntity | undefined;
25
+ peek(id: number): IfcEntity;
26
+ referenceList(id: number): readonly number[] | undefined;
27
+ typeOf(id: number): string | undefined;
28
+ ids(): readonly number[];
29
+ byType(type: string, includeSubtypes?: boolean): IfcEntity[];
30
+ globalIdOwners(globalId: string): number[];
31
+ byGlobalId(globalId: string): number | undefined;
32
+ referencesTo(id: number): readonly number[];
33
+ overlayIndexes(): OverlayIndexes;
34
+ releaseIndexes(): OverlayIndexes | undefined;
35
+ adoptIndexes(indexes: OverlayIndexes): void;
36
+ }
@@ -0,0 +1,144 @@
1
+ import { isEditableSchema } from "../schema/registry";
2
+ import { EntityLookup } from "./entity-lookup";
3
+ import { OverlayIndexes } from "./overlay-indexes";
4
+ const NO_IDS = [];
5
+ const ascending = (a, b) => a - b;
6
+ export class ModelSnapshot extends EntityLookup {
7
+ constructor(parts) {
8
+ super();
9
+ this.schema = parts.schema;
10
+ this.header = parts.header;
11
+ this.headerExtras = parts.headerExtras;
12
+ this.source = parts.source;
13
+ this.overlay = parts.overlay;
14
+ this.nextId = parts.nextId;
15
+ this.seededIds = parts.seededIds;
16
+ }
17
+ get parts() {
18
+ return { schema: this.schema, header: this.header, headerExtras: this.headerExtras, source: this.source, overlay: this.overlay, nextId: this.nextId, seededIds: this.seededIds };
19
+ }
20
+ get schemaName() {
21
+ var _a;
22
+ return ((_a = this.header.schemaIdentifiers[0]) === null || _a === void 0 ? void 0 : _a.trim().toUpperCase()) || this.schema.name;
23
+ }
24
+ get editable() {
25
+ return this.schemaName === this.schema.name && isEditableSchema(this.schema.name);
26
+ }
27
+ get size() {
28
+ return this.ids().length;
29
+ }
30
+ get keySeed() {
31
+ var _a;
32
+ if (this.projectGlobalId === undefined) {
33
+ const globalId = (_a = this.byType("IfcProject")[0]) === null || _a === void 0 ? void 0 : _a.args[0];
34
+ this.projectGlobalId = typeof globalId === "string" ? globalId : "";
35
+ }
36
+ return this.projectGlobalId;
37
+ }
38
+ has(id) {
39
+ var _a, _b;
40
+ const changed = this.overlay.get(id);
41
+ if (changed !== undefined) {
42
+ return changed !== null;
43
+ }
44
+ return (_b = (_a = this.source) === null || _a === void 0 ? void 0 : _a.has(id)) !== null && _b !== void 0 ? _b : false;
45
+ }
46
+ get(id) {
47
+ var _a;
48
+ const changed = this.overlay.get(id);
49
+ if (changed !== undefined) {
50
+ return changed !== null && changed !== void 0 ? changed : undefined;
51
+ }
52
+ return (_a = this.source) === null || _a === void 0 ? void 0 : _a.get(id);
53
+ }
54
+ peek(id) {
55
+ var _a;
56
+ const changed = this.overlay.get(id);
57
+ const entity = changed === undefined ? (_a = this.source) === null || _a === void 0 ? void 0 : _a.peek(id) : changed;
58
+ if (!entity) {
59
+ throw new Error(`The model has no entity #${id}`);
60
+ }
61
+ return entity;
62
+ }
63
+ referenceList(id) {
64
+ var _a;
65
+ return this.overlay.get(id) === undefined ? (_a = this.source) === null || _a === void 0 ? void 0 : _a.referenceList(id) : undefined;
66
+ }
67
+ typeOf(id) {
68
+ var _a;
69
+ const changed = this.overlay.get(id);
70
+ if (changed !== undefined) {
71
+ return changed === null || changed === void 0 ? void 0 : changed.type;
72
+ }
73
+ return (_a = this.source) === null || _a === void 0 ? void 0 : _a.typeOf(id);
74
+ }
75
+ ids() {
76
+ const ids = [];
77
+ const source = this.source;
78
+ if (source) {
79
+ for (const id of source.index.ids) {
80
+ if (this.overlay.get(id) !== null) {
81
+ ids.push(id);
82
+ }
83
+ }
84
+ }
85
+ this.overlay.forEach((entity, id) => {
86
+ if (entity && !(source === null || source === void 0 ? void 0 : source.has(id))) {
87
+ ids.push(id);
88
+ }
89
+ });
90
+ return ids;
91
+ }
92
+ byType(type, includeSubtypes = true) {
93
+ var _a, _b, _c;
94
+ const names = includeSubtypes ? this.schema.subtypesOf(type) : [this.schema.entityName(type)].filter((name) => name !== undefined);
95
+ const indexes = this.overlayIndexes();
96
+ const ids = [];
97
+ for (const name of names) {
98
+ for (const id of (_b = (_a = this.source) === null || _a === void 0 ? void 0 : _a.idsOfType(name)) !== null && _b !== void 0 ? _b : NO_IDS) {
99
+ if (!this.overlay.has(id)) {
100
+ ids.push(id);
101
+ }
102
+ }
103
+ (_c = indexes.idsOfType(name)) === null || _c === void 0 ? void 0 : _c.forEach((id) => ids.push(id));
104
+ }
105
+ return ids.sort(ascending).map((id) => this.entity(id));
106
+ }
107
+ globalIdOwners(globalId) {
108
+ var _a, _b, _c;
109
+ const owners = [...((_a = this.overlayIndexes().ownersOfGlobalId(globalId)) !== null && _a !== void 0 ? _a : NO_IDS)];
110
+ for (const id of (_c = (_b = this.source) === null || _b === void 0 ? void 0 : _b.ownersOfGlobalId(globalId)) !== null && _c !== void 0 ? _c : NO_IDS) {
111
+ if (!this.overlay.has(id)) {
112
+ owners.push(id);
113
+ }
114
+ }
115
+ return owners.sort(ascending);
116
+ }
117
+ byGlobalId(globalId) {
118
+ return this.globalIdOwners(globalId)[0];
119
+ }
120
+ referencesTo(id) {
121
+ var _a, _b, _c;
122
+ const users = [...((_a = this.overlayIndexes().usersOf(id)) !== null && _a !== void 0 ? _a : NO_IDS)];
123
+ for (const user of (_c = (_b = this.source) === null || _b === void 0 ? void 0 : _b.usersOf(id)) !== null && _c !== void 0 ? _c : NO_IDS) {
124
+ if (!this.overlay.has(user)) {
125
+ users.push(user);
126
+ }
127
+ }
128
+ return users.sort(ascending);
129
+ }
130
+ overlayIndexes() {
131
+ if (!this.indexes) {
132
+ this.indexes = new OverlayIndexes(this.schema, this.overlay);
133
+ }
134
+ return this.indexes;
135
+ }
136
+ releaseIndexes() {
137
+ const indexes = this.indexes;
138
+ this.indexes = undefined;
139
+ return indexes;
140
+ }
141
+ adoptIndexes(indexes) {
142
+ this.indexes = indexes;
143
+ }
144
+ }
@@ -0,0 +1,29 @@
1
+ import type { IfcSchema } from "../schema/schema";
2
+ import type { IfcEntity, IfcValue, StepIndex } from "../step/step-types";
3
+ export declare class IfcSource {
4
+ readonly index: StepIndex;
5
+ readonly schema: IfcSchema;
6
+ readonly maxId: number;
7
+ private readonly rows;
8
+ private readonly decoded;
9
+ private readonly typeOfCode;
10
+ private readonly spell;
11
+ private typeIds;
12
+ private globalIdOwners;
13
+ private users;
14
+ constructor(index: StepIndex, schema: IfcSchema);
15
+ has(id: number): boolean;
16
+ typeOf(id: number): string | undefined;
17
+ rawTypeOf(id: number): string | undefined;
18
+ get(id: number): IfcEntity | undefined;
19
+ peek(id: number): IfcEntity | undefined;
20
+ referenceList(id: number): number[] | undefined;
21
+ rawArguments(id: number): IfcValue[] | undefined;
22
+ private decode;
23
+ idsOfType(type: string): readonly number[];
24
+ ownersOfGlobalId(globalId: string): readonly number[];
25
+ usersOf(id: number): readonly number[];
26
+ private indexGlobalIds;
27
+ private typeOfRow;
28
+ private indexUsers;
29
+ }