1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.geometry.spherical.twod;
18
19 import org.apache.commons.geometry.core.GeometryTestUtils;
20 import org.apache.commons.geometry.euclidean.threed.Vector3D;
21 import org.apache.commons.geometry.euclidean.threed.rotation.QuaternionRotation;
22 import org.apache.commons.geometry.spherical.SphericalTestUtils;
23 import org.apache.commons.numbers.angle.Angle;
24 import org.junit.jupiter.api.Assertions;
25 import org.junit.jupiter.api.Test;
26
27 class Transform2STest {
28
29 private static final double TEST_EPS = 1e-10;
30
31 @Test
32 void testIdentity() {
33
34 final Transform2S t = Transform2S.identity();
35
36
37 Assertions.assertTrue(t.preservesOrientation());
38 Assertions.assertArrayEquals(new double[] {
39 1, 0, 0, 0,
40 0, 1, 0, 0,
41 0, 0, 1, 0
42 }, t.getEuclideanTransform().toArray(), 0);
43
44 SphericalTestUtils.assertPointsEqual(Point2S.PLUS_I, t.apply(Point2S.PLUS_I), TEST_EPS);
45 SphericalTestUtils.assertPointsEqual(Point2S.PLUS_J, t.apply(Point2S.PLUS_J), TEST_EPS);
46 SphericalTestUtils.assertPointsEqual(Point2S.PLUS_K, t.apply(Point2S.PLUS_K), TEST_EPS);
47
48 checkInverse(t);
49 }
50
51 @Test
52 void testRotation() {
53
54 final Transform2S aroundPole = Transform2S.createRotation(Point2S.PLUS_K, Angle.PI_OVER_TWO);
55 final Transform2S aroundX = Transform2S.createRotation(Vector3D.Unit.PLUS_X, -Angle.PI_OVER_TWO);
56 final Transform2S aroundY = Transform2S.createRotation(
57 QuaternionRotation.fromAxisAngle(Vector3D.Unit.PLUS_Y, Angle.PI_OVER_TWO));
58
59
60 SphericalTestUtils.assertPointsEqual(Point2S.PLUS_J, aroundPole.apply(Point2S.PLUS_I), TEST_EPS);
61 SphericalTestUtils.assertPointsEqual(Point2S.MINUS_I, aroundPole.apply(Point2S.PLUS_J), TEST_EPS);
62 SphericalTestUtils.assertPointsEq(Point2S.PLUS_K, aroundPole.apply(Point2S.PLUS_K), TEST_EPS);
63 checkInverse(aroundPole);
64
65 SphericalTestUtils.assertPointsEqual(Point2S.PLUS_I, aroundX.apply(Point2S.PLUS_I), TEST_EPS);
66 SphericalTestUtils.assertPointsEq(Point2S.MINUS_K, aroundX.apply(Point2S.PLUS_J), TEST_EPS);
67 SphericalTestUtils.assertPointsEqual(Point2S.PLUS_J, aroundX.apply(Point2S.PLUS_K), TEST_EPS);
68 checkInverse(aroundX);
69
70 SphericalTestUtils.assertPointsEq(Point2S.MINUS_K, aroundY.apply(Point2S.PLUS_I), TEST_EPS);
71 SphericalTestUtils.assertPointsEqual(Point2S.PLUS_J, aroundY.apply(Point2S.PLUS_J), TEST_EPS);
72 SphericalTestUtils.assertPointsEqual(Point2S.PLUS_I, aroundY.apply(Point2S.PLUS_K), TEST_EPS);
73 checkInverse(aroundY);
74 }
75
76 @Test
77 void testMultipleRotations() {
78
79 final Transform2S t = Transform2S.identity()
80 .rotate(Point2S.PLUS_K, Angle.PI_OVER_TWO)
81 .rotate(Vector3D.Unit.PLUS_X, -Angle.PI_OVER_TWO)
82 .rotate(QuaternionRotation.fromAxisAngle(Vector3D.Unit.PLUS_Y, Angle.PI_OVER_TWO));
83
84
85 SphericalTestUtils.assertPointsEqual(Point2S.MINUS_I, t.apply(Point2S.PLUS_I), TEST_EPS);
86 SphericalTestUtils.assertPointsEq(Point2S.PLUS_K, t.apply(Point2S.PLUS_J), TEST_EPS);
87 SphericalTestUtils.assertPointsEqual(Point2S.PLUS_J, t.apply(Point2S.PLUS_K), TEST_EPS);
88
89 checkInverse(t);
90 }
91
92 @Test
93 void testMultiply() {
94
95 final Transform2S t = Transform2S.identity()
96 .multiply(Transform2S.createRotation(Point2S.PLUS_K, Angle.PI_OVER_TWO))
97 .multiply(Transform2S.createRotation(Point2S.PLUS_J, Angle.PI_OVER_TWO));
98
99
100 SphericalTestUtils.assertPointsEq(Point2S.MINUS_K, t.apply(Point2S.PLUS_I), TEST_EPS);
101 SphericalTestUtils.assertPointsEqual(Point2S.MINUS_I, t.apply(Point2S.PLUS_J), TEST_EPS);
102 SphericalTestUtils.assertPointsEqual(Point2S.PLUS_J, t.apply(Point2S.PLUS_K), TEST_EPS);
103
104 checkInverse(t);
105 }
106
107 @Test
108 void testPremultiply() {
109
110 final Transform2S t = Transform2S.identity()
111 .premultiply(Transform2S.createRotation(Point2S.PLUS_K, Angle.PI_OVER_TWO))
112 .premultiply(Transform2S.createRotation(Point2S.PLUS_J, Angle.PI_OVER_TWO));
113
114
115 SphericalTestUtils.assertPointsEqual(Point2S.PLUS_J, t.apply(Point2S.PLUS_I), TEST_EPS);
116 SphericalTestUtils.assertPointsEq(Point2S.PLUS_K, t.apply(Point2S.PLUS_J), TEST_EPS);
117 SphericalTestUtils.assertPointsEqual(Point2S.PLUS_I, t.apply(Point2S.PLUS_K), TEST_EPS);
118
119 checkInverse(t);
120 }
121
122 @Test
123 void testReflection_point() {
124
125 final Point2S a = Point2S.of(1, 1);
126 final Point2S b = Point2S.of(-1, 1);
127
128 final Point2S c = Point2S.of(1, Math.PI - 1);
129 final Point2S d = Point2S.of(-1, Math.PI - 1);
130
131
132 final Transform2S t = Transform2S.createReflection(Point2S.PLUS_I);
133
134
135 Assertions.assertFalse(t.preservesOrientation());
136
137 SphericalTestUtils.assertPointsEqual(Point2S.MINUS_I, t.apply(Point2S.PLUS_I), TEST_EPS);
138 SphericalTestUtils.assertPointsEqual(Point2S.PLUS_J, t.apply(Point2S.PLUS_J), TEST_EPS);
139 SphericalTestUtils.assertPointsEq(Point2S.PLUS_K, t.apply(Point2S.PLUS_K), TEST_EPS);
140
141 SphericalTestUtils.assertPointsEqual(Point2S.of(Math.PI - 1, 1), t.apply(a), TEST_EPS);
142 SphericalTestUtils.assertPointsEqual(Point2S.of(Math.PI + 1, 1), t.apply(b), TEST_EPS);
143
144 SphericalTestUtils.assertPointsEqual(Point2S.of(Math.PI - 1, Math.PI - 1), t.apply(c), TEST_EPS);
145 SphericalTestUtils.assertPointsEqual(Point2S.of(Math.PI + 1, Math.PI - 1), t.apply(d), TEST_EPS);
146
147 checkInverse(t);
148 }
149
150 @Test
151 void testReflection_vector() {
152
153 final Point2S a = Point2S.of(1, 1);
154 final Point2S b = Point2S.of(-1, 1);
155
156 final Point2S c = Point2S.of(1, Math.PI - 1);
157 final Point2S d = Point2S.of(-1, Math.PI - 1);
158
159
160 final Transform2S t = Transform2S.createReflection(Vector3D.Unit.PLUS_Y);
161
162
163 Assertions.assertFalse(t.preservesOrientation());
164
165 SphericalTestUtils.assertPointsEqual(Point2S.PLUS_I, t.apply(Point2S.PLUS_I), TEST_EPS);
166 SphericalTestUtils.assertPointsEqual(Point2S.MINUS_J, t.apply(Point2S.PLUS_J), TEST_EPS);
167 SphericalTestUtils.assertPointsEq(Point2S.PLUS_K, t.apply(Point2S.PLUS_K), TEST_EPS);
168
169 SphericalTestUtils.assertPointsEqual(b, t.apply(a), TEST_EPS);
170 SphericalTestUtils.assertPointsEqual(a, t.apply(b), TEST_EPS);
171
172 SphericalTestUtils.assertPointsEqual(d, t.apply(c), TEST_EPS);
173 SphericalTestUtils.assertPointsEqual(c, t.apply(d), TEST_EPS);
174
175 checkInverse(t);
176 }
177
178 @Test
179 void testDoubleReflection() {
180
181 final Point2S a = Point2S.of(1, 1);
182 final Point2S b = Point2S.of(-1, 1);
183
184 final Point2S c = Point2S.of(1, Math.PI - 1);
185 final Point2S d = Point2S.of(-1, Math.PI - 1);
186
187
188 final Transform2S t = Transform2S.identity()
189 .reflect(Point2S.PLUS_I)
190 .reflect(Vector3D.Unit.PLUS_Y);
191
192
193 Assertions.assertTrue(t.preservesOrientation());
194
195 SphericalTestUtils.assertPointsEqual(Point2S.MINUS_I, t.apply(Point2S.PLUS_I), TEST_EPS);
196 SphericalTestUtils.assertPointsEqual(Point2S.MINUS_J, t.apply(Point2S.PLUS_J), TEST_EPS);
197 SphericalTestUtils.assertPointsEq(Point2S.PLUS_K, t.apply(Point2S.PLUS_K), TEST_EPS);
198
199 SphericalTestUtils.assertPointsEqual(Point2S.of(Math.PI + 1, 1), t.apply(a), TEST_EPS);
200 SphericalTestUtils.assertPointsEqual(Point2S.of(Math.PI - 1, 1), t.apply(b), TEST_EPS);
201
202 SphericalTestUtils.assertPointsEqual(Point2S.of(Math.PI + 1, Math.PI - 1), t.apply(c), TEST_EPS);
203 SphericalTestUtils.assertPointsEqual(Point2S.of(Math.PI - 1, Math.PI - 1), t.apply(d), TEST_EPS);
204
205 checkInverse(t);
206 }
207
208 @Test
209 void testHashcode() {
210
211 final Transform2S a = Transform2S.createRotation(Point2S.PLUS_I, Angle.PI_OVER_TWO);
212 final Transform2S b = Transform2S.createRotation(Point2S.PLUS_J, Angle.PI_OVER_TWO);
213 final Transform2S c = Transform2S.createRotation(Point2S.PLUS_I, Math.PI);
214 final Transform2S d = Transform2S.createRotation(Point2S.PLUS_I, Angle.PI_OVER_TWO);
215
216
217 final int hash = a.hashCode();
218
219
220 Assertions.assertEquals(hash, a.hashCode());
221
222 Assertions.assertNotEquals(hash, b.hashCode());
223 Assertions.assertNotEquals(hash, c.hashCode());
224
225 Assertions.assertEquals(hash, d.hashCode());
226 }
227
228 @Test
229 void testEquals() {
230
231 final Transform2S a = Transform2S.createRotation(Point2S.PLUS_I, Angle.PI_OVER_TWO);
232 final Transform2S b = Transform2S.createRotation(Point2S.PLUS_J, Angle.PI_OVER_TWO);
233 final Transform2S c = Transform2S.createRotation(Point2S.PLUS_I, Math.PI);
234 final Transform2S d = Transform2S.createRotation(Point2S.PLUS_I, Angle.PI_OVER_TWO);
235
236
237 GeometryTestUtils.assertSimpleEqualsCases(a);
238
239 Assertions.assertNotEquals(a, b);
240 Assertions.assertNotEquals(a, c);
241
242 Assertions.assertEquals(a, d);
243 Assertions.assertEquals(d, a);
244 }
245
246 @Test
247 void testToString() {
248
249 final Transform2S t = Transform2S.identity();
250
251
252 final String str = t.toString();
253
254
255 GeometryTestUtils.assertContains("Transform2S", str);
256 GeometryTestUtils.assertContains("euclideanTransform= [", str);
257 }
258
259 private static void checkInverse(final Transform2S t) {
260 final Transform2S inv = t.inverse();
261
262
263 for (double az = -Angle.TWO_PI; az <= 2 * Angle.TWO_PI; az += 0.2) {
264 for (double p = 0.1; p < Math.PI; p += 0.2) {
265
266 final Point2S pt = Point2S.of(az, p);
267
268 SphericalTestUtils.assertPointsEqual(pt, inv.apply(t.apply(pt)), TEST_EPS);
269 SphericalTestUtils.assertPointsEqual(pt, t.apply(inv.apply(pt)), TEST_EPS);
270 }
271 }
272
273
274 SphericalTestUtils.assertVectorsEqual(Vector3D.Unit.PLUS_Z,
275 inv.apply(t.apply(Point2S.of(1, 0))).getVector(), TEST_EPS);
276 SphericalTestUtils.assertVectorsEqual(Vector3D.Unit.PLUS_Z,
277 t.apply(inv.apply(Point2S.of(-1, 0))).getVector(), TEST_EPS);
278
279 SphericalTestUtils.assertVectorsEqual(Vector3D.Unit.MINUS_Z,
280 inv.apply(t.apply(Point2S.of(1, Math.PI))).getVector(), TEST_EPS);
281 SphericalTestUtils.assertVectorsEqual(Vector3D.Unit.MINUS_Z,
282 t.apply(inv.apply(Point2S.of(-1, Math.PI))).getVector(), TEST_EPS);
283 }
284 }