1 package org.djutils.draw.point;
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.assertNotNull;
7 import static org.junit.Assert.assertNull;
8 import static org.junit.Assert.assertTrue;
9 import static org.junit.Assert.fail;
10
11 import java.awt.geom.Point2D;
12 import java.util.List;
13
14 import org.djutils.draw.DrawRuntimeException;
15 import org.djutils.draw.bounds.Bounds2d;
16 import org.djutils.draw.line.LineSegment2d;
17 import org.djutils.draw.line.PolyLine2d;
18 import org.djutils.exceptions.Try;
19 import org.junit.Test;
20
21
22
23
24
25
26
27
28
29
30 public class Point2dTest
31 {
32
33
34
35 @SuppressWarnings("unlikely-arg-type")
36 @Test
37 public void testPoint2dConstruction()
38 {
39 Point2d p = new Point2d(10.0, -20.0);
40 assertNotNull(p);
41 assertEquals("Access x", 10.0, p.x, 1E-6);
42 assertEquals("Access y", -20.0, p.y, 1E-6);
43 assertEquals("Dimensions is 2", 2, p.getDimensions());
44
45 assertEquals("Size method returns 1", 1, p.size());
46
47 try
48 {
49 new Point2d(Double.NaN, 0);
50 fail("NaN should have thrown an IllegalArgumentException");
51 }
52 catch (IllegalArgumentException iae)
53 {
54
55 }
56
57 try
58 {
59 new Point2d(0, Double.NaN);
60 fail("NaN should have thrown an IllegalArgumentException");
61 }
62 catch (IllegalArgumentException iae)
63 {
64
65 }
66
67 double[] p2Arr = new double[] { 5.0, 6.0 };
68 p = new Point2d(p2Arr);
69 assertEquals(5.0, p.x, 0);
70 assertEquals(6.0, p.y, 0);
71 Point2D.Double p2DD = new Point2D.Double(-0.1, -0.2);
72 p = new Point2d(p2DD);
73 assertEquals(-0.1, p.x, 1E-6);
74 assertEquals(-0.2, p.y, 1E-6);
75 assertEquals(p2DD, p.toPoint2D());
76
77 Try.testFail(new Try.Execution()
78 {
79 @Override
80 public void execute() throws Throwable
81 {
82 new Point2d((Point2D.Double) null);
83 }
84 }, "Should throw NPE", NullPointerException.class);
85
86 Try.testFail(new Try.Execution()
87 {
88 @Override
89 public void execute() throws Throwable
90 {
91 new Point2d(new double[] {});
92 }
93 }, "Should throw IAE", IllegalArgumentException.class);
94
95 Try.testFail(new Try.Execution()
96 {
97 @Override
98 public void execute() throws Throwable
99 {
100 new Point2d(new double[] { 1.0 });
101 }
102 }, "Should throw IAE", IllegalArgumentException.class);
103
104 Try.testFail(new Try.Execution()
105 {
106 @Override
107 public void execute() throws Throwable
108 {
109 new Point2d(new double[] { 1.0, 2.0, 3.0 });
110 }
111 }, "Should throw IAE", IllegalArgumentException.class);
112
113 Try.testFail(new Try.Execution()
114 {
115 @Override
116 public void execute() throws Throwable
117 {
118 new Point2d(new Point2D.Double(Double.NaN, 2));
119 }
120 }, "Should throw IAE", IllegalArgumentException.class);
121
122 Try.testFail(new Try.Execution()
123 {
124 @Override
125 public void execute() throws Throwable
126 {
127 new Point2d(new Point2D.Double(1, Double.NaN));
128 }
129 }, "Should throw IAE", IllegalArgumentException.class);
130
131
132 assertTrue(p.equals(p));
133 assertEquals(p.hashCode(), p.hashCode());
134 Point3d p3d = p.translate(1.0, 2.0, 3.0);
135 assertFalse(p.equals(p3d));
136 assertFalse(p.equals(null));
137 assertNotEquals(p3d.hashCode(), p.hashCode());
138 assertEquals(p, p.translate(0.0, 0.0));
139 assertNotEquals(p, p.translate(1.0, 0.0));
140 assertNotEquals(p, p.translate(0.0, 1.0));
141 assertEquals("x", p.x + 1, p3d.x, 0.00001);
142 assertEquals("y", p.y + 2, p3d.y, 0.00001);
143 assertEquals("z", 3, p3d.z, 0);
144
145
146 p = new Point2d(10.0, 20.0);
147 assertEquals("Point2d [x=10.000000, y=20.000000]", p.toString());
148 assertEquals("Point2d [x=10.0, y=20.0]", p.toString("%.1f"));
149 assertEquals("[x=10, y=20]", p.toString("%.0f", true));
150
151
152 assertTrue(p.epsilonEquals(p, 0.1));
153 assertTrue(p.epsilonEquals(p, 0.001));
154 assertTrue(p.epsilonEquals(p, 0.0));
155 Point2d p3 = p.translate(0.001, 0.0);
156 assertTrue(p.epsilonEquals(p3, 0.09));
157 assertTrue(p3.epsilonEquals(p, 0.09));
158 assertFalse(p.epsilonEquals(p3, 0.0009));
159 assertFalse(p3.epsilonEquals(p, 0.0009));
160 p3 = p.translate(0.0, 0.001);
161 assertTrue(p.epsilonEquals(p3, 0.09));
162 assertTrue(p3.epsilonEquals(p, 0.09));
163 assertFalse(p.epsilonEquals(p3, 0.0009));
164 assertFalse(p3.epsilonEquals(p, 0.0009));
165 }
166
167
168
169
170 @Test
171 public void testPoint2dOperators()
172 {
173 Point2d p = new Point2d(-0.1, -0.2);
174 assertEquals(0.1, p.abs().x, 1E-6);
175 assertEquals(0.2, p.abs().y, 1E-6);
176 p = p.neg();
177 assertEquals(0.1, p.x, 1E-6);
178 assertEquals(0.2, p.y, 1E-6);
179 p = p.scale(1.0);
180 assertEquals(0.1, p.x, 1E-6);
181 assertEquals(0.2, p.y, 1E-6);
182 p = p.scale(10.0);
183 assertEquals(1.0, p.x, 1E-6);
184 assertEquals(2.0, p.y, 1E-6);
185 p = p.translate(5.0, -1.0);
186 assertEquals(6.0, p.x, 1E-6);
187 assertEquals(1.0, p.y, 1E-6);
188 Point3d p3d = p.translate(1.0, 1.0, 1.0);
189 assertEquals(7.0, p3d.x, 1E-6);
190 assertEquals(2.0, p3d.y, 1E-6);
191 assertEquals(1.0, p3d.z, 1E-6);
192
193 try
194 {
195 p.translate(Double.NaN, 2.0);
196 fail("NaN translation should have thrown an IllegalArgumentException");
197 }
198 catch (IllegalArgumentException iae)
199 {
200
201 }
202
203 try
204 {
205 p.translate(1.0, Double.NaN);
206 fail("NaN translation should have thrown an IllegalArgumentException");
207 }
208 catch (IllegalArgumentException iae)
209 {
210
211 }
212
213
214 Point2d p1 = new Point2d(1.0, 1.0);
215 Point2d p2 = new Point2d(5.0, 5.0);
216 assertEquals(p1, p1.interpolate(p2, 0.0));
217 assertEquals(p2, p2.interpolate(p1, 0.0));
218 assertEquals(p1, p1.interpolate(p1, 0.0));
219 assertEquals(new Point2d(3.0, 3.0), p1.interpolate(p2, 0.5));
220
221
222 assertEquals(Math.sqrt(32.0), p1.distance(p2), 0.001);
223 assertEquals(32.0, p1.distanceSquared(p2), 0.001);
224
225
226
227
228
229
230
231
232
233
234 Point2d pn = p2.normalize();
235 assertEquals(1.0 / Math.sqrt(2.0), pn.x, 0.001);
236 assertEquals(1.0 / Math.sqrt(2.0), pn.y, 0.001);
237
238 Try.testFail(new Try.Execution()
239 {
240 @Override
241 public void execute() throws Throwable
242 {
243 new Point2d(0.0, 0.0).normalize();
244 }
245 }, "Should throw DRtE", DrawRuntimeException.class);
246
247 Bounds2d bounds = p1.getBounds();
248 assertEquals("Bounds min x", p1.x, bounds.getMinX(), 0);
249 assertEquals("Bounds min y", p1.y, bounds.getMinY(), 0);
250 assertEquals("Bounds max x", p1.x, bounds.getMaxX(), 0);
251 assertEquals("Bounds max y", p1.y, bounds.getMaxY(), 0);
252 }
253
254
255
256
257 @Test
258 public void testPoint2dOperatorsNPE()
259 {
260 final Point2d p1 = new Point2d(1.0, 1.0);
261
262 try
263 {
264 p1.translate(Double.NaN, 2.0);
265 fail("NaN translation should have thrown an IllegalArgumentException");
266 }
267 catch (IllegalArgumentException iae)
268 {
269
270 }
271
272 try
273 {
274 p1.translate(1.0, Double.NaN);
275 fail("NaN translation should have thrown an IllegalArgumentException");
276 }
277 catch (IllegalArgumentException iae)
278 {
279
280 }
281
282 try
283 {
284 p1.translate(Double.NaN, 2.0, 3.0);
285 fail("NaN translation should have thrown an IllegalArgumentException");
286 }
287 catch (IllegalArgumentException iae)
288 {
289
290 }
291
292 try
293 {
294 p1.translate(1.0, Double.NaN, 3.0);
295 fail("NaN translation should have thrown an IllegalArgumentException");
296 }
297 catch (IllegalArgumentException iae)
298 {
299
300 }
301
302 try
303 {
304 p1.translate(1.0, 2.0, Double.NaN);
305 fail("NaN translation should have thrown an IllegalArgumentException");
306 }
307 catch (IllegalArgumentException iae)
308 {
309
310 }
311
312 Try.testFail(new Try.Execution()
313 {
314 @Override
315 public void execute() throws Throwable
316 {
317 p1.interpolate(null, 0.5);
318 }
319 }, "Should throw NPE", NullPointerException.class);
320
321 Try.testFail(new Try.Execution()
322 {
323 @Override
324 public void execute() throws Throwable
325 {
326 p1.distance(null);
327 }
328 }, "Should throw NPE", NullPointerException.class);
329
330 Try.testFail(new Try.Execution()
331 {
332 @Override
333 public void execute() throws Throwable
334 {
335 p1.distanceSquared(null);
336 }
337 }, "Should throw NPE", NullPointerException.class);
338 }
339
340
341
342
343 @Test
344 public void testIntersectionOfLineSegments()
345 {
346 assertNull("horizontal line intersection with itself returns null",
347 Point2d.intersectionOfLineSegments(new Point2d(1, 2), new Point2d(4, 2), new Point2d(1, 2), new Point2d(4, 2)));
348 assertNull("vertical line intersection with itself returns null", Point2d.intersectionOfLineSegments(new Point2d(1, 2),
349 new Point2d(1, 10), new Point2d(1, 2), new Point2d(1, 10)));
350 assertEquals("Intersection is at (2,2)", new Point2d(2, 2), Point2d.intersectionOfLineSegments(new Point2d(1, 1),
351 new Point2d(6, 6), new Point2d(4, 2), new Point2d(-2, 2)));
352 assertEquals("Intersection is at (2,2)", new Point2d(2, 2),
353 Point2d.intersectionOfLineSegments(1, 1, 6, 6, 4, 2, -2, 2));
354
355 assertNull("line two passes before start of line one", Point2d.intersectionOfLineSegments(new Point2d(1, 1),
356 new Point2d(5, 5), new Point2d(0, -3), new Point2d(10, 0)));
357 assertNull("line two passes before after end of line one", Point2d.intersectionOfLineSegments(new Point2d(1, 1),
358 new Point2d(5, 5), new Point2d(0, 20), new Point2d(100, 30)));
359 assertNull("line one passes before start of line two", Point2d.intersectionOfLineSegments(new Point2d(1, 1),
360 new Point2d(5, 5), new Point2d(5, 3), new Point2d(10, 2)));
361 assertNull("line one passes after end of line two", Point2d.intersectionOfLineSegments(new Point2d(1, 1),
362 new Point2d(5, 5), new Point2d(-10, 3), new Point2d(0, 2)));
363 assertNull("line two passes before start of line one", Point2d.intersectionOfLineSegments(1, 1, 5, 5, 0, -3, 10, 0));
364 assertNull("line two passes before after end of line one",
365 Point2d.intersectionOfLineSegments(1, 1, 5, 5, 0, 20, 100, 30));
366 assertNull("line one passes before start of line two", Point2d.intersectionOfLineSegments(1, 1, 5, 5, 5, 3, 10, 2));
367 assertNull("line one passes after end of line two", Point2d.intersectionOfLineSegments(1, 1, 5, 5, -10, 3, 0, 2));
368
369 Point2d line1P1 = new Point2d(1, 2);
370 Point2d line1P2 = new Point2d(3, 2);
371 Point2d line2P1 = new Point2d(2, 0);
372 Point2d line2P2 = new Point2d(2, 4);
373 try
374 {
375 Point2d.intersectionOfLines(null, line1P2, line2P1, line2P2);
376 fail("Null parameter should have thrown a NullPointerException");
377 }
378 catch (NullPointerException npe)
379 {
380
381 }
382
383 try
384 {
385 Point2d.intersectionOfLines(line1P1, null, line2P1, line2P2);
386 fail("Null parameter should have thrown a NullPointerException");
387 }
388 catch (NullPointerException npe)
389 {
390
391 }
392
393 try
394 {
395 Point2d.intersectionOfLines(line1P1, line1P2, null, line2P2);
396 fail("Null parameter should have thrown a NullPointerException");
397 }
398 catch (NullPointerException npe)
399 {
400
401 }
402
403 try
404 {
405 Point2d.intersectionOfLines(line1P1, line1P2, line2P1, null);
406 fail("Null parameter should have thrown a NullPointerException");
407 }
408 catch (NullPointerException npe)
409 {
410
411 }
412
413 try
414 {
415 Point2d.intersectionOfLineSegments(null, line1P2, line2P1, line2P2);
416 fail("Null parameter should have thrown a NullPointerException");
417 }
418 catch (NullPointerException npe)
419 {
420
421 }
422
423 try
424 {
425 Point2d.intersectionOfLineSegments(line1P1, null, line2P1, line2P2);
426 fail("Null parameter should have thrown a NullPointerException");
427 }
428 catch (NullPointerException npe)
429 {
430
431 }
432
433 try
434 {
435 Point2d.intersectionOfLineSegments(line1P1, line1P2, null, line2P2);
436 fail("Null parameter should have thrown a NullPointerException");
437 }
438 catch (NullPointerException npe)
439 {
440
441 }
442
443 try
444 {
445 Point2d.intersectionOfLineSegments(line1P1, line1P2, line2P1, null);
446 fail("Null parameter should have thrown a NullPointerException");
447 }
448 catch (NullPointerException npe)
449 {
450
451 }
452
453 }
454
455
456
457
458 @Test
459 public void testIntersectionOfLines()
460 {
461 assertNull("horizontal line intersection with itself returns null",
462 Point2d.intersectionOfLines(new Point2d(1, 2), new Point2d(4, 2), new Point2d(1, 2), new Point2d(4, 2)));
463 assertNull("horizontal line intersection with itself returns null",
464 Point2d.intersectionOfLines(1, 2, 4, 2, 1, 2, 4, 2));
465 assertNull("vertical line intersection with itself returns null", Point2d.intersectionOfLineSegments(new Point2d(1, 2),
466 new Point2d(1, 10), new Point2d(1, 2), new Point2d(1, 10)));
467 assertNull("vertical line intersection with itself returns null",
468 Point2d.intersectionOfLineSegments(1, 2, 1, 10, 1, 2, 1, 10));
469 assertEquals("Intersection is at (2,2)", new Point2d(2, 2),
470 Point2d.intersectionOfLines(new Point2d(1, 1), new Point2d(6, 6), new Point2d(4, 2), new Point2d(-2, 2)));
471
472 assertEquals("line two passes before start of line one", new Point2d(-1.5, -1.5),
473 Point2d.intersectionOfLines(new Point2d(1, 1), new Point2d(5, 5), new Point2d(0, -3), new Point2d(10, -13)));
474 assertEquals("line two passes before after end of line one", new Point2d(20, 20),
475 Point2d.intersectionOfLines(new Point2d(1, 1), new Point2d(5, 5), new Point2d(0, 20), new Point2d(100, 20)));
476 assertEquals("line one passes before start of line two", new Point2d(4, 4),
477 Point2d.intersectionOfLines(new Point2d(1, 1), new Point2d(5, 5), new Point2d(7, 1), new Point2d(10, -2)));
478 assertEquals("line one passes after end of line two", new Point2d(-3.5, -3.5),
479 Point2d.intersectionOfLines(new Point2d(1, 1), new Point2d(5, 5), new Point2d(-10, 3), new Point2d(0, -7)));
480
481 assertEquals("begin of first is on second", new Point2d(1, 1),
482 Point2d.intersectionOfLines(new Point2d(1, 1), new Point2d(2, 1), new Point2d(1, 0), new Point2d(1, 3)));
483 assertEquals("end of first is on second", new Point2d(1, 1),
484 Point2d.intersectionOfLines(new Point2d(-1, 1), new Point2d(1, 1), new Point2d(1, 0), new Point2d(1, 3)));
485 assertEquals("begin of second is on first", new Point2d(1, 1),
486 Point2d.intersectionOfLines(new Point2d(-1, 1), new Point2d(2, 1), new Point2d(1, 1), new Point2d(1, 3)));
487 assertEquals("end of second is on first", new Point2d(1, 1),
488 Point2d.intersectionOfLines(new Point2d(-1, 1), new Point2d(2, 1), new Point2d(1, -1), new Point2d(1, 1)));
489
490 assertTrue("begin of first is just over second", new Point2d(1, 1).epsilonEquals(
491 Point2d.intersectionOfLines(new Point2d(1.001, 1), new Point2d(2, 1), new Point2d(1, 0), new Point2d(1, 3)),
492 0.0001));
493 assertTrue("end of first is just over second", new Point2d(1, 1).epsilonEquals(
494 Point2d.intersectionOfLines(new Point2d(-1, 1), new Point2d(0.999, 1), new Point2d(1, 0), new Point2d(1, 3)),
495 0.0001));
496 assertTrue("begin of second is just over first", new Point2d(1, 1).epsilonEquals(
497 Point2d.intersectionOfLines(new Point2d(-1, 1), new Point2d(2, 1), new Point2d(1, 1.001), new Point2d(1, 3)),
498 0.0001));
499 assertTrue("end of second is just over first", new Point2d(1, 1).epsilonEquals(
500 Point2d.intersectionOfLines(new Point2d(-1, 1), new Point2d(2, 1), new Point2d(1, -1), new Point2d(1, 0.999)),
501 0.0001));
502
503 assertNull("begin of first is just not on second", Point2d.intersectionOfLineSegments(new Point2d(1.001, 1),
504 new Point2d(2, 1), new Point2d(1, 0), new Point2d(1, 3)));
505 assertNull("end of first is just not on second", Point2d.intersectionOfLineSegments(new Point2d(-1, 1),
506 new Point2d(0.999, 1), new Point2d(1, 0), new Point2d(1, 3)));
507 assertNull("begin of second is just not on first", Point2d.intersectionOfLineSegments(new Point2d(-1, 1),
508 new Point2d(2, 1), new Point2d(1, 1.001), new Point2d(1, 3)));
509 assertNull("end of second is just not on first", Point2d.intersectionOfLineSegments(new Point2d(-1, 1),
510 new Point2d(2, 1), new Point2d(1, -1), new Point2d(1, 0.999)));
511 }
512
513
514
515
516
517 @Test
518 public void testClosestPointOnSegmentAndLine() throws DrawRuntimeException
519 {
520 Point2d p1 = new Point2d(-2, 3);
521 for (Point2d p2 : new Point2d[] { new Point2d(7, 4), new Point2d(-3, 6) ,
522 new Point2d(-2, -5) , new Point2d(8, 3) })
523 {
524 PolyLine2d line = new PolyLine2d(p1, p2);
525 for (double x = -10; x <= 10; x += 0.5)
526 {
527 for (double y = -10; y <= 10; y += 0.5)
528 {
529 Point2d p = new Point2d(x, y);
530
531 double fraction = 0.5;
532 double step = 0.25;
533 Point2d approximation = line.getLocationFraction(fraction);
534 double distance = approximation.distance(p);
535
536 for (int iteration = 0; iteration < 10; iteration++)
537 {
538
539 double upFraction = fraction + step;
540 Point2d upApproximation = line.getLocationFraction(upFraction);
541 double upDistance = upApproximation.distance(p);
542 if (upDistance < distance)
543 {
544 distance = upDistance;
545 fraction = upFraction;
546 approximation = upApproximation;
547 }
548 else
549 {
550
551 double downFraction = fraction - step;
552 Point2d downApproximation = line.getLocationFraction(downFraction);
553 double downDistance = downApproximation.distance(p);
554 if (downDistance < distance)
555 {
556 distance = downDistance;
557 fraction = downFraction;
558 approximation = downApproximation;
559 }
560 }
561 step /= 2;
562 }
563 Point2d result = p.closestPointOnSegment(p1, p2);
564 assertEquals("distance should be less than one thousandth of line length", 0,
565 approximation.distance(result), line.getLength() / 1000);
566 assertEquals("zero length line segment should always return start point", p1,
567 p.closestPointOnSegment(p1, p1));
568 result = p.closestPointOnSegment(p1.x, p1.y, p2.x, p2.y);
569 assertEquals("distance should be less than one thousandth of line length", 0,
570 approximation.distance(result), line.getLength() / 1000);
571
572 if (fraction > 0.001 && fraction < 0.999)
573 {
574 result = p.closestPointOnLine(p1, p2);
575 assertEquals("distance should be less than one thousandth of line length", 0,
576 approximation.distance(result), line.getLength() / 1000);
577 result = p.closestPointOnLine(p1, p2);
578 assertEquals("distance should be less than one thousandth of line length", 0,
579 approximation.distance(result), line.getLength() / 1000);
580 result = p.closestPointOnLine(p1.x, p1.y, p2.x, p2.y);
581 assertEquals("distance should be less than one thousandth of line length", 0,
582 approximation.distance(result), line.getLength() / 1000);
583 }
584 else
585 {
586
587 double range = Math.max(Math.max(line.getLength(), p.distance(p1)), p.distance(p2));
588 step = 5.0;
589 fraction = 0.5;
590 distance = range;
591
592 for (int iteration = 0; iteration < 20; iteration++)
593 {
594
595 double upFraction = fraction + step;
596 Point2d upApproximation = line.getLocationFractionExtended(upFraction);
597 double upDistance = upApproximation.distance(p);
598 if (upDistance < distance)
599 {
600 distance = upDistance;
601 fraction = upFraction;
602 approximation = upApproximation;
603 }
604 else
605 {
606
607 double downFraction = fraction - step;
608 Point2d downApproximation = line.getLocationFractionExtended(downFraction);
609 double downDistance = downApproximation.distance(p);
610 if (downDistance < distance)
611 {
612 distance = downDistance;
613 fraction = downFraction;
614 approximation = downApproximation;
615 }
616 }
617 step /= 2;
618 }
619 result = p.closestPointOnLine(p1, p2);
620 assertEquals("distance should be less than one thousandth of range", 0, approximation.distance(result),
621 range / 1000);
622 result = p.closestPointOnLine(p1, p2);
623 assertEquals("distance should be less than one thousandth of range", 0, approximation.distance(result),
624 range / 1000);
625 result = p.closestPointOnLine(p1.x, p1.y, p2.x, p2.y);
626 assertEquals("distance should be less than one thousandth of range", 0, approximation.distance(result),
627 range / 1000);
628 if (fraction < -0.001 || fraction > 1.001)
629 {
630 assertNull("projectOrthogonal should return null", new LineSegment2d(p1, p2).projectOrthogonal(p));
631 assertEquals("projectOrthogonalExtended should return same result as closestPointOnLine", result,
632 new LineSegment2d(p1, p2).projectOrthogonalExtended(p));
633 }
634 }
635 }
636 }
637 }
638
639 try
640 {
641 p1.closestPointOnLine(null, new Point2d(5, 6));
642 fail("null should have thrown a NullPointerException");
643 }
644 catch (NullPointerException npe)
645 {
646
647 }
648
649 try
650 {
651 p1.closestPointOnLine(new Point2d(5, 6), null);
652 fail("null should have thrown a NullPointerException");
653 }
654 catch (NullPointerException npe)
655 {
656
657 }
658
659 try
660 {
661 p1.closestPointOnSegment(Double.NaN, 7, 8, 9);
662 fail("NaN value should have thrown a DrawRuntimeException");
663 }
664 catch (DrawRuntimeException dre)
665 {
666
667 }
668
669 try
670 {
671 p1.closestPointOnSegment(6, Double.NaN, 8, 9);
672 fail("NaN value should have thrown a DrawRuntimeException");
673 }
674 catch (DrawRuntimeException dre)
675 {
676
677 }
678
679 try
680 {
681 p1.closestPointOnSegment(6, 7, Double.NaN, 9);
682 fail("NaN value should have thrown a DrawRuntimeException");
683 }
684 catch (DrawRuntimeException dre)
685 {
686
687 }
688
689 try
690 {
691 p1.closestPointOnSegment(6, 7, 8, Double.NaN);
692 fail("NaN value should have thrown a DrawRuntimeException");
693 }
694 catch (DrawRuntimeException dre)
695 {
696
697 }
698
699 try
700 {
701 p1.closestPointOnLine(Double.NaN, 7, 8, 9);
702 fail("NaN value should have thrown a DrawRuntimeException");
703 }
704 catch (DrawRuntimeException dre)
705 {
706
707 }
708
709 try
710 {
711 p1.closestPointOnLine(6, Double.NaN, 8, 9);
712 fail("NaN value should have thrown a DrawRuntimeException");
713 }
714 catch (DrawRuntimeException dre)
715 {
716
717 }
718
719 try
720 {
721 p1.closestPointOnLine(6, 7, Double.NaN, 9);
722 fail("NaN value should have thrown a DrawRuntimeException");
723 }
724 catch (DrawRuntimeException dre)
725 {
726
727 }
728
729 try
730 {
731 p1.closestPointOnLine(6, 7, 8, Double.NaN);
732 fail("NaN value should have thrown a DrawRuntimeException");
733 }
734 catch (DrawRuntimeException dre)
735 {
736
737 }
738
739 try
740 {
741 p1.closestPointOnLine(6, 7, 6, 7);
742 fail("identical points should have thrown a DrawRuntimeException");
743 }
744 catch (DrawRuntimeException dre)
745 {
746
747 }
748
749 }
750
751
752
753
754 @Test
755 public void circleIntersectionTest()
756 {
757 for (int x1 = -5; x1 <= 5; x1++)
758 {
759 for (int y1 = -5; y1 <= 5; y1++)
760 {
761 Point2d p1 = new Point2d(x1, y1);
762 for (int r1 = 0; r1 < 5; r1++)
763 {
764 for (int x2 = -5; x2 <= 5; x2++)
765 {
766 for (int y2 = -5; y2 <= 5; y2++)
767 {
768 Point2d p2 = new Point2d(x2, y2);
769 double distance = p1.distance(p2);
770 for (int r2 = 0; r2 < 5; r2++)
771 {
772 if (x1 == x2 && y1 == y2 && r1 == r2)
773 {
774 try
775 {
776 Point2d.circleIntersections(p1, r1, p2, r2);
777 fail("Identical circles should have thrown a DrawRuntimeException");
778 }
779 catch (DrawRuntimeException dre)
780 {
781
782 }
783 }
784 else
785 {
786 List<Point2d> result = Point2d.circleIntersections(p1, r1, p2, r2);
787
788
789
790
791
792
793
794 if (distance > r1 + r2 + 0.0001)
795 {
796 if (result.size() > 0)
797 {
798 Point2d.circleIntersections(p1, r1, p2, r2);
799 }
800 assertEquals("There are 0 intersections", 0, result.size());
801 }
802 if (distance < r1 + r2 - 0.0001 && distance > Math.abs(r2 - r1) + 0.0001)
803 {
804 if (result.size() != 2)
805 {
806 Point2d.circleIntersections(p1, r1, p2, r2);
807 }
808 assertEquals("There are 2 intersections", 2, result.size());
809 }
810 for (Point2d p : result)
811 {
812 if (Math.abs(r1 - p.distance(p1)) > 0.1 || Math.abs(r2 - p.distance(p2)) > 0.1)
813 {
814 Point2d.circleIntersections(p1, r1, p2, r2);
815 }
816 assertEquals("result is at r1 from p1", r1, p.distance(p1), 0.0001);
817 assertEquals("result is at r2 from p2", r2, p.distance(p2), 0.0001);
818 }
819 }
820 }
821 }
822 }
823 }
824 }
825 }
826 try
827 {
828 Point2d.circleIntersections(new Point2d(1, 2), -1, new Point2d(3, 4), 2);
829 fail("negative radius should have thrown a DrawRuntimeException");
830 }
831 catch (DrawRuntimeException dre)
832 {
833
834 }
835
836 try
837 {
838 Point2d.circleIntersections(new Point2d(1, 2), 5, new Point2d(3, 4), -2);
839 fail("negative radius should have thrown a DrawRuntimeException");
840 }
841 catch (DrawRuntimeException dre)
842 {
843
844 }
845
846 try
847 {
848 Point2d.circleIntersections(null, 5, new Point2d(3, 4), 2);
849 fail("null for center1 should have thrown a NullPointerException");
850 }
851 catch (NullPointerException npe)
852 {
853
854 }
855
856 try
857 {
858 Point2d.circleIntersections(new Point2d(3, 4), 5, null, 2);
859 fail("null for center1 should have thrown a NullPointerException");
860 }
861 catch (NullPointerException npe)
862 {
863
864 }
865 }
866
867
868
869
870 @Test
871 public void testDirection()
872 {
873 Point2d reference = new Point2d(5, 8);
874 assertEquals("East", 0, reference.directionTo(new Point2d(reference.x + 10, reference.y)), 0);
875 assertEquals("North", Math.PI / 2, reference.directionTo(new Point2d(reference.x, reference.y + 5)), 0.00001);
876 assertEquals("NorthEast", Math.PI / 4, reference.directionTo(new Point2d(reference.x + 2, reference.y + 2)), 0.00001);
877 assertEquals("West", Math.PI, reference.directionTo(new Point2d(reference.x - 1, reference.y)), 0);
878 assertEquals("South", -Math.PI / 2, reference.directionTo(new Point2d(reference.x, reference.y - 0.5)), 0.00001);
879 assertEquals("SouthWst", -3 * Math.PI / 4, reference.directionTo(new Point2d(reference.x - 0.2, reference.y - 0.2)),
880 0.00001);
881 }
882
883 }