ceiling holes
This commit is contained in:
@@ -566,7 +566,7 @@ export class SpatialGridManager {
|
||||
|
||||
/**
|
||||
* Check if an item can be placed on a ceiling.
|
||||
* Validates that the footprint is within the ceiling polygon and doesn't overlap other ceiling items.
|
||||
* Validates that the footprint is within the ceiling polygon (but not in any holes) and doesn't overlap other ceiling items.
|
||||
*/
|
||||
canPlaceOnCeiling(
|
||||
ceilingId: string,
|
||||
@@ -588,6 +588,15 @@ export class SpatialGridManager {
|
||||
}
|
||||
}
|
||||
|
||||
// Check if item center is in any hole (if so, it cannot be placed)
|
||||
const [centerX, , centerZ] = position
|
||||
const holes = ceiling.holes || []
|
||||
for (const hole of holes) {
|
||||
if (hole.length >= 3 && pointInPolygon(centerX, centerZ, hole)) {
|
||||
return { valid: false, conflictIds: [] }
|
||||
}
|
||||
}
|
||||
|
||||
// Check for overlaps with other ceiling items
|
||||
return this.getCeilingGrid(ceilingId).canPlace(position, dimensions, rotation, ignoreIds)
|
||||
}
|
||||
|
||||
@@ -10,11 +10,13 @@ export const CeilingNode = BaseNode.extend({
|
||||
// Specific props
|
||||
// Polygon boundary - array of [x, z] coordinates defining the ceiling
|
||||
polygon: z.array(z.tuple([z.number(), z.number()])),
|
||||
holes: z.array(z.array(z.tuple([z.number(), z.number()]))).default([]),
|
||||
height: z.number().default(2.5), // Height in meters
|
||||
}).describe(
|
||||
dedent`
|
||||
Ceiling node - used to represent a ceiling in the building
|
||||
- polygon: array of [x, z] points defining the ceiling boundary
|
||||
- holes: array of polygons representing holes in the ceiling
|
||||
`,
|
||||
)
|
||||
|
||||
|
||||
@@ -70,6 +70,24 @@ export function generateCeilingGeometry(ceilingNode: CeilingNode): THREE.BufferG
|
||||
}
|
||||
shape.closePath()
|
||||
|
||||
// Add holes to the shape
|
||||
const holes = ceilingNode.holes || []
|
||||
for (const holePolygon of holes) {
|
||||
if (holePolygon.length < 3) continue
|
||||
|
||||
const holePath = new THREE.Path()
|
||||
const holeFirstPt = holePolygon[0]!
|
||||
holePath.moveTo(holeFirstPt[0], -holeFirstPt[1])
|
||||
|
||||
for (let i = 1; i < holePolygon.length; i++) {
|
||||
const pt = holePolygon[i]!
|
||||
holePath.lineTo(pt[0], -pt[1])
|
||||
}
|
||||
holePath.closePath()
|
||||
|
||||
shape.holes.push(holePath)
|
||||
}
|
||||
|
||||
// Create flat shape geometry (no extrusion)
|
||||
const geometry = new THREE.ShapeGeometry(shape)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user