deckhearth/test/lib/scanner-card-warp.test.js

94 lines
2.3 KiB
JavaScript
Raw Normal View History

import { describe, expect, it } from 'vitest';
import {
boundsFromCorners,
computeHomography,
isValidCardQuad,
orderQuadCorners,
} from '../../lib/scanner-card-warp.js';
describe('orderQuadCorners', () => {
it('orders corners as top-left, top-right, bottom-right, bottom-left', () => {
const points = [
{ x: 10, y: 10 },
{ x: 90, y: 12 },
{ x: 88, y: 140 },
{ x: 12, y: 138 },
];
expect(orderQuadCorners(points)).toEqual([
{ x: 10, y: 10 },
{ x: 90, y: 12 },
{ x: 88, y: 140 },
{ x: 12, y: 138 },
]);
});
});
describe('boundsFromCorners', () => {
it('returns the enclosing axis-aligned rectangle', () => {
const corners = [
{ x: 10, y: 20 },
{ x: 110, y: 25 },
{ x: 105, y: 165 },
{ x: 15, y: 160 },
];
expect(boundsFromCorners(corners)).toEqual({
x: 10,
y: 20,
width: 100,
height: 145,
});
});
});
describe('isValidCardQuad', () => {
it('accepts a convex card-shaped quad', () => {
const corners = [
{ x: 0, y: 0 },
{ x: 50, y: 0 },
{ x: 50, y: 70 },
{ x: 0, y: 70 },
];
expect(isValidCardQuad(corners)).toBe(true);
});
it('rejects a quad with implausible aspect ratio', () => {
const corners = [
{ x: 0, y: 0 },
{ x: 200, y: 0 },
{ x: 200, y: 70 },
{ x: 0, y: 70 },
];
expect(isValidCardQuad(corners)).toBe(false);
});
});
describe('computeHomography', () => {
it('maps source corners to the destination rectangle', () => {
const src = [
{ x: 0, y: 0 },
{ x: 100, y: 0 },
{ x: 100, y: 140 },
{ x: 0, y: 140 },
];
const matrix = computeHomography(src, 200, 280);
const mappedTopLeft = applyForward(matrix, 0, 0);
expect(mappedTopLeft.x).toBeCloseTo(0, 4);
expect(mappedTopLeft.y).toBeCloseTo(0, 4);
const mappedBottomRight = applyForward(matrix, 100, 140);
expect(mappedBottomRight.x).toBeCloseTo(200, 4);
expect(mappedBottomRight.y).toBeCloseTo(280, 4);
});
});
function applyForward(matrix, x, y) {
const denom = matrix[2][0] * x + matrix[2][1] * y + matrix[2][2];
return {
x: (matrix[0][0] * x + matrix[0][1] * y + matrix[0][2]) / denom,
y: (matrix[1][0] * x + matrix[1][1] * y + matrix[1][2]) / denom,
};
}