ts-scikit
Version:
A scientific toolkit written in Typescript
229 lines • 8.97 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Quaternion = void 0;
const matrix44_1 = require("./matrix44");
const vector3_1 = require("./vector3");
const tuple4_1 = require("./tuple4");
const utils_1 = require("../utils");
/**
* A quaternion.
*
* Quaternions are vector-like objects of the form w + xi + yj + zk, where
* w, x, y, and z are real numbers and i, j, and k are imaginary units.
*/
class Quaternion extends tuple4_1.Tuple4 {
/**
* Constructs a new quaternion from euler angles of rotation.
* @param angleX the angle of rotation in the x-axis.
* @param angleY the angle of rotation in the y-axis.
* @param angleZ the angle of rotation in the z-axis.
*/
static FromEulerAngles(angleX, angleY, angleZ) {
const sx = Math.sin(angleX * 0.5);
const sy = Math.sin(angleY * 0.5);
const sz = Math.sin(angleZ * 0.5);
const cx = utils_1.cosFromSin(sx, angleX * 0.5);
const cy = utils_1.cosFromSin(sy, angleY * 0.5);
const cz = utils_1.cosFromSin(sz, angleZ * 0.5);
const cycz = cy * cz;
const sysz = sy * sz;
const sycz = sy * cz;
const cysz = cy * sz;
return new Quaternion(sx * cycz + cx * sysz, cx * sycz - sx * cysz, cx * cysz + sx * sycz, cx * cycz - sx * sysz);
}
/**
* Constructs a new quaternion from a specified matrix.
* @param mat the matrix.
*/
static FromMatrix(mat) {
const m = mat.m;
const trace = m[0] + m[5] + m[10];
let qx;
let qy;
let qz;
let qw;
if (trace > 0.0) {
const w4 = Math.sqrt(trace + 1.0) * 2.0;
qw = w4 / 4.0;
qx = (m[6] - m[9]) / w4;
qy = (m[8] - m[2]) / w4;
qz = (m[1] - m[4]) / w4;
}
else if ((m[0] > m[5]) && (m[0] > m[10])) {
const x4 = Math.sqrt(1.0 + m[0] - m[5] - m[10]) * 2.0;
qw = (m[6] - m[9]) / x4;
qx = x4 / 4.0;
qy = (m[4] + m[1]) / x4;
qz = (m[8] + m[2]) / x4;
}
else if (m[5] > m[10]) {
const y4 = Math.sqrt(1.0 + m[5] - m[0] - m[10]) * 2.0;
qw = (m[8] - m[2]) / y4;
qx = (m[4] + m[1]) / y4;
qy = y4 / 4.0;
qz = (m[9] + m[6]) / y4;
}
else {
const z4 = Math.sqrt(1.0 + m[10] - m[0] - m[5]) * 2.0;
qw = (m[1] - m[4]) / z4;
qx = (m[8] + m[2]) / z4;
qy = (m[9] + m[6]) / z4;
qz = z4 / 4.0;
}
return new Quaternion(qx, qy, qz, qw);
}
/**
* Constructs a copy of a specified quaternion.
* @param q the quaternion.
*/
static FromQuaternion(q) {
return new Quaternion(q.x, q.y, q.z, q.w);
}
/**
* Constructs a new quaternion.
* @param x the x-component.
* @param y the y-component.
* @param z the z-component.
* @param w the w-component.
*/
constructor(x, y, z, w) {
super(x, y, z, w);
}
/**
* Gets the length of this quaternion, squared.
* @returns the length of this quaternion, squared.
*/
get lengthSquared() {
return this.x * this.x + this.y * this.y + this.z * this.z;
}
/**
* Gets the length of this quaternion.
* @returns the length of this quaternion.
*/
get length() {
return Math.sqrt(this.lengthSquared);
}
/**
* Adds a specified quaternion to this quaternion.
* @param q the quaternion to add.
* @returns a reference to this quaternion, updated.
*/
plusEquals(q) {
this.x += q.x;
this.y += q.y;
this.z += q.z;
this.w += q.w;
return this;
}
/**
* Returns the quaternion y = x + q for this quaternion x and specified quaternion q.
* @param q the quaternion q.
* @returns the quaternion y = x + q.
*/
plus(q) {
return new Quaternion(q.x + this.x, q.y + this.y, q.z + this.z, q.w + this.w);
}
/**
* Subtracts a specified quaternion from this quaternion.
* @param q the quaternion to subtract.
* @returns a reference to this quaternion, updated.
*/
minusEquals(q) {
this.x -= q.x;
this.y -= q.y;
this.z -= q.z;
this.w -= q.w;
return this;
}
/**
* Returns the quaternion y = x - q for this quaternion x and specified quaternion q.
* @param q the quaternion q.
* @returns the quaternion y = x - q.
*/
minus(q) {
return new Quaternion(q.x - this.x, q.y - this.y, q.z - this.z, q.w - this.w);
}
/**
* Computes the multiplicative inverse with another quaternion.
* @param q the quaternion.
* @returns the multiplicative inverse.
*/
timesInverse(q) {
let n = this.lengthSquared;
n = (n === 0) ? n : 1.0 / n;
return new Quaternion((this.x * q.w - this.w * q.x - this.y * q.z + this.z * q.y) * n, (this.y * q.w - this.w * q.y - this.z * q.x + this.x * q.z) * n, (this.z * q.w - this.w * q.z - this.x * q.y + this.y * q.x) * n, (this.w * q.w + this.x * q.x + this.y * q.y + this.z * q.z) * n);
}
/**
* Multiplies this quaternion by a specified factor.
* @param q the multiplication factor.
* @returns the result.
*/
times(q) {
if (typeof q === 'number') {
return new Quaternion(this.x * q, this.y * q, this.z * q, this.w * q);
}
else {
if (q instanceof Quaternion) {
return new Quaternion(this.x * q.w + this.w * q.x + this.y * q.z - this.z * q.y, this.y * q.w + this.w * q.y + this.z * q.x - this.x * q.z, this.z * q.w + this.w * q.z + this.x * q.y - this.y * q.x, this.w * q.w - this.x * q.x - this.y * q.y - this.z * q.z);
}
if (q instanceof vector3_1.Vector3) {
return this.rotateVector(q);
}
}
}
/**
* Returns the normalized version of this quaternion.
* @returns this quaternion, normalized.
*/
normalize() {
const l = this.length;
return new Quaternion(this.x / l, this.y / l, this.z / l, 1.0);
}
/**
* Computes the dot product of this quaternion with a specified quaternion.
* @param q the quaternion.
* @returns the dot product.
*/
dot(q) {
return this.w * q.w + this.x * q.x + this.y * q.y + this.z * q.z;
}
/**
* Returns this quaternion as a vector in the Euler space.
* @returns this quaternion as an Euler vector.
*/
toEuler() {
const x = Math.atan2(2.0 * (this.x * this.w - this.y * this.z), 1.0 - 2.0 * (this.x * this.x + this.y * this.y));
const y = Math.asin(2.0 * (this.x * this.z + this.y * this.w));
const z = Math.atan2(2.0 * (this.z * this.w - this.x * this.y), 1.0 - 2.0 * (this.y * this.y + this.z * this.z));
return new vector3_1.Vector3(x, y, z);
}
/**
* Returns this quaternion as a matrix.
* @returns the matrix.
*/
toMatrix() {
const w2 = this.w * this.w, x2 = this.x * this.x, y2 = this.y * this.y, z2 = this.z * this.z, zw = this.z * this.w, xy = this.x * this.y, xz = this.x * this.z, yw = this.y * this.w, yz = this.y * this.z, xw = this.x * this.w;
const m00 = w2 + x2 - z2 - y2, m01 = xy + zw + zw + xy, m02 = xz - yw + xz - yw, m03 = 0.0, m10 = -zw + xy - zw + xy, m11 = y2 - z2 + w2 - x2, m12 = yz + yz + xw + xw, m13 = 0.0, m20 = yw + xz + xz + yw, m21 = yz + yz - xw - xw, m22 = z2 - y2 - x2 + w2, m23 = 0.0, m30 = 0.0, m31 = 0.0, m32 = 0.0, m33 = 0.0;
return new matrix44_1.Matrix44(m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33);
}
/**
* Returns this quaternion as a rotational matrix.
* @returns the rotational matrix.
*/
toRotationMatrix() {
const xy = this.x * this.y, xz = this.x * this.z, xw = this.x * this.w, yz = this.y * this.z, yw = this.y * this.w, zw = this.z * this.w, x2 = this.x * this.x, y2 = this.y * this.y, z2 = this.z * this.z;
const m00 = 1.0 - 2.0 * (y2 + z2), m01 = 2.0 * (xy - zw), m02 = 2.0 * (xz + yw), m03 = 0.0, m10 = 2.0 * (xy + zw), m11 = 1.0 - 2.0 * (x2 + z2), m12 = 2.0 * (yz - xw), m13 = 0.0, m20 = 2.0 * (xz - yw), m21 = 2.0 * (yz + xw), m22 = 1.0 - 2.0 * (x2 + y2), m23 = 0.0, m30 = 0.0, m31 = 0.0, m32 = 0.0, m33 = 0.0;
return new matrix44_1.Matrix44(m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33);
}
rotateVector(other) {
const q = new vector3_1.Vector3(this.x, this.y, this.z);
const cross1 = q.cross(other);
const cross2 = q.cross(cross1);
const c1w = cross1.times(this.w);
const c1w2 = c1w.plus(cross2);
const c1w22 = c1w2.times(2.0);
return other.plus(c1w22);
}
}
exports.Quaternion = Quaternion;
//# sourceMappingURL=quaternion.js.map