feat(core): haunch-and-Level-300 coping underside, steel pile 609.6, W03/W04 checks

- Multi-column coping (2·3주형): underside between columns drops 300 below
  Level with 300 × 300 haunches (spec §4.5, Q3 추천안).
- Steel pipe pile diameter 609.6 mm (spec §4.5, Q5 추천안).
- Direct foundation keeps the 100 mm blinding concrete (Q4 추천안, test added).
- W03: bearing centre closer than half a block width to a step boundary.
- W04: block footprint outside the coping plan.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
ypshimandClaude Haiku 5.5 committed 2026-10-22 08:58:57 +09:00
1 parent 112f460f1f
commit 5466b3522e
3 files changed
+100 -7

No files matched your search

+28 -4
View File
@@ -6,11 +6,9 @@ const EXPECTED_COLUMNS: Record<PierType, number> = { 'T형': 1, '2주형': 2, '3
/** Rules from spec §10 that are not implemented in this stage. Shown to the user, never silently skipped. */
export const NOT_IMPLEMENTED_RULES = [
'E04 fck 미입력 (배근 단계, 3단계)',
'W03 받침 중심 ~ 계단 경계 < 블럭 폭/2',
'W04 블럭이 코핑 평면 밖',
'W06 속성 복사 건너뜀 (2단계)',
'W08 솔플레이트 T1−T2 검사 (2단계)',
'다주형 코핑 헌치·Level−300 (Q3), 일체기초 판정 (2·3주형)',
'일체기초 판정 (2·3주형)',
] as const;
/** Input-level checks (spec §10 E01, E02). Returns false when the pier must not be built. */
@@ -34,7 +32,7 @@ export function validateInput(input: PierInput, issues: Issue[]): boolean {
return ok;
}
/** Geometry-level checks (spec §10 W01, W02, W05, W07, I01) on a built model. */
/** Geometry-level checks (spec §10 W01–W05, W07, I01) on a built model. */
export function validatePier(input: PierInput, model: PierModel, issues: Issue[]): void {
const ip2Gap = Math.hypot(model.ip2Input.e - model.ip2Calc.e, model.ip2Input.n - model.ip2Calc.n);
if (ip2Gap > 0.001) {
@@ -49,6 +47,32 @@ export function validatePier(input: PierInput, model: PierModel, issues: Issue[]
if (minBlock <= 0) {
issues.push({ code: 'W02', level: 'W', pier: input.name, message: '받침블럭 콘크리트 높이가 0 이하입니다. 블럭을 생략합니다.' });
}
// W03: bearing centre closer than half a block width to a step boundary (interior boundaries only).
const halfBlock = DIM.blockSize / 2;
const stepBounds = model.segments.slice(1).map((seg) => seg.s0);
for (const b of model.bearings) {
const nearest = Math.min(...stepBounds.map((s) => Math.abs(b.s - s)));
if (nearest < halfBlock) {
issues.push({
code: 'W03',
level: 'W',
pier: input.name,
message: `${b.row} 받침 ${b.no}번 중심이 계단 경계에서 ${(nearest * 1000).toFixed(0)} mm 떨어져 블럭 폭의 절반(${(halfBlock * 1000).toFixed(0)} mm)보다 가깝습니다.`,
});
}
}
// W04: block footprint extends beyond the coping plan (s in [0, L], n in [−B/2, B/2]).
const planHalfB = model.copingB / 2;
const outside = model.blocks.some(
(b) =>
b.s - halfBlock < 0 ||
b.s + halfBlock > model.copingL ||
b.n - halfBlock < -planHalfB ||
b.n + halfBlock > planHalfB,
);
if (outside) {
issues.push({ code: 'W04', level: 'W', pier: input.name, message: '받침블럭이 코핑 평면 밖으로 나갑니다.' });
}
if (input.foundationType !== '현장타설말뚝' && model.footings.some((f) => f.top > input.groundEl)) {
issues.push({ code: 'W05', level: 'W', pier: input.name, message: '확대기초 상면이 지반고보다 높습니다.' });
}