package openmods.geometry; import com.google.common.base.Joiner; import com.google.common.collect.HashMultimap; import com.google.common.collect.Maps; import com.google.common.collect.Multimap; import java.util.Collection; import java.util.Map; import org.apache.commons.lang3.tuple.Pair; import org.junit.Assert; import org.junit.Test; public class OrientationTest { @Test public void testFourSameRotations() { for (Orientation o : Orientation.VALUES) for (HalfAxis a : HalfAxis.VALUES) { Assert.assertEquals(o, o.rotateAround(a).rotateAround(a).rotateAround(a).rotateAround(a)); } } @Test public void testCounterRotations() { for (Orientation o : Orientation.VALUES) for (HalfAxis a : HalfAxis.VALUES) { Assert.assertEquals(o, o.rotateAround(a).rotateAround(a.negate())); Assert.assertEquals(o, o.rotateAround(a).rotateAround(a).rotateAround(a.negate()).rotateAround(a.negate())); } } private static HalfAxis[] select(HalfAxis... axes) { return axes; } @Test public void testRotationAroundX() { for (Orientation o : Orientation.VALUES) for (HalfAxis a : select(HalfAxis.POS_X, HalfAxis.NEG_X)) { final Orientation r = o.rotateAround(a).rotateAround(a); Assert.assertEquals(o.x, r.x); Assert.assertEquals(o.y.negate(), r.y); Assert.assertEquals(o.z.negate(), r.z); } } @Test public void testRotationY() { for (Orientation o : Orientation.VALUES) for (HalfAxis a : select(HalfAxis.POS_Y, HalfAxis.NEG_Y)) { final Orientation r = o.rotateAround(a).rotateAround(a); Assert.assertEquals(o.x.negate(), r.x); Assert.assertEquals(o.y, r.y); Assert.assertEquals(o.z.negate(), r.z); } } @Test public void testRotationZ() { for (Orientation o : Orientation.VALUES) for (HalfAxis a : select(HalfAxis.POS_Z, HalfAxis.NEG_Z)) { final Orientation r = o.rotateAround(a).rotateAround(a); Assert.assertEquals(o.x.negate(), r.x); Assert.assertEquals(o.y.negate(), r.y); Assert.assertEquals(o.z, r.z); } } private static class TwoRotations { public final HalfAxis first; public final HalfAxis second; public TwoRotations(HalfAxis first, HalfAxis second) { this.first = first; this.second = second; } public Orientation apply(Orientation orientation) { return orientation.rotateAround(first).rotateAround(second); } } public static TwoRotations pair(HalfAxis first, HalfAxis second) { return new TwoRotations(first, second); } private static void testSameRotations(Orientation orientation, TwoRotations... rotations) { final Orientation first = rotations[0].apply(orientation); for (int i = 1; i < rotations.length; i++) { Orientation next = rotations[i].apply(orientation); Assert.assertEquals(first, next); } } @Test public void testTwoRotations() { for (Orientation o : Orientation.VALUES) { testSameRotations(o, pair(HalfAxis.NEG_Z, HalfAxis.POS_X), pair(HalfAxis.POS_Y, HalfAxis.NEG_Z), pair(HalfAxis.POS_X, HalfAxis.POS_Y)); testSameRotations(o, pair(HalfAxis.POS_Z, HalfAxis.POS_X), pair(HalfAxis.POS_X, HalfAxis.NEG_Y), pair(HalfAxis.NEG_Y, HalfAxis.POS_Z)); testSameRotations(o, pair(HalfAxis.POS_Z, HalfAxis.NEG_X), pair(HalfAxis.POS_Y, HalfAxis.POS_Z), pair(HalfAxis.NEG_X, HalfAxis.POS_Y)); testSameRotations(o, pair(HalfAxis.NEG_Z, HalfAxis.NEG_X), pair(HalfAxis.NEG_Y, HalfAxis.NEG_Z), pair(HalfAxis.NEG_X, HalfAxis.NEG_Y)); testSameRotations(o, pair(HalfAxis.POS_X, HalfAxis.POS_Z), pair(HalfAxis.POS_Z, HalfAxis.POS_Y), pair(HalfAxis.POS_Y, HalfAxis.POS_X)); testSameRotations(o, pair(HalfAxis.POS_X, HalfAxis.NEG_Z), pair(HalfAxis.NEG_Z, HalfAxis.NEG_Y), pair(HalfAxis.NEG_Y, HalfAxis.POS_X)); testSameRotations(o, pair(HalfAxis.NEG_X, HalfAxis.POS_Z), pair(HalfAxis.POS_Z, HalfAxis.NEG_Y), pair(HalfAxis.NEG_Y, HalfAxis.NEG_X)); testSameRotations(o, pair(HalfAxis.NEG_X, HalfAxis.NEG_Z), pair(HalfAxis.POS_Y, HalfAxis.NEG_X), pair(HalfAxis.NEG_Z, HalfAxis.POS_Y)); } } // This is code for generation of one of tests. // I brute-forced those relations and then started to rotate random things to verify it // If anyone knows, if there is more formalized way, please let me know. -boq public static void main(String[] argv) { final Multimap<Matrix3d, Pair<HalfAxis, HalfAxis>> m = HashMultimap.create(); final Map<HalfAxis, Matrix3d> ms = Maps.newHashMap(); // note: we need intrinsic matrices (axis rotation instead of point) // remove inverts to get extrinsic relationships ms.put(HalfAxis.NEG_X, new Matrix3d(1, 0, 0, 0, 0, +1, 0, -1, 0).invertInplace()); ms.put(HalfAxis.POS_X, new Matrix3d(1, 0, 0, 0, 0, -1, 0, +1, 0).invertInplace()); ms.put(HalfAxis.NEG_Y, new Matrix3d(0, 0, -1, 0, 1, 0, +1, 0, 0).invertInplace()); ms.put(HalfAxis.POS_Y, new Matrix3d(0, 0, +1, 0, 1, 0, -1, 0, 0).invertInplace()); ms.put(HalfAxis.NEG_Z, new Matrix3d(0, +1, 0, -1, 0, 0, 0, 0, 1).invertInplace()); ms.put(HalfAxis.POS_Z, new Matrix3d(0, -1, 0, +1, 0, 0, 0, 0, 1).invertInplace()); for (HalfAxis a : HalfAxis.VALUES) for (HalfAxis b : HalfAxis.VALUES) { final Matrix3d ma = ms.get(a); final Matrix3d mb = ms.get(b); m.put(Matrix3d.mul(ma, mb), Pair.of(a, b)); } for (Collection<Pair<HalfAxis, HalfAxis>> v : m.asMap().values()) { System.out.println(Joiner.on("=").join(v)); } } }