@pascal-app/core 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/events/bus.d.ts +45 -6
- package/dist/events/bus.d.ts.map +1 -1
- package/dist/events/bus.js +1 -1
- package/dist/hooks/scene-registry/scene-registry.d.ts +2 -0
- package/dist/hooks/scene-registry/scene-registry.d.ts.map +1 -1
- package/dist/hooks/scene-registry/scene-registry.js +2 -0
- package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts.map +1 -1
- package/dist/hooks/spatial-grid/spatial-grid-manager.js +164 -6
- package/dist/index.d.ts +8 -15
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -14
- package/dist/lib/door-operation.d.ts +7 -0
- package/dist/lib/door-operation.d.ts.map +1 -0
- package/dist/lib/door-operation.js +25 -0
- package/dist/lib/polygon-geometry.d.ts.map +1 -1
- package/dist/lib/slab-polygon.d.ts +3 -0
- package/dist/lib/slab-polygon.d.ts.map +1 -0
- package/dist/lib/slab-polygon.js +58 -0
- package/dist/lib/space-detection.d.ts.map +1 -1
- package/dist/lib/space-detection.js +10 -8
- package/dist/material-library.d.ts +5 -3
- package/dist/material-library.d.ts.map +1 -1
- package/dist/material-library.js +28 -32
- package/dist/schema/asset-url.d.ts +34 -0
- package/dist/schema/asset-url.d.ts.map +1 -0
- package/dist/schema/asset-url.js +79 -0
- package/dist/schema/asset-url.test.d.ts +2 -0
- package/dist/schema/asset-url.test.d.ts.map +1 -0
- package/dist/schema/asset-url.test.js +134 -0
- package/dist/schema/index.d.ts +7 -5
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +5 -3
- package/dist/schema/material.d.ts +1 -0
- package/dist/schema/material.d.ts.map +1 -1
- package/dist/schema/material.js +13 -11
- package/dist/schema/nodes/column.d.ts +520 -0
- package/dist/schema/nodes/column.d.ts.map +1 -0
- package/dist/schema/nodes/column.js +385 -0
- package/dist/schema/nodes/door.d.ts +72 -0
- package/dist/schema/nodes/door.d.ts.map +1 -1
- package/dist/schema/nodes/door.js +39 -2
- package/dist/schema/nodes/fence.d.ts +1 -1
- package/dist/schema/nodes/fence.js +2 -2
- package/dist/schema/nodes/guide.d.ts +17 -0
- package/dist/schema/nodes/guide.d.ts.map +1 -1
- package/dist/schema/nodes/guide.js +11 -1
- package/dist/schema/nodes/item.d.ts +20 -0
- package/dist/schema/nodes/item.d.ts.map +1 -1
- package/dist/schema/nodes/item.js +30 -1
- package/dist/schema/nodes/level.d.ts +1 -1
- package/dist/schema/nodes/level.d.ts.map +1 -1
- package/dist/schema/nodes/level.js +6 -0
- package/dist/schema/nodes/roof-segment.d.ts +2 -2
- package/dist/schema/nodes/roof.d.ts +2 -2
- package/dist/schema/nodes/roof.d.ts.map +1 -1
- package/dist/schema/nodes/roof.js +5 -5
- package/dist/schema/nodes/scan.d.ts.map +1 -1
- package/dist/schema/nodes/scan.js +2 -1
- package/dist/schema/nodes/site.d.ts +7 -0
- package/dist/schema/nodes/site.d.ts.map +1 -1
- package/dist/schema/nodes/spawn.d.ts +24 -0
- package/dist/schema/nodes/spawn.d.ts.map +1 -0
- package/dist/schema/nodes/spawn.js +8 -0
- package/dist/schema/nodes/stair.d.ts +6 -6
- package/dist/schema/nodes/stair.d.ts.map +1 -1
- package/dist/schema/nodes/stair.js +9 -7
- package/dist/schema/nodes/window.d.ts +55 -0
- package/dist/schema/nodes/window.d.ts.map +1 -1
- package/dist/schema/nodes/window.js +29 -0
- package/dist/schema/types.d.ts +320 -5
- package/dist/schema/types.d.ts.map +1 -1
- package/dist/schema/types.js +4 -0
- package/dist/store/actions/node-actions.d.ts.map +1 -1
- package/dist/store/actions/node-actions.js +13 -10
- package/dist/store/use-interactive.d.ts +43 -0
- package/dist/store/use-interactive.d.ts.map +1 -1
- package/dist/store/use-interactive.js +66 -0
- package/dist/store/use-scene.d.ts.map +1 -1
- package/dist/store/use-scene.js +69 -5
- package/dist/systems/stair/stair-opening-sync.d.ts.map +1 -1
- package/dist/systems/stair/stair-opening-sync.js +41 -7
- package/dist/systems/stair/stair-opening-sync.test.d.ts +2 -0
- package/dist/systems/stair/stair-opening-sync.test.d.ts.map +1 -0
- package/dist/systems/stair/stair-opening-sync.test.js +63 -0
- package/dist/systems/wall/wall-curve.d.ts +1 -1
- 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.d.ts.map +1 -1
- package/dist/systems/wall/wall-mitering.js +2 -6
- package/package.json +34 -5
- package/dist/materials.d.ts +0 -10
- package/dist/materials.d.ts.map +0 -1
- package/dist/materials.js +0 -22
- package/dist/systems/ceiling/ceiling-system.d.ts +0 -8
- package/dist/systems/ceiling/ceiling-system.d.ts.map +0 -1
- package/dist/systems/ceiling/ceiling-system.js +0 -92
- package/dist/systems/door/door-system.d.ts +0 -2
- package/dist/systems/door/door-system.d.ts.map +0 -1
- package/dist/systems/door/door-system.js +0 -195
- package/dist/systems/fence/fence-system.d.ts +0 -2
- package/dist/systems/fence/fence-system.d.ts.map +0 -1
- package/dist/systems/fence/fence-system.js +0 -187
- package/dist/systems/item/item-system.d.ts +0 -2
- package/dist/systems/item/item-system.d.ts.map +0 -1
- package/dist/systems/item/item-system.js +0 -48
- package/dist/systems/roof/roof-system.d.ts +0 -16
- package/dist/systems/roof/roof-system.d.ts.map +0 -1
- package/dist/systems/roof/roof-system.js +0 -797
- package/dist/systems/slab/slab-system.d.ts +0 -8
- package/dist/systems/slab/slab-system.d.ts.map +0 -1
- package/dist/systems/slab/slab-system.js +0 -214
- package/dist/systems/stair/stair-system.d.ts +0 -2
- package/dist/systems/stair/stair-system.d.ts.map +0 -1
- package/dist/systems/stair/stair-system.js +0 -776
- package/dist/systems/wall/wall-system.d.ts +0 -12
- package/dist/systems/wall/wall-system.d.ts.map +0 -1
- package/dist/systems/wall/wall-system.js +0 -455
- package/dist/systems/window/window-system.d.ts +0 -2
- package/dist/systems/window/window-system.d.ts.map +0 -1
- package/dist/systems/window/window-system.js +0 -131
package/dist/events/bus.d.ts
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import type { ThreeEvent } from '@react-three/fiber';
|
|
2
2
|
import type { Object3D } from 'three';
|
|
3
|
-
import type { BuildingNode, CeilingNode, DoorNode, FenceNode, ItemNode, LevelNode, RoofNode, RoofSegmentNode, SiteNode, SlabNode, StairNode, StairSegmentNode, WallNode, WindowNode, ZoneNode } from '../schema';
|
|
3
|
+
import type { BuildingNode, CeilingNode, ColumnNode, DoorNode, FenceNode, GuideNode, ItemNode, LevelNode, RoofNode, RoofSegmentNode, SiteNode, SlabNode, SpawnNode, StairNode, StairSegmentNode, WallNode, WindowNode, ZoneNode } from '../schema';
|
|
4
4
|
import type { AnyNode } from '../schema/types';
|
|
5
5
|
export interface GridEvent {
|
|
6
6
|
/** World-space intersection point on the grid plane. */
|
|
7
7
|
position: [number, number, number];
|
|
8
8
|
/**
|
|
9
|
-
* Building-local intersection point
|
|
9
|
+
* Building-local intersection point — relative to the currently selected building.
|
|
10
10
|
* Equals `position` when no building is selected.
|
|
11
|
-
* Use this for placing
|
|
12
|
-
* (walls, slabs, items, etc.).
|
|
11
|
+
* Use this for placing/committing anything that lives inside a building (walls, slabs, items, etc.).
|
|
13
12
|
*/
|
|
14
13
|
localPosition: [number, number, number];
|
|
14
|
+
faceIndex?: number;
|
|
15
|
+
object: Object3D;
|
|
15
16
|
nativeEvent: ThreeEvent<PointerEvent>;
|
|
16
17
|
}
|
|
17
18
|
export interface NodeEvent<T extends AnyNode = AnyNode> {
|
|
@@ -32,7 +33,9 @@ export type BuildingEvent = NodeEvent<BuildingNode>;
|
|
|
32
33
|
export type LevelEvent = NodeEvent<LevelNode>;
|
|
33
34
|
export type ZoneEvent = NodeEvent<ZoneNode>;
|
|
34
35
|
export type SlabEvent = NodeEvent<SlabNode>;
|
|
36
|
+
export type SpawnEvent = NodeEvent<SpawnNode>;
|
|
35
37
|
export type CeilingEvent = NodeEvent<CeilingNode>;
|
|
38
|
+
export type ColumnEvent = NodeEvent<ColumnNode>;
|
|
36
39
|
export type RoofEvent = NodeEvent<RoofNode>;
|
|
37
40
|
export type RoofSegmentEvent = NodeEvent<RoofSegmentNode>;
|
|
38
41
|
export type StairEvent = NodeEvent<StairNode>;
|
|
@@ -62,11 +65,25 @@ export interface ThumbnailGenerateEvent {
|
|
|
62
65
|
/**
|
|
63
66
|
* When true, snap levels to their true positions before capturing (for a
|
|
64
67
|
* consistent auto-thumbnail angle) and defer the capture if the tab is
|
|
65
|
-
* hidden
|
|
68
|
+
* hidden — the background auto-save path. Omit for user-driven captures
|
|
66
69
|
* that should fire immediately from the current camera pose.
|
|
67
70
|
*/
|
|
68
71
|
snapLevels?: boolean;
|
|
69
72
|
}
|
|
73
|
+
export interface CameraControlFitSceneEvent {
|
|
74
|
+
/**
|
|
75
|
+
* XZ-plane axis-aligned bounds of the scene's geometry, computed from the
|
|
76
|
+
* scene graph (see `@pascal-app/editor`'s `computeSceneBoundsXZ`). The
|
|
77
|
+
* viewer's camera-controls listener frames the camera onto this box.
|
|
78
|
+
* Omitted values fall back to the camera's default pose.
|
|
79
|
+
*/
|
|
80
|
+
bounds?: {
|
|
81
|
+
min: [number, number];
|
|
82
|
+
max: [number, number];
|
|
83
|
+
center: [number, number];
|
|
84
|
+
size: [number, number];
|
|
85
|
+
};
|
|
86
|
+
}
|
|
70
87
|
type CameraControlEvents = {
|
|
71
88
|
'camera-controls:view': CameraControlEvent;
|
|
72
89
|
'camera-controls:focus': CameraControlEvent;
|
|
@@ -74,11 +91,33 @@ type CameraControlEvents = {
|
|
|
74
91
|
'camera-controls:top-view': undefined;
|
|
75
92
|
'camera-controls:orbit-cw': undefined;
|
|
76
93
|
'camera-controls:orbit-ccw': undefined;
|
|
94
|
+
'camera-controls:fit-scene': CameraControlFitSceneEvent;
|
|
77
95
|
'camera-controls:generate-thumbnail': ThumbnailGenerateEvent;
|
|
78
96
|
};
|
|
79
97
|
type ToolEvents = {
|
|
80
98
|
'tool:cancel': undefined;
|
|
81
99
|
};
|
|
100
|
+
type GuideEvents = {
|
|
101
|
+
'guide:set-reference-scale': {
|
|
102
|
+
guideId: GuideNode['id'];
|
|
103
|
+
};
|
|
104
|
+
'guide:cancel-reference-scale': undefined;
|
|
105
|
+
'guide:deleted': {
|
|
106
|
+
guideId: GuideNode['id'];
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
type DoorAnimationEvents = {
|
|
110
|
+
'door:animation-completed': {
|
|
111
|
+
doorId: DoorNode['id'];
|
|
112
|
+
field: 'operationState' | 'swingAngle';
|
|
113
|
+
};
|
|
114
|
+
};
|
|
115
|
+
type WindowAnimationEvents = {
|
|
116
|
+
'window:animation-completed': {
|
|
117
|
+
windowId: WindowNode['id'];
|
|
118
|
+
field: 'operationState';
|
|
119
|
+
};
|
|
120
|
+
};
|
|
82
121
|
type PresetEvents = {
|
|
83
122
|
'preset:generate-thumbnail': {
|
|
84
123
|
presetId: string;
|
|
@@ -109,7 +148,7 @@ type AIChatEvents = {
|
|
|
109
148
|
}[];
|
|
110
149
|
};
|
|
111
150
|
};
|
|
112
|
-
type EditorEvents = GridEvents & NodeEvents<'wall', WallEvent> & NodeEvents<'fence', FenceEvent> & NodeEvents<'item', ItemEvent> & NodeEvents<'site', SiteEvent> & NodeEvents<'building', BuildingEvent> & NodeEvents<'level', LevelEvent> & NodeEvents<'zone', ZoneEvent> & NodeEvents<'slab', SlabEvent> & NodeEvents<'ceiling', CeilingEvent> & NodeEvents<'roof', RoofEvent> & NodeEvents<'roof-segment', RoofSegmentEvent> & NodeEvents<'stair', StairEvent> & NodeEvents<'stair-segment', StairSegmentEvent> & NodeEvents<'window', WindowEvent> & NodeEvents<'door', DoorEvent> & CameraControlEvents & ToolEvents & PresetEvents & ThumbnailEvents & SnapshotEvents & AIChatEvents;
|
|
151
|
+
type EditorEvents = GridEvents & NodeEvents<'wall', WallEvent> & NodeEvents<'fence', FenceEvent> & NodeEvents<'item', ItemEvent> & NodeEvents<'site', SiteEvent> & NodeEvents<'building', BuildingEvent> & NodeEvents<'level', LevelEvent> & NodeEvents<'zone', ZoneEvent> & NodeEvents<'slab', SlabEvent> & NodeEvents<'spawn', SpawnEvent> & NodeEvents<'ceiling', CeilingEvent> & NodeEvents<'column', ColumnEvent> & NodeEvents<'roof', RoofEvent> & NodeEvents<'roof-segment', RoofSegmentEvent> & NodeEvents<'stair', StairEvent> & NodeEvents<'stair-segment', StairSegmentEvent> & NodeEvents<'window', WindowEvent> & NodeEvents<'door', DoorEvent> & CameraControlEvents & ToolEvents & GuideEvents & DoorAnimationEvents & WindowAnimationEvents & PresetEvents & ThumbnailEvents & SnapshotEvents & AIChatEvents;
|
|
113
152
|
export declare const emitter: import("mitt").Emitter<EditorEvents>;
|
|
114
153
|
export {};
|
|
115
154
|
//# sourceMappingURL=bus.d.ts.map
|
package/dist/events/bus.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bus.d.ts","sourceRoot":"","sources":["../../src/events/bus.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"bus.d.ts","sourceRoot":"","sources":["../../src/events/bus.ts"],"names":[],"mappings":"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"}
|
package/dist/events/bus.js
CHANGED
|
@@ -5,11 +5,13 @@ export declare const sceneRegistry: {
|
|
|
5
5
|
site: Set<string>;
|
|
6
6
|
building: Set<string>;
|
|
7
7
|
ceiling: Set<string>;
|
|
8
|
+
column: Set<string>;
|
|
8
9
|
level: Set<string>;
|
|
9
10
|
wall: Set<string>;
|
|
10
11
|
fence: Set<string>;
|
|
11
12
|
item: Set<string>;
|
|
12
13
|
slab: Set<string>;
|
|
14
|
+
spawn: Set<string>;
|
|
13
15
|
zone: Set<string>;
|
|
14
16
|
roof: Set<string>;
|
|
15
17
|
'roof-segment': Set<string>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scene-registry.d.ts","sourceRoot":"","sources":["../../../src/hooks/scene-registry/scene-registry.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAA;AAEnC,eAAO,MAAM,aAAa
|
|
1
|
+
{"version":3,"file":"scene-registry.d.ts","sourceRoot":"","sources":["../../../src/hooks/scene-registry/scene-registry.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAA;AAEnC,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;IA4BxB,gFAAgF;;CAOjF,CAAA;AAED,wBAAgB,WAAW,CACzB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,OAAO,aAAa,CAAC,MAAM,EACvC,GAAG,EAAE,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,QAkBrC"}
|
|
@@ -9,11 +9,13 @@ export const sceneRegistry = {
|
|
|
9
9
|
site: new Set(),
|
|
10
10
|
building: new Set(),
|
|
11
11
|
ceiling: new Set(),
|
|
12
|
+
column: new Set(),
|
|
12
13
|
level: new Set(),
|
|
13
14
|
wall: new Set(),
|
|
14
15
|
fence: new Set(),
|
|
15
16
|
item: new Set(),
|
|
16
17
|
slab: new Set(),
|
|
18
|
+
spawn: new Set(),
|
|
17
19
|
zone: new Set(),
|
|
18
20
|
roof: new Set(),
|
|
19
21
|
'roof-segment': new Set(),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spatial-grid-manager.d.ts","sourceRoot":"","sources":["../../../src/hooks/spatial-grid/spatial-grid-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAA6C,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"spatial-grid-manager.d.ts","sourceRoot":"","sources":["../../../src/hooks/spatial-grid/spatial-grid-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { getScaledDimensions } from '../../schema';
|
|
1
|
+
import { getScaledDimensions, isLowProfileItemSurface } from '../../schema';
|
|
2
|
+
import useScene from '../../store/use-scene';
|
|
2
3
|
import { SpatialGrid } from './spatial-grid';
|
|
3
4
|
import { WallSpatialGrid } from './wall-spatial-grid';
|
|
4
5
|
// ============================================================================
|
|
@@ -37,6 +38,65 @@ function getItemFootprint(position, dimensions, rotation, inset = 0) {
|
|
|
37
38
|
[x + (-halfW * cos - halfD * sin), z + (-halfW * sin + halfD * cos)],
|
|
38
39
|
];
|
|
39
40
|
}
|
|
41
|
+
function getItemLocalBounds(item) {
|
|
42
|
+
const [width, height, depth] = getScaledDimensions(item);
|
|
43
|
+
const minZ = item.asset.attachTo === 'wall-side' ? -depth : -depth / 2;
|
|
44
|
+
const maxZ = item.asset.attachTo === 'wall-side' ? 0 : depth / 2;
|
|
45
|
+
return {
|
|
46
|
+
min: [-width / 2, 0, minZ],
|
|
47
|
+
max: [width / 2, height, maxZ],
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function getItemParentAabb(item) {
|
|
51
|
+
const bounds = getItemLocalBounds(item);
|
|
52
|
+
const corners = [
|
|
53
|
+
[bounds.min[0], bounds.min[1], bounds.min[2]],
|
|
54
|
+
[bounds.min[0], bounds.min[1], bounds.max[2]],
|
|
55
|
+
[bounds.min[0], bounds.max[1], bounds.min[2]],
|
|
56
|
+
[bounds.min[0], bounds.max[1], bounds.max[2]],
|
|
57
|
+
[bounds.max[0], bounds.min[1], bounds.min[2]],
|
|
58
|
+
[bounds.max[0], bounds.min[1], bounds.max[2]],
|
|
59
|
+
[bounds.max[0], bounds.max[1], bounds.min[2]],
|
|
60
|
+
[bounds.max[0], bounds.max[1], bounds.max[2]],
|
|
61
|
+
];
|
|
62
|
+
const yRot = item.rotation[1] ?? 0;
|
|
63
|
+
const cos = Math.cos(yRot);
|
|
64
|
+
const sin = Math.sin(yRot);
|
|
65
|
+
let minX = Number.POSITIVE_INFINITY;
|
|
66
|
+
let minY = Number.POSITIVE_INFINITY;
|
|
67
|
+
let minZ = Number.POSITIVE_INFINITY;
|
|
68
|
+
let maxX = Number.NEGATIVE_INFINITY;
|
|
69
|
+
let maxY = Number.NEGATIVE_INFINITY;
|
|
70
|
+
let maxZ = Number.NEGATIVE_INFINITY;
|
|
71
|
+
for (const [cx, cy, cz] of corners) {
|
|
72
|
+
const rotatedX = cx * cos + cz * sin;
|
|
73
|
+
const rotatedZ = -cx * sin + cz * cos;
|
|
74
|
+
const worldX = rotatedX + item.position[0];
|
|
75
|
+
const worldY = cy + item.position[1];
|
|
76
|
+
const worldZ = rotatedZ + item.position[2];
|
|
77
|
+
minX = Math.min(minX, worldX);
|
|
78
|
+
minY = Math.min(minY, worldY);
|
|
79
|
+
minZ = Math.min(minZ, worldZ);
|
|
80
|
+
maxX = Math.max(maxX, worldX);
|
|
81
|
+
maxY = Math.max(maxY, worldY);
|
|
82
|
+
maxZ = Math.max(maxZ, worldZ);
|
|
83
|
+
}
|
|
84
|
+
return { minX, maxX, minY, maxY, minZ, maxZ };
|
|
85
|
+
}
|
|
86
|
+
function intervalsOverlap(minA, maxA, minB, maxB, epsilon = 1e-4) {
|
|
87
|
+
return minA < maxB - epsilon && maxA > minB + epsilon;
|
|
88
|
+
}
|
|
89
|
+
function resolveNodeLevelId(node, nodes) {
|
|
90
|
+
if (node.type === 'level')
|
|
91
|
+
return node.id;
|
|
92
|
+
let current = node;
|
|
93
|
+
while (current) {
|
|
94
|
+
if (current.type === 'level')
|
|
95
|
+
return current.id;
|
|
96
|
+
current = current.parentId ? nodes[current.parentId] : undefined;
|
|
97
|
+
}
|
|
98
|
+
return 'default';
|
|
99
|
+
}
|
|
40
100
|
/**
|
|
41
101
|
* Test if two line segments (a1->a2) and (b1->b2) intersect.
|
|
42
102
|
*/
|
|
@@ -373,8 +433,40 @@ export class SpatialGridManager {
|
|
|
373
433
|
}
|
|
374
434
|
// Query methods
|
|
375
435
|
canPlaceOnFloor(levelId, position, dimensions, rotation, ignoreIds) {
|
|
376
|
-
const
|
|
377
|
-
|
|
436
|
+
const nodes = useScene.getState().nodes;
|
|
437
|
+
const ignoreSet = new Set(ignoreIds ?? []);
|
|
438
|
+
const [width, , depth] = dimensions;
|
|
439
|
+
const yRot = rotation[1];
|
|
440
|
+
const cos = Math.abs(Math.cos(yRot));
|
|
441
|
+
const sin = Math.abs(Math.sin(yRot));
|
|
442
|
+
const rotatedW = width * cos + depth * sin;
|
|
443
|
+
const rotatedD = width * sin + depth * cos;
|
|
444
|
+
const draftBounds = {
|
|
445
|
+
minX: position[0] - rotatedW / 2,
|
|
446
|
+
maxX: position[0] + rotatedW / 2,
|
|
447
|
+
minZ: position[2] - rotatedD / 2,
|
|
448
|
+
maxZ: position[2] + rotatedD / 2,
|
|
449
|
+
};
|
|
450
|
+
const conflicts = [];
|
|
451
|
+
for (const node of Object.values(nodes)) {
|
|
452
|
+
if (node.type !== 'item')
|
|
453
|
+
continue;
|
|
454
|
+
const item = node;
|
|
455
|
+
if (item.asset.attachTo)
|
|
456
|
+
continue;
|
|
457
|
+
if (isLowProfileItemSurface(item))
|
|
458
|
+
continue;
|
|
459
|
+
if (ignoreSet.has(item.id))
|
|
460
|
+
continue;
|
|
461
|
+
if (resolveNodeLevelId(item, nodes) !== levelId)
|
|
462
|
+
continue;
|
|
463
|
+
const bounds = getItemParentAabb(item);
|
|
464
|
+
if (intervalsOverlap(draftBounds.minX, draftBounds.maxX, bounds.minX, bounds.maxX) &&
|
|
465
|
+
intervalsOverlap(draftBounds.minZ, draftBounds.maxZ, bounds.minZ, bounds.maxZ)) {
|
|
466
|
+
conflicts.push(item.id);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
return { valid: conflicts.length === 0, conflictIds: conflicts };
|
|
378
470
|
}
|
|
379
471
|
/**
|
|
380
472
|
* Check if an item can be placed on a wall
|
|
@@ -396,7 +488,43 @@ export class SpatialGridManager {
|
|
|
396
488
|
// Convert local X position to parametric t (0-1)
|
|
397
489
|
const tCenter = localX / wallLength;
|
|
398
490
|
const [itemWidth, itemHeight] = dimensions;
|
|
399
|
-
|
|
491
|
+
const baseResult = this.getWallGrid(levelId).canPlaceOnWall(wallId, wallLength, wallHeight, tCenter, itemWidth, localY, itemHeight, attachType, side, ignoreIds);
|
|
492
|
+
if (!baseResult.valid)
|
|
493
|
+
return baseResult;
|
|
494
|
+
const nodes = useScene.getState().nodes;
|
|
495
|
+
const ignoreSet = new Set(ignoreIds ?? []);
|
|
496
|
+
const draftBounds = {
|
|
497
|
+
minX: localX - itemWidth / 2,
|
|
498
|
+
maxX: localX + itemWidth / 2,
|
|
499
|
+
minY: baseResult.adjustedY,
|
|
500
|
+
maxY: baseResult.adjustedY + itemHeight,
|
|
501
|
+
};
|
|
502
|
+
const conflicts = [];
|
|
503
|
+
for (const node of Object.values(nodes)) {
|
|
504
|
+
if (node.type !== 'item')
|
|
505
|
+
continue;
|
|
506
|
+
const item = node;
|
|
507
|
+
if (!(item.asset.attachTo === 'wall' || item.asset.attachTo === 'wall-side'))
|
|
508
|
+
continue;
|
|
509
|
+
if (ignoreSet.has(item.id))
|
|
510
|
+
continue;
|
|
511
|
+
if (item.parentId !== wallId)
|
|
512
|
+
continue;
|
|
513
|
+
if (attachType === 'wall-side' && item.asset.attachTo === 'wall-side' && side && item.side) {
|
|
514
|
+
if (side !== item.side)
|
|
515
|
+
continue;
|
|
516
|
+
}
|
|
517
|
+
const bounds = getItemParentAabb(item);
|
|
518
|
+
if (intervalsOverlap(draftBounds.minX, draftBounds.maxX, bounds.minX, bounds.maxX) &&
|
|
519
|
+
intervalsOverlap(draftBounds.minY, draftBounds.maxY, bounds.minY, bounds.maxY)) {
|
|
520
|
+
conflicts.push(item.id);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
return {
|
|
524
|
+
...baseResult,
|
|
525
|
+
valid: conflicts.length === 0,
|
|
526
|
+
conflictIds: conflicts,
|
|
527
|
+
};
|
|
400
528
|
}
|
|
401
529
|
getWallForItem(levelId, itemId) {
|
|
402
530
|
return this.getWallGrid(levelId).getWallForItem(itemId);
|
|
@@ -541,8 +669,38 @@ export class SpatialGridManager {
|
|
|
541
669
|
return { valid: false, conflictIds: [] };
|
|
542
670
|
}
|
|
543
671
|
}
|
|
544
|
-
|
|
545
|
-
|
|
672
|
+
const nodes = useScene.getState().nodes;
|
|
673
|
+
const ignoreSet = new Set(ignoreIds ?? []);
|
|
674
|
+
const [width, , depth] = dimensions;
|
|
675
|
+
const yRot = rotation[1];
|
|
676
|
+
const cos = Math.abs(Math.cos(yRot));
|
|
677
|
+
const sin = Math.abs(Math.sin(yRot));
|
|
678
|
+
const rotatedW = width * cos + depth * sin;
|
|
679
|
+
const rotatedD = width * sin + depth * cos;
|
|
680
|
+
const draftBounds = {
|
|
681
|
+
minX: position[0] - rotatedW / 2,
|
|
682
|
+
maxX: position[0] + rotatedW / 2,
|
|
683
|
+
minZ: position[2] - rotatedD / 2,
|
|
684
|
+
maxZ: position[2] + rotatedD / 2,
|
|
685
|
+
};
|
|
686
|
+
const conflicts = [];
|
|
687
|
+
for (const node of Object.values(nodes)) {
|
|
688
|
+
if (node.type !== 'item')
|
|
689
|
+
continue;
|
|
690
|
+
const item = node;
|
|
691
|
+
if (item.asset.attachTo !== 'ceiling')
|
|
692
|
+
continue;
|
|
693
|
+
if (ignoreSet.has(item.id))
|
|
694
|
+
continue;
|
|
695
|
+
if (item.parentId !== ceilingId)
|
|
696
|
+
continue;
|
|
697
|
+
const bounds = getItemParentAabb(item);
|
|
698
|
+
if (intervalsOverlap(draftBounds.minX, draftBounds.maxX, bounds.minX, bounds.maxX) &&
|
|
699
|
+
intervalsOverlap(draftBounds.minZ, draftBounds.maxZ, bounds.minZ, bounds.maxZ)) {
|
|
700
|
+
conflicts.push(item.id);
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
return { valid: conflicts.length === 0, conflictIds: conflicts };
|
|
546
704
|
}
|
|
547
705
|
clearLevel(levelId) {
|
|
548
706
|
this.floorGrids.delete(levelId);
|
package/dist/index.d.ts
CHANGED
|
@@ -1,30 +1,23 @@
|
|
|
1
|
-
export type { BuildingEvent, CameraControlEvent, CeilingEvent, DoorEvent, EventSuffix, FenceEvent, GridEvent, ItemEvent, LevelEvent, NodeEvent, RoofEvent, RoofSegmentEvent, SiteEvent, SlabEvent, StairEvent, StairSegmentEvent, WallEvent, WindowEvent, ZoneEvent, } from './events/bus';
|
|
1
|
+
export type { BuildingEvent, CameraControlEvent, CameraControlFitSceneEvent, CeilingEvent, ColumnEvent, DoorEvent, EventSuffix, FenceEvent, GridEvent, ItemEvent, LevelEvent, NodeEvent, RoofEvent, RoofSegmentEvent, SiteEvent, SlabEvent, SpawnEvent, StairEvent, StairSegmentEvent, WallEvent, WindowEvent, ZoneEvent, } from './events/bus';
|
|
2
2
|
export { emitter, eventSuffixes } from './events/bus';
|
|
3
3
|
export { sceneRegistry, useRegistry, } from './hooks/scene-registry/scene-registry';
|
|
4
4
|
export { pointInPolygon, spatialGridManager } from './hooks/spatial-grid/spatial-grid-manager';
|
|
5
5
|
export { initSpatialGridSync, resolveLevelId, } from './hooks/spatial-grid/spatial-grid-sync';
|
|
6
6
|
export { useSpatialQuery } from './hooks/spatial-grid/use-spatial-query';
|
|
7
7
|
export { loadAssetUrl, saveAsset } from './lib/asset-storage';
|
|
8
|
+
export { clampDoorOperationState, getDoorRenderOpenAmount, getGarageVisibleOpeningRatio, isOperationDoorType, SECTIONAL_GARAGE_RENDER_OPEN_SCALE, } from './lib/door-operation';
|
|
9
|
+
export { getRenderableSlabPolygon } from './lib/slab-polygon';
|
|
8
10
|
export { detectSpacesForLevel, initSpaceDetectionSync, type Space, wallTouchesOthers, } from './lib/space-detection';
|
|
9
|
-
export {
|
|
10
|
-
export { getCatalogMaterialById, getLibraryMaterialIdFromRef, getMaterialPresetByRef, getMaterialsForTarget, LIBRARY_MATERIAL_REF_PREFIX, MATERIAL_CATALOG, type MaterialCatalogItem, toLibraryMaterialRef, } from './material-library';
|
|
11
|
+
export { getCatalogMaterialById, getLibraryMaterialIdFromRef, getMaterialPresetByRef, getMaterialsForCategory, LIBRARY_MATERIAL_REF_PREFIX, MATERIAL_CATALOG, MATERIAL_CATEGORIES, type MaterialCatalogItem, type MaterialCategory, toLibraryMaterialRef, } from './material-library';
|
|
11
12
|
export * from './schema';
|
|
12
|
-
export { type ControlValue, type ItemInteractiveState, useInteractive, } from './store/use-interactive';
|
|
13
13
|
export { getSceneHistoryPauseDepth, pauseSceneHistory, resetSceneHistoryPauseDepth, resumeSceneHistory, } from './store/history-control';
|
|
14
|
+
export { type ControlValue, type DoorAnimationState, type DoorInteractiveState, type ItemInteractiveState, useInteractive, type WindowAnimationState, type WindowInteractiveState, } from './store/use-interactive';
|
|
14
15
|
export { default as useLiveTransforms, type LiveTransform } from './store/use-live-transforms';
|
|
15
|
-
export { FenceSystem } from './systems/fence/fence-system';
|
|
16
16
|
export { clearSceneHistory, default as useScene } from './store/use-scene';
|
|
17
|
-
export {
|
|
18
|
-
export { DoorSystem } from './systems/door/door-system';
|
|
19
|
-
export { ItemSystem } from './systems/item/item-system';
|
|
20
|
-
export { RoofSystem } from './systems/roof/roof-system';
|
|
21
|
-
export { SlabSystem } from './systems/slab/slab-system';
|
|
22
|
-
export { StairSystem } from './systems/stair/stair-system';
|
|
23
|
-
export { DEFAULT_WALL_HEIGHT, DEFAULT_WALL_THICKNESS, getWallPlanFootprint, getWallThickness, } from './systems/wall/wall-footprint';
|
|
17
|
+
export { syncAutoStairOpenings } from './systems/stair/stair-opening-sync';
|
|
24
18
|
export { getClampedWallCurveOffset, getMaxWallCurveOffset, getWallChordFrame, getWallCurveFrameAt, getWallCurveLength, getWallMidpointHandlePoint, getWallStraightSnapOffset, getWallSurfacePolygon, isCurvedWall, normalizeWallCurveOffset, sampleWallCenterline, } from './systems/wall/wall-curve';
|
|
25
|
-
export {
|
|
26
|
-
export {
|
|
27
|
-
export { WindowSystem } from './systems/window/window-system';
|
|
19
|
+
export { DEFAULT_WALL_HEIGHT, DEFAULT_WALL_THICKNESS, getWallPlanFootprint, getWallThickness, } from './systems/wall/wall-footprint';
|
|
20
|
+
export { calculateLevelMiters, getAdjacentWallIds, getWallMiterBoundaryPoints, type Point2D, pointToKey, type WallMiterBoundaryPoints, type WallMiterData, } from './systems/wall/wall-mitering';
|
|
28
21
|
export type { SceneGraph } from './utils/clone-scene-graph';
|
|
29
22
|
export { cloneLevelSubtree, cloneSceneGraph, forkSceneGraph } from './utils/clone-scene-graph';
|
|
30
23
|
export { isObject } from './utils/types';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,aAAa,EACb,kBAAkB,EAClB,YAAY,EACZ,SAAS,EACT,WAAW,EACX,UAAU,EACV,SAAS,EACT,SAAS,EACT,UAAU,EACV,SAAS,EACT,SAAS,EACT,gBAAgB,EAChB,SAAS,EACT,SAAS,EACT,UAAU,EACV,iBAAiB,EACjB,SAAS,EACT,WAAW,EACX,SAAS,GACV,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AACrD,OAAO,EACL,aAAa,EACb,WAAW,GACZ,MAAM,uCAAuC,CAAA;AAC9C,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,2CAA2C,CAAA;AAC9F,OAAO,EACL,mBAAmB,EACnB,cAAc,GACf,MAAM,wCAAwC,CAAA;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,wCAAwC,CAAA;AACxE,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAC7D,OAAO,EACL,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,aAAa,EACb,kBAAkB,EAClB,0BAA0B,EAC1B,YAAY,EACZ,WAAW,EACX,SAAS,EACT,WAAW,EACX,UAAU,EACV,SAAS,EACT,SAAS,EACT,UAAU,EACV,SAAS,EACT,SAAS,EACT,gBAAgB,EAChB,SAAS,EACT,SAAS,EACT,UAAU,EACV,UAAU,EACV,iBAAiB,EACjB,SAAS,EACT,WAAW,EACX,SAAS,GACV,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AACrD,OAAO,EACL,aAAa,EACb,WAAW,GACZ,MAAM,uCAAuC,CAAA;AAC9C,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,2CAA2C,CAAA;AAC9F,OAAO,EACL,mBAAmB,EACnB,cAAc,GACf,MAAM,wCAAwC,CAAA;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,wCAAwC,CAAA;AACxE,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAC7D,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EACvB,4BAA4B,EAC5B,mBAAmB,EACnB,kCAAkC,GACnC,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAA;AAC7D,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,KAAK,KAAK,EACV,iBAAiB,GAClB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACL,sBAAsB,EACtB,2BAA2B,EAC3B,sBAAsB,EACtB,uBAAuB,EACvB,2BAA2B,EAC3B,gBAAgB,EAChB,mBAAmB,EACnB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,oBAAoB,GACrB,MAAM,oBAAoB,CAAA;AAC3B,cAAc,UAAU,CAAA;AACxB,OAAO,EACL,yBAAyB,EACzB,iBAAiB,EACjB,2BAA2B,EAC3B,kBAAkB,GACnB,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,cAAc,EACd,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,GAC5B,MAAM,yBAAyB,CAAA;AAChC,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,KAAK,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAC9F,OAAO,EAAE,iBAAiB,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC1E,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAA;AAC1E,OAAO,EACL,yBAAyB,EACzB,qBAAqB,EACrB,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,0BAA0B,EAC1B,yBAAyB,EACzB,qBAAqB,EACrB,YAAY,EACZ,wBAAwB,EACxB,oBAAoB,GACrB,MAAM,2BAA2B,CAAA;AAClC,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,+BAA+B,CAAA;AACtC,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,0BAA0B,EAC1B,KAAK,OAAO,EACZ,UAAU,EACV,KAAK,uBAAuB,EAC5B,KAAK,aAAa,GACnB,MAAM,8BAA8B,CAAA;AACrC,YAAY,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAA;AAC3D,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAC9F,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -4,25 +4,18 @@ export { pointInPolygon, spatialGridManager } from './hooks/spatial-grid/spatial
|
|
|
4
4
|
export { initSpatialGridSync, resolveLevelId, } from './hooks/spatial-grid/spatial-grid-sync';
|
|
5
5
|
export { useSpatialQuery } from './hooks/spatial-grid/use-spatial-query';
|
|
6
6
|
export { loadAssetUrl, saveAsset } from './lib/asset-storage';
|
|
7
|
+
export { clampDoorOperationState, getDoorRenderOpenAmount, getGarageVisibleOpeningRatio, isOperationDoorType, SECTIONAL_GARAGE_RENDER_OPEN_SCALE, } from './lib/door-operation';
|
|
8
|
+
export { getRenderableSlabPolygon } from './lib/slab-polygon';
|
|
7
9
|
export { detectSpacesForLevel, initSpaceDetectionSync, wallTouchesOthers, } from './lib/space-detection';
|
|
8
|
-
export {
|
|
9
|
-
export { getCatalogMaterialById, getLibraryMaterialIdFromRef, getMaterialPresetByRef, getMaterialsForTarget, LIBRARY_MATERIAL_REF_PREFIX, MATERIAL_CATALOG, toLibraryMaterialRef, } from './material-library';
|
|
10
|
+
export { getCatalogMaterialById, getLibraryMaterialIdFromRef, getMaterialPresetByRef, getMaterialsForCategory, LIBRARY_MATERIAL_REF_PREFIX, MATERIAL_CATALOG, MATERIAL_CATEGORIES, toLibraryMaterialRef, } from './material-library';
|
|
10
11
|
export * from './schema';
|
|
11
|
-
export { useInteractive, } from './store/use-interactive';
|
|
12
12
|
export { getSceneHistoryPauseDepth, pauseSceneHistory, resetSceneHistoryPauseDepth, resumeSceneHistory, } from './store/history-control';
|
|
13
|
+
export { useInteractive, } from './store/use-interactive';
|
|
13
14
|
export { default as useLiveTransforms } from './store/use-live-transforms';
|
|
14
|
-
export { FenceSystem } from './systems/fence/fence-system';
|
|
15
15
|
export { clearSceneHistory, default as useScene } from './store/use-scene';
|
|
16
|
-
export {
|
|
17
|
-
export { DoorSystem } from './systems/door/door-system';
|
|
18
|
-
export { ItemSystem } from './systems/item/item-system';
|
|
19
|
-
export { RoofSystem } from './systems/roof/roof-system';
|
|
20
|
-
export { SlabSystem } from './systems/slab/slab-system';
|
|
21
|
-
export { StairSystem } from './systems/stair/stair-system';
|
|
22
|
-
export { DEFAULT_WALL_HEIGHT, DEFAULT_WALL_THICKNESS, getWallPlanFootprint, getWallThickness, } from './systems/wall/wall-footprint';
|
|
16
|
+
export { syncAutoStairOpenings } from './systems/stair/stair-opening-sync';
|
|
23
17
|
export { getClampedWallCurveOffset, getMaxWallCurveOffset, getWallChordFrame, getWallCurveFrameAt, getWallCurveLength, getWallMidpointHandlePoint, getWallStraightSnapOffset, getWallSurfacePolygon, isCurvedWall, normalizeWallCurveOffset, sampleWallCenterline, } from './systems/wall/wall-curve';
|
|
24
|
-
export {
|
|
25
|
-
export {
|
|
26
|
-
export { WindowSystem } from './systems/window/window-system';
|
|
18
|
+
export { DEFAULT_WALL_HEIGHT, DEFAULT_WALL_THICKNESS, getWallPlanFootprint, getWallThickness, } from './systems/wall/wall-footprint';
|
|
19
|
+
export { calculateLevelMiters, getAdjacentWallIds, getWallMiterBoundaryPoints, pointToKey, } from './systems/wall/wall-mitering';
|
|
27
20
|
export { cloneLevelSubtree, cloneSceneGraph, forkSceneGraph } from './utils/clone-scene-graph';
|
|
28
21
|
export { isObject } from './utils/types';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { DoorNode, DoorType } from '../schema/nodes/door';
|
|
2
|
+
export declare const SECTIONAL_GARAGE_RENDER_OPEN_SCALE = 0.88;
|
|
3
|
+
export declare function clampDoorOperationState(value: number | undefined): number;
|
|
4
|
+
export declare function isOperationDoorType(doorType: DoorType | DoorNode['doorType'] | string | undefined): doorType is "folding" | "pocket" | "barn" | "sliding" | "garage-sectional" | "garage-rollup" | "garage-tiltup";
|
|
5
|
+
export declare function getDoorRenderOpenAmount(doorType: DoorType | DoorNode['doorType'], operationState: number | undefined): number;
|
|
6
|
+
export declare function getGarageVisibleOpeningRatio(doorType: DoorType | DoorNode['doorType'], operationState: number | undefined): number;
|
|
7
|
+
//# sourceMappingURL=door-operation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"door-operation.d.ts","sourceRoot":"","sources":["../../src/lib/door-operation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAE9D,eAAO,MAAM,kCAAkC,OAAO,CAAA;AAEtD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,UAEhE;AAED,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,QAAQ,GAAG,QAAQ,CAAC,UAAU,CAAC,GAAG,MAAM,GAAG,SAAS,kHAW/D;AAED,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,QAAQ,GAAG,QAAQ,CAAC,UAAU,CAAC,EACzC,cAAc,EAAE,MAAM,GAAG,SAAS,UAMnC;AAED,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,QAAQ,GAAG,QAAQ,CAAC,UAAU,CAAC,EACzC,cAAc,EAAE,MAAM,GAAG,SAAS,UAOnC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export const SECTIONAL_GARAGE_RENDER_OPEN_SCALE = 0.88;
|
|
2
|
+
export function clampDoorOperationState(value) {
|
|
3
|
+
return Math.max(0, Math.min(1, value ?? 0));
|
|
4
|
+
}
|
|
5
|
+
export function isOperationDoorType(doorType) {
|
|
6
|
+
return (doorType === 'folding' ||
|
|
7
|
+
doorType === 'pocket' ||
|
|
8
|
+
doorType === 'barn' ||
|
|
9
|
+
doorType === 'sliding' ||
|
|
10
|
+
doorType === 'garage-sectional' ||
|
|
11
|
+
doorType === 'garage-rollup' ||
|
|
12
|
+
doorType === 'garage-tiltup');
|
|
13
|
+
}
|
|
14
|
+
export function getDoorRenderOpenAmount(doorType, operationState) {
|
|
15
|
+
const openAmount = clampDoorOperationState(operationState);
|
|
16
|
+
return doorType === 'garage-sectional'
|
|
17
|
+
? openAmount * SECTIONAL_GARAGE_RENDER_OPEN_SCALE
|
|
18
|
+
: openAmount;
|
|
19
|
+
}
|
|
20
|
+
export function getGarageVisibleOpeningRatio(doorType, operationState) {
|
|
21
|
+
if (doorType === 'garage-sectional') {
|
|
22
|
+
return Math.min(1, clampDoorOperationState(operationState) / SECTIONAL_GARAGE_RENDER_OPEN_SCALE);
|
|
23
|
+
}
|
|
24
|
+
return clampDoorOperationState(operationState);
|
|
25
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"polygon-geometry.d.ts","sourceRoot":"","sources":["../../src/lib/polygon-geometry.ts"],"names":[],"mappings":"AAAA,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAChC,KAAK,EAAE,MAAM,GACZ,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"polygon-geometry.d.ts","sourceRoot":"","sources":["../../src/lib/polygon-geometry.ts"],"names":[],"mappings":"AAAA,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAChC,KAAK,EAAE,MAAM,GACZ,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAoBzB;AA0ED,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAChC,SAAS,EAAE,MAAM,GAChB,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAiCzB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slab-polygon.d.ts","sourceRoot":"","sources":["../../src/lib/slab-polygon.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAQzC,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,QAAQ,GAAG,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAOpF"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { insetPolygonFromCentroid, simplifyClosedPolygon } from './polygon-geometry';
|
|
2
|
+
/** Half of default wall thickness — used to extend slab geometry under walls */
|
|
3
|
+
const SLAB_OUTSET = 0.05;
|
|
4
|
+
const AUTO_SLAB_INSET = 0.02;
|
|
5
|
+
const AUTO_SLAB_SIMPLIFY_TOLERANCE = 0.08;
|
|
6
|
+
export function getRenderableSlabPolygon(slabNode) {
|
|
7
|
+
return slabNode.autoFromWalls
|
|
8
|
+
? simplifyClosedPolygon(insetPolygonFromCentroid(slabNode.polygon, AUTO_SLAB_INSET), AUTO_SLAB_SIMPLIFY_TOLERANCE)
|
|
9
|
+
: outsetPolygon(slabNode.polygon, SLAB_OUTSET);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Expand a polygon outward by a uniform distance.
|
|
13
|
+
* Offsets each edge outward then intersects consecutive offset edges.
|
|
14
|
+
*/
|
|
15
|
+
function outsetPolygon(polygon, amount) {
|
|
16
|
+
const n = polygon.length;
|
|
17
|
+
if (n < 3)
|
|
18
|
+
return polygon;
|
|
19
|
+
// Determine winding via signed area
|
|
20
|
+
let area2 = 0;
|
|
21
|
+
for (let i = 0; i < n; i++) {
|
|
22
|
+
const j = (i + 1) % n;
|
|
23
|
+
area2 += polygon[i][0] * polygon[j][1] - polygon[j][0] * polygon[i][1];
|
|
24
|
+
}
|
|
25
|
+
const s = area2 >= 0 ? 1 : -1;
|
|
26
|
+
// Offset each edge outward by amount
|
|
27
|
+
const offEdges = [];
|
|
28
|
+
for (let i = 0; i < n; i++) {
|
|
29
|
+
const j = (i + 1) % n;
|
|
30
|
+
const dx = polygon[j][0] - polygon[i][0];
|
|
31
|
+
const dz = polygon[j][1] - polygon[i][1];
|
|
32
|
+
const len = Math.sqrt(dx * dx + dz * dz);
|
|
33
|
+
if (len < 1e-9) {
|
|
34
|
+
offEdges.push([polygon[i][0], polygon[i][1], dx, dz]);
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
const nx = ((s * dz) / len) * amount;
|
|
38
|
+
const nz = ((s * -dx) / len) * amount;
|
|
39
|
+
offEdges.push([polygon[i][0] + nx, polygon[i][1] + nz, dx, dz]);
|
|
40
|
+
}
|
|
41
|
+
// Intersect consecutive offset edges to get new vertices
|
|
42
|
+
const result = [];
|
|
43
|
+
for (let i = 0; i < n; i++) {
|
|
44
|
+
const j = (i + 1) % n;
|
|
45
|
+
const [ax, az, adx, adz] = offEdges[i];
|
|
46
|
+
const [bx, bz, bdx, bdz] = offEdges[j];
|
|
47
|
+
const denom = adx * bdz - adz * bdx;
|
|
48
|
+
if (Math.abs(denom) < 1e-9) {
|
|
49
|
+
// Parallel edges — use offset endpoint
|
|
50
|
+
result.push([ax + adx, az + adz]);
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
const t = ((bx - ax) * bdz - (bz - az) * bdx) / denom;
|
|
54
|
+
result.push([ax + t * adx, az + t * adz]);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return result;
|
|
58
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"space-detection.d.ts","sourceRoot":"","sources":["../../src/lib/space-detection.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"space-detection.d.ts","sourceRoot":"","sources":["../../src/lib/space-detection.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,QAAQ,EACd,MAAM,WAAW,CAAA;AAalB,KAAK,OAAO,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAEvC,MAAM,MAAM,KAAK,GAAG;IAClB,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IAChC,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,UAAU,EAAE,OAAO,CAAA;CACpB,CAAA;AAED,KAAK,cAAc,GAAG;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,UAAU,GAAG,UAAU,GAAG,SAAS,CAAA;IAC9C,QAAQ,EAAE,UAAU,GAAG,UAAU,GAAG,SAAS,CAAA;CAC9C,CAAA;AAkWD,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,OAAO,GAAG,KAAK,GAAG,WAAW,GAAG,WAAW,GAAG,UAAU,CAAC,EAC9E,YAAY,EAAE,OAAO,EAAE,EAAE,GACxB,IAAI,CAAC,cAAc,EAAE,WAAW,GAAG,UAAU,CAAC,CA4ChD;AAyWD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE;;;;EAEtE;AAsED,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,GAAG,EAAE,WAAW,EAAE,GAAG,GAAG,MAAM,IAAI,CAuDpF;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,OAAO,CAiBjF"}
|