feat(core,view): footing rebar B1–B12 (plan C5) and the ③ rebar screen v1
- Footing (확대기초철근 (1).md): grid counts from W and L, layer heights, B1–B4 and B5–B8 counts and lengths (B2 13646, B6 11396), B10-1/B10-2, B11 (60) and B12 (47) with their lengths. B9 is not computed yet. - rebarSummary: one 철근표 per pier from the model (bearing, coping, column, footing), with alerts: RB-F08 (B2 needs a splice, Q-B6), RB-F09 (B9 not computed). - ③ screen v1: stage nav button, member tabs (받침블럭 · 코핑 · 기둥 · 확대기초), rebar table with 번호 · 규격 · 개수 · 길이 · 비고, alert list, and the open questions (Q-B5, Q-B6, Q-C9). Drawings and the 강조 연동 are not in v1. - Tests: footing values from the document; P1 summary totals; warnings. - Not verified in a browser. Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
a403ab9641
commit
3af8729e9f
7 files changed
+464
-3
No files matched your search
@@ -0,0 +1,147 @@
|
||||
import { hookLength, NOMINAL_DIAMETER, type BarSize } from './common';
|
||||
|
||||
/**
|
||||
* 확대기초 철근 B1–B8, B10–B12 (plan C5). Source: RAG/확대기초철근 (1).md, 2026-10-22 최종 정리.
|
||||
* B9 (전단철근) is not computed yet. Lengths in mm, heights in mm from the 확대기초 하면.
|
||||
*/
|
||||
export const FOOTING_DEFAULTS = {
|
||||
/** 피복 상면 / 측면 / 하면 (최외측 철근 중심까지). */
|
||||
cTop: 100,
|
||||
cSide: 100,
|
||||
cBottom: 150,
|
||||
/** 첫 철근 최소 여유. */
|
||||
eMin: 150,
|
||||
/** 격자 실간격 s. */
|
||||
s: 125,
|
||||
/** 하면 1단과 2단의 간격 Δ_2. */
|
||||
delta2: 100,
|
||||
/** B10 높이 간격 s_v and 조립 단 배수 n. */
|
||||
sV: 200,
|
||||
n: 2,
|
||||
/** B1·B3 leg and B5·B7 leg (proposed values; Q-B5 open). */
|
||||
legB1: 300,
|
||||
legB3: 230,
|
||||
legB5: 343,
|
||||
legB7: 230,
|
||||
} as const;
|
||||
|
||||
export interface GridResult {
|
||||
/** 격자 칸 수 n = floor((A − 2·e_min)/s); 위치 수 = n + 1. */
|
||||
n: number;
|
||||
/** 격자 길이 G = n·s. */
|
||||
G: number;
|
||||
/** 양끝 여유 e = (A − G)/2. */
|
||||
e: number;
|
||||
/** 위치 수 n + 1. */
|
||||
positions: number;
|
||||
}
|
||||
|
||||
/** Grid along one side of the footing (§3.1). side = W for B1–B4, L for B5–B8. */
|
||||
export function grid(side: number, s = FOOTING_DEFAULTS.s, cSide = FOOTING_DEFAULTS.cSide, eMin = FOOTING_DEFAULTS.eMin): GridResult {
|
||||
const A = side - 2 * cSide;
|
||||
const n = Math.floor((A - 2 * eMin) / s);
|
||||
const G = n * s;
|
||||
const e = (A - G) / 2;
|
||||
return { n, G, e, positions: n + 1 };
|
||||
}
|
||||
|
||||
const d = (size: BarSize) => NOMINAL_DIAMETER[size];
|
||||
|
||||
/** Layer heights (§4.2), mm from the 하면. H = footing height. */
|
||||
export interface Layers {
|
||||
B5: number;
|
||||
B1: number;
|
||||
B24: number;
|
||||
B68: number;
|
||||
B3: number;
|
||||
B7: number;
|
||||
}
|
||||
|
||||
export function layers(H: number): Layers {
|
||||
const { cTop, cBottom, delta2 } = FOOTING_DEFAULTS;
|
||||
const zB5 = H - cTop;
|
||||
const zB1 = zB5 - (d('S29') + d('S25')) / 2;
|
||||
const zB24 = cBottom;
|
||||
const zB68 = cBottom + (d('S25') + d('S29')) / 2;
|
||||
return { B5: zB5, B1: zB1, B24: zB24, B68: zB68, B3: zB24 + delta2, B7: zB68 + delta2 };
|
||||
}
|
||||
|
||||
/** Lengths of the B1–B4 family along the length L (§5.2). */
|
||||
export function legB2(H: number): number {
|
||||
const z = layers(H);
|
||||
return z.B1 - z.B24; // 1723 at H 2000
|
||||
}
|
||||
|
||||
export interface FootingBar {
|
||||
name: 'B1' | 'B2' | 'B3' | 'B4' | 'B5' | 'B6' | 'B7' | 'B8' | 'B10-1' | 'B10-2' | 'B11' | 'B12';
|
||||
size: BarSize;
|
||||
/** Bars in all (over the footing). */
|
||||
count: number;
|
||||
/** Length of one bar, mm (straight part + legs). */
|
||||
length: number;
|
||||
}
|
||||
|
||||
/** B1–B4 (§5): the grid along W, with lengths from L. */
|
||||
export function bottomBars(L: number, W: number, H: number): FootingBar[] {
|
||||
const g = grid(W);
|
||||
const n = g.positions;
|
||||
const N4 = Math.ceil(n / 2); // B4 at even i
|
||||
const N2 = Math.floor(n / 2); // B2 at odd i
|
||||
const l0 = L - 2 * FOOTING_DEFAULTS.cSide;
|
||||
const leg2 = legB2(H);
|
||||
return [
|
||||
{ name: 'B1', size: 'S25', count: N2, length: l0 + 2 * FOOTING_DEFAULTS.legB1 },
|
||||
{ name: 'B2', size: 'S25', count: N2, length: l0 + 2 * leg2 },
|
||||
{ name: 'B3', size: 'S19', count: N2, length: l0 + 2 * FOOTING_DEFAULTS.legB3 },
|
||||
{ name: 'B4', size: 'S25', count: N4, length: l0 },
|
||||
];
|
||||
}
|
||||
|
||||
/** B5–B8 (§6): the grid along L, with lengths from W. */
|
||||
export function crossBars(L: number, W: number, H: number): FootingBar[] {
|
||||
const g = grid(L);
|
||||
const n = g.positions;
|
||||
const N8 = Math.ceil(n / 2); // B8 at even i
|
||||
const N6 = Math.floor(n / 2); // B6, B5, B7 at odd i
|
||||
const l0 = W - 2 * FOOTING_DEFAULTS.cSide;
|
||||
const z = layers(H);
|
||||
const leg6 = z.B5 - z.B68;
|
||||
return [
|
||||
{ name: 'B5', size: 'S29', count: N6, length: l0 + 2 * FOOTING_DEFAULTS.legB5 },
|
||||
{ name: 'B6', size: 'S29', count: N6, length: l0 + 2 * leg6 },
|
||||
{ name: 'B7', size: 'S19', count: N6, length: l0 + 2 * FOOTING_DEFAULTS.legB7 },
|
||||
{ name: 'B8', size: 'S29', count: N8, length: l0 },
|
||||
];
|
||||
}
|
||||
|
||||
/** B10-1 (on W sides) and B10-2 (on L sides): m + 1 levels at s_v, two faces each (§7). */
|
||||
export function sideBars(L: number, W: number): FootingBar[] {
|
||||
const depth1 = 123.85; // B10-1 depth from the side
|
||||
const depth2 = 122.25; // B10-2 depth from the side
|
||||
const levels = 9; // 8 @ 200 (기본)
|
||||
const hook = hookLength('main90', d('S19'));
|
||||
return [
|
||||
{ name: 'B10-1', size: 'S19', count: levels * 2, length: L - 2 * depth2 + 2 * hook },
|
||||
{ name: 'B10-2', size: 'S19', count: levels * 2, length: W - 2 * depth1 + 2 * hookLength('main90', d('S19')) },
|
||||
];
|
||||
}
|
||||
|
||||
/** B11 (along W, between the B10-2 levels) and B12 (along L), 4s apart with a 2s stagger per level (§8). */
|
||||
export function assemblyBars(L: number, W: number): FootingBar[] {
|
||||
const levelsJ = [2, 4, 6]; // j = n, 2n, 3n … inside the B10 levels (n = 2)
|
||||
const perLevel = (n: number, startOdd: number, startEven: number) =>
|
||||
levelsJ.map((_, idx) => {
|
||||
const i0 = idx % 2 === 0 ? startOdd : startEven;
|
||||
return Math.floor((n - i0) / 4) + 1;
|
||||
});
|
||||
const nW = grid(W).positions - 1; // 61
|
||||
const nL = grid(L).positions - 1; // 79
|
||||
// B11 is spread along L (n = 79) and B12 along W (n = 61); each level has its own count.
|
||||
const b11 = perLevel(nL, 0, 2).reduce((a, b) => a + b, 0);
|
||||
const b12 = perLevel(nW, 0, 2).reduce((a, b) => a + b, 0);
|
||||
const hook = hookLength('main90', d('S16'));
|
||||
return [
|
||||
{ name: 'B11', size: 'S16', count: b11, length: W - 2 * 141.35 + 2 * hook },
|
||||
{ name: 'B12', size: 'S16', count: b12, length: L - 2 * 139.75 + 2 * hook },
|
||||
];
|
||||
}
|
||||
Reference in new issue
Block a user