- 말뚝 윗면이 저판 바닥·버림 윗면과 같은 높이에 있어, 아래에서 보면 원 안에 줄무늬가 생겼음 - 그리는 말뚝 머리를 저판 안으로 0.1 m 넣어 윗면이 저판 속에 숨도록 함. 선단 EL은 그대로 - 테스트 1건 추가. 전체 662건 통과, 타입 검사 · 빌드 통과 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
67 lines
3.5 KiB
TypeScript
67 lines
3.5 KiB
TypeScript
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);
|
||
});
|
||
});
|