From 8ac5d2973cf33167c9cb70dafba8d79aa8ee0594 Mon Sep 17 00:00:00 2001 From: ypshim Date: Thu, 22 Oct 2026 12:17:12 +0900 Subject: [PATCH] =?UTF-8?q?feat(view):=20=EC=A0=84=EB=8B=A8=EC=B2=A0?= =?UTF-8?q?=EA=B7=BC=20=EA=B5=AC=EA=B0=84=20=ED=91=9C=20on=20the=20?= =?UTF-8?q?=E2=91=A2=20coping=20tab=20(=EC=8B=9C=EC=95=88=20=E2=91=A2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Segments of C9 (좌 경사), C10 (Level), C11 (우 경사): first and last bar in metres, spacing, count, and bar number. From the bar positions (코핑철근.md §3). - Test: 0.300–4.550 (18 @250), 4.800–7.200 (9 @300), 7.450–11.700 (18 @250). - Not verified in a browser. Co-Authored-By: Claude Haiku 5.5 --- src/core/rebar/coping.ts | 21 +++++++++++++++++++++ src/main.ts | 27 +++++++++++++++++++++++++++ tests/rebar-coping-lengths.test.ts | 11 +++++++++++ 3 files changed, 59 insertions(+) diff --git a/src/core/rebar/coping.ts b/src/core/rebar/coping.ts index 2ab3841..44568bb 100644 --- a/src/core/rebar/coping.ts +++ b/src/core/rebar/coping.ts @@ -110,3 +110,24 @@ export function capLength(x: number, coping: number): number { /** Pieces per position: 3 closed stirrups × (U + cap) = 6. Total 270 for C9 + C10 + C11 (document). */ export const PIECES_PER_POSITION = 6; + +/** + * 전단철근 구간 표 (시안 ③ · 코핑): C9 / C10 / C11 grouped by segment, from the bar positions. + * Positions are along the coping length (mm); the table shows the first and last bar of each segment. + */ +export function shearSegments(coping: number): { segment: string; from: number; to: number; spacing: number; count: number; bar: 'C9' | 'C10' | 'C11' }[] { + const b = shearBars(coping); + const seg = (name: string, xs: number[], bar: 'C9' | 'C10' | 'C11', spacing: number) => ({ + segment: name, + from: Math.min(...xs), + to: Math.max(...xs), + spacing, + count: xs.length, + bar, + }); + return [ + seg('좌 경사', b.c9, 'C9', COPING_REBAR.spacingS), + seg('Level', b.c10, 'C10', COPING_REBAR.spacingL), + seg('우 경사', b.c11, 'C11', COPING_REBAR.spacingS), + ]; +} diff --git a/src/main.ts b/src/main.ts index 187e1e4..e542fed 100644 --- a/src/main.ts +++ b/src/main.ts @@ -11,6 +11,7 @@ import { adjustRow, layoutText, resolveRowCounts, rowLayout, totalPiles } from ' import { applyCopy, DEFAULT_COPY_ITEMS, planCopy, type CopyItem } from './core/copy'; import { pileGeometry } from './core/geometry'; import { rebarSummary, type RebarRow } from './core/rebar/summary'; +import { shearSegments } from './core/rebar/coping'; import { DEFAULT_MATERIAL, isAssumedMaterial, type Material } from './core/rebar/common'; import { allVisibleChecked, setVisibleChecked, type TypeFilter } from './core/selection'; import { choose, defaultSummary, isSelectable, SHAPE_GROUPS, UNDEFINED_REASON, type MemberId } from './core/shape-options'; @@ -788,6 +789,32 @@ function renderRebar(): void { } $('step3-status').textContent = `계산됨 · 경고 ${warnings.length}`; renderMaterial(); + // 전단철근 구간 표 (시안 ③ 코핑 탭): segments of C9 / C10 / C11 along the coping, in metres. + if (state.rebarMember === 'coping') { + const seg = shearSegments(pier.model.copingL * 1000); + const st = el('table', undefined, 'grid-table rebar-table'); + const sh = el('thead'); + const shr = el('tr'); + for (const h of ['구간', '시작 (m)', '끝 (m)', '간격 (mm)', '개수', '번호']) shr.appendChild(el('th', h)); + sh.appendChild(shr); + st.appendChild(sh); + const sb = el('tbody'); + for (const g of seg) { + const tr = el('tr'); + tr.append( + el('td', g.segment), + el('td', (g.from / 1000).toFixed(3)), + el('td', (g.to / 1000).toFixed(3)), + el('td', String(g.spacing)), + el('td', String(g.count)), + el('td', g.bar), + ); + sb.appendChild(tr); + } + st.appendChild(sb); + box.appendChild(el('p', '전단철근 구간 (끝면 기준, 철근 위치의 처음과 끝)', 'lbl')); + box.appendChild(st); + } const focused = box.querySelector('tr.hl'); if (focused && state.rebarFocus) focused.scrollIntoView({ block: 'center' }); } diff --git a/tests/rebar-coping-lengths.test.ts b/tests/rebar-coping-lengths.test.ts index f7271fe..6f28213 100644 --- a/tests/rebar-coping-lengths.test.ts +++ b/tests/rebar-coping-lengths.test.ts @@ -36,3 +36,14 @@ describe('삿갓과 조각 수 (코핑철근.md §4.3, Q-K5 추천안)', () => { expect(pieces).toBe(270); }); }); + +import { shearSegments } from '../src/core/rebar/coping'; + +describe('전단철근 구간 표 (시안 ③)', () => { + it('left slope C9 0.300–4.550 (18, @250), Level C10 4.800–7.200 (9, @300), right slope C11 7.450–11.700 (18, @250)', () => { + const [left, level, right] = shearSegments(12000); + expect([left.from, left.to, left.count, left.spacing]).toEqual([300, 4550, 18, 250]); + expect([level.from, level.to, level.count, level.spacing]).toEqual([4800, 7200, 9, 300]); + expect([right.from, right.to, right.count, right.spacing]).toEqual([7450, 11700, 18, 250]); + }); +});