4 package jp.sfjp.mikutoga.math;
6 import org.junit.After;
7 import org.junit.AfterClass;
8 import org.junit.Before;
9 import org.junit.BeforeClass;
10 import org.junit.Test;
11 import static org.junit.Assert.*;
16 public strictfp class MkQuatTest {
18 private static final double RAD_90DEG = StrictMath.PI / 2.0;
19 private static final double RAD_60DEG = StrictMath.PI / 3.0;
20 private static final double RAD_45DEG = StrictMath.PI / 4.0;
21 private static final double RAD_30DEG = StrictMath.PI / 6.0;
22 private static final double RAD_15DEG = StrictMath.PI / 12.0;
23 private static final double EPSILON = StrictMath.ulp(1.0);
29 public static void setUpClass() {
33 public static void tearDownClass() {
41 public void tearDown() {
45 * StrictMath.toRadians(6) results are not same between JDK8 & JDK9.
47 private static double toRadians(double deg){
48 double result = deg * 0.01745329251994329576924;
49 // assert StrictMath.toRadians(6) == 0.10471975511965977; //JDK8
50 // assert StrictMath.toRadians(6) == 0.10471975511965978; //JDK9
54 private static void assert0UlpEquals(double expected, double result){
55 assertUlpEquals(expected, result, 0);
59 private static void assertUlpEquals(double expected, double result, int ulpNum){
60 double ulpExpected = StrictMath.ulp(expected);
61 double ulpResult = StrictMath.ulp(result);
62 double ulp = StrictMath.max(ulpExpected, ulpResult);
63 double delta = ulp * ulpNum;
66 assertEquals(expected, result, delta);
67 }catch(AssertionError e){
68 double dist = StrictMath.abs(expected - result);
69 String msg = e.getMessage();
70 msg += " ULP * " + (dist / ulp);
71 AssertionError err = new AssertionError(msg);
80 * Test of constructor, of class MkQuat.
83 public void testCons() {
84 System.out.println("constructor");
89 assert0UlpEquals(0.0, qq.getQ1());
90 assert0UlpEquals(0.0, qq.getQ2());
91 assert0UlpEquals(0.0, qq.getQ3());
92 assert0UlpEquals(1.0, qq.getQW());
95 assert0UlpEquals(2.0, qq.getQ1());
96 assert0UlpEquals(0.0, qq.getQ2());
97 assert0UlpEquals(0.0, qq.getQ3());
98 assert0UlpEquals(1.0, qq.getQW());
101 assert0UlpEquals(2.0, qq.getQ1());
102 assert0UlpEquals(3.0, qq.getQ2());
103 assert0UlpEquals(0.0, qq.getQ3());
104 assert0UlpEquals(1.0, qq.getQW());
107 assert0UlpEquals(2.0, qq.getQ1());
108 assert0UlpEquals(3.0, qq.getQ2());
109 assert0UlpEquals(4.0, qq.getQ3());
110 assert0UlpEquals(1.0, qq.getQW());
113 assert0UlpEquals(2.0, qq.getQ1());
114 assert0UlpEquals(3.0, qq.getQ2());
115 assert0UlpEquals(4.0, qq.getQ3());
116 assert0UlpEquals(5.0, qq.getQW());
118 qq.setQ123W(6.0, 7.0, 8.0, 9.0);
119 assert0UlpEquals(6.0, qq.getQ1());
120 assert0UlpEquals(7.0, qq.getQ2());
121 assert0UlpEquals(8.0, qq.getQ3());
122 assert0UlpEquals(9.0, qq.getQW());
124 qq = new MkQuat(0.1, 0.2, 0.3, 0.4);
125 assert0UlpEquals(0.1, qq.getQ1());
126 assert0UlpEquals(0.2, qq.getQ2());
127 assert0UlpEquals(0.3, qq.getQ3());
128 assert0UlpEquals(0.4, qq.getQW());
130 MkQuat qqx = new MkQuat(1.0, 2.0, 3.0, 4.0);
131 qq = new MkQuat(qqx);
132 assert0UlpEquals(1.0, qq.getQ1());
133 assert0UlpEquals(2.0, qq.getQ2());
134 assert0UlpEquals(3.0, qq.getQ3());
135 assert0UlpEquals(4.0, qq.getQW());
141 * Test of mul method, of class MkQuat.
144 public void testMul() {
145 System.out.println("mul");
151 result = new MkQuat();
153 qqa = new MkQuat(1.0, 2.0, 3.0, 4.0);
154 qqb = new MkQuat(5.0, 6.0, 7.0, 8.0);
155 MkQuat.mul(qqa, qqb, result);
156 assert0UlpEquals(24.0, result.getQ1());
157 assert0UlpEquals(48.0, result.getQ2());
158 assert0UlpEquals(48.0, result.getQ3());
159 assert0UlpEquals(-6.0, result.getQW());
161 qqa = new MkQuat(1.0, 2.0, 3.0, 4.0);
162 qqb = new MkQuat(6.0, 7.0, 8.0, 9.0);
163 MkQuat.mul(qqa, qqb, result);
164 assert0UlpEquals(28.0, result.getQ1());
165 assert0UlpEquals(56.0, result.getQ2());
166 assert0UlpEquals(54.0, result.getQ3());
167 assert0UlpEquals(-8.0, result.getQW());
169 EulerYXZ eu = new EulerYXZ();
170 qqa.setEulerYXZ(0.0, RAD_60DEG, 0.0);
171 qqb.setEulerYXZ(RAD_30DEG, 0.0, 0.0);
172 MkQuat.mul(qqa, qqb, result);
173 result.toEulerYXZ(eu, 0.0);
174 assertUlpEquals(RAD_30DEG, eu.getXRot(), 1);
175 assertUlpEquals(RAD_60DEG, eu.getYRot(), 0);
176 assertEquals(0.0, eu.getZRot(), EPSILON);
178 qqa.setEulerYXZ(0.0, RAD_15DEG, 0.0);
179 qqb.setEulerYXZ(0.0, RAD_30DEG, 0.0);
180 MkQuat.mul(qqa, qqb, result);
181 result.toEulerYXZ(eu, 0.0);
182 assert0UlpEquals(0.0, eu.getXRot());
183 assert0UlpEquals(RAD_45DEG, eu.getYRot());
184 assert0UlpEquals(0.0, eu.getZRot());
190 * Test of conjugate method, of class MkQuat.
193 public void testConjugate() {
194 System.out.println("conjugate");
199 qq = new MkQuat(1.0, 2.0, 3.0, 4.0);
200 result = new MkQuat();
201 MkQuat.conjugate(qq, result);
202 assert0UlpEquals(-1.0, result.getQ1());
203 assert0UlpEquals(-2.0, result.getQ2());
204 assert0UlpEquals(-3.0, result.getQ3());
205 assert0UlpEquals(4.0, result.getQW());
211 * Test of normalize method, of class MkQuat.
214 public void testNormalize() {
215 System.out.println("normalize");
221 result = new MkQuat();
222 MkQuat.normalize(qq, result);
223 assert0UlpEquals(0.0, result.getQ1());
224 assert0UlpEquals(0.0, result.getQ2());
225 assert0UlpEquals(0.0, result.getQ3());
226 assert0UlpEquals(1.0, result.getQW());
228 qq = new MkQuat(2.0, 2.0, 2.0, 2.0);
229 MkQuat.normalize(qq, result);
230 assert0UlpEquals(0.5, result.getQ1());
231 assert0UlpEquals(0.5, result.getQ2());
232 assert0UlpEquals(0.5, result.getQ3());
233 assert0UlpEquals(0.5, result.getQW());
239 * Test of inverse method, of class MkQuat.
242 public void testInverse() {
243 System.out.println("inverse");
249 result = new MkQuat();
250 MkQuat.inverse(qq, result);
251 assert0UlpEquals(0.0, result.getQ1());
252 assert0UlpEquals(0.0, result.getQ2());
253 assert0UlpEquals(0.0, result.getQ3());
254 assert0UlpEquals(1.0, result.getQW());
256 qq = new MkQuat(2.0, 2.0, 2.0, 2.0);
257 MkQuat.inverse(qq, result);
258 assert0UlpEquals(-0.125, result.getQ1());
259 assert0UlpEquals(-0.125, result.getQ2());
260 assert0UlpEquals(-0.125, result.getQ3());
261 assert0UlpEquals(0.125, result.getQW());
267 * Test of abs method, of class MkQuat.
270 public void testAbs() {
271 System.out.println("abs");
276 assert0UlpEquals(1.0, qq.abs());
278 qq = new MkQuat(0.0, 0.0, 0.0, 0.0);
279 assert0UlpEquals(0.0, qq.abs());
281 qq = new MkQuat(1.0, 2.0, 0.0, 2.0);
282 assert0UlpEquals(3.0, qq.abs());
284 qq = new MkQuat(2.0, 2.0, 2.0, 2.0);
285 assert0UlpEquals(4.0, qq.abs());
291 * Test of setPos3D method, of class MkQuat.
294 public void testReadPos3D_3args() {
295 System.out.println("readPos3D");
299 qq = new MkQuat(9, 9, 9, 9);
300 qq.setPos3D(1.0, 2.0, 3.0);
301 assert0UlpEquals(1.0, qq.getQ1());
302 assert0UlpEquals(2.0, qq.getQ2());
303 assert0UlpEquals(3.0, qq.getQ3());
304 assert0UlpEquals(0.0, qq.getQW());
310 * Test of setPos3D method, of class MkQuat.
313 public void testReadPos3D_MkPos3D() {
314 System.out.println("readPos3D");
319 qq = new MkQuat(9, 9, 9, 9);
320 pos = new MkPos3D(1.0, 2.0, 3.0);
322 assert0UlpEquals(1.0, qq.getQ1());
323 assert0UlpEquals(2.0, qq.getQ2());
324 assert0UlpEquals(3.0, qq.getQ3());
325 assert0UlpEquals(0.0, qq.getQW());
331 * Test of setEulerYXZ method, of class MkQuat.
334 public void testReadEulerYXZ_3args() {
335 System.out.println("readEulerYXZ");
339 qq = new MkQuat(9, 9, 9, 9);
340 qq.setEulerYXZ(0.0, 0.0, 0.0);
341 assert0UlpEquals(0.0, qq.getQ1());
342 assert0UlpEquals(0.0, qq.getQ2());
343 assert0UlpEquals(0.0, qq.getQ3());
344 assert0UlpEquals(1.0, qq.getQW());
350 * Test of setEulerYXZ method, of class MkQuat.
353 public void testReadEulerYXZ_EulerYXZ() {
354 System.out.println("readEulerYXZ");
359 qq = new MkQuat(9, 9, 9, 9);
360 yxz = new EulerYXZ();
362 assert0UlpEquals(0.0, qq.getQ1());
363 assert0UlpEquals(0.0, qq.getQ2());
364 assert0UlpEquals(0.0, qq.getQ3());
365 assert0UlpEquals(1.0, qq.getQW());
371 * Test of toEulerYXZ method, of class MkQuat.
374 public void testToEulerYXZ_EulerYXZ_double() {
375 System.out.println("toEulerYXZ");
382 qq.setEulerYXZ(1.0, 2.0, 3.0);
384 qq.toEulerYXZ(eu, 0.0);
385 assertUlpEquals(1.0, eu.getXRot(), 1);
386 assertUlpEquals(2.0, eu.getYRot(), 2);
387 assertUlpEquals(3.0, eu.getZRot(), 0);
391 qq.setEulerYXZ(RAD_90DEG, 0.0, 0.0);
392 qq.toEulerYXZ(eu, 0.0);
393 assert0UlpEquals(RAD_90DEG, eu.getXRot());
394 assert0UlpEquals(0.0, eu.getYRot());
395 assert0UlpEquals(0.0, eu.getZRot());
397 qq.setEulerYXZ(RAD_90DEG, RAD_30DEG, 0.0);
398 qq.toEulerYXZ(eu, 0.0);
399 assert0UlpEquals(RAD_90DEG, eu.getXRot());
400 assert0UlpEquals(0.0, eu.getYRot());
401 assertUlpEquals(-RAD_30DEG, eu.getZRot(), 1);
403 qq.toEulerYXZ(eu, RAD_15DEG);
404 assert0UlpEquals(RAD_90DEG, eu.getXRot());
405 assert0UlpEquals(RAD_15DEG, eu.getYRot());
406 assertUlpEquals(-RAD_15DEG, eu.getZRot(), 2);
408 qq.setEulerYXZ(-RAD_90DEG, RAD_30DEG, 0.0);
409 qq.toEulerYXZ(eu, 0.0);
410 assert0UlpEquals(-RAD_90DEG, eu.getXRot());
411 assert0UlpEquals(0.0, eu.getYRot());
412 assertUlpEquals(RAD_30DEG, eu.getZRot(), 1);
414 qq.toEulerYXZ(eu, RAD_15DEG);
415 assert0UlpEquals(-RAD_90DEG, eu.getXRot());
416 assert0UlpEquals(RAD_15DEG, eu.getYRot());
417 assertUlpEquals(RAD_15DEG, eu.getZRot(), 2);
419 qq.setEulerYXZ(RAD_90DEG, RAD_45DEG, 0.0);
420 qq.toEulerYXZ(eu, 0.0);
421 assert0UlpEquals(RAD_90DEG, eu.getXRot());
422 assert0UlpEquals(0.0, eu.getYRot());
423 assert0UlpEquals(-RAD_45DEG, eu.getZRot());
425 qq.setEulerYXZ(RAD_90DEG, RAD_45DEG, RAD_45DEG);
426 qq.toEulerYXZ(eu, 0.0);
427 assert0UlpEquals(RAD_90DEG, eu.getXRot());
428 assert0UlpEquals(0.0, eu.getYRot());
429 assertEquals(0.0, eu.getZRot(), EPSILON);
431 qq.setEulerYXZ(RAD_90DEG, RAD_30DEG, RAD_60DEG);
432 qq.toEulerYXZ(eu, 0.0);
433 assert0UlpEquals(RAD_90DEG, eu.getXRot());
434 assert0UlpEquals(0.0, eu.getYRot());
435 assert0UlpEquals(RAD_30DEG, eu.getZRot());
437 qq.setEulerYXZ(RAD_30DEG, RAD_45DEG, RAD_45DEG);
438 qq.toEulerYXZ(eu, 0.0);
439 assertUlpEquals(RAD_30DEG, eu.getXRot(), 1);
440 assertUlpEquals(RAD_45DEG, eu.getYRot(), 1);
441 assertUlpEquals(RAD_45DEG, eu.getZRot(), 1);
447 xRad = toRadians(95);
450 qq.setEulerYXZ(xRad, yRad, zRad);
451 qq.toEulerYXZ(eu, yRad);
452 assertUlpEquals(toRadians(85), eu.getXRot(), 1);
453 assertUlpEquals(toRadians(180), eu.getYRot(), 0);
454 assertUlpEquals(toRadians(180), eu.getZRot(), 0);
460 * Test of critical case, of class MkQuat.
463 public void testCritical() {
464 System.out.println("critical");
475 xRad = toRadians(89);
476 yRad = toRadians(80);
477 zRad = toRadians(41);
478 qq.setEulerYXZ(xRad, yRad, zRad);
479 qq.toEulerYXZ(eu, 0.0);
480 assertUlpEquals(xRad, eu.getXRot(), 164);
481 assertUlpEquals(yRad, eu.getYRot(), 143);
482 assertUlpEquals(zRad, eu.getZRot(), 211);
485 xRad = toRadians(90);
488 qq.setEulerYXZ(xRad, yRad, zRad);
489 qq.toEulerYXZ(eu, yRad);
490 assert0UlpEquals(xRad, eu.getXRot());
491 assert0UlpEquals(yRad, eu.getYRot());
492 assertUlpEquals(zRad, eu.getZRot(), 1);
494 xRad = toRadians(89.999);
495 yRad = toRadians(89.999);
496 zRad = toRadians(89.999);
497 qq.setEulerYXZ(xRad, yRad, zRad);
498 qq.toEulerYXZ(eu, yRad);
499 assertUlpEquals(xRad, eu.getXRot(), 83029);
500 assertUlpEquals(yRad, eu.getYRot(), 91782);
501 assertUlpEquals(zRad, eu.getZRot(), 91782);
507 * Test of toEulerYXZ method, of class MkQuat.
510 public void testToEulerYXZ_EulerYXZ() {
511 System.out.println("toEulerYXZ");
518 qq.setEulerYXZ(1.0, 2.0, 3.0);
521 assertUlpEquals(1.0, eu.getXRot(), 1);
522 assertUlpEquals(2.0, eu.getYRot(), 2);
523 assertUlpEquals(3.0, eu.getZRot(), 0);
525 qq.setEulerYXZ(StrictMath.PI, 0.0, 0.0);
527 assertEquals(0.0, eu.getXRot(), EPSILON);
528 assert0UlpEquals(StrictMath.PI, eu.getYRot());
529 assert0UlpEquals(StrictMath.PI, eu.getZRot());
535 * Test of rotatePos method, of class MkQuat.
538 public void testRotatePos() {
539 System.out.println("rotatePos");
547 pos = new MkPos3D(1.0, 1.0, 1.0);
548 result = new MkPos3D();
551 qq.setEulerYXZ(0.0, 0.0, 0.0);
552 qq.rotatePos(pos, result);
553 assert0UlpEquals(1.0, result.getXpos());
554 assert0UlpEquals(1.0, result.getYpos());
555 assert0UlpEquals(1.0, result.getZpos());
557 // test Left Hand Rotation
558 qq.setEulerYXZ(0.0, RAD_90DEG, 0.0);
559 qq.rotatePos(pos, result);
560 assertUlpEquals(1.0, result.getXpos(), 0);
561 assertUlpEquals(1.0, result.getYpos(), 0);
562 assertUlpEquals(-1.0, result.getZpos(), 2);
564 qq.setEulerYXZ(RAD_90DEG, 0.0, 0.0);
565 qq.rotatePos(pos, result);
566 assertUlpEquals(1.0, result.getXpos(), 0);
567 assertUlpEquals(-1.0, result.getYpos(), 2);
568 assertUlpEquals(1.0, result.getZpos(), 0);
570 qq.setEulerYXZ(0.0, 0.0, RAD_90DEG);
571 qq.rotatePos(pos, result);
572 assertUlpEquals(-1.0, result.getXpos(), 2);
573 assertUlpEquals(1.0, result.getYpos(), 0);
574 assertUlpEquals(1.0, result.getZpos(), 0);
576 // test Euler axis order
578 qq.setEulerYXZ(RAD_90DEG, RAD_90DEG, 0.0);
579 qq.rotatePos(pos, result);
580 assertUlpEquals(1.0, result.getXpos(), 2);
581 assertUlpEquals(-1.0, result.getYpos(), 1);
582 assertUlpEquals(-1.0, result.getZpos(), 1);
584 qq.setEulerYXZ(0.0, RAD_90DEG, RAD_90DEG);
585 qq.rotatePos(pos, result);
586 assertUlpEquals(1.0, result.getXpos(), 1);
587 assertUlpEquals(1.0, result.getYpos(), 1);
588 assertUlpEquals(1.0, result.getZpos(), 0);
590 qq.setEulerYXZ(RAD_90DEG, 0.0, RAD_90DEG);
591 qq.rotatePos(pos, result);
592 assertUlpEquals(-1.0, result.getXpos(), 1);
593 assertUlpEquals(-1.0, result.getYpos(), 1);
594 assertUlpEquals(1.0, result.getZpos(), 2);
596 pos = new MkPos3D(1.0, 2.0, 3.0);
598 qq.setEulerYXZ(0.0, RAD_90DEG, 0.0);
599 qq.rotatePos(pos, result);
600 assertUlpEquals(3.0, result.getXpos(), 0);
601 assertUlpEquals(2.0, result.getYpos(), 0);
602 assertUlpEquals(-1.0, result.getZpos(), 3);
604 qq.setEulerYXZ(RAD_90DEG, 0.0, 0.0);
605 qq.rotatePos(pos, result);
606 assertUlpEquals(1.0, result.getXpos(), 0);
607 assertUlpEquals(-3.0, result.getYpos(), 0);
608 assertUlpEquals(2.0, result.getZpos(), 2);
610 qq.setEulerYXZ(0.0, 0.0, RAD_90DEG);
611 qq.rotatePos(pos, result);
612 assertUlpEquals(-2.0, result.getXpos(), 0);
613 assertUlpEquals(1.0, result.getYpos(), 2);
614 assertUlpEquals(3.0, result.getZpos(), 0);
616 // rotate origin point
618 pos = new MkPos3D(0.0, 0.0, 0.0);
619 qq.setEulerYXZ(RAD_15DEG, RAD_30DEG, RAD_45DEG);
620 qq.rotatePos(pos, result);
621 assert0UlpEquals(0.0, result.getXpos());
622 assert0UlpEquals(0.0, result.getYpos());
623 assert0UlpEquals(0.0, result.getZpos());
629 * Test of full matching, of class MkQuat.
632 public void testFullMatch(){
633 System.out.println("full match");
635 for(int ix = -5; ix <= 90; ix++){
636 for(int iy = -5; iy <= 179; iy++){
637 for(int iz = -5; iz <= 179; iz++){
640 }catch(AssertionError e){
641 System.out.println(""+ix+":"+iy+":"+iz);
652 * Test of full matching, of class MkQuat.
655 public void testFullMatchRev(){
656 System.out.println("full match rev");
658 for(int ix = -90; ix <= 5; ix++){
659 for(int iy = -179; iy <= 5; iy++){
660 for(int iz = -179; iz <= 5; iz++){
663 }catch(AssertionError e){
664 System.out.println(""+ix+":"+iy+":"+iz);
674 private void rotTest(double ix, double iy, double iz){
679 result = new EulerYXZ();
681 double xRad = toRadians(ix);
682 double yRad = toRadians(iy);
683 double zRad = toRadians(iz);
685 qq.setEulerYXZ(xRad, yRad, zRad);
686 qq.toEulerYXZ(result, yRad);
688 final double DELTA = EPSILON * 164;
690 assertEquals(xRad, result.getXRot(), DELTA);
691 assertEquals(yRad, result.getYRot(), DELTA);
692 assertEquals(zRad, result.getZRot(), DELTA);
698 * Test of toString method, of class MkQuat.
701 public void testToString() {
702 System.out.println("toString");
706 qq = new MkQuat(-0.0, Double.MIN_NORMAL, Double.MAX_EXPONENT, StrictMath.PI);
707 assertEquals("q1=-0.0 q2=2.2250738585072014E-308 q3=1023.0 w=3.141592653589793", qq.toString());