fix(rebar): 확대기초 철근 — 구간별 3D 위치, 기둥 소속, 길이별 행, 2조각 수량
- 3D: 확대기초 철근을 늘 구간 0에 그려, 꺾인 교각의 구간 1 기초(산외교 P11 ③)는 철근이 없고 구간 0 기초에 겹쳐 그려졌다 - 기초에 속한 기둥을 같은 구간 안에서만 찾는다 (B9 기둥 구역이 다른 구간 기둥으로 잘못 빠지던 것) - 길이가 다른 기초의 철근을 가장 긴 길이 하나로 합치지 않고 길이별 조각으로 둔다 - 정척 초과 2조각 이음 행이 철근 한 개당 한 조각만 중량에 넣던 것을 두 조각으로 (P1 B6 31개 → 62조각) Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
33aa2d9a61
commit
ed84761449
3 files changed
+71
-21
No files matched your search
+22
-15
@@ -391,27 +391,34 @@ export function rebarSummary(
|
||||
if (model.footings.length > 0) {
|
||||
// Each footing (분리 or 일체) gives the same bar set. Several footings add their counts per bar name;
|
||||
// the length is the longest of them (the largest footing governs the bar).
|
||||
const agg = new Map<string, FootingBar>();
|
||||
// Per footing (2026-11-10): the columns of its own stretch only, and every bar length kept (a bent pier has footings
|
||||
// of different lengths; the longest no longer stands for all).
|
||||
const byName = new Map<string, { first: FootingBar; lengths: Map<number, number> }>();
|
||||
for (const f of model.footings) {
|
||||
// Columns on this footing, as x mm from the footing centre (for the B9 column-zone rule).
|
||||
const columnX = model.columns.filter((c) => Math.abs(c.s - f.s) <= f.length / 2).map((c) => (c.s - f.s) * 1000);
|
||||
const columnX = model.columns.filter((c) => c.k === f.k && Math.abs(c.s - f.s) <= f.length / 2).map((c) => (c.s - f.s) * 1000);
|
||||
for (const b of footingBarList(f.length * 1000, f.width * 1000, (f.top - f.bottom) * 1000, columnX, model.footingRebar)) {
|
||||
const cur = agg.get(b.name);
|
||||
if (cur) {
|
||||
cur.count += b.count;
|
||||
cur.length = Math.max(cur.length, b.length);
|
||||
} else {
|
||||
agg.set(b.name, { ...b });
|
||||
}
|
||||
const cur = byName.get(b.name) ?? { first: b, lengths: new Map<number, number>() };
|
||||
cur.lengths.set(b.length, (cur.lengths.get(b.length) ?? 0) + b.count);
|
||||
byName.set(b.name, cur);
|
||||
}
|
||||
}
|
||||
for (const b of agg.values()) {
|
||||
const split = splitPieces(b.length, 25.4, fyOf(mFooting, b.size), mFooting.fck, STANDARD_BAR);
|
||||
if (split && b.length > STANDARD_BAR && b.name !== 'B9') {
|
||||
rows.push({ member: 'footing', name: b.name, size: b.size, count: b.count, length: split.pieceLength, note: `${b.note}, 2조각 이음 (추천안, 겹침 ${Math.round(split.lap)})` });
|
||||
warnings.push({ code: 'RB-F08', message: `${b.name} 길이 ${Math.round(b.length)} mm > 정척 ${STANDARD_BAR} mm: 2조각 이음을 추천안으로 적용 (Q-B6).`, target: 'footing', bar: b.name });
|
||||
for (const { first: b, lengths } of byName.values()) {
|
||||
// Over 정척: two pieces lapped (추천안, Q-B6); both pieces count (the row used to weigh only one per bar).
|
||||
const pieces: { length: number; count: number }[] = [];
|
||||
let lap: number | null = null;
|
||||
for (const [length, count] of lengths) {
|
||||
const split = b.name === 'B9' ? null : splitPieces(length, 25.4, fyOf(mFooting, b.size), mFooting.fck, STANDARD_BAR);
|
||||
if (split) { pieces.push({ length: split.pieceLength, count: 2 * count }); lap = split.lap; } else pieces.push({ length, count });
|
||||
}
|
||||
const count = [...lengths.values()].reduce((sum, n) => sum + n, 0);
|
||||
const longest = Math.max(...lengths.keys());
|
||||
if (lap !== null) {
|
||||
rows.push({ member: 'footing', name: b.name, size: b.size, count, length: pieces.length === 1 ? pieces[0].length : null, pieces,
|
||||
note: `${b.note}, 2조각 이음 (추천안, 겹침 ${Math.round(lap)})` });
|
||||
warnings.push({ code: 'RB-F08', message: `${b.name} 길이 ${Math.round(longest)} mm > 정척 ${STANDARD_BAR} mm: 2조각 이음을 추천안으로 적용 (Q-B6).`, target: 'footing', bar: b.name });
|
||||
} else {
|
||||
rows.push({ member: 'footing', name: b.name, size: b.size, count: b.count, length: b.length, note: b.note });
|
||||
rows.push({ member: 'footing', name: b.name, size: b.size, count, length: pieces.length === 1 ? pieces[0].length : null, ...(pieces.length > 1 ? { pieces } : {}), note: b.note });
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
+6
-6
@@ -452,7 +452,7 @@ export function buildRebar3D(m: PierModel, common: Material = DEFAULT_MATERIAL,
|
||||
const off = legOffsets();
|
||||
// One name, several cylinders: each segment of the path is one bar piece.
|
||||
const path = (name: string, pts: [number, number, number][], dMm: number) => {
|
||||
addPath(name, 0, pts, dMm, COLOR.footing);
|
||||
addPath(name, f.k, pts, dMm, COLOR.footing);
|
||||
};
|
||||
// B1–B4: along s, at W position n. legTo (absolute EL, m) is where both ends turn up or down (§5.1); undefined = straight.
|
||||
const along = (name: string, n: number, y: number, legTo: number | undefined, dMm: number) => {
|
||||
@@ -492,21 +492,21 @@ export function buildRebar3D(m: PierModel, common: Material = DEFAULT_MATERIAL,
|
||||
// Each hook tail (6·d) turns toward the footing centre along the pier axis (Q-B19).
|
||||
const dB9 = NOMINAL_DIAMETER.H16;
|
||||
const tail9 = (6 * dB9) / 1000;
|
||||
const colX = m.columns.filter((c) => Math.abs(c.s - f.s) <= Lf / 2).map((c) => (c.s - f.s) * 1000);
|
||||
const colX = m.columns.filter((c) => c.k === f.k && Math.abs(c.s - f.s) <= Lf / 2).map((c) => (c.s - f.s) * 1000);
|
||||
const yB9Bot = bottom + mm(z.B24);
|
||||
const yB9Top = bottom + mm(z.B5);
|
||||
for (const b of b9Bars(Lf * 1000, Wf * 1000, colX, 2000, fs).bars) {
|
||||
const x = mm(b.x);
|
||||
const n = mm(b.n);
|
||||
const tailDir = x >= 0 ? -1 : 1;
|
||||
addBar('B9', 0, [f.s + x, yB9Bot, n], [f.s + x, yB9Top, n], dB9, COLOR.footing);
|
||||
addBar('B9', 0, [f.s + x, yB9Top, n], [f.s + x + tailDir * tail9, yB9Top, n], dB9, COLOR.footing);
|
||||
addBar('B9', 0, [f.s + x, yB9Bot, n], [f.s + x + tailDir * tail9, yB9Bot, n], dB9, COLOR.footing);
|
||||
addBar('B9', f.k, [f.s + x, yB9Bot, n], [f.s + x, yB9Top, n], dB9, COLOR.footing);
|
||||
addBar('B9', f.k, [f.s + x, yB9Top, n], [f.s + x + tailDir * tail9, yB9Top, n], dB9, COLOR.footing);
|
||||
addBar('B9', f.k, [f.s + x, yB9Bot, n], [f.s + x + tailDir * tail9, yB9Bot, n], dB9, COLOR.footing);
|
||||
}
|
||||
|
||||
// B10-1 / B10-2 (§7) at each B10 level, B11 / B12 (§8) between them. Ends turn 90° inward (B10) or down (B11, B12).
|
||||
const polyline = (name: string, pts: [number, number, number][], dMm: number) => {
|
||||
addPath(name, 0, pts, dMm, COLOR.footing);
|
||||
addPath(name, f.k, pts, dMm, COLOR.footing);
|
||||
};
|
||||
const hookB10 = mm(hookLength('main90', NOMINAL_DIAMETER.S19)); // 296
|
||||
const hookAsm = mm(Math.round(hookLength('main90', NOMINAL_DIAMETER.S16))); // 246
|
||||
|
||||
Reference in new issue
Block a user