feat(ground): 지반·지층 card inputs, layer rows, water level, section drawing
- types/ground.ts: 위치 (육상·하상·해상), 지하수위 고려 and EL, 지층 행 (name and 하단 EL, from the top down). Checks G01 (layer order), G02 (water level range), G03 (layer name). - The 지반고 still feeds the soil cover check; the layer rows and water level are inputs and do not change the 3D model. - view/ground-svg.ts: the 삽도 drawn from the inputs and the generated footings and piles on one EL scale. - 일괄 적용 copies 위치 and 지하수위 to the checked piers (속성 복사 item, off by default). Changes list shows arrays and booleans as text. Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
0e70cfb969
commit
16ab317094
8 files changed
+400
-6
No files matched your search
+5
-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'] as const;
|
||||
export const TRACKED_KEYS = [...EDITABLE_FIELDS.map((f) => f.key), 'pileRows', 'groundPosition', 'groundWaterOn', 'groundWaterEl', 'strataRows'] as const;
|
||||
|
||||
export type EditableKey = (typeof TRACKED_KEYS)[number];
|
||||
|
||||
@@ -44,6 +44,10 @@ export const FIELD_LABELS: Record<EditableKey, string> = {
|
||||
pileLengthMm: '말뚝 길이',
|
||||
groundEl: '지반고 EL',
|
||||
pileRows: '열별 본수',
|
||||
groundPosition: '지반 위치',
|
||||
groundWaterOn: '지하수위 고려',
|
||||
groundWaterEl: '지하수위 EL',
|
||||
strataRows: '지층 행',
|
||||
};
|
||||
|
||||
/** Keys whose values differ between two inputs. Arrays are compared by value. */
|
||||
|
||||
+2
-1
@@ -5,7 +5,7 @@ import type { PierInput } from './types';
|
||||
* 속성 복사 (spec §9 · plan C7). Copies chosen attributes from one pier to others.
|
||||
* Values the spec never copies (coordinates, IP, elevations, names) are not in any item, so they cannot be copied.
|
||||
*/
|
||||
export type CopyItem = 'coping-width' | 'coping-length' | 'pile-length' | 'pile-rows';
|
||||
export type CopyItem = 'coping-width' | 'coping-length' | 'pile-length' | 'pile-rows' | 'ground-position';
|
||||
|
||||
interface ItemRule {
|
||||
label: string;
|
||||
@@ -21,6 +21,7 @@ export const COPY_ITEMS: Record<CopyItem, ItemRule> = {
|
||||
'coping-length': { label: '코핑 길이 L', keys: ['copingLengthMm'], defaultOn: false, pileItem: false },
|
||||
'pile-length': { label: '말뚝 길이', keys: ['pileLengthMm'], defaultOn: false, pileItem: true },
|
||||
'pile-rows': { label: '열별 본수', keys: ['pileRows'], defaultOn: false, pileItem: true },
|
||||
'ground-position': { label: '지반 위치·지하수위', keys: ['groundPosition', 'groundWaterOn', 'groundWaterEl'], defaultOn: false, pileItem: false },
|
||||
};
|
||||
|
||||
export const DEFAULT_COPY_ITEMS: CopyItem[] = (Object.keys(COPY_ITEMS) as CopyItem[]).filter((k) => COPY_ITEMS[k].defaultOn);
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import type { Issue, PierInput } from './types';
|
||||
|
||||
/** 위치 choices of the 지반·지층 card (시안 2026-10-26). */
|
||||
export const GROUND_POSITIONS = ['육상', '하상', '해상'] as const;
|
||||
|
||||
/** 지층 names, in the order of the RAG strata list (지반모델링계획). */
|
||||
export const STRATA_NAMES = ['매립토', '퇴적토', '풍화토', '풍화암', '연암', '경암'] as const;
|
||||
|
||||
/** The 지지층 for the pile tip check (지반 모델 G-7). */
|
||||
export const SUPPORT_STRATUM = '연암';
|
||||
|
||||
/**
|
||||
* 지반·지층 입력 검사 (승인 2026-10-26).
|
||||
* G01: 층 하단 EL은 위 경계보다 낮아야 함. G02: 지하수위는 지반고와 가장 아래 층 사이에 있어야 함.
|
||||
* G03: 층 이름은 지층 목록에 있어야 함. Ground values are inputs only; they do not change the 3D model.
|
||||
*/
|
||||
export function validateGround(input: PierInput, issues: Issue[]): void {
|
||||
const rows = input.strataRows ?? [];
|
||||
let upper = input.groundEl;
|
||||
rows.forEach((row, i) => {
|
||||
const label = `지층 ${i + 1}행 (${row.name})`;
|
||||
if (!(STRATA_NAMES as readonly string[]).includes(row.name)) {
|
||||
issues.push({ code: 'G03', level: 'W', pier: input.name, message: `${label}: 층 이름이 지층 목록에 없습니다.` });
|
||||
}
|
||||
if (!(row.bottomEl < upper)) {
|
||||
issues.push({ code: 'G01', level: 'W', pier: input.name, message: `${label}: 하단 EL ${row.bottomEl.toFixed(3)}이 위 경계 ${upper.toFixed(3)}보다 낮아야 합니다.` });
|
||||
}
|
||||
upper = row.bottomEl;
|
||||
});
|
||||
if (input.groundWaterOn) {
|
||||
const w = input.groundWaterEl;
|
||||
const lowest = rows.length ? rows[rows.length - 1].bottomEl : undefined;
|
||||
if (w === undefined || !Number.isFinite(w)) {
|
||||
issues.push({ code: 'G02', level: 'W', pier: input.name, message: '지하수위를 고려하지만 지하수위 EL이 없습니다.' });
|
||||
} else if (w > input.groundEl || (lowest !== undefined && w < lowest)) {
|
||||
issues.push({ code: 'G02', level: 'W', pier: input.name, message: `지하수위 EL ${w.toFixed(3)}이 지반고와 가장 아래 층 사이에 있지 않습니다.` });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -56,6 +56,20 @@ export interface PierInput {
|
||||
pileKind?: '강관' | 'PHC';
|
||||
/** 공통 규칙 for the solplate: centre thickness T, 솔플 여유 margin (mm), bearing height h3 (mm). */
|
||||
solplate?: { T: number; margin: number; h3: number };
|
||||
/** 지반·지층 (승인 2026-10-26): 위치, 지하수위 고려와 EL, 지층별 행 (위에서 아래, 행의 EL = 그 층의 하단 EL).
|
||||
* Absent = 육상, 지하수위 없음, 지층 행 없음. */
|
||||
groundPosition?: GroundPosition;
|
||||
groundWaterOn?: boolean;
|
||||
groundWaterEl?: number;
|
||||
strataRows?: StrataRow[];
|
||||
}
|
||||
|
||||
export type GroundPosition = '육상' | '하상' | '해상';
|
||||
|
||||
export interface StrataRow {
|
||||
name: string;
|
||||
/** 이 층의 하단 EL (m). */
|
||||
bottomEl: number;
|
||||
}
|
||||
|
||||
export type IssueLevel = 'E' | 'W' | 'I';
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { DIM, type PierModel } from './geometry';
|
||||
import type { Issue, PierInput, PierType } from './types';
|
||||
import { validateGround } from './ground';
|
||||
|
||||
const EXPECTED_COLUMNS: Record<PierType, number> = { 'T형': 1, '2주형': 2, '3주형': 3 };
|
||||
|
||||
@@ -89,4 +90,5 @@ export function validatePier(input: PierInput, model: PierModel, issues: Issue[]
|
||||
message: `받침블럭 높이 ${(minBlock * 1000).toFixed(0)} mm가 피복 + 철근 지름(${((cover + barDia) * 1000).toFixed(0)} mm)보다 작습니다. 블럭 철근은 코핑 안에 묻힙니다.`,
|
||||
});
|
||||
}
|
||||
validateGround(input, issues);
|
||||
}
|
||||
Reference in new issue
Block a user