ts-scikit
Version:
A scientific toolkit written in Typescript
392 lines • 16.7 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Matrix44 = void 0;
/**
* A 4x4 matrix.
*/
const vector3_1 = require("./vector3");
const point3_1 = require("./point3");
const point4_1 = require("./point4");
class Matrix44 {
/**
* Constructs a matrix with specified elements.
* @param m00 the element with (row, col) indices (0, 0)
* @param m01 the element with (row, col) indices (0, 1)
* @param m02 the element with (row, col) indices (0, 2)
* @param m03 the element with (row, col) indices (0, 3)
* @param m10 the element with (row, col) indices (1, 0)
* @param m11 the element with (row, col) indices (1, 1)
* @param m12 the element with (row, col) indices (1, 2)
* @param m13 the element with (row, col) indices (1, 3)
* @param m20 the element with (row, col) indices (2, 0)
* @param m21 the element with (row, col) indices (2, 1)
* @param m22 the element with (row, col) indices (2, 2)
* @param m23 the element with (row, col) indices (2, 3)
* @param m30 the element with (row, col) indices (3, 0)
* @param m31 the element with (row, col) indices (3, 1)
* @param m32 the element with (row, col) indices (3, 2)
* @param m33 the element with (row, col) indices (3, 3)
*/
constructor(m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) {
this._m = new Array(16);
this.set(m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33);
}
/**
* Constructs an identity matrix.
*/
static AsIdentity() {
return new Matrix44(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
}
/**
* Constructs a new matrix from an array(16) of values.
* @param arr an array of values.
* @param columnMajorOrder true, if array is organized in column-major order; false, if row-major order.
*/
static FromArray(arr, columnMajorOrder = true) {
if (columnMajorOrder) {
return new Matrix44(arr[0], arr[4], arr[8], arr[12], arr[1], arr[5], arr[9], arr[13], arr[2], arr[6], arr[10], arr[14], arr[3], arr[7], arr[11], arr[15]);
}
else {
return new Matrix44(arr[0], arr[1], arr[2], arr[3], arr[4], arr[5], arr[6], arr[7], arr[8], arr[9], arr[10], arr[11], arr[12], arr[13], arr[14], arr[15]);
}
}
/**
* Constructs a new matrix from another.
* @param mat a matrix.
*/
static FromMatrix44(mat) {
return Matrix44.FromArray(mat.m);
}
/**
* Gets the column-major array of values for this matrix.
*/
get m() { return this._m; }
/**
* Computes the matrix product C = AB.
* The product may be computed in place.
*/
mul(a, b, c) {
const a00 = a[0], a01 = a[4], a02 = a[8], a03 = a[12];
const a10 = a[1], a11 = a[5], a12 = a[9], a13 = a[13];
const a20 = a[2], a21 = a[6], a22 = a[10], a23 = a[14];
const a30 = a[3], a31 = a[7], a32 = a[11], a33 = a[15];
const b00 = b[0], b01 = b[4], b02 = b[8], b03 = b[12];
const b10 = b[1], b11 = b[5], b12 = b[9], b13 = b[13];
const b20 = b[2], b21 = b[6], b22 = b[10], b23 = b[14];
const b30 = b[3], b31 = b[7], b32 = b[11], b33 = b[15];
c[0] = a00 * b00 + a01 * b10 + a02 * b20 + a03 * b30;
c[1] = a10 * b00 + a11 * b10 + a12 * b20 + a13 * b30;
c[2] = a20 * b00 + a21 * b10 + a22 * b20 + a23 * b30;
c[3] = a30 * b00 + a31 * b10 + a32 * b20 + a33 * b30;
c[4] = a00 * b01 + a01 * b11 + a02 * b21 + a03 * b31;
c[5] = a10 * b01 + a11 * b11 + a12 * b21 + a13 * b31;
c[6] = a20 * b01 + a21 * b11 + a22 * b21 + a23 * b31;
c[7] = a30 * b01 + a31 * b11 + a32 * b21 + a33 * b31;
c[8] = a00 * b02 + a01 * b12 + a02 * b22 + a03 * b32;
c[9] = a10 * b02 + a11 * b12 + a12 * b22 + a13 * b32;
c[10] = a20 * b02 + a21 * b12 + a22 * b22 + a23 * b32;
c[11] = a30 * b02 + a31 * b12 + a32 * b22 + a33 * b32;
c[12] = a00 * b03 + a01 * b13 + a02 * b23 + a03 * b33;
c[13] = a10 * b03 + a11 * b13 + a12 * b23 + a13 * b33;
c[14] = a20 * b03 + a21 * b13 + a22 * b23 + a23 * b33;
c[15] = a30 * b03 + a31 * b13 + a32 * b23 + a33 * b33;
return c;
}
/**
* Computes the matrix product C = AB'.
* The product may be computed in place.
*/
mult(a, b, c) {
const a00 = a[0], a01 = a[4], a02 = a[8], a03 = a[12];
const a10 = a[1], a11 = a[5], a12 = a[9], a13 = a[13];
const a20 = a[2], a21 = a[6], a22 = a[10], a23 = a[14];
const a30 = a[3], a31 = a[7], a32 = a[11], a33 = a[15];
const b00 = b[0], b01 = b[4], b02 = b[8], b03 = b[12];
const b10 = b[1], b11 = b[5], b12 = b[9], b13 = b[13];
const b20 = b[2], b21 = b[6], b22 = b[10], b23 = b[14];
const b30 = b[3], b31 = b[7], b32 = b[11], b33 = b[15];
c[0] = a00 * b00 + a01 * b01 + a02 * b02 + a03 * b03;
c[1] = a10 * b00 + a11 * b01 + a12 * b02 + a13 * b03;
c[2] = a20 * b00 + a21 * b01 + a22 * b02 + a23 * b03;
c[3] = a30 * b00 + a31 * b01 + a32 * b02 + a33 * b03;
c[4] = a00 * b10 + a01 * b11 + a02 * b12 + a03 * b13;
c[5] = a10 * b10 + a11 * b11 + a12 * b12 + a13 * b13;
c[6] = a20 * b10 + a21 * b11 + a22 * b12 + a23 * b13;
c[7] = a30 * b10 + a31 * b11 + a32 * b12 + a33 * b13;
c[8] = a00 * b20 + a01 * b21 + a02 * b22 + a03 * b23;
c[9] = a10 * b20 + a11 * b21 + a12 * b22 + a13 * b23;
c[10] = a20 * b20 + a21 * b21 + a22 * b22 + a23 * b23;
c[11] = a30 * b20 + a31 * b21 + a32 * b22 + a33 * b23;
c[12] = a00 * b30 + a01 * b31 + a02 * b32 + a03 * b33;
c[13] = a10 * b30 + a11 * b31 + a12 * b32 + a13 * b33;
c[14] = a20 * b30 + a21 * b31 + a22 * b32 + a23 * b33;
c[15] = a30 * b30 + a31 * b31 + a32 * b32 + a33 * b33;
return c;
}
/**
* Computes the matrix product C = A'B.
* The product may be computed in place.
*/
tmul(a, b, c) {
const a00 = a[0], a01 = a[4], a02 = a[8], a03 = a[12];
const a10 = a[1], a11 = a[5], a12 = a[9], a13 = a[13];
const a20 = a[2], a21 = a[6], a22 = a[10], a23 = a[14];
const a30 = a[3], a31 = a[7], a32 = a[11], a33 = a[15];
const b00 = b[0], b01 = b[4], b02 = b[8], b03 = b[12];
const b10 = b[1], b11 = b[5], b12 = b[9], b13 = b[13];
const b20 = b[2], b21 = b[6], b22 = b[10], b23 = b[14];
const b30 = b[3], b31 = b[7], b32 = b[11], b33 = b[15];
c[0] = a00 * b00 + a10 * b10 + a20 * b20 + a30 * b30;
c[1] = a01 * b00 + a11 * b10 + a21 * b20 + a31 * b30;
c[2] = a02 * b00 + a12 * b10 + a22 * b20 + a32 * b30;
c[3] = a03 * b00 + a13 * b10 + a23 * b20 + a33 * b30;
c[4] = a00 * b01 + a10 * b11 + a20 * b21 + a30 * b31;
c[5] = a01 * b01 + a11 * b11 + a21 * b21 + a31 * b31;
c[6] = a02 * b01 + a12 * b11 + a22 * b21 + a32 * b31;
c[7] = a03 * b01 + a13 * b11 + a23 * b21 + a33 * b31;
c[8] = a00 * b02 + a10 * b12 + a20 * b22 + a30 * b32;
c[9] = a01 * b02 + a11 * b12 + a21 * b22 + a31 * b32;
c[10] = a02 * b02 + a12 * b12 + a22 * b22 + a32 * b32;
c[11] = a03 * b02 + a13 * b12 + a23 * b22 + a33 * b32;
c[12] = a00 * b03 + a10 * b13 + a20 * b23 + a30 * b33;
c[13] = a01 * b03 + a11 * b13 + a21 * b23 + a31 * b33;
c[14] = a02 * b03 + a12 * b13 + a22 * b23 + a32 * b33;
c[15] = a03 * b03 + a13 * b13 + a23 * b23 + a33 * b33;
return c;
}
/**
* Compute the inverse of matrix A.
*
* This method is based off of Cramer's Rule for the inverse of a matrix
* and its implementation follows that described by Streaming SIMD
* Extensions - Inverse of 4x4 Matrix, Intel Corporation, Techncial
* Report AP-928.
* @param a array of matrix A.
* @returns the inverse of array A.
*/
invert(a) {
const b = new Array(16);
// transpose
const t00 = a[0], t01 = a[4], t02 = a[8], t03 = a[12];
const t04 = a[1], t08 = a[2], t12 = a[3], t05 = a[5];
const t09 = a[6], t13 = a[7], t06 = a[9], t10 = a[10];
const t14 = a[11], t07 = a[13], t11 = a[14], t15 = a[15];
// pairs for first 8 elements (cofactors)
let u00 = t10 * t15, u01 = t11 * t14, u02 = t09 * t15, u03 = t11 * t13, u04 = t09 * t14, u05 = t10 * t13, u06 = t08 * t15, u07 = t11 * t12, u08 = t08 * t14, u09 = t10 * t12, u10 = t08 * t13, u11 = t09 * t12;
// first 8 elements (cofactors)
b[0] = u00 * t05 + u03 * t06 + u04 * t07 - u01 * t05 - u02 * t06 - u05 * t07;
b[1] = u01 * t04 + u06 * t06 + u09 * t07 - u00 * t04 - u07 * t06 - u08 * t07;
b[2] = u02 * t04 + u07 * t05 + u10 * t07 - u03 * t04 - u06 * t05 - u11 * t07;
b[3] = u05 * t04 + u08 * t05 + u11 * t06 - u04 * t04 - u09 * t05 - u10 * t06;
b[4] = u01 * t01 + u02 * t02 + u05 * t03 - u00 * t01 - u03 * t02 - u04 * t03;
b[5] = u00 * t00 + u07 * t02 + u08 * t03 - u01 * t00 - u06 * t02 - u09 * t03;
b[6] = u03 * t00 + u06 * t01 + u11 * t03 - u02 * t00 - u07 * t01 - u10 * t03;
b[7] = u04 * t00 + u09 * t01 + u10 * t02 - u05 * t00 - u08 * t01 - u11 * t02;
// pairs for second 8 elements (cofactors)
u00 = t02 * t07;
u01 = t03 * t06;
u02 = t01 * t07;
u03 = t03 * t05;
u04 = t01 * t06;
u05 = t02 * t05;
u06 = t00 * t07;
u07 = t03 * t04;
u08 = t00 * t06;
u09 = t02 * t04;
u10 = t00 * t05;
u11 = t01 * t04;
// second 8 elements (cofactors)
b[8] = u00 * t13 + u03 * t14 + u04 * t15 - u01 * t13 - u02 * t14 - u05 * t15;
b[9] = u01 * t12 + u06 * t14 + u09 * t15 - u00 * t12 - u07 * t14 - u08 * t15;
b[10] = u02 * t12 + u07 * t13 + u10 * t15 - u03 * t12 - u06 * t13 - u11 * t15;
b[11] = u05 * t12 + u08 * t13 + u11 * t14 - u04 * t12 - u09 * t13 - u10 * t14;
b[12] = u02 * t10 + u05 * t11 + u01 * t09 - u04 * t11 - u00 * t09 - u03 * t10;
b[13] = u08 * t11 + u00 * t08 + u07 * t10 - u06 * t10 - u09 * t11 - u01 * t08;
b[14] = u06 * t09 + u11 * t11 + u03 * t08 - u10 * t11 - u02 * t08 - u07 * t09;
b[15] = u10 * t10 + u04 * t08 + u09 * t09 - u08 * t09 - u11 * t10 - u05 * t08;
// determinant
let d = t00 * b[0] + t01 * b[1] + t02 * b[2] + t03 * b[3];
// inverse
d = 1.0 / d;
b[0] *= d;
b[1] *= d;
b[2] *= d;
b[3] *= d;
b[4] *= d;
b[5] *= d;
b[6] *= d;
b[7] *= d;
b[8] *= d;
b[9] *= d;
b[10] *= d;
b[11] *= d;
b[12] *= d;
b[13] *= d;
b[14] *= d;
b[15] *= d;
return b;
}
/**
* Returns a copy (by value) of this matrix.
* @returns a copy of this matrix.
*/
clone() {
return Matrix44.FromMatrix44(this);
}
/**
* Returns the transpose of this matrix.
* @returns the transpose of this matrix.
*/
transpose() {
const t = [
this._m[0], this._m[4], this._m[8], this._m[12],
this._m[1], this._m[5], this._m[9], this._m[13],
this._m[2], this._m[6], this._m[10], this._m[14],
this._m[3], this._m[7], this._m[11], this._m[15]
];
return Matrix44.FromArray(t);
}
/**
* Replaces this matrix with its transpose.
* @returns the transpose of this matrix.
*/
transposeEquals() {
this._m = this.transpose().m;
return this;
}
/**
* Returns the inverse of this matrix.
* @returns the inverse of this matrix.
*/
inverse() {
return Matrix44.FromArray(this.invert(this._m));
}
/**
* Inverts this matrix.
* @returns the inverse of this matrix.
*/
inverseEquals() {
this._m = this.invert(Object.assign({}, this._m));
return this;
}
/**
* Returns the product MA of this matrix M and matrix A.
* @param a the matrix A.
* @returns the product MA.
*/
times(a) {
if (a instanceof Matrix44) {
return this.timesMatrix44(a);
}
else if (a instanceof vector3_1.Vector3) {
return this.timesVector3(a);
}
else if (a instanceof point3_1.Point3) {
return this.timesPoint3(a);
}
else if (a instanceof point4_1.Point4) {
return this.timesPoint4(a);
}
else {
return this;
}
}
/**
* Replaces this matrix M with the product MA.
* @param a the matrix A.
* @returns the product MA.
*/
timesEquals(a) {
this.mul(this.m, a.m, this.m);
return this;
}
/**
* Sets all elements of this matrix.
* @param m00 the element with (row, col) indices (0, 0)
* @param m01 the element with (row, col) indices (0, 1)
* @param m02 the element with (row, col) indices (0, 2)
* @param m03 the element with (row, col) indices (0, 3)
* @param m10 the element with (row, col) indices (1, 0)
* @param m11 the element with (row, col) indices (1, 1)
* @param m12 the element with (row, col) indices (1, 2)
* @param m13 the element with (row, col) indices (1, 3)
* @param m20 the element with (row, col) indices (2, 0)
* @param m21 the element with (row, col) indices (2, 1)
* @param m22 the element with (row, col) indices (2, 2)
* @param m23 the element with (row, col) indices (2, 3)
* @param m30 the element with (row, col) indices (3, 0)
* @param m31 the element with (row, col) indices (3, 1)
* @param m32 the element with (row, col) indices (3, 2)
* @param m33 the element with (row, col) indices (3, 3)
*/
set(m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) {
this._m[0] = m00;
this._m[4] = m01;
this._m[8] = m02;
this._m[12] = m03;
this._m[1] = m10;
this._m[5] = m11;
this._m[9] = m12;
this._m[13] = m13;
this._m[2] = m20;
this._m[6] = m21;
this._m[10] = m22;
this._m[14] = m23;
this._m[3] = m30;
this._m[7] = m31;
this._m[11] = m32;
this._m[15] = m33;
}
/**
* Returns the product MA of this matrix M and a matrix A.
* @param a the matrix A.
* @return the product MA.
*/
timesMatrix44(a) {
return Matrix44.FromArray(this.mul(this.m, a.m, new Array(16)), true);
}
/**
* Returns the product Mv of this matrix M and a vector v.
* Uses only the upper-left 3-by-3 elements of this matrix.
* @param v the vector v.
* @return the product Mv.
*/
timesVector3(v) {
const vx = v.x, vy = v.y, vz = v.z;
const ux = this.m[0] * vx + this.m[4] * vy + this.m[8] * vz, uy = this.m[1] * vx + this.m[5] * vy + this.m[9] * vz, uz = this.m[2] * vx + this.m[6] * vy + this.m[10] * vz;
return new vector3_1.Vector3(ux, uy, uz);
}
/**
* Returns the product Mp of this matrix M and a point p.
* The coordinate w of the specified point is assume to equal 1.0,
* and the returned point is homogenized,
* @param p the point p.
* @returns the product Mp.
*/
timesPoint3(p) {
const px = p.x, py = p.y, pz = p.z;
let qx = this.m[0] * px + this.m[4] * py + this.m[8] * pz + this.m[12];
let qy = this.m[1] * px + this.m[5] * py + this.m[9] * pz + this.m[13];
let qz = this.m[2] * px + this.m[6] * py + this.m[10] * pz + this.m[14];
const qw = this.m[3] * px + this.m[7] * py + this.m[11] * pz + this.m[15];
if (qw !== 1.0) {
const s = 1.0 / qw;
qx *= s;
qy *= s;
qz *= s;
}
return new point3_1.Point3(qx, qy, qz);
}
/**
* Returns the product Mp of this matrix M and a point p.
* @param p the point p.
* @returns the product Mp.
*/
timesPoint4(p) {
const px = p.x, py = p.y, pz = p.z, pw = p.w;
const qx = this.m[0] * px + this.m[4] * py + this.m[8] * pz + this.m[12] * pw, qy = this.m[1] * px + this.m[5] * py + this.m[9] * pz + this.m[13] * pw, qz = this.m[2] * px + this.m[6] * py + this.m[10] * pz + this.m[14] * pw, qw = this.m[3] * px + this.m[7] * py + this.m[11] * pz + this.m[15] * pw;
return new point4_1.Point4(qx, qy, qz, qw);
}
}
exports.Matrix44 = Matrix44;
//# sourceMappingURL=matrix44.js.map