feat(view): 전단철근 구간 표 on the ③ coping tab (시안 ③)

- 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 <noreply@anthropic.com>
This commit is contained in:
ypshimandClaude Haiku 5.5 committed 2026-10-22 12:17:12 +09:00
1 parent 488b65af31
commit 8ac5d2973c
3 files changed
+59

No files matched your search

+21
View File
@@ -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),
];
}
+27
View File
@@ -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' });
}
+11
View File
@@ -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]);
});
});