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.euclidean.threed;
18  
19  import java.util.regex.Pattern;
20  
21  import org.apache.commons.numbers.angle.PlaneAngleRadians;
22  import org.junit.Assert;
23  import org.junit.Test;
24  
25  public class SphericalCoordinatesTest {
26  
27      private static final double EPS = 1e-10;
28  
29      private static final double QUARTER_PI = 0.25 * PlaneAngleRadians.PI;
30      private static final double MINUS_QUARTER_PI = -0.25 * PlaneAngleRadians.PI;
31      private static final double THREE_QUARTER_PI = 0.75 * PlaneAngleRadians.PI;
32      private static final double MINUS_THREE_QUARTER_PI = -0.75 * PlaneAngleRadians.PI;
33  
34      @Test
35      public void testOf() {
36          // act/assert
37          checkSpherical(SphericalCoordinates.of(0, 0, 0), 0, 0, 0);
38          checkSpherical(SphericalCoordinates.of(0.1, 0.2, 0.3), 0.1, 0.2, 0.3);
39  
40          checkSpherical(SphericalCoordinates.of(1, PlaneAngleRadians.PI_OVER_TWO, PlaneAngleRadians.PI),
41                  1, PlaneAngleRadians.PI_OVER_TWO, PlaneAngleRadians.PI);
42          checkSpherical(SphericalCoordinates.of(1, -PlaneAngleRadians.PI_OVER_TWO, PlaneAngleRadians.PI_OVER_TWO),
43                  1, PlaneAngleRadians.THREE_PI_OVER_TWO, PlaneAngleRadians.PI_OVER_TWO);
44      }
45  
46      @Test
47      public void testOf_normalizesAzimuthAngle() {
48          // act/assert
49          checkSpherical(SphericalCoordinates.of(2, PlaneAngleRadians.TWO_PI, 0), 2, 0, 0);
50          checkSpherical(SphericalCoordinates.of(2, PlaneAngleRadians.PI_OVER_TWO + PlaneAngleRadians.TWO_PI, 0), 2, PlaneAngleRadians.PI_OVER_TWO, 0);
51          checkSpherical(SphericalCoordinates.of(2, -PlaneAngleRadians.PI, 0), 2, PlaneAngleRadians.PI, 0);
52          checkSpherical(SphericalCoordinates.of(2, PlaneAngleRadians.THREE_PI_OVER_TWO, 0), 2, PlaneAngleRadians.THREE_PI_OVER_TWO, 0);
53      }
54  
55      @Test
56      public void testOf_normalizesPolarAngle() {
57          // act/assert
58          checkSpherical(SphericalCoordinates.of(1, 0, 0), 1, 0, 0);
59  
60          checkSpherical(SphericalCoordinates.of(1, 0, QUARTER_PI), 1, 0, QUARTER_PI);
61          checkSpherical(SphericalCoordinates.of(1, 0, MINUS_QUARTER_PI), 1, 0, QUARTER_PI);
62  
63          checkSpherical(SphericalCoordinates.of(1, 0, PlaneAngleRadians.PI_OVER_TWO), 1, 0, PlaneAngleRadians.PI_OVER_TWO);
64          checkSpherical(SphericalCoordinates.of(1, 0, -PlaneAngleRadians.PI_OVER_TWO), 1, 0, PlaneAngleRadians.PI_OVER_TWO);
65  
66          checkSpherical(SphericalCoordinates.of(1, 0, THREE_QUARTER_PI), 1, 0, THREE_QUARTER_PI);
67          checkSpherical(SphericalCoordinates.of(1, 0, MINUS_THREE_QUARTER_PI), 1, 0, THREE_QUARTER_PI);
68  
69          checkSpherical(SphericalCoordinates.of(1, 0, PlaneAngleRadians.TWO_PI), 1, 0, 0);
70          checkSpherical(SphericalCoordinates.of(1, 0, -PlaneAngleRadians.TWO_PI), 1, 0, 0);
71      }
72  
73      @Test
74      public void testOf_angleWrapAround() {
75          // act/assert
76          checkOfWithAngleWrapAround(1, 0, 0);
77          checkOfWithAngleWrapAround(1, QUARTER_PI, QUARTER_PI);
78          checkOfWithAngleWrapAround(1, PlaneAngleRadians.PI_OVER_TWO, PlaneAngleRadians.PI_OVER_TWO);
79          checkOfWithAngleWrapAround(1, THREE_QUARTER_PI, THREE_QUARTER_PI);
80          checkOfWithAngleWrapAround(1, PlaneAngleRadians.PI, PlaneAngleRadians.PI);
81      }
82  
83      private void checkOfWithAngleWrapAround(final double radius, final double azimuth, final double polar) {
84          for (int i = -4; i <= 4; ++i) {
85              checkSpherical(
86                      SphericalCoordinates.of(radius, azimuth + (i * PlaneAngleRadians.TWO_PI), polar + (-i * PlaneAngleRadians.TWO_PI)),
87                      radius, azimuth, polar);
88          }
89      }
90  
91      @Test
92      public void testOf_negativeRadius() {
93          // act/assert
94          checkSpherical(SphericalCoordinates.of(-2, 0, 0), 2, PlaneAngleRadians.PI, PlaneAngleRadians.PI);
95          checkSpherical(SphericalCoordinates.of(-2, PlaneAngleRadians.PI, PlaneAngleRadians.PI), 2, 0, 0);
96  
97          checkSpherical(SphericalCoordinates.of(-3, PlaneAngleRadians.PI_OVER_TWO, QUARTER_PI), 3, PlaneAngleRadians.THREE_PI_OVER_TWO, THREE_QUARTER_PI);
98          checkSpherical(SphericalCoordinates.of(-3, -PlaneAngleRadians.PI_OVER_TWO, THREE_QUARTER_PI), 3, PlaneAngleRadians.PI_OVER_TWO, QUARTER_PI);
99  
100         checkSpherical(SphericalCoordinates.of(-4, QUARTER_PI, PlaneAngleRadians.PI_OVER_TWO), 4, PlaneAngleRadians.PI + QUARTER_PI, PlaneAngleRadians.PI_OVER_TWO);
101         checkSpherical(SphericalCoordinates.of(-4, MINUS_THREE_QUARTER_PI, PlaneAngleRadians.PI_OVER_TWO), 4, QUARTER_PI, PlaneAngleRadians.PI_OVER_TWO);
102     }
103 
104     @Test
105     public void testOf_NaNAndInfinite() {
106         // act/assert
107         checkSpherical(SphericalCoordinates.of(Double.NaN, Double.NaN, Double.NaN),
108                 Double.NaN, Double.NaN, Double.NaN);
109         checkSpherical(SphericalCoordinates.of(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY),
110                 Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
111         checkSpherical(SphericalCoordinates.of(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY),
112                 Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY);
113     }
114 
115     @Test
116     public void testFromCartesian_coordinates() {
117         // arrange
118         final double sqrt3 = Math.sqrt(3);
119 
120         // act/assert
121         checkSpherical(SphericalCoordinates.fromCartesian(0, 0, 0), 0, 0, 0);
122 
123         checkSpherical(SphericalCoordinates.fromCartesian(0.1, 0, 0), 0.1, 0, PlaneAngleRadians.PI_OVER_TWO);
124         checkSpherical(SphericalCoordinates.fromCartesian(-0.1, 0, 0), 0.1, PlaneAngleRadians.PI, PlaneAngleRadians.PI_OVER_TWO);
125 
126         checkSpherical(SphericalCoordinates.fromCartesian(0, 0.1, 0), 0.1, PlaneAngleRadians.PI_OVER_TWO, PlaneAngleRadians.PI_OVER_TWO);
127         checkSpherical(SphericalCoordinates.fromCartesian(0, -0.1, 0), 0.1, PlaneAngleRadians.THREE_PI_OVER_TWO, PlaneAngleRadians.PI_OVER_TWO);
128 
129         checkSpherical(SphericalCoordinates.fromCartesian(0, 0, 0.1), 0.1, 0, 0);
130         checkSpherical(SphericalCoordinates.fromCartesian(0, 0, -0.1), 0.1, 0, PlaneAngleRadians.PI);
131 
132         checkSpherical(SphericalCoordinates.fromCartesian(1, 1, 1), sqrt3, QUARTER_PI, Math.acos(1 / sqrt3));
133         checkSpherical(SphericalCoordinates.fromCartesian(-1, -1, -1), sqrt3, 1.25 * PlaneAngleRadians.PI, Math.acos(-1 / sqrt3));
134     }
135 
136     @Test
137     public void testFromCartesian_vector() {
138         // arrange
139         final double sqrt3 = Math.sqrt(3);
140 
141         // act/assert
142         checkSpherical(SphericalCoordinates.fromCartesian(Vector3D.of(0, 0, 0)), 0, 0, 0);
143 
144         checkSpherical(SphericalCoordinates.fromCartesian(Vector3D.of(0.1, 0, 0)), 0.1, 0, PlaneAngleRadians.PI_OVER_TWO);
145         checkSpherical(SphericalCoordinates.fromCartesian(Vector3D.of(-0.1, 0, 0)), 0.1, PlaneAngleRadians.PI, PlaneAngleRadians.PI_OVER_TWO);
146 
147         checkSpherical(SphericalCoordinates.fromCartesian(Vector3D.of(0, 0.1, 0)), 0.1, PlaneAngleRadians.PI_OVER_TWO, PlaneAngleRadians.PI_OVER_TWO);
148         checkSpherical(SphericalCoordinates.fromCartesian(Vector3D.of(0, -0.1, 0)), 0.1, PlaneAngleRadians.THREE_PI_OVER_TWO, PlaneAngleRadians.PI_OVER_TWO);
149 
150         checkSpherical(SphericalCoordinates.fromCartesian(Vector3D.of(0, 0, 0.1)), 0.1, 0, 0);
151         checkSpherical(SphericalCoordinates.fromCartesian(Vector3D.of(0, 0, -0.1)), 0.1, 0, PlaneAngleRadians.PI);
152 
153         checkSpherical(SphericalCoordinates.fromCartesian(Vector3D.of(1, 1, 1)), sqrt3, QUARTER_PI, Math.acos(1 / sqrt3));
154         checkSpherical(SphericalCoordinates.fromCartesian(Vector3D.of(-1, -1, -1)), sqrt3, 1.25 * PlaneAngleRadians.PI, Math.acos(-1 / sqrt3));
155     }
156 
157     @Test
158     public void testToVector() {
159         // arrange
160         final double sqrt3 = Math.sqrt(3);
161 
162         // act/assert
163         checkVector(SphericalCoordinates.of(0, 0, 0).toVector(), 0, 0, 0);
164 
165         checkVector(SphericalCoordinates.of(1, 0, PlaneAngleRadians.PI_OVER_TWO).toVector(), 1, 0, 0);
166         checkVector(SphericalCoordinates.of(1, PlaneAngleRadians.PI, PlaneAngleRadians.PI_OVER_TWO).toVector(), -1, 0, 0);
167 
168         checkVector(SphericalCoordinates.of(2, PlaneAngleRadians.PI_OVER_TWO, PlaneAngleRadians.PI_OVER_TWO).toVector(), 0, 2, 0);
169         checkVector(SphericalCoordinates.of(2, -PlaneAngleRadians.PI_OVER_TWO, PlaneAngleRadians.PI_OVER_TWO).toVector(), 0, -2, 0);
170 
171         checkVector(SphericalCoordinates.of(3, 0, 0).toVector(), 0, 0, 3);
172         checkVector(SphericalCoordinates.of(3, 0, PlaneAngleRadians.PI).toVector(), 0, 0, -3);
173 
174         checkVector(SphericalCoordinates.of(sqrt3, QUARTER_PI, Math.acos(1 / sqrt3)).toVector(), 1, 1, 1);
175         checkVector(SphericalCoordinates.of(sqrt3, MINUS_THREE_QUARTER_PI, Math.acos(-1 / sqrt3)).toVector(), -1, -1, -1);
176     }
177 
178     @Test
179     public void testToCartesian_static() {
180         // arrange
181         final double sqrt3 = Math.sqrt(3);
182 
183         // act/assert
184         checkVector(SphericalCoordinates.toCartesian(0, 0, 0), 0, 0, 0);
185 
186         checkVector(SphericalCoordinates.toCartesian(1, 0, PlaneAngleRadians.PI_OVER_TWO), 1, 0, 0);
187         checkVector(SphericalCoordinates.toCartesian(1, PlaneAngleRadians.PI, PlaneAngleRadians.PI_OVER_TWO), -1, 0, 0);
188 
189         checkVector(SphericalCoordinates.toCartesian(2, PlaneAngleRadians.PI_OVER_TWO, PlaneAngleRadians.PI_OVER_TWO), 0, 2, 0);
190         checkVector(SphericalCoordinates.toCartesian(2, -PlaneAngleRadians.PI_OVER_TWO, PlaneAngleRadians.PI_OVER_TWO), 0, -2, 0);
191 
192         checkVector(SphericalCoordinates.toCartesian(3, 0, 0), 0, 0, 3);
193         checkVector(SphericalCoordinates.toCartesian(3, 0, PlaneAngleRadians.PI), 0, 0, -3);
194 
195         checkVector(SphericalCoordinates.toCartesian(Math.sqrt(3), QUARTER_PI, Math.acos(1 / sqrt3)), 1, 1, 1);
196         checkVector(SphericalCoordinates.toCartesian(Math.sqrt(3), MINUS_THREE_QUARTER_PI, Math.acos(-1 / sqrt3)), -1, -1, -1);
197     }
198 
199     @Test
200     public void testGetDimension() {
201         // arrange
202         final SphericalCoordinates s = SphericalCoordinates.of(0, 0, 0);
203 
204         // act/assert
205         Assert.assertEquals(3, s.getDimension());
206     }
207 
208     @Test
209     public void testNaN() {
210         // act/assert
211         Assert.assertTrue(SphericalCoordinates.of(0, 0, Double.NaN).isNaN());
212         Assert.assertTrue(SphericalCoordinates.of(0, Double.NaN, 0).isNaN());
213         Assert.assertTrue(SphericalCoordinates.of(Double.NaN, 0, 0).isNaN());
214 
215         Assert.assertFalse(SphericalCoordinates.of(1, 1, 1).isNaN());
216         Assert.assertFalse(SphericalCoordinates.of(1, 1, Double.NEGATIVE_INFINITY).isNaN());
217         Assert.assertFalse(SphericalCoordinates.of(1, Double.POSITIVE_INFINITY, 1).isNaN());
218         Assert.assertFalse(SphericalCoordinates.of(Double.NEGATIVE_INFINITY, 1, 1).isNaN());
219     }
220 
221     @Test
222     public void testInfinite() {
223         // act/assert
224         Assert.assertTrue(SphericalCoordinates.of(0, 0, Double.NEGATIVE_INFINITY).isInfinite());
225         Assert.assertTrue(SphericalCoordinates.of(0, Double.NEGATIVE_INFINITY, 0).isInfinite());
226         Assert.assertTrue(SphericalCoordinates.of(Double.NEGATIVE_INFINITY, 0, 0).isInfinite());
227         Assert.assertTrue(SphericalCoordinates.of(0, 0, Double.POSITIVE_INFINITY).isInfinite());
228         Assert.assertTrue(SphericalCoordinates.of(0, Double.POSITIVE_INFINITY, 0).isInfinite());
229         Assert.assertTrue(SphericalCoordinates.of(Double.POSITIVE_INFINITY, 0, 0).isInfinite());
230 
231         Assert.assertFalse(SphericalCoordinates.of(1, 1, 1).isInfinite());
232         Assert.assertFalse(SphericalCoordinates.of(0, 0, Double.NaN).isInfinite());
233         Assert.assertFalse(SphericalCoordinates.of(0, Double.NEGATIVE_INFINITY, Double.NaN).isInfinite());
234         Assert.assertFalse(SphericalCoordinates.of(Double.NaN, 0, Double.NEGATIVE_INFINITY).isInfinite());
235         Assert.assertFalse(SphericalCoordinates.of(Double.POSITIVE_INFINITY, Double.NaN, 0).isInfinite());
236         Assert.assertFalse(SphericalCoordinates.of(0, Double.NaN, Double.POSITIVE_INFINITY).isInfinite());
237     }
238 
239     @Test
240     public void testFinite() {
241         // act/assert
242         Assert.assertTrue(SphericalCoordinates.of(1, 1, 1).isFinite());
243 
244         Assert.assertFalse(SphericalCoordinates.of(0, 0, Double.NEGATIVE_INFINITY).isFinite());
245         Assert.assertFalse(SphericalCoordinates.of(0, Double.NEGATIVE_INFINITY, 0).isFinite());
246         Assert.assertFalse(SphericalCoordinates.of(Double.NEGATIVE_INFINITY, 0, 0).isFinite());
247         Assert.assertFalse(SphericalCoordinates.of(0, 0, Double.POSITIVE_INFINITY).isFinite());
248         Assert.assertFalse(SphericalCoordinates.of(0, Double.POSITIVE_INFINITY, 0).isFinite());
249         Assert.assertFalse(SphericalCoordinates.of(Double.POSITIVE_INFINITY, 0, 0).isFinite());
250 
251         Assert.assertFalse(SphericalCoordinates.of(0, 0, Double.NaN).isFinite());
252         Assert.assertFalse(SphericalCoordinates.of(0, Double.NEGATIVE_INFINITY, Double.NaN).isFinite());
253         Assert.assertFalse(SphericalCoordinates.of(Double.NaN, 0, Double.NEGATIVE_INFINITY).isFinite());
254         Assert.assertFalse(SphericalCoordinates.of(Double.POSITIVE_INFINITY, Double.NaN, 0).isFinite());
255         Assert.assertFalse(SphericalCoordinates.of(0, Double.NaN, Double.POSITIVE_INFINITY).isFinite());
256     }
257 
258     @Test
259     public void testHashCode() {
260         // arrange
261         final SphericalCoordinates a = SphericalCoordinates.of(1, 2, 3);
262         final SphericalCoordinates b = SphericalCoordinates.of(10, 2, 3);
263         final SphericalCoordinates c = SphericalCoordinates.of(1, 20, 3);
264         final SphericalCoordinates d = SphericalCoordinates.of(1, 2, 30);
265 
266         final SphericalCoordinates e = SphericalCoordinates.of(1, 2, 3);
267 
268         // act/assert
269         Assert.assertEquals(a.hashCode(), a.hashCode());
270         Assert.assertEquals(a.hashCode(), e.hashCode());
271 
272         Assert.assertNotEquals(a.hashCode(), b.hashCode());
273         Assert.assertNotEquals(a.hashCode(), c.hashCode());
274         Assert.assertNotEquals(a.hashCode(), d.hashCode());
275     }
276 
277     @Test
278     public void testHashCode_NaNInstancesHaveSameHashCode() {
279         // arrange
280         final SphericalCoordinates a = SphericalCoordinates.of(1, 2, Double.NaN);
281         final SphericalCoordinates b = SphericalCoordinates.of(1, Double.NaN, 3);
282         final SphericalCoordinates c = SphericalCoordinates.of(Double.NaN, 2, 3);
283 
284         // act/assert
285         Assert.assertEquals(a.hashCode(), b.hashCode());
286         Assert.assertEquals(b.hashCode(), c.hashCode());
287     }
288 
289     @Test
290     public void testEquals() {
291         // arrange
292         final SphericalCoordinates a = SphericalCoordinates.of(1, 2, 3);
293         final SphericalCoordinates b = SphericalCoordinates.of(10, 2, 3);
294         final SphericalCoordinates c = SphericalCoordinates.of(1, 20, 3);
295         final SphericalCoordinates d = SphericalCoordinates.of(1, 2, 30);
296 
297         final SphericalCoordinates e = SphericalCoordinates.of(1, 2, 3);
298 
299         // act/assert
300         Assert.assertFalse(a.equals(null));
301         Assert.assertFalse(a.equals(new Object()));
302 
303         Assert.assertEquals(a, a);
304         Assert.assertEquals(a, e);
305 
306         Assert.assertNotEquals(a, b);
307         Assert.assertNotEquals(a, c);
308         Assert.assertNotEquals(a, d);
309     }
310 
311     @Test
312     public void testEquals_NaNInstancesEqual() {
313         // arrange
314         final SphericalCoordinates a = SphericalCoordinates.of(1, 2, Double.NaN);
315         final SphericalCoordinates b = SphericalCoordinates.of(1, Double.NaN, 3);
316         final SphericalCoordinates c = SphericalCoordinates.of(Double.NaN, 2, 3);
317 
318         // act/assert
319         Assert.assertEquals(a, b);
320         Assert.assertEquals(b, c);
321     }
322 
323     @Test
324     public void testEqualsAndHashCode_signedZeroConsistency() {
325         // arrange
326         final SphericalCoordinates a = SphericalCoordinates.of(0.0, -0.0, 0.0);
327         final SphericalCoordinates b = SphericalCoordinates.of(-0.0, 0.0, -0.0);
328         final SphericalCoordinates c = SphericalCoordinates.of(0.0, -0.0, 0.0);
329         final SphericalCoordinates d = SphericalCoordinates.of(-0.0, 0.0, -0.0);
330 
331         // act/assert
332         Assert.assertFalse(a.equals(b));
333         Assert.assertNotEquals(a.hashCode(), b.hashCode());
334 
335         Assert.assertTrue(a.equals(c));
336         Assert.assertEquals(a.hashCode(), c.hashCode());
337 
338         Assert.assertTrue(b.equals(d));
339         Assert.assertEquals(b.hashCode(), d.hashCode());
340     }
341 
342     @Test
343     public void testToString() {
344         // arrange
345         final SphericalCoordinates sph = SphericalCoordinates.of(1, 2, 3);
346         final Pattern pattern = Pattern.compile("\\(1.{0,2}, 2.{0,2}, 3.{0,2}\\)");
347 
348         // act
349         final String str = sph.toString();
350 
351         // assert
352         Assert.assertTrue("Expected string " + str + " to match regex " + pattern,
353                     pattern.matcher(str).matches());
354     }
355 
356     @Test
357     public void testParse() {
358         // act/assert
359         checkSpherical(SphericalCoordinates.parse("(1, 2, 3)"), 1, 2, 3);
360         checkSpherical(SphericalCoordinates.parse("(  -2.0 , 1 , -5e-1)"), 2, 1 + PlaneAngleRadians.PI, PlaneAngleRadians.PI - 0.5);
361         checkSpherical(SphericalCoordinates.parse("(NaN,Infinity,-Infinity)"), Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY);
362     }
363 
364     @Test(expected = IllegalArgumentException.class)
365     public void testParse_failure() {
366         // act/assert
367         SphericalCoordinates.parse("abc");
368     }
369 
370     @Test
371     public void testNormalizeAzimuth() {
372         // act/assert
373         Assert.assertEquals(0.0, SphericalCoordinates.normalizeAzimuth(0), EPS);
374 
375         Assert.assertEquals(PlaneAngleRadians.PI_OVER_TWO, SphericalCoordinates.normalizeAzimuth(PlaneAngleRadians.PI_OVER_TWO), EPS);
376         Assert.assertEquals(PlaneAngleRadians.PI, SphericalCoordinates.normalizeAzimuth(PlaneAngleRadians.PI), EPS);
377         Assert.assertEquals(PlaneAngleRadians.THREE_PI_OVER_TWO, SphericalCoordinates.normalizeAzimuth(PlaneAngleRadians.THREE_PI_OVER_TWO), EPS);
378         Assert.assertEquals(0.0, SphericalCoordinates.normalizeAzimuth(PlaneAngleRadians.TWO_PI), EPS);
379 
380         Assert.assertEquals(PlaneAngleRadians.THREE_PI_OVER_TWO, SphericalCoordinates.normalizeAzimuth(-PlaneAngleRadians.PI_OVER_TWO), EPS);
381         Assert.assertEquals(PlaneAngleRadians.PI, SphericalCoordinates.normalizeAzimuth(-PlaneAngleRadians.PI), EPS);
382         Assert.assertEquals(PlaneAngleRadians.PI_OVER_TWO, SphericalCoordinates.normalizeAzimuth(-PlaneAngleRadians.PI - PlaneAngleRadians.PI_OVER_TWO), EPS);
383         Assert.assertEquals(0.0, SphericalCoordinates.normalizeAzimuth(-PlaneAngleRadians.TWO_PI), EPS);
384     }
385 
386     @Test
387     public void testNormalizeAzimuth_NaNAndInfinite() {
388         // act/assert
389         Assert.assertEquals(Double.NaN, SphericalCoordinates.normalizeAzimuth(Double.NaN), EPS);
390         Assert.assertEquals(Double.NEGATIVE_INFINITY, SphericalCoordinates.normalizeAzimuth(Double.NEGATIVE_INFINITY), EPS);
391         Assert.assertEquals(Double.POSITIVE_INFINITY, SphericalCoordinates.normalizeAzimuth(Double.POSITIVE_INFINITY), EPS);
392     }
393 
394     @Test
395     public void testNormalizePolar() {
396         // act/assert
397         Assert.assertEquals(0.0, SphericalCoordinates.normalizePolar(0), EPS);
398 
399         Assert.assertEquals(PlaneAngleRadians.PI_OVER_TWO, SphericalCoordinates.normalizePolar(PlaneAngleRadians.PI_OVER_TWO), EPS);
400         Assert.assertEquals(PlaneAngleRadians.PI, SphericalCoordinates.normalizePolar(PlaneAngleRadians.PI), EPS);
401         Assert.assertEquals(PlaneAngleRadians.PI_OVER_TWO, SphericalCoordinates.normalizePolar(PlaneAngleRadians.PI + PlaneAngleRadians.PI_OVER_TWO), EPS);
402         Assert.assertEquals(0.0, SphericalCoordinates.normalizePolar(PlaneAngleRadians.TWO_PI), EPS);
403 
404         Assert.assertEquals(PlaneAngleRadians.PI_OVER_TWO, SphericalCoordinates.normalizePolar(-PlaneAngleRadians.PI_OVER_TWO), EPS);
405         Assert.assertEquals(PlaneAngleRadians.PI, SphericalCoordinates.normalizePolar(-PlaneAngleRadians.PI), EPS);
406         Assert.assertEquals(PlaneAngleRadians.PI_OVER_TWO, SphericalCoordinates.normalizePolar(-PlaneAngleRadians.PI - PlaneAngleRadians.PI_OVER_TWO), EPS);
407         Assert.assertEquals(0.0, SphericalCoordinates.normalizePolar(-PlaneAngleRadians.TWO_PI), EPS);
408     }
409 
410     @Test
411     public void testNormalizePolar_NaNAndInfinite() {
412         // act/assert
413         Assert.assertEquals(Double.NaN, SphericalCoordinates.normalizePolar(Double.NaN), EPS);
414         Assert.assertEquals(Double.NEGATIVE_INFINITY, SphericalCoordinates.normalizePolar(Double.NEGATIVE_INFINITY), EPS);
415         Assert.assertEquals(Double.POSITIVE_INFINITY, SphericalCoordinates.normalizePolar(Double.POSITIVE_INFINITY), EPS);
416     }
417 
418     private void checkSpherical(final SphericalCoordinates c, final double radius, final double azimuth, final double polar) {
419         Assert.assertEquals(radius, c.getRadius(), EPS);
420         Assert.assertEquals(azimuth, c.getAzimuth(), EPS);
421         Assert.assertEquals(polar, c.getPolar(), EPS);
422     }
423 
424     private void checkVector(final Vector3D v, final double x, final double y, final double z) {
425         Assert.assertEquals(x, v.getX(), EPS);
426         Assert.assertEquals(y, v.getY(), EPS);
427         Assert.assertEquals(z, v.getZ(), EPS);
428     }
429 }