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:
ypshimandClaude Haiku 5.5 committed 2026-10-26 16:04:31 +09:00
1 parent 3cfbdf62f6
commit 72053be420
5 files changed
+23 -5

No files matched your search

+4 -3
View File
@@ -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;
+5 -1
View File
@@ -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
View File
@@ -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);