111 lines
3.3 KiB
JavaScript
111 lines
3.3 KiB
JavaScript
import {
|
|
getAffineApproximation,
|
|
getProjective,
|
|
transform,
|
|
} from "@html_editor/utils/perspective_utils";
|
|
|
|
const epsilon = 100 * Number.EPSILON;
|
|
|
|
function midpoint([x0, y0], [x1, y1], weight = 0.5) {
|
|
return [weight * (x0 + y0), (1.0 - weight) * (x1 + y1)];
|
|
}
|
|
|
|
function pointEqual(a, b) {
|
|
expect(Math.abs(a[0] - b[0])).toBeLessThan(epsilon);
|
|
expect(Math.abs(a[1] - b[1])).toBeLessThan(epsilon);
|
|
}
|
|
|
|
function notPointEqual(a, b) {
|
|
expect(Math.abs(a[0] - b[0]) > epsilon || Math.abs(a[1] - b[1]) > epsilon).toBe(true);
|
|
}
|
|
|
|
import { describe, expect, test } from "@odoo/hoot";
|
|
|
|
describe("Perspective Utils", () => {
|
|
test("Should correctly transform 2D points using a projective transformation", async () => {
|
|
const translation = [
|
|
[0, 0, 3],
|
|
[0, 0, 5],
|
|
[0, 0, 1],
|
|
];
|
|
|
|
pointEqual(transform(translation, [0, 0]), [3, 5]);
|
|
|
|
const scale = [
|
|
[2, 0, 0],
|
|
[0, 0.5, 0],
|
|
[0, 0, 1],
|
|
];
|
|
pointEqual(transform(scale, [1, 1]), [2, 0.5]);
|
|
const perspective = [
|
|
[1, 0, 0],
|
|
[0, 1, 0],
|
|
[1, 1, 1],
|
|
];
|
|
pointEqual(transform(perspective, [4, 5]), [0.4, 0.5]);
|
|
});
|
|
|
|
test("Should find an affine approximation of a projective transformation", async () => {
|
|
const a = [0, 0];
|
|
const b = [1, 0];
|
|
const c = [0, 1];
|
|
|
|
const projective = [
|
|
[1, 2, 3],
|
|
[2, 4, 5],
|
|
[2, 2, 1],
|
|
];
|
|
const affine = getAffineApproximation(projective, [a, b, c]);
|
|
|
|
pointEqual(transform(projective, a), transform(affine, a));
|
|
pointEqual(transform(projective, b), transform(affine, b));
|
|
pointEqual(transform(projective, c), transform(affine, c));
|
|
|
|
notPointEqual((projective, [1, 1]), transform(affine, [1, 1]));
|
|
});
|
|
test("Should identically transform common edge points of two affine approximations", async () => {
|
|
const a = [0, 0];
|
|
const b = [1, 0];
|
|
const c = [1, 1];
|
|
const d = [0, 1];
|
|
|
|
const projective = [
|
|
[1, 2, 3],
|
|
[2, 4, 5],
|
|
[2, 2, 1],
|
|
];
|
|
const affine1 = getAffineApproximation(projective, [a, b, d]);
|
|
const affine2 = getAffineApproximation(projective, [b, c, d]);
|
|
|
|
pointEqual(
|
|
transform(affine1, midpoint(b, d, 0.2)),
|
|
transform(affine2, midpoint(b, d, 0.2))
|
|
);
|
|
pointEqual(
|
|
transform(affine1, midpoint(b, d, 0.5)),
|
|
transform(affine2, midpoint(b, d, 0.5))
|
|
);
|
|
pointEqual(
|
|
transform(affine1, midpoint(b, d, 0.8)),
|
|
transform(affine2, midpoint(b, d, 0.8))
|
|
);
|
|
});
|
|
|
|
test("Should find a projective transformation for a given quadrilateral", async () => {
|
|
const width = 2;
|
|
const height = 3;
|
|
|
|
const a = [0.1, 0.3];
|
|
const b = [1.9, 0.1];
|
|
const c = [1.7, 2.9];
|
|
const d = [0.1, 2.8];
|
|
|
|
const projective = getProjective(width, height, [a, b, c, d]);
|
|
|
|
pointEqual(a, transform(projective, [0, 0]));
|
|
pointEqual(b, transform(projective, [width, 0]));
|
|
pointEqual(c, transform(projective, [width, height]));
|
|
pointEqual(d, transform(projective, [0, height]));
|
|
});
|
|
});
|