3 import static org.testng.Assert.assertEquals;
5 import jalview.math.RotatableMatrix.Axis;
7 import java.io.ByteArrayOutputStream;
8 import java.io.PrintStream;
10 import org.testng.annotations.BeforeMethod;
11 import org.testng.annotations.Test;
13 public class RotatableMatrixTest
15 private static final String NL = System.lineSeparator();
17 private RotatableMatrix rm;
19 @BeforeMethod(alwaysRun = true)
22 rm = new RotatableMatrix();
29 for (int i = 1; i <= 3; i++)
31 for (int j = 1; j <= 3; j++)
33 rm.setValue(i - 1, j - 1, i * j / 2f);
38 @Test(groups = "Functional")
39 public void testPrint()
41 String expected = "0.5 1.0 1.5" + NL + "1.0 2.0 3.0" + NL
43 ByteArrayOutputStream os = new ByteArrayOutputStream();
44 PrintStream ps = new PrintStream(os, true);
46 String result = new String(os.toByteArray());
47 assertEquals(result, expected);
50 @Test(groups = "Functional")
51 public void testPreMultiply()
53 float[][] pre = new float[3][3];
55 for (int j = 0; j < 3; j++)
57 for (int k = 0; k < 3; k++)
66 * check rm[i, j] is now the product of the i'th row of pre
67 * and the j'th column of (original) rm
69 for (int j = 0; j < 3; j++)
71 for (int k = 0; k < 3; k++)
74 for (int l = 0; l < 3; l++)
76 float rm_l_k = (l + 1) * (k + 1) / 2f;
77 expected += pre[j][l] * rm_l_k;
79 assertEquals(rm.getValue(j, k), expected,
80 String.format("[%d, %d]", j, k));
85 @Test(groups = "Functional")
86 public void testVectorMultiply()
88 float[] result = rm.vectorMultiply(new float[] { 2f, 3f, 4.5f });
90 // vector times first column of matrix
91 assertEquals(result[0], 2f * 0.5f + 3f * 1f + 4.5f * 1.5f);
93 // vector times second column of matrix
94 assertEquals(result[1], 2f * 1.0f + 3f * 2f + 4.5f * 3f);
96 // vector times third column of matrix
97 assertEquals(result[2], 2f * 1.5f + 3f * 3f + 4.5f * 4.5f);
100 @Test(groups = "Functional")
101 public void testGetRotation()
104 double cosTheta = Math.cos((theta * Math.PI / 180f));
105 double sinTheta = Math.sin((theta * Math.PI / 180f));
108 * sanity check that sin(60) = sqrt(3) / 2, cos(60) = 1/2
110 double delta = 0.0001d;
111 assertEquals(cosTheta, 0.5f, delta);
112 assertEquals(sinTheta, Math.sqrt(3d) / 2d, delta);
115 * so far so good, now verify rotations
116 * @see https://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations
120 * 60 degrees about X axis should be
124 * but code applies the negative of this
125 * nb cos(-x) = cos(x), sin(-x) = -sin(x)
127 float[][] rot = RotatableMatrix.getRotation(theta, Axis.X);
128 assertEquals(rot[0][0], 1f, delta);
129 assertEquals(rot[0][1], 0f, delta);
130 assertEquals(rot[0][2], 0f, delta);
131 assertEquals(rot[1][0], 0f, delta);
132 assertEquals(rot[1][1], cosTheta, delta);
133 assertEquals(rot[1][2], sinTheta, delta);
134 assertEquals(rot[2][0], 0f, delta);
135 assertEquals(rot[2][1], -sinTheta, delta);
136 assertEquals(rot[2][2], cosTheta, delta);
139 * 60 degrees about Y axis should be
143 * but code applies the negative of this
145 rot = RotatableMatrix.getRotation(theta, Axis.Y);
146 assertEquals(rot[0][0], cosTheta, delta);
147 assertEquals(rot[0][1], 0f, delta);
148 assertEquals(rot[0][2], -sinTheta, delta);
149 assertEquals(rot[1][0], 0f, delta);
150 assertEquals(rot[1][1], 1f, delta);
151 assertEquals(rot[1][2], 0f, delta);
152 assertEquals(rot[2][0], sinTheta, delta);
153 assertEquals(rot[2][1], 0f, delta);
154 assertEquals(rot[2][2], cosTheta, delta);
157 * 60 degrees about Z axis should be
163 rot = RotatableMatrix.getRotation(theta, Axis.Z);
164 assertEquals(rot[0][0], cosTheta, delta);
165 assertEquals(rot[0][1], -sinTheta, delta);
166 assertEquals(rot[0][2], 0f, delta);
167 assertEquals(rot[1][0], sinTheta, delta);
168 assertEquals(rot[1][1], cosTheta, delta);
169 assertEquals(rot[1][2], 0f, delta);
170 assertEquals(rot[2][0], 0f, delta);
171 assertEquals(rot[2][1], 0f, delta);
172 assertEquals(rot[2][2], 1f, delta);