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.oned;
18  
19  import java.util.Comparator;
20  
21  import org.apache.commons.geometry.core.GeometryTestUtils;
22  import org.apache.commons.geometry.core.precision.DoublePrecisionContext;
23  import org.apache.commons.geometry.core.precision.EpsilonDoublePrecisionContext;
24  import org.apache.commons.geometry.euclidean.twod.PolarCoordinates;
25  import org.apache.commons.geometry.euclidean.twod.Vector2D;
26  import org.apache.commons.numbers.angle.PlaneAngle;
27  import org.apache.commons.numbers.angle.PlaneAngleRadians;
28  import org.junit.Assert;
29  import org.junit.Test;
30  
31  public class Point1STest {
32  
33      private static final double TEST_EPS = 1e-10;
34  
35      @Test
36      public void testConstants() {
37          // act/assert
38          Assert.assertEquals(0.0, Point1S.ZERO.getAzimuth(), TEST_EPS);
39          Assert.assertEquals(Math.PI, Point1S.PI.getAzimuth(), TEST_EPS);
40      }
41  
42      @Test
43      public void testNormalizedAzimuthComparator() {
44          // arrange
45          final Comparator<Point1S> comp = Point1S.NORMALIZED_AZIMUTH_ASCENDING_ORDER;
46  
47          // act/assert
48          Assert.assertEquals(0, comp.compare(Point1S.of(1), Point1S.of(1)));
49          Assert.assertEquals(-1, comp.compare(Point1S.of(0), Point1S.of(1)));
50          Assert.assertEquals(1, comp.compare(Point1S.of(1), Point1S.of(0)));
51          Assert.assertEquals(1, comp.compare(Point1S.of(1), Point1S.of(0.1 + PlaneAngleRadians.TWO_PI)));
52  
53          Assert.assertEquals(1, comp.compare(null, Point1S.of(0)));
54          Assert.assertEquals(-1, comp.compare(Point1S.of(0), null));
55          Assert.assertEquals(0, comp.compare(null, null));
56      }
57  
58      @Test
59      public void testOf() {
60          // act/assert
61          checkPoint(Point1S.of(0), 0, 0);
62          checkPoint(Point1S.of(1), 1, 1);
63          checkPoint(Point1S.of(-1), -1, PlaneAngleRadians.TWO_PI - 1);
64  
65          checkPoint(Point1S.of(PlaneAngle.ofDegrees(90)), PlaneAngleRadians.PI_OVER_TWO, PlaneAngleRadians.PI_OVER_TWO);
66          checkPoint(Point1S.of(PlaneAngle.ofTurns(0.5)), PlaneAngleRadians.PI, PlaneAngleRadians.PI);
67          checkPoint(Point1S.of(-PlaneAngleRadians.PI_OVER_TWO), -PlaneAngleRadians.PI_OVER_TWO, 1.5 * PlaneAngleRadians.PI);
68  
69          final double base = PlaneAngleRadians.PI_OVER_TWO;
70          for (int k = -3; k <= 3; ++k) {
71              final double az = base + (k * PlaneAngleRadians.TWO_PI);
72              checkPoint(Point1S.of(az), az, base);
73          }
74      }
75  
76      @Test
77      public void testFrom_vector() {
78          // act/assert
79          checkPoint(Point1S.from(Vector2D.of(2, 0)), 0.0);
80          checkPoint(Point1S.from(Vector2D.of(0, 0.1)), PlaneAngleRadians.PI_OVER_TWO);
81          checkPoint(Point1S.from(Vector2D.of(-0.5, 0)), PlaneAngleRadians.PI);
82          checkPoint(Point1S.from(Vector2D.of(0, -100)), 1.5 * PlaneAngleRadians.PI);
83      }
84  
85      @Test
86      public void testFrom_polar() {
87          // act/assert
88          checkPoint(Point1S.from(PolarCoordinates.of(100, 0)), 0.0);
89          checkPoint(Point1S.from(PolarCoordinates.of(1, PlaneAngleRadians.PI_OVER_TWO)), PlaneAngleRadians.PI_OVER_TWO);
90          checkPoint(Point1S.from(PolarCoordinates.of(0.5, PlaneAngleRadians.PI)), PlaneAngleRadians.PI);
91          checkPoint(Point1S.from(PolarCoordinates.of(1e-4, -PlaneAngleRadians.PI_OVER_TWO)), 1.5 * PlaneAngleRadians.PI);
92      }
93  
94      @Test
95      public void testFrom_polar_invalidAzimuths() {
96          // act/assert
97          checkPoint(Point1S.from(PolarCoordinates.of(100, Double.POSITIVE_INFINITY)), Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
98          checkPoint(Point1S.from(PolarCoordinates.of(100, Double.NEGATIVE_INFINITY)), Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY);
99          checkPoint(Point1S.from(PolarCoordinates.of(100, Double.NaN)), Double.NaN, Double.NaN);
100     }
101 
102     @Test
103     public void testNaN() {
104         // act
105         final Point1S pt = Point1S.of(Double.NaN);
106 
107         // assert
108         Assert.assertTrue(pt.isNaN());
109         Assert.assertTrue(Point1S.NaN.isNaN());
110 
111         Assert.assertTrue(Double.isNaN(pt.getAzimuth()));
112         Assert.assertTrue(Double.isNaN(pt.getNormalizedAzimuth()));
113         Assert.assertNull(pt.getVector());
114 
115         Assert.assertEquals(Point1S.NaN, pt);
116         Assert.assertNotEquals(Point1S.of(1.0), Point1S.NaN);
117     }
118 
119     @Test
120     public void testGetDimension() {
121         // arrange
122         final Point1S p = Point1S.of(0.0);
123 
124         // act/assert
125         Assert.assertEquals(1, p.getDimension());
126     }
127 
128     @Test
129     public void testInfinite() {
130         // act/assert
131         Assert.assertTrue(Point1S.of(Double.POSITIVE_INFINITY).isInfinite());
132         Assert.assertTrue(Point1S.of(Double.NEGATIVE_INFINITY).isInfinite());
133 
134         Assert.assertFalse(Point1S.NaN.isInfinite());
135         Assert.assertFalse(Point1S.of(1).isInfinite());
136     }
137 
138     @Test
139     public void testFinite() {
140         // act/assert
141         Assert.assertTrue(Point1S.of(0).isFinite());
142         Assert.assertTrue(Point1S.of(1).isFinite());
143 
144         Assert.assertFalse(Point1S.of(Double.POSITIVE_INFINITY).isFinite());
145         Assert.assertFalse(Point1S.of(Double.NEGATIVE_INFINITY).isFinite());
146         Assert.assertFalse(Point1S.NaN.isFinite());
147     }
148 
149     @Test
150     public void testAntipodal() {
151         for (double az = -6 * PlaneAngleRadians.PI; az <= 6 * PlaneAngleRadians.PI; az += 0.1) {
152             // arrange
153             final Point1S pt = Point1S.of(az);
154 
155             // act
156             final Point1S result = pt.antipodal();
157 
158             // assert
159             Assert.assertTrue(result.getAzimuth() >= 0 && result.getAzimuth() < PlaneAngleRadians.TWO_PI);
160             Assert.assertEquals(PlaneAngleRadians.PI, pt.distance(result), TEST_EPS);
161         }
162     }
163 
164     @Test
165     public void testHashCode() {
166         // act
167         final Point1S a = Point1S.of(1.0);
168         final Point1S b = Point1S.of(2.0);
169         final Point1S c = Point1S.of(1.0);
170         final Point1S d = Point1S.of(1.0 + PlaneAngleRadians.PI);
171 
172         final int hash = a.hashCode();
173 
174         // assert
175         Assert.assertEquals(hash, a.hashCode());
176         Assert.assertNotEquals(hash, b.hashCode());
177         Assert.assertEquals(hash, c.hashCode());
178         Assert.assertNotEquals(hash, d.hashCode());
179 
180         Assert.assertEquals(Point1S.NaN.hashCode(), Point1S.of(Double.NaN).hashCode());
181     }
182 
183     @Test
184     public void testEquals() {
185         // act
186         final Point1S a = Point1S.of(1.0);
187         final Point1S b = Point1S.of(2.0);
188         final Point1S c = Point1S.of(1.0 + PlaneAngleRadians.PI);
189         final Point1S d = Point1S.of(1.0);
190         final Point1S e = Point1S.of(Double.NaN);
191 
192         // assert
193         Assert.assertFalse(a.equals(null));
194         Assert.assertFalse(a.equals(new Object()));
195 
196         Assert.assertEquals(a, a);
197 
198         Assert.assertNotEquals(a, b);
199         Assert.assertNotEquals(b, a);
200 
201         Assert.assertNotEquals(a, c);
202         Assert.assertNotEquals(c, a);
203 
204         Assert.assertEquals(a, d);
205         Assert.assertEquals(d, a);
206 
207         Assert.assertNotEquals(a, e);
208         Assert.assertEquals(Point1S.NaN, e);
209     }
210 
211     @Test
212     public void testEqualsAndHashCode_signedZeroConsistency() {
213         // arrange
214         final Point1S a = Point1S.of(0.0);
215         final Point1S b = Point1S.of(-0.0);
216         final Point1S c = Point1S.of(0.0);
217         final Point1S d = Point1S.of(-0.0);
218 
219         // act/assert
220         Assert.assertFalse(a.equals(b));
221         Assert.assertNotEquals(a.hashCode(), b.hashCode());
222 
223         Assert.assertTrue(a.equals(c));
224         Assert.assertEquals(a.hashCode(), c.hashCode());
225 
226         Assert.assertTrue(b.equals(d));
227         Assert.assertEquals(b.hashCode(), d.hashCode());
228     }
229 
230     @Test
231     public void testEq() {
232         // arrange
233         final DoublePrecisionContext highPrecision = new EpsilonDoublePrecisionContext(1e-10);
234         final DoublePrecisionContext lowPrecision = new EpsilonDoublePrecisionContext(1e-2);
235 
236         final Point1S a = Point1S.of(1);
237         final Point1S b = Point1S.of(0.9999);
238         final Point1S c = Point1S.of(1.00001);
239         final Point1S d = Point1S.of(1 + (3 * PlaneAngleRadians.TWO_PI));
240 
241         // act/assert
242         Assert.assertTrue(a.eq(a, highPrecision));
243         Assert.assertTrue(a.eq(a, lowPrecision));
244 
245         Assert.assertFalse(a.eq(b, highPrecision));
246         Assert.assertTrue(a.eq(b, lowPrecision));
247 
248         Assert.assertFalse(a.eq(c, highPrecision));
249         Assert.assertTrue(a.eq(c, lowPrecision));
250 
251         Assert.assertTrue(a.eq(d, highPrecision));
252         Assert.assertTrue(a.eq(d, lowPrecision));
253     }
254 
255     @Test
256     public void testEq_wrapAround() {
257         // arrange
258         final DoublePrecisionContext precision = new EpsilonDoublePrecisionContext(1e-2);
259 
260         final Point1S a = Point1S.ZERO;
261         final Point1S b = Point1S.of(1e-3);
262         final Point1S c = Point1S.of(-1e-3);
263 
264         // act/assert
265         Assert.assertTrue(a.eq(a, precision));
266 
267         Assert.assertTrue(a.eq(b, precision));
268         Assert.assertTrue(b.eq(a, precision));
269 
270         Assert.assertTrue(a.eq(c, precision));
271         Assert.assertTrue(c.eq(a, precision));
272     }
273 
274     @Test
275     public void testDistance() {
276         // arrange
277         final Point1S a = Point1S.of(0.0);
278         final Point1S b = Point1S.of(PlaneAngleRadians.PI - 0.5);
279         final Point1S c = Point1S.of(PlaneAngleRadians.PI);
280         final Point1S d = Point1S.of(PlaneAngleRadians.PI + 0.5);
281         final Point1S e = Point1S.of(4.0);
282 
283         // act/assert
284         Assert.assertEquals(0.0, a.distance(a), TEST_EPS);
285         Assert.assertEquals(PlaneAngleRadians.PI - 0.5, a.distance(b), TEST_EPS);
286         Assert.assertEquals(PlaneAngleRadians.PI - 0.5, b.distance(a), TEST_EPS);
287 
288         Assert.assertEquals(PlaneAngleRadians.PI, a.distance(c), TEST_EPS);
289         Assert.assertEquals(PlaneAngleRadians.PI, c.distance(a), TEST_EPS);
290 
291         Assert.assertEquals(PlaneAngleRadians.PI - 0.5, a.distance(d), TEST_EPS);
292         Assert.assertEquals(PlaneAngleRadians.PI - 0.5, d.distance(a), TEST_EPS);
293 
294         Assert.assertEquals(PlaneAngleRadians.TWO_PI - 4, a.distance(e), TEST_EPS);
295         Assert.assertEquals(PlaneAngleRadians.TWO_PI - 4, e.distance(a), TEST_EPS);
296     }
297 
298     @Test
299     public void testSignedDistance() {
300         // arrange
301         final Point1S a = Point1S.of(0.0);
302         final Point1S b = Point1S.of(PlaneAngleRadians.PI - 0.5);
303         final Point1S c = Point1S.of(PlaneAngleRadians.PI);
304         final Point1S d = Point1S.of(PlaneAngleRadians.PI + 0.5);
305         final Point1S e = Point1S.of(4.0);
306 
307         // act/assert
308         Assert.assertEquals(0.0, a.signedDistance(a), TEST_EPS);
309         Assert.assertEquals(PlaneAngleRadians.PI - 0.5, a.signedDistance(b), TEST_EPS);
310         Assert.assertEquals(-PlaneAngleRadians.PI + 0.5, b.signedDistance(a), TEST_EPS);
311 
312         Assert.assertEquals(-PlaneAngleRadians.PI, a.signedDistance(c), TEST_EPS);
313         Assert.assertEquals(-PlaneAngleRadians.PI, c.signedDistance(a), TEST_EPS);
314 
315         Assert.assertEquals(-PlaneAngleRadians.PI + 0.5, a.signedDistance(d), TEST_EPS);
316         Assert.assertEquals(PlaneAngleRadians.PI - 0.5, d.signedDistance(a), TEST_EPS);
317 
318         Assert.assertEquals(-PlaneAngleRadians.TWO_PI + 4, a.signedDistance(e), TEST_EPS);
319         Assert.assertEquals(PlaneAngleRadians.TWO_PI - 4, e.signedDistance(a), TEST_EPS);
320     }
321 
322     @Test
323     public void testDistance_inRangeZeroToPi() {
324         for (double a = -4 * PlaneAngleRadians.PI; a < 4 * PlaneAngleRadians.PI; a += 0.1) {
325             for (double b = -4 * PlaneAngleRadians.PI; b < 4 * PlaneAngleRadians.PI; b += 0.1) {
326                 // arrange
327                 final Point1S p1 = Point1S.of(a);
328                 final Point1S p2 = Point1S.of(b);
329 
330                 // act/assert
331                 final double d1 = p1.distance(p2);
332                 Assert.assertTrue(d1 >= 0 && d1 <= PlaneAngleRadians.PI);
333 
334                 final double d2 = p2.distance(p1);
335                 Assert.assertTrue(d2 >= 0 && d2 <= PlaneAngleRadians.PI);
336             }
337         }
338     }
339 
340     @Test
341     public void testNormalize() {
342         for (double az = -PlaneAngleRadians.TWO_PI; az < 2 * PlaneAngleRadians.TWO_PI; az += 0.2) {
343             // arrange
344             final Point1S pt = Point1S.of(az);
345 
346             final double expectedPiNorm = PlaneAngleRadians.normalizeBetweenZeroAndTwoPi(az);
347             final double expectedZeroNorm = PlaneAngleRadians.normalizeBetweenMinusPiAndPi(az);
348 
349             // act
350             final Point1S piNorm = pt.normalize(Point1S.PI);
351             final Point1S zeroNorm = pt.normalize(0.0);
352 
353             // assert
354             Assert.assertEquals(expectedPiNorm, piNorm.getAzimuth(), TEST_EPS);
355             Assert.assertEquals(pt.getNormalizedAzimuth(), piNorm.getNormalizedAzimuth(), TEST_EPS);
356 
357             Assert.assertEquals(expectedZeroNorm, zeroNorm.getAzimuth(), TEST_EPS);
358             Assert.assertEquals(pt.getNormalizedAzimuth(), zeroNorm.getNormalizedAzimuth(), TEST_EPS);
359         }
360     }
361 
362     @Test
363     public void testNormalize_nonFinite() {
364         // act/assert
365         GeometryTestUtils.assertThrows(() -> {
366             Point1S.of(Double.POSITIVE_INFINITY).normalize(0.0);
367         }, IllegalArgumentException.class);
368 
369         GeometryTestUtils.assertThrows(() -> {
370             Point1S.of(Double.NEGATIVE_INFINITY).normalize(0.0);
371         }, IllegalArgumentException.class);
372 
373         GeometryTestUtils.assertThrows(() -> {
374             Point1S.of(Double.NaN).normalize(Point1S.ZERO);
375         }, IllegalArgumentException.class);
376     }
377 
378     @Test
379     public void testAbove() {
380         // arrange
381         final Point1S p1 = Point1S.ZERO;
382         final Point1S p2 = Point1S.of(PlaneAngle.ofDegrees(90));
383         final Point1S p3 = Point1S.PI;
384         final Point1S p4 = Point1S.of(PlaneAngle.ofDegrees(-90));
385         final Point1S p5 = Point1S.of(PlaneAngleRadians.TWO_PI);
386 
387         // act/assert
388         checkPoint(p1.above(p1), 0);
389         checkPoint(p2.above(p1), PlaneAngleRadians.PI_OVER_TWO);
390         checkPoint(p3.above(p1), PlaneAngleRadians.PI);
391         checkPoint(p4.above(p1), 1.5 * PlaneAngleRadians.PI);
392         checkPoint(p5.above(p1), 0);
393 
394         checkPoint(p1.above(p3), PlaneAngleRadians.TWO_PI);
395         checkPoint(p2.above(p3), 2.5 * PlaneAngleRadians.PI);
396         checkPoint(p3.above(p3), PlaneAngleRadians.PI);
397         checkPoint(p4.above(p3), 1.5 * PlaneAngleRadians.PI);
398         checkPoint(p5.above(p3), PlaneAngleRadians.TWO_PI);
399     }
400 
401     @Test
402     public void testAbove_nonFinite() {
403         // act/assert
404         GeometryTestUtils.assertThrows(() -> {
405             Point1S.of(Double.POSITIVE_INFINITY).above(Point1S.ZERO);
406         }, IllegalArgumentException.class);
407 
408         GeometryTestUtils.assertThrows(() -> {
409             Point1S.of(Double.NEGATIVE_INFINITY).above(Point1S.ZERO);
410         }, IllegalArgumentException.class);
411 
412         GeometryTestUtils.assertThrows(() -> {
413             Point1S.of(Double.NaN).above(Point1S.ZERO);
414         }, IllegalArgumentException.class);
415     }
416 
417     @Test
418     public void testBelow() {
419         // arrange
420         final Point1S p1 = Point1S.ZERO;
421         final Point1S p2 = Point1S.of(PlaneAngle.ofDegrees(90));
422         final Point1S p3 = Point1S.PI;
423         final Point1S p4 = Point1S.of(PlaneAngle.ofDegrees(-90));
424         final Point1S p5 = Point1S.of(PlaneAngleRadians.TWO_PI);
425 
426         // act/assert
427         checkPoint(p1.below(p1), -PlaneAngleRadians.TWO_PI);
428         checkPoint(p2.below(p1), -1.5 * PlaneAngleRadians.PI);
429         checkPoint(p3.below(p1), -PlaneAngleRadians.PI);
430         checkPoint(p4.below(p1), -PlaneAngleRadians.PI_OVER_TWO);
431         checkPoint(p5.below(p1), -PlaneAngleRadians.TWO_PI);
432 
433         checkPoint(p1.below(p3), 0.0);
434         checkPoint(p2.below(p3), PlaneAngleRadians.PI_OVER_TWO);
435         checkPoint(p3.below(p3), -PlaneAngleRadians.PI);
436         checkPoint(p4.below(p3), -PlaneAngleRadians.PI_OVER_TWO);
437         checkPoint(p5.below(p3), 0.0);
438     }
439 
440     @Test
441     public void testBelow_nonFinite() {
442         // act/assert
443         GeometryTestUtils.assertThrows(() -> {
444             Point1S.of(Double.POSITIVE_INFINITY).below(Point1S.ZERO);
445         }, IllegalArgumentException.class);
446 
447         GeometryTestUtils.assertThrows(() -> {
448             Point1S.of(Double.NEGATIVE_INFINITY).below(Point1S.ZERO);
449         }, IllegalArgumentException.class);
450 
451         GeometryTestUtils.assertThrows(() -> {
452             Point1S.of(Double.NaN).below(Point1S.ZERO);
453         }, IllegalArgumentException.class);
454     }
455 
456     @Test
457     public void testToString() {
458         // act/assert
459         Assert.assertEquals("(0.0)", Point1S.of(0.0).toString());
460         Assert.assertEquals("(1.0)", Point1S.of(1.0).toString());
461     }
462 
463     @Test
464     public void testParse() {
465         // act/assert
466         checkPoint(Point1S.parse("(0)"), 0.0);
467         checkPoint(Point1S.parse("(1)"), 1.0);
468     }
469 
470     @Test(expected = IllegalArgumentException.class)
471     public void testParse_failure() {
472         // act/assert
473         Point1S.parse("abc");
474     }
475 
476     private static void checkPoint(final Point1S pt, final double az) {
477         checkPoint(pt, az, PlaneAngleRadians.normalizeBetweenZeroAndTwoPi(az));
478     }
479 
480     private static void checkPoint(final Point1S pt, final double az, final double normAz) {
481         Assert.assertEquals(az, pt.getAzimuth(), TEST_EPS);
482         Assert.assertEquals(normAz, pt.getNormalizedAzimuth(), TEST_EPS);
483 
484         Assert.assertEquals(1, pt.getDimension());
485 
486         Assert.assertEquals(Double.isFinite(az), pt.isFinite());
487         Assert.assertEquals(Double.isInfinite(az), pt.isInfinite());
488 
489         final Vector2D vec = pt.getVector();
490         if (pt.isFinite()) {
491             Assert.assertEquals(1, vec.norm(), TEST_EPS);
492             Assert.assertEquals(normAz, PolarCoordinates.fromCartesian(vec).getAzimuth(), TEST_EPS);
493         } else {
494             Assert.assertNull(vec);
495         }
496     }
497 }