feat(rebar): B1–B4와 B5–B8 방향 교환 (B1–B4는 W 방향, B5–B8은 L 방향)

- 재료표(B5–B8 9150 = 9350 − 2c, B1–B4 7600 = 7800 − 2c)와 같은 방향 배정으로 맞춤
- 격자 키를 물리 방향으로 정리: sL = L 방향 간격, sW = W 방향 간격 (기존 sAxis → sL, sPerp → sW)
- B1–B4: L 격자로 개수, 길이 W − 2c. B5–B8: W 격자로 개수, 길이 L − 2c
- B9: 열(L)은 sL, 행(W)은 sW 격자 (물리 격자 일치), 개수 불변
- B11은 L 방향 간격(sL), B12는 W 방향 간격(sW)
- 3D 확대기초 철근과 단면 그림의 역할을 교환 (B1–B4 선, B5–B8 점)
- 철근표 간격과 규칙 값, 설정 라벨을 방향 기준으로 수정
- 테스트 기대값 갱신 (B1–B4 40, B5–B8 31, B6 13646 분할 경고)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
ypshimandClaude Haiku 5.5 committed 2026-10-27 09:36:20 +09:00
1 parent f2fa48913b
commit 752de2fd9d
12 files changed
+160 -167

No files matched your search

+23 -20
View File
@@ -384,10 +384,11 @@ export function buildRebar3D(m: PierModel, common: Material = DEFAULT_MATERIAL,
// 확대기초 입력 (승인 2026-10-26): the grid, covers and layer heights come from the model's footing settings.
const fs = m.footingRebar;
const z = layers(Hf, fs);
const gW = grid(Wf * 1000, fs);
const gL = grid(Lf * 1000, fs, 'sPerp');
const posW = (j: number) => -Wf / 2 + mm(fs.cSide + gW.e + j * fs.sAxis);
const posL = (i: number) => -Lf / 2 + mm(fs.cSide + gL.e + i * fs.sPerp);
// 방향 교환 (승인 2026-10-26): B1–B4 run along W and are spaced along L (sL); B5–B8 run along L and are spaced along W (sW).
const gW = grid(Wf * 1000, fs, 'sW');
const gL = grid(Lf * 1000, fs, 'sL');
const posW = (j: number) => -Wf / 2 + mm(fs.cSide + gW.e + j * fs.sW);
const posL = (i: number) => -Lf / 2 + mm(fs.cSide + gL.e + i * fs.sL);
const sA = -Lf / 2 + 0.1;
const sB = Lf / 2 - 0.1;
const nA = -Wf / 2 + 0.1;
@@ -408,26 +409,28 @@ export function buildRebar3D(m: PierModel, common: Material = DEFAULT_MATERIAL,
const at = (t: number, h: number): [number, number, number] => [f.s + s, h, t];
path(name, legTo === undefined ? [at(nA, y), at(nB, y)] : [at(nA, legTo), at(nA, y), at(nB, y), at(nB, legTo)], dMm);
};
for (let j = 0; j <= gW.n; j++) {
const n = posW(j);
if (j % 2 === 1) {
// B1–B4 run along W (at each L position s): odd positions carry B1, B2, B3, even carry B4 (same parity rule as bottomBars).
for (let i = 0; i <= gL.n; i++) {
const sPos = posL(i);
if (i % 2 === 1) {
// B1 ⊓ down, B2 ⊔ up to the B1 height, B3 ⊔ up. B1·B3 sit beside the B2 leg (+25.4 / +22.25, §5.3).
along('B1', n + mm(off.B1), bottom + mm(z.B1), bottom + mm(z.B1) - mm(legLength('S25')), NOMINAL_DIAMETER.S25);
along('B2', n, bottom + mm(z.B24), bottom + mm(z.B1), NOMINAL_DIAMETER.S25);
along('B3', n + mm(off.B3), bottom + mm(z.B3), bottom + mm(z.B3) + mm(legLength('S19')), NOMINAL_DIAMETER.S19);
across('B1', sPos + mm(off.B1), bottom + mm(z.B1), bottom + mm(z.B1) - mm(legLength('S25')), NOMINAL_DIAMETER.S25);
across('B2', sPos, bottom + mm(z.B24), bottom + mm(z.B1), NOMINAL_DIAMETER.S25);
across('B3', sPos + mm(off.B3), bottom + mm(z.B3), bottom + mm(z.B3) + mm(legLength('S19')), NOMINAL_DIAMETER.S19);
} else {
along('B4', n, bottom + mm(z.B24), undefined, NOMINAL_DIAMETER.S25);
across('B4', sPos, bottom + mm(z.B24), undefined, NOMINAL_DIAMETER.S25);
}
}
for (let i = 0; i <= gL.n; i++) {
const s = posL(i);
if (i % 2 === 1) {
// B5–B8 run along L (at each W position n): odd positions carry B5, B6, B7, even carry B8.
for (let j = 0; j <= gW.n; j++) {
const nPos = posW(j);
if (j % 2 === 1) {
// B5 ⊓ down, B6 ⊔ up to the B5 height, B7 ⊔ up. B5·B7 sit beside the B6 leg (+28.6 / +23.85, §6.3).
across('B5', s + mm(off.B5), bottom + mm(z.B5), bottom + mm(z.B5) - mm(legLength('S29')), NOMINAL_DIAMETER.S29);
across('B6', s, bottom + mm(z.B68), bottom + mm(z.B5), NOMINAL_DIAMETER.S29);
across('B7', s + mm(off.B7), bottom + mm(z.B7), bottom + mm(z.B7) + mm(legLength('S19')), NOMINAL_DIAMETER.S19);
along('B5', nPos + mm(off.B5), bottom + mm(z.B5), bottom + mm(z.B5) - mm(legLength('S29')), NOMINAL_DIAMETER.S29);
along('B6', nPos, bottom + mm(z.B68), bottom + mm(z.B5), NOMINAL_DIAMETER.S29);
along('B7', nPos + mm(off.B7), bottom + mm(z.B7), bottom + mm(z.B7) + mm(legLength('S19')), NOMINAL_DIAMETER.S19);
} else {
across('B8', s, bottom + mm(z.B68), undefined, NOMINAL_DIAMETER.S29);
along('B8', nPos, bottom + mm(z.B68), undefined, NOMINAL_DIAMETER.S29);
}
}
// B9 (확대기초철근 (1).md §9, rule applied): vertical H16 bars on the grid, outside the column zones, with 135° hooks.
@@ -472,8 +475,8 @@ export function buildRebar3D(m: PierModel, common: Material = DEFAULT_MATERIAL,
}
}
// B11 (across W, spread along L) and B12 (along L, spread across W) at the assembly levels, 4s apart, 2s stagger per level.
const xsL = gridPositions(Lf * 1000, fs, 'sPerp');
const ysW = gridPositions(Wf * 1000, fs, 'sAxis');
const xsL = gridPositions(Lf * 1000, fs, 'sL');
const ysW = gridPositions(Wf * 1000, fs, 'sW');
const dAsm = assemblyEndOffset();
const nAsm = Wf / 2 - mm(d1 + dAsm);
const sAsm = Lf / 2 - mm(d2 + dAsm);