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