import type { ColumnInput, columnRebar } from '../core/rebar/column'; /** * 기둥 배근 · 단면 A·B·C (승인 2026-10-26, 삽도 기준): plan views at the first level of each group, in the drawing's order. * A 일반 = P3 첫 단 (full ring, no coupler), B 확대기초 안 = P4 첫 단 (2 semicircles, 2 couplers), C 단부 = P5 첫 단 (full ring, 1 coupler). * P1 and P2 share each angle (r 875 and r 843.2). P6 is four chords through the centre only when a P6 level sits at the section. * Dimensions and labels are read from the column input and result; the section level is the first level of its group (no new calculation). */ export type ColumnSection = 'A' | 'B' | 'C'; const COLOR = { main: '#0F5C66', tie: '#6B3FA0', crossTie: '#B4531F', coupler: '#0F5C66', guide: '#55606E', dim: '#B42318' }; /** P6 chord angles (deg) from 기둥철근 (1).md §7: 0 · 46.96 · 90 · 133.04. */ const P6_ANGLES = [0, 46.96, 90, 133.04]; export function columnSectionSvg(kind: ColumnSection, input: ColumnInput, col: ReturnType): string { const W = 300; const H = 300; const level = kind === 'A' ? col.p3[0] : kind === 'B' ? col.p4[0] : col.p5[0]; const title = kind === 'A' ? 'A 일반 · P3' : kind === 'B' ? 'B 확대기초 안 · P4' : 'C 단부 · P5'; if (level === undefined) { return `단 없음`; } const cx = W / 2; const cy = H / 2 + 6; // Scale from the column outline (D/2), so the 2000 dimension and the 875 / 125 offsets fit in the frame. const k = (H / 2 - 52) / (input.D / 2); const pt = (r: number, deg: number): [number, number] => [cx + r * k * Math.cos((deg * Math.PI) / 180), cy - r * k * Math.sin((deg * Math.PI) / 180)]; const n = input.nDiv; const step = 360 / n; const R = (col.tieRadius * k).toFixed(1); const parts: string[] = []; const text = (x: number, yy: number, s: string, anchor = 'start', fill = COLOR.guide) => `${s}`; // Column outline (D) and the dimension lines: D above, c and r1 along the horizontal diameter. const outer = input.D / 2 * k; parts.push(``); const dimY = cy - outer - 14; parts.push(``); parts.push(text(cx, dimY - 4, (input.D / 1000).toFixed(3), 'middle', COLOR.dim)); const axisY = cy + 14; const p1x = cx - col.r1 * k; parts.push(text((cx - outer + p1x) / 2, axisY, `${input.D / 2 - col.r1}`, 'middle', COLOR.dim)); parts.push(text((p1x + cx) / 2, axisY, `${col.r1}`, 'middle', COLOR.dim)); // Tie: a full ring (A, C) or two semicircles through the couplers (B). if (kind === 'B') { const [x1, y1] = pt(col.tieRadius, step / 2); const [x2, y2] = pt(col.tieRadius, step / 2 + 180); parts.push(``); parts.push(``); } else { parts.push(``); } // Couplers: a filled dot on the tie, with a leader to a small hollow circle outside the column (the 삽도 convention). const couplerAngles = kind === 'B' ? [step / 2, step / 2 + 180] : kind === 'C' ? [step / 2] : []; for (const deg of couplerAngles) { const [x, y] = pt(col.tieRadius, deg); const [ox, oy] = pt(input.D / 2 + 90, deg); parts.push(``); parts.push(``); parts.push(``); } // P6 chords through the centre, only at a P6 level of this section. if (col.p6Levels.some((z) => Math.abs(z - level) < 1e-6)) { for (const deg of P6_ANGLES) { const [x1, y1] = pt(col.tieRadius, deg); const [x2, y2] = pt(col.tieRadius, deg + 180); parts.push(``); } } // Main bars: P1 (r1) and P2 (r2) on the same angles. for (let i = 0; i < n; i++) { const deg = i * step; const [x1, y1] = pt(col.r1, deg); const [x2, y2] = pt(col.r2, deg); parts.push(``); parts.push(``); } // Labels: the spec of each bar group with its live spacing, and the section level. const spec = kind === 'A' ? `P1·P2 S32 Div.${n} · P3 H19 @${input.ctcP3}` : kind === 'B' ? `P4 H19 @${input.ctcP4}` : `P5 H19 @${input.ctcP5}`; parts.push(text(8, 16, title, 'start', '#1F2937')); parts.push(text(8, 30, `z = ${level} mm`)); parts.push(text(8, H - 24, spec, 'start', '#1F2937')); if (kind === 'A') parts.push(text(8, H - 10, `띠철근 둘레 ${col.tieCircumference} · 겹침 ${col.lapP3}`)); if (kind === 'B') parts.push(text(8, H - 10, `반원 ${col.p4SemicircleLength} × 2 · 커플러 2`)); if (kind === 'C') parts.push(text(8, H - 10, `띠철근 둘레 ${col.tieCircumference} · 커플러 1`)); return `${parts.join('')}`; }