@pascal-app/core 0.9.2 → 1.0.0-beta.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/README.md +17 -10
- package/dist/events/bus.d.ts +21 -2
- package/dist/events/bus.d.ts.map +1 -1
- package/dist/hooks/spatial-grid/floor-placed-elevation.d.ts +17 -1
- package/dist/hooks/spatial-grid/floor-placed-elevation.d.ts.map +1 -1
- package/dist/hooks/spatial-grid/floor-placed-elevation.js +61 -8
- package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts +116 -66
- package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts.map +1 -1
- package/dist/hooks/spatial-grid/spatial-grid-manager.js +316 -441
- package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts +46 -1
- package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts.map +1 -1
- package/dist/hooks/spatial-grid/spatial-grid-sync.js +193 -12
- package/dist/hooks/spatial-grid/support-host-id.d.ts +3 -0
- package/dist/hooks/spatial-grid/support-host-id.d.ts.map +1 -0
- package/dist/hooks/spatial-grid/support-host-id.js +2 -0
- package/dist/hooks/spatial-grid/support-host-patch.d.ts +51 -0
- package/dist/hooks/spatial-grid/support-host-patch.d.ts.map +1 -0
- package/dist/hooks/spatial-grid/support-host-patch.js +164 -0
- package/dist/index.d.ts +23 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -10
- package/dist/lib/measurement-geometry.d.ts +4 -0
- package/dist/lib/measurement-geometry.d.ts.map +1 -1
- package/dist/lib/measurement-geometry.js +27 -10
- package/dist/lib/slab-polygon.d.ts.map +1 -1
- package/dist/lib/slab-polygon.js +33 -1
- package/dist/lib/space-detection.d.ts +15 -4
- package/dist/lib/space-detection.d.ts.map +1 -1
- package/dist/lib/space-detection.js +174 -88
- package/dist/lib/terrain-brush.d.ts +163 -0
- package/dist/lib/terrain-brush.d.ts.map +1 -0
- package/dist/lib/terrain-brush.js +359 -0
- package/dist/lib/terrain-codec.d.ts +51 -0
- package/dist/lib/terrain-codec.d.ts.map +1 -0
- package/dist/lib/terrain-codec.js +167 -0
- package/dist/lib/terrain-field.d.ts +150 -0
- package/dist/lib/terrain-field.d.ts.map +1 -0
- package/dist/lib/terrain-field.js +248 -0
- package/dist/lib/terrain-raycast.d.ts +44 -0
- package/dist/lib/terrain-raycast.d.ts.map +1 -0
- package/dist/lib/terrain-raycast.js +188 -0
- package/dist/lib/terrain-source.d.ts +60 -0
- package/dist/lib/terrain-source.d.ts.map +1 -0
- package/dist/lib/terrain-source.js +90 -0
- package/dist/lib/terrain-support.d.ts +60 -0
- package/dist/lib/terrain-support.d.ts.map +1 -0
- package/dist/lib/terrain-support.js +150 -0
- package/dist/lib/zone-quantities.d.ts +1 -1
- package/dist/lib/zone-quantities.d.ts.map +1 -1
- package/dist/lib/zone-quantities.js +311 -66
- package/dist/material-library.d.ts +9 -1
- package/dist/material-library.d.ts.map +1 -1
- package/dist/material-library.js +56 -4
- package/dist/registry/handles.d.ts +16 -1
- package/dist/registry/handles.d.ts.map +1 -1
- package/dist/registry/index.d.ts +1 -1
- package/dist/registry/index.d.ts.map +1 -1
- package/dist/registry/subtree.d.ts.map +1 -1
- package/dist/registry/subtree.js +5 -2
- package/dist/registry/types.d.ts +64 -1
- package/dist/registry/types.d.ts.map +1 -1
- package/dist/schema/index.d.ts +6 -3
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +6 -3
- package/dist/schema/nodes/cabinet.d.ts +2 -0
- package/dist/schema/nodes/cabinet.d.ts.map +1 -1
- package/dist/schema/nodes/cabinet.js +4 -2
- package/dist/schema/nodes/ceiling.d.ts +1 -1
- package/dist/schema/nodes/ceiling.d.ts.map +1 -1
- package/dist/schema/nodes/ceiling.js +7 -1
- package/dist/schema/nodes/column.d.ts +1 -0
- package/dist/schema/nodes/column.d.ts.map +1 -1
- package/dist/schema/nodes/column.js +2 -0
- package/dist/schema/nodes/construction-dimension.d.ts +195 -0
- package/dist/schema/nodes/construction-dimension.d.ts.map +1 -0
- package/dist/schema/nodes/construction-dimension.js +151 -0
- package/dist/schema/nodes/door.d.ts +29 -0
- package/dist/schema/nodes/door.d.ts.map +1 -1
- package/dist/schema/nodes/door.js +20 -0
- package/dist/schema/nodes/duct-terminal.d.ts +1 -0
- package/dist/schema/nodes/duct-terminal.d.ts.map +1 -1
- package/dist/schema/nodes/duct-terminal.js +2 -0
- package/dist/schema/nodes/fence.d.ts +2 -0
- package/dist/schema/nodes/fence.d.ts.map +1 -1
- package/dist/schema/nodes/fence.js +8 -0
- package/dist/schema/nodes/hvac-equipment.d.ts +1 -0
- package/dist/schema/nodes/hvac-equipment.d.ts.map +1 -1
- package/dist/schema/nodes/hvac-equipment.js +2 -0
- package/dist/schema/nodes/item.d.ts +1 -0
- package/dist/schema/nodes/item.d.ts.map +1 -1
- package/dist/schema/nodes/item.js +13 -0
- package/dist/schema/nodes/level.d.ts +2 -1
- package/dist/schema/nodes/level.d.ts.map +1 -1
- package/dist/schema/nodes/level.js +12 -33
- package/dist/schema/nodes/shelf.d.ts +1 -0
- package/dist/schema/nodes/shelf.d.ts.map +1 -1
- package/dist/schema/nodes/shelf.js +2 -0
- package/dist/schema/nodes/site.d.ts +9 -0
- package/dist/schema/nodes/site.d.ts.map +1 -1
- package/dist/schema/nodes/site.js +8 -6
- package/dist/schema/nodes/slab.d.ts +5 -0
- package/dist/schema/nodes/slab.d.ts.map +1 -1
- package/dist/schema/nodes/slab.js +14 -2
- package/dist/schema/nodes/spawn.d.ts +1 -0
- package/dist/schema/nodes/spawn.d.ts.map +1 -1
- package/dist/schema/nodes/spawn.js +2 -0
- package/dist/schema/nodes/stair.d.ts +3 -1
- package/dist/schema/nodes/stair.d.ts.map +1 -1
- package/dist/schema/nodes/stair.js +8 -1
- package/dist/schema/nodes/structural-grid.d.ts +27 -0
- package/dist/schema/nodes/structural-grid.d.ts.map +1 -0
- package/dist/schema/nodes/structural-grid.js +17 -0
- package/dist/schema/nodes/wall.d.ts +5 -2
- package/dist/schema/nodes/wall.d.ts.map +1 -1
- package/dist/schema/nodes/wall.js +13 -4
- package/dist/schema/nodes/window.d.ts +29 -0
- package/dist/schema/nodes/window.d.ts.map +1 -1
- package/dist/schema/nodes/window.js +18 -0
- package/dist/schema/nodes/zone.d.ts +20 -0
- package/dist/schema/nodes/zone.d.ts.map +1 -1
- package/dist/schema/nodes/zone.js +15 -0
- package/dist/schema/terrain.d.ts +28 -0
- package/dist/schema/terrain.d.ts.map +1 -0
- package/dist/schema/terrain.js +30 -0
- package/dist/schema/types.d.ts +211 -3
- package/dist/schema/types.d.ts.map +1 -1
- package/dist/schema/types.js +4 -0
- package/dist/services/__fixtures__/wall-plane-top-boundary-repro.d.ts +80 -0
- package/dist/services/__fixtures__/wall-plane-top-boundary-repro.d.ts.map +1 -0
- package/dist/services/__fixtures__/wall-plane-top-boundary-repro.js +89 -0
- package/dist/services/index.d.ts +2 -1
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/index.js +2 -1
- package/dist/services/level-height.d.ts +8 -9
- package/dist/services/level-height.d.ts.map +1 -1
- package/dist/services/level-height.js +48 -16
- package/dist/services/storey.d.ts +103 -0
- package/dist/services/storey.d.ts.map +1 -0
- package/dist/services/storey.js +296 -0
- package/dist/store/actions/node-actions.d.ts.map +1 -1
- package/dist/store/actions/node-actions.js +47 -3
- package/dist/store/history-control.d.ts +20 -0
- package/dist/store/history-control.d.ts.map +1 -1
- package/dist/store/history-control.js +110 -13
- package/dist/store/use-live-terrain.d.ts +65 -0
- package/dist/store/use-live-terrain.d.ts.map +1 -0
- package/dist/store/use-live-terrain.js +31 -0
- package/dist/store/use-live-transforms.d.ts +8 -0
- package/dist/store/use-live-transforms.d.ts.map +1 -1
- package/dist/store/use-scene.d.ts +31 -2
- package/dist/store/use-scene.d.ts.map +1 -1
- package/dist/store/use-scene.js +638 -8
- package/dist/systems/elevator/elevator-opening-system.d.ts +1 -0
- package/dist/systems/elevator/elevator-opening-system.d.ts.map +1 -1
- package/dist/systems/elevator/elevator-opening-system.js +27 -21
- package/dist/systems/elevator/elevator-service.d.ts +0 -2
- package/dist/systems/elevator/elevator-service.d.ts.map +1 -1
- package/dist/systems/elevator/elevator-service.js +2 -24
- package/dist/systems/slab/slab-placement.d.ts +11 -0
- package/dist/systems/slab/slab-placement.d.ts.map +1 -0
- package/dist/systems/slab/slab-placement.js +14 -0
- package/dist/systems/slab/slab-support.d.ts +137 -0
- package/dist/systems/slab/slab-support.d.ts.map +1 -0
- package/dist/systems/slab/slab-support.js +557 -0
- package/dist/systems/stair/stair-opening-preview.d.ts +1060 -935
- package/dist/systems/stair/stair-opening-preview.d.ts.map +1 -1
- package/dist/systems/stair/stair-opening-sync.d.ts.map +1 -1
- package/dist/systems/stair/stair-opening-sync.js +18 -15
- package/dist/systems/stair/stair-opening-system.d.ts.map +1 -1
- package/dist/systems/stair/stair-opening-system.js +32 -4
- package/dist/systems/stair/stair-rise.d.ts +22 -0
- package/dist/systems/stair/stair-rise.d.ts.map +1 -0
- package/dist/systems/stair/stair-rise.js +79 -0
- package/dist/systems/wall/wall-curve.d.ts +10 -0
- package/dist/systems/wall/wall-curve.d.ts.map +1 -1
- package/dist/systems/wall/wall-curve.js +1 -1
- package/dist/systems/wall/wall-mitering.js +6 -6
- package/dist/systems/wall/wall-top.d.ts +40 -0
- package/dist/systems/wall/wall-top.d.ts.map +1 -0
- package/dist/systems/wall/wall-top.js +46 -0
- package/dist/utils/clone-scene-graph.d.ts.map +1 -1
- package/dist/utils/clone-scene-graph.js +34 -3
- package/dist/utils/heal-scene-graph.d.ts +1 -1
- package/dist/utils/heal-scene-graph.d.ts.map +1 -1
- package/dist/utils/heal-scene-graph.js +25 -9
- package/dist/validation/validate-build-json.d.ts +2 -0
- package/dist/validation/validate-build-json.d.ts.map +1 -1
- package/dist/validation/validate-build-json.js +59 -3
- package/package.json +2 -2
- package/dist/hooks/scene-registry/scene-registry.test.d.ts +0 -2
- package/dist/hooks/scene-registry/scene-registry.test.d.ts.map +0 -1
- package/dist/hooks/scene-registry/scene-registry.test.js +0 -26
- package/dist/hooks/spatial-grid/floor-placed-elevation.test.d.ts +0 -2
- package/dist/hooks/spatial-grid/floor-placed-elevation.test.d.ts.map +0 -1
- package/dist/hooks/spatial-grid/floor-placed-elevation.test.js +0 -366
- package/dist/hooks/spatial-grid/wall-slab-overlap.test.d.ts +0 -2
- package/dist/hooks/spatial-grid/wall-slab-overlap.test.d.ts.map +0 -1
- package/dist/hooks/spatial-grid/wall-slab-overlap.test.js +0 -363
- package/dist/lib/measurement-geometry.test.d.ts +0 -2
- package/dist/lib/measurement-geometry.test.d.ts.map +0 -1
- package/dist/lib/measurement-geometry.test.js +0 -102
- package/dist/lib/slab-polygon.test.d.ts +0 -2
- package/dist/lib/slab-polygon.test.d.ts.map +0 -1
- package/dist/lib/slab-polygon.test.js +0 -635
- package/dist/lib/space-detection-pause.test.d.ts +0 -2
- package/dist/lib/space-detection-pause.test.d.ts.map +0 -1
- package/dist/lib/space-detection-pause.test.js +0 -42
- package/dist/lib/space-detection.test.d.ts +0 -2
- package/dist/lib/space-detection.test.d.ts.map +0 -1
- package/dist/lib/space-detection.test.js +0 -376
- package/dist/lib/zone-quantities.test.d.ts +0 -2
- package/dist/lib/zone-quantities.test.d.ts.map +0 -1
- package/dist/lib/zone-quantities.test.js +0 -82
- package/dist/registry/registry.test.d.ts +0 -2
- package/dist/registry/registry.test.d.ts.map +0 -1
- package/dist/registry/registry.test.js +0 -196
- package/dist/registry/relations-resolver.test.d.ts +0 -2
- package/dist/registry/relations-resolver.test.d.ts.map +0 -1
- package/dist/registry/relations-resolver.test.js +0 -183
- package/dist/registry/scene-api.test.d.ts +0 -2
- package/dist/registry/scene-api.test.d.ts.map +0 -1
- package/dist/registry/scene-api.test.js +0 -183
- package/dist/registry/subtree.test.d.ts +0 -2
- package/dist/registry/subtree.test.d.ts.map +0 -1
- package/dist/registry/subtree.test.js +0 -163
- package/dist/schema/asset-url.test.d.ts +0 -2
- package/dist/schema/asset-url.test.d.ts.map +0 -1
- package/dist/schema/asset-url.test.js +0 -134
- package/dist/schema/material.test.d.ts +0 -2
- package/dist/schema/material.test.d.ts.map +0 -1
- package/dist/schema/material.test.js +0 -43
- package/dist/schema/nodes/measurement.test.d.ts +0 -2
- package/dist/schema/nodes/measurement.test.d.ts.map +0 -1
- package/dist/schema/nodes/measurement.test.js +0 -139
- package/dist/schema/nodes/ridge-vent-defaults.test.d.ts +0 -2
- package/dist/schema/nodes/ridge-vent-defaults.test.d.ts.map +0 -1
- package/dist/schema/nodes/ridge-vent-defaults.test.js +0 -205
- package/dist/schema/nodes/roof-segment-shape.test.d.ts +0 -2
- package/dist/schema/nodes/roof-segment-shape.test.d.ts.map +0 -1
- package/dist/schema/nodes/roof-segment-shape.test.js +0 -175
- package/dist/schema/nodes/roof-segment-surface.test.d.ts +0 -2
- package/dist/schema/nodes/roof-segment-surface.test.d.ts.map +0 -1
- package/dist/schema/nodes/roof-segment-surface.test.js +0 -48
- package/dist/schema/nodes/roof-segment-trim.test.d.ts +0 -2
- package/dist/schema/nodes/roof-segment-trim.test.d.ts.map +0 -1
- package/dist/schema/nodes/roof-segment-trim.test.js +0 -107
- package/dist/schema/nodes/roof-segment-walls.test.d.ts +0 -2
- package/dist/schema/nodes/roof-segment-walls.test.d.ts.map +0 -1
- package/dist/schema/nodes/roof-segment-walls.test.js +0 -92
- package/dist/schema/nodes/wall.test.d.ts +0 -2
- package/dist/schema/nodes/wall.test.d.ts.map +0 -1
- package/dist/schema/nodes/wall.test.js +0 -208
- package/dist/services/alignment-anchors.test.d.ts +0 -2
- package/dist/services/alignment-anchors.test.d.ts.map +0 -1
- package/dist/services/alignment-anchors.test.js +0 -383
- package/dist/services/alignment.test.d.ts +0 -2
- package/dist/services/alignment.test.d.ts.map +0 -1
- package/dist/services/alignment.test.js +0 -92
- package/dist/services/drag-session.test.d.ts +0 -2
- package/dist/services/drag-session.test.d.ts.map +0 -1
- package/dist/services/drag-session.test.js +0 -219
- package/dist/services/hosting.test.d.ts +0 -2
- package/dist/services/hosting.test.d.ts.map +0 -1
- package/dist/services/hosting.test.js +0 -230
- package/dist/services/movement.test.d.ts +0 -2
- package/dist/services/movement.test.d.ts.map +0 -1
- package/dist/services/movement.test.js +0 -133
- package/dist/services/opening-guides.test.d.ts +0 -2
- package/dist/services/opening-guides.test.d.ts.map +0 -1
- package/dist/services/opening-guides.test.js +0 -208
- package/dist/services/port-connectivity.test.d.ts +0 -2
- package/dist/services/port-connectivity.test.d.ts.map +0 -1
- package/dist/services/port-connectivity.test.js +0 -297
- package/dist/services/riser-diagram.test.d.ts +0 -2
- package/dist/services/riser-diagram.test.d.ts.map +0 -1
- package/dist/services/riser-diagram.test.js +0 -66
- package/dist/services/single-undo-dance.test.d.ts +0 -2
- package/dist/services/single-undo-dance.test.d.ts.map +0 -1
- package/dist/services/single-undo-dance.test.js +0 -210
- package/dist/services/snap.test.d.ts +0 -2
- package/dist/services/snap.test.d.ts.map +0 -1
- package/dist/services/snap.test.js +0 -137
- package/dist/services/system-graph.test.d.ts +0 -2
- package/dist/services/system-graph.test.d.ts.map +0 -1
- package/dist/services/system-graph.test.js +0 -138
- package/dist/services/validate-dwv.test.d.ts +0 -2
- package/dist/services/validate-dwv.test.d.ts.map +0 -1
- package/dist/services/validate-dwv.test.js +0 -109
- package/dist/store/actions/node-mutation-sanitize.test.d.ts +0 -2
- package/dist/store/actions/node-mutation-sanitize.test.d.ts.map +0 -1
- package/dist/store/actions/node-mutation-sanitize.test.js +0 -147
- package/dist/store/actions/reparent.test.d.ts +0 -2
- package/dist/store/actions/reparent.test.d.ts.map +0 -1
- package/dist/store/actions/reparent.test.js +0 -212
- package/dist/store/actions/ridge-vent-update.test.d.ts +0 -2
- package/dist/store/actions/ridge-vent-update.test.d.ts.map +0 -1
- package/dist/store/actions/ridge-vent-update.test.js +0 -264
- package/dist/store/use-scene-dirty-tracking.test.d.ts +0 -2
- package/dist/store/use-scene-dirty-tracking.test.d.ts.map +0 -1
- package/dist/store/use-scene-dirty-tracking.test.js +0 -68
- package/dist/store/use-scene-elevator-migration.test.d.ts +0 -2
- package/dist/store/use-scene-elevator-migration.test.d.ts.map +0 -1
- package/dist/store/use-scene-elevator-migration.test.js +0 -109
- package/dist/store/use-scene-measurement-roundtrip.test.d.ts +0 -2
- package/dist/store/use-scene-measurement-roundtrip.test.d.ts.map +0 -1
- package/dist/store/use-scene-measurement-roundtrip.test.js +0 -97
- package/dist/store/use-scene-plugins.test.d.ts +0 -2
- package/dist/store/use-scene-plugins.test.d.ts.map +0 -1
- package/dist/store/use-scene-plugins.test.js +0 -51
- package/dist/store/use-scene-wall-slot-migration.test.d.ts +0 -2
- package/dist/store/use-scene-wall-slot-migration.test.d.ts.map +0 -1
- package/dist/store/use-scene-wall-slot-migration.test.js +0 -210
- package/dist/store/use-scene-window-migration.test.d.ts +0 -2
- package/dist/store/use-scene-window-migration.test.d.ts.map +0 -1
- package/dist/store/use-scene-window-migration.test.js +0 -85
- package/dist/systems/elevator/elevator-opening-sync.test.d.ts +0 -2
- package/dist/systems/elevator/elevator-opening-sync.test.d.ts.map +0 -1
- package/dist/systems/elevator/elevator-opening-sync.test.js +0 -146
- package/dist/systems/elevator/elevator-runtime.test.d.ts +0 -2
- package/dist/systems/elevator/elevator-runtime.test.d.ts.map +0 -1
- package/dist/systems/elevator/elevator-runtime.test.js +0 -64
- package/dist/systems/fence/fence-spline.test.d.ts +0 -2
- package/dist/systems/fence/fence-spline.test.d.ts.map +0 -1
- package/dist/systems/fence/fence-spline.test.js +0 -136
- package/dist/systems/stair/stair-opening-preview.test.d.ts +0 -2
- package/dist/systems/stair/stair-opening-preview.test.d.ts.map +0 -1
- package/dist/systems/stair/stair-opening-preview.test.js +0 -80
- package/dist/systems/stair/stair-opening-sync.test.d.ts +0 -2
- package/dist/systems/stair/stair-opening-sync.test.d.ts.map +0 -1
- package/dist/systems/stair/stair-opening-sync.test.js +0 -485
- package/dist/systems/wall/wall-mitering.test.d.ts +0 -2
- package/dist/systems/wall/wall-mitering.test.d.ts.map +0 -1
- package/dist/systems/wall/wall-mitering.test.js +0 -63
- package/dist/utils/clone-scene-graph.test.d.ts +0 -2
- package/dist/utils/clone-scene-graph.test.d.ts.map +0 -1
- package/dist/utils/clone-scene-graph.test.js +0 -62
- package/dist/utils/heal-scene-graph.test.d.ts +0 -2
- package/dist/utils/heal-scene-graph.test.d.ts.map +0 -1
- package/dist/utils/heal-scene-graph.test.js +0 -88
|
@@ -2,16 +2,15 @@ import type { CeilingNode } from '../schema';
|
|
|
2
2
|
import type { AnyNode, AnyNodeId } from '../schema/types';
|
|
3
3
|
export declare const DEFAULT_LEVEL_HEIGHT = 2.5;
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* omit it and get a deterministic result from serialized node data alone.
|
|
5
|
+
* Effective ceiling height in level-local meters. An explicit stored
|
|
6
|
+
* `height` wins; absent height means the ceiling follows the level top —
|
|
7
|
+
* the same bound its write-clamp uses: min(storey plane, lowest
|
|
8
|
+
* covering-slab underside over its polygon) − CEILING_CLAMP_MARGIN (see
|
|
9
|
+
* {@link getCeilingClampBound}). Falls back to the default plane minus
|
|
10
|
+
* the same margin when the owning level is unresolvable.
|
|
12
11
|
*/
|
|
13
|
-
export
|
|
14
|
-
export declare function
|
|
12
|
+
export declare function resolveCeilingHeight(ceiling: Pick<CeilingNode, 'height' | 'parentId' | 'polygon'>, nodes: Record<AnyNodeId, AnyNode>): number;
|
|
13
|
+
export declare function deriveLegacyLevelHeight(levelId: string, nodes: Record<AnyNodeId, AnyNode>): number;
|
|
15
14
|
/**
|
|
16
15
|
* The ceiling covering level-local point `[x, z]`, or `null` when none
|
|
17
16
|
* sits over it. Points inside a ceiling's hole are treated as uncovered.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"level-height.d.ts","sourceRoot":"","sources":["../../src/services/level-height.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"level-height.d.ts","sourceRoot":"","sources":["../../src/services/level-height.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAiC,MAAM,WAAW,CAAA;AAC3E,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAOzD,eAAO,MAAM,oBAAoB,MAAM,CAAA;AAEvC;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,IAAI,CAAC,WAAW,EAAE,QAAQ,GAAG,UAAU,GAAG,SAAS,CAAC,EAC7D,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,GAChC,MAAM,CAOR;AAED,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,GAChC,MAAM,CAqCR;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,EACjC,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,GACR,WAAW,GAAG,IAAI,CAmBpB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,EACjC,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,GACR,MAAM,GAAG,IAAI,CAGf"}
|
|
@@ -1,24 +1,53 @@
|
|
|
1
|
-
import { pointInPolygon } from '../
|
|
1
|
+
import { computeWallSlabSupport, pointInPolygon } from '../systems/slab/slab-support';
|
|
2
|
+
import { resolveWallTop } from '../systems/wall/wall-top';
|
|
3
|
+
// Cycle with ./storey (it imports DEFAULT_LEVEL_HEIGHT from here) is safe:
|
|
4
|
+
// both sides only reference the other inside function bodies.
|
|
5
|
+
import { CEILING_CLAMP_MARGIN, getCeilingClampBound } from './storey';
|
|
2
6
|
export const DEFAULT_LEVEL_HEIGHT = 2.5;
|
|
3
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Effective ceiling height in level-local meters. An explicit stored
|
|
9
|
+
* `height` wins; absent height means the ceiling follows the level top —
|
|
10
|
+
* the same bound its write-clamp uses: min(storey plane, lowest
|
|
11
|
+
* covering-slab underside over its polygon) − CEILING_CLAMP_MARGIN (see
|
|
12
|
+
* {@link getCeilingClampBound}). Falls back to the default plane minus
|
|
13
|
+
* the same margin when the owning level is unresolvable.
|
|
14
|
+
*/
|
|
15
|
+
export function resolveCeilingHeight(ceiling, nodes) {
|
|
16
|
+
if (ceiling.height != null)
|
|
17
|
+
return ceiling.height;
|
|
18
|
+
const bound = typeof ceiling.parentId === 'string'
|
|
19
|
+
? getCeilingClampBound(ceiling.parentId, nodes, ceiling.polygon)
|
|
20
|
+
: Number.POSITIVE_INFINITY;
|
|
21
|
+
return Number.isFinite(bound) ? bound : DEFAULT_LEVEL_HEIGHT - CEILING_CLAMP_MARGIN;
|
|
22
|
+
}
|
|
23
|
+
export function deriveLegacyLevelHeight(levelId, nodes) {
|
|
4
24
|
const level = nodes[levelId];
|
|
5
25
|
if (!level)
|
|
6
26
|
return DEFAULT_LEVEL_HEIGHT;
|
|
27
|
+
const levelChildren = level.children
|
|
28
|
+
.map((childId) => nodes[childId])
|
|
29
|
+
.filter((child) => child !== undefined);
|
|
30
|
+
const slabs = levelChildren.filter((child) => child.type === 'slab');
|
|
31
|
+
const walls = levelChildren.filter((child) => child.type === 'wall');
|
|
7
32
|
let maxTop = 0;
|
|
8
|
-
for (const
|
|
9
|
-
const child = nodes[childId];
|
|
10
|
-
if (!child)
|
|
11
|
-
continue;
|
|
33
|
+
for (const child of levelChildren) {
|
|
12
34
|
if (child.type === 'ceiling') {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
35
|
+
// Absence here is the PRE-migration legacy schema default (2.5), not
|
|
36
|
+
// follows-mode — this derivation runs before the level has a height
|
|
37
|
+
// for a follows-mode bound to track.
|
|
38
|
+
const height = child.height ?? DEFAULT_LEVEL_HEIGHT;
|
|
39
|
+
if (height > maxTop)
|
|
40
|
+
maxTop = height;
|
|
16
41
|
}
|
|
17
42
|
else if (child.type === 'wall') {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
43
|
+
const wall = child;
|
|
44
|
+
const electedElevation = computeWallSlabSupport({
|
|
45
|
+
start: wall.start,
|
|
46
|
+
end: wall.end,
|
|
47
|
+
curveOffset: wall.curveOffset,
|
|
48
|
+
thickness: wall.thickness,
|
|
49
|
+
}, slabs, walls).elevation;
|
|
50
|
+
const top = resolveWallTop(wall, level.height ?? DEFAULT_LEVEL_HEIGHT, electedElevation);
|
|
22
51
|
if (top > maxTop)
|
|
23
52
|
maxTop = top;
|
|
24
53
|
}
|
|
@@ -36,6 +65,7 @@ export function getCeilingAt(levelId, nodes, x, z) {
|
|
|
36
65
|
if (!level)
|
|
37
66
|
return null;
|
|
38
67
|
let best = null;
|
|
68
|
+
let bestHeight = Number.POSITIVE_INFINITY;
|
|
39
69
|
for (const childId of level.children) {
|
|
40
70
|
const child = nodes[childId];
|
|
41
71
|
if (child?.type !== 'ceiling')
|
|
@@ -45,9 +75,11 @@ export function getCeilingAt(levelId, nodes, x, z) {
|
|
|
45
75
|
continue;
|
|
46
76
|
if (ceiling.holes.some((hole) => hole.length >= 3 && pointInPolygon(x, z, hole)))
|
|
47
77
|
continue;
|
|
48
|
-
const h = ceiling
|
|
49
|
-
if (best === null || h <
|
|
78
|
+
const h = resolveCeilingHeight(ceiling, nodes);
|
|
79
|
+
if (best === null || h < bestHeight) {
|
|
50
80
|
best = ceiling;
|
|
81
|
+
bestHeight = h;
|
|
82
|
+
}
|
|
51
83
|
}
|
|
52
84
|
return best;
|
|
53
85
|
}
|
|
@@ -58,5 +90,5 @@ export function getCeilingAt(levelId, nodes, x, z) {
|
|
|
58
90
|
*/
|
|
59
91
|
export function getCeilingHeightAt(levelId, nodes, x, z) {
|
|
60
92
|
const ceiling = getCeilingAt(levelId, nodes, x, z);
|
|
61
|
-
return ceiling ? (ceiling
|
|
93
|
+
return ceiling ? resolveCeilingHeight(ceiling, nodes) : null;
|
|
62
94
|
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import type { LevelNode, WallNode } from '../schema';
|
|
2
|
+
import type { AnyNode, AnyNodeId } from '../schema/types';
|
|
3
|
+
/**
|
|
4
|
+
* Gap kept between a ceiling's stored height and its clamp bound (storey
|
|
5
|
+
* plane or covering-slab underside), so the ceiling surface never
|
|
6
|
+
* coincides with the solid above it.
|
|
7
|
+
*/
|
|
8
|
+
export declare const CEILING_CLAMP_MARGIN = 0.01;
|
|
9
|
+
/**
|
|
10
|
+
* Stored storey height in meters (floor-to-floor). Falls back to
|
|
11
|
+
* {@link DEFAULT_LEVEL_HEIGHT} for unmigrated legacy levels whose `height`
|
|
12
|
+
* field is absent.
|
|
13
|
+
*/
|
|
14
|
+
export declare function getStoredLevelHeight(level: Pick<LevelNode, 'height'>): number;
|
|
15
|
+
export type LevelElevation = {
|
|
16
|
+
/** World Y of the level's floor: prefix sum of the storey heights below it. */
|
|
17
|
+
baseY: number;
|
|
18
|
+
/** Stored storey height of this level (fallback applied). */
|
|
19
|
+
height: number;
|
|
20
|
+
buildingId: string | null;
|
|
21
|
+
ordinal: number;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Per-building stacked elevations from stored storey heights: levels are
|
|
25
|
+
* sorted by ordinal ascending within each building, the lowest level's floor
|
|
26
|
+
* sits at 0, and each next floor sits on top of the previous storey height.
|
|
27
|
+
* Levels with no resolvable building share one legacy stack from 0.
|
|
28
|
+
*
|
|
29
|
+
* Pure — operates on the serialized nodes record only.
|
|
30
|
+
*/
|
|
31
|
+
export declare function getLevelElevations(nodes: Record<AnyNodeId, AnyNode>): Map<string, LevelElevation>;
|
|
32
|
+
/**
|
|
33
|
+
* The id of the level directly above `levelId` in its own stack (same
|
|
34
|
+
* resolved building, or the shared legacy stack for building-less levels):
|
|
35
|
+
* the level with the lowest ordinal strictly greater than the queried
|
|
36
|
+
* level's. `null` when the level is topmost or unresolvable.
|
|
37
|
+
*/
|
|
38
|
+
export declare function findLevelAboveId(levelId: string, elevations: Map<string, LevelElevation>): string | null;
|
|
39
|
+
/**
|
|
40
|
+
* The level directly above `levelId` — see {@link findLevelAboveId}.
|
|
41
|
+
* `null` when topmost or unresolvable. Pure.
|
|
42
|
+
*/
|
|
43
|
+
export declare function getLevelAbove(levelId: string, nodes: Record<AnyNodeId, AnyNode>): LevelNode | null;
|
|
44
|
+
/**
|
|
45
|
+
* The id of the level directly below `levelId` in its own stack — mirror of
|
|
46
|
+
* {@link findLevelAboveId}: the level with the highest ordinal strictly less
|
|
47
|
+
* than the queried level's. `null` when the level is lowest or unresolvable.
|
|
48
|
+
*/
|
|
49
|
+
export declare function findLevelBelowId(levelId: string, elevations: Map<string, LevelElevation>): string | null;
|
|
50
|
+
/**
|
|
51
|
+
* The level directly below `levelId` — see {@link findLevelBelowId}.
|
|
52
|
+
* `null` when lowest or unresolvable. Pure.
|
|
53
|
+
*/
|
|
54
|
+
export declare function getLevelBelow(levelId: string, nodes: Record<AnyNodeId, AnyNode>): LevelNode | null;
|
|
55
|
+
/**
|
|
56
|
+
* Underside of the LOWEST slab from the level above that covers
|
|
57
|
+
* level-local point `[x, z]`, expressed in the queried level's local Y:
|
|
58
|
+
* `storeyHeight + (slab.elevation - slab.thickness)`. `recessed` slabs
|
|
59
|
+
* (pools) never cover. `null` when no covering slab (or no level above).
|
|
60
|
+
*
|
|
61
|
+
* Coordinate spaces: levels stack in Y only (`LevelNode` carries no XZ
|
|
62
|
+
* transform and the viewer's LevelSystem writes only `position.y`), so a
|
|
63
|
+
* level-local `[x, z]` is valid in every level of the stack unchanged.
|
|
64
|
+
*/
|
|
65
|
+
export declare function getCoveringSlabUndersideAt(levelId: string, nodes: Record<AnyNodeId, AnyNode>, x: number, z: number): number | null;
|
|
66
|
+
/**
|
|
67
|
+
* Top plane for a plane-bound wall on `levelId`, in level-local Y:
|
|
68
|
+
* `min(stored storey height, lowest covering-slab underside over the wall's
|
|
69
|
+
* span)` — a thick or flush slab on the level above SHORTENS the walls below
|
|
70
|
+
* instead of colliding with them (Revit-style automatic attach).
|
|
71
|
+
*
|
|
72
|
+
* Coverage: the wall's thickness band (centerline + face lines, arc-aware)
|
|
73
|
+
* is clipped against each covering slab's stored polygon minus holes via
|
|
74
|
+
* {@link wallOverlapsSlabFootprint} — the same overlap machinery as the
|
|
75
|
+
* support election. Point sampling is deliberately avoided: auto-slab
|
|
76
|
+
* polygons derive from wall CENTERLINES, so perimeter walls sit exactly ON
|
|
77
|
+
* the polygon boundary, where ray-cast point-in-polygon flips with the
|
|
78
|
+
* edge's orientation (one wall clamped, its neighbor didn't). Boundary
|
|
79
|
+
* contact counts as covered on every side of the slab.
|
|
80
|
+
*
|
|
81
|
+
* This is THE plane for a plane-bound wall (`height` absent). Explicit-height
|
|
82
|
+
* walls ignore the value (`resolveWallTop` returns their stored height), so
|
|
83
|
+
* passing it wherever a raw storey height feeds `resolveWallTop` /
|
|
84
|
+
* `resolveWallEffectiveHeight` is always safe. Falls back to
|
|
85
|
+
* {@link DEFAULT_LEVEL_HEIGHT} when `levelId` doesn't resolve to a level.
|
|
86
|
+
*/
|
|
87
|
+
export declare function getWallPlaneTop(wall: Pick<WallNode, 'start' | 'end'> & Partial<Pick<WallNode, 'thickness' | 'curveOffset'>>, levelId: string, nodes: Record<AnyNodeId, AnyNode>): number;
|
|
88
|
+
/**
|
|
89
|
+
* Upper bound for a ceiling's stored height over `polygon` on `levelId`:
|
|
90
|
+
* `min(storey plane, lowest covering-slab underside) - CEILING_CLAMP_MARGIN`.
|
|
91
|
+
* The covering underside is sampled at every polygon vertex plus the
|
|
92
|
+
* centroid — cheap, and a slab overlapping a convex-ish ceiling almost
|
|
93
|
+
* always covers one of those points; exact polygon-vs-polygon overlap is
|
|
94
|
+
* not worth its cost for a clamp bound. Ceiling outlines share footprint
|
|
95
|
+
* edges with the slabs above them the same way walls do, so vertices
|
|
96
|
+
* sitting exactly on a slab's boundary count as covered on every side
|
|
97
|
+
* (see `slabCoversPoint`) instead of flipping with the edge orientation.
|
|
98
|
+
*
|
|
99
|
+
* Returns `Infinity` when `levelId` doesn't resolve, so callers clamp
|
|
100
|
+
* against nothing rather than a garbage plane.
|
|
101
|
+
*/
|
|
102
|
+
export declare function getCeilingClampBound(levelId: string, nodes: Record<AnyNodeId, AnyNode>, polygon: ReadonlyArray<[number, number]>): number;
|
|
103
|
+
//# sourceMappingURL=storey.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storey.d.ts","sourceRoot":"","sources":["../../src/services/storey.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAgB,SAAS,EAAY,QAAQ,EAAE,MAAM,WAAW,CAAA;AAC5E,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAQzD;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,OAAO,CAAA;AAExC;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,GAAG,MAAM,CAE7E;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,+EAA+E;IAC/E,KAAK,EAAE,MAAM,CAAA;IACb,6DAA6D;IAC7D,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAkBD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAgCjG;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,GACtC,MAAM,GAAG,IAAI,CAef;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,GAChC,SAAS,GAAG,IAAI,CAKlB;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,GACtC,MAAM,GAAG,IAAI,CAef;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,GAChC,SAAS,GAAG,IAAI,CAKlB;AAuFD;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,EACjC,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,GACR,MAAM,GAAG,IAAI,CAIf;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,OAAO,GAAG,KAAK,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,WAAW,GAAG,aAAa,CAAC,CAAC,EAC5F,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,GAChC,MAAM,CAYR;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,EACjC,OAAO,EAAE,aAAa,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GACvC,MAAM,CAuBR"}
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
import { pointInPolygon, pointOnPolygonBoundary, wallOverlapsSlabFootprint, } from '../systems/slab/slab-support';
|
|
2
|
+
import { DEFAULT_LEVEL_HEIGHT } from './level-height';
|
|
3
|
+
/**
|
|
4
|
+
* Gap kept between a ceiling's stored height and its clamp bound (storey
|
|
5
|
+
* plane or covering-slab underside), so the ceiling surface never
|
|
6
|
+
* coincides with the solid above it.
|
|
7
|
+
*/
|
|
8
|
+
export const CEILING_CLAMP_MARGIN = 0.01;
|
|
9
|
+
/**
|
|
10
|
+
* Stored storey height in meters (floor-to-floor). Falls back to
|
|
11
|
+
* {@link DEFAULT_LEVEL_HEIGHT} for unmigrated legacy levels whose `height`
|
|
12
|
+
* field is absent.
|
|
13
|
+
*/
|
|
14
|
+
export function getStoredLevelHeight(level) {
|
|
15
|
+
return level.height ?? DEFAULT_LEVEL_HEIGHT;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Resolves the owning building: explicit `parentId` pointing at a building
|
|
19
|
+
* wins; legacy levels that only appear in a building's `children` array
|
|
20
|
+
* resolve through that membership.
|
|
21
|
+
*/
|
|
22
|
+
function resolveLevelBuildingId(levelId, parentId, buildings) {
|
|
23
|
+
const directParent = parentId ? buildings.find((building) => building.id === parentId) : undefined;
|
|
24
|
+
if (directParent)
|
|
25
|
+
return directParent.id;
|
|
26
|
+
return buildings.find((building) => building.children.includes(levelId))?.id ?? null;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Per-building stacked elevations from stored storey heights: levels are
|
|
30
|
+
* sorted by ordinal ascending within each building, the lowest level's floor
|
|
31
|
+
* sits at 0, and each next floor sits on top of the previous storey height.
|
|
32
|
+
* Levels with no resolvable building share one legacy stack from 0.
|
|
33
|
+
*
|
|
34
|
+
* Pure — operates on the serialized nodes record only.
|
|
35
|
+
*/
|
|
36
|
+
export function getLevelElevations(nodes) {
|
|
37
|
+
const buildings = Object.values(nodes).filter((node) => node?.type === 'building');
|
|
38
|
+
const entries = [];
|
|
39
|
+
for (const node of Object.values(nodes)) {
|
|
40
|
+
if (node?.type !== 'level')
|
|
41
|
+
continue;
|
|
42
|
+
const level = node;
|
|
43
|
+
entries.push({
|
|
44
|
+
levelId: level.id,
|
|
45
|
+
baseY: 0,
|
|
46
|
+
height: getStoredLevelHeight(level),
|
|
47
|
+
buildingId: resolveLevelBuildingId(level.id, level.parentId, buildings),
|
|
48
|
+
ordinal: level.level,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
const elevations = new Map();
|
|
52
|
+
const cumulativeYByBuilding = new Map();
|
|
53
|
+
for (const entry of entries.sort((a, b) => a.ordinal - b.ordinal)) {
|
|
54
|
+
const baseY = cumulativeYByBuilding.get(entry.buildingId) ?? 0;
|
|
55
|
+
elevations.set(entry.levelId, {
|
|
56
|
+
baseY,
|
|
57
|
+
height: entry.height,
|
|
58
|
+
buildingId: entry.buildingId,
|
|
59
|
+
ordinal: entry.ordinal,
|
|
60
|
+
});
|
|
61
|
+
cumulativeYByBuilding.set(entry.buildingId, baseY + entry.height);
|
|
62
|
+
}
|
|
63
|
+
return elevations;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* The id of the level directly above `levelId` in its own stack (same
|
|
67
|
+
* resolved building, or the shared legacy stack for building-less levels):
|
|
68
|
+
* the level with the lowest ordinal strictly greater than the queried
|
|
69
|
+
* level's. `null` when the level is topmost or unresolvable.
|
|
70
|
+
*/
|
|
71
|
+
export function findLevelAboveId(levelId, elevations) {
|
|
72
|
+
const entry = elevations.get(levelId);
|
|
73
|
+
if (!entry)
|
|
74
|
+
return null;
|
|
75
|
+
let aboveId = null;
|
|
76
|
+
let aboveOrdinal = Number.POSITIVE_INFINITY;
|
|
77
|
+
for (const [candidateId, candidate] of elevations) {
|
|
78
|
+
if (candidateId === levelId)
|
|
79
|
+
continue;
|
|
80
|
+
if (candidate.buildingId !== entry.buildingId)
|
|
81
|
+
continue;
|
|
82
|
+
if (candidate.ordinal > entry.ordinal && candidate.ordinal < aboveOrdinal) {
|
|
83
|
+
aboveOrdinal = candidate.ordinal;
|
|
84
|
+
aboveId = candidateId;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return aboveId;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* The level directly above `levelId` — see {@link findLevelAboveId}.
|
|
91
|
+
* `null` when topmost or unresolvable. Pure.
|
|
92
|
+
*/
|
|
93
|
+
export function getLevelAbove(levelId, nodes) {
|
|
94
|
+
const aboveId = findLevelAboveId(levelId, getLevelElevations(nodes));
|
|
95
|
+
if (!aboveId)
|
|
96
|
+
return null;
|
|
97
|
+
const above = nodes[aboveId];
|
|
98
|
+
return above?.type === 'level' ? above : null;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* The id of the level directly below `levelId` in its own stack — mirror of
|
|
102
|
+
* {@link findLevelAboveId}: the level with the highest ordinal strictly less
|
|
103
|
+
* than the queried level's. `null` when the level is lowest or unresolvable.
|
|
104
|
+
*/
|
|
105
|
+
export function findLevelBelowId(levelId, elevations) {
|
|
106
|
+
const entry = elevations.get(levelId);
|
|
107
|
+
if (!entry)
|
|
108
|
+
return null;
|
|
109
|
+
let belowId = null;
|
|
110
|
+
let belowOrdinal = Number.NEGATIVE_INFINITY;
|
|
111
|
+
for (const [candidateId, candidate] of elevations) {
|
|
112
|
+
if (candidateId === levelId)
|
|
113
|
+
continue;
|
|
114
|
+
if (candidate.buildingId !== entry.buildingId)
|
|
115
|
+
continue;
|
|
116
|
+
if (candidate.ordinal < entry.ordinal && candidate.ordinal > belowOrdinal) {
|
|
117
|
+
belowOrdinal = candidate.ordinal;
|
|
118
|
+
belowId = candidateId;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return belowId;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* The level directly below `levelId` — see {@link findLevelBelowId}.
|
|
125
|
+
* `null` when lowest or unresolvable. Pure.
|
|
126
|
+
*/
|
|
127
|
+
export function getLevelBelow(levelId, nodes) {
|
|
128
|
+
const belowId = findLevelBelowId(levelId, getLevelElevations(nodes));
|
|
129
|
+
if (!belowId)
|
|
130
|
+
return null;
|
|
131
|
+
const below = nodes[belowId];
|
|
132
|
+
return below?.type === 'level' ? below : null;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Storey height of the queried level plus the level-above's covering
|
|
136
|
+
* (non-recessed) slabs. `null` when `levelId` doesn't resolve to a level.
|
|
137
|
+
* A missing level above yields an empty slab list, not `null` — the
|
|
138
|
+
* storey height is still meaningful for the clamp bound.
|
|
139
|
+
*/
|
|
140
|
+
function resolveCoveringSlabContext(levelId, nodes) {
|
|
141
|
+
const level = nodes[levelId];
|
|
142
|
+
if (level?.type !== 'level')
|
|
143
|
+
return null;
|
|
144
|
+
const above = getLevelAbove(levelId, nodes);
|
|
145
|
+
const slabs = [];
|
|
146
|
+
for (const childId of above?.children ?? []) {
|
|
147
|
+
const child = nodes[childId];
|
|
148
|
+
if (child?.type !== 'slab')
|
|
149
|
+
continue;
|
|
150
|
+
const slab = child;
|
|
151
|
+
// Recessed slabs (pools) are open shells, not covering solids.
|
|
152
|
+
if (slab.recessed === true)
|
|
153
|
+
continue;
|
|
154
|
+
if (slab.polygon.length < 3)
|
|
155
|
+
continue;
|
|
156
|
+
slabs.push(slab);
|
|
157
|
+
}
|
|
158
|
+
return { storeyHeight: getStoredLevelHeight(level), slabs };
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Underside of `slab`'s solid in the QUERIED level's local Y. The solid
|
|
162
|
+
* occupies `[elevation - thickness, elevation]` in ITS level's local Y,
|
|
163
|
+
* which sits `storeyHeight` above the queried level's floor.
|
|
164
|
+
*/
|
|
165
|
+
function coveringUndersideY(storeyHeight, slab) {
|
|
166
|
+
return storeyHeight + ((slab.elevation ?? 0.05) - (slab.thickness ?? 0.05));
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Whether `slab`'s stored footprint (polygon minus holes) covers `[x, z]`.
|
|
170
|
+
* Ray-cast pointInPolygon flips arbitrarily for points exactly ON the
|
|
171
|
+
* boundary (min-side edges read inside, max-side edges outside), so
|
|
172
|
+
* boundary contact counts as covered explicitly — the same convention as
|
|
173
|
+
* the slab-support interval classification. A point on a hole's rim keeps
|
|
174
|
+
* coverage (mirrors the support election's hole handling).
|
|
175
|
+
*
|
|
176
|
+
* Raw stored polygon + holes on purpose (mirrors getCeilingAt): the
|
|
177
|
+
* clamp bound doesn't need the rendered footprint's junction trims,
|
|
178
|
+
* and staying off the render path keeps this query cheap and pure.
|
|
179
|
+
*/
|
|
180
|
+
function slabCoversPoint(slab, x, z) {
|
|
181
|
+
if (!pointInPolygon(x, z, slab.polygon) && !pointOnPolygonBoundary(x, z, slab.polygon)) {
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
for (const hole of slab.holes ?? []) {
|
|
185
|
+
if (hole.length < 3)
|
|
186
|
+
continue;
|
|
187
|
+
if (pointInPolygon(x, z, hole) && !pointOnPolygonBoundary(x, z, hole))
|
|
188
|
+
return false;
|
|
189
|
+
}
|
|
190
|
+
return true;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Lowest underside among `slabs` covering `[x, z]`, in the queried
|
|
194
|
+
* level's local Y, or `null` when none covers the point.
|
|
195
|
+
*/
|
|
196
|
+
function lowestCoveringUndersideAt(context, x, z) {
|
|
197
|
+
let lowest = null;
|
|
198
|
+
for (const slab of context.slabs) {
|
|
199
|
+
if (!slabCoversPoint(slab, x, z))
|
|
200
|
+
continue;
|
|
201
|
+
const underside = coveringUndersideY(context.storeyHeight, slab);
|
|
202
|
+
if (lowest === null || underside < lowest)
|
|
203
|
+
lowest = underside;
|
|
204
|
+
}
|
|
205
|
+
return lowest;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Underside of the LOWEST slab from the level above that covers
|
|
209
|
+
* level-local point `[x, z]`, expressed in the queried level's local Y:
|
|
210
|
+
* `storeyHeight + (slab.elevation - slab.thickness)`. `recessed` slabs
|
|
211
|
+
* (pools) never cover. `null` when no covering slab (or no level above).
|
|
212
|
+
*
|
|
213
|
+
* Coordinate spaces: levels stack in Y only (`LevelNode` carries no XZ
|
|
214
|
+
* transform and the viewer's LevelSystem writes only `position.y`), so a
|
|
215
|
+
* level-local `[x, z]` is valid in every level of the stack unchanged.
|
|
216
|
+
*/
|
|
217
|
+
export function getCoveringSlabUndersideAt(levelId, nodes, x, z) {
|
|
218
|
+
const context = resolveCoveringSlabContext(levelId, nodes);
|
|
219
|
+
if (!context)
|
|
220
|
+
return null;
|
|
221
|
+
return lowestCoveringUndersideAt(context, x, z);
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Top plane for a plane-bound wall on `levelId`, in level-local Y:
|
|
225
|
+
* `min(stored storey height, lowest covering-slab underside over the wall's
|
|
226
|
+
* span)` — a thick or flush slab on the level above SHORTENS the walls below
|
|
227
|
+
* instead of colliding with them (Revit-style automatic attach).
|
|
228
|
+
*
|
|
229
|
+
* Coverage: the wall's thickness band (centerline + face lines, arc-aware)
|
|
230
|
+
* is clipped against each covering slab's stored polygon minus holes via
|
|
231
|
+
* {@link wallOverlapsSlabFootprint} — the same overlap machinery as the
|
|
232
|
+
* support election. Point sampling is deliberately avoided: auto-slab
|
|
233
|
+
* polygons derive from wall CENTERLINES, so perimeter walls sit exactly ON
|
|
234
|
+
* the polygon boundary, where ray-cast point-in-polygon flips with the
|
|
235
|
+
* edge's orientation (one wall clamped, its neighbor didn't). Boundary
|
|
236
|
+
* contact counts as covered on every side of the slab.
|
|
237
|
+
*
|
|
238
|
+
* This is THE plane for a plane-bound wall (`height` absent). Explicit-height
|
|
239
|
+
* walls ignore the value (`resolveWallTop` returns their stored height), so
|
|
240
|
+
* passing it wherever a raw storey height feeds `resolveWallTop` /
|
|
241
|
+
* `resolveWallEffectiveHeight` is always safe. Falls back to
|
|
242
|
+
* {@link DEFAULT_LEVEL_HEIGHT} when `levelId` doesn't resolve to a level.
|
|
243
|
+
*/
|
|
244
|
+
export function getWallPlaneTop(wall, levelId, nodes) {
|
|
245
|
+
const context = resolveCoveringSlabContext(levelId, nodes);
|
|
246
|
+
if (!context)
|
|
247
|
+
return DEFAULT_LEVEL_HEIGHT;
|
|
248
|
+
let plane = context.storeyHeight;
|
|
249
|
+
for (const slab of context.slabs) {
|
|
250
|
+
const underside = coveringUndersideY(context.storeyHeight, slab);
|
|
251
|
+
if (underside >= plane)
|
|
252
|
+
continue;
|
|
253
|
+
if (!wallOverlapsSlabFootprint(wall, slab.polygon, slab.holes))
|
|
254
|
+
continue;
|
|
255
|
+
plane = underside;
|
|
256
|
+
}
|
|
257
|
+
return plane;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Upper bound for a ceiling's stored height over `polygon` on `levelId`:
|
|
261
|
+
* `min(storey plane, lowest covering-slab underside) - CEILING_CLAMP_MARGIN`.
|
|
262
|
+
* The covering underside is sampled at every polygon vertex plus the
|
|
263
|
+
* centroid — cheap, and a slab overlapping a convex-ish ceiling almost
|
|
264
|
+
* always covers one of those points; exact polygon-vs-polygon overlap is
|
|
265
|
+
* not worth its cost for a clamp bound. Ceiling outlines share footprint
|
|
266
|
+
* edges with the slabs above them the same way walls do, so vertices
|
|
267
|
+
* sitting exactly on a slab's boundary count as covered on every side
|
|
268
|
+
* (see `slabCoversPoint`) instead of flipping with the edge orientation.
|
|
269
|
+
*
|
|
270
|
+
* Returns `Infinity` when `levelId` doesn't resolve, so callers clamp
|
|
271
|
+
* against nothing rather than a garbage plane.
|
|
272
|
+
*/
|
|
273
|
+
export function getCeilingClampBound(levelId, nodes, polygon) {
|
|
274
|
+
const context = resolveCoveringSlabContext(levelId, nodes);
|
|
275
|
+
if (!context)
|
|
276
|
+
return Number.POSITIVE_INFINITY;
|
|
277
|
+
let bound = context.storeyHeight;
|
|
278
|
+
if (polygon.length > 0) {
|
|
279
|
+
let cx = 0;
|
|
280
|
+
let cz = 0;
|
|
281
|
+
for (const [x, z] of polygon) {
|
|
282
|
+
cx += x;
|
|
283
|
+
cz += z;
|
|
284
|
+
}
|
|
285
|
+
const samples = [
|
|
286
|
+
...polygon,
|
|
287
|
+
[cx / polygon.length, cz / polygon.length],
|
|
288
|
+
];
|
|
289
|
+
for (const [x, z] of samples) {
|
|
290
|
+
const underside = lowestCoveringUndersideAt(context, x, z);
|
|
291
|
+
if (underside !== null && underside < bound)
|
|
292
|
+
bound = underside;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
return bound - CEILING_CLAMP_MARGIN;
|
|
296
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node-actions.d.ts","sourceRoot":"","sources":["../../../src/store/actions/node-actions.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,SAAS,EASf,MAAM,cAAc,CAAA;AAErB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAG9C,KAAK,YAAY,GAAG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,SAAS,CAAA;CAAE,CAAA;AAC3D,KAAK,YAAY,GAAG;IAAE,EAAE,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAA;CAAE,CAAA;AAC7D,KAAK,YAAY,GAAG,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"node-actions.d.ts","sourceRoot":"","sources":["../../../src/store/actions/node-actions.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,SAAS,EASf,MAAM,cAAc,CAAA;AAErB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAG9C,KAAK,YAAY,GAAG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,SAAS,CAAA;CAAE,CAAA;AAC3D,KAAK,YAAY,GAAG;IAAE,EAAE,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAA;CAAE,CAAA;AAC7D,KAAK,YAAY,GAAG,SAAS,CAAA;AA0vB7B,eAAO,MAAM,iBAAiB,GAC5B,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC,UAAU,CAAC,KAAK,IAAI,EAC7D,KAAK,MAAM,UAAU,EACrB,KAAK,YAAY,EAAE,SAkDpB,CAAA;AAED,eAAO,MAAM,sBAAsB,GACjC,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC,UAAU,CAAC,KAAK,IAAI,EAC7D,KAAK,MAAM,UAAU,EACrB,SAAS;IAAE,MAAM,CAAC,EAAE,YAAY,EAAE,CAAC;IAAC,MAAM,CAAC,EAAE,YAAY,EAAE,CAAC;IAAC,MAAM,CAAC,EAAE,YAAY,EAAE,CAAA;CAAE,SAyIvF,CAAA;AAED,eAAO,MAAM,iBAAiB,GAC5B,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC,UAAU,CAAC,KAAK,IAAI,EAC7D,KAAK,MAAM,UAAU,EACrB,SAAS;IAAE,EAAE,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAA;CAAE,EAAE,SAoFrD,CAAA;AAED,eAAO,MAAM,iBAAiB,GAC5B,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC,UAAU,CAAC,KAAK,IAAI,EAC7D,KAAK,MAAM,UAAU,EACrB,KAAK,SAAS,EAAE,SA8JjB,CAAA"}
|
|
@@ -343,8 +343,21 @@ function parseCreatedNode(node, parentId) {
|
|
|
343
343
|
warnSanitizedNodeMutation('create', node.id, sanitized.issues);
|
|
344
344
|
return sanitized.value;
|
|
345
345
|
}
|
|
346
|
+
// An explicit `key: undefined` in update data REMOVES the key: optional
|
|
347
|
+
// fields like wall.height encode a mode by their absence (absent =
|
|
348
|
+
// plane-bound top), and zod's safeParse echoes explicit-undefined keys, so
|
|
349
|
+
// a plain spread would leave a lingering own key that breaks `'height' in
|
|
350
|
+
// node` checks.
|
|
351
|
+
function mergeNodeUpdate(currentNode, patch) {
|
|
352
|
+
const merged = { ...currentNode, ...patch };
|
|
353
|
+
for (const key of Object.keys(patch)) {
|
|
354
|
+
if (patch[key] === undefined)
|
|
355
|
+
delete merged[key];
|
|
356
|
+
}
|
|
357
|
+
return merged;
|
|
358
|
+
}
|
|
346
359
|
function parseUpdatedNode(currentNode, data) {
|
|
347
|
-
const candidate =
|
|
360
|
+
const candidate = mergeNodeUpdate(currentNode, data);
|
|
348
361
|
const parsed = AnyNodeSchema.safeParse(candidate);
|
|
349
362
|
if (parsed.success)
|
|
350
363
|
return parsed.data;
|
|
@@ -354,7 +367,7 @@ function parseUpdatedNode(currentNode, data) {
|
|
|
354
367
|
return candidate;
|
|
355
368
|
}
|
|
356
369
|
warnSanitizedNodeMutation('update', currentNode.id, sanitized.issues);
|
|
357
|
-
return
|
|
370
|
+
return mergeNodeUpdate(currentNode, sanitized.value);
|
|
358
371
|
}
|
|
359
372
|
function shouldRefreshDefaultRidgeVents(data) {
|
|
360
373
|
return Object.keys(data).some((key) => DEFAULT_RIDGE_VENT_REFRESH_FIELDS.has(key));
|
|
@@ -413,7 +426,10 @@ function areWallStylesCompatible(a, b) {
|
|
|
413
426
|
return ((a.parentId ?? null) === (b.parentId ?? null) &&
|
|
414
427
|
Math.abs((a.curveOffset ?? 0) - (b.curveOffset ?? 0)) <= 1e-6 &&
|
|
415
428
|
Math.abs((a.thickness ?? 0.2) - (b.thickness ?? 0.2)) <= 1e-6 &&
|
|
416
|
-
|
|
429
|
+
// Absent height means plane-bound (follows the storey), which must never
|
|
430
|
+
// merge with an explicit height — even one that currently matches the plane.
|
|
431
|
+
(a.height == null) === (b.height == null) &&
|
|
432
|
+
Math.abs((a.height ?? 0) - (b.height ?? 0)) <= 1e-6 &&
|
|
417
433
|
aInterior === bInterior &&
|
|
418
434
|
aExterior === bExterior &&
|
|
419
435
|
a.frontSide === b.frontSide &&
|
|
@@ -861,6 +877,34 @@ export const deleteNodesAction = (set, get, ids) => {
|
|
|
861
877
|
nodesToMarkDirty.add(update.id);
|
|
862
878
|
}
|
|
863
879
|
}
|
|
880
|
+
// Deleting a slab strips `supportSlabId` / `deckSlabId` references from
|
|
881
|
+
// surviving nodes in the same undo commit (mirrors the collectionIds
|
|
882
|
+
// cleanup below), so those nodes re-elect their support / re-derive
|
|
883
|
+
// their rise. Deletion is the ONLY writer — a host merely reshaped away
|
|
884
|
+
// keeps the field and the read path falls back, letting hosting resume
|
|
885
|
+
// if the slab returns.
|
|
886
|
+
const deletedSlabIds = new Set();
|
|
887
|
+
for (const id of allIds) {
|
|
888
|
+
if (nextNodes[id]?.type === 'slab')
|
|
889
|
+
deletedSlabIds.add(id);
|
|
890
|
+
}
|
|
891
|
+
if (deletedSlabIds.size > 0) {
|
|
892
|
+
for (const [nodeId, node] of Object.entries(nextNodes)) {
|
|
893
|
+
if (allIds.has(nodeId))
|
|
894
|
+
continue;
|
|
895
|
+
const patch = {};
|
|
896
|
+
const hostId = node.supportSlabId;
|
|
897
|
+
if (hostId && deletedSlabIds.has(hostId))
|
|
898
|
+
patch.supportSlabId = undefined;
|
|
899
|
+
const deckId = node.deckSlabId;
|
|
900
|
+
if (deckId && deletedSlabIds.has(deckId))
|
|
901
|
+
patch.deckSlabId = undefined;
|
|
902
|
+
if (Object.keys(patch).length > 0) {
|
|
903
|
+
nextNodes[nodeId] = { ...node, ...patch };
|
|
904
|
+
nodesToMarkDirty.add(nodeId);
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
}
|
|
864
908
|
for (const id of allIds) {
|
|
865
909
|
const node = nextNodes[id];
|
|
866
910
|
if (!node)
|
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
import type { Collection, CollectionId } from '../schema/collections';
|
|
2
|
+
import type { SceneMaterial, SceneMaterialId } from '../schema/scene-material';
|
|
3
|
+
import type { AnyNode, AnyNodeId } from '../schema/types';
|
|
4
|
+
export type SceneSnapshot = {
|
|
5
|
+
nodes: Record<AnyNodeId, AnyNode>;
|
|
6
|
+
rootNodeIds: AnyNodeId[];
|
|
7
|
+
collections: Record<CollectionId, Collection>;
|
|
8
|
+
materials: Record<SceneMaterialId, SceneMaterial>;
|
|
9
|
+
installedPlugins: string[];
|
|
10
|
+
};
|
|
11
|
+
export type SceneCommitOrigin = 'local' | 'load' | 'host';
|
|
12
|
+
export type SceneCommit = {
|
|
13
|
+
origin: SceneCommitOrigin;
|
|
14
|
+
before: SceneSnapshot;
|
|
15
|
+
current: SceneSnapshot;
|
|
16
|
+
};
|
|
17
|
+
export type SceneCommitListener = (commit: SceneCommit) => void;
|
|
1
18
|
type TemporalStoreLike = {
|
|
2
19
|
temporal: {
|
|
3
20
|
getState(): {
|
|
@@ -16,6 +33,9 @@ type TemporalHistoryStoreLike<TPastState> = {
|
|
|
16
33
|
}): void;
|
|
17
34
|
};
|
|
18
35
|
};
|
|
36
|
+
export declare function areSceneSnapshotsEqual(left: SceneSnapshot, right: SceneSnapshot): boolean;
|
|
37
|
+
export declare function subscribeSceneCommits(listener: SceneCommitListener): () => void;
|
|
38
|
+
export declare function notifySceneCommit(commit: SceneCommit): void;
|
|
19
39
|
export declare function pauseSceneHistory(sceneStore: TemporalStoreLike): void;
|
|
20
40
|
export declare function resumeSceneHistory(sceneStore: TemporalStoreLike): void;
|
|
21
41
|
export declare function getSceneHistoryPauseDepth(): number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"history-control.d.ts","sourceRoot":"","sources":["../../src/store/history-control.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"history-control.d.ts","sourceRoot":"","sources":["../../src/store/history-control.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAC9E,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAIzD,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;IACjC,WAAW,EAAE,SAAS,EAAE,CAAA;IACxB,WAAW,EAAE,MAAM,CAAC,YAAY,EAAE,UAAU,CAAC,CAAA;IAC7C,SAAS,EAAE,MAAM,CAAC,eAAe,EAAE,aAAa,CAAC,CAAA;IACjD,gBAAgB,EAAE,MAAM,EAAE,CAAA;CAC3B,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAA;AAEzD,MAAM,MAAM,WAAW,GAAG;IACxB,MAAM,EAAE,iBAAiB,CAAA;IACzB,MAAM,EAAE,aAAa,CAAA;IACrB,OAAO,EAAE,aAAa,CAAA;CACvB,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,CAAA;AAE/D,KAAK,iBAAiB,GAAG;IACvB,QAAQ,EAAE;QACR,QAAQ,IAAI;YACV,KAAK,IAAI,IAAI,CAAA;YACb,MAAM,IAAI,IAAI,CAAA;SACf,CAAA;KACF,CAAA;CACF,CAAA;AAED,KAAK,wBAAwB,CAAC,UAAU,IAAI;IAC1C,QAAQ,EAAE;QACR,QAAQ,IAAI;YACV,UAAU,EAAE,UAAU,EAAE,CAAA;SACzB,CAAA;QACD,QAAQ,CAAC,KAAK,EAAE;YAAE,UAAU,EAAE,UAAU,EAAE,CAAA;SAAE,GAAG,IAAI,CAAA;KACpD,CAAA;CACF,CAAA;AA+BD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAQzF;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,mBAAmB,GAAG,MAAM,IAAI,CAK/E;AAYD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAiB3D;AAyBD,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,iBAAiB,GAAG,IAAI,CAKrE;AAED,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,iBAAiB,GAAG,IAAI,CAStE;AAED,wBAAgB,yBAAyB,IAAI,MAAM,CAElD;AAED,wBAAgB,2BAA2B,IAAI,IAAI,CAElD;AAkBD,wBAAgB,2BAA2B,CAAC,UAAU,EAAE,OAAO,EAC7D,UAAU,EAAE,wBAAwB,CAAC,UAAU,CAAC,EAChD,GAAG,EAAE,MAAM,OAAO,GACjB,OAAO,CAuBT"}
|