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() {
44 private void assert0UlpEquals(double expected, double result){
45 assertUlpEquals(expected, result, 0);
49 private void assertUlpEquals(double expected, double result, int ulpNum){
50 double ulpExpected = StrictMath.ulp(expected);
51 double ulpResult = StrictMath.ulp(result);
52 double ulp = StrictMath.max(ulpExpected, ulpResult);
53 double delta = ulp * ulpNum;
56 assertEquals(expected, result, delta);
57 }catch(AssertionError e){
58 double dist = StrictMath.abs(expected - result);
59 String msg = e.getMessage();
60 msg += " ULP * " + (dist / ulp);
61 AssertionError err = new AssertionError(msg);
70 * Test of constructor, of class MkQuat.
73 public void testCons() {
74 System.out.println("constructor");
79 assert0UlpEquals(0.0, qq.getQ1());
80 assert0UlpEquals(0.0, qq.getQ2());
81 assert0UlpEquals(0.0, qq.getQ3());
82 assert0UlpEquals(1.0, qq.getQW());
85 assert0UlpEquals(2.0, qq.getQ1());
86 assert0UlpEquals(0.0, qq.getQ2());
87 assert0UlpEquals(0.0, qq.getQ3());
88 assert0UlpEquals(1.0, qq.getQW());
91 assert0UlpEquals(2.0, qq.getQ1());
92 assert0UlpEquals(3.0, qq.getQ2());
93 assert0UlpEquals(0.0, qq.getQ3());
94 assert0UlpEquals(1.0, qq.getQW());
97 assert0UlpEquals(2.0, qq.getQ1());
98 assert0UlpEquals(3.0, qq.getQ2());
99 assert0UlpEquals(4.0, qq.getQ3());
100 assert0UlpEquals(1.0, qq.getQW());
103 assert0UlpEquals(2.0, qq.getQ1());
104 assert0UlpEquals(3.0, qq.getQ2());
105 assert0UlpEquals(4.0, qq.getQ3());
106 assert0UlpEquals(5.0, qq.getQW());
108 qq.setQ123W(6.0, 7.0, 8.0, 9.0);
109 assert0UlpEquals(6.0, qq.getQ1());
110 assert0UlpEquals(7.0, qq.getQ2());
111 assert0UlpEquals(8.0, qq.getQ3());
112 assert0UlpEquals(9.0, qq.getQW());
114 qq = new MkQuat(0.1, 0.2, 0.3, 0.4);
115 assert0UlpEquals(0.1, qq.getQ1());
116 assert0UlpEquals(0.2, qq.getQ2());
117 assert0UlpEquals(0.3, qq.getQ3());
118 assert0UlpEquals(0.4, qq.getQW());
120 MkQuat qqx = new MkQuat(1.0, 2.0, 3.0, 4.0);
121 qq = new MkQuat(qqx);
122 assert0UlpEquals(1.0, qq.getQ1());
123 assert0UlpEquals(2.0, qq.getQ2());
124 assert0UlpEquals(3.0, qq.getQ3());
125 assert0UlpEquals(4.0, qq.getQW());
131 * Test of mul method, of class MkQuat.
134 public void testMul() {
135 System.out.println("mul");
141 result = new MkQuat();
143 qqa = new MkQuat(1.0, 2.0, 3.0, 4.0);
144 qqb = new MkQuat(5.0, 6.0, 7.0, 8.0);
145 MkQuat.mul(qqa, qqb, result);
146 assert0UlpEquals(24.0, result.getQ1());
147 assert0UlpEquals(48.0, result.getQ2());
148 assert0UlpEquals(48.0, result.getQ3());
149 assert0UlpEquals(-6.0, result.getQW());
151 qqa = new MkQuat(1.0, 2.0, 3.0, 4.0);
152 qqb = new MkQuat(6.0, 7.0, 8.0, 9.0);
153 MkQuat.mul(qqa, qqb, result);
154 assert0UlpEquals(28.0, result.getQ1());
155 assert0UlpEquals(56.0, result.getQ2());
156 assert0UlpEquals(54.0, result.getQ3());
157 assert0UlpEquals(-8.0, result.getQW());
159 EulerYXZ eu = new EulerYXZ();
160 qqa.setEulerYXZ(0.0, RAD_60DEG, 0.0);
161 qqb.setEulerYXZ(RAD_30DEG, 0.0, 0.0);
162 MkQuat.mul(qqa, qqb, result);
163 result.toEulerYXZ(eu, 0.0);
164 assertUlpEquals(RAD_30DEG, eu.getXRot(), 1);
165 assertUlpEquals(RAD_60DEG, eu.getYRot(), 0);
166 assertEquals(0.0, eu.getZRot(), EPSILON);
168 qqa.setEulerYXZ(0.0, RAD_15DEG, 0.0);
169 qqb.setEulerYXZ(0.0, RAD_30DEG, 0.0);
170 MkQuat.mul(qqa, qqb, result);
171 result.toEulerYXZ(eu, 0.0);
172 assert0UlpEquals(0.0, eu.getXRot());
173 assert0UlpEquals(RAD_45DEG, eu.getYRot());
174 assert0UlpEquals(0.0, eu.getZRot());
180 * Test of conjugate method, of class MkQuat.
183 public void testConjugate() {
184 System.out.println("conjugate");
189 qq = new MkQuat(1.0, 2.0, 3.0, 4.0);
190 result = new MkQuat();
191 MkQuat.conjugate(qq, result);
192 assert0UlpEquals(-1.0, result.getQ1());
193 assert0UlpEquals(-2.0, result.getQ2());
194 assert0UlpEquals(-3.0, result.getQ3());
195 assert0UlpEquals(4.0, result.getQW());
201 * Test of normalize method, of class MkQuat.
204 public void testNormalize() {
205 System.out.println("normalize");
211 result = new MkQuat();
212 MkQuat.normalize(qq, result);
213 assert0UlpEquals(0.0, result.getQ1());
214 assert0UlpEquals(0.0, result.getQ2());
215 assert0UlpEquals(0.0, result.getQ3());
216 assert0UlpEquals(1.0, result.getQW());
218 qq = new MkQuat(2.0, 2.0, 2.0, 2.0);
219 MkQuat.normalize(qq, result);
220 assert0UlpEquals(0.5, result.getQ1());
221 assert0UlpEquals(0.5, result.getQ2());
222 assert0UlpEquals(0.5, result.getQ3());
223 assert0UlpEquals(0.5, result.getQW());
229 * Test of inverse method, of class MkQuat.
232 public void testInverse() {
233 System.out.println("inverse");
239 result = new MkQuat();
240 MkQuat.inverse(qq, result);
241 assert0UlpEquals(0.0, result.getQ1());
242 assert0UlpEquals(0.0, result.getQ2());
243 assert0UlpEquals(0.0, result.getQ3());
244 assert0UlpEquals(1.0, result.getQW());
246 qq = new MkQuat(2.0, 2.0, 2.0, 2.0);
247 MkQuat.inverse(qq, result);
248 assert0UlpEquals(-0.125, result.getQ1());
249 assert0UlpEquals(-0.125, result.getQ2());
250 assert0UlpEquals(-0.125, result.getQ3());
251 assert0UlpEquals(0.125, result.getQW());
257 * Test of abs method, of class MkQuat.
260 public void testAbs() {
261 System.out.println("abs");
266 assert0UlpEquals(1.0, qq.abs());
268 qq = new MkQuat(0.0, 0.0, 0.0, 0.0);
269 assert0UlpEquals(0.0, qq.abs());
271 qq = new MkQuat(1.0, 2.0, 0.0, 2.0);
272 assert0UlpEquals(3.0, qq.abs());
274 qq = new MkQuat(2.0, 2.0, 2.0, 2.0);
275 assert0UlpEquals(4.0, qq.abs());
281 * Test of setPos3D method, of class MkQuat.
284 public void testReadPos3D_3args() {
285 System.out.println("readPos3D");
289 qq = new MkQuat(9, 9, 9, 9);
290 qq.setPos3D(1.0, 2.0, 3.0);
291 assert0UlpEquals(1.0, qq.getQ1());
292 assert0UlpEquals(2.0, qq.getQ2());
293 assert0UlpEquals(3.0, qq.getQ3());
294 assert0UlpEquals(0.0, qq.getQW());
300 * Test of setPos3D method, of class MkQuat.
303 public void testReadPos3D_MkPos3D() {
304 System.out.println("readPos3D");
309 qq = new MkQuat(9, 9, 9, 9);
310 pos = new MkPos3D(1.0, 2.0, 3.0);
312 assert0UlpEquals(1.0, qq.getQ1());
313 assert0UlpEquals(2.0, qq.getQ2());
314 assert0UlpEquals(3.0, qq.getQ3());
315 assert0UlpEquals(0.0, qq.getQW());
321 * Test of setEulerYXZ method, of class MkQuat.
324 public void testReadEulerYXZ_3args() {
325 System.out.println("readEulerYXZ");
329 qq = new MkQuat(9, 9, 9, 9);
330 qq.setEulerYXZ(0.0, 0.0, 0.0);
331 assert0UlpEquals(0.0, qq.getQ1());
332 assert0UlpEquals(0.0, qq.getQ2());
333 assert0UlpEquals(0.0, qq.getQ3());
334 assert0UlpEquals(1.0, qq.getQW());
340 * Test of setEulerYXZ method, of class MkQuat.
343 public void testReadEulerYXZ_EulerYXZ() {
344 System.out.println("readEulerYXZ");
349 qq = new MkQuat(9, 9, 9, 9);
350 yxz = new EulerYXZ();
352 assert0UlpEquals(0.0, qq.getQ1());
353 assert0UlpEquals(0.0, qq.getQ2());
354 assert0UlpEquals(0.0, qq.getQ3());
355 assert0UlpEquals(1.0, qq.getQW());
361 * Test of toEulerYXZ method, of class MkQuat.
364 public void testToEulerYXZ_EulerYXZ_double() {
365 System.out.println("toEulerYXZ");
372 qq.setEulerYXZ(1.0, 2.0, 3.0);
374 qq.toEulerYXZ(eu, 0.0);
375 assertUlpEquals(1.0, eu.getXRot(), 1);
376 assertUlpEquals(2.0, eu.getYRot(), 2);
377 assertUlpEquals(3.0, eu.getZRot(), 0);
381 qq.setEulerYXZ(RAD_90DEG, 0.0, 0.0);
382 qq.toEulerYXZ(eu, 0.0);
383 assert0UlpEquals(RAD_90DEG, eu.getXRot());
384 assert0UlpEquals(0.0, eu.getYRot());
385 assert0UlpEquals(0.0, eu.getZRot());
387 qq.setEulerYXZ(RAD_90DEG, RAD_30DEG, 0.0);
388 qq.toEulerYXZ(eu, 0.0);
389 assert0UlpEquals(RAD_90DEG, eu.getXRot());
390 assert0UlpEquals(0.0, eu.getYRot());
391 assertUlpEquals(-RAD_30DEG, eu.getZRot(), 1);
393 qq.toEulerYXZ(eu, RAD_15DEG);
394 assert0UlpEquals(RAD_90DEG, eu.getXRot());
395 assert0UlpEquals(RAD_15DEG, eu.getYRot());
396 assertUlpEquals(-RAD_15DEG, eu.getZRot(), 2);
398 qq.setEulerYXZ(-RAD_90DEG, RAD_30DEG, 0.0);
399 qq.toEulerYXZ(eu, 0.0);
400 assert0UlpEquals(-RAD_90DEG, eu.getXRot());
401 assert0UlpEquals(0.0, eu.getYRot());
402 assertUlpEquals(RAD_30DEG, eu.getZRot(), 1);
404 qq.toEulerYXZ(eu, RAD_15DEG);
405 assert0UlpEquals(-RAD_90DEG, eu.getXRot());
406 assert0UlpEquals(RAD_15DEG, eu.getYRot());
407 assertUlpEquals(RAD_15DEG, eu.getZRot(), 2);
409 qq.setEulerYXZ(RAD_90DEG, RAD_45DEG, 0.0);
410 qq.toEulerYXZ(eu, 0.0);
411 assert0UlpEquals(RAD_90DEG, eu.getXRot());
412 assert0UlpEquals(0.0, eu.getYRot());
413 assert0UlpEquals(-RAD_45DEG, eu.getZRot());
415 qq.setEulerYXZ(RAD_90DEG, RAD_45DEG, RAD_45DEG);
416 qq.toEulerYXZ(eu, 0.0);
417 assert0UlpEquals(RAD_90DEG, eu.getXRot());
418 assert0UlpEquals(0.0, eu.getYRot());
419 assertEquals(0.0, eu.getZRot(), EPSILON);
421 qq.setEulerYXZ(RAD_90DEG, RAD_30DEG, RAD_60DEG);
422 qq.toEulerYXZ(eu, 0.0);
423 assert0UlpEquals(RAD_90DEG, eu.getXRot());
424 assert0UlpEquals(0.0, eu.getYRot());
425 assert0UlpEquals(RAD_30DEG, eu.getZRot());
427 qq.setEulerYXZ(RAD_30DEG, RAD_45DEG, RAD_45DEG);
428 qq.toEulerYXZ(eu, 0.0);
429 assertUlpEquals(RAD_30DEG, eu.getXRot(), 1);
430 assertUlpEquals(RAD_45DEG, eu.getYRot(), 1);
431 assertUlpEquals(RAD_45DEG, eu.getZRot(), 1);
437 xRad = StrictMath.toRadians(95);
438 yRad = StrictMath.toRadians(0);
439 zRad = StrictMath.toRadians(0);
440 qq.setEulerYXZ(xRad, yRad, zRad);
441 qq.toEulerYXZ(eu, yRad);
442 assertUlpEquals(StrictMath.toRadians(85), eu.getXRot(), 1);
443 assertUlpEquals(StrictMath.toRadians(180), eu.getYRot(), 0);
444 assertUlpEquals(StrictMath.toRadians(180), eu.getZRot(), 0);
450 * Test of critical case, of class MkQuat.
453 public void testCritical() {
454 System.out.println("critical");
465 xRad = StrictMath.toRadians(89);
466 yRad = StrictMath.toRadians(80);
467 zRad = StrictMath.toRadians(41);
468 qq.setEulerYXZ(xRad, yRad, zRad);
469 qq.toEulerYXZ(eu, 0.0);
470 assertUlpEquals(xRad, eu.getXRot(), 164);
471 assertUlpEquals(yRad, eu.getYRot(), 143);
472 assertUlpEquals(zRad, eu.getZRot(), 211);
475 xRad = StrictMath.toRadians(90);
476 yRad = StrictMath.toRadians(6);
477 zRad = StrictMath.toRadians(7);
478 qq.setEulerYXZ(xRad, yRad, zRad);
479 qq.toEulerYXZ(eu, yRad);
480 assert0UlpEquals(xRad, eu.getXRot());
481 assert0UlpEquals(yRad, eu.getYRot());
482 assert0UlpEquals(zRad, eu.getZRot());
484 xRad = StrictMath.toRadians(89.999);
485 yRad = StrictMath.toRadians(89.999);
486 zRad = StrictMath.toRadians(89.999);
487 qq.setEulerYXZ(xRad, yRad, zRad);
488 qq.toEulerYXZ(eu, yRad);
489 assertUlpEquals(xRad, eu.getXRot(), 83029);
490 assertUlpEquals(yRad, eu.getYRot(), 80108);
491 assertUlpEquals(zRad, eu.getZRot(), 80108);
497 * Test of toEulerYXZ method, of class MkQuat.
500 public void testToEulerYXZ_EulerYXZ() {
501 System.out.println("toEulerYXZ");
508 qq.setEulerYXZ(1.0, 2.0, 3.0);
511 assertUlpEquals(1.0, eu.getXRot(), 1);
512 assertUlpEquals(2.0, eu.getYRot(), 2);
513 assertUlpEquals(3.0, eu.getZRot(), 0);
515 qq.setEulerYXZ(StrictMath.PI, 0.0, 0.0);
517 assertEquals(0.0, eu.getXRot(), EPSILON);
518 assert0UlpEquals(StrictMath.PI, eu.getYRot());
519 assert0UlpEquals(StrictMath.PI, eu.getZRot());
525 * Test of rotatePos method, of class MkQuat.
528 public void testRotatePos() {
529 System.out.println("rotatePos");
537 pos = new MkPos3D(1.0, 1.0, 1.0);
538 result = new MkPos3D();
541 qq.setEulerYXZ(0.0, 0.0, 0.0);
542 qq.rotatePos(pos, result);
543 assert0UlpEquals(1.0, result.getXpos());
544 assert0UlpEquals(1.0, result.getYpos());
545 assert0UlpEquals(1.0, result.getZpos());
547 // test Left Hand Rotation
548 qq.setEulerYXZ(0.0, RAD_90DEG, 0.0);
549 qq.rotatePos(pos, result);
550 assertUlpEquals(1.0, result.getXpos(), 0);
551 assertUlpEquals(1.0, result.getYpos(), 0);
552 assertUlpEquals(-1.0, result.getZpos(), 2);
554 qq.setEulerYXZ(RAD_90DEG, 0.0, 0.0);
555 qq.rotatePos(pos, result);
556 assertUlpEquals(1.0, result.getXpos(), 0);
557 assertUlpEquals(-1.0, result.getYpos(), 2);
558 assertUlpEquals(1.0, result.getZpos(), 0);
560 qq.setEulerYXZ(0.0, 0.0, RAD_90DEG);
561 qq.rotatePos(pos, result);
562 assertUlpEquals(-1.0, result.getXpos(), 2);
563 assertUlpEquals(1.0, result.getYpos(), 0);
564 assertUlpEquals(1.0, result.getZpos(), 0);
566 // test Euler axis order
568 qq.setEulerYXZ(RAD_90DEG, RAD_90DEG, 0.0);
569 qq.rotatePos(pos, result);
570 assertUlpEquals(1.0, result.getXpos(), 2);
571 assertUlpEquals(-1.0, result.getYpos(), 1);
572 assertUlpEquals(-1.0, result.getZpos(), 1);
574 qq.setEulerYXZ(0.0, RAD_90DEG, RAD_90DEG);
575 qq.rotatePos(pos, result);
576 assertUlpEquals(1.0, result.getXpos(), 1);
577 assertUlpEquals(1.0, result.getYpos(), 1);
578 assertUlpEquals(1.0, result.getZpos(), 0);
580 qq.setEulerYXZ(RAD_90DEG, 0.0, RAD_90DEG);
581 qq.rotatePos(pos, result);
582 assertUlpEquals(-1.0, result.getXpos(), 1);
583 assertUlpEquals(-1.0, result.getYpos(), 1);
584 assertUlpEquals(1.0, result.getZpos(), 2);
586 pos = new MkPos3D(1.0, 2.0, 3.0);
588 qq.setEulerYXZ(0.0, RAD_90DEG, 0.0);
589 qq.rotatePos(pos, result);
590 assertUlpEquals(3.0, result.getXpos(), 0);
591 assertUlpEquals(2.0, result.getYpos(), 0);
592 assertUlpEquals(-1.0, result.getZpos(), 3);
594 qq.setEulerYXZ(RAD_90DEG, 0.0, 0.0);
595 qq.rotatePos(pos, result);
596 assertUlpEquals(1.0, result.getXpos(), 0);
597 assertUlpEquals(-3.0, result.getYpos(), 0);
598 assertUlpEquals(2.0, result.getZpos(), 2);
600 qq.setEulerYXZ(0.0, 0.0, RAD_90DEG);
601 qq.rotatePos(pos, result);
602 assertUlpEquals(-2.0, result.getXpos(), 0);
603 assertUlpEquals(1.0, result.getYpos(), 2);
604 assertUlpEquals(3.0, result.getZpos(), 0);
606 // rotate origin point
608 pos = new MkPos3D(0.0, 0.0, 0.0);
609 qq.setEulerYXZ(RAD_15DEG, RAD_30DEG, RAD_45DEG);
610 qq.rotatePos(pos, result);
611 assert0UlpEquals(0.0, result.getXpos());
612 assert0UlpEquals(0.0, result.getYpos());
613 assert0UlpEquals(0.0, result.getZpos());
619 * Test of full matching, of class MkQuat.
622 public void testFullMatch(){
623 System.out.println("full match");
625 for(int ix = -5; ix <= 90; ix++){
626 for(int iy = -5; iy <= 179; iy++){
627 for(int iz = -5; iz <= 179; iz++){
630 }catch(AssertionError e){
631 System.out.println(""+ix+":"+iy+":"+iz);
642 * Test of full matching, of class MkQuat.
645 public void testFullMatchRev(){
646 System.out.println("full match rev");
648 for(int ix = -90; ix <= 5; ix++){
649 for(int iy = -179; iy <= 5; iy++){
650 for(int iz = -179; iz <= 5; iz++){
653 }catch(AssertionError e){
654 System.out.println(""+ix+":"+iy+":"+iz);
664 private void rotTest(double ix, double iy, double iz){
669 result = new EulerYXZ();
671 double xRad = StrictMath.toRadians(ix);
672 double yRad = StrictMath.toRadians(iy);
673 double zRad = StrictMath.toRadians(iz);
675 qq.setEulerYXZ(xRad, yRad, zRad);
676 qq.toEulerYXZ(result, yRad);
678 final double DELTA = EPSILON * 164;
680 assertEquals(xRad, result.getXRot(), DELTA);
681 assertEquals(yRad, result.getYRot(), DELTA);
682 assertEquals(zRad, result.getZRot(), DELTA);
688 * Test of toString method, of class MkQuat.
691 public void testToString() {
692 System.out.println("toString");
696 qq = new MkQuat(-0.0, Double.MIN_NORMAL, Double.MAX_EXPONENT, StrictMath.PI);
697 assertEquals("q1=-0.0 q2=2.2250738585072014E-308 q3=1023.0 w=3.141592653589793", qq.toString());