feat(rebar): 확대기초 패널 규칙 값 표시 (상면·2단, B2·B6 디리, B9, 조립 단 수) 및 "규칙" 표기
- footingRuleValues: 패널 표시값을 계산 함수에서 직접 읽음 (새 공식 없음) - B2·B6 디리 두 값, 조립 단 수(3단) 표시 - "(고정)"은 Δ₂ 100에만 사용, 4s·2s·상면 2s는 "(규칙)"으로 표기 - 테스트: 기본값 P1에서 250 · 100 · 1723 · 500·250 · 500·3단 @400 Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ddd6d55a72
commit
48e6811600
3 files changed
+57
-11
No files matched your search
@@ -232,3 +232,34 @@ export function assemblyHeights(H: number, f: FootingRebarSettings = DEFAULT_FOO
|
|||||||
const B12 = B11.map((z) => z + NOMINAL_DIAMETER.S19);
|
const B12 = B11.map((z) => z + NOMINAL_DIAMETER.S19);
|
||||||
return { B11, B12 };
|
return { B11, B12 };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Values shown on the 확대기초 panel as rules and derived values (승인 2026-10-26). Each is read from the same functions the
|
||||||
|
* rebar table and the 3D view use, so the panel cannot drift from the calculation. H is the footing height (mm).
|
||||||
|
*/
|
||||||
|
export function footingRuleValues(H: number, f: FootingRebarSettings = DEFAULT_FOOTING_REBAR): {
|
||||||
|
upper2sAxis: number;
|
||||||
|
upper2sPerp: number;
|
||||||
|
delta2: number;
|
||||||
|
b2Leg: number;
|
||||||
|
b6Leg: number;
|
||||||
|
b9Pitch: number;
|
||||||
|
b9Stagger: number;
|
||||||
|
assemblyPlanPitch: number;
|
||||||
|
assemblyVertical: number;
|
||||||
|
assemblyLevels: number;
|
||||||
|
} {
|
||||||
|
const z = layers(H, f);
|
||||||
|
return {
|
||||||
|
upper2sAxis: 2 * f.sAxis,
|
||||||
|
upper2sPerp: 2 * f.sPerp,
|
||||||
|
delta2: DELTA2,
|
||||||
|
b2Leg: legB2(H, f),
|
||||||
|
b6Leg: z.B5 - z.B68,
|
||||||
|
b9Pitch: 4 * f.sAxis,
|
||||||
|
b9Stagger: 2 * f.sAxis,
|
||||||
|
assemblyPlanPitch: 4 * f.sPerp,
|
||||||
|
assemblyVertical: f.n * f.sV,
|
||||||
|
assemblyLevels: assemblyJs(H, f).length,
|
||||||
|
};
|
||||||
|
}
|
||||||
+16
-10
@@ -31,7 +31,7 @@ import { COPING_REBAR_RANGES, copingSettingsIssues, type CopingRebarSettings, DE
|
|||||||
import { COLUMN_REBAR_RANGES, type ColumnRebarSettings, columnSettingsIssues, DEFAULT_COLUMN_REBAR } from './core/rebar/column-settings';
|
import { COLUMN_REBAR_RANGES, type ColumnRebarSettings, columnSettingsIssues, DEFAULT_COLUMN_REBAR } from './core/rebar/column-settings';
|
||||||
import { columnInputFor, columnRebar } from './core/rebar/column';
|
import { columnInputFor, columnRebar } from './core/rebar/column';
|
||||||
import { DEFAULT_FOOTING_REBAR, FOOTING_REBAR_RANGES, type FootingRebarSettings, footingSettingsIssues } from './core/rebar/footing-settings';
|
import { DEFAULT_FOOTING_REBAR, FOOTING_REBAR_RANGES, type FootingRebarSettings, footingSettingsIssues } from './core/rebar/footing-settings';
|
||||||
import { legB2 } from './core/rebar/footing';
|
import { footingRuleValues } from './core/rebar/footing';
|
||||||
import { columnElevationSvg } from './view/column-elevation-svg';
|
import { columnElevationSvg } from './view/column-elevation-svg';
|
||||||
import { type ColumnSection, columnSectionSvg } from './view/column-section-svg';
|
import { type ColumnSection, columnSectionSvg } from './view/column-section-svg';
|
||||||
import { groundSectionSvg } from './view/ground-svg';
|
import { groundSectionSvg } from './view/ground-svg';
|
||||||
@@ -1339,15 +1339,21 @@ function renderFootingSettings(box: HTMLDivElement, pier: Pier): void {
|
|||||||
// Fixed rules and derived values (읽기 전용). Derived from the current settings of the first footing.
|
// Fixed rules and derived values (읽기 전용). Derived from the current settings of the first footing.
|
||||||
const fs = current;
|
const fs = current;
|
||||||
const fixed = el('div', undefined, 'muted small');
|
const fixed = el('div', undefined, 'muted small');
|
||||||
const H = pier.model.footings[0] ? (pier.model.footings[0].top - pier.model.footings[0].bottom) * 1000 : undefined;
|
const foot = pier.model.footings[0];
|
||||||
fixed.textContent = [
|
const H = foot ? (foot.top - foot.bottom) * 1000 : undefined;
|
||||||
`B1–B4 간격 2·s (고정) ${2 * fs.sAxis} mm · B5–B8 간격 2·s (고정) ${2 * fs.sPerp} mm`,
|
if (H === undefined) {
|
||||||
`하면 1·2단 간격 Δ₂ (고정) 100 mm`,
|
fixed.textContent = '확대기초 없음 · 확대기초 규칙을 표시하지 않습니다';
|
||||||
`전단 B9 간격 4s · 행 엇갈림 2s (고정) ${4 * fs.sAxis} · ${2 * fs.sAxis} mm`,
|
} else {
|
||||||
`조립 평면 간격 4s · 연직 n·s_v (자동) ${4 * fs.sPerp} · ${fs.n * fs.sV} mm`,
|
const r = footingRuleValues(H, fs);
|
||||||
`cycle 배치: 교대 배치 (고정)`,
|
fixed.textContent = [
|
||||||
H === undefined ? 'B2·B6 디리 (자동): 확대기초 없음' : `B2·B6 디리 (자동) z_B1 − z_B24 = ${legB2(H, fs)} mm`,
|
`상면·2단 간격 B1·B3 = 2·s교각축 ${r.upper2sAxis} mm · B5·B7 = 2·s교각축직각 ${r.upper2sPerp} mm (규칙)`,
|
||||||
].join(' · ');
|
`하면 1·2단 간격 Δ₂ = ${r.delta2} mm (고정)`,
|
||||||
|
`B2 디리 ${r.b2Leg} mm · B6 디리 ${r.b6Leg} mm (자동, B1·B5 높이까지)`,
|
||||||
|
`B9 간격 4·s교각축 ${r.b9Pitch} · 행 엇갈림 2·s교각축 ${r.b9Stagger} mm (규칙)`,
|
||||||
|
`B11·B12 평면 간격 4·s교각축직각 ${r.assemblyPlanPitch} · 연직 n·s_v ${r.assemblyVertical} mm · 조립 단 ${r.assemblyLevels}단 (자동)`,
|
||||||
|
'cycle 배치: 교대 배치 (고정)',
|
||||||
|
].join(' · ');
|
||||||
|
}
|
||||||
wrap.appendChild(fixed);
|
wrap.appendChild(fixed);
|
||||||
const msg = el('p', undefined, 'muted small');
|
const msg = el('p', undefined, 'muted small');
|
||||||
const apply = el('button', '적용', 'btn small');
|
const apply = el('button', '적용', 'btn small');
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { describe, expect, it } from 'vitest';
|
import { describe, expect, it } from 'vitest';
|
||||||
import { buildPier } from '../src/core/geometry';
|
import { buildPier } from '../src/core/geometry';
|
||||||
import { assemblyJs, gridPositions } from '../src/core/rebar/footing';
|
import { assemblyJs, footingRuleValues, gridPositions } from '../src/core/rebar/footing';
|
||||||
import { DEFAULT_FOOTING_REBAR, FOOTING_REBAR_RANGES, footingSettingsIssues } from '../src/core/rebar/footing-settings';
|
import { DEFAULT_FOOTING_REBAR, FOOTING_REBAR_RANGES, footingSettingsIssues } from '../src/core/rebar/footing-settings';
|
||||||
import { rebarSummary } from '../src/core/rebar/summary';
|
import { rebarSummary } from '../src/core/rebar/summary';
|
||||||
import { loadP1 } from './helpers';
|
import { loadP1 } from './helpers';
|
||||||
@@ -58,6 +58,15 @@ describe('확대기초 배근 입력 (승인 2026-10-26, 시안 ③ 확대기초
|
|||||||
expect(rowsAxis.find((r) => r.name === 'B5')!.basis).toBe('default');
|
expect(rowsAxis.find((r) => r.name === 'B5')!.basis).toBe('default');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('패널 규칙 값 (P1, H 2000): 상면·2단 250 · Δ₂ 100 · B2·B6 1723 · B9 500·250 · 조립 500 · 3단 @400', () => {
|
||||||
|
const r = footingRuleValues(2000, DEFAULT_FOOTING_REBAR);
|
||||||
|
expect([r.upper2sAxis, r.upper2sPerp, r.delta2]).toEqual([250, 250, 100]);
|
||||||
|
expect(r.b2Leg).toBeCloseTo(1723, 0);
|
||||||
|
expect(r.b6Leg).toBeCloseTo(1723, 0);
|
||||||
|
expect([r.b9Pitch, r.b9Stagger]).toEqual([500, 250]);
|
||||||
|
expect([r.assemblyPlanPitch, r.assemblyVertical, r.assemblyLevels]).toEqual([500, 400, 3]);
|
||||||
|
});
|
||||||
|
|
||||||
it('the 조립 단 배수 n reaches the assembly levels', () => {
|
it('the 조립 단 배수 n reaches the assembly levels', () => {
|
||||||
const H = 2000;
|
const H = 2000;
|
||||||
const base = assemblyJs(H, DEFAULT_FOOTING_REBAR);
|
const base = assemblyJs(H, DEFAULT_FOOTING_REBAR);
|
||||||
|
|||||||
Reference in new issue
Block a user