@ifc-lite/ifcx 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +373 -0
- package/dist/composition.d.ts +28 -0
- package/dist/composition.d.ts.map +1 -0
- package/dist/composition.js +174 -0
- package/dist/composition.js.map +1 -0
- package/dist/entity-extractor.d.ts +26 -0
- package/dist/entity-extractor.d.ts.map +1 -0
- package/dist/entity-extractor.js +104 -0
- package/dist/entity-extractor.js.map +1 -0
- package/dist/geometry-extractor.d.ts +35 -0
- package/dist/geometry-extractor.d.ts.map +1 -0
- package/dist/geometry-extractor.js +301 -0
- package/dist/geometry-extractor.js.map +1 -0
- package/dist/hierarchy-builder.d.ts +16 -0
- package/dist/hierarchy-builder.d.ts.map +1 -0
- package/dist/hierarchy-builder.js +227 -0
- package/dist/hierarchy-builder.js.map +1 -0
- package/dist/index.d.ts +57 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +189 -0
- package/dist/index.js.map +1 -0
- package/dist/property-extractor.d.ts +23 -0
- package/dist/property-extractor.d.ts.map +1 -0
- package/dist/property-extractor.js +190 -0
- package/dist/property-extractor.js.map +1 -0
- package/dist/types.d.ts +89 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +55 -0
- package/dist/types.js.map +1 -0
- package/package.json +48 -0
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
import { ATTR, SPATIAL_TYPES } from './types.js';
|
|
5
|
+
import { IfcTypeEnum, IfcTypeEnumFromString } from '@ifc-lite/data';
|
|
6
|
+
/**
|
|
7
|
+
* Build spatial hierarchy from composed IFCX nodes.
|
|
8
|
+
*
|
|
9
|
+
* IFCX hierarchy comes from children relationships:
|
|
10
|
+
* - Project -> Site -> Building -> Storey -> Elements
|
|
11
|
+
*
|
|
12
|
+
* We identify spatial structure elements by their bsi::ifc::class codes.
|
|
13
|
+
*/
|
|
14
|
+
export function buildHierarchy(composed, pathToId) {
|
|
15
|
+
// Find project root
|
|
16
|
+
const projectNode = findProjectRoot(composed);
|
|
17
|
+
if (!projectNode) {
|
|
18
|
+
return createEmptyHierarchy();
|
|
19
|
+
}
|
|
20
|
+
// Build spatial tree
|
|
21
|
+
const projectSpatial = buildSpatialNode(projectNode, pathToId);
|
|
22
|
+
// Build lookup maps
|
|
23
|
+
const byStorey = new Map();
|
|
24
|
+
const byBuilding = new Map();
|
|
25
|
+
const bySite = new Map();
|
|
26
|
+
const bySpace = new Map();
|
|
27
|
+
const storeyElevations = new Map();
|
|
28
|
+
const storeyHeights = new Map();
|
|
29
|
+
const elementToStorey = new Map();
|
|
30
|
+
// Traverse and populate maps
|
|
31
|
+
populateMaps(projectSpatial, null, null, null, pathToId, byStorey, byBuilding, bySite, bySpace, storeyElevations, elementToStorey);
|
|
32
|
+
// Note: storeyHeights remains empty - uses on-demand property extraction
|
|
33
|
+
return {
|
|
34
|
+
project: projectSpatial,
|
|
35
|
+
byStorey,
|
|
36
|
+
byBuilding,
|
|
37
|
+
bySite,
|
|
38
|
+
bySpace,
|
|
39
|
+
storeyElevations,
|
|
40
|
+
storeyHeights,
|
|
41
|
+
elementToStorey,
|
|
42
|
+
// Helper methods
|
|
43
|
+
getStoreyElements(storeyId) {
|
|
44
|
+
return byStorey.get(storeyId) || [];
|
|
45
|
+
},
|
|
46
|
+
getStoreyByElevation(z) {
|
|
47
|
+
let closestStorey = null;
|
|
48
|
+
let closestDist = Infinity;
|
|
49
|
+
for (const [storeyId, elevation] of storeyElevations) {
|
|
50
|
+
const dist = Math.abs(z - elevation);
|
|
51
|
+
if (dist < closestDist) {
|
|
52
|
+
closestDist = dist;
|
|
53
|
+
closestStorey = storeyId;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return closestStorey;
|
|
57
|
+
},
|
|
58
|
+
getContainingSpace(elementId) {
|
|
59
|
+
// Check if element is directly in a space
|
|
60
|
+
for (const [spaceId, elements] of bySpace) {
|
|
61
|
+
if (elements.includes(elementId)) {
|
|
62
|
+
return spaceId;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return null;
|
|
66
|
+
},
|
|
67
|
+
getPath(elementId) {
|
|
68
|
+
const path = [];
|
|
69
|
+
function findPath(node) {
|
|
70
|
+
if (node.expressId === elementId) {
|
|
71
|
+
path.push(node);
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
if (node.elements.includes(elementId)) {
|
|
75
|
+
path.push(node);
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
for (const child of node.children) {
|
|
79
|
+
if (findPath(child)) {
|
|
80
|
+
path.unshift(node);
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
findPath(projectSpatial);
|
|
87
|
+
return path;
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Find the IfcProject node in composed nodes.
|
|
93
|
+
*/
|
|
94
|
+
function findProjectRoot(composed) {
|
|
95
|
+
for (const node of composed.values()) {
|
|
96
|
+
const ifcClass = node.attributes.get(ATTR.CLASS);
|
|
97
|
+
if (ifcClass?.code === 'IfcProject') {
|
|
98
|
+
return node;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Build a SpatialNode from a ComposedNode.
|
|
105
|
+
*/
|
|
106
|
+
function buildSpatialNode(node, pathToId) {
|
|
107
|
+
const ifcClass = node.attributes.get(ATTR.CLASS);
|
|
108
|
+
const expressId = pathToId.get(node.path) ?? 0;
|
|
109
|
+
const typeEnum = IfcTypeEnumFromString(ifcClass?.code ?? '');
|
|
110
|
+
const spatialNode = {
|
|
111
|
+
expressId,
|
|
112
|
+
type: typeEnum,
|
|
113
|
+
name: extractName(node) ?? node.path.slice(0, 8),
|
|
114
|
+
children: [],
|
|
115
|
+
elements: [],
|
|
116
|
+
};
|
|
117
|
+
// Extract elevation for storeys
|
|
118
|
+
if (ifcClass?.code === 'IfcBuildingStorey') {
|
|
119
|
+
const elevation = node.attributes.get('bsi::ifc::prop::Elevation');
|
|
120
|
+
if (typeof elevation === 'number') {
|
|
121
|
+
spatialNode.elevation = elevation;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// Process children
|
|
125
|
+
for (const [, child] of node.children) {
|
|
126
|
+
const childClass = child.attributes.get(ATTR.CLASS);
|
|
127
|
+
if (childClass && SPATIAL_TYPES.has(childClass.code)) {
|
|
128
|
+
// Spatial child - recurse
|
|
129
|
+
spatialNode.children.push(buildSpatialNode(child, pathToId));
|
|
130
|
+
}
|
|
131
|
+
else if (childClass) {
|
|
132
|
+
// Element - add to elements list
|
|
133
|
+
const childId = pathToId.get(child.path);
|
|
134
|
+
if (childId !== undefined) {
|
|
135
|
+
spatialNode.elements.push(childId);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
// Geometry-only children (Body, Axis, etc.) are skipped
|
|
139
|
+
}
|
|
140
|
+
return spatialNode;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Populate lookup maps by traversing the spatial hierarchy.
|
|
144
|
+
*/
|
|
145
|
+
function populateMaps(node, currentStorey, currentBuilding, currentSite, pathToId, byStorey, byBuilding, bySite, bySpace, storeyElevations, elementToStorey) {
|
|
146
|
+
// Update current context based on node type
|
|
147
|
+
if (node.type === IfcTypeEnum.IfcBuildingStorey) {
|
|
148
|
+
currentStorey = node.expressId;
|
|
149
|
+
if (node.elevation !== undefined) {
|
|
150
|
+
storeyElevations.set(node.expressId, node.elevation);
|
|
151
|
+
}
|
|
152
|
+
byStorey.set(node.expressId, []);
|
|
153
|
+
}
|
|
154
|
+
else if (node.type === IfcTypeEnum.IfcBuilding) {
|
|
155
|
+
currentBuilding = node.expressId;
|
|
156
|
+
byBuilding.set(node.expressId, []);
|
|
157
|
+
}
|
|
158
|
+
else if (node.type === IfcTypeEnum.IfcSite) {
|
|
159
|
+
currentSite = node.expressId;
|
|
160
|
+
bySite.set(node.expressId, []);
|
|
161
|
+
}
|
|
162
|
+
else if (node.type === IfcTypeEnum.IfcSpace) {
|
|
163
|
+
bySpace.set(node.expressId, []);
|
|
164
|
+
}
|
|
165
|
+
// Add elements to appropriate maps
|
|
166
|
+
for (const elementId of node.elements) {
|
|
167
|
+
if (currentStorey !== null) {
|
|
168
|
+
byStorey.get(currentStorey)?.push(elementId);
|
|
169
|
+
elementToStorey.set(elementId, currentStorey);
|
|
170
|
+
}
|
|
171
|
+
if (currentBuilding !== null) {
|
|
172
|
+
byBuilding.get(currentBuilding)?.push(elementId);
|
|
173
|
+
}
|
|
174
|
+
if (currentSite !== null) {
|
|
175
|
+
bySite.get(currentSite)?.push(elementId);
|
|
176
|
+
}
|
|
177
|
+
if (node.type === IfcTypeEnum.IfcSpace) {
|
|
178
|
+
bySpace.get(node.expressId)?.push(elementId);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
// Recurse to children
|
|
182
|
+
for (const child of node.children) {
|
|
183
|
+
populateMaps(child, currentStorey, currentBuilding, currentSite, pathToId, byStorey, byBuilding, bySite, bySpace, storeyElevations, elementToStorey);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Create an empty hierarchy when no project is found.
|
|
188
|
+
*/
|
|
189
|
+
function createEmptyHierarchy() {
|
|
190
|
+
const emptyProject = {
|
|
191
|
+
expressId: 0,
|
|
192
|
+
type: IfcTypeEnum.IfcProject,
|
|
193
|
+
name: 'Unknown Project',
|
|
194
|
+
children: [],
|
|
195
|
+
elements: [],
|
|
196
|
+
};
|
|
197
|
+
return {
|
|
198
|
+
project: emptyProject,
|
|
199
|
+
byStorey: new Map(),
|
|
200
|
+
byBuilding: new Map(),
|
|
201
|
+
bySite: new Map(),
|
|
202
|
+
bySpace: new Map(),
|
|
203
|
+
storeyElevations: new Map(),
|
|
204
|
+
storeyHeights: new Map(),
|
|
205
|
+
elementToStorey: new Map(),
|
|
206
|
+
getStoreyElements: () => [],
|
|
207
|
+
getStoreyByElevation: () => null,
|
|
208
|
+
getContainingSpace: () => null,
|
|
209
|
+
getPath: () => [],
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Extract name from node attributes.
|
|
214
|
+
*/
|
|
215
|
+
function extractName(node) {
|
|
216
|
+
const name = node.attributes.get('bsi::ifc::prop::Name');
|
|
217
|
+
if (typeof name === 'string')
|
|
218
|
+
return name;
|
|
219
|
+
const typeName = node.attributes.get('bsi::ifc::prop::TypeName');
|
|
220
|
+
if (typeof typeName === 'string')
|
|
221
|
+
return typeName;
|
|
222
|
+
const longName = node.attributes.get('bsi::ifc::prop::LongName');
|
|
223
|
+
if (typeof longName === 'string')
|
|
224
|
+
return longName;
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
227
|
+
//# sourceMappingURL=hierarchy-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hierarchy-builder.js","sourceRoot":"","sources":["../src/hierarchy-builder.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { type MeshData } from './geometry-extractor.js';
|
|
2
|
+
import { StringTable } from '@ifc-lite/data';
|
|
3
|
+
import type { SpatialHierarchy, EntityTable, PropertyTable, QuantityTable, RelationshipGraph } from '@ifc-lite/data';
|
|
4
|
+
export * from './types.js';
|
|
5
|
+
export { composeIfcx, findRoots, getDescendants, getPathToRoot } from './composition.js';
|
|
6
|
+
export { extractEntities } from './entity-extractor.js';
|
|
7
|
+
export { extractProperties, isQuantityProperty } from './property-extractor.js';
|
|
8
|
+
export { extractGeometry, type MeshData } from './geometry-extractor.js';
|
|
9
|
+
export { buildHierarchy } from './hierarchy-builder.js';
|
|
10
|
+
/**
|
|
11
|
+
* Result of parsing an IFCX file.
|
|
12
|
+
* Compatible with existing ifc-lite data structures.
|
|
13
|
+
*/
|
|
14
|
+
export interface IfcxParseResult {
|
|
15
|
+
/** Columnar entity table */
|
|
16
|
+
entities: EntityTable;
|
|
17
|
+
/** Columnar property table */
|
|
18
|
+
properties: PropertyTable;
|
|
19
|
+
/** Columnar quantity table */
|
|
20
|
+
quantities: QuantityTable;
|
|
21
|
+
/** Relationship graph */
|
|
22
|
+
relationships: RelationshipGraph;
|
|
23
|
+
/** Spatial hierarchy */
|
|
24
|
+
spatialHierarchy: SpatialHierarchy;
|
|
25
|
+
/** String table for interned strings */
|
|
26
|
+
strings: StringTable;
|
|
27
|
+
/** Pre-tessellated geometry meshes */
|
|
28
|
+
meshes: MeshData[];
|
|
29
|
+
/** Mapping from IFCX path to express ID */
|
|
30
|
+
pathToId: Map<string, number>;
|
|
31
|
+
/** Mapping from express ID to IFCX path */
|
|
32
|
+
idToPath: Map<number, string>;
|
|
33
|
+
/** Schema version */
|
|
34
|
+
schemaVersion: 'IFC5';
|
|
35
|
+
/** File size in bytes */
|
|
36
|
+
fileSize: number;
|
|
37
|
+
/** Number of entities */
|
|
38
|
+
entityCount: number;
|
|
39
|
+
/** Parse time in milliseconds */
|
|
40
|
+
parseTime: number;
|
|
41
|
+
}
|
|
42
|
+
export interface IfcxParseOptions {
|
|
43
|
+
/** Progress callback */
|
|
44
|
+
onProgress?: (progress: {
|
|
45
|
+
phase: string;
|
|
46
|
+
percent: number;
|
|
47
|
+
}) => void;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Parse an IFCX file and return data compatible with existing ifc-lite pipeline.
|
|
51
|
+
*/
|
|
52
|
+
export declare function parseIfcx(buffer: ArrayBuffer, options?: IfcxParseOptions): Promise<IfcxParseResult>;
|
|
53
|
+
/**
|
|
54
|
+
* Detect if a buffer contains IFCX (JSON) or IFC (STEP) format.
|
|
55
|
+
*/
|
|
56
|
+
export declare function detectFormat(buffer: ArrayBuffer): 'ifcx' | 'ifc' | 'unknown';
|
|
57
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAeA,OAAO,EAAmB,KAAK,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAEzE,OAAO,EACL,WAAW,EAIZ,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,gBAAgB,EAAE,WAAW,EAAE,aAAa,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAGrH,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACzF,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAChF,OAAO,EAAE,eAAe,EAAE,KAAK,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,4BAA4B;IAC5B,QAAQ,EAAE,WAAW,CAAC;IACtB,8BAA8B;IAC9B,UAAU,EAAE,aAAa,CAAC;IAC1B,8BAA8B;IAC9B,UAAU,EAAE,aAAa,CAAC;IAC1B,yBAAyB;IACzB,aAAa,EAAE,iBAAiB,CAAC;IACjC,wBAAwB;IACxB,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,wCAAwC;IACxC,OAAO,EAAE,WAAW,CAAC;IACrB,sCAAsC;IACtC,MAAM,EAAE,QAAQ,EAAE,CAAC;IACnB,2CAA2C;IAC3C,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,2CAA2C;IAC3C,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,qBAAqB;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,yBAAyB;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,yBAAyB;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,iCAAiC;IACjC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,wBAAwB;IACxB,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CACrE;AAED;;GAEG;AACH,wBAAsB,SAAS,CAC7B,MAAM,EAAE,WAAW,EACnB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,eAAe,CAAC,CAwE1B;AAiHD;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,GAAG,KAAK,GAAG,SAAS,CAe5E"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
import { composeIfcx } from './composition.js';
|
|
5
|
+
import { extractEntities } from './entity-extractor.js';
|
|
6
|
+
import { extractProperties, isQuantityProperty } from './property-extractor.js';
|
|
7
|
+
import { extractGeometry } from './geometry-extractor.js';
|
|
8
|
+
import { buildHierarchy } from './hierarchy-builder.js';
|
|
9
|
+
import { StringTable, RelationshipGraphBuilder, RelationshipType, QuantityTableBuilder, } from '@ifc-lite/data';
|
|
10
|
+
// Re-export types
|
|
11
|
+
export * from './types.js';
|
|
12
|
+
export { composeIfcx, findRoots, getDescendants, getPathToRoot } from './composition.js';
|
|
13
|
+
export { extractEntities } from './entity-extractor.js';
|
|
14
|
+
export { extractProperties, isQuantityProperty } from './property-extractor.js';
|
|
15
|
+
export { extractGeometry } from './geometry-extractor.js';
|
|
16
|
+
export { buildHierarchy } from './hierarchy-builder.js';
|
|
17
|
+
/**
|
|
18
|
+
* Parse an IFCX file and return data compatible with existing ifc-lite pipeline.
|
|
19
|
+
*/
|
|
20
|
+
export async function parseIfcx(buffer, options = {}) {
|
|
21
|
+
const startTime = performance.now();
|
|
22
|
+
// Phase 1: Parse JSON
|
|
23
|
+
options.onProgress?.({ phase: 'parse', percent: 0 });
|
|
24
|
+
const text = new TextDecoder().decode(buffer);
|
|
25
|
+
let file;
|
|
26
|
+
try {
|
|
27
|
+
file = JSON.parse(text);
|
|
28
|
+
}
|
|
29
|
+
catch (e) {
|
|
30
|
+
throw new Error(`Invalid IFCX file: JSON parse error - ${e}`);
|
|
31
|
+
}
|
|
32
|
+
// Validate header
|
|
33
|
+
if (!file.header?.ifcxVersion?.toLowerCase().includes('ifcx')) {
|
|
34
|
+
throw new Error('Invalid IFCX file: missing or invalid header.ifcxVersion');
|
|
35
|
+
}
|
|
36
|
+
options.onProgress?.({ phase: 'parse', percent: 100 });
|
|
37
|
+
// Phase 2: Compose ECS nodes
|
|
38
|
+
options.onProgress?.({ phase: 'compose', percent: 0 });
|
|
39
|
+
const composed = composeIfcx(file);
|
|
40
|
+
options.onProgress?.({ phase: 'compose', percent: 100 });
|
|
41
|
+
// Phase 3: Extract entities
|
|
42
|
+
options.onProgress?.({ phase: 'entities', percent: 0 });
|
|
43
|
+
const strings = new StringTable();
|
|
44
|
+
const { entities, pathToId, idToPath } = extractEntities(composed, strings);
|
|
45
|
+
options.onProgress?.({ phase: 'entities', percent: 100 });
|
|
46
|
+
// Phase 4: Extract properties
|
|
47
|
+
options.onProgress?.({ phase: 'properties', percent: 0 });
|
|
48
|
+
const properties = extractProperties(composed, pathToId, strings);
|
|
49
|
+
options.onProgress?.({ phase: 'properties', percent: 100 });
|
|
50
|
+
// Phase 5: Extract geometry
|
|
51
|
+
options.onProgress?.({ phase: 'geometry', percent: 0 });
|
|
52
|
+
const meshes = extractGeometry(composed, pathToId);
|
|
53
|
+
options.onProgress?.({ phase: 'geometry', percent: 100 });
|
|
54
|
+
// Phase 6: Build hierarchy
|
|
55
|
+
options.onProgress?.({ phase: 'hierarchy', percent: 0 });
|
|
56
|
+
const spatialHierarchy = buildHierarchy(composed, pathToId);
|
|
57
|
+
options.onProgress?.({ phase: 'hierarchy', percent: 100 });
|
|
58
|
+
// Phase 7: Build relationships
|
|
59
|
+
options.onProgress?.({ phase: 'relationships', percent: 0 });
|
|
60
|
+
const relationships = buildRelationships(composed, pathToId);
|
|
61
|
+
options.onProgress?.({ phase: 'relationships', percent: 100 });
|
|
62
|
+
// Phase 8: Build quantities (from properties that look like quantities)
|
|
63
|
+
const quantities = buildQuantities(composed, pathToId, strings);
|
|
64
|
+
const parseTime = performance.now() - startTime;
|
|
65
|
+
return {
|
|
66
|
+
entities,
|
|
67
|
+
properties,
|
|
68
|
+
quantities,
|
|
69
|
+
relationships,
|
|
70
|
+
spatialHierarchy,
|
|
71
|
+
strings,
|
|
72
|
+
meshes,
|
|
73
|
+
pathToId,
|
|
74
|
+
idToPath,
|
|
75
|
+
schemaVersion: 'IFC5',
|
|
76
|
+
fileSize: buffer.byteLength,
|
|
77
|
+
entityCount: entities.count,
|
|
78
|
+
parseTime,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Build relationship graph from composed nodes.
|
|
83
|
+
* In IFCX, relationships are implicit in the children structure.
|
|
84
|
+
*/
|
|
85
|
+
function buildRelationships(composed, pathToId) {
|
|
86
|
+
const builder = new RelationshipGraphBuilder();
|
|
87
|
+
let relId = 1;
|
|
88
|
+
for (const node of composed.values()) {
|
|
89
|
+
const parentId = pathToId.get(node.path);
|
|
90
|
+
if (parentId === undefined)
|
|
91
|
+
continue;
|
|
92
|
+
for (const child of node.children.values()) {
|
|
93
|
+
const childId = pathToId.get(child.path);
|
|
94
|
+
if (childId !== undefined) {
|
|
95
|
+
// Determine relationship type based on node types
|
|
96
|
+
const relType = determineRelationshipType(node, child);
|
|
97
|
+
builder.addEdge(parentId, childId, relType, relId++);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return builder.build();
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Determine relationship type based on parent and child node types.
|
|
105
|
+
*/
|
|
106
|
+
function determineRelationshipType(parent, child) {
|
|
107
|
+
const parentClass = parent.attributes.get('bsi::ifc::class')?.code;
|
|
108
|
+
const childClass = child.attributes.get('bsi::ifc::class')?.code;
|
|
109
|
+
// Spatial containment
|
|
110
|
+
if (isSpatialElement(parentClass) && !isSpatialElement(childClass)) {
|
|
111
|
+
return RelationshipType.ContainsElements;
|
|
112
|
+
}
|
|
113
|
+
// Aggregation (spatial structure hierarchy)
|
|
114
|
+
if (isSpatialElement(parentClass) && isSpatialElement(childClass)) {
|
|
115
|
+
return RelationshipType.Aggregates;
|
|
116
|
+
}
|
|
117
|
+
// Default to containment
|
|
118
|
+
return RelationshipType.ContainsElements;
|
|
119
|
+
}
|
|
120
|
+
function isSpatialElement(typeCode) {
|
|
121
|
+
if (!typeCode)
|
|
122
|
+
return false;
|
|
123
|
+
const spatialTypes = ['IfcProject', 'IfcSite', 'IfcBuilding', 'IfcBuildingStorey', 'IfcSpace'];
|
|
124
|
+
return spatialTypes.includes(typeCode);
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Build quantity table from properties that appear to be quantities.
|
|
128
|
+
* Uses the isQuantityProperty helper to identify quantity-like properties.
|
|
129
|
+
*/
|
|
130
|
+
function buildQuantities(composed, pathToId, strings) {
|
|
131
|
+
const builder = new QuantityTableBuilder(strings);
|
|
132
|
+
// Map property names to quantity types
|
|
133
|
+
const getQuantityType = (propName) => {
|
|
134
|
+
// Volume types
|
|
135
|
+
if (propName === 'Volume' || propName.endsWith('Volume'))
|
|
136
|
+
return 2; // QuantityType.Volume
|
|
137
|
+
// Area types
|
|
138
|
+
if (propName === 'Area' || propName.endsWith('Area'))
|
|
139
|
+
return 1; // QuantityType.Area
|
|
140
|
+
// Count types
|
|
141
|
+
if (propName === 'Count' || propName.endsWith('Count'))
|
|
142
|
+
return 3; // QuantityType.Count
|
|
143
|
+
// Weight types
|
|
144
|
+
if (propName === 'Weight' || propName === 'Mass' ||
|
|
145
|
+
propName.endsWith('Weight') || propName.endsWith('Mass'))
|
|
146
|
+
return 4; // QuantityType.Weight
|
|
147
|
+
// Default to length for dimension-like quantities
|
|
148
|
+
return 0; // QuantityType.Length
|
|
149
|
+
};
|
|
150
|
+
for (const node of composed.values()) {
|
|
151
|
+
const expressId = pathToId.get(node.path);
|
|
152
|
+
if (expressId === undefined)
|
|
153
|
+
continue;
|
|
154
|
+
// Get the IFC class to use as context for qset naming
|
|
155
|
+
const ifcClass = node.attributes.get('bsi::ifc::class')?.code;
|
|
156
|
+
const qsetName = ifcClass ? `Qto_${ifcClass.replace('Ifc', '')}BaseQuantities` : 'BaseQuantities';
|
|
157
|
+
for (const [key, value] of node.attributes) {
|
|
158
|
+
// Check if this looks like a quantity
|
|
159
|
+
const propName = key.split('::').pop() ?? '';
|
|
160
|
+
if (typeof value === 'number' && isQuantityProperty(propName)) {
|
|
161
|
+
builder.add({
|
|
162
|
+
entityId: expressId,
|
|
163
|
+
qsetName,
|
|
164
|
+
quantityName: propName,
|
|
165
|
+
quantityType: getQuantityType(propName),
|
|
166
|
+
value,
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return builder.build();
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Detect if a buffer contains IFCX (JSON) or IFC (STEP) format.
|
|
175
|
+
*/
|
|
176
|
+
export function detectFormat(buffer) {
|
|
177
|
+
const bytes = new Uint8Array(buffer, 0, Math.min(100, buffer.byteLength));
|
|
178
|
+
const start = new TextDecoder().decode(bytes).trim();
|
|
179
|
+
// IFCX is JSON starting with {
|
|
180
|
+
if (start.startsWith('{')) {
|
|
181
|
+
return 'ifcx';
|
|
182
|
+
}
|
|
183
|
+
// IFC STEP starts with ISO-10303-21
|
|
184
|
+
if (start.includes('ISO-10303-21') || start.startsWith('ISO')) {
|
|
185
|
+
return 'ifc';
|
|
186
|
+
}
|
|
187
|
+
return 'unknown';
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Property Extractor for IFCX
|
|
3
|
+
* Extracts properties from node attributes and builds PropertyTable
|
|
4
|
+
*/
|
|
5
|
+
import type { ComposedNode } from './types.js';
|
|
6
|
+
import { StringTable } from '@ifc-lite/data';
|
|
7
|
+
import type { PropertyTable } from '@ifc-lite/data';
|
|
8
|
+
/**
|
|
9
|
+
* Extract properties from composed IFCX nodes.
|
|
10
|
+
*
|
|
11
|
+
* IFCX properties are flat attributes with namespace prefixes:
|
|
12
|
+
* - bsi::ifc::prop::IsExternal -> PropertySingleValue
|
|
13
|
+
* - bsi::ifc::prop::Volume -> QuantitySingleValue
|
|
14
|
+
*
|
|
15
|
+
* We group properties by namespace prefix for PropertySet-like grouping.
|
|
16
|
+
*/
|
|
17
|
+
export declare function extractProperties(composed: Map<string, ComposedNode>, pathToId: Map<string, number>, strings: StringTable): PropertyTable;
|
|
18
|
+
/**
|
|
19
|
+
* Extract quantity-like properties (Volume, Area, Length, etc.)
|
|
20
|
+
* These are identified by their names matching quantity patterns.
|
|
21
|
+
*/
|
|
22
|
+
export declare function isQuantityProperty(propName: string): boolean;
|
|
23
|
+
//# sourceMappingURL=property-extractor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"property-extractor.d.ts","sourceRoot":"","sources":["../src/property-extractor.ts"],"names":[],"mappings":"AAIA;;;GAGG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,OAAO,EACL,WAAW,EAGZ,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAapD;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,EACnC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAC7B,OAAO,EAAE,WAAW,GACnB,aAAa,CA2Bf;AA+HD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAqC5D"}
|