diff --git a/src/view/abut-scene.ts b/src/view/abut-scene.ts index 0823449..e90cbe2 100644 --- a/src/view/abut-scene.ts +++ b/src/view/abut-scene.ts @@ -21,6 +21,8 @@ const SLAB_LENGTH_M = 7; const SLAB_FALL = 0.04; /** 접속슬래브와 날개벽 안쪽면 사이 간격 (m), spec_abut §4.8 "날개벽 20". */ const SLAB_CLEARANCE_M = 0.02; +/** 말뚝 두부 매입 (m): the drawn pile head goes this far into the 저판 (drawing only). */ +const PILE_HEAD_EMBED_M = 0.1; /** Eight-corner slab with its top sloping away from the wall. Indexed by (s end, t end, bottom/top). Double-sided: the winding is not critical. */ function slabGeometry(plan: [number, number][], bottomEl: (s: number, t: number) => number): THREE.BufferGeometry { @@ -289,7 +291,9 @@ export function buildAbutGroup( // 말뚝: 원기둥 (지름 입력, 기본 D600) at each row, from the 기초 하단 down to the 선단. if (members.pileBottomEl !== undefined && footingBottom !== undefined) { - const height = footingBottom - members.pileBottomEl; + // The pile head runs PILE_HEAD_EMBED_M into the 저판, so its top cap is hidden inside the slab and does not z-fight + // with the 저판 bottom (the striped discs seen from below, 2026-11-04). The 선단 EL is unchanged. + const height = footingBottom + PILE_HEAD_EMBED_M - members.pileBottomEl; for (const row of members.piles) { for (const s of row.s) { // 말뚝 지름은 입력값 (QA-5). Each row moves along s with the skew, like the 저판 (시안: 열마다 skew만큼 밀림). diff --git a/tests/abut-footing.test.ts b/tests/abut-footing.test.ts index aa4bd4a..8bc5a32 100644 --- a/tests/abut-footing.test.ts +++ b/tests/abut-footing.test.ts @@ -56,4 +56,11 @@ describe('교대 확대기초 · 말뚝 (시안 ②, 3D)', () => { for (const s of ['1열 · 전면 · t +2150 · 6본', '2열 · t +850 · 6본', '3열 · 배면 · t −1150 · 6본', '4600 = 뒷굽쪽 650 · 2000 · 1300 · 650 전면', '교대축']) expect(svg).toContain(s); expect(svg.match(/ { + const { m, g } = group(); + const box = new THREE.Box3().setFromObject((g.getObjectByName('piles') as THREE.Group).children[0]); + expect(box.max.y).toBeCloseTo(m.footingBottomEl! + 0.1, 4); + expect(box.min.y).toBeCloseTo(m.pileBottomEl!, 4); + }); });