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