feat(core): cap bars of C9–C11 and piece count (추천안 for Q-K5)

- Recommended l_cap = h − 100 (top cover), so l_cap stays below h (RB-K04).
  Cap length = 1740 + 2·l_cap. The shear rows show U and cap ranges.
- Piece count 6 per position (3 closed stirrups × U + cap): C9 + C10 + C11 gives
  270 pieces, as in the document.
- P1/P2 per-line pieces are shown from the document (기둥철근.md §3.2).
- Tests: cap length and the 270 check.
- 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 11:38:28 +09:00
1 parent 5641bbe265
commit 1c6194cd48
3 files changed
+41 -6

No files matched your search

+15
View File
@@ -95,3 +95,18 @@ export const SIDE_LENGTHS = { C12: [3717, 5333, 6950, 8567, 10183], C13: 11746 }
/** C15 (거꾸로 된 U, 3852) and C16 (L형, 4070 / 4069) lengths, mm (코핑철근.md §7). */
export const STEP_LENGTHS = { C15: 3852, C16: [4070, 4069] as const, C14: 3447.5 } as const;
/**
* 삿갓 (upper cap) of C9–C11 (코핑철근.md §4.3). l_cap is open (Q-K5); recommended here: l_cap = h − c (top cover 100),
* so that l_cap stays below h (RB-K04). Cap length = 1740 + 2·l_cap.
*/
export const CAP = { flat: 1740, cover: 100 } as const;
export function capLength(x: number, coping: number): number {
const h = shearUHeight(x, coping);
const lCap = h - CAP.cover;
return CAP.flat + 2 * lCap;
}
/** Pieces per position: 3 closed stirrups × (U + cap) = 6. Total 270 for C9 + C10 + C11 (document). */
export const PIECES_PER_POSITION = 6;
+12 -6
View File
@@ -1,7 +1,7 @@
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, shearULength, SIDE_LENGTHS, STEP_LENGTHS } from './coping';
import { shearBars, sideRows, C14_COUNTS, c14Total, STEP_BAR_COUNTS, shearULength, SIDE_LENGTHS, STEP_LENGTHS, capLength, PIECES_PER_POSITION } from './coping';
import { columnRebar, COLUMN_P1 } from './column';
import { bottomBars, crossBars, sideBars, assemblyBars, shearB9 } from './footing';
import { splitPieces } from './common';
@@ -54,9 +54,15 @@ export function rebarSummary(model: PierModel): { rows: RebarRow[]; warnings: Re
const u = xs.map((x) => Math.round(shearULength(x, L)));
return `${Math.min(...u)}–${Math.max(...u)}`;
};
rows.push({ member: 'coping', name: 'C9', size: 'H25', count: shear.c9.length, length: null, note: `전단 좌 @250, 하부 U ${uRange(shear.c9)} (삿갓 l_cap 미정)` });
rows.push({ member: 'coping', name: 'C10', size: 'H25', count: shear.c10.length, length: null, note: `전단 Level @300, 하부 U ${uRange(shear.c10)} (삿갓 l_cap 미정)` });
rows.push({ member: 'coping', name: 'C11', size: 'H25', count: shear.c11.length, length: null, note: `전단 우 @250, 하부 U ${uRange(shear.c11)} (삿갓 l_cap 미정)` });
const capRange = (xs: number[]) => {
const c = xs.map((x) => Math.round(capLength(x, L)));
return `${Math.min(...c)}–${Math.max(...c)}`;
};
const shearNote = (label: string, xs: number[]) =>
`${label}, 하부 U ${uRange(xs)}, 삿갓 ${capRange(xs)} (l_cap 추천안, Q-K5), 조각 ${xs.length * PIECES_PER_POSITION}`;
rows.push({ member: 'coping', name: 'C9', size: 'H25', count: shear.c9.length, length: null, note: shearNote('전단 좌 @250', shear.c9) });
rows.push({ member: 'coping', name: 'C10', size: 'H25', count: shear.c10.length, length: null, note: shearNote('전단 Level @300', shear.c10) });
rows.push({ member: 'coping', name: 'C11', size: 'H25', count: shear.c11.length, length: null, note: shearNote('전단 우 @250', shear.c11) });
const side = sideRows(41.288, 42.538);
rows.push({ member: 'coping', name: 'C12', size: 'H25', count: side.c12.length, length: null, note: `측면, 경사 하면에서 끊김, 일자 ${SIDE_LENGTHS.C12[0]}–${SIDE_LENGTHS.C12[4]}` });
rows.push({ member: 'coping', name: 'C13', size: 'H25', count: side.c13.length, length: SIDE_LENGTHS.C13, note: '측면, 끝면까지' });
@@ -66,8 +72,8 @@ export function rebarSummary(model: PierModel): { rows: RebarRow[]; warnings: Re
// 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: 'P1', size: 'S32', count: col.mainP1, length: null, note: '외측 r 875, 마디 4697.5 + 갈고리 525 / 3000 ×3 / 3147 (코핑 밖 마디는 기둥철근.md §3.2)' });
rows.push({ member: 'column', name: 'P2', size: 'S32', count: col.mainP2, length: null, note: '내측 r 843.2, 마디 4847.5 / 3000 ×3 / 2389' });
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: col.p3Length, note: `일반 구간 띠철근 @300, 겹침 ${col.lapP3} (추천안, Q-C6)` });
rows.push({ member: 'column', name: 'P5', size: 'H19', count: col.p5Count, length: col.p5Length, note: '단부 띠철근 @120, 커플러 1개' });
+14
View File
@@ -22,3 +22,17 @@ describe('C9·C10 하부 U 길이 (코핑철근.md §4.3)', () => {
expect(shearULength(11700, L)).toBeCloseTo(3522, 0);
});
});
import { capLength, PIECES_PER_POSITION } from '../src/core/rebar/coping';
import { rebarSummary } from '../src/core/rebar/summary';
import { buildPier } from '../src/core/geometry';
import { loadP1 } from './helpers';
describe('삿갓과 조각 수 (코핑철근.md §4.3, Q-K5 추천안)', () => {
it('cap length 1740 + 2·(h − 100) and the piece total 270 for C9 + C10 + C11', () => {
expect(capLength(4800, L)).toBeCloseTo(1740 + 2 * (2254.5 - 100), 0);
const rows = rebarSummary(buildPier(loadP1())).rows;
const pieces = ['C9', 'C10', 'C11'].reduce((sum, n) => sum + rows.find((r) => r.name === n)!.count * PIECES_PER_POSITION, 0);
expect(pieces).toBe(270);
});
});