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