Openings and walls on a room's edge
64-bitFinds the doors, windows and walls that lie on the outline of a room.
t = clamp(((p − a) · (b − a)) ÷ |b − a|², 0, 1); d = |p − a − t (b − a)|; on the edge if d ≤ tolerance
The distance is one Math.hypot of two differences; a zero-length edge uses a divisor of 1 instead of dividing by zero. The tolerances are 700 mm for doors and windows and half the wall thickness plus 60 mm for a wall's midpoint, neither scaled to the room.
const segD = (p, a, b) => { const dx = b[0] - a[0], dy = b[1] - a[1], L = dx * dx + dy * dy || 1, t = Math.max(0, Math.min(1, ((p[0] - a[0]) * dx + (p[1] - a[1]) * dy) / L)); return Math.hypot(p[0] - a[0] - dx * t, p[1] - a[1] - dy * t); };
for (const r of rooms) {
const edge = (p, tol) => r.poly.some((q, i) => segD(p, q, r.poly[(i + 1) % r.poly.length]) <= tol);
out.push(clone({ storey: lv.guid, storeyName: lv.name, index: r.index, name: lv.name + ': ' + String(r.index + 1), poly: r.poly, holes: r.holes, area: r.area, z: lv.elevation,
doors: doors.filter((d) => edge([d.x, d.y], 700)), windows: windows.filter((d) => edge([d.x, d.y], 700)),
walls: walls.filter((x) => edge([(x.a[0] + x.b[0]) / 2, (x.a[1] + x.b[1]) / 2], (x.t || 0) / 2 + 60)).map((x) => x.guid) }));