GCodeOverlay/src/geometry/homography.test.ts

32 lines
1.3 KiB
TypeScript
Raw Normal View History

import { describe, it, expect } from 'vitest';
import { estimateHomography, applyHomography, invertMat3 } from './homography';
import type { Vec2, Mat3 } 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;
describe('homography', () => {
it('recovers the identity from coincident point sets', () => {
const pts: Vec2[] = [[0, 0], [1, 0], [1, 1], [0, 1]];
const H = estimateHomography(pts, pts);
expect(close(applyHomography(H, [0.3, 0.7]), [0.3, 0.7])).toBe(true);
});
it('recovers a known perspective transform', () => {
const H: Mat3 = [1.1, 0.2, 5, -0.1, 0.9, 3, 0.001, 0.002, 1];
const src: Vec2[] = [[0, 0], [100, 0], [100, 100], [0, 100], [40, 60]];
const dst = src.map((p) => applyHomography(H, p));
const est = estimateHomography(src, dst);
for (const p of [[10, 20], [70, 30], [55, 90]] as Vec2[]) {
expect(close(applyHomography(est, p), applyHomography(H, p), 1e-4)).toBe(true);
}
});
it('invertMat3 round-trips a point', () => {
const H: Mat3 = [1.1, 0.2, 5, -0.1, 0.9, 3, 0.001, 0.002, 1];
const inv = invertMat3(H);
const p: Vec2 = [37, 91];
expect(close(applyHomography(inv, applyHomography(H, p)), p, 1e-6)).toBe(true);
});
});