Files
Pier_v1/tests/abut-footing.test.ts
ypshimandClaude Opus 5.5 4eb92d381d fix(abut): 말뚝 머리를 저판 안으로 100 mm 넣어 바닥면 줄무늬(z-fighting) 제거
- 말뚝 윗면이 저판 바닥·버림 윗면과 같은 높이에 있어, 아래에서 보면 원 안에 줄무늬가 생겼음
- 그리는 말뚝 머리를 저판 안으로 0.1 m 넣어 윗면이 저판 속에 숨도록 함. 선단 EL은 그대로
- 테스트 1건 추가. 전체 662건 통과, 타입 검사 · 빌드 통과

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-04 08:53:46 +09:00

67 lines
3.5 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { readFileSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import * as XLSX from 'xlsx';
import * as THREE from 'three';
import { describe, expect, it } from 'vitest';
import { buildAbut } from '../src/core/abut/geometry';
import { parseAbutments, toAbutInput } from '../src/core/abut/parse';
import { buildMembers } from '../src/core/abut/members';
import { buildWings } from '../src/core/abut/wings';
import { abutSkewK, buildAbutGroup } from '../src/view/abut-scene';
import { abutFootingPlanSvg } from '../src/view/abut-footing-svg';
const RAG = fileURLToPath(new URL('../../../RAG/운곡교P1입력.xlsx', import.meta.url));
const rec = parseAbutments(XLSX.read(readFileSync(RAG), { type: 'buffer' })).abutments[0];
const input = toAbutInput(rec);
const model = buildAbut(input);
const group = (changes = {}) => {
const m = buildMembers(model, { bottomEl: input.foundationBottomEl, pileLengthMm: input.pileLengthMm }, changes);
return { m, g: buildAbutGroup(model, m, buildWings(model, m)) };
};
describe('교대 확대기초 · 말뚝 (시안 ②, 3D)', () => {
it('draws the 버림 under the 저판: 100 thick, 100 wider on each side', () => {
const { m, g } = group();
const blind = new THREE.Box3().setFromObject(g.getObjectByName('blinding') as THREE.Object3D);
const foot = new THREE.Box3().setFromObject(g.getObjectByName('footing') as THREE.Object3D);
expect(blind.max.y).toBeCloseTo(m.footingBottomEl!, 4); // float32 vertices
expect(blind.max.y - blind.min.y).toBeCloseTo(0.1, 4);
expect(foot.min.z - blind.min.z).toBeCloseTo(0.1, 4);
expect(blind.max.z - foot.max.z).toBeCloseTo(0.1, 4);
});
it('no 버림 when its thickness is 0', () => {
expect(group({ blindingThicknessMm: 0 }).g.getObjectByName('blinding')).toBeUndefined();
});
it('the piles follow the 지름 input and shift with the skew row by row', () => {
const { m, g } = group({ pileDiameterMm: 800 });
const piles = (g.getObjectByName('piles') as THREE.Group).children;
expect(piles).toHaveLength(18);
const box = new THREE.Box3().setFromObject(piles[0]);
expect(box.max.x - box.min.x).toBeCloseTo(0.8, 2);
const k = abutSkewK(model);
const row = m.piles[0];
expect((box.min.x + box.max.x) / 2).toBeCloseTo(row.s[0] + k * row.t, 6);
});
it('평면 삽도: the rows, their t and counts, and the width line', () => {
const { m } = group();
const svg = abutFootingPlanSvg({
lengthM: model.length, skewK: abutSkewK(model), footingFrontM: m.shape.footingFrontM, footingBackM: m.shape.footingBackM,
wallFrontM: m.shape.wallFrontM, wallBackM: m.shape.wallBackM,
rows: m.piles.map((r, i) => ({ t: r.t, s: r.s, name: ['3열 · 배면', '2열', '1열 · 전면'][i] })),
pileDiameterM: m.shape.pileDiameterM, rowDimsMm: [650, 2000, 1300, 650], footingWidthMm: 4600,
});
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(/<circle /g)).toHaveLength(18);
});
it('the pile head sits 100 mm inside the 저판 (no top cap on the 저판 bottom face), the 선단 stays at the 선단 EL', () => {
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);
});
});