feat(abut): ② 확대기초 · 말뚝 카드를 시안대로 작성 (평면 삽도, 버림, 열별 본수)

- 선택: 평면 skew 평행사변형(기본) / 직사각(비활성, 다음 단계), 말뚝 원기둥 D600 / 강관 · PHC(비활성, 규칙 미정)
- 평면 삽도 (src/view/abut-footing-svg.ts): 저판, 벽체 윤곽, 교대축, 말뚝 3열(skew만큼 밀림), 열 위치 · 본수, 폭 치수
- 입력: 폭 4600, 두께 1100, 앞굽 1200 (뒷굽 자동 1000), 버림 여유 · 두께 100 / 100, 말뚝 지름 600 (QA-5), 연단 650, 본수 규칙 간격 2000
- 열 위치 "650 · 2000 · 1300 · 650" 입력 (전면 연단 자동, 합 = 폭 검사), 열별 말뚝 본수 표 − / + (0 = 본수 규칙)
- 자동 값: 뒷굽, 길이(교좌면 길이), 말뚝 길이(①에서 수정), 선단 EL, 본수 규칙 문구. 시안 메모
- 3D: 교대 버림을 저판 아래에 그림 (부재 표시 "버림" 토글 적용), 말뚝 지름 입력 반영, 말뚝 열을 skew만큼 s 방향으로 밀어 배치
- 예전 저장 파일의 앞굽 끝 · 뒷굽 끝은 폭 · 앞굽으로 바꿔 읽음
- 테스트 추가 · 갱신. 전체 661건 통과, 타입 검사 · 빌드 통과. 브라우저 시각 확인은 미실시

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ypshimandClaude Opus 5.5 committed 2026-11-04 08:46:58 +09:00
1 parent 55b679932e
commit 372d759eb7
10 files changed
+425 -46

No files matched your search

+26 -4
View File
@@ -12,7 +12,7 @@ import { buildWings, HAUNCH_LEG_M, WING_THICKNESS_M, type WingSolid } from '../c
import type { TerrainGrid } from '../core/ground-model';
import { terrainGeometry } from './terrain';
export const ABUT_GROUP_NAMES = ['wall', 'parapet', 'footing', 'piles', 'wings', 'haunches', 'ground', 'blocks', 'slab'] as const;
export const ABUT_GROUP_NAMES = ['wall', 'parapet', 'footing', 'blinding', 'piles', 'wings', 'haunches', 'ground', 'blocks', 'slab'] as const;
/** 접속슬래브 두께 (m), spec_abut §4.8. */
const SLAB_THICKNESS_M = 0.45;
/** 접속슬래브 길이 (배면 쪽, m), spec_abut §4.8 "7000 (날개벽 축 방향)". */
@@ -118,6 +118,12 @@ function wingDirectionAxis(model: AbutModel): { ws: number; wt: number } {
return { ws: w.e * model.u.e + w.n * model.u.n, wt: w.e * front.e + w.n * front.n };
}
/** Skew of the plan (s per m of t along the wing), the same one the 저판 · 벽체 · 말뚝 열 use. */
export function abutSkewK(model: AbutModel): number {
const d = wingDirectionAxis(model);
return d.ws / d.wt;
}
/**
* Placement of the abutment in the pier scene (2026-11-03). The pier scene maps (E, N, EL) to
* (E − pivot.E, EL, −(N − pivot.N)); the abutment's local (s, t, EL) → (E, N) with s along u and t along the front
@@ -220,6 +226,20 @@ export function buildAbutGroup(
[skewK * members.shape.footingFrontM, members.shape.footingFrontM],
];
add('footing', prism(footProfile, members.shape.footingThicknessM, new THREE.Vector3(0, footingBottom, 0), ex, ez, ey), 0x5a6a78);
// 버림 (2026-11-04): under the 저판, wider by the 여유 on every side, the same skew.
const m = members.shape.blindingMarginM;
const th = members.shape.blindingThicknessM;
if (th > 0) {
const tb = members.shape.footingBackM - m;
const tf = members.shape.footingFrontM + m;
const blindProfile: [number, number][] = [
[skewK * tb - m, tb],
[L + skewK * tb + m, tb],
[L + skewK * tf + m, tf],
[skewK * tf - m, tf],
];
add('blinding', prism(blindProfile, th, new THREE.Vector3(0, footingBottom - th, 0), ex, ez, ey), 0x9aa29a);
}
}
// 받침블럭 (spec §4.2, §6.6): concrete 1200 × 1200 from the 교좌면 to 50 below z, and the 몰탈패드 1000 × 1000 × 50 up to z.
@@ -267,13 +287,15 @@ export function buildAbutGroup(
slabGroup.add(slabMesh);
root.add(slabGroup);
// 말뚝: D 600 (r 0.3) at each row and bar, from the 기초 하단 down to the 선단.
// 말뚝: 원기둥 (지름 입력, 기본 D600) at each row, from the 기초 하단 down to the 선단.
if (members.pileBottomEl !== undefined && footingBottom !== undefined) {
const height = footingBottom - members.pileBottomEl;
for (const row of members.piles) {
for (const s of row.s) {
const geom = new THREE.CylinderGeometry(0.3, 0.3, height, 16);
geom.translate(s, members.pileBottomEl + height / 2, row.t);
// 말뚝 지름은 입력값 (QA-5). Each row moves along s with the skew, like the 저판 (시안: 열마다 skew만큼 밀림).
const r = members.shape.pileDiameterM / 2;
const geom = new THREE.CylinderGeometry(r, r, height, 16);
geom.translate(s + skewK * row.t, members.pileBottomEl + height / 2, row.t);
add('piles', geom, 0x7d8b99);
}
}