Files
Pier_v1/src/core/rebar/summary.ts
T
ypshimandClaude Haiku 5.5 73bff19aba feat(core): B9 shear bars of the footing (plan C5)
- B9 (확대기초철근 (1).md §9): H16 with the 135° stirrup hook, on the odd grid
  (i_W = 1, 5, …), 16 rows, 20 per row (even rows start at i_L 1, odd at 3),
  320 bars, length l_v 1750 + 2 × 189 ≈ 2128.
- The rebar summary now lists B9; the alert about B9 is gone. Positions and
  hooks are the document's proposed rules (Q-B18, Q-B19), noted on the row.
- Tests: the document's B9 values; P1 summary has 320 and only the splice alert.
- Not verified in a browser.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-22 11:34:56 +09:00

99 lines
6.4 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 '../geometry';
import { bearingBlockRebar, totals } from './bearing-block';
import { bottomPiece, topBarLength, widthLayout } from './coping-main';
import { shearBars, sideRows, C14_COUNTS, c14Total, STEP_BAR_COUNTS } from './coping';
import { columnRebar, COLUMN_P1 } from './column';
import { bottomBars, crossBars, sideBars, assemblyBars, shearB9 } from './footing';
/** One line of a 철근표. length is null where the document gives no length yet. */
export interface RebarRow {
member: 'bearing' | 'coping' | 'column' | 'footing';
name: string;
size: string;
count: number;
length: number | null;
note: string;
}
export interface RebarWarning {
code: string;
message: string;
}
/** 정척 L_bar (mm) from 확대기초철근.md §1.2. Bars longer than this need a splice. */
export const STANDARD_BAR = 12000;
/**
* 철근표 for one pier (③ screen v1): bearing blocks, coping, column, footing. Built from the generated model.
* Values come from the document rules in src/core/rebar/*. B9 (전단철근) is not computed yet.
*/
export function rebarSummary(model: PierModel): { rows: RebarRow[]; warnings: RebarWarning[] } {
const rows: RebarRow[] = [];
const warnings: RebarWarning[] = [];
const L = model.copingL * 1000;
const B = model.copingB * 1000;
// Bearing blocks (§6.3 · plan C2)
const blk = totals(bearingBlockRebar(model));
rows.push({ member: 'bearing', name: 'S1', size: 'H19', count: blk.S1, length: 2500, note: '블럭 배치 분리, 블럭당 8본' });
rows.push({ member: 'bearing', name: 'S2', size: 'H19', count: blk.S2, length: 2500, note: '블럭 배치 분리, 블럭당 8본' });
// Coping (코핑철근.md §5–§8)
const width = widthLayout(B);
const perRow = width.count / 2; // cycle split, 12 per row
// C1–C3 and C4–C6 are the same three top rows (row 1, 2, 3), one set per cycle.
for (const [name, k] of [['C1', 1], ['C2', 2], ['C3', 3], ['C4', 1], ['C5', 2], ['C6', 3]] as const) {
rows.push({ member: 'coping', name, size: 'H29', count: perRow, length: topBarLength(L, k), note: '상면, 이음 무시' });
}
const bottom = bottomPiece();
rows.push({ member: 'coping', name: 'C7', size: 'H29', count: perRow, length: bottom.piece, note: '하면, 2조각 겹침이음' });
rows.push({ member: 'coping', name: 'C8', size: 'H29', count: perRow, length: bottom.piece, note: '하면, 2조각 겹침이음' });
const shear = shearBars(L);
rows.push({ member: 'coping', name: 'C9', size: 'H25', count: shear.c9.length, length: null, note: '전단 좌 @250' });
rows.push({ member: 'coping', name: 'C10', size: 'H25', count: shear.c10.length, length: null, note: '전단 Level @300' });
rows.push({ member: 'coping', name: 'C11', size: 'H25', count: shear.c11.length, length: null, note: '전단 우 @250' });
const side = sideRows(41.288, 42.538);
rows.push({ member: 'coping', name: 'C12', size: 'H25', count: side.c12.length, length: null, note: '측면, 경사 하면에서 끊김' });
rows.push({ member: 'coping', name: 'C13', size: 'H25', count: side.c13.length, length: null, note: '측면, 끝면까지' });
rows.push({ member: 'coping', name: 'C14', size: 'H19', count: c14Total(), length: null, note: `직각 수평 ${C14_COUNTS.upperLines * C14_COUNTS.upperPerLine}+${C14_COUNTS.lower.join('+')}` });
rows.push({ member: 'coping', name: 'C15', size: 'H19', count: STEP_BAR_COUNTS.C15, length: null, note: '계단부, 가장 높은 구간' });
rows.push({ member: 'coping', name: 'C16', size: 'H19', count: STEP_BAR_COUNTS.C16, length: null, note: '계단부, 3·4구간' });
// Column (기둥철근.md · plan C4), P1 defaults
const col = columnRebar(COLUMN_P1);
rows.push({ member: 'column', name: 'P1', size: 'S32', count: col.mainP1, length: null, note: '외측 r 875, 커플러로 이음' });
rows.push({ member: 'column', name: 'P2', size: 'S32', count: col.mainP2, length: null, note: '내측 r 843.2, 커플러로 이음' });
rows.push({ member: 'column', name: '커플러', size: 'L150 Ø60', count: col.couplers, length: 150, note: '@3000, P2 +150' });
rows.push({ member: 'column', name: 'P3', size: 'H19', count: col.p3Count, length: null, note: '일반 구간 띠철근 @300' });
rows.push({ member: 'column', name: 'P5', size: 'H19', count: col.p5Count, length: null, note: '단부 띠철근 @120' });
rows.push({ member: 'column', name: 'P4', size: 'H19', count: col.p4Count, length: col.p4SemicircleLength * 2, note: '확대기초 안, 반원 2개 (길이는 반원 2개 합) · B11 간섭 무시' });
rows.push({ member: 'column', name: 'P6', size: 'H16', count: col.p6Count, length: col.p6Length, note: '크로스타이, 8단 × 4' });
// Footing (확대기초철근 (1).md · plan C5). Only when the footing exists (not 현장타설말뚝).
const f = model.footings[0];
if (f) {
const Lf = f.length * 1000;
const Wf = f.width * 1000;
const Hf = (f.top - f.bottom) * 1000;
for (const b of bottomBars(Lf, Wf, Hf)) {
rows.push({ member: 'footing', name: b.name, size: b.size, count: b.count, length: b.length, note: '교각축' });
if (b.length > STANDARD_BAR) {
warnings.push({ code: 'RB-F08', message: `${b.name} 길이 ${Math.round(b.length)} mm가 정척 ${STANDARD_BAR} mm를 넘어 이음이 필요합니다 (Q-B6).` });
}
}
for (const b of crossBars(Lf, Wf, Hf)) {
rows.push({ member: 'footing', name: b.name, size: b.size, count: b.count, length: b.length, note: '교각축 직각' });
if (b.length > STANDARD_BAR) {
warnings.push({ code: 'RB-F08', message: `${b.name} 길이 ${Math.round(b.length)} mm가 정척 ${STANDARD_BAR} mm를 넘어 이음이 필요합니다 (Q-B6).` });
}
}
for (const b of sideBars(Lf, Wf)) rows.push({ member: 'footing', name: b.name, size: b.size, count: b.count, length: b.length, note: '측면 수평' });
for (const b of assemblyBars(Lf, Wf)) rows.push({ member: 'footing', name: b.name, size: b.size, count: b.count, length: b.length, note: '조립 수평' });
const b9 = shearB9(Lf, Wf, Hf);
rows.push({ member: 'footing', name: 'B9', size: 'H16', count: b9.count, length: b9.length, note: `전단 @500 엇갈림, ${b9.rows}행 (위치·갈고리는 Q-B18·B19 제안)` });
} else {
warnings.push({ code: 'RB-F00', message: '현장타설말뚝은 확대기초가 없어 확대기초 철근을 만들지 않습니다.' });
}
return { rows, warnings };
}