@pascal-app/core 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/capture/index.d.ts +2 -2
- package/dist/capture/index.js +2 -2
- package/dist/capture/schema.d.ts.map +1 -1
- package/dist/capture/schema.js +2 -0
- package/dist/capture/source.d.ts +1 -1
- package/dist/capture/source.js +1 -1
- package/dist/events/bus.d.ts +6 -3
- package/dist/events/bus.d.ts.map +1 -1
- package/dist/hooks/spatial-grid/floor-placed-elevation.d.ts +4 -4
- package/dist/hooks/spatial-grid/floor-placed-elevation.d.ts.map +1 -1
- package/dist/hooks/spatial-grid/floor-placed-elevation.js +7 -12
- package/dist/hooks/spatial-grid/floor-placed-footprints.d.ts +4 -0
- package/dist/hooks/spatial-grid/floor-placed-footprints.d.ts.map +1 -0
- package/dist/hooks/spatial-grid/floor-placed-footprints.js +7 -0
- package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts +5 -8
- package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts.map +1 -1
- package/dist/hooks/spatial-grid/spatial-grid-manager.js +23 -106
- package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts +221 -76
- package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts.map +1 -1
- package/dist/hooks/spatial-grid/spatial-grid-sync.js +77 -13
- package/dist/hooks/spatial-grid/support-host-patch.d.ts +1 -1
- package/dist/hooks/spatial-grid/support-host-patch.js +6 -6
- package/dist/hooks/spatial-grid/use-spatial-query.d.ts +1 -1
- package/dist/hooks/spatial-grid/use-spatial-query.js +1 -1
- package/dist/index.d.ts +74 -72
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +71 -69
- package/dist/lib/door-operation.d.ts +1 -1
- package/dist/lib/item-polygon-overlap.d.ts +6 -0
- package/dist/lib/item-polygon-overlap.d.ts.map +1 -0
- package/dist/lib/item-polygon-overlap.js +67 -0
- package/dist/lib/level-name.d.ts +1 -1
- package/dist/lib/measurement-geometry.d.ts +4 -4
- package/dist/lib/plan-footprint.d.ts +41 -0
- package/dist/lib/plan-footprint.d.ts.map +1 -0
- package/dist/lib/plan-footprint.js +58 -0
- package/dist/lib/room-topology-index.d.ts +1 -1
- package/dist/lib/room-topology-index.js +1 -1
- package/dist/lib/selection-proxy.d.ts +1 -1
- package/dist/lib/slab-polygon.d.ts +2 -2
- package/dist/lib/slab-polygon.js +2 -2
- package/dist/lib/space-detection.d.ts +1 -1
- package/dist/lib/space-detection.d.ts.map +1 -1
- package/dist/lib/space-detection.js +16 -11
- package/dist/lib/terrain-brush.d.ts +1 -1
- package/dist/lib/terrain-brush.js +1 -1
- package/dist/lib/terrain-codec.d.ts +2 -2
- package/dist/lib/terrain-codec.js +1 -1
- package/dist/lib/terrain-raycast.d.ts +1 -1
- package/dist/lib/terrain-raycast.js +1 -1
- package/dist/lib/terrain-source.d.ts +3 -3
- package/dist/lib/terrain-source.js +3 -3
- package/dist/lib/terrain-support.d.ts +1 -1
- package/dist/lib/terrain-support.js +3 -3
- package/dist/lib/unit-containment.d.ts +19 -0
- package/dist/lib/unit-containment.d.ts.map +1 -0
- package/dist/lib/unit-containment.js +158 -0
- package/dist/lib/unit-report.d.ts +19 -0
- package/dist/lib/unit-report.d.ts.map +1 -0
- package/dist/lib/unit-report.js +36 -0
- package/dist/lib/wall-distance.d.ts +2 -2
- package/dist/lib/wall-distance.js +1 -1
- package/dist/lib/zone-quantities.d.ts +1 -1
- package/dist/lib/zone-quantities.js +7 -7
- package/dist/material-library.d.ts +1 -1
- package/dist/material-library.js +1 -1
- package/dist/procedural-items/fixtures.d.ts +261 -0
- package/dist/procedural-items/fixtures.d.ts.map +1 -0
- package/dist/procedural-items/fixtures.js +349 -0
- package/dist/procedural-items/index.d.ts +10 -0
- package/dist/procedural-items/index.d.ts.map +1 -0
- package/dist/procedural-items/index.js +9 -0
- package/dist/procedural-items/integration.d.ts +92 -0
- package/dist/procedural-items/integration.d.ts.map +1 -0
- package/dist/procedural-items/integration.js +19 -0
- package/dist/procedural-items/library-colors.d.ts +56 -0
- package/dist/procedural-items/library-colors.d.ts.map +1 -0
- package/dist/procedural-items/library-colors.js +84 -0
- package/dist/procedural-items/materials.d.ts +5 -0
- package/dist/procedural-items/materials.d.ts.map +1 -0
- package/dist/procedural-items/materials.js +47 -0
- package/dist/procedural-items/node.d.ts +280 -0
- package/dist/procedural-items/node.d.ts.map +1 -0
- package/dist/procedural-items/node.js +71 -0
- package/dist/procedural-items/placement.d.ts +7 -0
- package/dist/procedural-items/placement.d.ts.map +1 -0
- package/dist/procedural-items/placement.js +48 -0
- package/dist/procedural-items/query.d.ts +50 -0
- package/dist/procedural-items/query.d.ts.map +1 -0
- package/dist/procedural-items/query.js +298 -0
- package/dist/procedural-items/recipe.d.ts +144 -0
- package/dist/procedural-items/recipe.d.ts.map +1 -0
- package/dist/procedural-items/recipe.js +372 -0
- package/dist/procedural-items/spatial.d.ts +19 -0
- package/dist/procedural-items/spatial.d.ts.map +1 -0
- package/dist/procedural-items/spatial.js +39 -0
- package/dist/registry/__bench__/relations-resolver.bench.js +2 -2
- package/dist/registry/handles.d.ts +12 -4
- package/dist/registry/handles.d.ts.map +1 -1
- package/dist/registry/index.d.ts +6 -6
- package/dist/registry/index.js +4 -4
- package/dist/registry/registry.d.ts +1 -1
- package/dist/registry/relations-resolver.d.ts +2 -2
- package/dist/registry/relations-resolver.js +1 -1
- package/dist/registry/scene-api.d.ts +2 -2
- package/dist/registry/scene-api.js +2 -2
- package/dist/registry/subtree.d.ts +1 -1
- package/dist/registry/subtree.js +2 -2
- package/dist/registry/types.d.ts +21 -9
- package/dist/registry/types.d.ts.map +1 -1
- package/dist/registry/use-registry-version.js +1 -1
- package/dist/registry/validate-relations.d.ts +4 -0
- package/dist/registry/validate-relations.d.ts.map +1 -0
- package/dist/registry/validate-relations.js +22 -0
- package/dist/schema/__bench__/node-parsers.bench.js +3 -3
- package/dist/schema/__fixtures__/node-fixtures.d.ts +1 -1
- package/dist/schema/__fixtures__/node-fixtures.d.ts.map +1 -1
- package/dist/schema/__fixtures__/node-fixtures.js +4 -2
- package/dist/schema/base.js +1 -1
- package/dist/schema/collections.d.ts +1 -1
- package/dist/schema/collections.js +1 -1
- package/dist/schema/compiled-node-parsers.d.ts +1 -1
- package/dist/schema/compiled-node-parsers.js +1 -1
- package/dist/schema/index.d.ts +73 -70
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +64 -61
- package/dist/schema/material.d.ts +1 -1
- package/dist/schema/material.js +1 -1
- package/dist/schema/nodes/automatic-downspout.d.ts +4 -4
- package/dist/schema/nodes/automatic-downspout.js +5 -5
- package/dist/schema/nodes/block.d.ts +1 -1
- package/dist/schema/nodes/block.d.ts.map +1 -1
- package/dist/schema/nodes/block.js +3 -4
- package/dist/schema/nodes/box-vent.js +2 -2
- package/dist/schema/nodes/building.d.ts +1 -1
- package/dist/schema/nodes/building.d.ts.map +1 -1
- package/dist/schema/nodes/building.js +8 -5
- package/dist/schema/nodes/cabinet.d.ts +2 -2
- package/dist/schema/nodes/cabinet.js +4 -4
- package/dist/schema/nodes/ceiling.d.ts +1 -1
- package/dist/schema/nodes/ceiling.js +5 -5
- package/dist/schema/nodes/chimney.js +2 -2
- 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 +3 -2
- package/dist/schema/nodes/construction-dimension.d.ts +3 -3
- package/dist/schema/nodes/construction-dimension.js +2 -2
- package/dist/schema/nodes/cupola.d.ts +1 -1
- package/dist/schema/nodes/cupola.js +2 -2
- package/dist/schema/nodes/door.js +2 -2
- package/dist/schema/nodes/dormer.d.ts +3 -3
- package/dist/schema/nodes/dormer.js +4 -4
- package/dist/schema/nodes/downspout.js +2 -2
- package/dist/schema/nodes/duct-fitting.js +1 -1
- package/dist/schema/nodes/duct-segment.js +2 -2
- package/dist/schema/nodes/duct-terminal.js +1 -1
- package/dist/schema/nodes/elevator.js +2 -2
- package/dist/schema/nodes/eyebrow-vent.js +2 -2
- package/dist/schema/nodes/fence.js +2 -2
- package/dist/schema/nodes/guide.js +2 -2
- package/dist/schema/nodes/gutter.d.ts +1 -1
- package/dist/schema/nodes/gutter.js +4 -4
- package/dist/schema/nodes/hvac-equipment.js +1 -1
- package/dist/schema/nodes/imported-mesh.d.ts +40 -0
- package/dist/schema/nodes/imported-mesh.d.ts.map +1 -0
- package/dist/schema/nodes/imported-mesh.js +27 -0
- package/dist/schema/nodes/item.d.ts +3 -3
- package/dist/schema/nodes/item.js +3 -3
- package/dist/schema/nodes/lean-to-extension.js +4 -4
- 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 +1 -1
- package/dist/schema/nodes/lineset.js +1 -1
- package/dist/schema/nodes/liquid-line.js +1 -1
- package/dist/schema/nodes/measurement.js +2 -2
- package/dist/schema/nodes/pipe-fitting.d.ts +1 -1
- package/dist/schema/nodes/pipe-fitting.js +1 -1
- package/dist/schema/nodes/pipe-segment.d.ts +1 -1
- package/dist/schema/nodes/pipe-segment.js +2 -2
- package/dist/schema/nodes/pipe-trap.d.ts +1 -1
- package/dist/schema/nodes/pipe-trap.js +1 -1
- package/dist/schema/nodes/ridge-vent.d.ts +1 -1
- package/dist/schema/nodes/ridge-vent.js +3 -3
- package/dist/schema/nodes/roof-segment-shape.d.ts +1 -1
- package/dist/schema/nodes/roof-segment-shape.js +1 -1
- package/dist/schema/nodes/roof-segment-walls.d.ts +1 -1
- package/dist/schema/nodes/roof-segment-walls.js +1 -1
- package/dist/schema/nodes/roof-segment.d.ts +2 -2
- package/dist/schema/nodes/roof-segment.js +2 -2
- package/dist/schema/nodes/roof.d.ts +1 -1
- package/dist/schema/nodes/roof.js +3 -3
- package/dist/schema/nodes/scan.js +3 -3
- package/dist/schema/nodes/shelf.d.ts +1 -1
- package/dist/schema/nodes/shelf.d.ts.map +1 -1
- package/dist/schema/nodes/shelf.js +3 -4
- package/dist/schema/nodes/site.js +2 -2
- package/dist/schema/nodes/skylight.d.ts +4 -4
- package/dist/schema/nodes/skylight.js +2 -2
- package/dist/schema/nodes/slab.js +3 -3
- package/dist/schema/nodes/solar-panel.js +3 -3
- package/dist/schema/nodes/spawn.js +1 -1
- package/dist/schema/nodes/stair-segment.js +2 -2
- package/dist/schema/nodes/stair.d.ts +1 -1
- package/dist/schema/nodes/stair.js +3 -3
- package/dist/schema/nodes/structural-grid.js +1 -1
- package/dist/schema/nodes/turbine-vent.d.ts +1 -1
- package/dist/schema/nodes/turbine-vent.js +2 -2
- package/dist/schema/nodes/unit.d.ts +33 -0
- package/dist/schema/nodes/unit.d.ts.map +1 -0
- package/dist/schema/nodes/unit.js +13 -0
- package/dist/schema/nodes/wall.d.ts +2 -2
- package/dist/schema/nodes/wall.d.ts.map +1 -1
- package/dist/schema/nodes/wall.js +7 -6
- package/dist/schema/nodes/window.js +2 -2
- package/dist/schema/nodes/zone.js +1 -1
- package/dist/schema/scene-material.js +2 -2
- package/dist/schema/types.d.ts +341 -19
- package/dist/schema/types.d.ts.map +1 -1
- package/dist/schema/types.js +56 -49
- package/dist/services/alignment-anchors.d.ts +6 -11
- package/dist/services/alignment-anchors.d.ts.map +1 -1
- package/dist/services/alignment-anchors.js +7 -34
- package/dist/services/drag-session.d.ts +4 -4
- package/dist/services/drag-session.js +1 -1
- package/dist/services/hosting.d.ts +2 -8
- package/dist/services/hosting.d.ts.map +1 -1
- package/dist/services/hosting.js +2 -12
- package/dist/services/index.d.ts +16 -13
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/index.js +16 -13
- package/dist/services/level-height.d.ts +2 -2
- package/dist/services/level-height.js +3 -3
- package/dist/services/movement.d.ts +3 -3
- package/dist/services/movement.js +2 -2
- package/dist/services/port-connectivity.d.ts +1 -1
- package/dist/services/port-connectivity.js +1 -1
- package/dist/services/riser-diagram.d.ts +1 -1
- package/dist/services/shelf-board.d.ts +5 -0
- package/dist/services/shelf-board.d.ts.map +1 -0
- package/dist/services/shelf-board.js +15 -0
- package/dist/services/storey.d.ts +2 -2
- package/dist/services/storey.js +2 -2
- package/dist/services/surface-hosting-procedural-parity.fixtures.d.ts +13 -0
- package/dist/services/surface-hosting-procedural-parity.fixtures.d.ts.map +1 -0
- package/dist/services/surface-hosting-procedural-parity.fixtures.js +4691 -0
- package/dist/services/surface-hosting-shelf-parity.fixtures.d.ts +1060 -0
- package/dist/services/surface-hosting-shelf-parity.fixtures.d.ts.map +1 -0
- package/dist/services/surface-hosting-shelf-parity.fixtures.js +3127 -0
- package/dist/services/surface-hosting.d.ts +88 -0
- package/dist/services/surface-hosting.d.ts.map +1 -0
- package/dist/services/surface-hosting.js +268 -0
- package/dist/services/surface-region.d.ts +8 -0
- package/dist/services/surface-region.d.ts.map +1 -0
- package/dist/services/surface-region.js +44 -0
- package/dist/services/system-graph.d.ts +2 -2
- package/dist/services/system-graph.js +2 -2
- package/dist/services/validate-dwv.d.ts +1 -1
- package/dist/services/validate-dwv.js +1 -1
- package/dist/store/actions/node-actions.d.ts +2 -2
- package/dist/store/actions/node-actions.d.ts.map +1 -1
- package/dist/store/actions/node-actions.js +48 -9
- package/dist/store/history-control.d.ts +3 -3
- package/dist/store/history-invalidation.d.ts +1 -1
- package/dist/store/history-invalidation.js +1 -1
- package/dist/store/use-interactive.d.ts +2 -2
- package/dist/store/use-live-terrain.d.ts +1 -1
- package/dist/store/use-scene.d.ts +4 -4
- package/dist/store/use-scene.d.ts.map +1 -1
- package/dist/store/use-scene.js +37 -31
- package/dist/systems/elevator/elevator-dispatch.d.ts +2 -2
- package/dist/systems/elevator/elevator-dispatch.js +1 -1
- package/dist/systems/elevator/elevator-geometry.d.ts +1 -1
- package/dist/systems/elevator/elevator-opening-sync.d.ts +1 -1
- package/dist/systems/elevator/elevator-opening-sync.js +2 -2
- package/dist/systems/elevator/elevator-opening-system.js +3 -3
- package/dist/systems/elevator/elevator-runtime.d.ts +3 -3
- package/dist/systems/elevator/elevator-runtime.js +3 -3
- package/dist/systems/elevator/elevator-service.d.ts +1 -1
- package/dist/systems/elevator/elevator-service.js +1 -1
- package/dist/systems/fence/fence-centerline.d.ts +2 -2
- package/dist/systems/fence/fence-centerline.js +2 -2
- package/dist/systems/fence/fence-spline.d.ts +2 -2
- package/dist/systems/roof/roof-elevation-system.js +3 -3
- package/dist/systems/roof/roof-elevation.d.ts +2 -2
- package/dist/systems/roof/roof-elevation.js +6 -6
- package/dist/systems/roof/roof-footprint.d.ts +1 -1
- package/dist/systems/roof/roof-footprint.js +3 -3
- package/dist/systems/slab/slab-placement.d.ts +1 -1
- package/dist/systems/slab/slab-support.d.ts +1 -1
- package/dist/systems/slab/slab-support.js +4 -4
- package/dist/systems/stair/stair-flight.d.ts +2 -2
- package/dist/systems/stair/stair-flight.js +2 -2
- package/dist/systems/stair/stair-footprint.d.ts +1 -1
- package/dist/systems/stair/stair-opening-preview.d.ts +206 -79
- package/dist/systems/stair/stair-opening-preview.d.ts.map +1 -1
- package/dist/systems/stair/stair-opening-preview.js +2 -2
- package/dist/systems/stair/stair-opening-sync.d.ts +1 -1
- package/dist/systems/stair/stair-opening-sync.js +6 -6
- package/dist/systems/stair/stair-opening-system.js +8 -8
- package/dist/systems/stair/stair-rise.d.ts +1 -1
- package/dist/systems/stair/stair-rise.js +3 -3
- package/dist/systems/wall/wall-curve.d.ts +2 -2
- package/dist/systems/wall/wall-footprint.d.ts +3 -3
- package/dist/systems/wall/wall-footprint.js +3 -3
- package/dist/systems/wall/wall-mitering.d.ts +1 -1
- package/dist/systems/wall/wall-mitering.js +1 -1
- package/dist/systems/wall/wall-move.d.ts +1 -1
- package/dist/systems/wall/wall-top.d.ts +1 -1
- package/dist/systems/wall/wall-topology.d.ts +2 -2
- package/dist/systems/wall/wall-topology.js +4 -4
- package/dist/utils/clone-scene-graph.d.ts +3 -3
- package/dist/utils/clone-scene-graph.d.ts.map +1 -1
- package/dist/utils/clone-scene-graph.js +9 -3
- package/dist/utils/scene-migrations.d.ts +3 -3
- package/dist/utils/scene-migrations.js +3 -3
- package/dist/utils/vertical-scene-migration.js +5 -5
- package/dist/validation/validate-build-json.d.ts +5 -2
- package/dist/validation/validate-build-json.d.ts.map +1 -1
- package/dist/validation/validate-build-json.js +45 -4
- package/package.json +14 -3
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test if an item's footprint overlaps with a polygon.
|
|
3
|
+
* Checks: any item corner inside polygon, or any polygon vertex inside item AABB, or edges intersect.
|
|
4
|
+
*/
|
|
5
|
+
export declare function itemOverlapsPolygon(position: [number, number, number], dimensions: [number, number, number], rotation: [number, number, number], polygon: Array<[number, number]>, inset?: number): boolean;
|
|
6
|
+
//# sourceMappingURL=item-polygon-overlap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"item-polygon-overlap.d.ts","sourceRoot":"","sources":["../../src/lib/item-polygon-overlap.ts"],"names":[],"mappings":"AA0EA;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAClC,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EACpC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAClC,OAAO,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAChC,KAAK,SAAI,GACR,OAAO,CA8BT"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { pointInPolygon } from '../systems/slab/slab-support.js';
|
|
2
|
+
import { planFootprintCorners } from './plan-footprint.js';
|
|
3
|
+
/**
|
|
4
|
+
* Test if two line segments (a1->a2) and (b1->b2) intersect.
|
|
5
|
+
*/
|
|
6
|
+
function segmentsIntersect(ax1, az1, ax2, az2, bx1, bz1, bx2, bz2) {
|
|
7
|
+
const cross = (ox, oz, ax, az, bx, bz) => (ax - ox) * (bz - oz) - (az - oz) * (bx - ox);
|
|
8
|
+
const d1 = cross(bx1, bz1, bx2, bz2, ax1, az1);
|
|
9
|
+
const d2 = cross(bx1, bz1, bx2, bz2, ax2, az2);
|
|
10
|
+
const d3 = cross(ax1, az1, ax2, az2, bx1, bz1);
|
|
11
|
+
const d4 = cross(ax1, az1, ax2, az2, bx2, bz2);
|
|
12
|
+
if (((d1 > 0 && d2 < 0) || (d1 < 0 && d2 > 0)) && ((d3 > 0 && d4 < 0) || (d3 < 0 && d4 > 0))) {
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
// Collinear touching cases
|
|
16
|
+
const onSeg = (px, pz, qx, qz, rx, rz) => Math.min(px, qx) <= rx &&
|
|
17
|
+
rx <= Math.max(px, qx) &&
|
|
18
|
+
Math.min(pz, qz) <= rz &&
|
|
19
|
+
rz <= Math.max(pz, qz);
|
|
20
|
+
if (d1 === 0 && onSeg(bx1, bz1, bx2, bz2, ax1, az1))
|
|
21
|
+
return true;
|
|
22
|
+
if (d2 === 0 && onSeg(bx1, bz1, bx2, bz2, ax2, az2))
|
|
23
|
+
return true;
|
|
24
|
+
if (d3 === 0 && onSeg(ax1, az1, ax2, az2, bx1, bz1))
|
|
25
|
+
return true;
|
|
26
|
+
if (d4 === 0 && onSeg(ax1, az1, ax2, az2, bx2, bz2))
|
|
27
|
+
return true;
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Test if a line segment intersects any edge of a polygon.
|
|
32
|
+
*/
|
|
33
|
+
function segmentIntersectsPolygon(sx1, sz1, sx2, sz2, polygon) {
|
|
34
|
+
const n = polygon.length;
|
|
35
|
+
for (let i = 0; i < n; i++) {
|
|
36
|
+
const j = (i + 1) % n;
|
|
37
|
+
if (segmentsIntersect(sx1, sz1, sx2, sz2, polygon[i][0], polygon[i][1], polygon[j][0], polygon[j][1])) {
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Test if an item's footprint overlaps with a polygon.
|
|
45
|
+
* Checks: any item corner inside polygon, or any polygon vertex inside item AABB, or edges intersect.
|
|
46
|
+
*/
|
|
47
|
+
export function itemOverlapsPolygon(position, dimensions, rotation, polygon, inset = 0) {
|
|
48
|
+
const corners = planFootprintCorners(position, dimensions, rotation[1], inset);
|
|
49
|
+
// Check if any item corner is inside the polygon
|
|
50
|
+
for (const [cx, cz] of corners) {
|
|
51
|
+
if (pointInPolygon(cx, cz, polygon))
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
// Check if any polygon vertex is inside the item footprint
|
|
55
|
+
// (handles case where slab is fully inside a large item)
|
|
56
|
+
for (const [px, pz] of polygon) {
|
|
57
|
+
if (pointInPolygon(px, pz, corners))
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
// Check if any item edge intersects any polygon edge
|
|
61
|
+
for (let i = 0; i < 4; i++) {
|
|
62
|
+
const j = (i + 1) % 4;
|
|
63
|
+
if (segmentIntersectsPolygon(corners[i][0], corners[i][1], corners[j][0], corners[j][1], polygon))
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
return false;
|
|
67
|
+
}
|
package/dist/lib/level-name.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { LevelNode } from '../schema';
|
|
1
|
+
import type { LevelNode } from '../schema/index.js';
|
|
2
2
|
export declare function getDefaultLevelName(level: number): string;
|
|
3
3
|
export declare function getLevelDisplayName(level: Pick<LevelNode, 'name' | 'level'>): string;
|
|
4
4
|
//# sourceMappingURL=level-name.d.ts.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { MeasurementFeature, MeasurementFeatureBinding } from '../registry/types';
|
|
2
|
-
import type { ConstructionDimensionNode } from '../schema/nodes/construction-dimension';
|
|
3
|
-
import type { MeasurementAnchor, MeasurementPayload, MeasurementPoint } from '../schema/nodes/measurement';
|
|
4
|
-
import type { AnyNodeId } from '../schema/types';
|
|
1
|
+
import type { MeasurementFeature, MeasurementFeatureBinding } from '../registry/types.js';
|
|
2
|
+
import type { ConstructionDimensionNode } from '../schema/nodes/construction-dimension.js';
|
|
3
|
+
import type { MeasurementAnchor, MeasurementPayload, MeasurementPoint } from '../schema/nodes/measurement.js';
|
|
4
|
+
import type { AnyNodeId } from '../schema/types.js';
|
|
5
5
|
export declare const MEASUREMENT_PLANAR_TOLERANCE = 0.01;
|
|
6
6
|
export declare function measurementDistance(start: MeasurementPoint, end: MeasurementPoint): number;
|
|
7
7
|
export declare function measurementAnchorFallback(anchor: MeasurementAnchor): MeasurementPoint;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure plan (XZ) footprint math — one source for spatial-grid collision and
|
|
3
|
+
* alignment anchors. The `@pascal-app/core/plan-footprint` subpath is the seam
|
|
4
|
+
* for a follow-up that consolidates MCP layout clearance onto these helpers.
|
|
5
|
+
*
|
|
6
|
+
* ## Invariant
|
|
7
|
+
* Callers share `planFootprintCorners` / `planFootprintAABB`. Do not invent a
|
|
8
|
+
* third rotation-aware plan AABB path beside this module.
|
|
9
|
+
*
|
|
10
|
+
* ## Gap call-site meanings (for the follow-up overlap helper)
|
|
11
|
+
* When an expand-then-intersect overlap check lands here, treat `gap` as
|
|
12
|
+
* **minimum free space** (expand each box by `gap`, then intersect):
|
|
13
|
+
* - Packing / furnish: typically `gap ≈ 0.08` for breathing room between items
|
|
14
|
+
* - check / verify collision: use `gap = 0` for true interpenetration only
|
|
15
|
+
* Do not share one default blindly across both questions.
|
|
16
|
+
*
|
|
17
|
+
* ## Scope
|
|
18
|
+
* Foundation only. Does not move door keep-outs, level ancestry, or furnish
|
|
19
|
+
* search into core. Item-scaled / attach-aware wrappers stay with callers
|
|
20
|
+
* until the MCP consolidation follow-up.
|
|
21
|
+
*/
|
|
22
|
+
export type PlanAabb = {
|
|
23
|
+
minX: number;
|
|
24
|
+
maxX: number;
|
|
25
|
+
minZ: number;
|
|
26
|
+
maxZ: number;
|
|
27
|
+
};
|
|
28
|
+
export type PlanVec2 = [number, number];
|
|
29
|
+
/**
|
|
30
|
+
* Four XZ corners of a centred footprint at `position`, rotated by Y
|
|
31
|
+
* rotation. Matches spatial-grid `getItemFootprint` convention:
|
|
32
|
+
* local +X maps with (cos, sin), local +Z with (-sin, cos) terms as used
|
|
33
|
+
* in the existing corner formula.
|
|
34
|
+
*/
|
|
35
|
+
export declare function planFootprintCorners(position: readonly [number, number, number], dimensions: readonly [number, number, number], rotationY: number, inset?: number): PlanVec2[];
|
|
36
|
+
/**
|
|
37
|
+
* Axis-aligned XZ extent of a footprint. Equivalent to the AABB of
|
|
38
|
+
* `planFootprintCorners` (no inset) and to spatial-grid `footprintBoundsXZ`.
|
|
39
|
+
*/
|
|
40
|
+
export declare function planFootprintAABB(position: readonly [number, number, number], dimensions: readonly [number, number, number], rotationY: number): PlanAabb;
|
|
41
|
+
//# sourceMappingURL=plan-footprint.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan-footprint.d.ts","sourceRoot":"","sources":["../../src/lib/plan-footprint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED,MAAM,MAAM,QAAQ,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AAEvC;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAC3C,UAAU,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAC7C,SAAS,EAAE,MAAM,EACjB,KAAK,SAAI,GACR,QAAQ,EAAE,CAcZ;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAC3C,UAAU,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAC7C,SAAS,EAAE,MAAM,GAChB,QAAQ,CAYV"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure plan (XZ) footprint math — one source for spatial-grid collision and
|
|
3
|
+
* alignment anchors. The `@pascal-app/core/plan-footprint` subpath is the seam
|
|
4
|
+
* for a follow-up that consolidates MCP layout clearance onto these helpers.
|
|
5
|
+
*
|
|
6
|
+
* ## Invariant
|
|
7
|
+
* Callers share `planFootprintCorners` / `planFootprintAABB`. Do not invent a
|
|
8
|
+
* third rotation-aware plan AABB path beside this module.
|
|
9
|
+
*
|
|
10
|
+
* ## Gap call-site meanings (for the follow-up overlap helper)
|
|
11
|
+
* When an expand-then-intersect overlap check lands here, treat `gap` as
|
|
12
|
+
* **minimum free space** (expand each box by `gap`, then intersect):
|
|
13
|
+
* - Packing / furnish: typically `gap ≈ 0.08` for breathing room between items
|
|
14
|
+
* - check / verify collision: use `gap = 0` for true interpenetration only
|
|
15
|
+
* Do not share one default blindly across both questions.
|
|
16
|
+
*
|
|
17
|
+
* ## Scope
|
|
18
|
+
* Foundation only. Does not move door keep-outs, level ancestry, or furnish
|
|
19
|
+
* search into core. Item-scaled / attach-aware wrappers stay with callers
|
|
20
|
+
* until the MCP consolidation follow-up.
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* Four XZ corners of a centred footprint at `position`, rotated by Y
|
|
24
|
+
* rotation. Matches spatial-grid `getItemFootprint` convention:
|
|
25
|
+
* local +X maps with (cos, sin), local +Z with (-sin, cos) terms as used
|
|
26
|
+
* in the existing corner formula.
|
|
27
|
+
*/
|
|
28
|
+
export function planFootprintCorners(position, dimensions, rotationY, inset = 0) {
|
|
29
|
+
const [x, , z] = position;
|
|
30
|
+
const [w, , d] = dimensions;
|
|
31
|
+
const halfW = Math.max(0, w / 2 - inset);
|
|
32
|
+
const halfD = Math.max(0, d / 2 - inset);
|
|
33
|
+
const cos = Math.cos(rotationY);
|
|
34
|
+
const sin = Math.sin(rotationY);
|
|
35
|
+
return [
|
|
36
|
+
[x + (-halfW * cos + halfD * sin), z + (-halfW * sin - halfD * cos)],
|
|
37
|
+
[x + (halfW * cos + halfD * sin), z + (halfW * sin - halfD * cos)],
|
|
38
|
+
[x + (halfW * cos - halfD * sin), z + (halfW * sin + halfD * cos)],
|
|
39
|
+
[x + (-halfW * cos - halfD * sin), z + (-halfW * sin + halfD * cos)],
|
|
40
|
+
];
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Axis-aligned XZ extent of a footprint. Equivalent to the AABB of
|
|
44
|
+
* `planFootprintCorners` (no inset) and to spatial-grid `footprintBoundsXZ`.
|
|
45
|
+
*/
|
|
46
|
+
export function planFootprintAABB(position, dimensions, rotationY) {
|
|
47
|
+
const [width, , depth] = dimensions;
|
|
48
|
+
const cos = Math.abs(Math.cos(rotationY));
|
|
49
|
+
const sin = Math.abs(Math.sin(rotationY));
|
|
50
|
+
const rotatedW = width * cos + depth * sin;
|
|
51
|
+
const rotatedD = width * sin + depth * cos;
|
|
52
|
+
return {
|
|
53
|
+
minX: position[0] - rotatedW / 2,
|
|
54
|
+
maxX: position[0] + rotatedW / 2,
|
|
55
|
+
minZ: position[2] - rotatedD / 2,
|
|
56
|
+
maxZ: position[2] + rotatedD / 2,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AnyNode, AnyNodeId } from '../schema/types';
|
|
1
|
+
import type { AnyNode, AnyNodeId } from '../schema/types.js';
|
|
2
2
|
export declare function selectionProxyIdFromMetadata(metadata: unknown): AnyNodeId | null;
|
|
3
3
|
export declare function resolveSelectionProxyId(node: AnyNode, nodes: Readonly<Record<string, AnyNode | undefined>>): AnyNodeId;
|
|
4
4
|
//# sourceMappingURL=selection-proxy.d.ts.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { GeometryContext } from '../registry/types';
|
|
2
|
-
import type { AnyNode, AnyNodeId, SlabNode, WallNode } from '../schema';
|
|
1
|
+
import type { GeometryContext } from '../registry/types.js';
|
|
2
|
+
import type { AnyNode, AnyNodeId, SlabNode, WallNode } from '../schema/index.js';
|
|
3
3
|
export type SlabPolygonContext = {
|
|
4
4
|
/** Walls on the slab's level. */
|
|
5
5
|
walls: WallNode[];
|
package/dist/lib/slab-polygon.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { isCurvedWall, sampleWallCenterline } from '../systems/wall/wall-curve';
|
|
2
|
-
import { getWallThickness } from '../systems/wall/wall-footprint';
|
|
1
|
+
import { isCurvedWall, sampleWallCenterline } from '../systems/wall/wall-curve.js';
|
|
2
|
+
import { getWallThickness } from '../systems/wall/wall-footprint.js';
|
|
3
3
|
/**
|
|
4
4
|
* Render-time slab polygon rules.
|
|
5
5
|
*
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type AnyNodeId, type CeilingNode as CeilingNodeType, type SlabNode as SlabNodeType, type WallNode, type ZoneNode as ZoneNodeType } from '../schema';
|
|
1
|
+
import { type AnyNodeId, type CeilingNode as CeilingNodeType, type SlabNode as SlabNodeType, type WallNode, type ZoneNode as ZoneNodeType } from '../schema/index.js';
|
|
2
2
|
type Point2D = {
|
|
3
3
|
x: number;
|
|
4
4
|
y: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"space-detection.d.ts","sourceRoot":"","sources":["../../src/lib/space-detection.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"space-detection.d.ts","sourceRoot":"","sources":["../../src/lib/space-detection.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { GROUND_SUPPORT_ID } from '../hooks/spatial-grid/support-host-id';
|
|
2
|
-
import { CeilingNode, SlabNode, ZoneNode, } from '../schema';
|
|
3
|
-
import { DEFAULT_LEVEL_HEIGHT } from '../services/level-height';
|
|
4
|
-
import { CEILING_CLAMP_MARGIN, findLevelAboveId, getCeilingClampBound, getLevelBelow, getLevelElevations, getStoredLevelHeight, } from '../services/storey';
|
|
5
|
-
import { activeSceneCommitNodeIds, getSceneHistoryPauseDepth, pauseSceneHistory, resumeSceneHistory, subscribeSceneCommits, } from '../store/history-control';
|
|
6
|
-
import { computeWallSlabSupport } from '../systems/slab/slab-support';
|
|
7
|
-
import { getClampedWallCurveOffset, getWallCurveFrameAt, isCurvedWall, } from '../systems/wall/wall-curve';
|
|
8
|
-
import { resolveWallTop } from '../systems/wall/wall-top';
|
|
9
|
-
import { simplifyClosedPolygon } from './polygon-geometry';
|
|
10
|
-
import { distanceToSegment, RoomTopologyIndex, } from './room-topology-index';
|
|
11
|
-
import { levelBaseElevationAt } from './terrain-support';
|
|
1
|
+
import { GROUND_SUPPORT_ID } from '../hooks/spatial-grid/support-host-id.js';
|
|
2
|
+
import { CeilingNode, SlabNode, ZoneNode, } from '../schema/index.js';
|
|
3
|
+
import { DEFAULT_LEVEL_HEIGHT } from '../services/level-height.js';
|
|
4
|
+
import { CEILING_CLAMP_MARGIN, findLevelAboveId, getCeilingClampBound, getLevelBelow, getLevelElevations, getStoredLevelHeight, } from '../services/storey.js';
|
|
5
|
+
import { activeSceneCommitNodeIds, getSceneHistoryPauseDepth, pauseSceneHistory, resumeSceneHistory, subscribeSceneCommits, } from '../store/history-control.js';
|
|
6
|
+
import { computeWallSlabSupport } from '../systems/slab/slab-support.js';
|
|
7
|
+
import { getClampedWallCurveOffset, getWallCurveFrameAt, isCurvedWall, } from '../systems/wall/wall-curve.js';
|
|
8
|
+
import { resolveWallTop } from '../systems/wall/wall-top.js';
|
|
9
|
+
import { simplifyClosedPolygon } from './polygon-geometry.js';
|
|
10
|
+
import { distanceToSegment, RoomTopologyIndex, } from './room-topology-index.js';
|
|
11
|
+
import { levelBaseElevationAt } from './terrain-support.js';
|
|
12
12
|
const DEFAULT_AUTO_SLAB_ELEVATION = 0.05;
|
|
13
13
|
const CEILING_HEIGHT_EPSILON = 1e-6;
|
|
14
14
|
const ROOM_CURVE_TOLERANCE = 0.04;
|
|
@@ -1858,6 +1858,11 @@ export function initSpaceDetectionSync(sceneStore, editorStore, options = {}) {
|
|
|
1858
1858
|
return;
|
|
1859
1859
|
adoptSceneBaseline(commit.current.nodes);
|
|
1860
1860
|
});
|
|
1861
|
+
// Keep reconciliation in this synchronous store subscription. Zundo emits
|
|
1862
|
+
// the originating local SceneCommit only after subscribers return, so the
|
|
1863
|
+
// history-paused derived writes below join that commit's current snapshot
|
|
1864
|
+
// and undo step. Running from subscribeSceneCommits would cross the snapshot
|
|
1865
|
+
// boundary, and the paused writes would emit no replacement commit.
|
|
1861
1866
|
const unsubscribe = sceneStore.subscribe((state) => {
|
|
1862
1867
|
if (isProcessing)
|
|
1863
1868
|
return;
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
* one in-flight gesture and dies with it, which is cheaper and clearer than
|
|
31
31
|
* rebuilding a coverage map per pointer-move.
|
|
32
32
|
*/
|
|
33
|
-
import { type HeightPatch, type TerrainField } from './terrain-field';
|
|
33
|
+
import { type HeightPatch, type TerrainField } from './terrain-field.js';
|
|
34
34
|
export type BrushShape = 'round' | 'square';
|
|
35
35
|
/**
|
|
36
36
|
* `raise`/`lower` are one verb with an inverted sign at the call site, matching
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
* one in-flight gesture and dies with it, which is cheaper and clearer than
|
|
31
31
|
* rebuilding a coverage map per pointer-move.
|
|
32
32
|
*/
|
|
33
|
-
import { heightAt, heightAtSample, quantize, } from './terrain-field';
|
|
33
|
+
import { heightAt, heightAtSample, quantize, } from './terrain-field.js';
|
|
34
34
|
export const DEFAULT_BRUSH_SETTINGS = {
|
|
35
35
|
radius: 2,
|
|
36
36
|
strength: 0.6,
|
|
@@ -24,8 +24,8 @@
|
|
|
24
24
|
* the wire format must not depend on that being true of the machine that saved
|
|
25
25
|
* the scene.
|
|
26
26
|
*/
|
|
27
|
-
import { type TerrainData } from '../schema/terrain';
|
|
28
|
-
import type { HeightPatch, TerrainField } from './terrain-field';
|
|
27
|
+
import { type TerrainData } from '../schema/terrain.js';
|
|
28
|
+
import type { HeightPatch, TerrainField } from './terrain-field.js';
|
|
29
29
|
export type EncodedHeightPatch = Omit<HeightPatch, 'heights'> & {
|
|
30
30
|
heights: string;
|
|
31
31
|
};
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
* the wire format must not depend on that being true of the machine that saved
|
|
25
25
|
* the scene.
|
|
26
26
|
*/
|
|
27
|
-
import { MAX_TERRAIN_SIDE } from '../schema/terrain';
|
|
27
|
+
import { MAX_TERRAIN_SIDE } from '../schema/terrain.js';
|
|
28
28
|
const BASE64_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
|
29
29
|
function encodeBase64(bytes) {
|
|
30
30
|
let out = '';
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
* ladder, so the returned point is on the same rendered triangle plane
|
|
21
21
|
* `heightAt` reports.
|
|
22
22
|
*/
|
|
23
|
-
import { type TerrainField } from './terrain-field';
|
|
23
|
+
import { type TerrainField } from './terrain-field.js';
|
|
24
24
|
export type TerrainHit = {
|
|
25
25
|
/** Distance along the (unnormalized) direction vector. */
|
|
26
26
|
readonly t: number;
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
* ladder, so the returned point is on the same rendered triangle plane
|
|
21
21
|
* `heightAt` reports.
|
|
22
22
|
*/
|
|
23
|
-
import { heightAt } from './terrain-field';
|
|
23
|
+
import { heightAt } from './terrain-field.js';
|
|
24
24
|
/** Bisection depth. 20 halvings of one cell is sub-micrometre at any sane spacing. */
|
|
25
25
|
const REFINE_ITERATIONS = 20;
|
|
26
26
|
/**
|
|
@@ -17,9 +17,9 @@
|
|
|
17
17
|
* the commit, the next read is a cache hit, so a stroke never decodes base64 even
|
|
18
18
|
* once, let alone per dab.
|
|
19
19
|
*/
|
|
20
|
-
import type { SiteNode } from '../schema/nodes/site';
|
|
21
|
-
import type { TerrainData } from '../schema/terrain';
|
|
22
|
-
import { createTerrainField, type TerrainField } from './terrain-field';
|
|
20
|
+
import type { SiteNode } from '../schema/nodes/site.js';
|
|
21
|
+
import type { TerrainData } from '../schema/terrain.js';
|
|
22
|
+
import { createTerrainField, type TerrainField } from './terrain-field.js';
|
|
23
23
|
/**
|
|
24
24
|
* The terrain field for a site, or `null` when the site has no sculpted terrain.
|
|
25
25
|
*
|
|
@@ -17,9 +17,9 @@
|
|
|
17
17
|
* the commit, the next read is a cache hit, so a stroke never decodes base64 even
|
|
18
18
|
* once, let alone per dab.
|
|
19
19
|
*/
|
|
20
|
-
import useLiveTerrain from '../store/use-live-terrain';
|
|
21
|
-
import { decodeTerrainField, encodeTerrainField } from './terrain-codec';
|
|
22
|
-
import { createTerrainField } from './terrain-field';
|
|
20
|
+
import useLiveTerrain from '../store/use-live-terrain.js';
|
|
21
|
+
import { decodeTerrainField, encodeTerrainField } from './terrain-codec.js';
|
|
22
|
+
import { createTerrainField } from './terrain-field.js';
|
|
23
23
|
const fieldCache = new WeakMap();
|
|
24
24
|
/**
|
|
25
25
|
* Sites whose `terrain` failed to decode. Prevents re-attempting a doomed decode
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* The whole file is pure — nodes in, metres out — which is what lets the stacking
|
|
12
12
|
* matrix be tested per kind without a canvas.
|
|
13
13
|
*/
|
|
14
|
-
import type { AnyNode } from '../schema';
|
|
14
|
+
import type { AnyNode } from '../schema/index.js';
|
|
15
15
|
/**
|
|
16
16
|
* World Y of the site datum — the plane terrain heights are measured from.
|
|
17
17
|
*
|
|
@@ -11,9 +11,9 @@
|
|
|
11
11
|
* The whole file is pure — nodes in, metres out — which is what lets the stacking
|
|
12
12
|
* matrix be tested per kind without a canvas.
|
|
13
13
|
*/
|
|
14
|
-
import { getLevelElevations } from '../services/storey';
|
|
15
|
-
import { heightAt } from './terrain-field';
|
|
16
|
-
import { terrainFieldOf } from './terrain-source';
|
|
14
|
+
import { getLevelElevations } from '../services/storey.js';
|
|
15
|
+
import { heightAt } from './terrain-field.js';
|
|
16
|
+
import { terrainFieldOf } from './terrain-source.js';
|
|
17
17
|
/**
|
|
18
18
|
* World Y of the site datum — the plane terrain heights are measured from.
|
|
19
19
|
*
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { AnyNode, AnyNodeId, BuildingNode, LevelNode, UnitNode, WallNode, ZoneNode } from '../schema/index.js';
|
|
2
|
+
export type UnitDerivation = {
|
|
3
|
+
unitId: UnitNode['id'];
|
|
4
|
+
memberZoneIds: ZoneNode['id'][];
|
|
5
|
+
levelIds: LevelNode['id'][];
|
|
6
|
+
containedNodeIds: AnyNodeId[];
|
|
7
|
+
boundaryWallIds: WallNode['id'][];
|
|
8
|
+
supportIds: AnyNodeId[];
|
|
9
|
+
visibleNodeIds: AnyNodeId[];
|
|
10
|
+
};
|
|
11
|
+
type Nodes = Readonly<Record<AnyNodeId, AnyNode>>;
|
|
12
|
+
export declare function deriveUnit(unit: UnitNode, nodes: Nodes): UnitDerivation;
|
|
13
|
+
export declare function unitsForZone(zoneId: ZoneNode['id'], nodes: Nodes): UnitNode[];
|
|
14
|
+
export declare function unassignedZoneIds(buildingId: BuildingNode['id'], nodes: Nodes): ZoneNode['id'][];
|
|
15
|
+
export declare function unitWarnings(unit: UnitNode, nodes: Nodes): Array<{
|
|
16
|
+
code: 'empty' | 'non-adjacent-levels';
|
|
17
|
+
}>;
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=unit-containment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unit-containment.d.ts","sourceRoot":"","sources":["../../src/lib/unit-containment.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EACP,SAAS,EACT,YAAY,EACZ,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,QAAQ,EACT,MAAM,WAAW,CAAA;AAMlB,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAA;IACtB,aAAa,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAA;IAC/B,QAAQ,EAAE,SAAS,CAAC,IAAI,CAAC,EAAE,CAAA;IAC3B,gBAAgB,EAAE,SAAS,EAAE,CAAA;IAC7B,eAAe,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAA;IACjC,UAAU,EAAE,SAAS,EAAE,CAAA;IACvB,cAAc,EAAE,SAAS,EAAE,CAAA;CAC5B,CAAA;AAED,KAAK,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAA;AA8CjD,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,GAAG,cAAc,CAuFvE;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,GAAG,QAAQ,EAAE,CAI7E;AAED,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,YAAY,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,EAAE,CAqBhG;AAED,wBAAgB,YAAY,CAC1B,IAAI,EAAE,QAAQ,EACd,KAAK,EAAE,KAAK,GACX,KAAK,CAAC;IACP,IAAI,EAAE,OAAO,GAAG,qBAAqB,CAAA;CACtC,CAAC,CAiBD"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { pointOnPolygonBoundary, wallOverlapsSlabFootprint } from '../systems/slab/slab-support.js';
|
|
2
|
+
import { measurementCentroid } from './measurement-geometry.js';
|
|
3
|
+
import { pointInPolygon } from './polygon-relations.js';
|
|
4
|
+
import { detectSpacesForLevel, resolveAutoZonePolygon } from './space-detection.js';
|
|
5
|
+
function footprintCentroid(node) {
|
|
6
|
+
if ('position' in node && Array.isArray(node.position) && node.position.length === 3) {
|
|
7
|
+
return [node.position[0], node.position[2]];
|
|
8
|
+
}
|
|
9
|
+
if ('polygon' in node && Array.isArray(node.polygon)) {
|
|
10
|
+
const centroid = measurementCentroid(node.polygon.map(([x, z]) => [x, 0, z]));
|
|
11
|
+
return centroid ? [centroid[0], centroid[2]] : null;
|
|
12
|
+
}
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
function polygonCentroid(polygon) {
|
|
16
|
+
if (polygon.length < 3)
|
|
17
|
+
return null;
|
|
18
|
+
const centroid = measurementCentroid(polygon.map(([x, z]) => [x, 0, z]));
|
|
19
|
+
return centroid ? [centroid[0], centroid[2]] : null;
|
|
20
|
+
}
|
|
21
|
+
function coversPoint(point, polygon, holes = []) {
|
|
22
|
+
return (polygon.length >= 3 &&
|
|
23
|
+
(pointInPolygon(point, polygon) || pointOnPolygonBoundary(point[0], point[1], polygon)) &&
|
|
24
|
+
!holes.some((hole) => pointInPolygon(point, hole, { includeBoundary: false }) &&
|
|
25
|
+
!pointOnPolygonBoundary(point[0], point[1], hole)));
|
|
26
|
+
}
|
|
27
|
+
function overlapsSupport(polygon, support) {
|
|
28
|
+
if (polygon.length < 3 || support.polygon.length < 3)
|
|
29
|
+
return false;
|
|
30
|
+
return (polygon.some((point) => coversPoint(point, support.polygon, support.holes)) ||
|
|
31
|
+
support.polygon.some((point) => coversPoint(point, polygon)) ||
|
|
32
|
+
polygon.some((start, index) => wallOverlapsSlabFootprint({ start, end: polygon[(index + 1) % polygon.length], thickness: 0 }, support.polygon, support.holes)));
|
|
33
|
+
}
|
|
34
|
+
export function deriveUnit(unit, nodes) {
|
|
35
|
+
const members = [...new Set(unit.members)].flatMap((id) => {
|
|
36
|
+
const zone = nodes[id];
|
|
37
|
+
return zone?.type === 'zone' ? [zone] : [];
|
|
38
|
+
});
|
|
39
|
+
const levels = new Map();
|
|
40
|
+
const polygonsByLevel = new Map();
|
|
41
|
+
for (const zone of members) {
|
|
42
|
+
const level = zone.parentId ? nodes[zone.parentId] : undefined;
|
|
43
|
+
if (level?.type !== 'level')
|
|
44
|
+
continue;
|
|
45
|
+
levels.set(level.id, level);
|
|
46
|
+
const polygons = polygonsByLevel.get(level.id) ?? [];
|
|
47
|
+
polygons.push(resolveAutoZonePolygon(zone, (id) => nodes[id]));
|
|
48
|
+
polygonsByLevel.set(level.id, polygons);
|
|
49
|
+
}
|
|
50
|
+
const levelIds = [...levels.values()]
|
|
51
|
+
.sort((a, b) => a.level - b.level || a.id.localeCompare(b.id))
|
|
52
|
+
.map((level) => level.id);
|
|
53
|
+
const containedNodeIds = [];
|
|
54
|
+
const boundaryWalls = new Set();
|
|
55
|
+
const supportIds = [];
|
|
56
|
+
const wallsByLevel = new Map();
|
|
57
|
+
for (const node of Object.values(nodes)) {
|
|
58
|
+
const polygons = node.parentId
|
|
59
|
+
? polygonsByLevel.get(node.parentId)
|
|
60
|
+
: undefined;
|
|
61
|
+
if (!polygons)
|
|
62
|
+
continue;
|
|
63
|
+
if (node.type === 'wall') {
|
|
64
|
+
const levelId = node.parentId;
|
|
65
|
+
wallsByLevel.set(levelId, [...(wallsByLevel.get(levelId) ?? []), node]);
|
|
66
|
+
if (polygons.some((polygon) => polygon.length >= 3 && wallOverlapsSlabFootprint(node, polygon))) {
|
|
67
|
+
boundaryWalls.add(node.id);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
else if (node.type === 'slab' || node.type === 'ceiling') {
|
|
71
|
+
if (polygons.some((polygon) => overlapsSupport(polygon, node)))
|
|
72
|
+
supportIds.push(node.id);
|
|
73
|
+
}
|
|
74
|
+
else if (node.type !== 'zone' &&
|
|
75
|
+
node.type !== 'level' &&
|
|
76
|
+
node.type !== 'building' &&
|
|
77
|
+
node.type !== 'site' &&
|
|
78
|
+
node.type !== 'unit') {
|
|
79
|
+
const point = footprintCentroid(node);
|
|
80
|
+
if (point && polygons.some((polygon) => coversPoint(point, polygon)))
|
|
81
|
+
containedNodeIds.push(node.id);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// A zone drawn inside a room, short of the wall centerlines, still means
|
|
85
|
+
// that room: the walls of every detected space that encloses a member
|
|
86
|
+
// centroid, or whose own centroid the member encloses, are boundary walls.
|
|
87
|
+
for (const [levelId, walls] of wallsByLevel) {
|
|
88
|
+
const polygons = polygonsByLevel.get(levelId) ?? [];
|
|
89
|
+
for (const space of detectSpacesForLevel(levelId, walls).spaces) {
|
|
90
|
+
if (space.isExterior)
|
|
91
|
+
continue;
|
|
92
|
+
const spaceCentroid = polygonCentroid(space.polygon);
|
|
93
|
+
const matches = polygons.some((polygon) => {
|
|
94
|
+
const memberCentroid = polygonCentroid(polygon);
|
|
95
|
+
return ((memberCentroid !== null && coversPoint(memberCentroid, space.polygon)) ||
|
|
96
|
+
(spaceCentroid !== null && coversPoint(spaceCentroid, polygon)));
|
|
97
|
+
});
|
|
98
|
+
if (matches)
|
|
99
|
+
for (const wallId of space.wallIds)
|
|
100
|
+
boundaryWalls.add(wallId);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
const boundaryWallIds = [...boundaryWalls];
|
|
104
|
+
const memberZoneIds = members.map((zone) => zone.id);
|
|
105
|
+
// Ancestors (levels, building, site, the unit itself) are left out: the
|
|
106
|
+
// viewer's isolation filter keeps every descendant of a listed id, so
|
|
107
|
+
// listing a level would show the whole storey.
|
|
108
|
+
const visible = new Set([
|
|
109
|
+
...memberZoneIds,
|
|
110
|
+
...containedNodeIds,
|
|
111
|
+
...boundaryWallIds,
|
|
112
|
+
...supportIds,
|
|
113
|
+
]);
|
|
114
|
+
return {
|
|
115
|
+
unitId: unit.id,
|
|
116
|
+
memberZoneIds,
|
|
117
|
+
levelIds,
|
|
118
|
+
containedNodeIds,
|
|
119
|
+
boundaryWallIds,
|
|
120
|
+
supportIds,
|
|
121
|
+
visibleNodeIds: [...visible],
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
export function unitsForZone(zoneId, nodes) {
|
|
125
|
+
return Object.values(nodes).filter((node) => node.type === 'unit' && node.members.includes(zoneId));
|
|
126
|
+
}
|
|
127
|
+
export function unassignedZoneIds(buildingId, nodes) {
|
|
128
|
+
const assigned = new Set(Object.values(nodes).flatMap((node) => (node.type === 'unit' ? node.members : [])));
|
|
129
|
+
const building = nodes[buildingId];
|
|
130
|
+
if (building?.type !== 'building')
|
|
131
|
+
return [];
|
|
132
|
+
const levels = new Set(Object.values(nodes).flatMap((node) => node.type === 'level' && (node.parentId === buildingId || building.children.includes(node.id))
|
|
133
|
+
? [node.id]
|
|
134
|
+
: []));
|
|
135
|
+
return Object.values(nodes).flatMap((node) => node.type === 'zone' &&
|
|
136
|
+
node.parentId &&
|
|
137
|
+
levels.has(node.parentId) &&
|
|
138
|
+
!assigned.has(node.id)
|
|
139
|
+
? [node.id]
|
|
140
|
+
: []);
|
|
141
|
+
}
|
|
142
|
+
export function unitWarnings(unit, nodes) {
|
|
143
|
+
const members = [...new Set(unit.members)].filter((id) => nodes[id]?.type === 'zone');
|
|
144
|
+
const warnings = [];
|
|
145
|
+
if (members.length === 0)
|
|
146
|
+
warnings.push({ code: 'empty' });
|
|
147
|
+
const ordinals = [
|
|
148
|
+
...new Set(members.flatMap((id) => {
|
|
149
|
+
const parentId = nodes[id]?.parentId;
|
|
150
|
+
const level = parentId ? nodes[parentId] : undefined;
|
|
151
|
+
return level?.type === 'level' ? [level.level] : [];
|
|
152
|
+
})),
|
|
153
|
+
].sort((a, b) => a - b);
|
|
154
|
+
if (ordinals.some((ordinal, index) => index > 0 && ordinal - ordinals[index - 1] > 1)) {
|
|
155
|
+
warnings.push({ code: 'non-adjacent-levels' });
|
|
156
|
+
}
|
|
157
|
+
return warnings;
|
|
158
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { AnyNode, AnyNodeId, LevelNode, UnitNode, ZoneNode } from '../schema/index.js';
|
|
2
|
+
export type UnitReport = {
|
|
3
|
+
memberCount: number;
|
|
4
|
+
levelSpan: {
|
|
5
|
+
minOrdinal: number;
|
|
6
|
+
maxOrdinal: number;
|
|
7
|
+
count: number;
|
|
8
|
+
} | null;
|
|
9
|
+
grossAreaM2: number;
|
|
10
|
+
members: Array<{
|
|
11
|
+
zoneId: ZoneNode['id'];
|
|
12
|
+
name: string;
|
|
13
|
+
levelId: LevelNode['id'] | null;
|
|
14
|
+
levelOrdinal: number | null;
|
|
15
|
+
areaM2: number;
|
|
16
|
+
}>;
|
|
17
|
+
};
|
|
18
|
+
export declare function buildUnitReport(unit: UnitNode, nodes: Readonly<Record<AnyNodeId, AnyNode>>): UnitReport;
|
|
19
|
+
//# sourceMappingURL=unit-report.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unit-report.d.ts","sourceRoot":"","sources":["../../src/lib/unit-report.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAIlF,MAAM,MAAM,UAAU,GAAG;IACvB,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;IAC3E,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,KAAK,CAAC;QACb,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAA;QACtB,IAAI,EAAE,MAAM,CAAA;QACZ,OAAO,EAAE,SAAS,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;QAC/B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;QAC3B,MAAM,EAAE,MAAM,CAAA;KACf,CAAC,CAAA;CACH,CAAA;AAED,wBAAgB,eAAe,CAC7B,IAAI,EAAE,QAAQ,EACd,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,GAC1C,UAAU,CAgCZ"}
|