src/Matrix3.js
/**
* A 3x3 matrix.
*/
export class Matrix3 {
/**
* Constructs a new matrix.
*/
constructor() {
/**
* The matrix elements.
*
* @type {Float32Array}
*/
this.elements = new Float32Array([
1, 0, 0,
0, 1, 0,
0, 0, 1
]);
}
/**
* Sets the values of this matrix.
*
* @param {Number} m00 - The value of the first row, first column.
* @param {Number} m01 - The value of the first row, second column.
* @param {Number} m02 - The value of the first row, third column.
* @param {Number} m10 - The value of the second row, first column.
* @param {Number} m11 - The value of the second row, second column.
* @param {Number} m12 - The value of the second row, third column.
* @param {Number} m20 - The value of the third row, first column.
* @param {Number} m21 - The value of the third row, second column.
* @param {Number} m22 - The value of the third row, third column.
* @return {Matrix3} This matrix.
*/
set(m00, m01, m02, m10, m11, m12, m20, m21, m22) {
const te = this.elements;
te[0] = m00; te[3] = m01; te[6] = m02;
te[1] = m10; te[4] = m11; te[7] = m12;
te[2] = m20; te[5] = m21; te[8] = m22;
return this;
}
/**
* Sets this matrix to the identity matrix.
*
* @return {Matrix3} This matrix.
*/
identity() {
this.set(
1, 0, 0,
0, 1, 0,
0, 0, 1
);
return this;
}
/**
* Copies the values of a given matrix.
*
* @param {Matrix3} matrix - A matrix.
* @return {Matrix3} This matrix.
*/
copy(matrix) {
const me = matrix.elements;
const te = this.elements;
te[0] = me[0]; te[1] = me[1]; te[2] = me[2];
te[3] = me[3]; te[4] = me[4]; te[5] = me[5];
te[6] = me[6]; te[7] = me[7]; te[8] = me[8];
return this;
}
/**
* Clones this matrix.
*
* @return {Matrix3} A clone of this matrix.
*/
clone() {
return new this.constructor().fromArray(this.elements);
}
/**
* Copies the values of a given array.
*
* @param {Number[]} array - An array.
* @param {Number} [offset=0] - An offset into the array.
* @return {Matrix3} This matrix.
*/
fromArray(array, offset = 0) {
const te = this.elements;
let i;
for(i = 0; i < 9; ++i) {
te[i] = array[i + offset];
}
return this;
}
/**
* Stores this matrix in an array.
*
* @param {Number[]} [array] - A target array.
* @param {Number} [offset=0] - An offset into the array.
* @return {Number[]} The array.
*/
toArray(array = [], offset = 0) {
const te = this.elements;
let i;
for(i = 0; i < 9; ++i) {
array[i + offset] = te[i];
}
return array;
}
/**
* Sets this matrix to the product of the given matrices.
*
* @param {Matrix3} a - A matrix.
* @param {Matrix3} b - A matrix.
* @return {Matrix3} This matrix.
*/
multiplyMatrices(a, b) {
const ae = a.elements;
const be = b.elements;
const te = this.elements;
const a11 = ae[0], a12 = ae[3], a13 = ae[6];
const a21 = ae[1], a22 = ae[4], a23 = ae[7];
const a31 = ae[2], a32 = ae[5], a33 = ae[8];
const b11 = be[0], b12 = be[3], b13 = be[6];
const b21 = be[1], b22 = be[4], b23 = be[7];
const b31 = be[2], b32 = be[5], b33 = be[8];
te[0] = a11 * b11 + a12 * b21 + a13 * b31;
te[3] = a11 * b12 + a12 * b22 + a13 * b32;
te[6] = a11 * b13 + a12 * b23 + a13 * b33;
te[1] = a21 * b11 + a22 * b21 + a23 * b31;
te[4] = a21 * b12 + a22 * b22 + a23 * b32;
te[7] = a21 * b13 + a22 * b23 + a23 * b33;
te[2] = a31 * b11 + a32 * b21 + a33 * b31;
te[5] = a31 * b12 + a32 * b22 + a33 * b32;
te[8] = a31 * b13 + a32 * b23 + a33 * b33;
return this;
}
/**
* Multiplies this matrix with a given one.
*
* @param {Matrix3} m - A matrix.
* @return {Matrix3} This matrix.
*/
multiply(m) {
return this.multiplyMatrices(this, m);
}
/**
* Multiplies a given matrix with this one.
*
* @param {Matrix3} m - A matrix.
* @return {Matrix3} This matrix.
*/
premultiply(m) {
return this.multiplyMatrices(m, this);
}
/**
* Multiplies this matrix with a given scalar.
*
* @param {Number} s - A scalar.
* @return {Matrix3} This matrix.
*/
multiplyScalar(s) {
const te = this.elements;
te[0] *= s; te[3] *= s; te[6] *= s;
te[1] *= s; te[4] *= s; te[7] *= s;
te[2] *= s; te[5] *= s; te[8] *= s;
return this;
}
/**
* Calculates the determinant of this matrix.
*
* @return {Number} The determinant.
*/
determinant() {
const te = this.elements;
const a = te[0], b = te[1], c = te[2];
const d = te[3], e = te[4], f = te[5];
const g = te[6], h = te[7], i = te[8];
return (
a * e * i -
a * f * h -
b * d * i +
b * f * g +
c * d * h -
c * e * g
);
}
/**
* Inverts the given matrix and stores the result in this matrix.
*
* @param {Matrix3} matrix - The matrix that should be inverted.
* @return {Matrix3} This matrix.
*/
getInverse(matrix) {
const me = matrix.elements;
const te = this.elements;
const n11 = me[0], n21 = me[1], n31 = me[2];
const n12 = me[3], n22 = me[4], n32 = me[5];
const n13 = me[6], n23 = me[7], n33 = me[8];
const t11 = n33 * n22 - n32 * n23;
const t12 = n32 * n13 - n33 * n12;
const t13 = n23 * n12 - n22 * n13;
const det = n11 * t11 + n21 * t12 + n31 * t13;
let invDet;
if(det !== 0) {
invDet = 1.0 / det;
te[0] = t11 * invDet;
te[1] = (n31 * n23 - n33 * n21) * invDet;
te[2] = (n32 * n21 - n31 * n22) * invDet;
te[3] = t12 * invDet;
te[4] = (n33 * n11 - n31 * n13) * invDet;
te[5] = (n31 * n12 - n32 * n11) * invDet;
te[6] = t13 * invDet;
te[7] = (n21 * n13 - n23 * n11) * invDet;
te[8] = (n22 * n11 - n21 * n12) * invDet;
} else {
this.set(0, 0, 0, 0, 0, 0, 0, 0, 0);
}
return this;
}
/**
* Transposes this matrix.
*
* @return {Matrix3} This matrix.
*/
transpose() {
const me = this.elements;
let t;
t = me[1]; me[1] = me[3]; me[3] = t;
t = me[2]; me[2] = me[6]; me[6] = t;
t = me[5]; me[5] = me[7]; me[7] = t;
return this;
}
/**
* Scales this matrix.
*
* @param {Number} sx - The X scale.
* @param {Number} sy - The Y scale.
* @return {Matrix3} This matrix.
*/
scale(sx, sy) {
const te = this.elements;
te[0] *= sx; te[3] *= sx; te[6] *= sx;
te[1] *= sy; te[4] *= sy; te[7] *= sy;
return this;
}
/**
* Rotates this matrix.
*
* @param {Number} theta - The rotation.
* @return {Matrix3} This matrix.
*/
rotate(theta) {
const c = Math.cos(theta);
const s = Math.sin(theta);
const te = this.elements;
const a11 = te[0], a12 = te[3], a13 = te[6];
const a21 = te[1], a22 = te[4], a23 = te[7];
te[0] = c * a11 + s * a21;
te[3] = c * a12 + s * a22;
te[6] = c * a13 + s * a23;
te[1] = -s * a11 + c * a21;
te[4] = -s * a12 + c * a22;
te[7] = -s * a13 + c * a23;
return this;
}
/**
* Translates this matrix.
*
* @param {Number} tx - The X offset.
* @param {Number} ty - The Y offset.
* @return {Matrix3} This matrix.
*/
translate(tx, ty) {
const te = this.elements;
te[0] += tx * te[2]; te[3] += tx * te[5]; te[6] += tx * te[8];
te[1] += ty * te[2]; te[4] += ty * te[5]; te[7] += ty * te[8];
return this;
}
/**
* Checks if this matrix equals the given one.
*
* @param {Matrix3} m - A matrix.
* @return {Boolean} Whether the matrix are equal.
*/
equals(m) {
const te = this.elements;
const me = m.elements;
let result = true;
let i;
for(i = 0; result && i < 9; ++i) {
if(te[i] !== me[i]) {
result = false;
}
}
return result;
}
}