feat(rebar): add downward 90° hooks (135 mm) to P6 crossties in 3D rebar model
This commit is contained in:
1 parent
4aa8dbb3cb
commit
a2317caf6c
15 files changed
+740
-133
No files matched your search
+86
-33
@@ -18,11 +18,8 @@ export const FOOTING_DEFAULTS = {
|
||||
/** 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,
|
||||
/** 상단 최소 여유 e_top (B10 top level, §7.1). */
|
||||
eTop: 150,
|
||||
} as const;
|
||||
|
||||
export interface GridResult {
|
||||
@@ -47,6 +44,9 @@ export function grid(side: number, s: number = FOOTING_DEFAULTS.s, cSide: number
|
||||
|
||||
const d = (size: BarSize) => NOMINAL_DIAMETER[size];
|
||||
|
||||
/** Leg of B1·B3·B5·B7: 12·d_b on each end (proposed rule, spec §1.2 · Q-B5). */
|
||||
export const legLength = (size: BarSize) => 12 * d(size);
|
||||
|
||||
/** Layer heights (§4.2), mm from the 하면. H = footing height. */
|
||||
export interface Layers {
|
||||
B5: number;
|
||||
@@ -90,9 +90,9 @@ export function bottomBars(L: number, W: number, H: number): FootingBar[] {
|
||||
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: 'B1', size: 'S25', count: N2, length: l0 + 2 * legLength('S25') },
|
||||
{ name: 'B2', size: 'S25', count: N2, length: l0 + 2 * leg2 },
|
||||
{ name: 'B3', size: 'S19', count: N2, length: l0 + 2 * FOOTING_DEFAULTS.legB3 },
|
||||
{ name: 'B3', size: 'S19', count: N2, length: l0 + 2 * legLength('S19') },
|
||||
{ name: 'B4', size: 'S25', count: N4, length: l0 },
|
||||
];
|
||||
}
|
||||
@@ -107,28 +107,50 @@ export function crossBars(L: number, W: number, H: number): FootingBar[] {
|
||||
const z = layers(H);
|
||||
const leg6 = z.B5 - z.B68;
|
||||
return [
|
||||
{ name: 'B5', size: 'S29', count: N6, length: l0 + 2 * FOOTING_DEFAULTS.legB5 },
|
||||
{ name: 'B5', size: 'S29', count: N6, length: l0 + 2 * legLength('S29') },
|
||||
{ name: 'B6', size: 'S29', count: N6, length: l0 + 2 * leg6 },
|
||||
{ name: 'B7', size: 'S19', count: N6, length: l0 + 2 * FOOTING_DEFAULTS.legB7 },
|
||||
{ name: 'B7', size: 'S19', count: N6, length: l0 + 2 * legLength('S19') },
|
||||
{ name: 'B8', size: 'S29', count: N8, length: l0 },
|
||||
];
|
||||
}
|
||||
|
||||
/** B10 levels: m = floor((z_B5 − e_top − c_b)/s_v) (§7.1), so the count is m + 1 (9 for P1, H 2000). */
|
||||
export function b10Levels(H: number): number {
|
||||
const m = Math.floor((layers(H).B5 - FOOTING_DEFAULTS.eTop - FOOTING_DEFAULTS.cBottom) / FOOTING_DEFAULTS.sV);
|
||||
return m + 1;
|
||||
}
|
||||
|
||||
/** Depth of a side bar from the side face: c_s + (d_a + d_b)/2 (§7, §8.3). B10-1 hangs on B6, B10-2 on B2. */
|
||||
export const sideDepth = (dOuter: number, dB10: number) => FOOTING_DEFAULTS.cSide + (dOuter + dB10) / 2;
|
||||
|
||||
/** 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 (기본)
|
||||
export function sideBars(L: number, W: number, H: number): FootingBar[] {
|
||||
const depth1 = sideDepth(NOMINAL_DIAMETER.S29, NOMINAL_DIAMETER.S19); // B10-1: 123.85
|
||||
const depth2 = sideDepth(NOMINAL_DIAMETER.S25, NOMINAL_DIAMETER.S19); // B10-2: 122.25
|
||||
const levels = b10Levels(H);
|
||||
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')) },
|
||||
{ name: 'B10-2', size: 'S19', count: levels * 2, length: W - 2 * depth1 + 2 * hook },
|
||||
];
|
||||
}
|
||||
|
||||
/** Assembly levels j = n, 2n, … strictly inside the B10 levels, 0 < j < m (§8.1). */
|
||||
export function assemblyJs(H: number): number[] {
|
||||
const m = b10Levels(H) - 1;
|
||||
const js: number[] = [];
|
||||
for (let j = FOOTING_DEFAULTS.n; j < m; j += FOOTING_DEFAULTS.n) js.push(j);
|
||||
return js;
|
||||
}
|
||||
|
||||
/** Ends of B11 / B12 lie (d_B10 + d_assembly)/2 further inside than the B10 depth, so the two bars just touch (§8.3). */
|
||||
export function assemblyEndOffset(): number {
|
||||
return (d('S19') + d('S16')) / 2; // 17.5
|
||||
}
|
||||
|
||||
/** 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)
|
||||
export function assemblyBars(L: number, W: number, H: number): FootingBar[] {
|
||||
const levelsJ = assemblyJs(H);
|
||||
const perLevel = (n: number, startOdd: number, startEven: number) =>
|
||||
levelsJ.map((_, idx) => {
|
||||
const i0 = idx % 2 === 0 ? startOdd : startEven;
|
||||
@@ -139,31 +161,63 @@ export function assemblyBars(L: number, W: number): FootingBar[] {
|
||||
// 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'));
|
||||
const hook = Math.round(hookLength('main90', d('S16'))); // 246 mm, rounded as in the document (§8.3)
|
||||
const depth1 = sideDepth(NOMINAL_DIAMETER.S29, NOMINAL_DIAMETER.S19);
|
||||
const depth2 = sideDepth(NOMINAL_DIAMETER.S25, NOMINAL_DIAMETER.S19);
|
||||
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 },
|
||||
{ name: 'B11', size: 'S16', count: b11, length: W - 2 * (depth1 + assemblyEndOffset()) + 2 * hook },
|
||||
{ name: 'B12', size: 'S16', count: b12, length: L - 2 * (depth2 + assemblyEndOffset()) + 2 * hook },
|
||||
];
|
||||
}
|
||||
|
||||
/** Plane positions of the grid along one side, mm from the footing centre: x_i = −side/2 + c_s + e + i·s (§3.1). */
|
||||
export function gridPositions(side: number): number[] {
|
||||
const g = grid(side);
|
||||
return Array.from({ length: g.positions }, (_, i) => -side / 2 + FOOTING_DEFAULTS.cSide + g.e + i * FOOTING_DEFAULTS.s);
|
||||
}
|
||||
|
||||
/** B9 bar of the rule (§9.1, Q-B18): a vertical bar at (x, n), mm from the footing centre. */
|
||||
export interface B9Bar {
|
||||
x: number;
|
||||
n: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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).
|
||||
* B9 positions (확대기초철근 (1).md §9.1, rule applied): rows at W index 1, 5, 9 … (step 4 on the grid); in row r the L index
|
||||
* starts at 1 (even r) or 3 (odd r) and steps by 4. A bar is left out when it falls in a column zone: its centre is closer
|
||||
* than the column radius plus half a bar to a column axis (Q-B20, applied: the 기둥 구역 is removed).
|
||||
*/
|
||||
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
|
||||
export function b9Bars(L: number, W: number, columnX: number[], columnD: number = 2000): { rows: number; perRow: number[]; bars: B9Bar[] } {
|
||||
const xs = gridPositions(L);
|
||||
const ns = gridPositions(W);
|
||||
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) => {
|
||||
for (let i = 1; i < ns.length; i += 4) rowIndices.push(i);
|
||||
const halfBar = NOMINAL_DIAMETER.H16 / 2;
|
||||
const bars: B9Bar[] = [];
|
||||
const perRow = rowIndices.map((iW, r) => {
|
||||
const start = r % 2 === 0 ? 1 : 3;
|
||||
return Math.floor((nL - start) / 4) + 1;
|
||||
let kept = 0;
|
||||
for (let iL = start; iL < xs.length; iL += 4) {
|
||||
const x = xs[iL];
|
||||
const n = ns[iW];
|
||||
if (columnX.some((cx) => Math.hypot(x - cx, n) < columnD / 2 + halfBar)) continue;
|
||||
bars.push({ x, n });
|
||||
kept++;
|
||||
}
|
||||
return kept;
|
||||
});
|
||||
const count = perRow.reduce((a, b) => a + b, 0);
|
||||
return { rows: rowIndices.length, perRow, bars };
|
||||
}
|
||||
|
||||
/**
|
||||
* B9 전단철근 (확대기초철근 (1).md §9). Vertical bars from the B2·B4 level to the B5 level, H16, with 135° hooks at both ends.
|
||||
* Length = l_v + 2·l_h (l_v = z_B5 − z_B24). The hook tail (6·d) turns toward the footing centre (Q-B19, applied).
|
||||
*/
|
||||
export function shearB9(L: number, W: number, H: number, columnX: number[] = [], columnD: number = 2000): { rows: number; perRow: number[]; count: number; length: number; bars: B9Bar[] } {
|
||||
const { rows, perRow, bars } = b9Bars(L, W, columnX, columnD);
|
||||
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 };
|
||||
return { rows, perRow, count: bars.length, length: lv + 2 * lh, bars };
|
||||
}
|
||||
|
||||
/** Leg offsets from the grid line (§5.3, §6.3): the B1/B3 and B5/B7 legs sit beside the outer leg. */
|
||||
@@ -183,11 +237,10 @@ export function legOffsets(): { B1: number; B3: number; B5: number; B7: number }
|
||||
}
|
||||
|
||||
/** 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[] } {
|
||||
export function assemblyHeights(H: number): { 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 js = assemblyJs(H);
|
||||
const B11 = js.map((j) => cBottom + j * sV);
|
||||
const B12 = B11.map((z) => z + NOMINAL_DIAMETER.S19);
|
||||
return { B11, B12 };
|
||||
|
||||
Reference in new issue
Block a user