Files
Pier_v1/src/view/block-rebar-svg.ts
T
ypshimandClaude Haiku 5.5 38bb26eda5 feat(rebar): block rebar settings card and C–C section on the ③ bearing tab
- Six inputs with their ranges and P1 defaults; a change regenerates the pier.
- The 적용 블럭 line shows the blocks (분리 n개 or 일체 n쌍, 전체).
- view/block-rebar-svg.ts: the section C–C along the 교축 with the S2 dots, the
  S1 lines and legs, and the dimensions (block widths, the S2 layout).
- 받침블럭 철근 설정 is tracked for changes (defaults vs the current draft).

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-26 14:12:36 +09:00

56 lines
3.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type { PierModel } from '../core/geometry';
import { barDepths, barsAcross, type BlockRebarSettings } from '../core/rebar/bearing-block';
import { INTEGRATED_BLOCK } from '../core/integrated-block';
/**
* 받침블럭 배근 · 단면 C–C (승인 2026-10-26, 시안 ③): a section along the 교축, through the blocks. x = 교축 (n), y = EL
* (down from the highest block top). S2 bars are dots along the top, S1 bars are lines with legs down into the coping.
* Dimensions: the block widths and gap, the bar layout (end · n@spacing = span), and the top cover.
*/
export function blockRebarSectionSvg(m: PierModel): string {
const s: BlockRebarSettings = m.blockRebar;
const depth = barDepths(s);
const ib = m.integratedBlocks;
const parts: string[] = [];
const topRef = Math.max(...m.blocks.map((b) => b.top));
const Y = (el: number) => (topRef - el) * 1000;
// Spans to draw: one 2500 span per 일체 pair, else one 1200 span per bearing.
const spans = ib.length > 0
? ib.map((x) => ({ nc: x.n, width: INTEGRATED_BLOCK.length, bottom: x.bottom, topL: x.topFront, topR: x.topBack, depthTopL: x.topFront, depthTopR: x.topBack, stepped: true }))
: m.blocks.map((b) => ({ nc: b.n, width: 1200, bottom: b.bottom, topL: b.top, topR: b.top, depthTopL: b.top, depthTopR: b.top, stepped: false }));
const nAll = spans.map((x) => x.nc);
const nc = (Math.min(...nAll) + Math.max(...nAll)) / 2;
const X = (n: number) => (n - nc) * 1000;
for (const sp of spans) {
const x0 = X(sp.nc - sp.width / 2000);
const x1 = X(sp.nc + sp.width / 2000);
if (sp.stepped) {
const xm = X(sp.nc);
parts.push(`<polygon points="${x0},${Y(sp.bottom)} ${x1},${Y(sp.bottom)} ${x1},${Y(sp.topR)} ${xm},${Y(sp.topR)} ${xm},${Y(sp.topL)} ${x0},${Y(sp.topL)}" fill="#D6DDE5" stroke="#6E8496" stroke-width="8"></polygon>`);
} else {
parts.push(`<rect x="${x0}" y="${Y(sp.topL)}" width="${x1 - x0}" height="${(sp.topL - sp.bottom) * 1000}" fill="#D6DDE5" stroke="#6E8496" stroke-width="8"></rect>`);
}
// S2: dots along the top at the S2 depth (each half at its own top when stepped).
const a2 = barsAcross(sp.width, s.spacingS2, s);
for (let i = 0; i < a2.count; i++) {
const xb = x0 + a2.firstEnd + i * a2.spacing;
const top = sp.stepped && xb > (x0 + x1) / 2 ? sp.depthTopR : sp.depthTopL;
parts.push(`<circle cx="${xb}" cy="${Y(top - depth.S2 / 1000)}" r="16" fill="#0F5C66"></circle>`);
}
// S1: a line across the block at the S1 depth, legs down into the coping at both ends.
const low = sp.stepped ? Math.min(sp.topL, sp.topR) : sp.topL;
const z1 = low - depth.S1 / 1000;
const leg = s.legLength;
parts.push(`<line x1="${x0 + s.coverSide / 1}" y1="${Y(z1)}" x2="${x1 - s.coverSide / 1}" y2="${Y(z1)}" stroke="#B4531F" stroke-width="10"></line>`);
parts.push(`<line x1="${x0 + s.coverSide / 1}" y1="${Y(z1)}" x2="${x0 + s.coverSide / 1}" y2="${Y(z1) + leg}" stroke="#B4531F" stroke-width="10"></line>`);
parts.push(`<line x1="${x1 - s.coverSide / 1}" y1="${Y(z1)}" x2="${x1 - s.coverSide / 1}" y2="${Y(z1) + leg}" stroke="#B4531F" stroke-width="10"></line>`);
// Dimensions: the S2 layout under the span.
const yDim = Y(sp.bottom) + 120;
parts.push(`<text x="${(x0 + x1) / 2}" y="${yDim + 90}" text-anchor="middle" font-size="70" fill="#18212B">${a2.firstEnd.toFixed(1)} · ${a2.count - 1}@${a2.spacing}=${(a2.count - 1) * a2.spacing} · ${a2.firstEnd.toFixed(1)}</text>`);
parts.push(`<text x="${(x0 + x1) / 2}" y="${Y(topRef) - 80}" text-anchor="middle" font-size="70" fill="#18212B">${(sp.width).toFixed(0)}</text>`);
}
return `<svg viewBox="-1900 -700 3800 1900" width="100%" style="max-width: 680px; height: auto" role="img" aria-label="받침블럭 배근 단면 C–C: S2 점, S1 선과 다리, 치수">${parts.join('')}</svg>`;
}