feat(core): coping main bars C1–C8 (plan C3) and column rebar C4
- Nominal bar diameters (H29 28.6, S32 31.8, …) as used by the documents. With them, C7/C8 l_s = 1.3·l_d(28.6, fck 27) = 1717.6, which is the document's 1717. - C1–C8 (코핑철근.md §5): width layout 127 · 110.5 · 21@125 · 110.5 · 127 with 24 bars (12 + 12); heights 43.284 / 43.227 / 43.170; top bar lengths 12744 / 12629.6 / 12515.2; bottom pieces ≈ 7448. - C4 (기둥철근.md): P1 r 875 and P2 r 843.2; couplers P1 +3/6/9/12 m, P2 +150; 230 + 230 main pieces and 368 couplers; tie radius 900.45; P3 38 at @300 from 2.340; P5 19 at @120; P4 8 at @120 from −0.060; P6 8 levels × 4 = 32, length ≈ 2071. - Not yet: C4 interference checks (P4 vs B11, Q-C9), bar lengths of P3/P5/P4 and coupler shapes, the coping/column drawing checks, and the ③ screen. Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
b962cf1a1c
commit
a403ab9641
5 files changed
+325
No files matched your search
@@ -0,0 +1,123 @@
|
||||
import { developmentLength, hookLength, NOMINAL_DIAMETER } from './common';
|
||||
|
||||
/**
|
||||
* 기둥 철근 C4 (plan C4). Source: RAG/기둥철근 (1).md, 2026-10-22 최종 정리. Type-1 원형 중실 기둥.
|
||||
* Lengths in mm, heights in mm from the 확대기초 상면 (up +).
|
||||
*/
|
||||
export interface ColumnInput {
|
||||
/** 기둥 지름 D. */
|
||||
D: number;
|
||||
/** 기둥 높이 H_c (확대기초 상면 ~ 코핑 Level 하면). */
|
||||
Hc: number;
|
||||
/** 기둥 중심 위치의 코핑 높이 h_cop. */
|
||||
hcop: number;
|
||||
/** 기둥 면 ~ P1 중심 피복 c. */
|
||||
c: number;
|
||||
/** P1 위 끝의 코핑 상면 아래 깊이 e_P1. */
|
||||
eP1: number;
|
||||
/** 띠철근 구간 위 끝의 코핑 상면 아래 깊이 e_top. */
|
||||
eTop: number;
|
||||
/** 확대기초 깊이 H_f (for P4). */
|
||||
Hf: number;
|
||||
/** 주철근 원주 등분 수 n_div. */
|
||||
nDiv: number;
|
||||
/** 주철근 커플러 간격 (확대기초 상면부터). */
|
||||
ctcCoupler: number;
|
||||
/** P2 커플러를 P1보다 올리는 높이. */
|
||||
dzCp2: number;
|
||||
ctcP3: number;
|
||||
ctcP5: number;
|
||||
ctcP4: number;
|
||||
/** P4 구간 깊이 비율 r_P4. */
|
||||
rP4: number;
|
||||
ctcP6: number;
|
||||
}
|
||||
|
||||
/** 예제 운곡교 P1 (기둥철근.md §1.2 기본값). */
|
||||
export const COLUMN_P1: ColumnInput = {
|
||||
D: 2000,
|
||||
Hc: 12703,
|
||||
hcop: 2644,
|
||||
c: 125,
|
||||
eP1: 200,
|
||||
eTop: 1623,
|
||||
Hf: 2000,
|
||||
nDiv: 46,
|
||||
ctcCoupler: 3000,
|
||||
dzCp2: 150,
|
||||
ctcP3: 300,
|
||||
ctcP5: 120,
|
||||
ctcP4: 120,
|
||||
rP4: 0.5,
|
||||
ctcP6: 1800,
|
||||
};
|
||||
|
||||
const dS32 = NOMINAL_DIAMETER.S32;
|
||||
const dH19 = NOMINAL_DIAMETER.H19;
|
||||
const dH16 = NOMINAL_DIAMETER.H16;
|
||||
const round = (v: number, d = 1) => Math.round(v * 10 ** d) / 10 ** d;
|
||||
|
||||
export function columnRebar(x: ColumnInput = COLUMN_P1) {
|
||||
// P1 and P2 main bars (기둥철근.md §3)
|
||||
const r1 = x.D / 2 - x.c;
|
||||
const r2 = r1 - dS32;
|
||||
const zTop1 = x.Hc + x.hcop - x.eP1;
|
||||
const lD2 = developmentLength(dS32, 500, 27);
|
||||
const zTop2 = x.Hc + lD2;
|
||||
const couplerLevels = Array.from({ length: Math.max(0, Math.floor(zTop1 / x.ctcCoupler) - 1) }, (_, i) => (i + 1) * x.ctcCoupler);
|
||||
const couplersP1 = couplerLevels.length;
|
||||
const mainLines = x.nDiv;
|
||||
const mainP1 = mainLines * (couplersP1 + 1);
|
||||
const mainP2 = mainLines * (couplersP1 + 1);
|
||||
const couplers = couplersP1 * x.nDiv * 2;
|
||||
|
||||
// Ties (기둥철근.md §4–§6)
|
||||
// Tie radius r_t = r_1 + (d_P1 + d_P3)/2 (기둥철근.md §4.1)
|
||||
const tieRadius = r1 + (dS32 + dH19) / 2;
|
||||
const zTopT = x.Hc + x.hcop - x.eTop;
|
||||
const lEmin = Math.max(x.D, zTopT / 6, 450);
|
||||
const n5 = Math.floor(lEmin / x.ctcP5);
|
||||
const lE = Math.max(lEmin, n5 * x.ctcP5 + x.ctcP5 / 2);
|
||||
const p3 = Array.from({ length: Math.floor((zTopT - lE) / x.ctcP3) + 1 }, (_, k) => lE + k * x.ctcP3);
|
||||
const n5all = Math.floor(lE / x.ctcP5);
|
||||
const p5 = Array.from({ length: n5all }, (_, j) => lE - (j + 1) * x.ctcP5);
|
||||
const z5last = lE - n5all * x.ctcP5;
|
||||
const m4 = Math.floor((z5last + x.rP4 * x.Hf) / x.ctcP4);
|
||||
const p4 = Array.from({ length: m4 }, (_, j) => z5last - (j + 1) * x.ctcP4);
|
||||
|
||||
// P6 crossties (기둥철근.md §7): 4 bars per 단, from the first P4
|
||||
const z4first = p4.length ? p4[0] : z5last;
|
||||
const p6Levels: number[] = [];
|
||||
for (let z = z4first; z <= x.Hc; z += x.ctcP6) p6Levels.push(z);
|
||||
const p6Straight = 2 * tieRadius;
|
||||
const p6Hook = hookLength('tie90', dH16);
|
||||
const p6Length = p6Straight + 2 * p6Hook;
|
||||
|
||||
return {
|
||||
r1: round(r1),
|
||||
r2: round(r2),
|
||||
angleStepDeg: 360 / x.nDiv,
|
||||
zTop1: round(zTop1),
|
||||
zTop2: round(zTop2),
|
||||
couplerP1: couplerLevels,
|
||||
couplerP2: couplerLevels.map((z) => z + x.dzCp2),
|
||||
mainP1,
|
||||
mainP2,
|
||||
couplers,
|
||||
tieRadius: round(tieRadius, 2),
|
||||
tieCircumference: round(2 * Math.PI * tieRadius, 1),
|
||||
zTopT: round(zTopT),
|
||||
lEmin: round(lEmin),
|
||||
lE: round(lE),
|
||||
p3,
|
||||
p5,
|
||||
p4,
|
||||
p6Levels,
|
||||
p6Count: p6Levels.length * 4,
|
||||
p6Length: round(p6Length, 1),
|
||||
p4SemicircleLength: round(Math.PI * tieRadius, 1),
|
||||
p3Count: p3.length,
|
||||
p5Count: p5.length,
|
||||
p4Count: p4.length,
|
||||
};
|
||||
}
|
||||
@@ -23,6 +23,20 @@ export function spliceLength(db: number, fy: number, fck: number, lambda = MATER
|
||||
return 1.3 * developmentLength(db, fy, fck, lambda);
|
||||
}
|
||||
|
||||
/** Nominal diameters d (mm) of the bar sizes used in the documents (코핑철근.md, 기둥철근.md). */
|
||||
export const NOMINAL_DIAMETER = {
|
||||
D13: 12.7,
|
||||
H16: 15.9,
|
||||
H19: 19.1,
|
||||
D22: 22.2,
|
||||
H25: 25.4,
|
||||
H29: 28.6,
|
||||
S32: 31.8,
|
||||
D35: 34.9,
|
||||
} as const;
|
||||
|
||||
export type BarSize = keyof typeof NOMINAL_DIAMETER;
|
||||
|
||||
export type HookKind = 'main90' | 'tie90' | 'stirrup135';
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
import { hookLength, NOMINAL_DIAMETER, spliceLength } from './common';
|
||||
|
||||
/**
|
||||
* C1–C8 상·하면 주철근 (plan C3 continued). Source: RAG/코핑철근.md §5, 2026-10-22 최종 정리.
|
||||
* Lengths in mm, heights in m (EL).
|
||||
*/
|
||||
export const MAIN = {
|
||||
/** 피복 (최외측 철근 중심까지). */
|
||||
cover: 100,
|
||||
/** 기본 간격 s_m and minimum end gap g_min. */
|
||||
spacing: 125,
|
||||
endGapMin: 80,
|
||||
/** 상면 단 간격 s_lay (EL, m) and its horizontal step (mm). */
|
||||
layEl: 0.057,
|
||||
layHorizontal: 57.2,
|
||||
/** 90° 갈고리 l_h (mm, as in the document). */
|
||||
hook: 472,
|
||||
/** 하면 경사 구간 수평 길이 (mm, each side) and Level width. */
|
||||
slopeEach: 5067.8,
|
||||
level: 2100,
|
||||
} as const;
|
||||
|
||||
export interface WidthLayout {
|
||||
/** Edge bar centre from the coping side face: c + (d_st + d_m)/2. */
|
||||
yE: number;
|
||||
/** Clear length between the two edge bars: B − 2·y_e. */
|
||||
S: number;
|
||||
/** Bars inside the edge bars: n (so n + 3 in all, including the two edges and the two 110.5 ends). */
|
||||
n: number;
|
||||
/** Equal end gap g = (S − n·s_m)/2. */
|
||||
g: number;
|
||||
/** Bars in all: n + 3. */
|
||||
count: number;
|
||||
/** Bars per cycle (alternating): 12 / 12 for 24. */
|
||||
cyclePerKind: number;
|
||||
/** Dimension string, e.g. "127 · 110.5 · 21@125 · 110.5 · 127". */
|
||||
text: string;
|
||||
}
|
||||
|
||||
/** 폭 방향 배치 (코핑철근.md §5.1). d_st = H25 stirrup, d_m = H29 main. */
|
||||
export function widthLayout(B: number, dSt = NOMINAL_DIAMETER.H25, dM = NOMINAL_DIAMETER.H29): WidthLayout {
|
||||
const yE = MAIN.cover + (dSt + dM) / 2;
|
||||
const S = B - 2 * yE;
|
||||
const n = Math.floor((S - 2 * MAIN.endGapMin) / MAIN.spacing);
|
||||
const g = (S - n * MAIN.spacing) / 2;
|
||||
const count = n + 3;
|
||||
const r = (v: number) => Math.round(v * 10) / 10;
|
||||
return {
|
||||
yE: r(yE),
|
||||
S: r(S),
|
||||
n,
|
||||
g: r(g),
|
||||
count,
|
||||
cyclePerKind: count / 2,
|
||||
text: `${r(yE)} · ${r(g)} · ${n}@${MAIN.spacing} · ${r(g)} · ${r(yE)}`,
|
||||
};
|
||||
}
|
||||
|
||||
/** Top-layer EL of the k-th row (k = 1, 2, 3): z_k = z_1 − (k − 1)·s_lay (m). */
|
||||
export function topRowEl(z1: number, k: number): number {
|
||||
return Math.round((z1 - (k - 1) * MAIN.layEl) * 1000) / 1000;
|
||||
}
|
||||
|
||||
/** Length of one top bar on row k: path L − 2·(c + (k−1)·step), plus two 90° hooks. */
|
||||
export function topBarLength(L: number, k: number): number {
|
||||
const path = L - 2 * (MAIN.cover + (k - 1) * MAIN.layHorizontal);
|
||||
return path + 2 * MAIN.hook;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bottom bar C7·C8 (spliced at the column centre, 하면 겹침이음). Each piece:
|
||||
* path/2 + l_s/2 + l_h, with path = 2·slope + Level and l_s = 1.3·l_d for H29 (nominal 28.6, fck 27, fy 400).
|
||||
*/
|
||||
export function bottomPiece(fck = 27): { path: number; ls: number; piece: number } {
|
||||
const path = 2 * MAIN.slopeEach + MAIN.level;
|
||||
const ls = spliceLength(NOMINAL_DIAMETER.H29, 400, fck);
|
||||
const lh = hookLength('main90', NOMINAL_DIAMETER.H29);
|
||||
return { path, ls, piece: path / 2 + ls / 2 + lh };
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user