Files
SlabUploader/frontend/src/png/rotateCal.test.ts
T
grokbot_ty 4ea2618475 fix(overlay): Photos-ready dims follow tape, not wood MAR
After rotateCalibration, map tape tick A→B through bakeTiltTransform into
baked cal coords, orient overlay bbox with orientedRect(..., tapeAngle), and
pass optional axis into buildOverlayPlan so length || tape and widths ⊥ tape.
2026-09-26 08:08:21 -07:00

57 lines
2.4 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 { test } from 'node:test';
import assert from 'node:assert/strict';
import { bakeTiltTransform } from './rotateCal.ts';
test('bakeTiltTransform: identity ≈0° leaves points and size unchanged', () => {
const x = bakeTiltTransform(800, 600, 0);
assert.equal(x.identity, true);
assert.equal(x.outW, 800);
assert.equal(x.outH, 600);
assert.deepEqual(x.mapPoint(100, 200), [100, 200]);
assert.deepEqual(x.mapPoint(0, 0), [0, 0]);
});
test('bakeTiltTransform: 360° folds to identity', () => {
const x = bakeTiltTransform(400, 300, 360);
assert.equal(x.identity, true);
assert.deepEqual(x.mapPoint(10, 20), [10, 20]);
});
test('bakeTiltTransform: 90° CW maps centre→centre; corner into AABB canvas', () => {
const srcW = 200, srcH = 100;
const x = bakeTiltTransform(srcW, srcH, 90);
assert.equal(x.identity, false);
// Rotated AABB of 200×100 about centre ≈ 100×200 (ceil may add 1px from float).
assert.ok(x.outW >= 100 && x.outW <= 101, `outW=${x.outW}`);
assert.ok(x.outH >= 200 && x.outH <= 201, `outH=${x.outH}`);
const [cx, cy] = x.mapPoint(srcW / 2, srcH / 2);
assert.ok(Math.abs(cx - x.outW / 2) < 1e-9);
assert.ok(Math.abs(cy - x.outH / 2) < 1e-9);
// Top-left (0,0) relative (−100,−50) → CW90 → (~50,~−100) → +out/2
const [tlx, tly] = x.mapPoint(0, 0);
assert.ok(Math.abs(tlx - (50 + x.outW / 2)) < 1e-4, `tlx=${tlx}`);
assert.ok(Math.abs(tly - (-100 + x.outH / 2)) < 1e-4, `tly=${tly}`);
});
test('bakeTiltTransform: maps a tape-like vertical segment; direction rotates with tilt', () => {
const srcW = 400, srcH = 600;
const start: [number, number] = [200, 100];
const end: [number, number] = [200, 500];
const preUx = 0, preUy = 1; // vertical down
for (const tilt of [15, 30, -20, 45]) {
const x = bakeTiltTransform(srcW, srcH, tilt);
const a = x.mapPoint(start[0], start[1]);
const b = x.mapPoint(end[0], end[1]);
const dx = b[0] - a[0], dy = b[1] - a[1];
const len = Math.hypot(dx, dy) || 1;
const ux = dx / len, uy = dy / len;
// Expected: rotate (preUx, preUy) clockwise by tilt
const rad = (((tilt % 360) + 360) % 360) * Math.PI / 180;
const cos = Math.cos(rad), sin = Math.sin(rad);
const expUx = preUx * cos - preUy * sin;
const expUy = preUx * sin + preUy * cos;
const dot = ux * expUx + uy * expUy;
assert.ok(dot > 0.999, `tilt=${tilt} direction mismatch dot=${dot}`);
}
});