fix wall elevation with slab holes
This commit is contained in:
@@ -201,6 +201,21 @@ export function wallOverlapsPolygon(
|
|||||||
const nz = (dz / len) * step
|
const nz = (dz / len) * step
|
||||||
if (pointInPolygon(start[0] + nx, start[1] + nz, polygon)) return true
|
if (pointInPolygon(start[0] + nx, start[1] + nz, polygon)) return true
|
||||||
if (pointInPolygon(end[0] - nx, end[1] - nz, polygon)) return true
|
if (pointInPolygon(end[0] - nx, end[1] - nz, polygon)) return true
|
||||||
|
|
||||||
|
// Also nudge perpendicular to the wall (into the slab interior) for walls that
|
||||||
|
// lie exactly on the slab boundary. The along-wall nudge keeps points on the
|
||||||
|
// boundary where pointInPolygon is unreliable; a perpendicular inward nudge
|
||||||
|
// moves the point clearly inside (or outside) the polygon.
|
||||||
|
// Sample the wall at 1/4, 1/2, 3/4 positions with a perpendicular nudge.
|
||||||
|
const PERP_STEP = 1e-4
|
||||||
|
const pnx = (-nz / step) * PERP_STEP // perpendicular left
|
||||||
|
const pnz = (nx / step) * PERP_STEP
|
||||||
|
for (const t of [0.25, 0.5, 0.75]) {
|
||||||
|
const bx = start[0] + dx * t
|
||||||
|
const bz = start[1] + dz * t
|
||||||
|
if (pointInPolygon(bx + pnx, bz + pnz, polygon)) return true
|
||||||
|
if (pointInPolygon(bx - pnx, bz - pnz, polygon)) return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if midpoint is inside (catches walls crossing through)
|
// Check if midpoint is inside (catches walls crossing through)
|
||||||
@@ -557,25 +572,41 @@ export class SpatialGridManager {
|
|||||||
let maxElevation = -Infinity
|
let maxElevation = -Infinity
|
||||||
for (const slab of slabMap.values()) {
|
for (const slab of slabMap.values()) {
|
||||||
if (slab.polygon.length < 3) continue
|
if (slab.polygon.length < 3) continue
|
||||||
if (wallOverlapsPolygon(start, end, slab.polygon)) {
|
if (!wallOverlapsPolygon(start, end, slab.polygon)) continue
|
||||||
// Check if wall midpoint is in a hole (if so, ignore this slab)
|
|
||||||
let inHole = false
|
|
||||||
const midX = (start[0] + end[0]) / 2
|
|
||||||
const midZ = (start[1] + end[1]) / 2
|
|
||||||
const holes = slab.holes || []
|
const holes = slab.holes || []
|
||||||
|
if (holes.length === 0) {
|
||||||
|
// No holes: wall is on this slab
|
||||||
|
const elevation = slab.elevation ?? 0.05
|
||||||
|
if (elevation > maxElevation) maxElevation = elevation
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sample multiple points along the wall to check whether any portion lies on
|
||||||
|
// solid slab (not inside any hole). Checking only the midpoint fails when the
|
||||||
|
// midpoint falls in a staircase hole but the wall's endpoints are on solid slab.
|
||||||
|
const dx = end[0] - start[0]
|
||||||
|
const dz = end[1] - start[1]
|
||||||
|
let hasValidPoint = false
|
||||||
|
for (const t of [0, 0.25, 0.5, 0.75, 1]) {
|
||||||
|
const px = start[0] + dx * t
|
||||||
|
const pz = start[1] + dz * t
|
||||||
|
let inHole = false
|
||||||
for (const hole of holes) {
|
for (const hole of holes) {
|
||||||
if (hole.length >= 3 && pointInPolygon(midX, midZ, hole)) {
|
if (hole.length >= 3 && pointInPolygon(px, pz, hole)) {
|
||||||
inHole = true
|
inHole = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!inHole) {
|
if (!inHole) {
|
||||||
|
hasValidPoint = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasValidPoint) {
|
||||||
const elevation = slab.elevation ?? 0.05
|
const elevation = slab.elevation ?? 0.05
|
||||||
if (elevation > maxElevation) {
|
if (elevation > maxElevation) maxElevation = elevation
|
||||||
maxElevation = elevation
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return maxElevation === -Infinity ? 0 : maxElevation
|
return maxElevation === -Infinity ? 0 : maxElevation
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ export function initSpatialGridSync() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (node.type === 'slab' && prev.type === 'slab') {
|
} else if (node.type === 'slab' && prev.type === 'slab') {
|
||||||
if (node.polygon !== prev.polygon || node.elevation !== prev.elevation) {
|
if (node.polygon !== prev.polygon || node.elevation !== prev.elevation || node.holes !== prev.holes) {
|
||||||
const levelId = resolveLevelId(node, state.nodes)
|
const levelId = resolveLevelId(node, state.nodes)
|
||||||
spatialGridManager.handleNodeUpdated(node, levelId)
|
spatialGridManager.handleNodeUpdated(node, levelId)
|
||||||
|
|
||||||
|
|||||||
@@ -167,7 +167,6 @@ const useScene: UseSceneStore = create<SceneState>()(
|
|||||||
rootNodeIds: state.rootNodeIds,
|
rootNodeIds: state.rootNodeIds,
|
||||||
}),
|
}),
|
||||||
merge: (persistedState, currentState) => {
|
merge: (persistedState, currentState) => {
|
||||||
console.log('merge calling...', persistedState, currentState)
|
|
||||||
const persisted = persistedState as Partial<SceneState>
|
const persisted = persistedState as Partial<SceneState>
|
||||||
// Backward compat: add default scale to item nodes saved before scale was added
|
// Backward compat: add default scale to item nodes saved before scale was added
|
||||||
if (persisted.nodes) {
|
if (persisted.nodes) {
|
||||||
|
|||||||
Reference in New Issue
Block a user