handle holes in spatial grid manager
This commit is contained in:
@@ -42,6 +42,13 @@ export function SlabPanel() {
|
|||||||
}
|
}
|
||||||
}, [node, setEditingHoleIndex])
|
}, [node, setEditingHoleIndex])
|
||||||
|
|
||||||
|
// Clear hole editing state on unmount
|
||||||
|
useEffect(() => {
|
||||||
|
return () => {
|
||||||
|
setEditingHoleIndex(null)
|
||||||
|
}
|
||||||
|
}, [setEditingHoleIndex])
|
||||||
|
|
||||||
const handleAddHole = useCallback(() => {
|
const handleAddHole = useCallback(() => {
|
||||||
if (!node) return
|
if (!node) return
|
||||||
|
|
||||||
|
|||||||
@@ -457,7 +457,7 @@ export class SpatialGridManager {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the total slab elevation at a given (x, z) position on a level.
|
* Get the total slab elevation at a given (x, z) position on a level.
|
||||||
* Returns the highest slab elevation if the point is inside any slab polygon, otherwise 0.
|
* Returns the highest slab elevation if the point is inside any slab polygon (but not in any holes), otherwise 0.
|
||||||
*/
|
*/
|
||||||
getSlabElevationAt(levelId: string, x: number, z: number): number {
|
getSlabElevationAt(levelId: string, x: number, z: number): number {
|
||||||
const slabMap = this.slabsByLevel.get(levelId)
|
const slabMap = this.slabsByLevel.get(levelId)
|
||||||
@@ -466,18 +466,31 @@ export class SpatialGridManager {
|
|||||||
let maxElevation = 0
|
let maxElevation = 0
|
||||||
for (const slab of slabMap.values()) {
|
for (const slab of slabMap.values()) {
|
||||||
if (slab.polygon.length >= 3 && pointInPolygon(x, z, slab.polygon)) {
|
if (slab.polygon.length >= 3 && pointInPolygon(x, z, slab.polygon)) {
|
||||||
|
// Check if point is in any hole
|
||||||
|
let inHole = false
|
||||||
|
if (slab.holes && slab.holes.length > 0) {
|
||||||
|
for (const hole of slab.holes) {
|
||||||
|
if (hole.length >= 3 && pointInPolygon(x, z, hole)) {
|
||||||
|
inHole = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!inHole) {
|
||||||
const elevation = slab.elevation ?? 0.05
|
const elevation = slab.elevation ?? 0.05
|
||||||
if (elevation > maxElevation) {
|
if (elevation > maxElevation) {
|
||||||
maxElevation = elevation
|
maxElevation = elevation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return maxElevation
|
return maxElevation
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the slab elevation for an item using its full footprint (bounding box).
|
* Get the slab elevation for an item using its full footprint (bounding box).
|
||||||
* Checks if any part of the item's rotated footprint overlaps with any slab polygon.
|
* Checks if any part of the item's rotated footprint overlaps with any slab polygon (excluding holes).
|
||||||
* Returns the highest overlapping slab elevation, or 0 if none.
|
* Returns the highest overlapping slab elevation, or 0 if none.
|
||||||
*/
|
*/
|
||||||
getSlabElevationForItem(
|
getSlabElevationForItem(
|
||||||
@@ -492,17 +505,32 @@ 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 && itemOverlapsPolygon(position, dimensions, rotation, slab.polygon, 0.01)) {
|
if (slab.polygon.length >= 3 && itemOverlapsPolygon(position, dimensions, rotation, slab.polygon, 0.01)) {
|
||||||
|
// Check if item is entirely within a hole (if so, ignore this slab)
|
||||||
|
// We consider it entirely in a hole if the item center is in the hole
|
||||||
|
let inHole = false
|
||||||
|
if (slab.holes && slab.holes.length > 0) {
|
||||||
|
const [cx, , cz] = position
|
||||||
|
for (const hole of slab.holes) {
|
||||||
|
if (hole.length >= 3 && pointInPolygon(cx, cz, hole)) {
|
||||||
|
inHole = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!inHole) {
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the slab elevation for a wall by checking if it overlaps with any slab polygon.
|
* Get the slab elevation for a wall by checking if it overlaps with any slab polygon (excluding holes).
|
||||||
* Uses wallOverlapsPolygon which handles edge cases (points on boundary, collinear segments).
|
* Uses wallOverlapsPolygon which handles edge cases (points on boundary, collinear segments).
|
||||||
* Returns the highest slab elevation found, or 0 if none.
|
* Returns the highest slab elevation found, or 0 if none.
|
||||||
*/
|
*/
|
||||||
@@ -518,12 +546,27 @@ export class SpatialGridManager {
|
|||||||
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)) {
|
||||||
|
// Check if wall midpoint is in a hole (if so, ignore this slab)
|
||||||
|
let inHole = false
|
||||||
|
if (slab.holes && slab.holes.length > 0) {
|
||||||
|
const midX = (start[0] + end[0]) / 2
|
||||||
|
const midZ = (start[1] + end[1]) / 2
|
||||||
|
for (const hole of slab.holes) {
|
||||||
|
if (hole.length >= 3 && pointInPolygon(midX, midZ, hole)) {
|
||||||
|
inHole = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!inHole) {
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user