- Leg offsets (B1 +25.4, B3 +22.25, B5 +28.6, B7 +23.85) and B11 / B12 heights (550 / 950 / 1350; 569.1 / 969.1 / 1369.1). - Reproduction counts: W 7800 → B4 30 / B2 29; L 9350 → B8 36 / B6 35. - Variables: W 8000 with s 150 → 50 steps, e 150; W 12000 → 92 steps. - Splice cases: L 8700 → B2 11946 (no splice), L 12400 → B4 12200, W 8800 → B6 12046. - Not covered: the 배근도 H 2200 case for B10 (the document's count is unclear). Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
195 lines
7.2 KiB
TypeScript
195 lines
7.2 KiB
TypeScript
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: number = FOOTING_DEFAULTS.s, cSide: number = FOOTING_DEFAULTS.cSide, eMin: number = 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 },
|
||
];
|
||
}
|
||
|
||
/**
|
||
* B9 전단철근 (확대기초철근 (1).md §9). Wraps B5 (top outer) and B2·B4 (bottom outer), H16 @500 staggered.
|
||
* Plane positions and hooks are proposed rules (Q-B18, Q-B19).
|
||
*/
|
||
export function shearB9(L: number, W: number, H: number): { rows: number; perRow: number[]; count: number; length: number } {
|
||
const nW = grid(W).n; // 61
|
||
const nL = grid(L).n; // 79
|
||
const rowIndices: number[] = [];
|
||
for (let i = 1; i <= nW; i += 4) rowIndices.push(i);
|
||
// Even-numbered rows start at i_L = 1, odd-numbered rows at i_L = 3 (2s stagger).
|
||
const perRow = rowIndices.map((_, r) => {
|
||
const start = r % 2 === 0 ? 1 : 3;
|
||
return Math.floor((nL - start) / 4) + 1;
|
||
});
|
||
const count = perRow.reduce((a, b) => a + b, 0);
|
||
const lv = layers(H).B5 - layers(H).B24; // 1750
|
||
const lh = hookLength('stirrup135', d('H16'));
|
||
return { rows: rowIndices.length, perRow, count, length: lv + 2 * lh };
|
||
}
|
||
|
||
/** Leg offsets from the grid line (§5.3, §6.3): the B1/B3 and B5/B7 legs sit beside the outer leg. */
|
||
export function legOffsets(): { B1: number; B3: number; B5: number; B7: number } {
|
||
const dB2 = NOMINAL_DIAMETER.S25;
|
||
const dB1 = NOMINAL_DIAMETER.S25;
|
||
const dB3 = NOMINAL_DIAMETER.S19;
|
||
const dB6 = NOMINAL_DIAMETER.S29;
|
||
const dB5 = NOMINAL_DIAMETER.S29;
|
||
const dB7 = NOMINAL_DIAMETER.S19;
|
||
return {
|
||
B1: (dB2 + dB1) / 2,
|
||
B3: (dB2 + dB3) / 2,
|
||
B5: (dB6 + dB5) / 2,
|
||
B7: (dB6 + dB7) / 2,
|
||
};
|
||
}
|
||
|
||
/** B11/B12 heights (§8.1): B10 levels at 150 + k·s_v; the assembly levels are j = n, 2n, 3n (n = 2), and B12 sits d_B10 above B11. */
|
||
export function assemblyHeights(): { B11: number[]; B12: number[] } {
|
||
const { cBottom } = FOOTING_DEFAULTS;
|
||
const sV = FOOTING_DEFAULTS.sV;
|
||
const n = FOOTING_DEFAULTS.n;
|
||
const js = [n, 2 * n, 3 * n];
|
||
const B11 = js.map((j) => cBottom + j * sV);
|
||
const B12 = B11.map((z) => z + NOMINAL_DIAMETER.S19);
|
||
return { B11, B12 };
|
||
}
|