1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.geometry.euclidean.oned;
18
19 import org.apache.commons.geometry.core.RegionLocation;
20 import org.apache.commons.geometry.core.partitioning.Split;
21 import org.apache.commons.geometry.core.partitioning.SplitLocation;
22 import org.apache.commons.geometry.euclidean.EuclideanTestUtils;
23 import org.apache.commons.numbers.core.Precision;
24 import org.junit.jupiter.api.Assertions;
25 import org.junit.jupiter.api.Test;
26
27 class IntervalTest {
28
29 private static final double TEST_EPS = 1e-15;
30
31 private static final Precision.DoubleEquivalence TEST_PRECISION =
32 Precision.doubleEquivalenceOfEpsilon(TEST_EPS);
33
34 @Test
35 void testOf_doubles() {
36
37 checkInterval(Interval.of(0, 0, TEST_PRECISION), 0, 0);
38
39 checkInterval(Interval.of(1, 2, TEST_PRECISION), 1, 2);
40 checkInterval(Interval.of(2, 1, TEST_PRECISION), 1, 2);
41
42 checkInterval(Interval.of(-2, -1, TEST_PRECISION), -2, -1);
43 checkInterval(Interval.of(-1, -2, TEST_PRECISION), -2, -1);
44
45 checkInterval(Interval.of(1, Double.POSITIVE_INFINITY, TEST_PRECISION),
46 1, Double.POSITIVE_INFINITY);
47 checkInterval(Interval.of(Double.POSITIVE_INFINITY, 1, TEST_PRECISION),
48 1, Double.POSITIVE_INFINITY);
49
50 checkInterval(Interval.of(Double.NEGATIVE_INFINITY, 1, TEST_PRECISION),
51 Double.NEGATIVE_INFINITY, 1);
52 checkInterval(Interval.of(1, Double.NEGATIVE_INFINITY, TEST_PRECISION),
53 Double.NEGATIVE_INFINITY, 1);
54
55 checkInterval(Interval.of(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, TEST_PRECISION),
56 Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);
57
58 checkInterval(Interval.of(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, TEST_PRECISION),
59 Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);
60 }
61
62 @Test
63 void testOf_doubles_invalidIntervals() {
64
65
66 Assertions.assertThrows(IllegalArgumentException.class, () -> Interval.of(1, Double.NaN, TEST_PRECISION));
67 Assertions.assertThrows(IllegalArgumentException.class, () -> Interval.of(Double.NaN, 1, TEST_PRECISION));
68 Assertions.assertThrows(IllegalArgumentException.class, () -> Interval.of(Double.NaN, Double.NaN, TEST_PRECISION));
69 Assertions.assertThrows(IllegalArgumentException.class, () -> Interval.of(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, TEST_PRECISION));
70 Assertions.assertThrows(IllegalArgumentException.class, () -> Interval.of(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, TEST_PRECISION));
71 }
72
73 @Test
74 void testOf_points() {
75
76 checkInterval(Interval.of(Vector1D.of(1), Vector1D.of(2), TEST_PRECISION), 1, 2);
77 checkInterval(Interval.of(Vector1D.of(Double.POSITIVE_INFINITY), Vector1D.of(Double.NEGATIVE_INFINITY), TEST_PRECISION),
78 Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);
79 }
80
81 @Test
82 void testOf_points_invalidIntervals() {
83
84
85 Assertions.assertThrows(IllegalArgumentException.class, () -> Interval.of(Vector1D.of(1), Vector1D.of(Double.NaN), TEST_PRECISION));
86 Assertions.assertThrows(IllegalArgumentException.class, () -> Interval.of(Vector1D.of(Double.POSITIVE_INFINITY), Vector1D.of(Double.POSITIVE_INFINITY), TEST_PRECISION));
87 }
88
89 @Test
90 void testOf_hyperplanes() {
91
92 Assertions.assertSame(Interval.full(), Interval.of(null, null));
93
94 checkInterval(Interval.of(
95 OrientedPoints.fromLocationAndDirection(1, true, TEST_PRECISION),
96 OrientedPoints.fromLocationAndDirection(1, false, TEST_PRECISION)), 1, 1);
97 checkInterval(Interval.of(
98 OrientedPoints.fromLocationAndDirection(1, false, TEST_PRECISION),
99 OrientedPoints.fromLocationAndDirection(1, true, TEST_PRECISION)), 1, 1);
100
101 checkInterval(Interval.of(
102 OrientedPoints.fromLocationAndDirection(-2, false, TEST_PRECISION),
103 OrientedPoints.fromLocationAndDirection(5, true, TEST_PRECISION)), -2, 5);
104 checkInterval(Interval.of(
105 OrientedPoints.fromLocationAndDirection(5, true, TEST_PRECISION),
106 OrientedPoints.fromLocationAndDirection(-2, false, TEST_PRECISION)), -2, 5);
107
108 checkInterval(Interval.of(
109 null,
110 OrientedPoints.fromLocationAndDirection(5, true, TEST_PRECISION)), Double.NEGATIVE_INFINITY, 5);
111 checkInterval(Interval.of(
112 OrientedPoints.fromLocationAndDirection(5, true, TEST_PRECISION),
113 null), Double.NEGATIVE_INFINITY, 5);
114 checkInterval(Interval.of(
115 OrientedPoints.fromLocationAndDirection(Double.NEGATIVE_INFINITY, false, TEST_PRECISION),
116 OrientedPoints.fromLocationAndDirection(5, true, TEST_PRECISION)), Double.NEGATIVE_INFINITY, 5);
117
118 checkInterval(Interval.of(
119 null,
120 OrientedPoints.fromLocationAndDirection(5, false, TEST_PRECISION)), 5, Double.POSITIVE_INFINITY);
121 checkInterval(Interval.of(
122 OrientedPoints.fromLocationAndDirection(5, false, TEST_PRECISION),
123 null), 5, Double.POSITIVE_INFINITY);
124 checkInterval(Interval.of(
125 OrientedPoints.fromLocationAndDirection(Double.POSITIVE_INFINITY, true, TEST_PRECISION),
126 OrientedPoints.fromLocationAndDirection(5, false, TEST_PRECISION)), 5, Double.POSITIVE_INFINITY);
127 }
128
129 @Test
130 void testOf_hyperplanes_invalidArgs() {
131
132 Assertions.assertThrows(IllegalArgumentException.class, () -> Interval.of(
133 OrientedPoints.fromLocationAndDirection(1, false, TEST_PRECISION),
134 OrientedPoints.fromLocationAndDirection(1, false, TEST_PRECISION)));
135 Assertions.assertThrows(IllegalArgumentException.class, () -> Interval.of(
136 OrientedPoints.fromLocationAndDirection(2, false, TEST_PRECISION),
137 OrientedPoints.fromLocationAndDirection(1, true, TEST_PRECISION)));
138 Assertions.assertThrows(IllegalArgumentException.class, () -> Interval.of(
139 OrientedPoints.fromLocationAndDirection(Double.POSITIVE_INFINITY, false, TEST_PRECISION),
140 OrientedPoints.fromLocationAndDirection(Double.POSITIVE_INFINITY, true, TEST_PRECISION)));
141 Assertions.assertThrows(IllegalArgumentException.class, () -> Interval.of(
142 OrientedPoints.fromLocationAndDirection(Double.NaN, false, TEST_PRECISION),
143 OrientedPoints.fromLocationAndDirection(1, true, TEST_PRECISION)));
144 Assertions.assertThrows(IllegalArgumentException.class, () -> Interval.of(
145 OrientedPoints.fromLocationAndDirection(1, false, TEST_PRECISION),
146 OrientedPoints.fromLocationAndDirection(Double.NaN, true, TEST_PRECISION)));
147 Assertions.assertThrows(IllegalArgumentException.class, () -> Interval.of(
148 OrientedPoints.fromLocationAndDirection(Double.NaN, false, TEST_PRECISION),
149 OrientedPoints.fromLocationAndDirection(Double.NaN, true, TEST_PRECISION)));
150 Assertions.assertThrows(IllegalArgumentException.class, () -> Interval.of(
151 null,
152 OrientedPoints.fromLocationAndDirection(Double.NaN, true, TEST_PRECISION)));
153 }
154
155 @Test
156 void testPoint() {
157
158 checkInterval(Interval.point(0, TEST_PRECISION), 0, 0);
159 checkInterval(Interval.point(1, TEST_PRECISION), 1, 1);
160 checkInterval(Interval.point(-1, TEST_PRECISION), -1, -1);
161 }
162
163 @Test
164 void testPoint_invalidArgs() {
165
166 Assertions.assertThrows(IllegalArgumentException.class, () -> Interval.point(Double.NEGATIVE_INFINITY, TEST_PRECISION));
167 Assertions.assertThrows(IllegalArgumentException.class, () -> Interval.point(Double.POSITIVE_INFINITY, TEST_PRECISION));
168 Assertions.assertThrows(IllegalArgumentException.class, () -> Interval.point(Double.NaN, TEST_PRECISION));
169 }
170
171 @Test
172 void testMin() {
173
174 checkInterval(Interval.min(Double.NEGATIVE_INFINITY, TEST_PRECISION),
175 Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);
176
177 checkInterval(Interval.min(0, TEST_PRECISION), 0, Double.POSITIVE_INFINITY);
178 checkInterval(Interval.min(1, TEST_PRECISION), 1, Double.POSITIVE_INFINITY);
179 checkInterval(Interval.min(-1, TEST_PRECISION), -1, Double.POSITIVE_INFINITY);
180 }
181
182 @Test
183 void testMin_invalidArgs() {
184
185 Assertions.assertThrows(IllegalArgumentException.class, () -> Interval.min(Double.POSITIVE_INFINITY, TEST_PRECISION));
186 Assertions.assertThrows(IllegalArgumentException.class, () -> Interval.min(Double.NaN, TEST_PRECISION));
187 }
188
189 @Test
190 void testMax() {
191
192 checkInterval(Interval.max(Double.POSITIVE_INFINITY, TEST_PRECISION),
193 Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);
194
195 checkInterval(Interval.max(0, TEST_PRECISION), Double.NEGATIVE_INFINITY, 0);
196 checkInterval(Interval.max(1, TEST_PRECISION), Double.NEGATIVE_INFINITY, 1);
197 checkInterval(Interval.max(-1, TEST_PRECISION), Double.NEGATIVE_INFINITY, -1);
198 }
199
200 @Test
201 void testMax_invalidArgs() {
202
203 Assertions.assertThrows(IllegalArgumentException.class, () -> Interval.max(Double.NEGATIVE_INFINITY, TEST_PRECISION));
204 Assertions.assertThrows(IllegalArgumentException.class, () -> Interval.max(Double.NaN, TEST_PRECISION));
205 }
206
207 @Test
208 void testIsInfinite() {
209
210 Assertions.assertFalse(Interval.of(1, 2, TEST_PRECISION).isInfinite());
211
212 Assertions.assertTrue(Interval.of(Double.NEGATIVE_INFINITY, 2, TEST_PRECISION).isInfinite());
213 Assertions.assertTrue(Interval.of(2, Double.POSITIVE_INFINITY, TEST_PRECISION).isInfinite());
214 Assertions.assertTrue(Interval.of(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, TEST_PRECISION).isInfinite());
215 }
216
217 @Test
218 void testIsFinite() {
219
220 Assertions.assertTrue(Interval.of(1, 2, TEST_PRECISION).isFinite());
221
222 Assertions.assertFalse(Interval.of(Double.NEGATIVE_INFINITY, 2, TEST_PRECISION).isFinite());
223 Assertions.assertFalse(Interval.of(2, Double.POSITIVE_INFINITY, TEST_PRECISION).isFinite());
224 Assertions.assertFalse(Interval.of(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, TEST_PRECISION).isFinite());
225 }
226
227 @Test
228 void testClassify_finite() {
229
230 final Precision.DoubleEquivalence precision = Precision.doubleEquivalenceOfEpsilon(1e-2);
231 final Interval interval = Interval.of(-1, 1, precision);
232
233
234 checkClassify(interval, RegionLocation.OUTSIDE,
235 Double.NEGATIVE_INFINITY, -2, -1.1,
236 1.1, 2, Double.POSITIVE_INFINITY);
237
238 checkClassify(interval, RegionLocation.BOUNDARY,
239 -1.001, -1, -0.999,
240 0.999, 1, 1.001);
241
242 checkClassify(interval, RegionLocation.INSIDE, -0.9, 0, 0.9);
243
244 checkClassify(interval, RegionLocation.OUTSIDE, Double.NaN);
245 }
246
247 @Test
248 void testClassify_singlePoint() {
249
250 final Precision.DoubleEquivalence precision = Precision.doubleEquivalenceOfEpsilon(1e-2);
251 final Interval interval = Interval.of(1, 1, precision);
252
253
254 checkClassify(interval, RegionLocation.OUTSIDE,
255 Double.NEGATIVE_INFINITY, 0, 0.9, 1.1, 2, Double.POSITIVE_INFINITY);
256
257 checkClassify(interval, RegionLocation.BOUNDARY,
258 0.999, 1, 1.0001);
259
260 checkClassify(interval, RegionLocation.OUTSIDE, Double.NaN);
261 }
262
263 @Test
264 void testClassify_maxInfinite() {
265
266 final Precision.DoubleEquivalence precision = Precision.doubleEquivalenceOfEpsilon(1e-2);
267 final Interval interval = Interval.of(-1, Double.POSITIVE_INFINITY, precision);
268
269
270 checkClassify(interval, RegionLocation.OUTSIDE,
271 Double.NEGATIVE_INFINITY, -2, -1.1);
272
273 checkClassify(interval, RegionLocation.BOUNDARY,
274 -1.001, -1, -0.999);
275
276 checkClassify(interval, RegionLocation.INSIDE,
277 -0.9, 0, 1.0, Double.POSITIVE_INFINITY);
278
279 checkClassify(interval, RegionLocation.OUTSIDE, Double.NaN);
280 }
281
282 @Test
283 void testClassify_minInfinite() {
284
285 final Precision.DoubleEquivalence precision = Precision.doubleEquivalenceOfEpsilon(1e-2);
286 final Interval interval = Interval.of(Double.NEGATIVE_INFINITY, 1, precision);
287
288
289 checkClassify(interval, RegionLocation.INSIDE,
290 Double.NEGATIVE_INFINITY, 0, 0.9);
291
292 checkClassify(interval, RegionLocation.BOUNDARY,
293 0.999, 1, 1.001);
294
295 checkClassify(interval, RegionLocation.OUTSIDE,
296 1.1, 2, Double.POSITIVE_INFINITY);
297
298 checkClassify(interval, RegionLocation.OUTSIDE, Double.NaN);
299 }
300
301 @Test
302 void testClassify_minMaxInfinite() {
303
304 final Precision.DoubleEquivalence precision = Precision.doubleEquivalenceOfEpsilon(1e-2);
305 final Interval interval = Interval.of(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, precision);
306
307
308 checkClassify(interval, RegionLocation.INSIDE,
309 Double.NEGATIVE_INFINITY, -1, 0, 1, Double.POSITIVE_INFINITY);
310
311 checkClassify(interval, RegionLocation.OUTSIDE, Double.NaN);
312 }
313
314 @Test
315 void testContains_finite() {
316
317 final Precision.DoubleEquivalence precision = Precision.doubleEquivalenceOfEpsilon(1e-2);
318 final Interval interval = Interval.of(-1, 1, precision);
319
320
321 checkContains(interval, true,
322 -1.001, -1, -0.999,
323 0.999, 1, 1.001,
324
325 -0.9, 0, 0.9);
326
327 checkContains(interval, false,
328 Double.NEGATIVE_INFINITY, -2, -1.1,
329 1.1, 2, Double.POSITIVE_INFINITY);
330
331 checkContains(interval, false, Double.NaN);
332 }
333
334 @Test
335 void testIsFull() {
336
337 Assertions.assertFalse(Interval.of(1, 1, TEST_PRECISION).isFull());
338 Assertions.assertFalse(Interval.of(-2, 2, TEST_PRECISION).isFull());
339
340 Assertions.assertFalse(Interval.of(1, Double.POSITIVE_INFINITY, TEST_PRECISION).isFull());
341 Assertions.assertFalse(Interval.of(Double.NEGATIVE_INFINITY, 1, TEST_PRECISION).isFull());
342
343 Assertions.assertTrue(Interval.of(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, TEST_PRECISION).isFull());
344 }
345
346 @Test
347 void testGetSize() {
348
349 Assertions.assertEquals(0, Interval.of(1, 1, TEST_PRECISION).getSize(), TEST_EPS);
350
351 Assertions.assertEquals(4, Interval.of(-2, 2, TEST_PRECISION).getSize(), TEST_EPS);
352 Assertions.assertEquals(5, Interval.of(2, -3, TEST_PRECISION).getSize(), TEST_EPS);
353
354 Assertions.assertEquals(Double.POSITIVE_INFINITY,
355 Interval.of(1, Double.POSITIVE_INFINITY, TEST_PRECISION).getSize(), TEST_EPS);
356 Assertions.assertEquals(Double.POSITIVE_INFINITY,
357 Interval.of(Double.NEGATIVE_INFINITY, 1, TEST_PRECISION).getSize(), TEST_EPS);
358
359 Assertions.assertEquals(Double.POSITIVE_INFINITY,
360 Interval.of(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, TEST_PRECISION).getSize(), TEST_EPS);
361 }
362
363 @Test
364 void testGetBoundarySize() {
365
366 Assertions.assertEquals(0, Interval.of(1, 1, TEST_PRECISION).getBoundarySize(), TEST_EPS);
367 Assertions.assertEquals(0, Interval.of(-2, 5, TEST_PRECISION).getBoundarySize(), TEST_EPS);
368 Assertions.assertEquals(0, Interval.full().getBoundarySize(), TEST_EPS);
369 }
370
371 @Test
372 void testGetCentroid() {
373
374 EuclideanTestUtils.assertCoordinatesEqual(Vector1D.ZERO,
375 Interval.of(-1, 1, TEST_PRECISION).getCentroid(), TEST_EPS);
376 EuclideanTestUtils.assertCoordinatesEqual(Vector1D.of(10),
377 Interval.of(10, 10, TEST_PRECISION).getCentroid(), TEST_EPS);
378
379 EuclideanTestUtils.assertCoordinatesEqual(Vector1D.of(2),
380 Interval.of(1, 3, TEST_PRECISION).getCentroid(), TEST_EPS);
381 EuclideanTestUtils.assertCoordinatesEqual(Vector1D.of(-1),
382 Interval.of(-2, 0, TEST_PRECISION).getCentroid(), TEST_EPS);
383
384 Assertions.assertNull(Interval.of(1, Double.POSITIVE_INFINITY, TEST_PRECISION).getCentroid());
385 Assertions.assertNull(Interval.of(Double.NEGATIVE_INFINITY, 1, TEST_PRECISION).getCentroid());
386 Assertions.assertNull(Interval.of(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, TEST_PRECISION).getCentroid());
387 }
388
389 @Test
390 void checkToTree_finite() {
391
392 final Precision.DoubleEquivalence precision = Precision.doubleEquivalenceOfEpsilon(1e-2);
393 final Interval interval = Interval.of(-1, 1, precision);
394
395
396 final RegionBSPTree1D tree = interval.toTree();
397
398
399 Assertions.assertEquals(5, tree.count());
400
401 checkClassify(tree, RegionLocation.OUTSIDE,
402 Double.NEGATIVE_INFINITY, -2, -1.1,
403 1.1, 2, Double.POSITIVE_INFINITY);
404
405 checkClassify(tree, RegionLocation.BOUNDARY,
406 -1.001, -1, -0.999,
407 0.999, 1, 1.001);
408
409 checkClassify(tree, RegionLocation.INSIDE, -0.9, 0, 0.9);
410
411 checkClassify(tree, RegionLocation.OUTSIDE, Double.NaN);
412 }
413
414 @Test
415 void checkToTree_singlePoint() {
416
417 final Precision.DoubleEquivalence precision = Precision.doubleEquivalenceOfEpsilon(1e-2);
418 final Interval interval = Interval.of(1, 1, precision);
419
420
421 final RegionBSPTree1D tree = interval.toTree();
422
423
424 Assertions.assertEquals(5, tree.count());
425
426 checkClassify(tree, RegionLocation.OUTSIDE,
427 Double.NEGATIVE_INFINITY, 0, 0.9, 1.1, 2, Double.POSITIVE_INFINITY);
428
429 checkClassify(tree, RegionLocation.BOUNDARY,
430 0.999, 1, 1.0001);
431
432 checkClassify(tree, RegionLocation.OUTSIDE, Double.NaN);
433 }
434
435 @Test
436 void checkToTree_maxInfinite() {
437
438 final Precision.DoubleEquivalence precision = Precision.doubleEquivalenceOfEpsilon(1e-2);
439 final Interval interval = Interval.of(-1, Double.POSITIVE_INFINITY, precision);
440
441
442 final RegionBSPTree1D tree = interval.toTree();
443
444
445 Assertions.assertEquals(3, tree.count());
446
447 checkClassify(tree, RegionLocation.OUTSIDE,
448 Double.NEGATIVE_INFINITY, -2, -1.1);
449
450 checkClassify(tree, RegionLocation.BOUNDARY,
451 -1.001, -1, -0.999);
452
453 checkClassify(tree, RegionLocation.INSIDE,
454 -0.9, 0, 1.0, Double.POSITIVE_INFINITY);
455
456 checkClassify(interval, RegionLocation.OUTSIDE, Double.NaN);
457 }
458
459 @Test
460 void checkToTree_minInfinite() {
461
462 final Precision.DoubleEquivalence precision = Precision.doubleEquivalenceOfEpsilon(1e-2);
463 final Interval interval = Interval.of(Double.NEGATIVE_INFINITY, 1, precision);
464
465
466 final RegionBSPTree1D tree = interval.toTree();
467
468
469 Assertions.assertEquals(3, tree.count());
470
471 checkClassify(tree, RegionLocation.INSIDE,
472 Double.NEGATIVE_INFINITY, 0, 0.9);
473
474 checkClassify(tree, RegionLocation.BOUNDARY,
475 0.999, 1, 1.001);
476
477 checkClassify(tree, RegionLocation.OUTSIDE,
478 1.1, 2, Double.POSITIVE_INFINITY);
479
480 checkClassify(tree, RegionLocation.OUTSIDE, Double.NaN);
481 }
482
483 @Test
484 void checkToTree_minMaxInfinite() {
485
486 final Precision.DoubleEquivalence precision = Precision.doubleEquivalenceOfEpsilon(1e-2);
487 final Interval interval = Interval.of(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, precision);
488
489
490 final RegionBSPTree1D tree = interval.toTree();
491
492
493 Assertions.assertEquals(1, tree.count());
494
495 checkClassify(tree, RegionLocation.INSIDE,
496 Double.NEGATIVE_INFINITY, -1, 0, 1, Double.POSITIVE_INFINITY);
497
498 checkClassify(tree, RegionLocation.OUTSIDE, Double.NaN);
499 }
500
501 @Test
502 void testProjectToBoundary_full() {
503
504 final Interval full = Interval.full();
505
506
507
508 Assertions.assertNull(full.project(Vector1D.of(Double.NEGATIVE_INFINITY)));
509 Assertions.assertNull(full.project(Vector1D.of(0)));
510 Assertions.assertNull(full.project(Vector1D.of(Double.POSITIVE_INFINITY)));
511 }
512
513 @Test
514 void testProjectToBoundary_singlePoint() {
515
516 final Interval interval = Interval.point(1, TEST_PRECISION);
517
518
519 checkBoundaryProjection(interval, -1, 1);
520 checkBoundaryProjection(interval, 0, 1);
521
522 checkBoundaryProjection(interval, 1, 1);
523
524 checkBoundaryProjection(interval, 2, 1);
525 checkBoundaryProjection(interval, 3, 1);
526
527 checkBoundaryProjection(interval, Double.NEGATIVE_INFINITY, 1);
528 checkBoundaryProjection(interval, Double.POSITIVE_INFINITY, 1);
529 }
530
531 @Test
532 void testProjectToBoundary_closedInterval() {
533
534 final Interval interval = Interval.of(1, 3, TEST_PRECISION);
535
536
537 checkBoundaryProjection(interval, -1, 1);
538 checkBoundaryProjection(interval, 0, 1);
539 checkBoundaryProjection(interval, 1, 1);
540
541 checkBoundaryProjection(interval, 1.9, 1);
542 checkBoundaryProjection(interval, 2, 1);
543 checkBoundaryProjection(interval, 2.1, 3);
544
545 checkBoundaryProjection(interval, 3, 3);
546 checkBoundaryProjection(interval, 4, 3);
547 checkBoundaryProjection(interval, 5, 3);
548
549 checkBoundaryProjection(interval, Double.NEGATIVE_INFINITY, 1);
550 checkBoundaryProjection(interval, Double.POSITIVE_INFINITY, 3);
551 }
552
553 @Test
554 void testProjectToBoundary_noMinBoundary() {
555
556 final Interval interval = Interval.of(Double.NEGATIVE_INFINITY, 1, TEST_PRECISION);
557
558
559 checkBoundaryProjection(interval, -1, 1);
560 checkBoundaryProjection(interval, 0, 1);
561 checkBoundaryProjection(interval, 1, 1);
562 checkBoundaryProjection(interval, 2, 1);
563 checkBoundaryProjection(interval, 3, 1);
564
565 checkBoundaryProjection(interval, Double.NEGATIVE_INFINITY, 1);
566 checkBoundaryProjection(interval, Double.POSITIVE_INFINITY, 1);
567 }
568
569 @Test
570 void testProjectToBoundary_noMaxBoundary() {
571
572 final Interval interval = Interval.of(1, Double.POSITIVE_INFINITY, TEST_PRECISION);
573
574
575 checkBoundaryProjection(interval, -1, 1);
576 checkBoundaryProjection(interval, 0, 1);
577 checkBoundaryProjection(interval, 1, 1);
578 checkBoundaryProjection(interval, 2, 1);
579 checkBoundaryProjection(interval, 3, 1);
580
581 checkBoundaryProjection(interval, Double.NEGATIVE_INFINITY, 1);
582 checkBoundaryProjection(interval, Double.POSITIVE_INFINITY, 1);
583 }
584
585 @Test
586 void testTransform() {
587
588 final AffineTransformMatrix1D transform = AffineTransformMatrix1D.createScale(2);
589
590
591 checkInterval(Interval.of(-1, 2, TEST_PRECISION).transform(transform), -2, 4);
592
593 checkInterval(Interval.of(Double.NEGATIVE_INFINITY, 2, TEST_PRECISION).transform(transform),
594 Double.NEGATIVE_INFINITY, 4);
595
596 checkInterval(Interval.of(-1, Double.POSITIVE_INFINITY, TEST_PRECISION).transform(transform), -2,
597 Double.POSITIVE_INFINITY);
598
599 checkInterval(Interval.of(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, TEST_PRECISION).transform(transform),
600 Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);
601 }
602
603 @Test
604 void testTransform_reflection() {
605
606 final AffineTransformMatrix1D transform = AffineTransformMatrix1D.createScale(-1);
607
608
609 checkInterval(Interval.of(-1, 2, TEST_PRECISION).transform(transform), -2, 1);
610
611 checkInterval(Interval.of(Double.NEGATIVE_INFINITY, 2, TEST_PRECISION).transform(transform),
612 -2, Double.POSITIVE_INFINITY);
613
614 checkInterval(Interval.of(-1, Double.POSITIVE_INFINITY, TEST_PRECISION).transform(transform),
615 Double.NEGATIVE_INFINITY, 1);
616 }
617
618 @Test
619 void testSplit_full_positiveFacingSplitter() {
620
621 final Interval interval = Interval.full();
622 final OrientedPoint splitter = OrientedPoints.fromPointAndDirection(
623 Vector1D.of(1), true, TEST_PRECISION);
624
625
626 final Split<Interval> split = interval.split(splitter);
627
628
629 Assertions.assertEquals(SplitLocation.BOTH, split.getLocation());
630
631 checkInterval(split.getMinus(), Double.NEGATIVE_INFINITY, 1);
632 checkInterval(split.getPlus(), 1, Double.POSITIVE_INFINITY);
633 }
634
635 @Test
636 void testSplit_full_negativeFacingSplitter() {
637
638 final Interval interval = Interval.full();
639 final OrientedPoint splitter = OrientedPoints.fromPointAndDirection(
640 Vector1D.of(1), true, TEST_PRECISION);
641
642
643 final Split<Interval> split = interval.split(splitter);
644
645
646 Assertions.assertEquals(SplitLocation.BOTH, split.getLocation());
647
648 checkInterval(split.getMinus(), Double.NEGATIVE_INFINITY, 1);
649 checkInterval(split.getPlus(), 1, Double.POSITIVE_INFINITY);
650 }
651
652 @Test
653 void testSplit_halfSpace_positiveFacingSplitter() {
654
655 final Interval interval = Interval.min(-1, TEST_PRECISION);
656 final OrientedPoint splitter = OrientedPoints.fromPointAndDirection(
657 Vector1D.of(1), false, TEST_PRECISION);
658
659
660 final Split<Interval> split = interval.split(splitter);
661
662
663 Assertions.assertEquals(SplitLocation.BOTH, split.getLocation());
664
665 checkInterval(split.getMinus(), 1, Double.POSITIVE_INFINITY);
666 checkInterval(split.getPlus(), -1, 1);
667 }
668
669
670 @Test
671 void testSplit_halfSpace_negativeFacingSplitter() {
672
673 final Interval interval = Interval.min(-1, TEST_PRECISION);
674 final OrientedPoint splitter = OrientedPoints.fromPointAndDirection(
675 Vector1D.of(1), false, TEST_PRECISION);
676
677
678 final Split<Interval> split = interval.split(splitter);
679
680
681 Assertions.assertEquals(SplitLocation.BOTH, split.getLocation());
682
683 checkInterval(split.getMinus(), 1, Double.POSITIVE_INFINITY);
684 checkInterval(split.getPlus(), -1, 1);
685 }
686
687 @Test
688 void testSplit_splitterBelowInterval() {
689
690 final Interval interval = Interval.of(5, 10, TEST_PRECISION);
691 final OrientedPoint splitter = OrientedPoints.fromPointAndDirection(
692 Vector1D.of(1), true, TEST_PRECISION);
693
694
695 final Split<Interval> split = interval.split(splitter);
696
697
698 Assertions.assertEquals(SplitLocation.PLUS, split.getLocation());
699
700 Assertions.assertSame(interval, split.getPlus());
701 }
702
703 @Test
704 void testSplit_splitterOnMinBoundary() {
705
706 final Interval interval = Interval.of(5, 10, TEST_PRECISION);
707 final OrientedPoint splitter = OrientedPoints.fromPointAndDirection(
708 Vector1D.of(5), false, TEST_PRECISION);
709
710
711 final Split<Interval> split = interval.split(splitter);
712
713
714 Assertions.assertEquals(SplitLocation.MINUS, split.getLocation());
715
716 Assertions.assertSame(interval, split.getMinus());
717 }
718
719 @Test
720 void testSplit_splitterAboveInterval() {
721
722 final Interval interval = Interval.of(5, 10, TEST_PRECISION);
723 final OrientedPoint splitter = OrientedPoints.fromPointAndDirection(
724 Vector1D.of(11), true, TEST_PRECISION);
725
726
727 final Split<Interval> split = interval.split(splitter);
728
729
730 Assertions.assertEquals(SplitLocation.MINUS, split.getLocation());
731
732 Assertions.assertSame(interval, split.getMinus());
733 }
734
735 @Test
736 void testSplit_splitterOnMaxBoundary() {
737
738 final Interval interval = Interval.of(5, 10, TEST_PRECISION);
739 final OrientedPoint splitter = OrientedPoints.fromPointAndDirection(
740 Vector1D.of(10), false, TEST_PRECISION);
741
742
743 final Split<Interval> split = interval.split(splitter);
744
745
746 Assertions.assertEquals(SplitLocation.PLUS, split.getLocation());
747
748 Assertions.assertSame(interval, split.getPlus());
749 }
750
751 @Test
752 void testSplit_point_minusOnly() {
753
754 final Interval interval = Interval.point(2, TEST_PRECISION);
755 final OrientedPoint splitter = OrientedPoints.fromPointAndDirection(
756 Vector1D.of(1), false, TEST_PRECISION);
757
758
759 final Split<Interval> split = interval.split(splitter);
760
761
762 Assertions.assertEquals(SplitLocation.MINUS, split.getLocation());
763
764 checkInterval(split.getMinus(), 2, 2);
765 Assertions.assertNull(split.getPlus());
766 }
767
768 @Test
769 void testSplit_point_plusOnly() {
770
771 final Interval interval = Interval.point(2, TEST_PRECISION);
772 final OrientedPoint splitter = OrientedPoints.fromPointAndDirection(
773 Vector1D.of(1), true, TEST_PRECISION);
774
775
776 final Split<Interval> split = interval.split(splitter);
777
778
779 Assertions.assertEquals(SplitLocation.PLUS, split.getLocation());
780
781 Assertions.assertNull(split.getMinus());
782 checkInterval(split.getPlus(), 2, 2);
783 }
784
785 @Test
786 void testSplit_point_onPoint() {
787
788 final Interval interval = Interval.point(1, TEST_PRECISION);
789 final OrientedPoint splitter = OrientedPoints.fromPointAndDirection(
790 Vector1D.of(1), true, TEST_PRECISION);
791
792
793 final Split<Interval> split = interval.split(splitter);
794
795
796 Assertions.assertEquals(SplitLocation.NEITHER, split.getLocation());
797
798 Assertions.assertNull(split.getMinus());
799 Assertions.assertNull(split.getPlus());
800 }
801
802 @Test
803 void testToString() {
804
805 final Interval interval = Interval.of(2, 1, TEST_PRECISION);
806
807
808 final String str = interval.toString();
809
810
811 Assertions.assertTrue(str.contains("Interval"));
812 Assertions.assertTrue(str.contains("min= 1.0"));
813 Assertions.assertTrue(str.contains("max= 2.0"));
814 }
815
816 @Test
817 void testFull() {
818
819 final Interval full = Interval.full();
820
821
822 Assertions.assertTrue(full.isFull());
823 Assertions.assertFalse(full.isEmpty());
824 Assertions.assertFalse(full.hasMinBoundary());
825 Assertions.assertFalse(full.hasMaxBoundary());
826 Assertions.assertTrue(full.isInfinite());
827
828 Assertions.assertEquals(RegionLocation.INSIDE, full.classify(Double.NEGATIVE_INFINITY));
829 Assertions.assertEquals(RegionLocation.INSIDE, full.classify(Double.POSITIVE_INFINITY));
830 }
831
832 private static void checkContains(final Interval interval, final boolean contains, final double... points) {
833 for (final double x : points) {
834 final String msg = "Unexpected contains status for point " + x;
835
836 Assertions.assertEquals(contains, interval.contains(x), msg);
837 Assertions.assertEquals(contains, interval.contains(Vector1D.of(x)), msg);
838 }
839 }
840
841 private static void checkClassify(final Interval interval, final RegionLocation loc, final double... points) {
842 for (final double x : points) {
843 final String msg = "Unexpected location for point " + x;
844
845 Assertions.assertEquals(loc, interval.classify(x), msg);
846 Assertions.assertEquals(loc, interval.classify(Vector1D.of(x)), msg);
847 }
848 }
849
850 private static void checkClassify(final RegionBSPTree1D tree, final RegionLocation loc, final double... points) {
851 for (final double x : points) {
852 final String msg = "Unexpected location for point " + x;
853
854 Assertions.assertEquals(loc, tree.classify(x), msg);
855 Assertions.assertEquals(loc, tree.classify(Vector1D.of(x)), msg);
856 }
857 }
858
859 private static void checkBoundaryProjection(final Interval interval, final double location, final double projectedLocation) {
860 final Vector1D pt = Vector1D.of(location);
861
862 final Vector1D proj = interval.project(pt);
863
864 Assertions.assertEquals(projectedLocation, proj.getX(), TEST_EPS);
865 }
866
867
868
869
870
871
872 private static void checkInterval(final Interval interval, final double min, final double max) {
873 checkInterval(interval, min, max, TEST_PRECISION);
874 }
875
876
877
878
879
880
881
882 private static void checkInterval(final Interval interval, final double min, final double max, final Precision.DoubleEquivalence precision) {
883 Assertions.assertEquals(min, interval.getMin(), TEST_EPS);
884 Assertions.assertEquals(max, interval.getMax(), TEST_EPS);
885
886 final boolean finiteMin = Double.isFinite(min);
887 final boolean finiteMax = Double.isFinite(max);
888
889 Assertions.assertEquals(finiteMin, interval.hasMinBoundary());
890 Assertions.assertEquals(finiteMax, interval.hasMaxBoundary());
891
892 if (finiteMin) {
893 Assertions.assertEquals(min, interval.getMinBoundary().getLocation(), TEST_EPS);
894 } else {
895 Assertions.assertNull(interval.getMinBoundary());
896 }
897
898 if (finiteMax) {
899 Assertions.assertEquals(max, interval.getMaxBoundary().getLocation(), TEST_EPS);
900 } else {
901 Assertions.assertNull(interval.getMaxBoundary());
902 }
903
904 Assertions.assertFalse(interval.isEmpty());
905 }
906 }