package com.facebook.react.uimanager;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import static org.fest.assertions.api.Assertions.assertThat;
/**
* Test for {@link MatrixMathHelper}
*/
@RunWith(RobolectricTestRunner.class)
public class MatrixMathHelperTest {
private void verifyZRotatedMatrix(double degrees, double rotX, double rotY, double rotZ) {
MatrixMathHelper.MatrixDecompositionContext ctx =
new MatrixMathHelper.MatrixDecompositionContext();
double[] matrix = createRotateZ(degreesToRadians(degrees));
MatrixMathHelper.decomposeMatrix(matrix, ctx);
assertThat(ctx.rotationDegrees).containsSequence(rotX, rotY, rotZ);
}
private void verifyYRotatedMatrix(double degrees, double rotX, double rotY, double rotZ) {
MatrixMathHelper.MatrixDecompositionContext ctx =
new MatrixMathHelper.MatrixDecompositionContext();
double[] matrix = createRotateY(degreesToRadians(degrees));
MatrixMathHelper.decomposeMatrix(matrix, ctx);
assertThat(ctx.rotationDegrees).containsSequence(rotX, rotY, rotZ);
}
private void verifyXRotatedMatrix(double degrees, double rotX, double rotY, double rotZ) {
MatrixMathHelper.MatrixDecompositionContext ctx =
new MatrixMathHelper.MatrixDecompositionContext();
double[] matrix = createRotateX(degreesToRadians(degrees));
MatrixMathHelper.decomposeMatrix(matrix, ctx);
assertThat(ctx.rotationDegrees).containsSequence(rotX, rotY, rotZ);
}
@Test
public void testDecomposing4x4MatrixToProduceAccurateZaxisAngles() {
MatrixMathHelper.MatrixDecompositionContext ctx =
new MatrixMathHelper.MatrixDecompositionContext();
MatrixMathHelper.decomposeMatrix(
new double[]{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1},
ctx);
assertThat(ctx.rotationDegrees).containsSequence(0d, 0d, 0d);
double[] angles = new double[]{30, 45, 60, 75, 90, 100, 115, 120, 133, 167};
for (double angle : angles) {
verifyZRotatedMatrix(angle, 0d, 0d, angle);
verifyZRotatedMatrix(-angle, 0d, 0d, -angle);
}
verifyZRotatedMatrix(180d, 0d, 0d, 180d);
// all values are between 0 and 180;
// change of sign and direction in the third and fourth quadrant
verifyZRotatedMatrix(222, 0d, 0d, -138d);
verifyZRotatedMatrix(270, 0d, 0d, -90d);
// 360 is expressed as 0
verifyZRotatedMatrix(360, 0d, 0d, 0d);
verifyZRotatedMatrix(33.33333333, 0d, 0d, 33.333d);
verifyZRotatedMatrix(86.75309, 0d, 0d, 86.753d);
verifyZRotatedMatrix(42.00000000001, 0d, 0d, 42d);
verifyZRotatedMatrix(42.99999999999, 0d, 0d, 43d);
verifyZRotatedMatrix(42.99999999999, 0d, 0d, 43d);
verifyZRotatedMatrix(42.49999999999, 0d, 0d, 42.5d);
verifyZRotatedMatrix(42.55555555555, 0d, 0d, 42.556d);
}
@Test
public void testDecomposing4x4MatrixToProduceAccurateYaxisAngles() {
double[] angles = new double[]{30, 45, 60, 75, 90, 100, 110, 120, 133, 167};
for (double angle : angles) {
verifyYRotatedMatrix(angle, 0d, angle, 0d);
verifyYRotatedMatrix(-angle, 0d, -angle, 0d);
}
// all values are between 0 and 180;
// change of sign and direction in the third and fourth quadrant
verifyYRotatedMatrix(222, 0d, -138d, 0d);
verifyYRotatedMatrix(270, 0d, -90d, 0d);
verifyYRotatedMatrix(360, 0d, 0d, 0d);
}
@Test
public void testDecomposing4x4MatrixToProduceAccurateXaxisAngles() {
double[] angles = new double[]{30, 45, 60, 75, 90, 100, 110, 120, 133, 167};
for (double angle : angles) {
verifyXRotatedMatrix(angle, angle, 0d, 0d);
verifyXRotatedMatrix(-angle, -angle, 0d, 0d);
}
// all values are between 0 and 180;
// change of sign and direction in the third and fourth quadrant
verifyXRotatedMatrix(222, -138d, 0d, 0d);
verifyXRotatedMatrix(270, -90d, 0d, 0d);
verifyXRotatedMatrix(360, 0d, 0d, 0d);
}
private static double degreesToRadians(double degrees) {
return degrees * Math.PI / 180;
}
private static double[] createRotateZ(double radians) {
double[] mat = MatrixMathHelper.createIdentityMatrix();
mat[0] = Math.cos(radians);
mat[1] = Math.sin(radians);
mat[4] = -Math.sin(radians);
mat[5] = Math.cos(radians);
return mat;
}
private static double[] createRotateY(double radians) {
double[] mat = MatrixMathHelper.createIdentityMatrix();
mat[0] = Math.cos(radians);
mat[2] = -Math.sin(radians);
mat[8] = Math.sin(radians);
mat[10] = Math.cos(radians);
return mat;
}
private static double[] createRotateX(double radians) {
double[] mat = MatrixMathHelper.createIdentityMatrix();
mat[5] = Math.cos(radians);
mat[6] = Math.sin(radians);
mat[9] = -Math.sin(radians);
mat[10] = Math.cos(radians);
return mat;
}
}