task(CAD-11): truss professional upgrade - chordCount (1-4 belt tubes) with adjustable rendering, free length input (10-1000cm), variable angle corners (15-165), circle truss tool with diameter option, BOM with chordCount grouping + Pi*d circumference
This commit is contained in:
@@ -400,14 +400,16 @@ export function elementToPrimitives(el: CADElement, attrDefs?: Array<{ tag: stri
|
||||
}
|
||||
|
||||
case 'truss': {
|
||||
// Traverse (CAD-7/8): ROTIERTES Rechteck-Polygon + Gurtlinien
|
||||
// entlang der Richtung (Fachwerk-Profil), Breite = trussWidth.
|
||||
// Traverse (CAD-7/8/11): ROTIERTES Rechteck-Polygon + Gurtlinien
|
||||
// entlang der Richtung (Fachwerk-Profil), Breite = trussWidth,
|
||||
// chordCount = Anzahl Gurtrohre (CAD-11).
|
||||
const length = (props.length as number | undefined) ?? el.width;
|
||||
const tWidth = (props.trussWidth as number | undefined) ?? el.height ?? 29;
|
||||
const chordCount = Math.max(1, Math.min(4, (props.chordCount as number | undefined) ?? 2));
|
||||
const rotDeg = (props.rotation as number | undefined) ?? 0;
|
||||
const rad = (rotDeg * Math.PI) / 180;
|
||||
const ux = Math.cos(rad), uy = Math.sin(rad); // Laengsrichtung
|
||||
const nx = -Math.sin(rad), ny = Math.cos(rad); // Normalenrichtung
|
||||
const ux = Math.cos(rad), uy = Math.sin(rad);
|
||||
const nx = -Math.sin(rad), ny = Math.cos(rad);
|
||||
const hl = length / 2, hw = tWidth / 2;
|
||||
const c = { x: el.x, y: el.y };
|
||||
const corner = (su: number, sv: number): { x: number; y: number } => ({
|
||||
@@ -424,45 +426,58 @@ export function elementToPrimitives(el: CADElement, attrDefs?: Array<{ tag: stri
|
||||
stroke: strokeCol,
|
||||
strokeWidth: 2,
|
||||
},
|
||||
// Gurtlinien oben/unten
|
||||
{
|
||||
kind: 'line',
|
||||
from: corner(-1, -1),
|
||||
to: corner(1, -1),
|
||||
stroke: '#4b5563', strokeWidth: 1,
|
||||
},
|
||||
{
|
||||
kind: 'line',
|
||||
from: corner(-1, 1),
|
||||
to: corner(1, 1),
|
||||
stroke: '#4b5563', strokeWidth: 1,
|
||||
},
|
||||
];
|
||||
// Gurtrohre: chordCount Linien gleichmaessig ueber die Breite verteilt
|
||||
// chordCount=1: Mittellinie, chordCount=2: bei ±hw/2, chordCount=4: bei ±hw/2 und ±hw/6
|
||||
for (let ci = 0; ci < chordCount; ci++) {
|
||||
let sv: number;
|
||||
if (chordCount === 1) sv = 0;
|
||||
else if (chordCount === 2) sv = ci === 0 ? -0.5 : 0.5;
|
||||
else if (chordCount === 3) sv = ci === 0 ? -0.67 : ci === 1 ? 0 : 0.67;
|
||||
else sv = -0.75 + ci * 0.5; // chordCount=4: -0.75, -0.25, 0.25, 0.75
|
||||
const chordPt = (su: number): { x: number; y: number } => ({
|
||||
x: c.x + ux * (hl * su) + nx * (hw * sv),
|
||||
y: c.y + uy * (hl * su) + ny * (hw * sv),
|
||||
});
|
||||
const from = chordPt(-1);
|
||||
const to = chordPt(1);
|
||||
out.push({ kind: 'line', from, to, 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.
|
||||
// Eck-Traverse (CAD-8/11): L-foermiges Polygon (6 Punkte) aus zwei
|
||||
// Armen (rot und rot+angle) um den Eckpunkt, Breite = trussWidth,
|
||||
// Winkel = angle (variabel, CAD-11, Default 90).
|
||||
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 angleDeg = (props.angle as number | undefined) ?? 90;
|
||||
const rad = (rotDeg * Math.PI) / 180;
|
||||
const rad2 = ((rotDeg + angleDeg) * 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 vx = { 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,
|
||||
x: vx.x + ux * a + nx * b,
|
||||
y: vx.y + uy * a + ny * b,
|
||||
});
|
||||
// L-Geometrie: Arm1 entlang +u, Arm2 entlang +n (rot+90)
|
||||
const ax2 = Math.cos(rad2), ay2 = Math.sin(rad2);
|
||||
const pxa = (a: number, b: number): { x: number; y: number } => ({
|
||||
x: vx.x + ax2 * a - ay2 * b,
|
||||
y: vx.y + ay2 * a + ax2 * b,
|
||||
});
|
||||
// L-Geometrie: Arm1 entlang +u (rot), Arm2 entlang rot+angle
|
||||
const pts = [
|
||||
px(0, 0),
|
||||
px(armLength, 0),
|
||||
px(armLength, bWidth),
|
||||
px(bWidth, bWidth),
|
||||
px(bWidth, armLength),
|
||||
px(0, armLength),
|
||||
pxa(bWidth, 0),
|
||||
pxa(armLength, 0),
|
||||
pxa(0, 0),
|
||||
px(0, bWidth),
|
||||
];
|
||||
const strokeCol = (props.stroke as string | undefined) ?? '#9aa0a6';
|
||||
return [{
|
||||
@@ -474,6 +489,35 @@ export function elementToPrimitives(el: CADElement, attrDefs?: Array<{ tag: stri
|
||||
}];
|
||||
}
|
||||
|
||||
case 'circletruss': {
|
||||
// Kreis-Traverse (CAD-11): Aussenkreis + Innenkreis +
|
||||
// chordCount Gurtrohr-Kreise gleichmaessig verteilt.
|
||||
const diameter = (props.diameter as number | undefined) ?? el.width;
|
||||
const tWidth = (props.trussWidth as number | undefined) ?? 29;
|
||||
const chordCount = Math.max(1, Math.min(4, (props.chordCount as number | undefined) ?? 2));
|
||||
const rOuter = diameter / 2;
|
||||
const rInner = rOuter - tWidth;
|
||||
const strokeCol = (props.stroke as string | undefined) ?? '#9aa0a6';
|
||||
const out: ShapePrimitive[] = [
|
||||
{ kind: 'circle', center: { x: el.x, y: el.y }, radius: rOuter, fill: null, stroke: strokeCol, strokeWidth: 2 },
|
||||
{ kind: 'circle', center: { x: el.x, y: el.y }, radius: rInner, fill: null, stroke: strokeCol, strokeWidth: 1 },
|
||||
];
|
||||
// Gurtrohr-Kreise: gleichmaessig zwischen Aussen- und Innenkreis
|
||||
const rMid = (rOuter + rInner) / 2;
|
||||
for (let ci = 0; ci < chordCount; ci++) {
|
||||
const ang = (2 * Math.PI * ci) / chordCount;
|
||||
out.push({
|
||||
kind: 'circle',
|
||||
center: { x: el.x + Math.cos(ang) * rMid, y: el.y + Math.sin(ang) * rMid },
|
||||
radius: tWidth * 0.15,
|
||||
fill: null,
|
||||
stroke: '#4b5563',
|
||||
strokeWidth: 1,
|
||||
});
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
case 'barrier': {
|
||||
// Absperrung (Task E7): Kette aus Kreis-Paaren (properties.circles).
|
||||
const circles = Array.isArray(props.circles)
|
||||
|
||||
Reference in New Issue
Block a user