From 1c6194cd482ec36f6f286cd19fb93af62ca9cb73 Mon Sep 17 00:00:00 2001 From: ypshim Date: Thu, 22 Oct 2026 11:38:28 +0900 Subject: [PATCH] =?UTF-8?q?feat(core):=20cap=20bars=20of=20C9=E2=80=93C11?= =?UTF-8?q?=20and=20piece=20count=20(=EC=B6=94=EC=B2=9C=EC=95=88=20for=20Q?= =?UTF-8?q?-K5)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- src/core/rebar/coping.ts | 15 +++++++++++++++ src/core/rebar/summary.ts | 18 ++++++++++++------ tests/rebar-coping-lengths.test.ts | 14 ++++++++++++++ 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/src/core/rebar/coping.ts b/src/core/rebar/coping.ts index b4e523d..2ab3841 100644 --- a/src/core/rebar/coping.ts +++ b/src/core/rebar/coping.ts @@ -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; diff --git a/src/core/rebar/summary.ts b/src/core/rebar/summary.ts index e9f5b18..026f5b1 100644 --- a/src/core/rebar/summary.ts +++ b/src/core/rebar/summary.ts @@ -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개' }); diff --git a/tests/rebar-coping-lengths.test.ts b/tests/rebar-coping-lengths.test.ts index 6ac7265..f7271fe 100644 --- a/tests/rebar-coping-lengths.test.ts +++ b/tests/rebar-coping-lengths.test.ts @@ -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); + }); +});