feat(rebar): C15·C16 폭 간격을 2 × 주철근 기본간격에 연동
- stairBars가 pitch를 받는다 (기본 2 × 기본간격 = 250, P1 그대로) - 3D와 철근표가 같은 pitch를 쓴다 - 철근표 간격·실간격: 2 × 기본간격, 근거는 기본값/입력 Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
3cfbdf62f6
commit
72053be420
5 files changed
+23
-5
No files matched your search
@@ -229,12 +229,13 @@ export interface StepBar {
|
||||
|
||||
/**
|
||||
* C15 (거꾸로 된 U, on the highest segment) and C16 (L형, on segments 3 and 4), 11 bars each across the width (코핑철근.md §7).
|
||||
* Across: 137 from the cover line, then @250 (피복선 기준). Along: from each segment start + c to the next end − c.
|
||||
* Across: 137 from the cover line, then @pitch (피복선 기준). pitch = 2 × 주철근 기본간격 (승인 2026-10-26; 250 at P1).
|
||||
* Along: from each segment start + c to the next end − c.
|
||||
*/
|
||||
export function stairBars(L: number, B: number, topEl: number, m: Material = DEFAULT_MATERIAL): { c15: StepBar[]; c16: StepBar[] } {
|
||||
export function stairBars(L: number, B: number, topEl: number, m: Material = DEFAULT_MATERIAL, pitch = 2 * DEFAULT_COPING_REBAR.mainSpacing): { c15: StepBar[]; c16: StepBar[] } {
|
||||
const ld = stepDevLength(m);
|
||||
const c = COPING_REBAR.cover;
|
||||
const ns = Array.from({ length: 11 }, (_, k) => -B / 2 + c + 137 + 250 * k);
|
||||
const ns = Array.from({ length: 11 }, (_, k) => -B / 2 + c + 137 + pitch * k);
|
||||
const seg = STAIR_SEGMENTS;
|
||||
const top = (i: number) => topEl + seg[i].rise / 1000;
|
||||
const c15Z = top(3) - c / 1000;
|
||||
|
||||
@@ -134,6 +134,10 @@ export function linkedSpacing(name: string, model: PierModel): Pick<RebarRow, 's
|
||||
if (MAIN_BARS.includes(name)) {
|
||||
return { spacing: String(2 * c.mainSpacing), actual: String(c.mainSpacing), basis: basis(c.mainSpacing !== d.mainSpacing) };
|
||||
}
|
||||
if (name === 'C15' || name === 'C16') {
|
||||
// C15·C16 are on the same width pitch as the main bars (2 × 기본간격); 250 at P1.
|
||||
return { spacing: String(2 * c.mainSpacing), actual: String(2 * c.mainSpacing), basis: basis(c.mainSpacing !== d.mainSpacing) };
|
||||
}
|
||||
if (name === 'C9' || name === 'C11') return { spacing: String(c.spacingS), actual: String(c.spacingS), basis: basis(c.spacingS !== d.spacingS) };
|
||||
if (name === 'C10') return { spacing: String(c.spacingL), actual: String(c.spacingL), basis: basis(c.spacingL !== d.spacingL) };
|
||||
if (name === 'C12' || name === 'C13') return { spacing: String(c.sideSpacing), actual: String(c.sideSpacing), basis: basis(c.sideSpacing !== d.sideSpacing) };
|
||||
@@ -240,7 +244,7 @@ export function rebarSummary(
|
||||
const lineCount = (line: number) => c14.filter((b) => b.line === line).length;
|
||||
const omitted = c14.filter((b) => !b.legs).length;
|
||||
rows.push({ member: 'coping', name: 'C14', size: 'H19', count: c14.length, length: c14Length(model.copingB * 1000), note: `위 2 줄 ${lineCount(1)} · ${lineCount(2)}본씩, 아래 ${[3, 4, 5, 6].map(lineCount).join(' · ')} (합 ${c14.length}) · 연직 발 생략 ${omitted}개 (하면 밖)` });
|
||||
const stairs = stairBars(model.copingL * 1000, model.copingB * 1000, model.copingRefTop, mCoping);
|
||||
const stairs = stairBars(model.copingL * 1000, model.copingB * 1000, model.copingRefTop, mCoping, 2 * model.copingRebar.mainSpacing);
|
||||
rows.push({ member: 'coping', name: 'C15', size: 'H19', count: stairs.c15.length, length: stairs.c15[0].length, note: '계단부, 가장 높은 구간 (거꾸로 U)' });
|
||||
rows.push({ member: 'coping', name: 'C16', size: 'H19', count: stairs.c16.length, length: stairs.c16[0].length, note: `계단부, 3·4구간 (${Math.round(stairs.c16[0].length)} / ${Math.round(stairs.c16[stairs.c16.length - 1].length)})` });
|
||||
|
||||
|
||||
+1
-1
@@ -249,7 +249,7 @@ export function buildRebar3D(m: PierModel, common: Material = DEFAULT_MATERIAL,
|
||||
}
|
||||
}
|
||||
// C15 (거꾸로 된 U) and C16 (L형) on the stair (코핑철근.md §7): 11 bars each across the width.
|
||||
const stairs = stairBars(L * 1000, B * 1000, topEl, mCoping);
|
||||
const stairs = stairBars(L * 1000, B * 1000, topEl, mCoping, 2 * m.copingRebar.mainSpacing);
|
||||
for (const s of stairs.c15) {
|
||||
const n = mm(s.n);
|
||||
const ld = mm(s.leg);
|
||||
|
||||
@@ -40,12 +40,16 @@ describe('C1–C8 상·하면 주철근 (코핑철근.md §5, plan C3)', () => {
|
||||
expect([c1.spacing, c1.actual, c1.basis]).toEqual(['250', '125', 'default']);
|
||||
const c12 = base.find((r) => r.name === 'C12')!;
|
||||
expect(c12.basis).toBe('default');
|
||||
const c15 = base.find((r) => r.name === 'C15')!;
|
||||
expect([c15.spacing, c15.actual, c15.basis]).toEqual(['250', '250', 'default']);
|
||||
|
||||
const m = buildPier({ ...loadP1(), copingRebar: { mainSpacing: 140 }, blockRebar: { spacingS1: 130 } });
|
||||
const rows = rebarSummary(m).rows;
|
||||
const c8 = rows.find((r) => r.name === 'C8')!;
|
||||
expect([c8.spacing, c8.actual, c8.basis]).toEqual(['280', '140', 'input']);
|
||||
expect(rows.find((r) => r.name === 'C12')!.basis).toBe('default');
|
||||
const c16 = rows.find((r) => r.name === 'C16')!;
|
||||
expect([c16.spacing, c16.actual, c16.basis]).toEqual(['280', '280', 'input']);
|
||||
const s1 = rows.find((r) => r.name === 'S1')!;
|
||||
expect([s1.spacing, s1.actual, s1.basis]).toEqual(['130', '130', 'input']);
|
||||
});
|
||||
|
||||
@@ -65,3 +65,12 @@ describe('C14 연직 발 (코핑철근.md §8)', () => {
|
||||
expect(omitted).toEqual([[4, 1], [4, 11]]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('C15 간격 = 2 × 주철근 기본간격 (승인 2026-10-26)', () => {
|
||||
it('the default pitch is 250, and a larger pitch moves the 11 C15 bars apart', () => {
|
||||
const { c15 } = stairBars(L, B, m.copingRefTop);
|
||||
expect(c15[1].n - c15[0].n).toBe(250);
|
||||
const wider = stairBars(L, B, m.copingRefTop, undefined, 280).c15;
|
||||
expect(wider[1].n - wider[0].n).toBe(280);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user