import { describe, it, expect } from 'vitest'; import { applyAlignment, projectSegments, imageToMachine, alignmentFromOrigin } from './transform'; import { estimatePolyWarp } from './polywarp'; import type { Vec2, Segment, Alignment, PolyWarp } from '../types'; const close = (a: Vec2, b: Vec2, eps = 1e-6) => Math.abs(a[0] - b[0]) < eps && Math.abs(a[1] - b[1]) < eps; // Identity warp: image == machine. A degree-1 fit on a non-degenerate quad is exact. const square: Vec2[] = [[0, 0], [10, 0], [10, 10], [0, 10]]; const IDENT: PolyWarp = estimatePolyWarp(square, square, 1); describe('transform', () => { it('applyAlignment rotates then translates', () => { const a: Alignment = { tx: 5, ty: 1, rot: Math.PI / 2 }; expect(close(applyAlignment(a, [1, 0]), [5, 2])).toBe(true); }); it('projectSegments applies alignment then the warp to every point', () => { const segs: Segment[] = [{ kind: 'cut', points: [[0, 0], [10, 0]] }]; const a: Alignment = { tx: 2, ty: 3, rot: 0 }; const out = projectSegments(segs, a, IDENT); expect(out[0]!.kind).toBe('cut'); expect(close(out[0]!.points[0]!, [2, 3])).toBe(true); expect(close(out[0]!.points[1]!, [12, 3])).toBe(true); }); it('imageToMachine inverts the warp', () => { // Warp scales machine→image by 0.5 (offset 0): machine (4,8) → image (2,4). const m: Vec2[] = [[0, 0], [10, 0], [10, 10], [0, 10]]; const img: Vec2[] = m.map((p): Vec2 => [p[0] * 0.5, p[1] * 0.5]); const w = estimatePolyWarp(m, img, 1); expect(close(imageToMachine(w, [2, 4]), [4, 8], 1e-4)).toBe(true); }); it('alignmentFromOrigin places work-origin at the given machine point', () => { const a = alignmentFromOrigin([7, 9], 0); expect(close(applyAlignment(a, [0, 0]), [7, 9])).toBe(true); }); });