@ifc-lite/create 1.14.5 → 1.15.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ifc-creator-math.d.ts +23 -0
- package/dist/ifc-creator-math.d.ts.map +1 -0
- package/dist/ifc-creator-math.js +50 -0
- package/dist/ifc-creator-math.js.map +1 -0
- package/dist/ifc-creator.d.ts +63 -1
- package/dist/ifc-creator.d.ts.map +1 -1
- package/dist/ifc-creator.js +222 -41
- package/dist/ifc-creator.js.map +1 -1
- package/dist/in-store/_emit-helpers.d.ts +52 -0
- package/dist/in-store/_emit-helpers.d.ts.map +1 -0
- package/dist/in-store/_emit-helpers.js +147 -0
- package/dist/in-store/_emit-helpers.js.map +1 -0
- package/dist/in-store/anchor.d.ts +29 -0
- package/dist/in-store/anchor.d.ts.map +1 -0
- package/dist/in-store/anchor.js +5 -0
- package/dist/in-store/anchor.js.map +1 -0
- package/dist/in-store/auto-space-detect.d.ts +68 -0
- package/dist/in-store/auto-space-detect.d.ts.map +1 -0
- package/dist/in-store/auto-space-detect.js +393 -0
- package/dist/in-store/auto-space-detect.js.map +1 -0
- package/dist/in-store/beam.d.ts +25 -0
- package/dist/in-store/beam.d.ts.map +1 -0
- package/dist/in-store/beam.js +119 -0
- package/dist/in-store/beam.js.map +1 -0
- package/dist/in-store/column.d.ts +42 -0
- package/dist/in-store/column.d.ts.map +1 -0
- package/dist/in-store/column.js +108 -0
- package/dist/in-store/column.js.map +1 -0
- package/dist/in-store/door.d.ts +44 -0
- package/dist/in-store/door.d.ts.map +1 -0
- package/dist/in-store/door.js +68 -0
- package/dist/in-store/door.js.map +1 -0
- package/dist/in-store/duplicate.d.ts +100 -0
- package/dist/in-store/duplicate.d.ts.map +1 -0
- package/dist/in-store/duplicate.js +122 -0
- package/dist/in-store/duplicate.js.map +1 -0
- package/dist/in-store/extract-walls.d.ts +80 -0
- package/dist/in-store/extract-walls.d.ts.map +1 -0
- package/dist/in-store/extract-walls.js +522 -0
- package/dist/in-store/extract-walls.js.map +1 -0
- package/dist/in-store/generate-spaces.d.ts +71 -0
- package/dist/in-store/generate-spaces.d.ts.map +1 -0
- package/dist/in-store/generate-spaces.js +76 -0
- package/dist/in-store/generate-spaces.js.map +1 -0
- package/dist/in-store/member.d.ts +32 -0
- package/dist/in-store/member.d.ts.map +1 -0
- package/dist/in-store/member.js +35 -0
- package/dist/in-store/member.js.map +1 -0
- package/dist/in-store/plate.d.ts +43 -0
- package/dist/in-store/plate.d.ts.map +1 -0
- package/dist/in-store/plate.js +33 -0
- package/dist/in-store/plate.js.map +1 -0
- package/dist/in-store/resolve-anchor.d.ts +12 -0
- package/dist/in-store/resolve-anchor.d.ts.map +1 -0
- package/dist/in-store/resolve-anchor.js +125 -0
- package/dist/in-store/resolve-anchor.js.map +1 -0
- package/dist/in-store/resolve-source.d.ts +19 -0
- package/dist/in-store/resolve-source.d.ts.map +1 -0
- package/dist/in-store/resolve-source.js +203 -0
- package/dist/in-store/resolve-source.js.map +1 -0
- package/dist/in-store/roof.d.ts +43 -0
- package/dist/in-store/roof.d.ts.map +1 -0
- package/dist/in-store/roof.js +33 -0
- package/dist/in-store/roof.js.map +1 -0
- package/dist/in-store/slab.d.ts +44 -0
- package/dist/in-store/slab.d.ts.map +1 -0
- package/dist/in-store/slab.js +142 -0
- package/dist/in-store/slab.js.map +1 -0
- package/dist/in-store/space.d.ts +43 -0
- package/dist/in-store/space.d.ts.map +1 -0
- package/dist/in-store/space.js +71 -0
- package/dist/in-store/space.js.map +1 -0
- package/dist/in-store/wall.d.ts +27 -0
- package/dist/in-store/wall.d.ts.map +1 -0
- package/dist/in-store/wall.js +121 -0
- package/dist/in-store/wall.js.map +1 -0
- package/dist/in-store/window.d.ts +36 -0
- package/dist/in-store/window.d.ts.map +1 -0
- package/dist/in-store/window.js +57 -0
- package/dist/in-store/window.js.map +1 -0
- package/dist/index.d.ts +18 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +96 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +10 -6
|
@@ -0,0 +1,76 @@
|
|
|
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 { resolveSpatialAnchor } from './resolve-anchor.js';
|
|
5
|
+
import { extractWallSegmentsForStorey, } from './extract-walls.js';
|
|
6
|
+
import { detectEnclosedAreasWithStats, } from './auto-space-detect.js';
|
|
7
|
+
import { addSpaceToStore } from './space.js';
|
|
8
|
+
export function generateSpacesFromWalls(editor, store, storeyExpressId, options = {}, overlay) {
|
|
9
|
+
const height = options.height ?? 3;
|
|
10
|
+
const namePattern = options.namePattern ?? 'Space {n}';
|
|
11
|
+
if (height <= 0) {
|
|
12
|
+
throw new Error('generateSpacesFromWalls: height must be positive');
|
|
13
|
+
}
|
|
14
|
+
const debug = !!options.debug;
|
|
15
|
+
const log = debug ? (...args) => console.debug('[generate-spaces]', ...args) : () => { };
|
|
16
|
+
log(`storey #${storeyExpressId}: starting auto-space generation`);
|
|
17
|
+
const extraction = extractWallSegmentsForStorey(store, storeyExpressId, overlay, {
|
|
18
|
+
debug,
|
|
19
|
+
extraDividerTypes: options.extraDividerTypes,
|
|
20
|
+
});
|
|
21
|
+
log(`extracted ${extraction.segments.length} segments from ${extraction.considered} walls (${extraction.skipped.length} skipped); unitScale=${extraction.lengthUnitScale}`);
|
|
22
|
+
// Snap tolerance / min area are user-friendly metres. Segments are
|
|
23
|
+
// also already converted to metres by the extractor, so no further
|
|
24
|
+
// unit-scaling is needed here.
|
|
25
|
+
const detection = detectEnclosedAreasWithStats(extraction.segments, {
|
|
26
|
+
snapTolerance: options.snapTolerance ?? 0.1,
|
|
27
|
+
minArea: options.minArea ?? 0.5,
|
|
28
|
+
debug,
|
|
29
|
+
});
|
|
30
|
+
const detected = detection.spaces;
|
|
31
|
+
// Always log a one-liner summary at info level so users see something
|
|
32
|
+
// in devtools without flipping the debug flag — the most common
|
|
33
|
+
// failure ("no regions detected") becomes self-explanatory.
|
|
34
|
+
const unitNote = extraction.lengthUnitScale === 1 ? 'metres'
|
|
35
|
+
: extraction.lengthUnitScale === 0.001 ? 'millimetres'
|
|
36
|
+
: `scale ${extraction.lengthUnitScale}`;
|
|
37
|
+
console.info(`[auto-spaces] storey #${storeyExpressId}: ${detected.length} region(s) from ${extraction.contributingWallIds.length}/${extraction.considered} walls — ` +
|
|
38
|
+
`${detection.stats.vertices}v / ${detection.stats.segmentsAfterSplit}e / ${detection.stats.faces}f ` +
|
|
39
|
+
`(dropped ${detection.stats.outerFacesDropped} outer + ${detection.stats.belowMinAreaDropped} small) [${unitNote}].`);
|
|
40
|
+
const emitted = [];
|
|
41
|
+
if (options.dryRun || detected.length === 0) {
|
|
42
|
+
return {
|
|
43
|
+
wallsConsidered: extraction.considered,
|
|
44
|
+
wallsContributing: extraction.contributingWallIds.length,
|
|
45
|
+
wallsSkipped: extraction.skipped,
|
|
46
|
+
detected,
|
|
47
|
+
detectionStats: detection.stats,
|
|
48
|
+
emitted,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
const anchor = resolveSpatialAnchor(store, storeyExpressId);
|
|
52
|
+
if (!anchor) {
|
|
53
|
+
throw new Error(`generateSpacesFromWalls: no resolvable spatial anchor for storey #${storeyExpressId}`);
|
|
54
|
+
}
|
|
55
|
+
detected.forEach((region, i) => {
|
|
56
|
+
const name = namePattern.replace('{n}', String(i + 1));
|
|
57
|
+
const result = addSpaceToStore(editor, anchor, {
|
|
58
|
+
Profile: 'polygon',
|
|
59
|
+
OuterCurve: region.outline,
|
|
60
|
+
Height: height,
|
|
61
|
+
Name: name,
|
|
62
|
+
LongName: options.longName,
|
|
63
|
+
PredefinedType: options.predefinedType,
|
|
64
|
+
});
|
|
65
|
+
emitted.push({ region, result, name });
|
|
66
|
+
});
|
|
67
|
+
return {
|
|
68
|
+
wallsConsidered: extraction.considered,
|
|
69
|
+
wallsContributing: extraction.contributingWallIds.length,
|
|
70
|
+
wallsSkipped: extraction.skipped,
|
|
71
|
+
detected,
|
|
72
|
+
detectionStats: detection.stats,
|
|
73
|
+
emitted,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=generate-spaces.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-spaces.js","sourceRoot":"","sources":["../../src/in-store/generate-spaces.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anchored builder for IfcMember — a generic structural member
|
|
3
|
+
* (brace, strut, post). Geometry shape mirrors `addBeamToStore`:
|
|
4
|
+
* - placement origin at `Start`, local Z = member axis
|
|
5
|
+
* - cross-section centred on the axis, extruded by member length
|
|
6
|
+
* The distinction is the IFC type and the `.NOTDEFINED.` PredefinedType
|
|
7
|
+
* default — IfcBeam carries `.BEAM.`.
|
|
8
|
+
*/
|
|
9
|
+
import type { StoreEditor } from '@ifc-lite/mutations';
|
|
10
|
+
import type { SpatialAnchor } from './anchor.js';
|
|
11
|
+
export interface MemberInStoreParams {
|
|
12
|
+
Start: [number, number, number];
|
|
13
|
+
End: [number, number, number];
|
|
14
|
+
Width: number;
|
|
15
|
+
Height: number;
|
|
16
|
+
PredefinedType?: 'BRACE' | 'CHORD' | 'COLLAR' | 'MEMBER' | 'MULLION' | 'PLATE' | 'POST' | 'PURLIN' | 'RAFTER' | 'STRINGER' | 'STRUT' | 'STUD' | 'USERDEFINED' | 'NOTDEFINED';
|
|
17
|
+
Name?: string;
|
|
18
|
+
Description?: string;
|
|
19
|
+
ObjectType?: string;
|
|
20
|
+
Tag?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface MemberBuildResult {
|
|
23
|
+
memberId: number;
|
|
24
|
+
placementId: number;
|
|
25
|
+
profileId: number;
|
|
26
|
+
solidId: number;
|
|
27
|
+
shapeRepId: number;
|
|
28
|
+
productShapeId: number;
|
|
29
|
+
relContainedId: number;
|
|
30
|
+
}
|
|
31
|
+
export declare function addMemberToStore(editor: StoreEditor, anchor: SpatialAnchor, params: MemberInStoreParams): MemberBuildResult;
|
|
32
|
+
//# sourceMappingURL=member.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"member.d.ts","sourceRoot":"","sources":["../../src/in-store/member.ts"],"names":[],"mappings":"AAIA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAGvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAUjD,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,GAAG,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EACX,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,GAC7D,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,UAAU,GAAG,OAAO,GAAG,MAAM,GAC5D,aAAa,GAAG,YAAY,CAAC;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;CACxB;AAOD,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,mBAAmB,GAC1B,iBAAiB,CA2BnB"}
|
|
@@ -0,0 +1,35 @@
|
|
|
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 { vecCross, vecNorm } from '../ifc-creator-math.js';
|
|
5
|
+
import { emitBodyRepresentation, emitExtrudedSolid, emitLocalPlacement, emitRectangleProfile, emitRelContainedInSpatialStructure, ifcElementHeader, } from './_emit-helpers.js';
|
|
6
|
+
function computeRefDirection(axis) {
|
|
7
|
+
const up = Math.abs(axis[2]) < 0.9 ? [0, 0, 1] : [1, 0, 0];
|
|
8
|
+
return vecNorm(vecCross(up, axis));
|
|
9
|
+
}
|
|
10
|
+
export function addMemberToStore(editor, anchor, params) {
|
|
11
|
+
const dx = params.End[0] - params.Start[0];
|
|
12
|
+
const dy = params.End[1] - params.Start[1];
|
|
13
|
+
const dz = params.End[2] - params.Start[2];
|
|
14
|
+
const memberLen = Math.sqrt(dx * dx + dy * dy + dz * dz);
|
|
15
|
+
if (memberLen <= 0) {
|
|
16
|
+
throw new Error('addMemberToStore: Start and End must be distinct points');
|
|
17
|
+
}
|
|
18
|
+
if (params.Width <= 0 || params.Height <= 0) {
|
|
19
|
+
throw new Error('addMemberToStore: Width and Height must be positive');
|
|
20
|
+
}
|
|
21
|
+
const dir = vecNorm([dx, dy, dz]);
|
|
22
|
+
const refDir = computeRefDirection(dir);
|
|
23
|
+
const placementId = emitLocalPlacement(editor, anchor.storeyPlacementId, params.Start, dir, refDir);
|
|
24
|
+
const profileId = emitRectangleProfile(editor, params.Width, params.Height);
|
|
25
|
+
const solidId = emitExtrudedSolid(editor, profileId, memberLen);
|
|
26
|
+
const { shapeRepId, productShapeId } = emitBodyRepresentation(editor, anchor.bodyContextId, solidId);
|
|
27
|
+
const attrs = ifcElementHeader(anchor.ownerHistoryId, placementId, productShapeId, params, 'Member');
|
|
28
|
+
if ((anchor.schema ?? 'IFC4') !== 'IFC2X3') {
|
|
29
|
+
attrs.push(`.${params.PredefinedType ?? 'NOTDEFINED'}.`);
|
|
30
|
+
}
|
|
31
|
+
const memberId = editor.addEntity('IfcMember', attrs).expressId;
|
|
32
|
+
const relContainedId = emitRelContainedInSpatialStructure(editor, anchor.ownerHistoryId, memberId, anchor.storeyId);
|
|
33
|
+
return { memberId, placementId, profileId, solidId, shapeRepId, productShapeId, relContainedId };
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=member.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"member.js","sourceRoot":"","sources":["../../src/in-store/member.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anchored builder for IfcPlate — a thin flat element (steel plate,
|
|
3
|
+
* gusset plate, etc.). Geometry-wise identical to a slab; the
|
|
4
|
+
* distinction is the IFC type and the `.NOTDEFINED.` PredefinedType
|
|
5
|
+
* default (callers can override).
|
|
6
|
+
*/
|
|
7
|
+
import type { StoreEditor } from '@ifc-lite/mutations';
|
|
8
|
+
import type { SpatialAnchor } from './anchor.js';
|
|
9
|
+
export type PlateInStoreParams = PlateRectangleParams | PlatePolygonParams;
|
|
10
|
+
export interface PlateRectangleParams {
|
|
11
|
+
Position: [number, number, number];
|
|
12
|
+
Width: number;
|
|
13
|
+
Depth: number;
|
|
14
|
+
Thickness: number;
|
|
15
|
+
Profile?: 'rectangle';
|
|
16
|
+
PredefinedType?: 'CURTAIN_PANEL' | 'SHEET' | 'USERDEFINED' | 'NOTDEFINED';
|
|
17
|
+
Name?: string;
|
|
18
|
+
Description?: string;
|
|
19
|
+
ObjectType?: string;
|
|
20
|
+
Tag?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface PlatePolygonParams {
|
|
23
|
+
Profile: 'polygon';
|
|
24
|
+
OuterCurve: Array<[number, number]>;
|
|
25
|
+
Position?: [number, number, number];
|
|
26
|
+
Thickness: number;
|
|
27
|
+
PredefinedType?: 'CURTAIN_PANEL' | 'SHEET' | 'USERDEFINED' | 'NOTDEFINED';
|
|
28
|
+
Name?: string;
|
|
29
|
+
Description?: string;
|
|
30
|
+
ObjectType?: string;
|
|
31
|
+
Tag?: string;
|
|
32
|
+
}
|
|
33
|
+
export interface PlateBuildResult {
|
|
34
|
+
plateId: number;
|
|
35
|
+
placementId: number;
|
|
36
|
+
profileId: number;
|
|
37
|
+
solidId: number;
|
|
38
|
+
shapeRepId: number;
|
|
39
|
+
productShapeId: number;
|
|
40
|
+
relContainedId: number;
|
|
41
|
+
}
|
|
42
|
+
export declare function addPlateToStore(editor: StoreEditor, anchor: SpatialAnchor, params: PlateInStoreParams): PlateBuildResult;
|
|
43
|
+
//# sourceMappingURL=plate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plate.d.ts","sourceRoot":"","sources":["../../src/in-store/plate.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAWjD,MAAM,MAAM,kBAAkB,GAAG,oBAAoB,GAAG,kBAAkB,CAAC;AAE3E,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,cAAc,CAAC,EAAE,eAAe,GAAG,OAAO,GAAG,aAAa,GAAG,YAAY,CAAC;IAC1E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,SAAS,CAAC;IACnB,UAAU,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACpC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,eAAe,GAAG,OAAO,GAAG,aAAa,GAAG,YAAY,CAAC;IAC1E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;CACxB;AAMD,wBAAgB,eAAe,CAC7B,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,kBAAkB,GACzB,gBAAgB,CA4BlB"}
|
|
@@ -0,0 +1,33 @@
|
|
|
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 { emitBodyRepresentation, emitExtrudedSolid, emitLocalPlacement, emitPolygonProfile, emitRectangleProfile, emitRelContainedInSpatialStructure, ifcElementHeader, } from './_emit-helpers.js';
|
|
5
|
+
function isPolygonParams(p) {
|
|
6
|
+
return p.Profile === 'polygon';
|
|
7
|
+
}
|
|
8
|
+
export function addPlateToStore(editor, anchor, params) {
|
|
9
|
+
const polygon = isPolygonParams(params);
|
|
10
|
+
const placementOrigin = polygon
|
|
11
|
+
? params.Position ?? [0, 0, 0]
|
|
12
|
+
: params.Position;
|
|
13
|
+
if (params.Thickness <= 0) {
|
|
14
|
+
throw new Error('addPlateToStore: Thickness must be positive');
|
|
15
|
+
}
|
|
16
|
+
if (!polygon && (params.Width <= 0 || params.Depth <= 0)) {
|
|
17
|
+
throw new Error('addPlateToStore: Width and Depth must be positive');
|
|
18
|
+
}
|
|
19
|
+
const placementId = emitLocalPlacement(editor, anchor.storeyPlacementId, placementOrigin);
|
|
20
|
+
const profileId = polygon
|
|
21
|
+
? emitPolygonProfile(editor, params.OuterCurve)
|
|
22
|
+
: emitRectangleProfile(editor, params.Width, params.Depth, params.Width / 2, params.Depth / 2);
|
|
23
|
+
const solidId = emitExtrudedSolid(editor, profileId, params.Thickness);
|
|
24
|
+
const { shapeRepId, productShapeId } = emitBodyRepresentation(editor, anchor.bodyContextId, solidId);
|
|
25
|
+
const attrs = ifcElementHeader(anchor.ownerHistoryId, placementId, productShapeId, params, 'Plate');
|
|
26
|
+
if ((anchor.schema ?? 'IFC4') !== 'IFC2X3') {
|
|
27
|
+
attrs.push(`.${params.PredefinedType ?? 'NOTDEFINED'}.`);
|
|
28
|
+
}
|
|
29
|
+
const plateId = editor.addEntity('IfcPlate', attrs).expressId;
|
|
30
|
+
const relContainedId = emitRelContainedInSpatialStructure(editor, anchor.ownerHistoryId, plateId, anchor.storeyId);
|
|
31
|
+
return { plateId, placementId, profileId, solidId, shapeRepId, productShapeId, relContainedId };
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=plate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plate.js","sourceRoot":"","sources":["../../src/in-store/plate.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAW/D,OAAO,EACL,sBAAsB,EACtB,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,EACpB,kCAAkC,EAClC,gBAAgB,GACjB,MAAM,oBAAoB,CAAC;AAuC5B,SAAS,eAAe,CAAC,CAAqB;IAC5C,OAAO,CAAC,CAAC,OAAO,KAAK,SAAS,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,MAAmB,EACnB,MAAqB,EACrB,MAA0B;IAE1B,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IACxC,MAAM,eAAe,GAA6B,OAAO;QACvD,CAAC,CAAC,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QAC9B,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC;IAEpB,IAAI,MAAM,CAAC,SAAS,IAAI,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;IACjE,CAAC;IACD,IAAI,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC,CAAC,EAAE,CAAC;QACzD,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvE,CAAC;IAED,MAAM,WAAW,GAAG,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,iBAAiB,EAAE,eAAe,CAAC,CAAC;IAC1F,MAAM,SAAS,GAAG,OAAO;QACvB,CAAC,CAAC,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,UAAU,CAAC;QAC/C,CAAC,CAAC,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,GAAG,CAAC,EAAE,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;IACjG,MAAM,OAAO,GAAG,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;IACvE,MAAM,EAAE,UAAU,EAAE,cAAc,EAAE,GAAG,sBAAsB,CAAC,MAAM,EAAE,MAAM,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;IAErG,MAAM,KAAK,GAAG,gBAAgB,CAAC,MAAM,CAAC,cAAc,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IACpG,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,KAAK,QAAQ,EAAE,CAAC;QAC3C,KAAK,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,cAAc,IAAI,YAAY,GAAG,CAAC,CAAC;IAC3D,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC,UAAU,EAAE,KAAgD,CAAC,CAAC,SAAS,CAAC;IACzG,MAAM,cAAc,GAAG,kCAAkC,CAAC,MAAM,EAAE,MAAM,CAAC,cAAc,EAAE,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IAEnH,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,cAAc,EAAE,CAAC;AAClG,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve a `SpatialAnchor` from a parsed `IfcDataStore`.
|
|
3
|
+
*
|
|
4
|
+
* Walks the entity index for the IfcOwnerHistory, the 'Body'
|
|
5
|
+
* IfcGeometricRepresentationSubContext (falling back to the model's
|
|
6
|
+
* 3D IfcGeometricRepresentationContext), and the target storey's
|
|
7
|
+
* IfcLocalPlacement.
|
|
8
|
+
*/
|
|
9
|
+
import { type IfcDataStore } from '@ifc-lite/parser';
|
|
10
|
+
import type { SpatialAnchor } from './anchor.js';
|
|
11
|
+
export declare function resolveSpatialAnchor(store: IfcDataStore, storeyExpressId: number): SpatialAnchor;
|
|
12
|
+
//# sourceMappingURL=resolve-anchor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-anchor.d.ts","sourceRoot":"","sources":["../../src/in-store/resolve-anchor.ts"],"names":[],"mappings":"AAIA;;;;;;;GAOG;AAEH,OAAO,EAAsC,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACzF,OAAO,KAAK,EAAE,aAAa,EAAuB,MAAM,aAAa,CAAC;AAEtE,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,GAAG,aAAa,CAwBhG"}
|
|
@@ -0,0 +1,125 @@
|
|
|
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
|
+
/**
|
|
5
|
+
* Resolve a `SpatialAnchor` from a parsed `IfcDataStore`.
|
|
6
|
+
*
|
|
7
|
+
* Walks the entity index for the IfcOwnerHistory, the 'Body'
|
|
8
|
+
* IfcGeometricRepresentationSubContext (falling back to the model's
|
|
9
|
+
* 3D IfcGeometricRepresentationContext), and the target storey's
|
|
10
|
+
* IfcLocalPlacement.
|
|
11
|
+
*/
|
|
12
|
+
import { EntityExtractor, getAttributeNames } from '@ifc-lite/parser';
|
|
13
|
+
export function resolveSpatialAnchor(store, storeyExpressId) {
|
|
14
|
+
const ownerHistoryId = findOwnerHistoryId(store);
|
|
15
|
+
if (ownerHistoryId === null) {
|
|
16
|
+
throw new Error('resolveSpatialAnchor: no IfcOwnerHistory found in store');
|
|
17
|
+
}
|
|
18
|
+
const bodyContextId = findBodyContextId(store);
|
|
19
|
+
if (bodyContextId === null) {
|
|
20
|
+
throw new Error('resolveSpatialAnchor: no IfcGeometricRepresentationContext (or Body subcontext) found in store');
|
|
21
|
+
}
|
|
22
|
+
const axisContextId = findAxisContextId(store);
|
|
23
|
+
if (axisContextId === null) {
|
|
24
|
+
throw new Error('resolveSpatialAnchor: no IfcGeometricRepresentationContext (or Axis subcontext) found in store');
|
|
25
|
+
}
|
|
26
|
+
const storeyPlacementId = findStoreyPlacementId(store, storeyExpressId);
|
|
27
|
+
if (storeyPlacementId === null) {
|
|
28
|
+
throw new Error(`resolveSpatialAnchor: storey #${storeyExpressId} has no resolvable IfcLocalPlacement`);
|
|
29
|
+
}
|
|
30
|
+
const schema = (store.schemaVersion ?? 'IFC4');
|
|
31
|
+
return { ownerHistoryId, bodyContextId, axisContextId, storeyId: storeyExpressId, storeyPlacementId, schema };
|
|
32
|
+
}
|
|
33
|
+
function findOwnerHistoryId(store) {
|
|
34
|
+
const ids = store.entityIndex.byType.get('IFCOWNERHISTORY');
|
|
35
|
+
return ids && ids.length > 0 ? ids[0] : null;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Prefer an IfcGeometricRepresentationSubContext with ContextIdentifier='Body';
|
|
39
|
+
* otherwise fall back to the first 3D IfcGeometricRepresentationContext.
|
|
40
|
+
*/
|
|
41
|
+
function findBodyContextId(store) {
|
|
42
|
+
if (!store.source)
|
|
43
|
+
return null;
|
|
44
|
+
const extractor = new EntityExtractor(store.source);
|
|
45
|
+
const subIds = store.entityIndex.byType.get('IFCGEOMETRICREPRESENTATIONSUBCONTEXT') ?? [];
|
|
46
|
+
for (const id of subIds) {
|
|
47
|
+
const ref = store.entityIndex.byId.get(id);
|
|
48
|
+
if (!ref)
|
|
49
|
+
continue;
|
|
50
|
+
const entity = extractor.extractEntity(ref);
|
|
51
|
+
const identifier = entity?.attributes?.[1];
|
|
52
|
+
if (typeof identifier === 'string' && identifier.toLowerCase() === 'body') {
|
|
53
|
+
return id;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const ctxIds = store.entityIndex.byType.get('IFCGEOMETRICREPRESENTATIONCONTEXT') ?? [];
|
|
57
|
+
for (const id of ctxIds) {
|
|
58
|
+
const ref = store.entityIndex.byId.get(id);
|
|
59
|
+
if (!ref)
|
|
60
|
+
continue;
|
|
61
|
+
const entity = extractor.extractEntity(ref);
|
|
62
|
+
const dimension = entity?.attributes?.[2];
|
|
63
|
+
if (typeof dimension === 'number' && dimension === 3) {
|
|
64
|
+
return id;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return ctxIds[0] ?? null;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Prefer an IfcGeometricRepresentationSubContext with ContextIdentifier='Axis';
|
|
71
|
+
* otherwise fall back to the first 3D IfcGeometricRepresentationContext.
|
|
72
|
+
*/
|
|
73
|
+
function findAxisContextId(store) {
|
|
74
|
+
if (!store.source)
|
|
75
|
+
return null;
|
|
76
|
+
const extractor = new EntityExtractor(store.source);
|
|
77
|
+
const subIds = store.entityIndex.byType.get('IFCGEOMETRICREPRESENTATIONSUBCONTEXT') ?? [];
|
|
78
|
+
for (const id of subIds) {
|
|
79
|
+
const ref = store.entityIndex.byId.get(id);
|
|
80
|
+
if (!ref)
|
|
81
|
+
continue;
|
|
82
|
+
const entity = extractor.extractEntity(ref);
|
|
83
|
+
const identifier = entity?.attributes?.[1];
|
|
84
|
+
if (typeof identifier === 'string' && identifier.toLowerCase() === 'axis') {
|
|
85
|
+
return id;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
const ctxIds = store.entityIndex.byType.get('IFCGEOMETRICREPRESENTATIONCONTEXT') ?? [];
|
|
89
|
+
for (const id of ctxIds) {
|
|
90
|
+
const ref = store.entityIndex.byId.get(id);
|
|
91
|
+
if (!ref)
|
|
92
|
+
continue;
|
|
93
|
+
const entity = extractor.extractEntity(ref);
|
|
94
|
+
const dimension = entity?.attributes?.[2];
|
|
95
|
+
if (typeof dimension === 'number' && dimension === 3) {
|
|
96
|
+
return id;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return ctxIds[0] ?? null;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Resolve the target storey's `ObjectPlacement` (an IfcLocalPlacement).
|
|
103
|
+
*
|
|
104
|
+
* The attribute lives at the same positional index across IFC2X3 and IFC4
|
|
105
|
+
* (inherited from IfcProduct), but rather than hard-code an offset we walk
|
|
106
|
+
* the schema-resolved attribute name list — that way the lookup keeps
|
|
107
|
+
* working if the schema gen ever shifts inheritance.
|
|
108
|
+
*/
|
|
109
|
+
function findStoreyPlacementId(store, storeyExpressId) {
|
|
110
|
+
if (!store.source)
|
|
111
|
+
return null;
|
|
112
|
+
const ref = store.entityIndex.byId.get(storeyExpressId);
|
|
113
|
+
if (!ref)
|
|
114
|
+
return null;
|
|
115
|
+
const extractor = new EntityExtractor(store.source);
|
|
116
|
+
const entity = extractor.extractEntity(ref);
|
|
117
|
+
if (!entity)
|
|
118
|
+
return null;
|
|
119
|
+
const attrNames = getAttributeNames(entity.type);
|
|
120
|
+
const placementIndex = attrNames.indexOf('ObjectPlacement');
|
|
121
|
+
const idx = placementIndex >= 0 ? placementIndex : 5;
|
|
122
|
+
const placement = entity.attributes?.[idx];
|
|
123
|
+
return typeof placement === 'number' ? placement : null;
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=resolve-anchor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-anchor.js","sourceRoot":"","sources":["../../src/in-store/resolve-anchor.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D;;;;;;;GAOG;AAEH,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAqB,MAAM,kBAAkB,CAAC;AAGzF,MAAM,UAAU,oBAAoB,CAAC,KAAmB,EAAE,eAAuB;IAC/E,MAAM,cAAc,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;IACjD,IAAI,cAAc,KAAK,IAAI,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;IAC7E,CAAC;IAED,MAAM,aAAa,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;IAC/C,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,gGAAgG,CAAC,CAAC;IACpH,CAAC;IAED,MAAM,aAAa,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;IAC/C,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,gGAAgG,CAAC,CAAC;IACpH,CAAC;IAGD,MAAM,iBAAiB,GAAG,qBAAqB,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC;IACxE,IAAI,iBAAiB,KAAK,IAAI,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,iCAAiC,eAAe,sCAAsC,CAAC,CAAC;IAC1G,CAAC;IAED,MAAM,MAAM,GAAG,CAAC,KAAK,CAAC,aAAa,IAAI,MAAM,CAAwB,CAAC;IACtE,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,aAAa,EAAE,QAAQ,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,EAAE,CAAC;AAChH,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAmB;IAC7C,MAAM,GAAG,GAAG,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IAC5D,OAAO,GAAG,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAC/C,CAAC;AAED;;;GAGG;AACH,SAAS,iBAAiB,CAAC,KAAmB;IAC5C,IAAI,CAAC,KAAK,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAC/B,MAAM,SAAS,GAAG,IAAI,eAAe,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACpD,MAAM,MAAM,GAAG,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,sCAAsC,CAAC,IAAI,EAAE,CAAC;IAC1F,KAAK,MAAM,EAAE,IAAI,MAAM,EAAE,CAAC;QACxB,MAAM,GAAG,GAAG,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC3C,IAAI,CAAC,GAAG;YAAE,SAAS;QACnB,MAAM,MAAM,GAAG,SAAS,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;QAC5C,MAAM,UAAU,GAAG,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC;QAC3C,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,CAAC,WAAW,EAAE,KAAK,MAAM,EAAE,CAAC;YAC1E,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,mCAAmC,CAAC,IAAI,EAAE,CAAC;IACvF,KAAK,MAAM,EAAE,IAAI,MAAM,EAAE,CAAC;QACxB,MAAM,GAAG,GAAG,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC3C,IAAI,CAAC,GAAG;YAAE,SAAS;QACnB,MAAM,MAAM,GAAG,SAAS,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;QAC5C,MAAM,SAAS,GAAG,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC;QAC1C,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,KAAK,CAAC,EAAE,CAAC;YACrD,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;AAC3B,CAAC;AAED;;;GAGG;AACH,SAAS,iBAAiB,CAAC,KAAmB;IAC5C,IAAI,CAAC,KAAK,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAC/B,MAAM,SAAS,GAAG,IAAI,eAAe,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAEpD,MAAM,MAAM,GAAG,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,sCAAsC,CAAC,IAAI,EAAE,CAAC;IAC1F,KAAK,MAAM,EAAE,IAAI,MAAM,EAAE,CAAC;QACxB,MAAM,GAAG,GAAG,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC3C,IAAI,CAAC,GAAG;YAAE,SAAS;QACnB,MAAM,MAAM,GAAG,SAAS,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;QAC5C,MAAM,UAAU,GAAG,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC;QAC3C,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,CAAC,WAAW,EAAE,KAAK,MAAM,EAAE,CAAC;YAC1E,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,mCAAmC,CAAC,IAAI,EAAE,CAAC;IACvF,KAAK,MAAM,EAAE,IAAI,MAAM,EAAE,CAAC;QACxB,MAAM,GAAG,GAAG,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC3C,IAAI,CAAC,GAAG;YAAE,SAAS;QACnB,MAAM,MAAM,GAAG,SAAS,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;QAC5C,MAAM,SAAS,GAAG,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC;QAC1C,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,KAAK,CAAC,EAAE,CAAC;YACrD,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;AAC3B,CAAC;AAGD;;;;;;;GAOG;AACH,SAAS,qBAAqB,CAAC,KAAmB,EAAE,eAAuB;IACzE,IAAI,CAAC,KAAK,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAC/B,MAAM,GAAG,GAAG,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IACxD,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IACtB,MAAM,SAAS,GAAG,IAAI,eAAe,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACpD,MAAM,MAAM,GAAG,SAAS,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IAC5C,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAEzB,MAAM,SAAS,GAAG,iBAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACjD,MAAM,cAAc,GAAG,SAAS,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAC5D,MAAM,GAAG,GAAG,cAAc,IAAI,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;IAErD,MAAM,SAAS,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC,GAAG,CAAC,CAAC;IAC3C,OAAO,OAAO,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;AAC1D,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pull the `SourceAttributes` shape consumed by `duplicateInStore`
|
|
3
|
+
* from a parsed `IfcDataStore`. Resolves the source entity's
|
|
4
|
+
* positional attributes, walks the placement chain to find its
|
|
5
|
+
* cartesian-point location and parent placement, and looks up the
|
|
6
|
+
* containing storey.
|
|
7
|
+
*
|
|
8
|
+
* Lives in @ifc-lite/create alongside the in-store builders so the
|
|
9
|
+
* backend layer can call it without needing parser internals.
|
|
10
|
+
*/
|
|
11
|
+
import { type IfcDataStore } from '@ifc-lite/parser';
|
|
12
|
+
import type { SourceAttributes } from './duplicate.js';
|
|
13
|
+
/**
|
|
14
|
+
* Resolve everything `duplicateInStore` needs to clone a source
|
|
15
|
+
* IfcRoot product. Throws when the source isn't an IfcProduct
|
|
16
|
+
* (no ObjectPlacement at index 5).
|
|
17
|
+
*/
|
|
18
|
+
export declare function resolveDuplicateSource(store: IfcDataStore, sourceExpressId: number): SourceAttributes;
|
|
19
|
+
//# sourceMappingURL=resolve-source.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-source.d.ts","sourceRoot":"","sources":["../../src/in-store/resolve-source.ts"],"names":[],"mappings":"AAIA;;;;;;;;;GASG;AAEH,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEtE,OAAO,KAAK,EAAE,gBAAgB,EAA2B,MAAM,gBAAgB,CAAC;AAyChF;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,YAAY,EACnB,eAAe,EAAE,MAAM,GACtB,gBAAgB,CAoGlB"}
|
|
@@ -0,0 +1,203 @@
|
|
|
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
|
+
/**
|
|
5
|
+
* Pull the `SourceAttributes` shape consumed by `duplicateInStore`
|
|
6
|
+
* from a parsed `IfcDataStore`. Resolves the source entity's
|
|
7
|
+
* positional attributes, walks the placement chain to find its
|
|
8
|
+
* cartesian-point location and parent placement, and looks up the
|
|
9
|
+
* containing storey.
|
|
10
|
+
*
|
|
11
|
+
* Lives in @ifc-lite/create alongside the in-store builders so the
|
|
12
|
+
* backend layer can call it without needing parser internals.
|
|
13
|
+
*/
|
|
14
|
+
import { EntityExtractor } from '@ifc-lite/parser';
|
|
15
|
+
/**
|
|
16
|
+
* Rel types whose `RelatedObjects` list is replayed against a
|
|
17
|
+
* duplicate so the export carries the same psets / qsets / material /
|
|
18
|
+
* classifications / documents / type binding as the source.
|
|
19
|
+
*
|
|
20
|
+
* `IFCRELCONTAINEDINSPATIALSTRUCTURE` is intentionally excluded — the
|
|
21
|
+
* duplicate flow already emits a fresh one anchored to the source's
|
|
22
|
+
* storey (see `duplicate.ts` step 5).
|
|
23
|
+
*/
|
|
24
|
+
const ASSOCIATION_REL_TYPES = [
|
|
25
|
+
'IFCRELDEFINESBYPROPERTIES', // psets + qsets (RelatingPropertyDefinition)
|
|
26
|
+
'IFCRELDEFINESBYTYPE', // type binding
|
|
27
|
+
'IFCRELASSOCIATESMATERIAL',
|
|
28
|
+
'IFCRELASSOCIATESCLASSIFICATION',
|
|
29
|
+
'IFCRELASSOCIATESDOCUMENT',
|
|
30
|
+
];
|
|
31
|
+
function asString(v) {
|
|
32
|
+
if (v === null || v === undefined)
|
|
33
|
+
return '$';
|
|
34
|
+
if (typeof v === 'number')
|
|
35
|
+
return `#${v}`;
|
|
36
|
+
if (typeof v === 'string')
|
|
37
|
+
return v;
|
|
38
|
+
return '$';
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Like asString but maps the omitted-token sentinel (`$`) to `null`.
|
|
42
|
+
* The editor serialises plain strings as quoted STEP literals, so the
|
|
43
|
+
* verbatim `'$'` would land as `'$'` in output instead of the bare token.
|
|
44
|
+
*/
|
|
45
|
+
function asRefOrNull(v) {
|
|
46
|
+
const s = asString(v);
|
|
47
|
+
return s === '$' ? null : s;
|
|
48
|
+
}
|
|
49
|
+
function asNumber(v) {
|
|
50
|
+
if (typeof v === 'number')
|
|
51
|
+
return v;
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Resolve everything `duplicateInStore` needs to clone a source
|
|
56
|
+
* IfcRoot product. Throws when the source isn't an IfcProduct
|
|
57
|
+
* (no ObjectPlacement at index 5).
|
|
58
|
+
*/
|
|
59
|
+
export function resolveDuplicateSource(store, sourceExpressId) {
|
|
60
|
+
if (!store.source) {
|
|
61
|
+
throw new Error('resolveDuplicateSource: data store has no source bytes');
|
|
62
|
+
}
|
|
63
|
+
const sourceRef = store.entityIndex.byId.get(sourceExpressId);
|
|
64
|
+
if (!sourceRef) {
|
|
65
|
+
throw new Error(`resolveDuplicateSource: entity #${sourceExpressId} not found`);
|
|
66
|
+
}
|
|
67
|
+
const extractor = new EntityExtractor(store.source);
|
|
68
|
+
const sourceEntity = extractor.extractEntity(sourceRef);
|
|
69
|
+
if (!sourceEntity) {
|
|
70
|
+
throw new Error(`resolveDuplicateSource: could not parse #${sourceExpressId}`);
|
|
71
|
+
}
|
|
72
|
+
const attrs = sourceEntity.attributes;
|
|
73
|
+
// OwnerHistory is optional in IFC4, so null is a valid round-trip
|
|
74
|
+
// value here. The duplicate flow re-emits null on the new entity.
|
|
75
|
+
const ownerHistoryId = asNumber(attrs[1]);
|
|
76
|
+
const placementId = asNumber(attrs[5]);
|
|
77
|
+
const representationId = asNumber(attrs[6]);
|
|
78
|
+
if (placementId === null) {
|
|
79
|
+
throw new Error(`resolveDuplicateSource: #${sourceExpressId} has no ObjectPlacement — only IfcProduct can be duplicated`);
|
|
80
|
+
}
|
|
81
|
+
const placementRef = store.entityIndex.byId.get(placementId);
|
|
82
|
+
if (!placementRef) {
|
|
83
|
+
throw new Error(`resolveDuplicateSource: placement #${placementId} missing from index`);
|
|
84
|
+
}
|
|
85
|
+
const placementEntity = extractor.extractEntity(placementRef);
|
|
86
|
+
if (!placementEntity) {
|
|
87
|
+
throw new Error(`resolveDuplicateSource: could not parse placement #${placementId}`);
|
|
88
|
+
}
|
|
89
|
+
const parentPlacementId = asNumber(placementEntity.attributes[0]); // PlacementRelTo
|
|
90
|
+
const axisPlacementId = asNumber(placementEntity.attributes[1]); // RelativePlacement
|
|
91
|
+
if (axisPlacementId === null) {
|
|
92
|
+
throw new Error(`resolveDuplicateSource: placement #${placementId} has no RelativePlacement`);
|
|
93
|
+
}
|
|
94
|
+
const axisPlacementRef = store.entityIndex.byId.get(axisPlacementId);
|
|
95
|
+
if (!axisPlacementRef) {
|
|
96
|
+
throw new Error(`resolveDuplicateSource: axis placement #${axisPlacementId} missing`);
|
|
97
|
+
}
|
|
98
|
+
const axisEntity = extractor.extractEntity(axisPlacementRef);
|
|
99
|
+
if (!axisEntity) {
|
|
100
|
+
throw new Error(`resolveDuplicateSource: could not parse axis #${axisPlacementId}`);
|
|
101
|
+
}
|
|
102
|
+
const locationId = asNumber(axisEntity.attributes[0]); // Location → IfcCartesianPoint
|
|
103
|
+
const axisRef = asRefOrNull(axisEntity.attributes[1]); // Axis (optional)
|
|
104
|
+
const refDirectionRef = asRefOrNull(axisEntity.attributes[2]); // RefDirection (optional)
|
|
105
|
+
let sourceLocation = [0, 0, 0];
|
|
106
|
+
if (locationId !== null) {
|
|
107
|
+
const pointRef = store.entityIndex.byId.get(locationId);
|
|
108
|
+
if (pointRef) {
|
|
109
|
+
const pointEntity = extractor.extractEntity(pointRef);
|
|
110
|
+
const coords = pointEntity?.attributes[0];
|
|
111
|
+
if (Array.isArray(coords)) {
|
|
112
|
+
sourceLocation = [
|
|
113
|
+
asNumber(coords[0]) ?? 0,
|
|
114
|
+
asNumber(coords[1]) ?? 0,
|
|
115
|
+
asNumber(coords[2]) ?? 0,
|
|
116
|
+
];
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
// Containing storey lookup via the pre-built spatial hierarchy.
|
|
121
|
+
// Falls back to null when the entity sits outside the spatial tree.
|
|
122
|
+
const storeyId = store.spatialHierarchy?.elementToStorey?.get(sourceExpressId) ?? null;
|
|
123
|
+
// Association rels that reference the source — replayed against
|
|
124
|
+
// the duplicate by `duplicateInStore` so the exported STEP carries
|
|
125
|
+
// the same psets / qsets / material / classifications / documents
|
|
126
|
+
// / type binding.
|
|
127
|
+
const associations = collectSourceAssociations(store, extractor, sourceExpressId);
|
|
128
|
+
return {
|
|
129
|
+
// Canonical PascalCase (e.g. "IfcWall"); falls back to the raw
|
|
130
|
+
// extractor type when the entity table doesn't recognise the id
|
|
131
|
+
// (vendor extensions etc).
|
|
132
|
+
type: store.entities.getTypeName(sourceExpressId) || sourceEntity.type,
|
|
133
|
+
attributes: attrs,
|
|
134
|
+
placementExpressId: placementId,
|
|
135
|
+
parentPlacementId,
|
|
136
|
+
sourceLocation,
|
|
137
|
+
representationId,
|
|
138
|
+
ownerHistoryId,
|
|
139
|
+
axisRef,
|
|
140
|
+
refDirectionRef,
|
|
141
|
+
storeyId,
|
|
142
|
+
associations,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Walk the parsed entity index for every association rel type and
|
|
147
|
+
* gather the ones whose `RelatedObjects` list contains `sourceId`.
|
|
148
|
+
* Returns one `SourceAssociation` per matching rel — duplicate flow
|
|
149
|
+
* emits a fresh rel of the same type pointing at the duplicate.
|
|
150
|
+
*/
|
|
151
|
+
function collectSourceAssociations(store, extractor, sourceId) {
|
|
152
|
+
const out = [];
|
|
153
|
+
for (const relType of ASSOCIATION_REL_TYPES) {
|
|
154
|
+
const ids = store.entityIndex.byType.get(relType);
|
|
155
|
+
if (!ids || ids.length === 0)
|
|
156
|
+
continue;
|
|
157
|
+
for (const relId of ids) {
|
|
158
|
+
const ref = store.entityIndex.byId.get(relId);
|
|
159
|
+
if (!ref)
|
|
160
|
+
continue;
|
|
161
|
+
const entity = extractor.extractEntity(ref);
|
|
162
|
+
if (!entity)
|
|
163
|
+
continue;
|
|
164
|
+
const related = entity.attributes[4];
|
|
165
|
+
// RelatedObjects is a STEP set serialised as a JS array. The
|
|
166
|
+
// parser returns each `#N` as a plain number — we look for the
|
|
167
|
+
// source id by direct membership, not by string match.
|
|
168
|
+
if (!Array.isArray(related))
|
|
169
|
+
continue;
|
|
170
|
+
let referencesSource = false;
|
|
171
|
+
for (const member of related) {
|
|
172
|
+
if (typeof member === 'number' && member === sourceId) {
|
|
173
|
+
referencesSource = true;
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
if (!referencesSource)
|
|
178
|
+
continue;
|
|
179
|
+
const ownerHistoryId = asNumber(entity.attributes[1]);
|
|
180
|
+
const relatingExpressId = asNumber(entity.attributes[5]);
|
|
181
|
+
// RelatingPropertyDefinition / RelatingType / etc. is required
|
|
182
|
+
// by the schema, so a missing one is a hard skip. OwnerHistory
|
|
183
|
+
// is optional (IFC4) — null is fine and round-trips cleanly.
|
|
184
|
+
if (relatingExpressId === null)
|
|
185
|
+
continue;
|
|
186
|
+
const name = typeof entity.attributes[2] === 'string' ? entity.attributes[2] : null;
|
|
187
|
+
const description = typeof entity.attributes[3] === 'string' ? entity.attributes[3] : null;
|
|
188
|
+
// Use the entity table's canonical name so the duplicate replays
|
|
189
|
+
// a PascalCase type into the editor (e.g. "IfcRelDefinesByProperties"),
|
|
190
|
+
// not the byType map's UPPERCASE storage key.
|
|
191
|
+
const canonicalRelType = store.entities.getTypeName(relId) || relType;
|
|
192
|
+
out.push({
|
|
193
|
+
relType: canonicalRelType,
|
|
194
|
+
ownerHistoryId,
|
|
195
|
+
name,
|
|
196
|
+
description,
|
|
197
|
+
relatingExpressId,
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return out;
|
|
202
|
+
}
|
|
203
|
+
//# sourceMappingURL=resolve-source.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-source.js","sourceRoot":"","sources":["../../src/in-store/resolve-source.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D;;;;;;;;;GASG;AAEH,OAAO,EAAE,eAAe,EAAqB,MAAM,kBAAkB,CAAC;AAItE;;;;;;;;GAQG;AACH,MAAM,qBAAqB,GAAG;IAC5B,2BAA2B,EAAM,6CAA6C;IAC9E,qBAAqB,EAAY,eAAe;IAChD,0BAA0B;IAC1B,gCAAgC;IAChC,0BAA0B;CAClB,CAAC;AAEX,SAAS,QAAQ,CAAC,CAAgC;IAChD,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,SAAS;QAAE,OAAO,GAAG,CAAC;IAC9C,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC,EAAE,CAAC;IAC1C,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,CAAC,CAAC;IACpC,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;GAIG;AACH,SAAS,WAAW,CAAC,CAAgC;IACnD,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IACtB,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9B,CAAC;AAED,SAAS,QAAQ,CAAC,CAAgC;IAChD,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,CAAC,CAAC;IACpC,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CACpC,KAAmB,EACnB,eAAuB;IAEvB,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;IAC5E,CAAC;IACD,MAAM,SAAS,GAAG,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAC9D,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,mCAAmC,eAAe,YAAY,CAAC,CAAC;IAClF,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,eAAe,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACpD,MAAM,YAAY,GAAG,SAAS,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;IACxD,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CAAC,4CAA4C,eAAe,EAAE,CAAC,CAAC;IACjF,CAAC;IAED,MAAM,KAAK,GAAG,YAAY,CAAC,UAAU,CAAC;IACtC,kEAAkE;IAClE,kEAAkE;IAClE,MAAM,cAAc,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1C,MAAM,WAAW,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACvC,MAAM,gBAAgB,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAE5C,IAAI,WAAW,KAAK,IAAI,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CACb,4BAA4B,eAAe,6DAA6D,CACzG,CAAC;IACJ,CAAC;IAED,MAAM,YAAY,GAAG,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC7D,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CAAC,sCAAsC,WAAW,qBAAqB,CAAC,CAAC;IAC1F,CAAC;IACD,MAAM,eAAe,GAAG,SAAS,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;IAC9D,IAAI,CAAC,eAAe,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,sDAAsD,WAAW,EAAE,CAAC,CAAC;IACvF,CAAC;IAED,MAAM,iBAAiB,GAAG,QAAQ,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAG,iBAAiB;IACtF,MAAM,eAAe,GAAG,QAAQ,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAK,oBAAoB;IACzF,IAAI,eAAe,KAAK,IAAI,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CACb,sCAAsC,WAAW,2BAA2B,CAC7E,CAAC;IACJ,CAAC;IAED,MAAM,gBAAgB,GAAG,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IACrE,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,2CAA2C,eAAe,UAAU,CAAC,CAAC;IACxF,CAAC;IACD,MAAM,UAAU,GAAG,SAAS,CAAC,aAAa,CAAC,gBAAgB,CAAC,CAAC;IAC7D,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CAAC,iDAAiD,eAAe,EAAE,CAAC,CAAC;IACtF,CAAC;IAED,MAAM,UAAU,GAAG,QAAQ,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAE,+BAA+B;IACvF,MAAM,OAAO,GAAG,WAAW,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAK,kBAAkB;IAC7E,MAAM,eAAe,GAAG,WAAW,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,0BAA0B;IAEzF,IAAI,cAAc,GAAS,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IACrC,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;QACxB,MAAM,QAAQ,GAAG,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACxD,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,WAAW,GAAG,SAAS,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;YACtD,MAAM,MAAM,GAAG,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;YAC1C,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC1B,cAAc,GAAG;oBACf,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;oBACxB,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;oBACxB,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;iBACzB,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAED,gEAAgE;IAChE,oEAAoE;IACpE,MAAM,QAAQ,GAAG,KAAK,CAAC,gBAAgB,EAAE,eAAe,EAAE,GAAG,CAAC,eAAe,CAAC,IAAI,IAAI,CAAC;IAEvF,gEAAgE;IAChE,mEAAmE;IACnE,kEAAkE;IAClE,kBAAkB;IAClB,MAAM,YAAY,GAAG,yBAAyB,CAAC,KAAK,EAAE,SAAS,EAAE,eAAe,CAAC,CAAC;IAElF,OAAO;QACL,+DAA+D;QAC/D,gEAAgE;QAChE,2BAA2B;QAC3B,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,eAAe,CAAC,IAAI,YAAY,CAAC,IAAI;QACtE,UAAU,EAAE,KAAK;QACjB,kBAAkB,EAAE,WAAW;QAC/B,iBAAiB;QACjB,cAAc;QACd,gBAAgB;QAChB,cAAc;QACd,OAAO;QACP,eAAe;QACf,QAAQ;QACR,YAAY;KACb,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAS,yBAAyB,CAChC,KAAmB,EACnB,SAA0B,EAC1B,QAAgB;IAEhB,MAAM,GAAG,GAAwB,EAAE,CAAC;IACpC,KAAK,MAAM,OAAO,IAAI,qBAAqB,EAAE,CAAC;QAC5C,MAAM,GAAG,GAAG,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAClD,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QACvC,KAAK,MAAM,KAAK,IAAI,GAAG,EAAE,CAAC;YACxB,MAAM,GAAG,GAAG,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAC9C,IAAI,CAAC,GAAG;gBAAE,SAAS;YACnB,MAAM,MAAM,GAAG,SAAS,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;YAC5C,IAAI,CAAC,MAAM;gBAAE,SAAS;YAEtB,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;YACrC,6DAA6D;YAC7D,+DAA+D;YAC/D,uDAAuD;YACvD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;gBAAE,SAAS;YACtC,IAAI,gBAAgB,GAAG,KAAK,CAAC;YAC7B,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;gBAC7B,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;oBACtD,gBAAgB,GAAG,IAAI,CAAC;oBACxB,MAAM;gBACR,CAAC;YACH,CAAC;YACD,IAAI,CAAC,gBAAgB;gBAAE,SAAS;YAEhC,MAAM,cAAc,GAAG,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;YACtD,MAAM,iBAAiB,GAAG,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;YACzD,+DAA+D;YAC/D,+DAA+D;YAC/D,6DAA6D;YAC7D,IAAI,iBAAiB,KAAK,IAAI;gBAAE,SAAS;YAEzC,MAAM,IAAI,GAAG,OAAO,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YACpF,MAAM,WAAW,GAAG,OAAO,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAE3F,iEAAiE;YACjE,wEAAwE;YACxE,8CAA8C;YAC9C,MAAM,gBAAgB,GAAG,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC;YACtE,GAAG,CAAC,IAAI,CAAC;gBACP,OAAO,EAAE,gBAAgB;gBACzB,cAAc;gBACd,IAAI;gBACJ,WAAW;gBACX,iBAAiB;aAClB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|