spec_abut §3 · §4.9 (QA-7 가정)와 맞지 않던 세 가지를 고친다. - 위치: 등분점(1개면 L/2)이 아니라 가장 가까운 '받침 사이 중간'(= 교좌면 계단 경계). 이전에는 운곡교 교대 5기 모두 줄눈이 가운데 받침 ③ 블럭을 지났다 (A1: 줄눈 6.099 · 받침 6.037). 이제 A1은 IP3에서 4.905 m - 개수: 입력이 없으면 ceil(L/10) − 1 (길이에 따라 자동, 이전에는 1 고정). 입력 칸은 비우면 자동 - 3D: 벽체 전면 · 흉벽 전면 · 벽체 배면 · 흉벽 배면에 선으로 표시(저판은 연속이라 없음), '벽체·흉벽' 토글을 따름 - 공통 계산 core/abut/joints.ts를 ② 정면·배면 삽도, 교대 상세 요약, 입력 칸 안내, 3D가 함께 씀 - 테스트: 개수 규칙, A1 위치 = ②·③ 중간 = 계단 경계, 여러 개 · 받침 부족 시 등분, 3D 선 4면 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
59 lines
2.8 KiB
TypeScript
59 lines
2.8 KiB
TypeScript
import { jointPositions } from '../src/core/abut/joints';
|
|
import { readFileSync } from 'node:fs';
|
|
import { fileURLToPath } from 'node:url';
|
|
import * as XLSX from 'xlsx';
|
|
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 { abutWallElevationSvg, abutWallSectionSvg, type AbutWallDrawing } from '../src/view/abut-wall-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 m = buildMembers(model, { bottomEl: input.foundationBottomEl, pileLengthMm: input.pileLengthMm });
|
|
const d: AbutWallDrawing = {
|
|
lengthM: model.length,
|
|
segments: m.wallSegments,
|
|
bearings: model.bearings,
|
|
footingTopEl: m.footingTopEl,
|
|
footingBottomEl: m.footingBottomEl!,
|
|
parapetTopStartEl: m.parapetTopStartEl,
|
|
parapetTopEndEl: m.parapetTopEndEl,
|
|
wallFrontM: m.shape.wallFrontM,
|
|
parapetBackM: m.shape.parapetBackM,
|
|
wallBackM: m.shape.wallBackM,
|
|
footingFrontM: m.shape.footingFrontM,
|
|
footingBackM: m.shape.footingBackM,
|
|
bracketHeightM: m.shape.bracketHeightM,
|
|
shrinkJointsS: jointPositions(model.length, model.bearings.map((b) => b.s)),
|
|
bracketWidthMm: 300,
|
|
parapetThicknessMm: 500,
|
|
seatWidthMm: 1600,
|
|
};
|
|
|
|
describe('교대 벽체·흉벽 삽도 (시안 ② 벽체·흉벽 카드)', () => {
|
|
it('단면 (① 구간): the width line and the levels of the generated model', () => {
|
|
const svg = abutWallSectionSvg(d);
|
|
for (const s of ['300 + 500 + 1600 = 2400', '교좌면 EL.44.367', '벽체 2.372', '상면 EL.41.995', '기초 하단 EL.40.895', '교대축', '← 배면', '전면 →']) {
|
|
expect(svg).toContain(s);
|
|
}
|
|
expect(svg).toMatch(/흉벽 상단 EL\.4[78]\.\d{3}/);
|
|
expect(svg).toMatch(/브라켓 상면 EL\.4[56]\.\d{3}/);
|
|
});
|
|
|
|
it('정면·배면도: five steps, five bearings, the sloped 흉벽 top (IP3 47.661 → IP1 48.006) and the 수축줄눈', () => {
|
|
const svg = abutWallElevationSvg(d);
|
|
for (const s of ['IP3', 'IP1', `${model.length.toFixed(3)} m`, '수축줄눈 1', 'EL.47.661', 'EL.48.006', '①', '⑤']) expect(svg).toContain(s);
|
|
expect(svg).toContain('H_w 3326'); // 받침 ① 기준선의 벽체 높이 (사용자 도면 2026-11-04)
|
|
expect(svg).toContain('교좌면 계단 5구간');
|
|
});
|
|
|
|
it('the 수축줄눈 count follows the input', () => {
|
|
const svg = abutWallElevationSvg({ ...d, shrinkJointsS: jointPositions(model.length, model.bearings.map((b) => b.s), 2) });
|
|
expect(svg).toContain('수축줄눈 2');
|
|
expect(svg.match(/stroke-dasharray="5 3"/g)).toHaveLength(2);
|
|
});
|
|
});
|