feat(rebar,view): coping end height h1, taper h2 and Level width as inputs on ② (1단계)
The three values are inputs on the coping card, with the P1 values (1000 · 1500 · 2100) when absent, and they are tracked like the other shape inputs. The geometry and the coping rebar read them from one CopingGeom: the U heights follow the closed form (h1 − 2c) + h2·min(x_s, x_L0)/x_L0, which reproduces the P1 values. The side rows are assumed to keep their position relative to the Level underside (명세 확인 필요). P1 results are unchanged; the full suite passes. Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
5b5db60657
commit
0a5edfb152
9 files changed
+169
-45
No files matched your search
+27
-23
@@ -3,6 +3,7 @@
|
||||
* Positions are along the coping length from its start, in mm.
|
||||
*/
|
||||
import { DEFAULT_MATERIAL, developmentLength, fyOf, hookLength, Material, NOMINAL_DIAMETER } from './common';
|
||||
import { type CopingGeom, P1_COPING_GEOM } from '../coping-geom';
|
||||
export const COPING_REBAR = {
|
||||
/** 피복 (최외측 철근 중심까지). */
|
||||
cover: 100,
|
||||
@@ -40,9 +41,9 @@ export interface ShearBars {
|
||||
* 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.ceil(levelWidth / 2 / spacingL); // k_max = ceil((W_L/2)/s_L), spec §3.1
|
||||
export function shearBars(coping: number, xc = coping / 2, g: CopingGeom = P1_COPING_GEOM): ShearBars {
|
||||
const { spacingL, spacingS } = COPING_REBAR;
|
||||
const kMax = Math.ceil(g.levelWidth / 2 / spacingL); // k_max = ceil((W_L/2)/s_L), spec §3.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];
|
||||
@@ -82,15 +83,18 @@ export const STEP_BAR_COUNTS = { C15: 11, C16: 22 } as const;
|
||||
*/
|
||||
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 {
|
||||
/**
|
||||
* U height at x (mm): h = (h1 − 2c) + h2·min(x_s, x_L0)/x_L0, with x_L0 = L/2 − W_L/2 (코핑철근.md §4.2).
|
||||
* Reproduces the P1 values (890.9 at x = 300, 2178.8 at x = 4550, 2300 at the Level).
|
||||
*/
|
||||
export function shearUHeight(x: number, coping: number, g: CopingGeom = P1_COPING_GEOM): 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);
|
||||
const xL0 = coping / 2 - g.levelWidth / 2;
|
||||
return g.h1 - 2 * COPING_REBAR.cover + (g.h2 * Math.min(xs, xL0)) / xL0;
|
||||
}
|
||||
|
||||
export function shearULength(x: number, coping: number): number {
|
||||
return SHEAR_U.flat + 2 * shearUHeight(x, coping);
|
||||
export function shearULength(x: number, coping: number, g: CopingGeom = P1_COPING_GEOM): number {
|
||||
return SHEAR_U.flat + 2 * shearUHeight(x, coping, g);
|
||||
}
|
||||
|
||||
/** C13 sits 127 in from each end face (코핑철근.md §6.2). */
|
||||
@@ -113,13 +117,13 @@ export interface SideBar {
|
||||
* C12 meets the sloped bottom at x_w = c + (z_break − z_k)·(x_L0 − c)/h2, with x_L0 = L/2 − W_L/2.
|
||||
* C13 starts at x_w = 127. Each row has two 일자 bars (side faces) and two ㄷ bars (one at each end).
|
||||
*/
|
||||
export function copingSideBars(L: number, zBottom: number, zBreak: number): { c12: SideBar[]; c13: SideBar[] } {
|
||||
export function copingSideBars(L: number, zBottom: number, zBreak: number, g: CopingGeom = P1_COPING_GEOM): { c12: SideBar[]; c13: SideBar[] } {
|
||||
const c = COPING_REBAR.cover;
|
||||
const xL0 = L / 2 - COPING_REBAR.levelWidth / 2;
|
||||
const xL0 = L / 2 - g.levelWidth / 2;
|
||||
const bar = (z: number, xw: number): SideBar => ({ z, xw, straight: L - 2 * xw });
|
||||
const rows = sideRows(zBottom, zBreak);
|
||||
return {
|
||||
c12: rows.c12.map((z) => bar(z, c + ((zBreak - z) * 1000 * (xL0 - c)) / COPING_REBAR.taperHeight)),
|
||||
c12: rows.c12.map((z) => bar(z, c + ((zBreak - z) * 1000 * (xL0 - c)) / g.h2)),
|
||||
c13: rows.c13.map((z) => bar(z, SIDE_C13_END)),
|
||||
};
|
||||
}
|
||||
@@ -159,8 +163,8 @@ export interface C14Bar {
|
||||
}
|
||||
|
||||
/** Underside of the coping (EL m) at x (mm from the start), T형: sloped from each end to the Level zone, flat in the middle. */
|
||||
export function undersideAt(L: number, x: number, endBottom: number, levelBottom: number): number {
|
||||
const xL0 = L / 2 - COPING_REBAR.levelWidth / 2;
|
||||
export function undersideAt(L: number, x: number, endBottom: number, levelBottom: number, levelWidth = P1_COPING_GEOM.levelWidth): number {
|
||||
const xL0 = L / 2 - levelWidth / 2;
|
||||
return endBottom + (levelBottom - endBottom) * Math.min(Math.min(x, L - x) / xL0, 1);
|
||||
}
|
||||
|
||||
@@ -246,8 +250,8 @@ export function stairBars(L: number, B: number, topEl: number, m: Material = DEF
|
||||
*/
|
||||
export const CAP = { flat: 1740, cover: 100 } as const;
|
||||
|
||||
export function capLength(x: number, coping: number): number {
|
||||
const h = shearUHeight(x, coping);
|
||||
export function capLength(x: number, coping: number, g: CopingGeom = P1_COPING_GEOM): number {
|
||||
const h = shearUHeight(x, coping, g);
|
||||
const lCap = h - CAP.cover;
|
||||
return CAP.flat + 2 * lCap;
|
||||
}
|
||||
@@ -265,8 +269,8 @@ export const PIECES_PER_POSITION = 6;
|
||||
* 전단철근 구간 표 (시안 ③ · 코핑): the segments of C9 / C10 / C11 along the coping, from the bar positions.
|
||||
* One column gives the three T형 segments; several columns add the segments between them (추천안, Q-K2).
|
||||
*/
|
||||
export function shearSegments(coping: number, columns: number[] = [coping / 2]): { segment: string; from: number; to: number; spacing: number; count: number; bar: 'C9' | 'C10' | 'C11' | 'C9·C11' }[] {
|
||||
const b = shearBarsMulti(coping, columns);
|
||||
export function shearSegments(coping: number, columns: number[] = [coping / 2], g: CopingGeom = P1_COPING_GEOM): { segment: string; from: number; to: number; spacing: number; count: number; bar: 'C9' | 'C10' | 'C11' | 'C9·C11' }[] {
|
||||
const b = shearBarsMulti(coping, columns, g);
|
||||
const seg = (name: string, xs: number[], bar: 'C9' | 'C10' | 'C11' | 'C9·C11', spacing: number) => ({
|
||||
segment: name,
|
||||
from: Math.min(...xs),
|
||||
@@ -279,7 +283,7 @@ export function shearSegments(coping: number, columns: number[] = [coping / 2]):
|
||||
const groups = columns.length > 1 ? columns.length : 1;
|
||||
for (let k = 0; k < groups; k++) {
|
||||
const xc = columns[k] ?? coping / 2;
|
||||
out.push(seg(`Level ${k + 1}`, b.c10.filter((x) => Math.abs(x - xc) <= (COPING_REBAR.levelWidth / 2 + COPING_REBAR.spacingL * 4)).slice(0, 2 * 4 + 1), 'C10', COPING_REBAR.spacingL));
|
||||
out.push(seg(`Level ${k + 1}`, b.c10.filter((x) => Math.abs(x - xc) <= (g.levelWidth / 2 + COPING_REBAR.spacingL * 4)).slice(0, 2 * 4 + 1), 'C10', COPING_REBAR.spacingL));
|
||||
}
|
||||
for (let k = 0; k + 1 < groups; k++) {
|
||||
const between = b.between.filter((x) => x > columns[k] && x < columns[k + 1]);
|
||||
@@ -296,13 +300,13 @@ export function shearSegments(coping: number, columns: number[] = [coping / 2]):
|
||||
* Between columns: @250 in from both C10 groups, the remaining length shared evenly (추천안, Q-K2).
|
||||
* With one column this is the same as shearBars.
|
||||
*/
|
||||
export function shearBarsMulti(coping: number, columns: number[]): ShearBars & { between: number[] } {
|
||||
export function shearBarsMulti(coping: number, columns: number[], g: CopingGeom = P1_COPING_GEOM): ShearBars & { between: number[] } {
|
||||
if (columns.length <= 1) {
|
||||
const one = shearBars(coping, columns[0] ?? coping / 2);
|
||||
const one = shearBars(coping, columns[0] ?? coping / 2, g);
|
||||
return { ...one, between: [] };
|
||||
}
|
||||
const { spacingL, spacingS, levelWidth } = COPING_REBAR;
|
||||
const kMax = Math.ceil(levelWidth / 2 / spacingL); // k_max = ceil((W_L/2)/s_L), spec §3.1
|
||||
const { spacingL, spacingS } = COPING_REBAR;
|
||||
const kMax = Math.ceil(g.levelWidth / 2 / spacingL); // k_max = ceil((W_L/2)/s_L), spec §3.1
|
||||
const groups = columns.map((xc) =>
|
||||
Array.from({ length: 2 * kMax + 1 }, (_, i) => Math.round(xc + (i - kMax) * spacingL)),
|
||||
);
|
||||
|
||||
Reference in new issue
Block a user