feat(rebar): 기둥 배근 입력 8개 (피복·띠철근 K3/K5/K4·K6·커플러·Δz·n_div), CL01·CL02 검사
- core/rebar/column-settings.ts: 입력 정의, 기본값(기둥철근 (1).md), 범위(제안), 검사 (CL01 범위, CL02 n_div 홀수) - 주철근 하단 갈고리는 고정 (입력 없음) - 기둥 탭 패널: 적용 버튼으로 반영, 계산 결과(K2 내측 r, 주철근·커플러 수량) 표시 - P1·P2 등분 수, P3·P5·P4·P6 간격, 커플러 간격·상승을 철근표 간격·비고와 근거(기본값/입력)에 연동 - 3D 주철근 개수도 n_div 입력을 사용 (COLUMN_P1 하드코딩 제거) Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
496e0ea4e5
commit
f619b9ea20
9 files changed
+215
-20
No files matched your search
+2
-1
@@ -23,7 +23,7 @@ export const EDITABLE_FIELDS = [
|
||||
] as const;
|
||||
|
||||
/** Inputs tracked for overrides and pending changes: the numeric cards plus 열별 본수 (an array, compared by value). */
|
||||
export const TRACKED_KEYS = [...EDITABLE_FIELDS.map((f) => f.key), 'pileRows', 'groundPosition', 'groundWaterOn', 'groundWaterEl', 'floodLevelEl', 'scourDepthM', 'highWaterEl', 'lowWaterEl', 'strataRows', 'bearingType', 'bearingLayout', 'blockRebar', 'copingRebar', 'topSplice'] as const;
|
||||
export const TRACKED_KEYS = [...EDITABLE_FIELDS.map((f) => f.key), 'pileRows', 'groundPosition', 'groundWaterOn', 'groundWaterEl', 'floodLevelEl', 'scourDepthM', 'highWaterEl', 'lowWaterEl', 'strataRows', 'bearingType', 'bearingLayout', 'blockRebar', 'copingRebar', 'topSplice', 'columnRebar'] as const;
|
||||
|
||||
export type EditableKey = (typeof TRACKED_KEYS)[number];
|
||||
|
||||
@@ -56,6 +56,7 @@ export const FIELD_LABELS: Record<EditableKey, string> = {
|
||||
blockRebar: '받침블럭 철근 설정',
|
||||
copingRebar: '코핑 배근 입력',
|
||||
topSplice: '상면 주철근 이음',
|
||||
columnRebar: '기둥 배근 입력',
|
||||
strataRows: '지층 행',
|
||||
};
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import { buildAxis, copingSpan, fromAxis, kinkArc, nearKink, toAxis } from './ax
|
||||
import { buildIntegratedBlocks, type IntegratedBlock } from './integrated-block';
|
||||
import { type BlockRebarSettings, DEFAULT_BLOCK_REBAR } from './rebar/bearing-block';
|
||||
import { type CopingRebarSettings, DEFAULT_COPING_REBAR, DEFAULT_TOP_SPLICE, type TopSpliceSettings } from './rebar/coping-settings';
|
||||
import { type ColumnRebarSettings, DEFAULT_COLUMN_REBAR } from './rebar/column-settings';
|
||||
import { layoutText, resolveRowCounts, rowLayout, type PileGeometry } from './piles';
|
||||
import type { PierInput, Row } from './types';
|
||||
import { type CopingGeom, P1_COPING_GEOM } from './coping-geom';
|
||||
@@ -181,6 +182,8 @@ export interface PierModel {
|
||||
copingRebar: CopingRebarSettings;
|
||||
/** 상면 주철근 이음 used by the coping rebar (승인 2026-10-26). */
|
||||
topSplice: TopSpliceSettings;
|
||||
/** 기둥 배근 입력 used by the column rebar (승인 2026-10-26). */
|
||||
columnRebar: ColumnRebarSettings;
|
||||
columns: ColumnModel[];
|
||||
footings: FootingModel[];
|
||||
blindings: BlindingModel[];
|
||||
@@ -471,6 +474,7 @@ export function buildPier(input: PierInput): PierModel {
|
||||
blockRebar: { ...DEFAULT_BLOCK_REBAR, ...input.blockRebar },
|
||||
copingRebar: { ...DEFAULT_COPING_REBAR, ...input.copingRebar },
|
||||
topSplice: { ...DEFAULT_TOP_SPLICE, ...input.topSplice },
|
||||
columnRebar: { ...DEFAULT_COLUMN_REBAR, ...input.columnRebar },
|
||||
columns,
|
||||
footings,
|
||||
blindings,
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* 기둥 배근 입력 (승인 2026-10-26, 시안 ③ 기둥 삽도). The inputs of the 기둥 panel; the names match ColumnInput.
|
||||
* Defaults are the 기둥철근 (1).md P1 values; the ranges are proposed and pending the design-standard check.
|
||||
* The 주철근 하단 갈고리 is fixed (no input).
|
||||
*/
|
||||
export interface ColumnRebarSettings {
|
||||
/** K1 중심 피복 c (기둥 면 ~ P1 중심, mm). */
|
||||
c: number;
|
||||
/** 띠철근 간격 K3 (일반 구간, mm). */
|
||||
ctcP3: number;
|
||||
/** 띠철근 간격 K5 (단부, mm). */
|
||||
ctcP5: number;
|
||||
/** 띠철근 간격 K4 (기초 안, mm). */
|
||||
ctcP4: number;
|
||||
/** 크로스타이 K6 간격 (단 간격, mm). */
|
||||
ctcP6: number;
|
||||
/** 주철근 커플러 간격 (기초 상면부터, mm). */
|
||||
ctcCoupler: number;
|
||||
/** P2 커플러를 P1보다 올리는 높이 (mm). */
|
||||
dzCp2: number;
|
||||
/** 주철근 원주 등분 수 n_div (P1·P2 공통, 짝수). */
|
||||
nDiv: number;
|
||||
}
|
||||
|
||||
export const DEFAULT_COLUMN_REBAR: ColumnRebarSettings = {
|
||||
c: 125,
|
||||
ctcP3: 300,
|
||||
ctcP5: 120,
|
||||
ctcP4: 120,
|
||||
ctcP6: 1800,
|
||||
ctcCoupler: 3000,
|
||||
dzCp2: 150,
|
||||
nDiv: 46,
|
||||
};
|
||||
|
||||
/** Allowed range per input (inclusive, mm). */
|
||||
export const COLUMN_REBAR_RANGES: Record<keyof ColumnRebarSettings, [number, number]> = {
|
||||
c: [100, 150],
|
||||
ctcP3: [200, 400],
|
||||
ctcP5: [80, 200],
|
||||
ctcP4: [80, 200],
|
||||
ctcP6: [1200, 2400],
|
||||
ctcCoupler: [2000, 4000],
|
||||
dzCp2: [0, 300],
|
||||
nDiv: [40, 50],
|
||||
};
|
||||
|
||||
export interface ColumnSettingsIssue {
|
||||
code: 'CL01' | 'CL02';
|
||||
key: keyof ColumnRebarSettings;
|
||||
message: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* CL01: a value is not a finite number or is out of range (W). CL02: n_div is odd (the main bars come in pairs around the circle).
|
||||
*/
|
||||
export function columnSettingsIssues(s: ColumnRebarSettings): ColumnSettingsIssue[] {
|
||||
const out: ColumnSettingsIssue[] = [];
|
||||
for (const key of Object.keys(COLUMN_REBAR_RANGES) as (keyof ColumnRebarSettings)[]) {
|
||||
const v = s[key];
|
||||
const [lo, hi] = COLUMN_REBAR_RANGES[key];
|
||||
if (!Number.isFinite(v) || v < lo || v > hi) {
|
||||
out.push({ code: 'CL01', key, message: `CL01 ${key} ${v} 범위 밖 (${lo}–${hi})` });
|
||||
}
|
||||
}
|
||||
if (Number.isFinite(s.nDiv) && s.nDiv % 2 !== 0) {
|
||||
out.push({ code: 'CL02', key: 'nDiv', message: `CL02 주철근 등분 수 ${s.nDiv}는 홀수 (짝수만 허용)` });
|
||||
}
|
||||
return out;
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { PierModel } from '../geometry';
|
||||
import { DEFAULT_MATERIAL, developmentLength, fyOf, hookLength, Material, NOMINAL_DIAMETER, spliceLength } from './common';
|
||||
import { layers } from './footing';
|
||||
import { DEFAULT_COLUMN_REBAR } from './column-settings';
|
||||
|
||||
/**
|
||||
* 기둥 철근 C4 (plan C4). Source: RAG/기둥철근 (1).md, 2026-10-22 최종 정리. Type-1 원형 중실 기둥.
|
||||
@@ -54,26 +55,19 @@ export function columnInputFor(model: PierModel, base: ColumnInput = COLUMN_P1):
|
||||
const eP1 = Math.round((seg.top - (c3 - 0.1)) * 1000);
|
||||
// e_top: the coping middle level (Level 하면 + 계단 상면)/2 is the top of P3 and P6 (승인 2026-10-23).
|
||||
const eTop = Math.round((seg.top - (model.levelBottom + seg.top) / 2) * 1000);
|
||||
return { ...base, Hc, hcop, eP1, eTop, D: model.columnDiameterMm };
|
||||
return { ...base, ...model.columnRebar, Hc, hcop, eP1, eTop, D: model.columnDiameterMm };
|
||||
}
|
||||
|
||||
export const COLUMN_P1: ColumnInput = {
|
||||
D: 2000,
|
||||
Hc: 12703,
|
||||
hcop: 2644,
|
||||
c: 125,
|
||||
...DEFAULT_COLUMN_REBAR,
|
||||
eP1: 485,
|
||||
// Coping middle level: (Level 하면 + 계단 상면)/2 on P1 = 42.233 → e_top 1322 (승인 2026-10-23, Q-C3 대체).
|
||||
eTop: 1322,
|
||||
Hf: 2000,
|
||||
nDiv: 46,
|
||||
ctcCoupler: 3000,
|
||||
dzCp2: 150,
|
||||
ctcP3: 300,
|
||||
ctcP5: 120,
|
||||
ctcP4: 120,
|
||||
rP4: 0.5,
|
||||
ctcP6: 1800,
|
||||
};
|
||||
|
||||
/** A bar in the 확대기초 top layer, height from the 확대기초 상면 (mm, negative = below). */
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { PierModel } from '../geometry';
|
||||
import { barLength, bearingBlockRebar, DEFAULT_BLOCK_REBAR, totals } from './bearing-block';
|
||||
import { DEFAULT_COPING_REBAR } from './coping-settings';
|
||||
import { DEFAULT_COLUMN_REBAR } from './column-settings';
|
||||
import { bottomPiece, topBarLength, widthLayout, topSplicePieces } from './coping-main';
|
||||
import { shearBars, shearBarsMulti, copingSideBars, SIDE_HOOK_LEG, c14Bars, c14Length, stairBars, stepDevLength, undersideAt, shearULength, capLength, PIECES_PER_POSITION } from './coping';
|
||||
import { sideRowLevels } from '../coping-geom';
|
||||
@@ -147,6 +148,17 @@ export function linkedSpacing(name: string, model: PierModel): Pick<RebarRow, 's
|
||||
basis: basis(c.c14UpperSpacing !== d.c14UpperSpacing || c.c14LowerSpacing !== d.c14LowerSpacing),
|
||||
};
|
||||
}
|
||||
// 기둥 (승인 2026-10-26): P1·P2 등분 수, 주철근 커플러, 띠철근 P3·P5·P4, 크로스타이 P6.
|
||||
const k = model.columnRebar;
|
||||
const kd = DEFAULT_COLUMN_REBAR;
|
||||
if (name === 'P1' || name === 'P2') return { spacing: `원주 ${k.nDiv}등분`, actual: '—', basis: basis(k.nDiv !== kd.nDiv) };
|
||||
if (name === '주철근 커플러') {
|
||||
return { spacing: `@${k.ctcCoupler} (P2 +${k.dzCp2})`, actual: '—', basis: basis(k.ctcCoupler !== kd.ctcCoupler || k.dzCp2 !== kd.dzCp2) };
|
||||
}
|
||||
if (name === 'P3') return { spacing: String(k.ctcP3), actual: String(k.ctcP3), basis: basis(k.ctcP3 !== kd.ctcP3) };
|
||||
if (name === 'P5') return { spacing: String(k.ctcP5), actual: String(k.ctcP5), basis: basis(k.ctcP5 !== kd.ctcP5) };
|
||||
if (name === 'P4') return { spacing: String(k.ctcP4), actual: String(k.ctcP4), basis: basis(k.ctcP4 !== kd.ctcP4) };
|
||||
if (name === 'P6') return { spacing: String(k.ctcP6), actual: String(k.ctcP6), basis: basis(k.ctcP6 !== kd.ctcP6) };
|
||||
if (name === 'S1') return { spacing: String(b.spacingS1), actual: String(b.spacingS1), basis: basis(b.spacingS1 !== bd.spacingS1) };
|
||||
if (name === 'S2') return { spacing: String(b.spacingS2), actual: String(b.spacingS2), basis: basis(b.spacingS2 !== bd.spacingS2) };
|
||||
return undefined;
|
||||
@@ -257,11 +269,11 @@ export function rebarSummary(
|
||||
const col = columnRebar(columnInputFor(model), mColumn);
|
||||
rows.push({ member: 'column', name: 'P1', size: 'S32', count: col.mainP1, length: null, pieces: col.p1Pieces.map((length) => ({ length, count: col.mainP1 })), note: `외측 r ${col.r1}, 마디 ${col.p1Pieces.join(' / ')} (첫 마디에 갈고리 ${col.p1Hook}, 기둥철근.md §3.2)` });
|
||||
rows.push({ member: 'column', name: 'P2', size: 'S32', count: col.mainP2, length: null, pieces: col.p2Pieces.map((length) => ({ length, count: col.mainP2 })), note: `내측 r ${col.r2}, 마디 ${col.p2Pieces.join(' / ')}` });
|
||||
rows.push({ member: 'column', name: '주철근 커플러', size: 'D32용 (L150 Ø60)', count: col.couplers, length: 150, note: '@3000, P2는 +150 mm 상향 엇갈림' });
|
||||
rows.push({ member: 'column', name: '주철근 커플러', size: 'D32용 (L150 Ø60)', count: col.couplers, length: 150, note: `@${model.columnRebar.ctcCoupler}, P2는 +${model.columnRebar.dzCp2} mm 상향 엇갈림` });
|
||||
const tieCouplerCount = col.p5Count + col.p4Count * 2;
|
||||
rows.push({ member: 'column', name: '띠철근 커플러', size: 'D19용 (L100 Ø40)', count: tieCouplerCount, length: 100, note: `단부 P5 1개(${col.p5Count}) · 기초안 P4 2개(${col.p4Count * 2}) 폐합용` });
|
||||
rows.push({ member: 'column', name: 'P3', size: 'H19', count: col.p3Count, length: col.p3Length, note: `일반 구간 띠철근 @300, 겹침 ${col.lapP3} (추천안, Q-C6)` });
|
||||
rows.push({ member: 'column', name: 'P5', size: 'H19', count: col.p5Count, length: col.p5Length, note: '단부 띠철근 @120, 커플러 1개' });
|
||||
rows.push({ member: 'column', name: 'P3', size: 'H19', count: col.p3Count, length: col.p3Length, note: `일반 구간 띠철근 @${model.columnRebar.ctcP3}, 겹침 ${col.lapP3} (추천안, Q-C6)` });
|
||||
rows.push({ member: 'column', name: 'P5', size: 'H19', count: col.p5Count, length: col.p5Length, note: `단부 띠철근 @${model.columnRebar.ctcP5}, 커플러 1개` });
|
||||
rows.push({ member: 'column', name: 'P4', size: 'H19', count: col.p4Count, length: col.p4SemicircleLength * 2, note: '확대기초 안, 반원 2개 (길이는 반원 2개 합) · B11 간섭 무시' });
|
||||
rows.push({ member: 'column', name: 'P6', size: 'H16', count: col.p6Count, length: col.p6Length, note: '크로스타이, 8단 × 4' });
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { CopingRebarSettings, TopSpliceSettings } from './rebar/coping-settings';
|
||||
import type { ColumnRebarSettings } from './rebar/column-settings';
|
||||
|
||||
export type PierType = 'T형' | '2주형' | '3주형';
|
||||
export type FoundationType = '말뚝기초' | '직접기초' | '현장타설말뚝';
|
||||
@@ -80,6 +81,8 @@ export interface PierInput {
|
||||
copingRebar?: Partial<CopingRebarSettings>;
|
||||
/** 상면 주철근(C1–C6) 이음 (승인 2026-10-26). Absent = 이음 무시, 기둥 중심. */
|
||||
topSplice?: Partial<TopSpliceSettings>;
|
||||
/** 기둥 배근 입력 (승인 2026-10-26, 시안 ③ 기둥). Absent = the 기둥철근 (1).md defaults. */
|
||||
columnRebar?: Partial<ColumnRebarSettings>;
|
||||
strataRows?: StrataRow[];
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user