Files
Pier_v1/tests/abut-bearing-azimuth.test.ts
T
ypshimandClaude Opus 5.5 6b969f4a7c fix(abut): 교대 받침 공통 규칙을 교각 솔플레이트 규칙 형식으로 변경
- 이전 가정(받침 A×B 700×640, h3 181, T 30, 여유 100)을 없애고, 교각과 같은 솔플레이트 규칙(src/core/solplate-rule.ts)을 씀 (결정 2026-11-03: 교각 규칙을 기본값으로)
- 입력: 솔플레이트 교직 L 1000, 교축 W 1100, 종단 기울기 S −0.5 %. 받침높이 H는 교대 받침 시트 값(A1 275 mm)으로 고정
- 계산: T = ⌈22 + L·|S|/200⌉ = 25, h3 = H − T = 250, T1 27.5 / T2 22.5, E = 400. 교각 카드와 같은 안내 줄 표시
- 받침 종류 · 용량 입력은 유지. ELEVATION TABLE의 A·B 열 삭제, 삽도는 솔플레이트 L × W 기준
- 테스트 갱신. 전체 651건 통과, 타입 검사·빌드 통과. 브라우저 시각 확인은 미실시

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 18:37:17 +09:00

58 lines
3.3 KiB
TypeScript
Raw 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 { bearingRotDeg, 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 { buildAbutGroup } from '../src/view/abut-scene';
import { abutElevationRows, resolveBearingRule } from '../src/core/abut/bearing-table';
const RAG = fileURLToPath(new URL('../../../RAG/운곡교P1입력.xlsx', import.meta.url));
const rec = parseAbutments(XLSX.read(readFileSync(RAG), { type: 'buffer' })).abutments[0];
const model = buildAbut(toAbutInput(rec));
describe('교대 받침 방위각 (엑셀 받침 시트 6번째 열)', () => {
it('reads the 방위각 of every bearing (75°56′55.9″ … 75°58′08.4″ in the workbook frame)', () => {
expect(rec.bearings.every((b) => b.azimuthDeg !== undefined && Number.isFinite(b.azimuthDeg))).toBe(true);
// model-xy = 90 − workbook value: 75.94886° → 14.05114°
expect(rec.bearings.find((b) => b.no === 1)!.azimuthDeg).toBeCloseTo(90 - (75 + 56 / 60 + 55.9 / 3600), 6);
});
it('turns each block like the pier rule (≈ 4.42° from the axis normal); against the wing (skew) line the rest is 0.63° (시안 AW01)', () => {
const front = { e: model.nLeft.e * model.frontSide, n: model.nLeft.n * model.frontSide };
// 날개벽 방향: CAD 각 lineDeg → 진북 = 90 − CAD (시안: 진북 194.68°, CAD 255.32°).
const wingRot = bearingRotDeg(90 - model.wing!.lineDeg, model.u, front);
for (const b of model.bearings) {
expect(Math.abs(b.rotDeg)).toBeGreaterThan(4.3);
expect(Math.abs(b.rotDeg)).toBeLessThan(4.5);
}
const first = model.bearings.find((b) => b.no === 1)!;
expect(Math.abs(first.rotDeg - wingRot)).toBeCloseTo(0.63, 1);
});
it('without the 방위각 the blocks stay on the axis (rotation 0)', () => {
const flat = buildAbut({ ...toAbutInput(rec), bearings: toAbutInput(rec).bearings.map((b) => ({ ...b, azimuthDeg: undefined })) });
expect(flat.bearings.every((b) => b.rotDeg === 0)).toBe(true);
});
it('the 3D block turns with the bearing: its footprint is no longer axis-aligned', () => {
const input = toAbutInput(rec);
const members = buildMembers(model, { bottomEl: input.foundationBottomEl, pileLengthMm: input.pileLengthMm });
const group = buildAbutGroup(model, members, buildWings(model, members));
const block = (group.getObjectByName('blocks') as THREE.Group).children[0] as THREE.Mesh;
const box = new THREE.Box3().setFromObject(block);
// a turned 1.2 m square is wider than 1.2 m along s
expect(box.max.x - box.min.x).toBeGreaterThan(1.2 + 1e-4);
});
it('the ELEVATION table shows the 방위각 (CAD = the workbook value, 진북) and the block turn', () => {
const [r] = abutElevationRows(model, resolveBearingRule(), rec.bearingHeightMm).filter((x) => x.no === 1);
expect(r.azimuthCadDeg).toBeCloseTo(75 + 56 / 60 + 55.9 / 3600, 6);
expect(r.azimuthNorthDeg).toBeCloseTo(90 - (75 + 56 / 60 + 55.9 / 3600), 6);
expect(r.rotDeg).toBeCloseTo(model.bearings.find((b) => b.no === 1)!.rotDeg, 9);
});
});