Files
Pier_v1/src/core/rebar/coping.ts
T
ypshimandClaude Haiku 5.5 8ac5d2973c feat(view): 전단철근 구간 표 on the ③ coping tab (시안 ③)
- Segments of C9 (좌 경사), C10 (Level), C11 (우 경사): first and last bar in
  metres, spacing, count, and bar number. From the bar positions (코핑철근.md §3).
- Test: 0.300–4.550 (18 @250), 4.800–7.200 (9 @300), 7.450–11.700 (18 @250).
- Not verified in a browser.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-22 12:17:12 +09:00

134 lines
5.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 코핑 철근 (plan C3). Source: RAG/코핑철근.md, 2026-10-22 최종 정리 (spec §6.4 is older and is not used here).
* Positions are along the coping length from its start, in mm.
*/
export const COPING_REBAR = {
/** 피복 (최외측 철근 중심까지). */
cover: 100,
/** 첫 전단철근 최소 여유 e_add. 끝 여유 e_min = cover + e_add = 300. */
eAdd: 200,
/** Level 폭 W_L. */
levelWidth: 2100,
/** C10 간격 s_L (기둥 중심부터). */
spacingL: 300,
/** C9·C11 간격 s_s (C10에서 바깥으로). */
spacingS: 250,
/** C12·C13 측면 수평 간격. */
spacingSide: 250,
/** C14 위 2줄 간격 / 아래 줄 수평 간격 / 아래 줄 연직 간격 / 끝 여유. */
c14: { upperSpacing: 1000, lowerSpacing: 2000, verticalSpacing: 500, endGap: 500 },
} as const;
export const COPING_END_GAP = COPING_REBAR.cover + COPING_REBAR.eAdd;
export interface ShearBars {
/** C10 positions (mm), from the first to the last. */
c10: number[];
/** C9 positions (mm), from the left end toward the column. */
c9: number[];
/** C11 positions (mm), from the column toward the right end. */
c11: number[];
/** Distance from the coping end to the outermost C9 / C11 bar (mm). */
endGap: number;
}
/**
* Shear bars C9–C11 along the axis (코핑철근.md §3). A single column at the coping centre.
* C10: @300 from the column centre, out to the first position beyond the Level edge (k_max).
* C9 / C11: @250 outward from the outermost C10, as many as fit with the end gap of at least 300.
*/
export function shearBars(coping: number, xc = coping / 2): ShearBars {
const { spacingL, spacingS, levelWidth } = COPING_REBAR;
const kMax = Math.floor(levelWidth / 2 / spacingL) + 1;
const c10 = Array.from({ length: 2 * kMax + 1 }, (_, i) => Math.round(xc + (i - kMax) * spacingL));
const left = c10[0];
const right = c10[c10.length - 1];
const n9 = Math.floor((left - COPING_END_GAP) / spacingS);
if (n9 < 0) {
throw new Error('RB-K01: C10 바깥 구간이 끝 여유보다 짧아 C9를 놓을 수 없습니다.');
}
const c9 = Array.from({ length: n9 }, (_, j) => Math.round(left - (n9 - j) * spacingS));
const c11 = Array.from({ length: n9 }, (_, j) => Math.round(right + (j + 1) * spacingS));
const endGap = Math.min(left - c9[0], coping - c11[c11.length - 1]);
return { c10, c9, c11, endGap: endGap };
}
/**
* Side horizontal bars (코핑철근.md §6): seven rows from the bottom at 250 mm.
* Rows below the sloped-bottom break (z_7,end) are C12, the rows at and above it are C13.
*/
export function sideRows(zBottom: number, zBreak: number, rows = 7): { c12: number[]; c13: number[] } {
const z = Array.from({ length: rows }, (_, i) => Math.round((zBottom + i * COPING_REBAR.spacingSide / 1000) * 1000) / 1000);
return { c12: z.filter((v) => v < zBreak - 1e-9), c13: z.filter((v) => v >= zBreak - 1e-9) };
}
/** C14 counts (코핑철근.md §8): 2 upper lines of 11 plus the lower rows 5 / 6 / 3 / 2 = 38. */
export const C14_COUNTS = { upperLines: 2, upperPerLine: 11, lower: [5, 6, 3, 2] as const };
export function c14Total(): number {
return C14_COUNTS.upperLines * C14_COUNTS.upperPerLine + C14_COUNTS.lower.reduce((a, b) => a + b, 0);
}
/** C15 (거꾸로 된 U, 가장 높은 계단) and C16 (L형, 2구간) counts (코핑철근.md §7). */
export const STEP_BAR_COUNTS = { C15: 11, C16: 22 } as const;
/**
* C9·C10 lower U length (코핑철근.md §4.3): 1740 + 2h. h rises linearly along the slope between the document's
* ends (x 300 → h 890.9, x 4550 → h 2178.8) and stays at the Level height 2300 from the Level edge (4950) on.
* The bar's upper cap (삿갓) length depends on l_cap, which is still open (Q-K5), so only the U is given here.
*/
export const SHEAR_U = { x0: 300, h0: 890.9, x1: 4550, h1: 2178.8, levelH: 2300, levelEdgeFromCentre: 1050, flat: 1740 } as const;
export function shearUHeight(x: number, coping: number): number {
const xs = Math.min(x, coping - x); // mirror to the left half
const slope = (SHEAR_U.h1 - SHEAR_U.h0) / (SHEAR_U.x1 - SHEAR_U.x0);
const h = SHEAR_U.h0 + (xs - SHEAR_U.x0) * slope;
return Math.min(h, SHEAR_U.levelH);
}
export function shearULength(x: number, coping: number): number {
return SHEAR_U.flat + 2 * shearUHeight(x, coping);
}
/** C12 straight lengths per row (코핑철근.md §6 table, mm) and C13. */
export const SIDE_LENGTHS = { C12: [3717, 5333, 6950, 8567, 10183], C13: 11746 } as const;
/** C15 (거꾸로 된 U, 3852) and C16 (L형, 4070 / 4069) lengths, mm (코핑철근.md §7). */
export const STEP_LENGTHS = { C15: 3852, C16: [4070, 4069] as const, C14: 3447.5 } as const;
/**
* 삿갓 (upper cap) of C9–C11 (코핑철근.md §4.3). l_cap is open (Q-K5); recommended here: l_cap = h − c (top cover 100),
* so that l_cap stays below h (RB-K04). Cap length = 1740 + 2·l_cap.
*/
export const CAP = { flat: 1740, cover: 100 } as const;
export function capLength(x: number, coping: number): number {
const h = shearUHeight(x, coping);
const lCap = h - CAP.cover;
return CAP.flat + 2 * lCap;
}
/** Pieces per position: 3 closed stirrups × (U + cap) = 6. Total 270 for C9 + C10 + C11 (document). */
export const PIECES_PER_POSITION = 6;
/**
* 전단철근 구간 표 (시안 ③ · 코핑): C9 / C10 / C11 grouped by segment, from the bar positions.
* Positions are along the coping length (mm); the table shows the first and last bar of each segment.
*/
export function shearSegments(coping: number): { segment: string; from: number; to: number; spacing: number; count: number; bar: 'C9' | 'C10' | 'C11' }[] {
const b = shearBars(coping);
const seg = (name: string, xs: number[], bar: 'C9' | 'C10' | 'C11', spacing: number) => ({
segment: name,
from: Math.min(...xs),
to: Math.max(...xs),
spacing,
count: xs.length,
bar,
});
return [
seg('좌 경사', b.c9, 'C9', COPING_REBAR.spacingS),
seg('Level', b.c10, 'C10', COPING_REBAR.spacingL),
seg('우 경사', b.c11, 'C11', COPING_REBAR.spacingS),
];
}