UNPKG

react-native-redash

Version:
171 lines (154 loc) 4.59 kB
/* eslint-disable @typescript-eslint/no-explicit-any */ export const sdot = (...args: number[]): number => { let acc = 0; for (let i = 0; i < args.length - 1; i += 2) { acc += args[i] * args[i + 1]; } return acc; }; const identityN = (n: number): number[] => { let size = n * n; const m = new Array(size); while (size--) { m[size] = size % (n + 1) === 0 ? 1.0 : 0.0; } return m; }; export const identity = () => identityN(4); function isnumber(val: number) { return !isNaN(val); } const m = (m1: number[], m2: number[]) => { const size = 4; if (!m1.every(isnumber) || !m2.every(isnumber)) { throw "Some members of matrices are NaN m1=" + m1 + ", m2=" + m2 + ""; } if (m1.length !== m2.length) { throw ( "Undefined for matrices of different sizes. m1.length=" + m1.length + ", m2.length=" + m2.length ); } if (size * size !== m1.length) { throw "Undefined for non-square matrices. array size was " + size; } const result = Array(m1.length); for (let r = 0; r < size; r++) { for (let c = 0; c < size; c++) { // accumulate a sum of m1[r,k]*m2[k, c] let acc = 0; for (let k = 0; k < size; k++) { acc += m1[size * r + k] * m2[size * k + c]; } result[r * size + c] = acc; } } return result; }; export const multiply = (...listOfMatrices: any[]) => { if (listOfMatrices.length < 2) { throw "multiplication expected two or more matrices"; } let result = m(listOfMatrices[0], listOfMatrices[1]); let next = 2; while (next < listOfMatrices.length) { result = m(result, listOfMatrices[next]); next++; } return result; }; export const stride = ( v: number[], matrix: number[], width: number, offset: number, colStride: number ): number[] => { for (let i = 0; i < v.length; i++) { matrix[i * width + ((i * colStride + offset + width) % width)] = v[i]; } return matrix; }; const dot = (a: number[], b: number[]): number => { if (a.length !== b.length) { throw new Error("Arrays must have the same length for dot product."); } return a.reduce((acc, val, i) => acc + val * b[i], 0); }; const vectorLengthSquared = (v: number[]): number => dot(v, v); const vectorLength = (v: number[]): number => Math.sqrt(vectorLengthSquared(v)); const mulScalar = (v: number[], s: number): number[] => v.map((val) => val * s); // const addVectors = (a: number[], b: number[]): number[] => // a.map((val, i) => val + b[i]); // const subVectors = (a: number[], b: number[]): number[] => // a.map((val, i) => val - b[i]); const normalize = (v: number[]): number[] => mulScalar(v, 1 / vectorLength(v)); // const cross = (a: number[], b: number[]): number[] => { // if (a.length !== 3 || b.length !== 3) { // throw new Error("Cross product is only defined for 3-dimensional vectors."); // } // return [ // a[1] * b[2] - a[2] * b[1], // a[2] * b[0] - a[0] * b[2], // a[0] * b[1] - a[1] * b[0], // ]; // }; // Matrix operations export const translated = (vec: number[]): number[] => stride(vec, identityN(4), 4, 3, 0); export const scaled = (vec: number[]): number[] => stride(vec, identityN(4), 4, 0, 1); export const rotated = (axisVec: number[], radians: number): number[] => { const normalizedAxisVec = normalize(axisVec); const sinRadians = Math.sin(radians); const cosRadians = Math.cos(radians); return rotatedUnitSinCos(normalizedAxisVec, sinRadians, cosRadians); }; const rotatedUnitSinCos = ( axisVec: number[], sinAngle: number, cosAngle: number ): number[] => { const [x, y, z] = axisVec; const c = cosAngle; const s = sinAngle; const t = 1 - c; return [ t * x * x + c, t * x * y - s * z, t * x * z + s * y, 0, t * x * y + s * z, t * y * y + c, t * y * z - s * x, 0, t * x * z - s * y, t * y * z + s * x, t * z * z + c, 0, 0, 0, 0, 1, ]; }; export const transformPoint = (matrix: number[], t: number[]): number[] => { const x = matrix[0] * t[0] + matrix[1] * t[1] + matrix[2] * t[2] + matrix[3] * t[3]; const y = matrix[4] * t[0] + matrix[5] * t[1] + matrix[6] * t[2] + matrix[7] * t[3]; const z = matrix[8] * t[0] + matrix[9] * t[1] + matrix[10] * t[2] + matrix[11] * t[3]; const w = matrix[12] * t[0] + matrix[13] * t[1] + matrix[14] * t[2] + matrix[15] * t[3]; return [x, y, z, w]; }; export const transformPoint3d = (m4: number[], t: number[]): number[] => { const [x, y, z, w] = transformPoint(m4, [...t, 1]); return [x / w, y / w, z / w]; };