diff --git a/src/main.ts b/src/main.ts index cbc1520..1e29773 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1017,6 +1017,20 @@ function renderBlockRebarSettings(box: HTMLDivElement, pier: Pier): void { const wrap = el('div', undefined, 'bearing-ref'); const current: BlockRebarSettings = { ...DEFAULT_BLOCK_REBAR, ...pier.draft.blockRebar }; wrap.appendChild(el('p', '받침블럭 배근 설정 (기본값 = P1 · 범위는 칸 옆에 표시)', 'lbl')); + // 단면 쌍 (the same selection as ②): the C–C section cuts through one pair. + const pairList = pairEccentricities(pier.model.blocks); + const chipRow = el('div', undefined, 'opts'); + pairList.forEach((p, i) => { + const chip = el('button', `${PAIR_CHIP_LABELS[p.frontNo - 1] ?? p.frontNo}·${PAIR_CHIP_LABELS[p.backNo - 1] ?? p.backNo}`, 'btn small'); + chip.type = 'button'; + chip.setAttribute('aria-pressed', String(i === bearingPairIndex)); + chip.addEventListener('click', () => { + bearingPairIndex = i; + renderAll(); + }); + chipRow.appendChild(chip); + }); + wrap.appendChild(chipRow); const grid = el('div', undefined, 'edit-fields'); for (const f of BLOCK_REBAR_FIELDS) { const row = el('div', undefined, 'edit-row'); @@ -1034,8 +1048,8 @@ function renderBlockRebarSettings(box: HTMLDivElement, pier: Pier): void { const n = pier.model.integratedBlocks.length; wrap.appendChild(el('p', `적용 블럭: ${n > 0 ? `일체 ${n}쌍` : `분리 ${pier.model.blocks.length}개`} (전체)`, 'muted small')); const fig = el('figure', undefined, 'ground-fig'); - fig.innerHTML = blockRebarSectionSvg(pier.model); - fig.appendChild(el('figcaption', '단면 C–C · 교축 방향 · S2 점(상면), S1 선과 다리(⊓) · 치수 mm', 'muted small')); + fig.innerHTML = blockRebarSectionSvg(pier.model, Math.min(bearingPairIndex, Math.max(0, pairEccentricities(pier.model.blocks).length - 1))); + fig.appendChild(el('figcaption', '단면 C–C · 교축 방향 · 선택한 쌍 · S2 점(상면), S1 선과 다리(⊓) · 치수 mm', 'muted small')); wrap.appendChild(fig); box.appendChild(wrap); } diff --git a/src/view/block-rebar-svg.ts b/src/view/block-rebar-svg.ts index 42f9787..d5626eb 100644 --- a/src/view/block-rebar-svg.ts +++ b/src/view/block-rebar-svg.ts @@ -1,24 +1,29 @@ import type { PierModel } from '../core/geometry'; import { barDepths, barsAcross, type BlockRebarSettings } from '../core/rebar/bearing-block'; import { INTEGRATED_BLOCK } from '../core/integrated-block'; +import { pairEccentricities } from '../core/bearing-layout'; /** * 받침블럭 배근 · 단면 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 { +export function blockRebarSectionSvg(m: PierModel, pairIndex = 0): string { const s: BlockRebarSettings = m.blockRebar; const depth = barDepths(s); - const ib = m.integratedBlocks; + const pair = pairEccentricities(m.blocks)[pairIndex]; + if (!pair) return ''; + const f = m.blocks.find((b) => b.no === pair.frontNo && b.row === '전열')!; + const k = m.blocks.find((b) => b.no === pair.backNo && b.row === '후열')!; + const ib = m.integratedBlocks.find((x) => x.frontNo === pair.frontNo); const parts: string[] = []; - const topRef = Math.max(...m.blocks.map((b) => b.top)); + const topRef = Math.max(f.top, k.top, ib?.topFront ?? 0, ib?.topBack ?? 0); 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 })); + // One section through the selected pair: a 2500 span (일체) or the two 1200 blocks (분리), along the 교축. + const spans = ib + ? [{ nc: ib.n, width: INTEGRATED_BLOCK.length, bottom: ib.bottom, topL: ib.topFront, topR: ib.topBack, depthTopL: ib.topFront, depthTopR: ib.topBack, stepped: true }] + : [f, k].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;