57 lines
2.9 KiB
TypeScript
57 lines
2.9 KiB
TypeScript
import { readFileSync, readdirSync } from 'node:fs';
|
|
import { fileURLToPath } from 'node:url';
|
|
import * as XLSX from 'xlsx';
|
|
import { describe, expect, it } from 'vitest';
|
|
import { swapXYAzimuth } from '../src/core/coordinate-frame';
|
|
import { parseWorkbook } from '../src/core/parseWorkbook';
|
|
import { buildPier } from '../src/core/geometry';
|
|
import { parseProject, serializeProject, SCHEMA_VERSION, type ProjectFile } from '../src/core/project';
|
|
import { loadP1 } from './helpers';
|
|
|
|
describe('bearing position / direction coordinate agreement', () => {
|
|
it('reflects the direction vector with the exchanged coordinate axes', () => {
|
|
for (const angle of [0, 45, 90, 153.200861111, 180, 270, 350, -30, 720]) {
|
|
const original = angle * Math.PI / 180;
|
|
const converted = swapXYAzimuth(angle) * Math.PI / 180;
|
|
expect(Math.sin(converted)).toBeCloseTo(Math.cos(original), 12);
|
|
expect(Math.cos(converted)).toBeCloseTo(Math.sin(original), 12);
|
|
}
|
|
expect(swapXYAzimuth(NaN)).toBeNaN();
|
|
});
|
|
|
|
it('keeps every real Sanwoe bearing approximately aligned with its coping', () => {
|
|
const dir = fileURLToPath(new URL('../pierzainer_ground/', import.meta.url));
|
|
const name = readdirSync(dir).find((name) => name.includes('산외교') && name.endsWith('.xlsx'))!;
|
|
const { piers, issues } = parseWorkbook(XLSX.read(readFileSync(`${dir}/${name}`), { type: 'buffer' }));
|
|
expect(issues).toEqual([]);
|
|
expect(piers).toHaveLength(7);
|
|
for (const input of piers) {
|
|
const model = buildPier(input);
|
|
expect(model.blocks).toHaveLength(4);
|
|
for (const block of model.blocks) expect(Math.abs(block.rowSkewDeg), `${input.name}/${block.no}`).toBeLessThan(0.03);
|
|
}
|
|
expect(piers[0].bearings[0].azimuthDeg).toBeCloseTo(296.799138889, 8);
|
|
});
|
|
|
|
it('migrates legacy input/defaults/draft once, including backup-style project round trips', () => {
|
|
const normalized = loadP1();
|
|
const legacy = structuredClone(normalized);
|
|
delete legacy.bearingAzimuthFrame;
|
|
legacy.bearings = legacy.bearings.map((b) => ({ ...b, azimuthDeg: swapXYAzimuth(b.azimuthDeg) }));
|
|
const file: ProjectFile = {
|
|
schemaVersion: SCHEMA_VERSION,
|
|
project: { name: '', bridge: '', client: '', author: '', crs: '', memo: '' },
|
|
source: { fileName: 'legacy.xlsx', sheets: [] },
|
|
piers: [{ id: 'P1', input: legacy, defaults: structuredClone(legacy), draft: structuredClone(legacy) }], history: [],
|
|
};
|
|
const opened = parseProject(JSON.stringify(file));
|
|
for (const input of [opened.piers[0].input, opened.piers[0].defaults!, opened.piers[0].draft!]) {
|
|
expect(input.bearingAzimuthFrame).toBe('model-xy');
|
|
input.bearings.forEach((b, i) => expect(b.azimuthDeg).toBeCloseTo(normalized.bearings[i].azimuthDeg, 10));
|
|
expect(input.ips).toEqual(normalized.ips);
|
|
}
|
|
expect(parseProject(serializeProject(opened))).toEqual(opened);
|
|
expect(legacy.bearingAzimuthFrame).toBeUndefined();
|
|
});
|
|
});
|