1 package org.djutils.draw.bounds;
2
3 import static org.junit.Assert.assertEquals;
4 import static org.junit.Assert.assertFalse;
5 import static org.junit.Assert.assertNotEquals;
6 import static org.junit.Assert.assertNull;
7 import static org.junit.Assert.assertTrue;
8 import static org.junit.Assert.fail;
9
10 import java.awt.geom.Rectangle2D;
11 import java.util.ArrayList;
12 import java.util.Collection;
13 import java.util.Iterator;
14
15 import org.djutils.draw.DrawRuntimeException;
16 import org.djutils.draw.Drawable2d;
17 import org.djutils.draw.line.LineSegment2d;
18 import org.djutils.draw.line.PolyLine2d;
19 import org.djutils.draw.point.Point2d;
20 import org.junit.Test;
21
22
23
24
25
26
27
28
29
30
31 public class Bounds2dTest
32 {
33
34
35
36
37
38
39 @Test
40 public void constructorTest() throws IllegalArgumentException, DrawRuntimeException
41 {
42 try
43 {
44 new Bounds2d(Double.NaN, 0, 0, 0);
45 fail("Nan should have thrown an IllegalArgumentException");
46 }
47 catch (IllegalArgumentException iae)
48 {
49
50 }
51
52 try
53 {
54 new Bounds2d(0, Double.NaN, 0, 0);
55 fail("Nan should have thrown an IllegalArgumentException");
56 }
57 catch (IllegalArgumentException iae)
58 {
59
60 }
61
62 try
63 {
64 new Bounds2d(0, 0, Double.NaN, 0);
65 fail("Nan should have thrown an IllegalArgumentException");
66 }
67 catch (IllegalArgumentException iae)
68 {
69
70 }
71
72 try
73 {
74 new Bounds2d(0, 0, 0, Double.NaN);
75 fail("Nan should have thrown an IllegalArgumentException");
76 }
77 catch (IllegalArgumentException iae)
78 {
79
80 }
81
82 try
83 {
84 new Bounds2d(2, -2, 0, 0);
85 fail("Negative x-range should have thrown an IllegalArgumentException");
86 }
87 catch (IllegalArgumentException iae)
88 {
89
90 }
91
92 try
93 {
94 new Bounds2d(0, 0, 2, -2);
95 fail("Negative y-range should have thrown an IllegalArgumentException");
96 }
97 catch (IllegalArgumentException iae)
98 {
99
100 }
101
102 try
103 {
104 new Bounds2d(new Drawable2d[] {});
105 fail("Empty array should have thrown an IllegalArgumentException");
106 }
107 catch (IllegalArgumentException iae)
108 {
109
110 }
111
112 Bounds2d br = new Bounds2d(1, 2, 3, 6);
113 assertEquals("minX", 1, br.getMinX(), 0);
114 assertEquals("maxX", 2, br.getMaxX(), 0);
115 assertEquals("minY", 3, br.getMinY(), 0);
116 assertEquals("maxY", 6, br.getMaxY(), 0);
117
118 try
119 {
120 new Bounds2d(Double.NaN, 0);
121 fail("Nan should have thrown an IllegalArgumentException");
122 }
123 catch (IllegalArgumentException iae)
124 {
125
126 }
127
128 try
129 {
130 new Bounds2d(0, Double.NaN);
131 fail("Nan should have thrown an IllegalArgumentException");
132 }
133 catch (IllegalArgumentException iae)
134 {
135
136 }
137
138 try
139 {
140 new Bounds2d(-3, 0);
141 fail("Negative x-range should have thrown an IllegalArgumentException");
142 }
143 catch (IllegalArgumentException iae)
144 {
145
146 }
147
148 try
149 {
150 new Bounds2d(0, -3);
151 fail("Negative y-range should have thrown an IllegalArgumentException");
152 }
153 catch (IllegalArgumentException iae)
154 {
155
156 }
157
158 br = new Bounds2d(20, 30);
159 assertEquals("deltaX", 20, br.getDeltaX(), 0);
160 assertEquals("deltaY", 30, br.getDeltaY(), 0);
161 assertEquals("volume", 20 * 30, br.getArea(), 0);
162 assertFalse("contains does not include boundaries", br.contains(-10, 0));
163 assertFalse("contains does not include boundaries", br.contains(10, 0));
164 assertFalse("contains does not include boundaries", br.contains(0, -15));
165 assertFalse("contains does not include boundaries", br.contains(0, 15));
166 assertTrue("contains", br.contains(-0.999, 0));
167 assertTrue("contains", br.contains(0.999, 0));
168 assertTrue("contains", br.contains(0, -14.999));
169 assertTrue("contains", br.contains(0, 14.999));
170 assertTrue("covers includes boundaries", br.covers(-10, 0));
171 assertTrue("covers includes boundaries", br.covers(10, 0));
172 assertTrue("covers includes boundaries", br.covers(0, -15));
173 assertTrue("covers includes boundaries", br.covers(0, 15));
174 assertFalse("covers", br.covers(-10.001, 0));
175 assertFalse("covers", br.covers(10.001, 0));
176 assertFalse("covers", br.covers(0, -15.001));
177 assertFalse("covers", br.covers(0, 15.001));
178
179 Collection<Drawable2d> drawable2dCollection = new ArrayList<>();
180 try
181 {
182 new Bounds2d(drawable2dCollection);
183 fail("Empty drawable collection should have thrown an IllegalArgumentException");
184 }
185 catch (IllegalArgumentException iae)
186 {
187
188 }
189
190 drawable2dCollection.add(null);
191 try
192 {
193 new Bounds2d(drawable2dCollection);
194 fail("null element in collection should have thrown an NullPointerException");
195 }
196 catch (NullPointerException npe)
197 {
198
199 }
200 drawable2dCollection.clear();
201
202 drawable2dCollection.add(new Point2d(10, 20));
203 br = new Bounds2d(drawable2dCollection);
204 assertEquals("minX", 10, br.getMinX(), 0);
205 assertEquals("maxX", 10, br.getMaxX(), 0);
206 assertEquals("minY", 20, br.getMinY(), 0);
207 assertEquals("maxY", 20, br.getMaxY(), 0);
208
209 drawable2dCollection.add(new Point2d(-5, -6));
210 br = new Bounds2d(drawable2dCollection);
211 assertEquals("minX", -5, br.getMinX(), 0);
212 assertEquals("maxX", 10, br.getMaxX(), 0);
213 assertEquals("minY", -6, br.getMinY(), 0);
214 assertEquals("maxY", 20, br.getMaxY(), 0);
215
216 drawable2dCollection.add(new LineSegment2d(20, 30, 40, 50));
217 br = new Bounds2d(drawable2dCollection);
218 assertEquals("minX", -5, br.getMinX(), 0);
219 assertEquals("maxX", 40, br.getMaxX(), 0);
220 assertEquals("minY", -6, br.getMinY(), 0);
221 assertEquals("maxY", 50, br.getMaxY(), 0);
222
223 assertTrue("toString returns something descriptive", br.toString().startsWith("Bounds2d "));
224 assertEquals("toString with false argument produces same as toString with no argument", br.toString(),
225 br.toString(false));
226 assertTrue("toString with true argument produces rhs of toString with no argument",
227 br.toString().indexOf(br.toString(true)) > 0);
228
229 drawable2dCollection.add(new Point2d(40, 50));
230
231 br = new Bounds2d(drawable2dCollection);
232 assertEquals("minX", -5, br.getMinX(), 0);
233 assertEquals("maxX", 40, br.getMaxX(), 0);
234 assertEquals("minY", -6, br.getMinY(), 0);
235 assertEquals("maxY", 50, br.getMaxY(), 0);
236
237 br = new Bounds2d(drawable2dCollection.toArray((new Drawable2d[0])));
238 assertEquals("minX", -5, br.getMinX(), 0);
239 assertEquals("maxX", 40, br.getMaxX(), 0);
240 assertEquals("minY", -6, br.getMinY(), 0);
241 assertEquals("maxY", 50, br.getMaxY(), 0);
242
243 drawable2dCollection.add(null);
244 try
245 {
246 new Bounds2d(drawable2dCollection);
247 fail("null element in collection should have thrown an NullPointerException");
248 }
249 catch (NullPointerException npe)
250 {
251
252 }
253
254 PolyLine2d line = new PolyLine2d(new Point2d(1, 12), new Point2d(3, 12), new Point2d(2, 11));
255 br = new Bounds2d(line);
256 assertEquals("minX", 1, br.getMinX(), 0);
257 assertEquals("minY", 11, br.getMinY(), 0);
258 assertEquals("maxX", 3, br.getMaxX(), 0);
259 assertEquals("maxY", 12, br.getMaxY(), 0);
260
261 assertEquals("bounding box of reversed line", br, new Bounds2d(line.reverse()));
262
263 Point2d p2d = new Point2d(123, 456);
264 br = new Bounds2d(p2d);
265 assertEquals("minX", 123, br.getMinX(), 0);
266 assertEquals("maxX", 123, br.getMaxX(), 0);
267 assertEquals("minY", 456, br.getMinY(), 0);
268 assertEquals("maxY", 456, br.getMaxY(), 0);
269 assertFalse("contains does not include boundaries", br.contains(p2d));
270 assertTrue("covers includes boundaries", br.covers(p2d));
271
272 try
273 {
274 new Bounds2d((Point2d) null);
275 fail("Null parameter should have thrown a NullPointerException");
276 }
277 catch (NullPointerException npe)
278 {
279
280 }
281
282 assertEquals("Size of a Bounds2d is always 4", 4, br.size());
283
284 br = new Bounds2d(line, p2d);
285 assertEquals("minX", 1, br.getMinX(), 0);
286 assertEquals("minY", 11, br.getMinY(), 0);
287 assertEquals("maxX", 123, br.getMaxX(), 0);
288 assertEquals("maxY", 456, br.getMaxY(), 0);
289
290 br = new Bounds2d(p2d, line);
291 assertEquals("minX", 1, br.getMinX(), 0);
292 assertEquals("minY", 11, br.getMinY(), 0);
293 assertEquals("maxX", 123, br.getMaxX(), 0);
294 assertEquals("maxY", 456, br.getMaxY(), 0);
295
296 br = new Bounds2d(line, line);
297 assertEquals("minX", 1, br.getMinX(), 0);
298 assertEquals("minY", 11, br.getMinY(), 0);
299 assertEquals("maxX", 3, br.getMaxX(), 0);
300 assertEquals("maxY", 12, br.getMaxY(), 0);
301
302 try
303 {
304 new Bounds2d(line, p2d, null);
305 fail("Null parameter should have thrown a NullPointerException");
306 }
307 catch (NullPointerException npe)
308 {
309
310 }
311
312 try
313 {
314 new Bounds2d(new Iterator<Point2d>()
315 {
316
317 @Override
318 public boolean hasNext()
319 {
320 return false;
321 }
322
323 @Override
324 public Point2d next()
325 {
326 return null;
327 }
328 });
329 fail("iterator that yields zero points should have thrown an IllegalArgumentException");
330 }
331 catch (IllegalArgumentException iae)
332 {
333
334 }
335
336 }
337
338
339
340
341
342
343
344 @Test
345 @SuppressWarnings("unlikely-arg-type")
346 public void methodTest() throws NullPointerException, IllegalArgumentException, DrawRuntimeException
347 {
348 PolyLine2d l2d = new PolyLine2d(new Point2d(10, 10), new Point2d(30, -20), new Point2d(-40, 100));
349 Bounds2d br = new Bounds2d(l2d);
350 assertEquals("minX", -40, br.getMinX(), 0);
351 assertEquals("maxX", 30, br.getMaxX(), 0);
352 assertEquals("minY", -20, br.getMinY(), 0);
353 assertEquals("maxY", 100, br.getMaxY(), 0);
354
355 Point2d midPoint = br.midPoint();
356 assertEquals("midPoint x", (br.getMinX() + br.getMaxX()) / 2, midPoint.x, 0);
357 assertEquals("midPoint y", (br.getMinY() + br.getMaxY()) / 2, midPoint.y, 0);
358 assertEquals("midPoint of bounds of point is point", midPoint, new Bounds2d(midPoint).midPoint());
359
360 try
361 {
362 br.contains(Double.NaN, 0);
363 fail("NaN should have thrown an IllegalArgumentException");
364 }
365 catch (IllegalArgumentException iae)
366 {
367
368 }
369
370 try
371 {
372 br.contains(0, Double.NaN);
373 fail("NaN should have thrown an IllegalArgumentException");
374 }
375 catch (IllegalArgumentException iae)
376 {
377
378 }
379
380 assertFalse("boundingbox does not contain itself", br.contains(br));
381 Bounds2d br2 = new Bounds2d(br.getMinX() - 0.0001, br.getMaxX() + 0.0001, br.getMinY() - 0.0001, br.getMaxY() + 0.0001);
382 assertTrue("Slightly enlarged bounding box contains non-enlarged version", br2.contains(br));
383
384 try
385 {
386 br.covers((Bounds2d) null);
387 fail("Should have thrown a NullPointerException");
388 }
389 catch (NullPointerException npe)
390 {
391
392 }
393
394 try
395 {
396 br.covers(Double.NaN, 0);
397 fail("Should have thrown an IllegalArgumentException");
398 }
399 catch (IllegalArgumentException iae)
400 {
401
402 }
403
404 try
405 {
406 br.covers(0, Double.NaN);
407 fail("Should have thrown an IllegalArgumentException");
408 }
409 catch (IllegalArgumentException iae)
410 {
411
412 }
413
414 assertTrue("Bounds2d covers itself", br.covers(br));
415 assertFalse("Bounds2d does not cover slightly enlarged version of itself", br.covers(br2));
416 br2 = new Bounds2d(br.getMinX() + 0.0001, br.getMaxX() + 0.0001, br.getMinY() + 0.0001, br.getMaxY() + 0.0001);
417 assertFalse("Bounds2d does not cover slightly moved version of itself", br.covers(br2));
418
419 assertFalse("Overlapping Bounds2d is not disjoint", br.disjoint(br2));
420 assertTrue("Overlapping Bounds2d is not disjoint", br.intersects(br2));
421
422 br2 = new Bounds2d(br.getMinX() + 1000, br.getMaxX() + 1000, br.getMinY() + 1000, br.getMaxY() + 1000);
423 assertFalse("No intersection", br.intersects(br2));
424 assertTrue("Disjoint", br.disjoint(br2));
425 br2 = new Bounds2d(br.getMaxX(), br.getMaxX() + 0.0001, br.getMinY() + 0.0001, br.getMaxY() + 0.0001);
426 assertTrue("Only touching at vertical line is disjoint", br.disjoint(br2));
427 assertTrue("Only touching at vertical line is disjoint", br2.disjoint(br));
428
429 try
430 {
431 br.intersection(null);
432 fail("Should have thrown a NullPointerException");
433 }
434 catch (NullPointerException npe)
435 {
436
437 }
438
439 double[] shifts = new double[] { -200, -5, 0, 5, 200 };
440 for (double dx : shifts)
441 {
442 for (double dy : shifts)
443 {
444 br2 = new Bounds2d(br.getMinX() + dx, br.getMaxX() + dx, br.getMinY() + dy, br.getMaxY() + dy);
445 Bounds2d intersection = br.intersection(br2);
446 if (Math.abs(dx) >= 200 || Math.abs(dy) >= 200)
447 {
448 assertNull("intersection is null", intersection);
449 }
450 else
451 {
452 assertEquals("min x", Math.max(br.getMinX(), br2.getMinX()), intersection.getMinX(), 0);
453 assertEquals("max x", Math.min(br.getMaxX(), br2.getMaxX()), intersection.getMaxX(), 0);
454 assertEquals("min y", Math.max(br.getMinY(), br2.getMinY()), intersection.getMinY(), 0);
455 assertEquals("max y", Math.min(br.getMaxY(), br2.getMaxY()), intersection.getMaxY(), 0);
456 }
457 }
458 }
459 Rectangle2D r2D = br.toRectangle2D();
460 assertEquals("x", r2D.getX(), br.getMinX(), 0);
461 assertEquals("y", r2D.getY(), br.getMinY(), 0);
462 assertEquals("w", r2D.getWidth(), br.getDeltaX(), 0.000001);
463 assertEquals("h", r2D.getHeight(), br.getDeltaY(), 0.000001);
464 assertEquals("getBounds returns this", br, br.getBounds());
465 assertNotEquals("HashCode uses minX", br.hashCode(),
466 new Bounds2d(br.getMinX() + 1, br.getMaxX(), br.getMinY(), br.getMaxY()));
467 assertNotEquals("HashCode uses maxX", br.hashCode(),
468 new Bounds2d(br.getMinX(), br.getMaxX() + 1, br.getMinY(), br.getMaxY()));
469 assertNotEquals("HashCode uses minY", br.hashCode(),
470 new Bounds2d(br.getMinX(), br.getMaxX(), br.getMinY() + 1, br.getMaxY()));
471 assertNotEquals("HashCode uses maxY", br.hashCode(),
472 new Bounds2d(br.getMinX(), br.getMaxX(), br.getMinY(), br.getMaxY() + 1));
473
474 assertFalse("equals checks for null", br.equals(null));
475 assertFalse("equals checks for different kind of object", br.equals("string"));
476 assertFalse("equals checks minX", br.equals(new Bounds2d(br.getMinX() + 1, br.getMaxX(), br.getMinY(), br.getMaxY())));
477 assertFalse("equals checks maxX", br.equals(new Bounds2d(br.getMinX(), br.getMaxX() + 1, br.getMinY(), br.getMaxY())));
478 assertFalse("equals checks minY", br.equals(new Bounds2d(br.getMinX(), br.getMaxX(), br.getMinY() + 1, br.getMaxY())));
479 assertFalse("equals checks maxy", br.equals(new Bounds2d(br.getMinX(), br.getMaxX(), br.getMinY(), br.getMaxY() + 1)));
480 assertTrue("equals to copy of itself", br.equals(new Bounds2d(br)));
481 }
482
483 }