feat(core): RB-C07 — delete P4 ties that interfere with the footing top bars
- A P4 is deleted when |z_P4 − z_bar| < (d_P4 + d_bar)/2 against B5 and B1 (the 확대기초 top layer, from the 상면). B11/B12 are not checked (Q-C9 무시). - The P6 crossties start from the first kept P4. - Tests: the document's example keeps all 8; B5 moved to −70 deletes the P4 at −60; a P4 just outside the limit is kept. Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
02d740d8ca
commit
5cc166c2e1
2 files changed
+61
-2
No files matched your search
@@ -1,4 +1,5 @@
|
||||
import { developmentLength, hookLength, NOMINAL_DIAMETER, spliceLength } from './common';
|
||||
import { layers } from './footing';
|
||||
|
||||
/**
|
||||
* 기둥 철근 C4 (plan C4). Source: RAG/기둥철근 (1).md, 2026-10-22 최종 정리. Type-1 원형 중실 기둥.
|
||||
@@ -52,6 +53,38 @@ export const COLUMN_P1: ColumnInput = {
|
||||
ctcP6: 1800,
|
||||
};
|
||||
|
||||
/** A bar in the 확대기초 top layer, height from the 확대기초 상면 (mm, negative = below). */
|
||||
export interface TopBar {
|
||||
name: string;
|
||||
z: number;
|
||||
d: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* RB-C07 (기둥철근.md §6.1–6.2, 결정): a P4 that interferes with a 확대기초 top bar is deleted.
|
||||
* Interference: |z_P4 − z_bar| < (d_P4 + d_bar)/2. Only the top layer (B5, B1) is checked; the assembly bars
|
||||
* B11/B12 are not, by the 2026-10-22 decision (Q-C9 무시).
|
||||
*/
|
||||
export function deleteInterferingP4(p4: number[], topBars: TopBar[], dP4: number = NOMINAL_DIAMETER.H19): { kept: number[]; deleted: { z: number; bar: string }[] } {
|
||||
const kept: number[] = [];
|
||||
const deleted: { z: number; bar: string }[] = [];
|
||||
for (const z of p4) {
|
||||
const hit = topBars.find((b) => Math.abs(z - b.z) < (dP4 + b.d) / 2);
|
||||
if (hit) deleted.push({ z, bar: hit.name });
|
||||
else kept.push(z);
|
||||
}
|
||||
return { kept, deleted };
|
||||
}
|
||||
|
||||
/** Top-layer bars of the footing as heights from its 상면 (B5 and B1, §4.2). */
|
||||
export function footingTopBars(Hf: number): TopBar[] {
|
||||
const z = layers(Hf);
|
||||
return [
|
||||
{ name: 'B5', z: z.B5 - Hf, d: NOMINAL_DIAMETER.S29 },
|
||||
{ name: 'B1', z: z.B1 - Hf, d: NOMINAL_DIAMETER.S25 },
|
||||
];
|
||||
}
|
||||
|
||||
const dS32 = NOMINAL_DIAMETER.S32;
|
||||
const dH19 = NOMINAL_DIAMETER.H19;
|
||||
const dH16 = NOMINAL_DIAMETER.H16;
|
||||
@@ -83,9 +116,11 @@ export function columnRebar(x: ColumnInput = COLUMN_P1) {
|
||||
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);
|
||||
const p4All = Array.from({ length: m4 }, (_, j) => z5last - (j + 1) * x.ctcP4);
|
||||
const p4Check = deleteInterferingP4(p4All, footingTopBars(x.Hf));
|
||||
const p4 = p4Check.kept;
|
||||
|
||||
// P6 crossties (기둥철근.md §7): 4 bars per 단, from the first P4
|
||||
// P6 crossties (기둥철근.md §7): 4 bars per 단, from the first kept P4
|
||||
const z4first = p4.length ? p4[0] : z5last;
|
||||
const p6Levels: number[] = [];
|
||||
for (let z = z4first; z <= x.Hc; z += x.ctcP6) p6Levels.push(z);
|
||||
@@ -127,5 +162,6 @@ export function columnRebar(x: ColumnInput = COLUMN_P1) {
|
||||
p3Count: p3.length,
|
||||
p5Count: p5.length,
|
||||
p4Count: p4.length,
|
||||
p4Deleted: p4Check.deleted,
|
||||
};
|
||||
}
|
||||
@@ -61,3 +61,26 @@ describe('기둥 철근 C4 (기둥철근.md, plan C4)', () => {
|
||||
expect(c.p6Length).toBeCloseTo(2071, 0);
|
||||
});
|
||||
});
|
||||
|
||||
import { deleteInterferingP4, footingTopBars } from '../src/core/rebar/column';
|
||||
|
||||
describe('RB-C07 P4 삭제 규칙 (기둥철근.md §6.2)', () => {
|
||||
it('the example: no P4 interferes with the top bars (B5 −100, B1 −127): 8 kept, 0 deleted', () => {
|
||||
expect(c.p4Count).toBe(8);
|
||||
expect(c.p4Deleted).toEqual([]);
|
||||
const r = deleteInterferingP4([-60, -180], footingTopBars(2000));
|
||||
expect(r.deleted).toEqual([]);
|
||||
});
|
||||
|
||||
it('hypothetical: B5 moved to −70 deletes the P4 at −60 (|−60 + 70| = 10 < 23.85)', () => {
|
||||
const bars = [{ name: 'B5', z: -70, d: 28.6 }];
|
||||
const r = deleteInterferingP4([-60, -180, -300], bars);
|
||||
expect(r.deleted).toEqual([{ z: -60, bar: 'B5' }]);
|
||||
expect(r.kept).toEqual([-180, -300]);
|
||||
});
|
||||
|
||||
it('a P4 just outside the limit is kept: |−60 + 84| = 24 ≥ 23.85', () => {
|
||||
const r = deleteInterferingP4([-60], [{ name: 'B5', z: -84, d: 28.6 }]);
|
||||
expect(r.kept).toEqual([-60]);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user