View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
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          // act
34          final Transform2S t = Transform2S.identity();
35  
36          // assert
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          // arrange
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          // act/assert
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          // act
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          // assert
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          // act
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          // assert
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         // act
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         // assert
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         // arrange
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         // act
132         final Transform2S t = Transform2S.createReflection(Point2S.PLUS_I);
133 
134         // assert
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         // arrange
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         // act
160         final Transform2S t = Transform2S.createReflection(Vector3D.Unit.PLUS_Y);
161 
162         // assert
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         // arrange
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         // act
188         final Transform2S t = Transform2S.identity()
189                 .reflect(Point2S.PLUS_I)
190                 .reflect(Vector3D.Unit.PLUS_Y);
191 
192         // assert
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         // arrange
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         // act
217         final int hash = a.hashCode();
218 
219         // assert
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         // arrange
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         // act/assert
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         // arrange
249         final Transform2S t = Transform2S.identity();
250 
251         // act
252         final String str = t.toString();
253 
254         // assert
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         // test non-pole points
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         // test poles
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 }