task(CAD-8): truss upgrade - length presets 50/100/200/300cm, adjustable width (default 29cm), rotatable rendering as direction polygon, boxcorner corner element with bidirectional magnetic docking

This commit is contained in:
Agent Zero
2026-08-31 20:06:51 +02:00
parent ee4142b6d1
commit 3ecc99a5e8
4 changed files with 562 additions and 47 deletions
+56 -17
View File
@@ -400,39 +400,78 @@ export function elementToPrimitives(el: CADElement, attrDefs?: Array<{ tag: stri
}
case 'truss': {
// Traverse (CAD-7): Balken als Rechteck + 2 Gurtlinien entlang
// der Rotation (wie ein Fachwerk-Profil)
// Traverse (CAD-7/8): ROTIERTES Rechteck-Polygon + Gurtlinien
// entlang der Richtung (Fachwerk-Profil), Breite = trussWidth.
const length = (props.length as number | undefined) ?? el.width;
const tWidth = (props.trussWidth as number | undefined) ?? el.height ?? 29;
const rotDeg = (props.rotation as number | undefined) ?? 0;
const rad = (rotDeg * Math.PI) / 180;
const dx = Math.cos(rad) * (length / 2);
const dy = Math.sin(rad) * (length / 2);
const nx = -Math.sin(rad) * 10; // Normalen-Offset (halbe Hoehe)
const ny = Math.cos(rad) * 10;
const ux = Math.cos(rad), uy = Math.sin(rad); // Laengsrichtung
const nx = -Math.sin(rad), ny = Math.cos(rad); // Normalenrichtung
const hl = length / 2, hw = tWidth / 2;
const c = { x: el.x, y: el.y };
return [
const corner = (su: number, sv: number): { x: number; y: number } => ({
x: c.x + ux * (hl * su) + nx * (hw * sv),
y: c.y + uy * (hl * su) + ny * (hw * sv),
});
const pts = [corner(-1, -1), corner(1, -1), corner(1, 1), corner(-1, 1)];
const strokeCol = (props.stroke as string | undefined) ?? '#9aa0a6';
const out: ShapePrimitive[] = [
{
kind: 'rect',
x: c.x - dx, y: c.y - dy,
w: length, h: 20,
fill: fillOrNull(props.fill) ?? '#6b7280',
stroke: (props.stroke as string | undefined) ?? '#9aa0a6',
kind: 'polyline',
points: pts,
close: true,
stroke: strokeCol,
strokeWidth: 2,
},
// Gurtlinien oben/unten entlang der Traverse
// Gurtlinien oben/unten
{
kind: 'line',
from: { x: c.x - dx + nx, y: c.y - dy + ny },
to: { x: c.x + dx + nx, y: c.y + dy + ny },
from: corner(-1, -1),
to: corner(1, -1),
stroke: '#4b5563', strokeWidth: 1,
},
{
kind: 'line',
from: { x: c.x - dx - nx, y: c.y - dy - ny },
to: { x: c.x + dx - nx, y: c.y + dy - ny },
from: corner(-1, 1),
to: corner(1, 1),
stroke: '#4b5563', strokeWidth: 1,
},
];
return out;
}
case 'boxcorner': {
// Eck-Traverse (CAD-8): L-foermiges Polygon (6 Punkte) aus zwei
// Armen (rot und rot+90) um den Eckpunkt, Breite = trussWidth.
const armLength = (props.armLength as number | undefined) ?? 50;
const bWidth = (props.trussWidth as number | undefined) ?? 29;
const rotDeg = (props.rotation as number | undefined) ?? 0;
const rad = (rotDeg * Math.PI) / 180;
const ux = Math.cos(rad), uy = Math.sin(rad);
const nx = -Math.sin(rad), ny = Math.cos(rad);
const v = { x: el.x, y: el.y };
const px = (a: number, b: number): { x: number; y: number } => ({
x: v.x + ux * a + nx * b,
y: v.y + uy * a + ny * b,
});
// L-Geometrie: Arm1 entlang +u, Arm2 entlang +n (rot+90)
const pts = [
px(0, 0),
px(armLength, 0),
px(armLength, bWidth),
px(bWidth, bWidth),
px(bWidth, armLength),
px(0, armLength),
];
const strokeCol = (props.stroke as string | undefined) ?? '#9aa0a6';
return [{
kind: 'polyline',
points: pts,
close: true,
stroke: strokeCol,
strokeWidth: 2,
}];
}
case 'barrier': {