- 이전 가정(받침 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>
58 lines
3.3 KiB
TypeScript
58 lines
3.3 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 { 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);
|
||
});
|
||
});
|