You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1328 lines
41 KiB
JavaScript

import { Cartesian3 } from "../../Source/Cesium.js";
import { HeadingPitchRoll } from "../../Source/Cesium.js";
import { Math as CesiumMath } from "../../Source/Cesium.js";
import { Matrix3 } from "../../Source/Cesium.js";
import { Quaternion } from "../../Source/Cesium.js";
import createPackableSpecs from "../createPackableSpecs.js";
describe("Core/Quaternion", function () {
it("construct with default values", function () {
var quaternion = new Quaternion();
expect(quaternion.x).toEqual(0.0);
expect(quaternion.y).toEqual(0.0);
expect(quaternion.z).toEqual(0.0);
expect(quaternion.w).toEqual(0.0);
});
it("construct with all values", function () {
var quaternion = new Quaternion(1.0, 2.0, 3.0, 4.0);
expect(quaternion.x).toEqual(1.0);
expect(quaternion.y).toEqual(2.0);
expect(quaternion.z).toEqual(3.0);
expect(quaternion.w).toEqual(4.0);
});
it("fromAxisAngle works without a result parameter", function () {
var axis = new Cartesian3(0.0, 0.0, 1.0);
var angle = CesiumMath.PI_OVER_TWO;
var s = Math.sin(angle / 2.0);
var c = Math.cos(angle / 2.0);
var a = Cartesian3.multiplyByScalar(axis, s, new Cartesian3());
var expected = new Quaternion(a.x, a.y, a.z, c);
var returnedResult = Quaternion.fromAxisAngle(axis, angle);
expect(returnedResult).toEqual(expected);
});
it("fromAxisAngle works with a result parameter", function () {
var axis = new Cartesian3(0.0, 0.0, 1.0);
var angle = CesiumMath.PI_OVER_TWO;
var s = Math.sin(angle / 2.0);
var c = Math.cos(angle / 2.0);
var a = Cartesian3.multiplyByScalar(axis, s, new Cartesian3());
var result = new Quaternion();
var expected = new Quaternion(a.x, a.y, a.z, c);
var returnedResult = Quaternion.fromAxisAngle(axis, angle, result);
expect(result).toBe(returnedResult);
expect(returnedResult).toEqual(expected);
});
it("fromRotationMatrix works when m22 is max", function () {
var q = Quaternion.fromAxisAngle(
Cartesian3.negate(Cartesian3.UNIT_Z, new Cartesian3()),
Math.PI
);
var rotation = new Matrix3(-1.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 1.0);
expect(Quaternion.fromRotationMatrix(rotation)).toEqualEpsilon(
q,
CesiumMath.EPSILON15
);
});
it("fromRotationMatrix works when m11 is max", function () {
var q = Quaternion.fromAxisAngle(
Cartesian3.negate(Cartesian3.UNIT_Y, new Cartesian3()),
Math.PI
);
var rotation = new Matrix3(-1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, -1.0);
expect(Quaternion.fromRotationMatrix(rotation)).toEqualEpsilon(
q,
CesiumMath.EPSILON15
);
});
it("fromRotationMatrix works when m00 is max", function () {
var q = Quaternion.fromAxisAngle(
Cartesian3.negate(Cartesian3.UNIT_X, new Cartesian3()),
Math.PI
);
var rotation = new Matrix3(1.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, -1.0);
expect(Quaternion.fromRotationMatrix(rotation)).toEqualEpsilon(
q,
CesiumMath.EPSILON15
);
});
it("fromRotationMatrix works when trace is greater than zero", function () {
var rotation = new Matrix3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0);
var q = new Quaternion(0.0, 0.0, 0.0, 1.0);
expect(Quaternion.fromRotationMatrix(rotation)).toEqualEpsilon(
q,
CesiumMath.EPSILON15
);
});
it("fromRotationMatrix works with result parameter", function () {
var rotation = new Matrix3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0);
var q = new Quaternion(0.0, 0.0, 0.0, 1.0);
var result = new Quaternion();
var returnedResult = Quaternion.fromRotationMatrix(rotation, result);
expect(returnedResult).toEqualEpsilon(q, CesiumMath.EPSILON15);
expect(returnedResult).toBe(result);
});
it("fromRotationMatrix using a view matrix", function () {
var direction = new Cartesian3(
-0.2349326833984488,
0.8513513009480378,
0.46904967396353314
);
var up = new Cartesian3(
0.12477198625717335,
-0.4521499177166376,
0.8831717858696695
);
var right = new Cartesian3(
0.9639702203483635,
0.26601017702986895,
6.456422901079747e-10
);
var matrix = new Matrix3(
right.x,
right.y,
right.z,
up.x,
up.y,
up.z,
-direction.x,
-direction.y,
-direction.z
);
var quaternion = Quaternion.fromRotationMatrix(matrix);
expect(Matrix3.fromQuaternion(quaternion)).toEqualEpsilon(
matrix,
CesiumMath.EPSILON12
);
});
it("fromHeadingPitchRoll with just heading", function () {
var angle = CesiumMath.toRadians(20.0);
var hpr = new HeadingPitchRoll(angle, 0.0, 0.0);
var quaternion = Quaternion.fromHeadingPitchRoll(hpr);
expect(Matrix3.fromQuaternion(quaternion)).toEqualEpsilon(
Matrix3.fromRotationZ(-angle),
CesiumMath.EPSILON11
);
});
it("fromHeadingPitchRoll with just pitch", function () {
var angle = CesiumMath.toRadians(20.0);
var hpr = new HeadingPitchRoll(0.0, angle, 0.0);
var quaternion = Quaternion.fromHeadingPitchRoll(hpr);
expect(Matrix3.fromQuaternion(quaternion)).toEqualEpsilon(
Matrix3.fromRotationY(-angle),
CesiumMath.EPSILON11
);
});
it("fromHeadingPitchRoll with just roll", function () {
var angle = CesiumMath.toRadians(20.0);
var hpr = new HeadingPitchRoll(0.0, 0.0, angle);
var quaternion = Quaternion.fromHeadingPitchRoll(hpr);
expect(Matrix3.fromQuaternion(quaternion)).toEqualEpsilon(
Matrix3.fromRotationX(angle),
CesiumMath.EPSILON11
);
});
it("fromHeadingPitchRoll with all angles (1)", function () {
var angle = CesiumMath.toRadians(20.0);
var hpr = new HeadingPitchRoll(angle, angle, angle);
var quaternion = Quaternion.fromHeadingPitchRoll(hpr);
var expected = Matrix3.fromRotationX(angle);
Matrix3.multiply(Matrix3.fromRotationY(-angle), expected, expected);
Matrix3.multiply(Matrix3.fromRotationZ(-angle), expected, expected);
expect(Matrix3.fromQuaternion(quaternion)).toEqualEpsilon(
expected,
CesiumMath.EPSILON11
);
});
it("fromHeadingPitchRoll with all angles (2)", function () {
var heading = CesiumMath.toRadians(180.0);
var pitch = CesiumMath.toRadians(-45.0);
var roll = CesiumMath.toRadians(45.0);
var hpr = new HeadingPitchRoll(heading, pitch, roll);
var quaternion = Quaternion.fromHeadingPitchRoll(hpr);
var expected = Matrix3.fromRotationX(roll);
Matrix3.multiply(Matrix3.fromRotationY(-pitch), expected, expected);
Matrix3.multiply(Matrix3.fromRotationZ(-heading), expected, expected);
expect(Matrix3.fromQuaternion(quaternion)).toEqualEpsilon(
expected,
CesiumMath.EPSILON11
);
});
it("fromHeadingPitchRoll works with result parameter", function () {
var angle = CesiumMath.toRadians(20.0);
var hpr = new HeadingPitchRoll(0.0, 0.0, angle);
var result = new Quaternion();
var quaternion = Quaternion.fromHeadingPitchRoll(hpr, result);
var expected = Quaternion.fromRotationMatrix(Matrix3.fromRotationX(angle));
expect(quaternion).toBe(result);
expect(quaternion).toEqualEpsilon(expected, CesiumMath.EPSILON11);
});
it("clone without a result parameter", function () {
var quaternion = new Quaternion(1.0, 2.0, 3.0, 4.0);
var result = quaternion.clone();
expect(quaternion).not.toBe(result);
expect(quaternion).toEqual(result);
});
it("clone with a result parameter", function () {
var quaternion = new Quaternion(1.0, 2.0, 3.0, 4.0);
var result = new Quaternion();
var returnedResult = quaternion.clone(result);
expect(quaternion).not.toBe(result);
expect(result).toBe(returnedResult);
expect(quaternion).toEqual(result);
});
it("clone works with a result parameter that is an input parameter", function () {
var quaternion = new Quaternion(1.0, 2.0, 3.0, 4.0);
var returnedResult = quaternion.clone(quaternion);
expect(quaternion).toBe(returnedResult);
});
it("conjugate works", function () {
var expected = new Quaternion(-1.0, -2.0, -3.0, 4.0);
var quaternion = new Quaternion(1.0, 2.0, 3.0, 4.0);
var result = new Quaternion();
var returnedResult = Quaternion.conjugate(quaternion, result);
expect(result).toBe(returnedResult);
expect(returnedResult).toEqual(expected);
});
it("conjugate works with a result parameter that is an input parameter", function () {
var expected = new Quaternion(-1.0, -2.0, -3.0, 4.0);
var quaternion = new Quaternion(1.0, 2.0, 3.0, 4.0);
var returnedResult = Quaternion.conjugate(quaternion, quaternion);
expect(quaternion).toBe(returnedResult);
expect(quaternion).toEqual(expected);
});
it("magnitudeSquared computes correct result", function () {
var expected = 2 * 2 + 3 * 3 + 4 * 4 + 5 * 5;
var quaternion = new Quaternion(2.0, 3.0, 4.0, 5.0);
var result = Quaternion.magnitudeSquared(quaternion);
expect(result).toEqual(expected);
});
it("norm computes correct result", function () {
var expected = Math.sqrt(2 * 2 + 3 * 3 + 4 * 4 + 5 * 5);
var quaternion = new Quaternion(2.0, 3.0, 4.0, 5.0);
var result = Quaternion.magnitude(quaternion);
expect(result).toEqual(expected);
});
it("normalize works", function () {
var quaternion = new Quaternion(2.0, 0.0, 0.0, 0.0);
var expectedResult = new Quaternion(1.0, 0.0, 0.0, 0.0);
var result = new Quaternion();
var returnedResult = Quaternion.normalize(quaternion, result);
expect(result).toBe(returnedResult);
expect(result).toEqual(expectedResult);
});
it("normalize works with a result parameter that is an input parameter", function () {
var quaternion = new Quaternion(2.0, 0.0, 0.0, 0.0);
var expectedResult = new Quaternion(1.0, 0.0, 0.0, 0.0);
var returnedResult = Quaternion.normalize(quaternion, quaternion);
expect(quaternion).toBe(returnedResult);
expect(quaternion).toEqual(expectedResult);
});
it("inverse works", function () {
var quaternion = new Quaternion(2.0, 3.0, 4.0, 5.0);
var magnitudeSquared = Quaternion.magnitudeSquared(quaternion);
var expected = new Quaternion(
-2.0 / magnitudeSquared,
-3.0 / magnitudeSquared,
-4.0 / magnitudeSquared,
5.0 / magnitudeSquared
);
var result = new Quaternion();
var returnedResult = Quaternion.inverse(quaternion, result);
expect(returnedResult).toEqual(expected);
expect(returnedResult).toBe(result);
});
it("inverse works with a result parameter that is an input parameter", function () {
var quaternion = new Quaternion(2.0, 3.0, 4.0, 5.0);
var magnitudeSquared = Quaternion.magnitudeSquared(quaternion);
var expected = new Quaternion(
-2.0 / magnitudeSquared,
-3.0 / magnitudeSquared,
-4.0 / magnitudeSquared,
5.0 / magnitudeSquared
);
var returnedResult = Quaternion.inverse(quaternion, quaternion);
expect(returnedResult).toEqual(expected);
expect(returnedResult).toBe(quaternion);
});
it("dot", function () {
var left = new Quaternion(2.0, 3.0, 6.0, 8.0);
var right = new Quaternion(4.0, 5.0, 7.0, 9.0);
var expectedResult = 137.0;
var result = Quaternion.dot(left, right);
expect(result).toEqual(expectedResult);
});
it("multiply works", function () {
var left = new Quaternion(1.0, 2.0, 3.0, 4.0);
var right = new Quaternion(8.0, 7.0, 6.0, 5.0);
var expected = new Quaternion(28.0, 56.0, 30.0, -20.0);
var result = new Quaternion();
var returnedResult = Quaternion.multiply(left, right, result);
expect(returnedResult).toEqual(expected);
expect(result).toBe(returnedResult);
});
it("multiply works with a result parameter that is an input parameter", function () {
var left = new Quaternion(1.0, 2.0, 3.0, 4.0);
var right = new Quaternion(8.0, 7.0, 6.0, 5.0);
var expected = new Quaternion(28.0, 56.0, 30.0, -20.0);
var returnedResult = Quaternion.multiply(left, right, left);
expect(returnedResult).toEqual(expected);
expect(left).toBe(returnedResult);
});
it("add works", function () {
var left = new Quaternion(2.0, 3.0, 6.0, 8.0);
var right = new Quaternion(4.0, 5.0, 7.0, 9.0);
var result = new Quaternion();
var expectedResult = new Quaternion(6.0, 8.0, 13.0, 17.0);
var returnedResult = Quaternion.add(left, right, result);
expect(result).toBe(returnedResult);
expect(result).toEqual(expectedResult);
});
it("add works with a result parameter that is an input parameter", function () {
var left = new Quaternion(2.0, 3.0, 6.0, 8.0);
var right = new Quaternion(4.0, 5.0, 7.0, 9.0);
var expectedResult = new Quaternion(6.0, 8.0, 13.0, 17.0);
var returnedResult = Quaternion.add(left, right, left);
expect(left).toBe(returnedResult);
expect(left).toEqual(expectedResult);
});
it("subtract works", function () {
var left = new Quaternion(2.0, 3.0, 4.0, 8.0);
var right = new Quaternion(1.0, 5.0, 7.0, 9.0);
var result = new Quaternion();
var expectedResult = new Quaternion(1.0, -2.0, -3.0, -1.0);
var returnedResult = Quaternion.subtract(left, right, result);
expect(result).toBe(returnedResult);
expect(result).toEqual(expectedResult);
});
it("subtract works with this result parameter", function () {
var left = new Quaternion(2.0, 3.0, 4.0, 8.0);
var right = new Quaternion(1.0, 5.0, 7.0, 9.0);
var expectedResult = new Quaternion(1.0, -2.0, -3.0, -1.0);
var returnedResult = Quaternion.subtract(left, right, left);
expect(returnedResult).toBe(left);
expect(left).toEqual(expectedResult);
});
it("multiplyByScalar works ", function () {
var quaternion = new Quaternion(1.0, 2.0, 3.0, 4.0);
var result = new Quaternion();
var scalar = 2;
var expectedResult = new Quaternion(2.0, 4.0, 6.0, 8.0);
var returnedResult = Quaternion.multiplyByScalar(
quaternion,
scalar,
result
);
expect(result).toBe(returnedResult);
expect(result).toEqual(expectedResult);
});
it("multiplyByScalar works with a result parameter that is an input parameter", function () {
var quaternion = new Quaternion(1.0, 2.0, 3.0, 4.0);
var scalar = 2;
var expectedResult = new Quaternion(2.0, 4.0, 6.0, 8.0);
var returnedResult = Quaternion.multiplyByScalar(
quaternion,
scalar,
quaternion
);
expect(quaternion).toBe(returnedResult);
expect(quaternion).toEqual(expectedResult);
});
it("divideByScalar works", function () {
var quaternion = new Quaternion(1.0, 2.0, 3.0, 4.0);
var result = new Quaternion();
var scalar = 2;
var expectedResult = new Quaternion(0.5, 1.0, 1.5, 2.0);
var returnedResult = Quaternion.divideByScalar(quaternion, scalar, result);
expect(result).toBe(returnedResult);
expect(result).toEqual(expectedResult);
});
it("divideByScalar works with a result parameter that is an input parameter", function () {
var quaternion = new Quaternion(1.0, 2.0, 3.0, 4.0);
var scalar = 2;
var expectedResult = new Quaternion(0.5, 1.0, 1.5, 2.0);
var returnedResult = Quaternion.divideByScalar(
quaternion,
scalar,
quaternion
);
expect(quaternion).toBe(returnedResult);
expect(quaternion).toEqual(expectedResult);
});
it("axis works", function () {
// 60 degrees is used here to ensure that the sine and cosine of the half angle are not equal.
var angle = Math.PI / 3.0;
var cos = Math.cos(angle / 2.0);
var sin = Math.sin(angle / 2.0);
var expected = Cartesian3.normalize(
new Cartesian3(2.0, 3.0, 6.0),
new Cartesian3()
);
var quaternion = new Quaternion(
sin * expected.x,
sin * expected.y,
sin * expected.z,
cos
);
var result = new Cartesian3();
var returnedResult = Quaternion.computeAxis(quaternion, result);
expect(returnedResult).toEqualEpsilon(expected, CesiumMath.EPSILON15);
expect(result).toBe(returnedResult);
});
it("axis returns Cartesian3 0 when w equals 1.0", function () {
var expected = new Cartesian3(0.0, 0.0, 0.0);
var quaternion = new Quaternion(4.0, 2.0, 3.0, 1.0);
var result = new Cartesian3(1, 2, 3);
var returnedResult = Quaternion.computeAxis(quaternion, result);
expect(returnedResult).toEqual(expected);
expect(result).toBe(returnedResult);
});
it("angle works", function () {
// 60 degrees is used here to ensure that the sine and cosine of the half angle are not equal.
var angle = Math.PI / 3.0;
var cos = Math.cos(angle / 2.0);
var sin = Math.sin(angle / 2.0);
var axis = Cartesian3.normalize(
new Cartesian3(2.0, 3.0, 6.0),
new Cartesian3()
);
var quaternion = new Quaternion(
sin * axis.x,
sin * axis.y,
sin * axis.z,
cos
);
var result = Quaternion.computeAngle(quaternion);
expect(result).toEqualEpsilon(angle, CesiumMath.EPSILON15);
});
it("negate works", function () {
var quaternion = new Quaternion(1.0, -2.0, -5.0, 4.0);
var result = new Quaternion();
var expectedResult = new Quaternion(-1.0, 2.0, 5.0, -4.0);
var returnedResult = Quaternion.negate(quaternion, result);
expect(result).toBe(returnedResult);
expect(result).toEqual(expectedResult);
});
it("negate works with a result parameter that is an input parameter", function () {
var quaternion = new Quaternion(1.0, -2.0, -5.0);
var expectedResult = new Quaternion(-1.0, 2.0, 5.0);
var returnedResult = Quaternion.negate(quaternion, quaternion);
expect(quaternion).toBe(returnedResult);
expect(quaternion).toEqual(expectedResult);
});
it("lerp works", function () {
var start = new Quaternion(4.0, 8.0, 10.0, 20.0);
var end = new Quaternion(8.0, 20.0, 20.0, 30.0);
var t = 0.25;
var result = new Quaternion();
var expectedResult = new Quaternion(5.0, 11.0, 12.5, 22.5);
var returnedResult = Quaternion.lerp(start, end, t, result);
expect(result).toBe(returnedResult);
expect(result).toEqual(expectedResult);
});
it("lerp works with a result parameter that is an input parameter", function () {
var start = new Quaternion(4.0, 8.0, 10.0, 20.0);
var end = new Quaternion(8.0, 20.0, 20.0, 30.0);
var t = 0.25;
var expectedResult = new Quaternion(5.0, 11.0, 12.5, 22.5);
var returnedResult = Quaternion.lerp(start, end, t, start);
expect(start).toBe(returnedResult);
expect(start).toEqual(expectedResult);
});
it("lerp extrapolate forward", function () {
var start = new Quaternion(4.0, 8.0, 10.0, 20.0);
var end = new Quaternion(8.0, 20.0, 20.0, 30.0);
var t = 2.0;
var expectedResult = new Quaternion(12.0, 32.0, 30.0, 40.0);
var result = Quaternion.lerp(start, end, t, new Quaternion());
expect(result).toEqual(expectedResult);
});
it("lerp extrapolate backward", function () {
var start = new Quaternion(4.0, 8.0, 10.0, 20.0);
var end = new Quaternion(8.0, 20.0, 20.0, 30.0);
var t = -1.0;
var expectedResult = new Quaternion(0.0, -4.0, 0.0, 10.0);
var result = Quaternion.lerp(start, end, t, new Quaternion());
expect(result).toEqual(expectedResult);
});
it("slerp works", function () {
var start = Quaternion.normalize(
new Quaternion(0.0, 0.0, 0.0, 1.0),
new Quaternion()
);
var end = new Quaternion(
0.0,
0.0,
Math.sin(CesiumMath.PI_OVER_FOUR),
Math.cos(CesiumMath.PI_OVER_FOUR)
);
var expected = new Quaternion(
0.0,
0.0,
Math.sin(Math.PI / 8.0),
Math.cos(Math.PI / 8.0)
);
var result = new Quaternion();
var returnedResult = Quaternion.slerp(start, end, 0.5, result);
expect(result).toEqualEpsilon(expected, CesiumMath.EPSILON15);
expect(result).toBe(returnedResult);
});
it("slerp works with a result parameter that is an input parameter", function () {
var start = Quaternion.normalize(
new Quaternion(0.0, 0.0, 0.0, 1.0),
new Quaternion()
);
var end = new Quaternion(
0.0,
0.0,
Math.sin(CesiumMath.PI_OVER_FOUR),
Math.cos(CesiumMath.PI_OVER_FOUR)
);
var expected = new Quaternion(
0.0,
0.0,
Math.sin(Math.PI / 8.0),
Math.cos(Math.PI / 8.0)
);
var returnedResult = Quaternion.slerp(start, end, 0.5, start);
expect(start).toEqualEpsilon(expected, CesiumMath.EPSILON15);
expect(start).toBe(returnedResult);
});
it("slerp works with obtuse angles", function () {
var start = Quaternion.normalize(
new Quaternion(0.0, 0.0, 0.0, -1.0),
new Quaternion()
);
var end = new Quaternion(
0.0,
0.0,
Math.sin(CesiumMath.PI_OVER_FOUR),
Math.cos(CesiumMath.PI_OVER_FOUR)
);
var expected = new Quaternion(
0.0,
0.0,
-Math.sin(Math.PI / 8.0),
-Math.cos(Math.PI / 8.0)
);
expect(Quaternion.slerp(start, end, 0.5, new Quaternion())).toEqualEpsilon(
expected,
CesiumMath.EPSILON15
);
});
it("slerp uses lerp when dot product is close to 1", function () {
var start = new Quaternion(0.0, 0.0, 0.0, 1.0);
var end = new Quaternion(1.0, 2.0, 3.0, 1.0);
var expected = new Quaternion(0.5, 1.0, 1.5, 1.0);
var result = new Quaternion();
expect(Quaternion.slerp(start, end, 0.0, result)).toEqual(start);
expect(Quaternion.slerp(start, end, 1.0, result)).toEqual(end);
expect(Quaternion.slerp(start, end, 0.5, result)).toEqual(expected);
});
it("slerp uses lerp when dot product is close to 1 and a result parameter", function () {
var start = new Quaternion(0.0, 0.0, 0.0, 1.0);
var end = new Quaternion(1.0, 2.0, 3.0, 1.0);
var result = new Quaternion();
var actual = Quaternion.slerp(start, end, 0.0, result);
expect(actual).toBe(result);
expect(result).toEqual(start);
});
it("log works", function () {
var axis = Cartesian3.normalize(
new Cartesian3(1.0, -1.0, 1.0),
new Cartesian3()
);
var angle = CesiumMath.PI_OVER_FOUR;
var quat = Quaternion.fromAxisAngle(axis, angle);
var result = new Cartesian3();
var log = Quaternion.log(quat, result);
var expected = Cartesian3.multiplyByScalar(
axis,
angle * 0.5,
new Cartesian3()
);
expect(log).toBe(result);
expect(log).toEqualEpsilon(expected, CesiumMath.EPSILON15);
});
it("exp works", function () {
var axis = Cartesian3.normalize(
new Cartesian3(1.0, -1.0, 1.0),
new Cartesian3()
);
var angle = CesiumMath.PI_OVER_FOUR;
var cartesian = Cartesian3.multiplyByScalar(
axis,
angle * 0.5,
new Cartesian3()
);
var result = new Quaternion();
var exp = Quaternion.exp(cartesian, result);
var expected = Quaternion.fromAxisAngle(axis, angle);
expect(exp).toBe(result);
expect(exp).toEqualEpsilon(expected, CesiumMath.EPSILON15);
});
it("squad and computeInnerQuadrangle work", function () {
var q0 = Quaternion.fromAxisAngle(Cartesian3.UNIT_X, 0.0);
var q1 = Quaternion.fromAxisAngle(
Cartesian3.UNIT_X,
CesiumMath.PI_OVER_FOUR
);
var q2 = Quaternion.fromAxisAngle(
Cartesian3.UNIT_Z,
CesiumMath.PI_OVER_FOUR
);
var q3 = Quaternion.fromAxisAngle(
Cartesian3.UNIT_X,
-CesiumMath.PI_OVER_FOUR
);
var s1Result = new Quaternion();
var s1 = Quaternion.computeInnerQuadrangle(q0, q1, q2, s1Result);
expect(s1).toBe(s1Result);
var s2 = Quaternion.computeInnerQuadrangle(q1, q2, q3, new Quaternion());
var squadResult = new Quaternion();
var squad = Quaternion.squad(q1, q2, s1, s2, 0.0, squadResult);
expect(squad).toBe(squadResult);
expect(squad).toEqualEpsilon(q1, CesiumMath.EPSILON15);
});
it("fastSlerp works", function () {
var start = Quaternion.normalize(
new Quaternion(0.0, 0.0, 0.0, 1.0),
new Quaternion()
);
var end = new Quaternion(
0.0,
0.0,
Math.sin(CesiumMath.PI_OVER_FOUR),
Math.cos(CesiumMath.PI_OVER_FOUR)
);
var expected = new Quaternion(
0.0,
0.0,
Math.sin(Math.PI / 8.0),
Math.cos(Math.PI / 8.0)
);
var result = new Quaternion();
var returnedResult = Quaternion.fastSlerp(start, end, 0.5, result);
expect(result).toEqualEpsilon(expected, CesiumMath.EPSILON6);
expect(result).toBe(returnedResult);
});
it("fastSlerp works with a result parameter that is an input parameter", function () {
var start = Quaternion.normalize(
new Quaternion(0.0, 0.0, 0.0, 1.0),
new Quaternion()
);
var end = new Quaternion(
0.0,
0.0,
Math.sin(CesiumMath.PI_OVER_FOUR),
Math.cos(CesiumMath.PI_OVER_FOUR)
);
var expected = new Quaternion(
0.0,
0.0,
Math.sin(Math.PI / 8.0),
Math.cos(Math.PI / 8.0)
);
var returnedResult = Quaternion.fastSlerp(start, end, 0.5, start);
expect(start).toEqualEpsilon(expected, CesiumMath.EPSILON6);
expect(start).toBe(returnedResult);
});
it("fastSlerp works with obtuse angles", function () {
var start = Quaternion.normalize(
new Quaternion(0.0, 0.0, 0.0, -1.0),
new Quaternion()
);
var end = new Quaternion(
0.0,
0.0,
Math.sin(CesiumMath.PI_OVER_FOUR),
Math.cos(CesiumMath.PI_OVER_FOUR)
);
var expected = new Quaternion(
0.0,
0.0,
-Math.sin(Math.PI / 8.0),
-Math.cos(Math.PI / 8.0)
);
expect(
Quaternion.fastSlerp(start, end, 0.5, new Quaternion())
).toEqualEpsilon(expected, CesiumMath.EPSILON6);
});
it("fastSlerp vs slerp", function () {
var start = Quaternion.normalize(
new Quaternion(0.0, 0.0, 0.0, 1.0),
new Quaternion()
);
var end = new Quaternion(
0.0,
0.0,
Math.sin(CesiumMath.PI_OVER_FOUR),
Math.cos(CesiumMath.PI_OVER_FOUR)
);
var expected = Quaternion.slerp(start, end, 0.25, new Quaternion());
var actual = Quaternion.fastSlerp(start, end, 0.25, new Quaternion());
expect(actual).toEqualEpsilon(expected, CesiumMath.EPSILON6);
expected = Quaternion.slerp(start, end, 0.5, new Quaternion());
actual = Quaternion.fastSlerp(start, end, 0.5, new Quaternion());
expect(actual).toEqualEpsilon(expected, CesiumMath.EPSILON6);
expected = Quaternion.slerp(start, end, 0.75, new Quaternion());
actual = Quaternion.fastSlerp(start, end, 0.75, new Quaternion());
expect(actual).toEqualEpsilon(expected, CesiumMath.EPSILON6);
});
it("fastSquad works", function () {
var q0 = Quaternion.fromAxisAngle(Cartesian3.UNIT_X, 0.0);
var q1 = Quaternion.fromAxisAngle(
Cartesian3.UNIT_X,
CesiumMath.PI_OVER_FOUR
);
var q2 = Quaternion.fromAxisAngle(
Cartesian3.UNIT_Z,
CesiumMath.PI_OVER_FOUR
);
var q3 = Quaternion.fromAxisAngle(
Cartesian3.UNIT_X,
-CesiumMath.PI_OVER_FOUR
);
var s1 = Quaternion.computeInnerQuadrangle(q0, q1, q2, new Quaternion());
var s2 = Quaternion.computeInnerQuadrangle(q1, q2, q3, new Quaternion());
var squadResult = new Quaternion();
var squad = Quaternion.fastSquad(q1, q2, s1, s2, 0.0, squadResult);
expect(squad).toBe(squadResult);
expect(squad).toEqualEpsilon(q1, CesiumMath.EPSILON6);
});
it("fastSquad vs squad", function () {
var q0 = Quaternion.fromAxisAngle(Cartesian3.UNIT_X, 0.0);
var q1 = Quaternion.fromAxisAngle(
Cartesian3.UNIT_X,
CesiumMath.PI_OVER_FOUR
);
var q2 = Quaternion.fromAxisAngle(
Cartesian3.UNIT_Z,
CesiumMath.PI_OVER_FOUR
);
var q3 = Quaternion.fromAxisAngle(
Cartesian3.UNIT_X,
-CesiumMath.PI_OVER_FOUR
);
var s1 = Quaternion.computeInnerQuadrangle(q0, q1, q2, new Quaternion());
var s2 = Quaternion.computeInnerQuadrangle(q1, q2, q3, new Quaternion());
var actual = Quaternion.fastSquad(q1, q2, s1, s2, 0.25, new Quaternion());
var expected = Quaternion.squad(q1, q2, s1, s2, 0.25, new Quaternion());
expect(actual).toEqualEpsilon(expected, CesiumMath.EPSILON6);
actual = Quaternion.fastSquad(q1, q2, s1, s2, 0.5, new Quaternion());
expected = Quaternion.squad(q1, q2, s1, s2, 0.5, new Quaternion());
expect(actual).toEqualEpsilon(expected, CesiumMath.EPSILON6);
actual = Quaternion.fastSquad(q1, q2, s1, s2, 0.75, new Quaternion());
expected = Quaternion.squad(q1, q2, s1, s2, 0.75, new Quaternion());
expect(actual).toEqualEpsilon(expected, CesiumMath.EPSILON6);
});
it("equals", function () {
var quaternion = new Quaternion(1.0, 2.0, 3.0, 4.0);
expect(
Quaternion.equals(quaternion, new Quaternion(1.0, 2.0, 3.0, 4.0))
).toEqual(true);
expect(
Quaternion.equals(quaternion, new Quaternion(2.0, 2.0, 3.0, 4.0))
).toEqual(false);
expect(
Quaternion.equals(quaternion, new Quaternion(2.0, 1.0, 3.0, 4.0))
).toEqual(false);
expect(
Quaternion.equals(quaternion, new Quaternion(1.0, 2.0, 4.0, 4.0))
).toEqual(false);
expect(
Quaternion.equals(quaternion, new Quaternion(1.0, 2.0, 3.0, 5.0))
).toEqual(false);
expect(Quaternion.equals(quaternion, undefined)).toEqual(false);
});
it("equalsEpsilon", function () {
var quaternion = new Quaternion(1.0, 2.0, 3.0, 4.0);
expect(
Quaternion.equalsEpsilon(
quaternion,
new Quaternion(1.0, 2.0, 3.0, 4.0),
0.0
)
).toEqual(true);
expect(
Quaternion.equalsEpsilon(
quaternion,
new Quaternion(1.0, 2.0, 3.0, 4.0),
1.0
)
).toEqual(true);
expect(
Quaternion.equalsEpsilon(
quaternion,
new Quaternion(2.0, 2.0, 3.0, 4.0),
1.0
)
).toEqual(true);
expect(
Quaternion.equalsEpsilon(
quaternion,
new Quaternion(1.0, 3.0, 3.0, 4.0),
1.0
)
).toEqual(true);
expect(
Quaternion.equalsEpsilon(
quaternion,
new Quaternion(1.0, 2.0, 4.0, 4.0),
1.0
)
).toEqual(true);
expect(
Quaternion.equalsEpsilon(
quaternion,
new Quaternion(1.0, 2.0, 3.0, 5.0),
1.0
)
).toEqual(true);
expect(
Quaternion.equalsEpsilon(
quaternion,
new Quaternion(2.0, 2.0, 3.0, 4.0),
0.99999
)
).toEqual(false);
expect(
Quaternion.equalsEpsilon(
quaternion,
new Quaternion(1.0, 3.0, 3.0, 4.0),
0.99999
)
).toEqual(false);
expect(
Quaternion.equalsEpsilon(
quaternion,
new Quaternion(1.0, 2.0, 4.0, 4.0),
0.99999
)
).toEqual(false);
expect(
Quaternion.equalsEpsilon(
quaternion,
new Quaternion(1.0, 2.0, 3.0, 5.0),
0.99999
)
).toEqual(false);
expect(Quaternion.equalsEpsilon(quaternion, undefined, 1)).toEqual(false);
});
it("toString", function () {
var quaternion = new Quaternion(1.123, 2.345, 6.789, 6.123);
expect(quaternion.toString()).toEqual("(1.123, 2.345, 6.789, 6.123)");
});
it("fromAxisAngle throws with undefined axis", function () {
expect(function () {
Quaternion.fromAxisAngle(undefined, 1.0);
}).toThrowDeveloperError();
});
it("fromAxisAngle throws with non-numeric angle", function () {
expect(function () {
Quaternion.fromAxisAngle(Cartesian3.UNIT_X, {});
}).toThrowDeveloperError();
});
it("fromRotationMatrix throws with undefined matrix", function () {
expect(function () {
Quaternion.fromRotationMatrix(undefined);
}).toThrowDeveloperError();
});
it("clone returns undefined with no parameter", function () {
expect(Quaternion.clone()).toBeUndefined();
});
it("conjugate throws with no parameter", function () {
expect(function () {
Quaternion.conjugate();
}).toThrowDeveloperError();
});
it("magnitudeSquared throws with no parameter", function () {
expect(function () {
Quaternion.magnitudeSquared();
}).toThrowDeveloperError();
});
it("magnitude throws with no parameter", function () {
expect(function () {
Quaternion.magnitude();
}).toThrowDeveloperError();
});
it("normalize throws with no parameter", function () {
expect(function () {
Quaternion.normalize();
}).toThrowDeveloperError();
});
it("inverse throws with no parameter", function () {
expect(function () {
Quaternion.inverse();
}).toThrowDeveloperError();
});
it("dot throws with no left parameter", function () {
expect(function () {
Quaternion.dot(undefined, new Quaternion());
}).toThrowDeveloperError();
});
it("dot throws with no right parameter", function () {
expect(function () {
Quaternion.dot(new Quaternion(), undefined);
}).toThrowDeveloperError();
});
it("multiply throws with no right parameter", function () {
expect(function () {
Quaternion.multiply(new Quaternion(), undefined);
}).toThrowDeveloperError();
});
it("multiply throws with no left parameter", function () {
expect(function () {
Quaternion.multiply(undefined, new Quaternion());
}).toThrowDeveloperError();
});
it("add throws with no left parameter", function () {
expect(function () {
Quaternion.add(undefined, new Quaternion());
}).toThrowDeveloperError();
});
it("add throws with no right parameter", function () {
expect(function () {
Quaternion.add(new Quaternion(), undefined);
}).toThrowDeveloperError();
});
it("subtract throws with no left parameter", function () {
expect(function () {
Quaternion.subtract(undefined, new Quaternion());
}).toThrowDeveloperError();
});
it("subtract throws with no right parameter", function () {
expect(function () {
Quaternion.subtract(new Quaternion(), undefined);
}).toThrowDeveloperError();
});
it("multiplyByScalar throws with no quaternion parameter", function () {
expect(function () {
Quaternion.multiplyByScalar(undefined, 2.0);
}).toThrowDeveloperError();
});
it("multiplyByScalar throws with no scalar parameter", function () {
expect(function () {
Quaternion.multiplyByScalar(new Quaternion(), undefined);
}).toThrowDeveloperError();
});
it("divideByScalar throws with no quaternion parameter", function () {
expect(function () {
Quaternion.divideByScalar(undefined, 2.0);
}).toThrowDeveloperError();
});
it("divideByScalar throws with no scalar parameter", function () {
expect(function () {
Quaternion.divideByScalar(new Quaternion(), undefined);
}).toThrowDeveloperError();
});
it("axis throws with no parameter", function () {
expect(function () {
Quaternion.computeAxis(undefined);
}).toThrowDeveloperError();
});
it("angle throws with no parameter", function () {
expect(function () {
Quaternion.computeAngle(undefined);
}).toThrowDeveloperError();
});
it("negate throws with no quaternion parameter", function () {
expect(function () {
Quaternion.negate(undefined);
}).toThrowDeveloperError();
});
it("lerp throws with no start parameter", function () {
var end = new Quaternion(8.0, 20.0, 6.0);
var t = 0.25;
expect(function () {
Quaternion.lerp(undefined, end, t);
}).toThrowDeveloperError();
});
it("lerp throws with no end parameter", function () {
var start = new Quaternion(4.0, 8.0, 6.0);
var t = 0.25;
expect(function () {
Quaternion.lerp(start, undefined, t);
}).toThrowDeveloperError();
});
it("lerp throws with no t parameter", function () {
var start = new Quaternion(4.0, 8.0, 6.0, 7.0);
var end = new Quaternion(8.0, 20.0, 6.0, 7.0);
expect(function () {
Quaternion.lerp(start, end, undefined);
}).toThrowDeveloperError();
});
it("slerp throws with no start parameter", function () {
var end = new Quaternion(8.0, 20.0, 6.0);
var t = 0.25;
expect(function () {
Quaternion.slerp(undefined, end, t);
}).toThrowDeveloperError();
});
it("slerp throws with no end parameter", function () {
var start = new Quaternion(4.0, 8.0, 6.0);
var t = 0.25;
expect(function () {
Quaternion.slerp(start, undefined, t);
}).toThrowDeveloperError();
});
it("slerp throws with no t parameter", function () {
var start = new Quaternion(4.0, 8.0, 6.0, 7.0);
var end = new Quaternion(8.0, 20.0, 6.0, 7.0);
expect(function () {
Quaternion.slerp(start, end, undefined);
}).toThrowDeveloperError();
});
it("log throws with no quaternion parameter", function () {
expect(function () {
Quaternion.log();
}).toThrowDeveloperError();
});
it("exp throws with no cartesian parameter", function () {
expect(function () {
Quaternion.exp();
}).toThrowDeveloperError();
});
it("computeInnerQuadrangle throws without q0, q1, or q2 parameter", function () {
expect(function () {
Quaternion.computeInnerQuadrangle();
}).toThrowDeveloperError();
});
it("squad throws without q0, q1, s0, or s1 parameter", function () {
expect(function () {
Quaternion.squad();
}).toThrowDeveloperError();
});
it("squad throws without t parameter", function () {
expect(function () {
Quaternion.squad(
new Quaternion(),
new Quaternion(),
new Quaternion(),
new Quaternion()
);
}).toThrowDeveloperError();
});
it("conjugate throws with no result", function () {
expect(function () {
Quaternion.conjugate(new Quaternion());
}).toThrowDeveloperError();
});
it("add throws with no result", function () {
expect(function () {
Quaternion.add(new Quaternion(), new Quaternion());
}).toThrowDeveloperError();
});
it("subtract throws with no result", function () {
expect(function () {
Quaternion.subtract(new Quaternion(), new Quaternion());
}).toThrowDeveloperError();
});
it("negate throws with no result", function () {
expect(function () {
Quaternion.negate(new Quaternion());
}).toThrowDeveloperError();
});
it("multiply throws with no result", function () {
expect(function () {
Quaternion.multiply(new Quaternion(), new Quaternion());
}).toThrowDeveloperError();
});
it("multiplyByScalar throws with no result", function () {
expect(function () {
Quaternion.multiplyByScalar(new Quaternion(), 3);
}).toThrowDeveloperError();
});
it("divideByScalar throws with no result", function () {
expect(function () {
Quaternion.divideByScalar(new Quaternion(), 3);
}).toThrowDeveloperError();
});
it("axis throws with no result", function () {
expect(function () {
Quaternion.computeAxis(new Quaternion());
}).toThrowDeveloperError();
});
it("lerp throws with no result", function () {
expect(function () {
Quaternion.lerp(new Quaternion(), new Quaternion(), 2);
}).toThrowDeveloperError();
});
it("slerp throws with no result", function () {
expect(function () {
Quaternion.slerp(new Quaternion(), new Quaternion(), 2);
}).toThrowDeveloperError();
});
it("log throws with no result", function () {
expect(function () {
Quaternion.log(new Quaternion());
}).toThrowDeveloperError();
});
it("exp throws with no result", function () {
expect(function () {
Quaternion.exp(new Cartesian3());
}).toThrowDeveloperError();
});
it("computeInnerQuadrangle throws with no result", function () {
expect(function () {
Quaternion.computeInnerQuadrangle(
new Quaternion(),
new Quaternion(),
new Quaternion()
);
}).toThrowDeveloperError();
});
it("squad throws with no result", function () {
expect(function () {
Quaternion.squad(
new Quaternion(),
new Quaternion(),
new Quaternion(),
new Quaternion(),
3
);
}).toThrowDeveloperError();
});
it("fastSlerp throws with no start", function () {
expect(function () {
Quaternion.fastSlerp();
}).toThrowDeveloperError();
});
it("fastSlerp throws with no end", function () {
expect(function () {
Quaternion.fastSlerp(new Quaternion());
}).toThrowDeveloperError();
});
it("fastSlerp throws with no t", function () {
expect(function () {
Quaternion.fastSlerp(new Quaternion(), new Quaternion());
}).toThrowDeveloperError();
});
it("fastSlerp throws with no result", function () {
expect(function () {
Quaternion.fastSlerp(new Quaternion(), new Quaternion(), 2);
}).toThrowDeveloperError();
});
it("fastSquad throws with no q0", function () {
expect(function () {
Quaternion.fastSquad();
}).toThrowDeveloperError();
});
it("fastSquad throws with no q1", function () {
expect(function () {
Quaternion.fastSquad(new Quaternion());
}).toThrowDeveloperError();
});
it("fastSquad throws with no s0", function () {
expect(function () {
Quaternion.fastSquad(new Quaternion(), new Quaternion());
}).toThrowDeveloperError();
});
it("fastSquad throws with no s1", function () {
expect(function () {
Quaternion.fastSquad(
new Quaternion(),
new Quaternion(),
new Quaternion()
);
}).toThrowDeveloperError();
});
it("fastSquad throws with no t", function () {
expect(function () {
Quaternion.fastSquad(
new Quaternion(),
new Quaternion(),
new Quaternion(),
new Quaternion()
);
}).toThrowDeveloperError();
});
it("fastSquad throws with no result", function () {
expect(function () {
Quaternion.fastSquad(
new Quaternion(),
new Quaternion(),
new Quaternion(),
new Quaternion(),
3
);
}).toThrowDeveloperError();
});
var q = new Quaternion(1, 2, 3, 4);
Quaternion.normalize(q, q);
createPackableSpecs(Quaternion, q, [q.x, q.y, q.z, q.w]);
});