Files
Pier_v1/tests/axis.test.ts
T

100 lines
4.1 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 { describe, expect, it } from 'vitest';
import { DIM, solveIp4 } from '../src/core/geometry';
import { buildAxis, copingSpan, fromAxis, kinkArc, nearKink, toAxis } from '../src/core/axis';
import type { PierInput } from '../src/core/types';
import { loadP1 } from './helpers';
const pt = (p: PierInput['ips'][number]) => ({ e: p.x, n: p.y });
const ip = (p: PierInput, name: string) => pt(p.ips.find((q) => q.name === name)!);
describe('straight axis (regression against spec §12)', () => {
const p1 = loadP1();
const axis = buildAxis(ip(p1, 'IP1'), ip(p1, 'IP3'), null);
const bp1 = copingSpan(axis, p1.copingLengthMm / 1000).sStart;
it('bearing s and n relative to BP1 match spec §12', () => {
const front = p1.bearings.filter((b) => b.row === '전열').sort((a, b) => a.no - b.no);
const back = p1.bearings.filter((b) => b.row === '후열').sort((a, b) => a.no - b.no);
const fs = front.map((b) => toAxis(axis, { e: b.x, n: b.y }));
const bs = back.map((b) => toAxis(axis, { e: b.x, n: b.y }));
expect(fs[0].s - bp1).toBeCloseTo(0.943, 3);
expect(fs[fs.length - 1].s - bp1).toBeCloseTo(10.965, 3);
expect(bs[0].s - bp1).toBeCloseTo(1.029, 3);
expect(bs[bs.length - 1].s - bp1).toBeCloseTo(11.05, 3);
expect(fs[0].n).toBeCloseTo(-0.698, 3);
expect(bs[0].n).toBeCloseTo(0.6, 3);
});
it('straight axis: every point is on stretch 0 and round-trips', () => {
for (const b of p1.bearings) {
const p = { e: b.x, n: b.y };
const q = toAxis(axis, p);
expect(q.k).toBe(0);
const back = fromAxis(axis, q);
expect(back.e).toBeCloseTo(p.e, 9);
expect(back.n).toBeCloseTo(p.n, 9);
}
});
});
// Synthetic bend: IP1 (0, 0), IP2 (1, 0), kink (7, 0), IP3 (9, −3.464), a 60° right turn with IP3 ahead on the turned line.
// The P1 sheet is straight (IP1, IP2, IP3 collinear), so P1 cannot exercise a bend.
describe('bent axis IP1 → IP4 → IP3', () => {
const p1 = loadP1();
const ip1 = { e: 0, n: 0 };
const ip2 = { e: 1, n: 0 };
const ip3 = { e: 9, n: -3.4641016 };
const kink = solveIp4(ip1, ip2, ip3, 60)!;
const axis = buildAxis(ip1, ip3, kink);
const a = kinkArc(axis)!;
it('kink lies on the IP1→IP2 line, at s = 7, and the arc length adds the two stretches', () => {
const cross = (kink.e - ip1.e) * (ip2.n - ip1.n) - (kink.n - ip1.n) * (ip2.e - ip1.e);
expect(cross).toBeCloseTo(0, 9);
expect(a).toBeCloseTo(7, 6);
const len2 = Math.hypot(ip3.e - kink.e, ip3.n - kink.n);
expect(axis.length).toBeCloseTo(a + len2, 9);
});
it('the kink is the continuity point: s = a on both stretches at n = 0', () => {
const from0 = fromAxis(axis, { k: 0, s: a, n: 0 });
const from1 = fromAxis(axis, { k: 1, s: a, n: 0 });
expect(from0.e).toBeCloseTo(kink.e, 9);
expect(from0.n).toBeCloseTo(kink.n, 9);
expect(from1.e).toBeCloseTo(kink.e, 9);
expect(from1.n).toBeCloseTo(kink.n, 9);
});
it('every bearing keeps its input world coordinates through toAxis → fromAxis', () => {
for (const b of p1.bearings) {
const p = { e: b.x, n: b.y };
const back = fromAxis(axis, toAxis(axis, p));
expect(back.e).toBeCloseTo(p.e, 9);
expect(back.n).toBeCloseTo(p.n, 9);
}
});
it('a point just before the mitre plane is on stretch 0, just after it on stretch 1', () => {
const u1 = axis.segments[0].u;
const u2 = axis.segments[1].u;
const before = { e: kink.e - 0.01 * u1.e, n: kink.n - 0.01 * u1.n };
const after = { e: kink.e + 0.01 * u2.e, n: kink.n + 0.01 * u2.n };
expect(toAxis(axis, before).k).toBe(0);
expect(toAxis(axis, after).k).toBe(1);
});
it('coping centred on the axis: span is L_IP/2 ± L/2 and the kink lies inside it', () => {
const L = 6;
const span = copingSpan(axis, L);
expect(span.sStart).toBeCloseTo(axis.length / 2 - L / 2, 9);
expect(span.sStart < a && a < span.sEnd).toBe(true);
});
it('columns within the Level half-width of the kink are reported', () => {
const half = DIM.levelWidth / 2;
const columns = [a - 0.5, a + 5];
expect(nearKink(axis, columns, half)).toEqual([a - 0.5]);
expect(nearKink(axis, [a + 5], half)).toEqual([]);
});
});