1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
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
43 final Comparator<Point1S> comp = Point1S.NORMALIZED_AZIMUTH_ASCENDING_ORDER;
44
45
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
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
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
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
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
103 final Point1S pt = Point1S.of(Double.NaN);
104
105
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
120 final Point1S p = Point1S.of(0.0);
121
122
123 Assertions.assertEquals(1, p.getDimension());
124 }
125
126 @Test
127 void testInfinite() {
128
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
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
151 final Point1S pt = Point1S.of(az);
152
153
154 final Point1S result = pt.antipodal();
155
156
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
322 final Point1S p1 = Point1S.of(a);
323 final Point1S p2 = Point1S.of(b);
324
325
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
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
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
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
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
376 checkPoint(Point1S.parse("(0)"), 0.0);
377 checkPoint(Point1S.parse("(1)"), 1.0);
378 }
379
380 @Test
381 void testParse_failure() {
382
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 }