feat(core): rebar for 2·3주형 — shear bars per column, column bars per column (plan)

- Coping §9: C10 at each column centre (@300, k_max as for one column), C9 / C11
  outside, and the gaps between columns filled @250 from both C10 groups with the
  remaining length shared evenly (추천안, Q-K2). One column gives the T형 result.
- Column bars and couplers repeat per column (P1 230 × 2 for 2주형, × 3 for 3주형).
- Footings: each footing's bars are summed per name; the longest length governs.
- C14 is kept as the T형 layout with an RB-M01 note (per-column rule open, Q-K11).
- Tests: counts for 2주형 and 3주형; T형 unchanged; too-close columns refused.
- Not yet: the ③ shear-segment table for multi columns (still single column), the
  C14 per column, and a drawing for multi columns. 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 12:20:49 +09:00
1 parent 8ac5d2973c
commit 13318e9393
3 files changed
+139 -19

No files matched your search

+41
View File
@@ -131,3 +131,44 @@ export function shearSegments(coping: number): { segment: string; from: number;
seg('우 경사', b.c11, 'C11', COPING_REBAR.spacingS),
];
}
/**
* Shear bars for a multi-column coping (코핑철근.md §9, 다주형 확장 원칙).
* C10: each column's centre, @300 out to the first position beyond its Level edge.
* C9 / C11: outward from the outermost C10 on each end, as for one column.
* Between columns: @250 in from both C10 groups, the remaining length shared evenly (추천안, Q-K2).
* With one column this is the same as shearBars.
*/
export function shearBarsMulti(coping: number, columns: number[]): ShearBars & { between: number[] } {
if (columns.length <= 1) {
const one = shearBars(coping, columns[0] ?? coping / 2);
return { ...one, between: [] };
}
const { spacingL, spacingS, levelWidth } = COPING_REBAR;
const kMax = Math.floor(levelWidth / 2 / spacingL) + 1;
const groups = columns.map((xc) =>
Array.from({ length: 2 * kMax + 1 }, (_, i) => Math.round(xc + (i - kMax) * spacingL)),
);
for (let i = 1; i < groups.length; i++) {
if (groups[i][0] <= groups[i - 1][groups[i - 1].length - 1]) {
throw new Error('기둥 간격이 좁아 C10 구간이 겹칩니다. 다주형 코핑 철근을 만들 수 없습니다.');
}
}
const c10 = groups.flat();
const left = groups[0][0];
const right = groups[groups.length - 1][groups[groups.length - 1].length - 1];
const n9 = Math.floor((left - COPING_END_GAP) / spacingS);
if (n9 < 0) throw new Error('RB-K01: C10 바깥 구간이 끝 여유보다 짧아 C9를 놓을 수 없습니다.');
const c9 = Array.from({ length: n9 }, (_, j) => Math.round(left - (n9 - j) * spacingS));
const c11 = Array.from({ length: n9 }, (_, j) => Math.round(right + (j + 1) * spacingS));
const between: number[] = [];
for (let i = 1; i < groups.length; i++) {
const a = groups[i - 1][groups[i - 1].length - 1];
const b = groups[i][0];
const gap = b - a;
const pitches = Math.floor(gap / spacingS);
for (let j = 1; j < pitches; j++) between.push(Math.round(a + (gap * j) / pitches));
}
const endGap = Math.min(left - c9[0], coping - c11[c11.length - 1]);
return { c10, c9, c11, between, endGap };
}