Adds two new MEP node families (HVAC ductwork, DWV plumbing) built on a shared port-connectivity model. Co-authored by @sudhir9297.
59 lines
1.7 KiB
TypeScript
59 lines
1.7 KiB
TypeScript
import type { FloorplanGeometry, GeometryContext } from '@pascal-app/core'
|
|
import { INCHES_TO_METERS } from '../duct-segment/geometry'
|
|
import { getPipeFittingPorts } from './ports'
|
|
import type { PipeFittingNode } from './schema'
|
|
|
|
const WASTE_COLOR = '#57534e'
|
|
const VENT_COLOR = '#78716c'
|
|
|
|
/**
|
|
* Floor-plan symbol for a DWV fitting: one line per collar from the
|
|
* junction out (a wye's 45° branch reads at its true plan angle), plus
|
|
* a hub circle. Vertical collars (stack connections) collapse onto the
|
|
* hub, which is how they should read from above.
|
|
*/
|
|
export function buildPipeFittingFloorplan(
|
|
node: PipeFittingNode,
|
|
ctx: GeometryContext,
|
|
): FloorplanGeometry | null {
|
|
const [cx, , cz] = node.position
|
|
const view = ctx.viewState
|
|
const palette = view?.palette
|
|
const showSelectedChrome = (view?.selected || view?.highlighted) ?? false
|
|
const stroke =
|
|
showSelectedChrome && palette
|
|
? palette.selectedStroke
|
|
: node.system === 'vent'
|
|
? VENT_COLOR
|
|
: WASTE_COLOR
|
|
|
|
const children: FloorplanGeometry[] = []
|
|
for (const port of getPipeFittingPorts(node)) {
|
|
const px = port.position[0]
|
|
const pz = port.position[2]
|
|
if (Math.hypot(px - cx, pz - cz) < 1e-4) continue
|
|
children.push({
|
|
kind: 'line',
|
|
x1: cx,
|
|
y1: cz,
|
|
x2: px,
|
|
y2: pz,
|
|
stroke,
|
|
strokeWidth: port.diameter * INCHES_TO_METERS,
|
|
strokeLinecap: 'round',
|
|
opacity: showSelectedChrome ? 0.95 : 0.85,
|
|
})
|
|
}
|
|
children.push({
|
|
kind: 'circle',
|
|
cx,
|
|
cy: cz,
|
|
r: (node.diameter * INCHES_TO_METERS) / 2 + 0.012,
|
|
fill: stroke,
|
|
opacity: 0.95,
|
|
})
|
|
if (showSelectedChrome) children.push({ kind: 'move-handle', point: [cx, cz] })
|
|
|
|
return { kind: 'group', children }
|
|
}
|