import { test } from 'node:test'; import assert from 'node:assert/strict'; import { CALIBRATION_FRAME, applyApprovedMask, cropTickPositions, pinchPhotoTransform, photoToStage, stageToPhoto, tapeLineFromStageTicks, } from './tapeCalibration.ts'; test('the reference line is fixed at the center of the calibration frame', () => { assert.equal(CALIBRATION_FRAME.width, 480); assert.equal(CALIBRATION_FRAME.height, 640); assert.equal(CALIBRATION_FRAME.width / 2, 240); const [top, bottom] = cropTickPositions(90); assert.ok(Math.abs(top - 32) < 1e-9); assert.ok(Math.abs(bottom - 608) < 1e-9); const transform = { tiltDeg: 21, zoom: 1.4, panX: -18, panY: 11 }; const tape = tapeLineFromStageTicks(100, 530, 2400, 1800, transform); const start = photoToStage(tape.start, 2400, 1800, transform); const end = photoToStage(tape.end, 2400, 1800, transform); assert.ok(Math.abs(start[0] - 240) < 1e-8 && Math.abs(start[1] - 100) < 1e-8); assert.ok(Math.abs(end[0] - 240) < 1e-8 && Math.abs(end[1] - 530) < 1e-8); }); test('pan, zoom, and tilt change the photo under the fixed reference line without losing source coordinates', () => { const transform = { tiltDeg: 31, zoom: 1.7, panX: 15, panY: -24 }; const sourcePoint: [number, number] = [317, 218]; const stagePoint = photoToStage(sourcePoint, 1200, 900, transform); const restored = stageToPhoto(stagePoint, 1200, 900, transform); assert.ok(Math.abs(restored[0] - sourcePoint[0]) < 1e-8); assert.ok(Math.abs(restored[1] - sourcePoint[1]) < 1e-8); }); test('approved-mask rendering removes background pixels but preserves slab pixels', () => { const rgba = new Uint8ClampedArray([ 180, 90, 30, 255, 20, 200, 40, 255, ]); const masked = applyApprovedMask(rgba, Uint8Array.of(1, 0)); assert.deepEqual([...masked.slice(0, 4)], [180, 90, 30, 255]); assert.deepEqual([...masked.slice(4, 8)], [20, 200, 40, 0]); }); test('pinch zoom keeps the photo point under the moving pinch midpoint', () => { const transform = { tiltDeg: 17, zoom: 1.2, panX: 11, panY: -8 }; const anchor: [number, number] = [420, 530]; const before = photoToStage(anchor, 1200, 900, transform); const midpoint: [number, number] = [before[0] + 18, before[1] - 12]; const next = pinchPhotoTransform(transform, anchor, midpoint, 1.5, 1200, 900); const after = photoToStage(anchor, 1200, 900, next); assert.ok(Math.abs(after[0] - midpoint[0]) < 1e-8); assert.ok(Math.abs(after[1] - midpoint[1]) < 1e-8); assert.ok(Math.abs(next.zoom - 1.8) < 1e-12); });