* 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>
80 lines
2.3 KiB
TypeScript
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
|
|
}
|