mind-ar
Version:
web augmented reality framework
119 lines (104 loc) • 3.73 kB
JavaScript
// check which side point C on the line from A to B
const linePointSide = (A, B, C) => {
return ((B[0]-A[0])*(C[1]-A[1])-(B[1]-A[1])*(C[0]-A[0]));
}
// srcPoints, dstPoints: array of four elements [x, y]
const checkFourPointsConsistent = (x1, x2, x3, x4, x1p, x2p, x3p, x4p) => {
if ((linePointSide(x1, x2, x3) > 0) !== (linePointSide(x1p, x2p, x3p) > 0)) return false;
if ((linePointSide(x2, x3, x4) > 0) !== (linePointSide(x2p, x3p, x4p) > 0)) return false;
if ((linePointSide(x3, x4, x1) > 0) !== (linePointSide(x3p, x4p, x1p) > 0)) return false;
if ((linePointSide(x4, x1, x2) > 0) !== (linePointSide(x4p, x1p, x2p) > 0)) return false;
return true;
}
const checkThreePointsConsistent = (x1, x2, x3, x1p, x2p, x3p) => {
if ((linePointSide(x1, x2, x3) > 0) !== (linePointSide(x1p, x2p, x3p) > 0)) return false;
return true;
}
const determinant = (A) => {
const C1 = A[4] * A[8] - A[5] * A[7];
const C2 = A[3] * A[8] - A[5] * A[6];
const C3 = A[3] * A[7] - A[4] * A[6];
return A[0] * C1 - A[1] * C2 + A[2] * C3;
}
const matrixInverse33 = (A, threshold) => {
const det = determinant(A);
if (Math.abs(det) <= threshold) return null;
const oneOver = 1.0 / det;
const B = [
(A[4] * A[8] - A[5] * A[7]) * oneOver,
(A[2] * A[7] - A[1] * A[8]) * oneOver,
(A[1] * A[5] - A[2] * A[4]) * oneOver,
(A[5] * A[6] - A[3] * A[8]) * oneOver,
(A[0] * A[8] - A[2] * A[6]) * oneOver,
(A[2] * A[3] - A[0] * A[5]) * oneOver,
(A[3] * A[7] - A[4] * A[6]) * oneOver,
(A[1] * A[6] - A[0] * A[7]) * oneOver,
(A[0] * A[4] - A[1] * A[3]) * oneOver,
];
return B;
}
const matrixMul33 = (A, B) => {
const C = [];
C[0] = A[0]*B[0] + A[1]*B[3] + A[2]*B[6];
C[1] = A[0]*B[1] + A[1]*B[4] + A[2]*B[7];
C[2] = A[0]*B[2] + A[1]*B[5] + A[2]*B[8];
C[3] = A[3]*B[0] + A[4]*B[3] + A[5]*B[6];
C[4] = A[3]*B[1] + A[4]*B[4] + A[5]*B[7];
C[5] = A[3]*B[2] + A[4]*B[5] + A[5]*B[8];
C[6] = A[6]*B[0] + A[7]*B[3] + A[8]*B[6];
C[7] = A[6]*B[1] + A[7]*B[4] + A[8]*B[7];
C[8] = A[6]*B[2] + A[7]*B[5] + A[8]*B[8];
return C;
}
const multiplyPointHomographyInhomogenous = (x, H) => {
const w = H[6]*x[0] + H[7]*x[1] + H[8];
const xp = [];
xp[0] = (H[0]*x[0] + H[1]*x[1] + H[2])/w;
xp[1] = (H[3]*x[0] + H[4]*x[1] + H[5])/w;
return xp;
}
const smallestTriangleArea = (x1, x2, x3, x4) => {
const v12 = _vector(x2, x1);
const v13 = _vector(x3, x1);
const v14 = _vector(x4, x1);
const v32 = _vector(x2, x3);
const v34 = _vector(x4, x3);
const a1 = _areaOfTriangle(v12, v13);
const a2 = _areaOfTriangle(v13, v14);
const a3 = _areaOfTriangle(v12, v14);
const a4 = _areaOfTriangle(v32, v34);
return Math.min(Math.min(Math.min(a1, a2), a3), a4);
}
// check if four points form a convex quadrilaternal.
// all four combinations should have same sign
const quadrilateralConvex = (x1, x2, x3, x4) => {
const first = linePointSide(x1, x2, x3) <= 0;
if ( (linePointSide(x2, x3, x4) <= 0) !== first) return false;
if ( (linePointSide(x3, x4, x1) <= 0) !== first) return false;
if ( (linePointSide(x4, x1, x2) <= 0) !== first) return false;
//if (linePointSide(x1, x2, x3) <= 0) return false;
//if (linePointSide(x2, x3, x4) <= 0) return false;
//if (linePointSide(x3, x4, x1) <= 0) return false;
//if (linePointSide(x4, x1, x2) <= 0) return false;
return true;
}
const _vector = (a, b) => {
return [
a[0] - b[0],
a[1] - b[1]
]
}
const _areaOfTriangle = (u, v) => {
const a = u[0]*v[1] - u[1]*v[0];
return Math.abs(a) * 0.5;
}
export {
matrixInverse33,
matrixMul33,
quadrilateralConvex,
smallestTriangleArea,
multiplyPointHomographyInhomogenous,
checkThreePointsConsistent,
checkFourPointsConsistent,
determinant
}