ai-chatbot/packages/core/src/systems/wall/wall-footprint.ts
Sudhir Yadav b1709de44a
feat: curved wall and fixes (#236)
* feat: add polygon movement support to editor and implement dedicated move tools for walls, slabs, and ceilings

* feat: add uv2 attribute to ceiling and slab geometries for lightmap support

* Fix curved wall miters and align roof position sliders

* Fix wall measurement label and extension anchors

* Fix WebGPU renderer initialization order

* fix(editor): scope wall movement to the selected level

---------

Co-authored-by: Pascal <open@pascal.app>
2026-04-15 12:41:16 -04:00

80 lines
2.3 KiB
TypeScript

import type { WallNode } from '../../schema'
import { getWallSurfacePolygon, isCurvedWall } from './wall-curve'
import {
getWallMiterBoundaryPoints,
type Point2D,
pointToKey,
type WallMiterData,
} from './wall-mitering'
export const DEFAULT_WALL_THICKNESS = 0.1
export const DEFAULT_WALL_HEIGHT = 2.5
const CURVED_WALL_SURFACE_SEGMENTS = 24
export function getWallThickness(wallNode: WallNode): number {
return wallNode.thickness ?? DEFAULT_WALL_THICKNESS
}
export function getWallPlanFootprint(wallNode: WallNode, miterData: WallMiterData): Point2D[] {
const { junctionData } = miterData
const wallStart: Point2D = { x: wallNode.start[0], y: wallNode.start[1] }
const wallEnd: Point2D = { x: wallNode.end[0], y: wallNode.end[1] }
const thickness = getWallThickness(wallNode)
const halfT = thickness / 2
const v = { x: wallEnd.x - wallStart.x, y: wallEnd.y - wallStart.y }
const L = Math.sqrt(v.x * v.x + v.y * v.y)
if (L < 1e-9) {
return []
}
const nUnit = { x: -v.y / L, y: v.x / L }
const keyStart = pointToKey(wallStart)
const keyEnd = pointToKey(wallEnd)
const startJunction = junctionData.get(keyStart)?.get(wallNode.id)
const endJunction = junctionData.get(keyEnd)?.get(wallNode.id)
if (isCurvedWall(wallNode)) {
const boundaryPoints = getWallMiterBoundaryPoints(wallNode, miterData)
if (!boundaryPoints) {
return []
}
const { startLeft, startRight, endLeft, endRight } = boundaryPoints
return getWallSurfacePolygon(wallNode, CURVED_WALL_SURFACE_SEGMENTS, {
endLeft,
endRight,
startLeft,
startRight,
})
}
const pStartLeft: Point2D = startJunction?.left || {
x: wallStart.x + nUnit.x * halfT,
y: wallStart.y + nUnit.y * halfT,
}
const pStartRight: Point2D = startJunction?.right || {
x: wallStart.x - nUnit.x * halfT,
y: wallStart.y - nUnit.y * halfT,
}
const pEndLeft: Point2D = endJunction?.right || {
x: wallEnd.x + nUnit.x * halfT,
y: wallEnd.y + nUnit.y * halfT,
}
const pEndRight: Point2D = endJunction?.left || {
x: wallEnd.x - nUnit.x * halfT,
y: wallEnd.y - nUnit.y * halfT,
}
const polygon: Point2D[] = [pStartRight, pEndRight]
if (endJunction) {
polygon.push(wallEnd)
}
polygon.push(pEndLeft, pStartLeft)
if (startJunction) {
polygon.push(wallStart)
}
return polygon
}