View Javadoc
1   package org.djutils.draw.point;
2   
3   import static org.junit.jupiter.api.Assertions.assertEquals;
4   import static org.junit.jupiter.api.Assertions.assertFalse;
5   import static org.junit.jupiter.api.Assertions.assertNotEquals;
6   import static org.junit.jupiter.api.Assertions.assertNotNull;
7   import static org.junit.jupiter.api.Assertions.assertNull;
8   import static org.junit.jupiter.api.Assertions.assertTrue;
9   import static org.junit.jupiter.api.Assertions.fail;
10  
11  import java.awt.geom.Point2D;
12  
13  import org.djutils.draw.bounds.Bounds3d;
14  import org.djutils.draw.line.LineSegment3d;
15  import org.djutils.draw.line.PolyLine3d;
16  import org.djutils.exceptions.Try;
17  import org.junit.jupiter.api.Test;
18  
19  /**
20   * Point3dTest.java.
21   * <p>
22   * Copyright (c) 2020-2025 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
23   * BSD-style license. See <a href="https://djutils.org/docs/current/djutils/licenses.html">DJUTILS License</a>.
24   * </p>
25   * @author <a href="https://www.tudelft.nl/averbraeck">Alexander Verbraeck</a>
26   * @author <a href="https://github.com/peter-knoppers">Peter Knoppers</a>
27   * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
28   */
29  public class Point3dTest
30  {
31      /**
32       * Test the Point3d construction methods.
33       */
34      @SuppressWarnings("unlikely-arg-type")
35      @Test
36      public void testPoint3dConstruction()
37      {
38          Point3d p = new Point3d(10.0, -20.0, 16.0);
39          assertNotNull(p);
40          assertEquals(10.0, p.x, 0, "Access x");
41          assertEquals(-20.0, p.y, 0, "Access y");
42          assertEquals(16.0, p.z, 0, "Access z");
43          assertEquals(3, p.getDimensions(), "Dimensions is 3");
44  
45          assertEquals(1, p.size(), "Size method returns 1");
46  
47          Point2d projection = p.project();
48          assertEquals(10.0, projection.x, 0);
49          assertEquals(-20.0, projection.y, 0);
50  
51          try
52          {
53              new Point3d(Double.NaN, 0, 0);
54              fail("NaN should have thrown an ArithmeticException");
55          }
56          catch (ArithmeticException e)
57          {
58              // Ignore expected exception
59          }
60  
61          try
62          {
63              new Point3d(0, Double.NaN, 0);
64              fail("NaN should have thrown an ArithmeticException");
65          }
66          catch (ArithmeticException e)
67          {
68              // Ignore expected exception
69          }
70  
71          try
72          {
73              new Point3d(0, 0, Double.NaN);
74              fail("NaN should have thrown an ArithmeticException");
75          }
76          catch (ArithmeticException e)
77          {
78              // Ignore expected exception
79          }
80  
81          double[] p3Arr = new double[] {5.0, 6.0, 7.0};
82          p = new Point3d(p3Arr);
83          assertEquals(5.0, p.x, 0);
84          assertEquals(6.0, p.y, 0);
85          assertEquals(7.0, p.z, 0);
86          Try.testFail(new Try.Execution()
87          {
88              @Override
89              public void execute() throws Throwable
90              {
91                  new Point3d(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 Point3d(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 Point3d(new double[] {1.0, 2.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 Point3d(new double[] {1.0, 2.0, 3.0, 4.0});
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 Point3d((Point2d) null, 0);
128             }
129         }, "Should throw NPE", NullPointerException.class);
130 
131         Try.testFail(new Try.Execution()
132         {
133             @Override
134             public void execute() throws Throwable
135             {
136                 new Point3d((Point2D.Double) null, 0);
137             }
138         }, "Should throw NPE", NullPointerException.class);
139 
140         Try.testFail(new Try.Execution()
141         {
142             @Override
143             public void execute() throws Throwable
144             {
145                 new Point3d(new Point2D.Double(Double.NaN, 2), 0);
146             }
147         }, "Should throw ArithmeticException", ArithmeticException.class);
148 
149         Try.testFail(new Try.Execution()
150         {
151             @Override
152             public void execute() throws Throwable
153             {
154                 new Point3d(new Point2D.Double(1, Double.NaN), 0);
155             }
156         }, "Should throw ArithmeticException", ArithmeticException.class);
157 
158         // equals and hashCode
159         assertTrue(p.equals(p));
160         assertEquals(p.hashCode(), p.hashCode());
161         Point2d p2d = new Point2d(1.0, 1.0);
162         assertFalse(p.equals(p2d));
163         assertFalse(p.equals(null));
164         assertNotEquals(p2d.hashCode(), p.hashCode());
165         assertEquals(p, p.translate(0.0, 0.0, 0.0), "Translating over 0,0,0 returns p");
166         assertNotEquals(p, p.translate(1.0, 0.0, 0.0));
167         assertNotEquals(p, p.translate(0.0, 1.0, 0.0));
168         assertNotEquals(p, p.translate(0.0, 0.0, 1.0));
169 
170         // toString
171         p = new Point3d(10.0, 20.0, 30.0);
172         assertEquals("Point3d [x=10.000000, y=20.000000, z=30.000000]", p.toString());
173         assertEquals("Point3d [x=10.0, y=20.0, z=30.0]", p.toString("%.1f"));
174         assertEquals("[x=10, y=20, z=30]", p.toString("%.0f", true));
175 
176         // epsilonEquals
177         assertTrue(p.epsilonEquals(p, 0.1));
178         assertTrue(p.epsilonEquals(p, 0.001));
179         assertTrue(p.epsilonEquals(p, 0.0));
180         Point3d p3 = p.translate(0.001, 0.0, 0.0);
181         assertTrue(p.epsilonEquals(p3, 0.09));
182         assertTrue(p3.epsilonEquals(p, 0.09));
183         assertFalse(p.epsilonEquals(p3, 0.0009));
184         assertFalse(p3.epsilonEquals(p, 0.0009));
185         p3 = p.translate(0.0, 0.001, 0.0);
186         assertTrue(p.epsilonEquals(p3, 0.09));
187         assertTrue(p3.epsilonEquals(p, 0.09));
188         assertFalse(p.epsilonEquals(p3, 0.0009));
189         assertFalse(p3.epsilonEquals(p, 0.0009));
190         p3 = p.translate(0.0, 0.0, 0.001);
191         assertTrue(p.epsilonEquals(p3, 0.09));
192         assertTrue(p3.epsilonEquals(p, 0.09));
193         assertFalse(p.epsilonEquals(p3, 0.0009));
194         assertFalse(p3.epsilonEquals(p, 0.0009));
195 
196         p2d = new Point2d(123, 456);
197         p3 = new Point3d(p2d, 789);
198         assertEquals(123, p3.x, 0, "x");
199         assertEquals(456, p3.y, 0, "y");
200         assertEquals(789, p3.z, 0, "z");
201 
202         Point2D p2D = new java.awt.geom.Point2D.Double(123, 456);
203         p3 = new Point3d(p2D, 789);
204         assertEquals(123, p3.x, 0, "x");
205         assertEquals(456, p3.y, 0, "y");
206         assertEquals(789, p3.z, 0, "z");
207     }
208 
209     /**
210      * Test the Point3d operators.
211      */
212     @Test
213     public void testPoint3dOperators()
214     {
215         Point3d p = new Point3d(-0.1, -0.2, -0.3);
216         assertEquals(0.1, p.abs().x, 1E-6);
217         assertEquals(0.2, p.abs().y, 1E-6);
218         assertEquals(0.3, p.abs().z, 1E-6);
219         p = p.neg();
220         assertEquals(0.1, p.x, 1E-6);
221         assertEquals(0.2, p.y, 1E-6);
222         assertEquals(0.3, p.z, 1E-6);
223         p = p.scale(1.0);
224         assertEquals(0.1, p.x, 1E-6);
225         assertEquals(0.2, p.y, 1E-6);
226         assertEquals(0.3, p.z, 1E-6);
227         p = p.scale(10.0);
228         assertEquals(1.0, p.x, 1E-6);
229         assertEquals(2.0, p.y, 1E-6);
230         assertEquals(3.0, p.z, 1E-6);
231         p = p.translate(5.0, -1.0, 0.5);
232         assertEquals(6.0, p.x, 1E-6);
233         assertEquals(1.0, p.y, 1E-6);
234         assertEquals(3.5, p.z, 1E-6);
235         Point3d p3d = p.translate(1.0, 1.0, 1.0);
236         assertEquals(7.0, p3d.x, 1E-6);
237         assertEquals(2.0, p3d.y, 1E-6);
238         assertEquals(4.5, p3d.z, 1E-6);
239         p3d = p.translate(6.0, 1.0);
240         assertEquals(12.0, p3d.x, 1E-6);
241         assertEquals(2.0, p3d.y, 1E-6);
242         assertEquals(3.5, p3d.z, 1E-6);
243 
244         try
245         {
246             p.translate(Double.NaN, 2.0);
247             fail("NaN translation should have thrown an ArithmeticException");
248         }
249         catch (ArithmeticException e)
250         {
251             // Ignore expected exception
252         }
253 
254         try
255         {
256             p.translate(1.0, Double.NaN);
257             fail("NaN translation should have thrown an ArithmeticException");
258         }
259         catch (ArithmeticException e)
260         {
261             // Ignore expected exception
262         }
263 
264         try
265         {
266             p.translate(Double.NaN, 2.0, 3.0);
267             fail("NaN translation should have thrown an ArithmeticException");
268         }
269         catch (ArithmeticException e)
270         {
271             // Ignore expected exception
272         }
273 
274         try
275         {
276             p.translate(1.0, Double.NaN, 3.0);
277             fail("NaN translation should have thrown an ArithmeticException");
278         }
279         catch (ArithmeticException e)
280         {
281             // Ignore expected exception
282         }
283 
284         try
285         {
286             p.translate(1.0, 2.0, Double.NaN);
287             fail("NaN translation should have thrown an ArithmeticException");
288         }
289         catch (ArithmeticException e)
290         {
291             // Ignore expected exception
292         }
293 
294         // interpolate
295         Point3d p1 = new Point3d(1.0, 1.0, 1.0);
296         Point3d p2 = new Point3d(5.0, 5.0, 5.0);
297         assertEquals(p1, p1.interpolate(p2, 0.0), "Interpolate at 0.0 returns this");
298         assertEquals(p2, p2.interpolate(p1, 0.0));
299         assertEquals(p1, p1.interpolate(p1, 0.0));
300         assertEquals(new Point3d(3.0, 3.0, 3.0), p1.interpolate(p2, 0.5));
301 
302         // distance
303         assertEquals(Math.sqrt(48.0), p1.distance(p2), 0.001);
304         assertEquals(48.0, p1.distanceSquared(p2), 0.001);
305         assertEquals(Math.sqrt(32.0), p1.horizontalDistance(p2), 0.001);
306         assertEquals(32.0, p1.horizontalDistanceSquared(p2), 0.001);
307 
308         // direction
309         assertEquals(Math.toRadians(45.0), p2.horizontalDirection(), 0.001);
310         assertEquals(Math.toRadians(45.0), p1.horizontalDirection(p2), 0.001);
311         assertEquals(0.0, new Point3d(0.0, 0.0, 0.0).horizontalDirection(), 0.001);
312         assertEquals(Math.atan2(Math.sqrt(2.0), 1), p1.verticalDirection(p2), 0.001);
313         assertEquals(Math.PI / 2, p1.verticalDirection(new Point3d(2.0, 2.0, 1.0)), 0.01);
314         assertEquals(0, p1.verticalDirection(new Point3d(1.0, 1.0, 2.0)), 0.01);
315 
316         // normalize
317         Point3d pn = p2.normalize();
318         assertEquals(1.0 / Math.sqrt(3.0), pn.x, 0.001);
319         assertEquals(1.0 / Math.sqrt(3.0), pn.y, 0.001);
320         assertEquals(1.0 / Math.sqrt(3.0), pn.z, 0.001);
321 
322         Try.testFail(new Try.Execution()
323         {
324             @Override
325             public void execute() throws Throwable
326             {
327                 new Point3d(0.0, 0.0, 0.0).normalize();
328             }
329         }, "Should throw DRtE", IllegalArgumentException.class);
330 
331         assertEquals(1, p1.size(), "size of a Point3d is 1");
332         Point2d projection = p1.project();
333         assertEquals(p1.x, projection.x, 0, "projected x");
334         assertEquals(p1.y, projection.y, 0, "projected y");
335 
336         Bounds3d bounds = p1.getAbsoluteBounds();
337         assertEquals(p1.x, bounds.getMinX(), 0, "Bounds min x");
338         assertEquals(p1.y, bounds.getMinY(), 0, "Bounds min y");
339         assertEquals(p1.z, bounds.getMinZ(), 0, "Bounds min z");
340         assertEquals(p1.x, bounds.getMaxX(), 0, "Bounds max x");
341         assertEquals(p1.y, bounds.getMaxY(), 0, "Bounds max y");
342         assertEquals(p1.z, bounds.getMaxZ(), 0, "Bounds max z");
343     }
344 
345     /**
346      * Test the Point3d operators for NPE.
347      */
348     @Test
349     public void testPoint3dOperatorsNPE()
350     {
351         final Point3d p1 = new Point3d(1.0, 1.0, 1.0);
352 
353         Try.testFail(new Try.Execution()
354         {
355             @Override
356             public void execute() throws Throwable
357             {
358                 p1.interpolate(null, 0.5);
359             }
360         }, "Should throw NPE", NullPointerException.class);
361 
362         Try.testFail(new Try.Execution()
363         {
364             @Override
365             public void execute() throws Throwable
366             {
367                 p1.distance(null);
368             }
369         }, "Should throw NPE", NullPointerException.class);
370 
371         Try.testFail(new Try.Execution()
372         {
373             @Override
374             public void execute() throws Throwable
375             {
376                 p1.distanceSquared(null);
377             }
378         }, "Should throw NPE", NullPointerException.class);
379 
380         // FIXME
381         // Try.testFail(new Try.Execution()
382         // {
383         // @Override
384         // public void execute() throws Throwable
385         // {
386         // p1.horizontalDistance((Point2d) null);
387         // }
388         // }, "Should throw NPE", NullPointerException.class);
389         //
390         // Try.testFail(new Try.Execution()
391         // {
392         // @Override
393         // public void execute() throws Throwable
394         // {
395         // p1.horizontalDistanceSquared((Point3d) null);
396         // }
397         // }, "Should throw NPE", NullPointerException.class);
398 
399     }
400 
401     /**
402      * Test the closestPointOnSegment and the closestPointOnLine methods.
403      */
404     @Test
405     public void testClosestPointOnSegmentAndLine()
406     {
407         Point3d p1 = new Point3d(-2, 3, 5);
408         for (Point3d p2 : new Point3d[] {new Point3d(7, 4, -5)/* angled */, new Point3d(-3, 6, 5) /* also angled */,
409                 new Point3d(-2, -5, 5) /* vertical */, new Point3d(8, 3, 5)/* horizontal */, new Point3d(-2, 3, 1)/* z */ })
410         {
411             PolyLine3d line = new PolyLine3d(p1, p2);
412             for (double x = -10; x <= 10; x += 0.5)
413             {
414                 for (double y = -10; y <= 10; y += 0.5)
415                 {
416                     for (double z = -10; z <= 10; z += 0.5)
417                     {
418                         Point3d p = new Point3d(x, y, z);
419                         // Figure out the correct result using a totally different method (binary search over the line segment)
420                         double fraction = 0.5;
421                         double step = 0.25;
422                         Point3d approximation = line.getLocationFraction(fraction);
423                         double distance = approximation.distance(p);
424                         // 10 iterations should get us to within one thousandth
425                         for (int iteration = 0; iteration < 10; iteration++)
426                         {
427                             // Try stepping up
428                             double upFraction = fraction + step;
429                             Point3d upApproximation = line.getLocationFraction(upFraction);
430                             double upDistance = upApproximation.distance(p);
431                             if (upDistance < distance)
432                             {
433                                 distance = upDistance;
434                                 fraction = upFraction;
435                                 approximation = upApproximation;
436                             }
437                             else
438                             {
439                                 // Try stepping down
440                                 double downFraction = fraction - step;
441                                 Point3d downApproximation = line.getLocationFraction(downFraction);
442                                 double downDistance = downApproximation.distance(p);
443                                 if (downDistance < distance)
444                                 {
445                                     distance = downDistance;
446                                     fraction = downFraction;
447                                     approximation = downApproximation;
448                                 }
449                             }
450                             step /= 2;
451                         }
452                         Point3d result = p.closestPointOnSegment(p1, p2);
453                         assertEquals(0, approximation.distance(result), line.getLength() / 1000,
454                                 "distance should be less than one thousandth of line length");
455                         assertEquals(p1, p.closestPointOnSegment(p1, p1),
456                                 "zero length line segment should always return start point");
457                         result = p.closestPointOnSegment(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z);
458                         assertEquals(0, approximation.distance(result), line.getLength() / 1000,
459                                 "distance should be less than one thousandth of line length");
460 
461                         if (fraction > 0.001 && fraction < 0.999)
462                         {
463                             result = p.closestPointOnLine(p1, p2);
464                             assertEquals(0, approximation.distance(result), line.getLength() / 1000,
465                                     "distance should be less than one thousandth of line length");
466                             result = p.closestPointOnLine(p1, p2);
467                             assertEquals(0, approximation.distance(result), line.getLength() / 1000,
468                                     "distance should be less than one thousandth of line length");
469                             result = p.closestPointOnLine(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z);
470                             assertEquals(0, approximation.distance(result), line.getLength() / 1000,
471                                     "distance should be less than one thousandth of line length");
472                         }
473                         else
474                         {
475                             // extrapolating
476                             double range = Math.max(Math.max(line.getLength(), p.distance(p1)), p.distance(p2));
477                             step = 5.0;
478                             fraction = 0.5;
479                             distance = range;
480                             // 10 iterations should get us to within one thousandth
481                             for (int iteration = 0; iteration < 20; iteration++)
482                             {
483                                 // Try stepping up
484                                 double upFraction = fraction + step;
485                                 Point3d upApproximation = line.getLocationFractionExtended(upFraction);
486                                 double upDistance = upApproximation.distance(p);
487                                 if (upDistance < distance)
488                                 {
489                                     distance = upDistance;
490                                     fraction = upFraction;
491                                     approximation = upApproximation;
492                                 }
493                                 else
494                                 {
495                                     // Try stepping down
496                                     double downFraction = fraction - step;
497                                     Point3d downApproximation = line.getLocationFractionExtended(downFraction);
498                                     double downDistance = downApproximation.distance(p);
499                                     if (downDistance < distance)
500                                     {
501                                         distance = downDistance;
502                                         fraction = downFraction;
503                                         approximation = downApproximation;
504                                     }
505                                 }
506                                 step /= 2;
507                             }
508                             result = p.closestPointOnLine(p1, p2);
509                             assertEquals(0, approximation.distance(result), range / 1000,
510                                     "distance should be less than one thousandth of range");
511                             result = p.closestPointOnLine(p1, p2);
512                             assertEquals(0, approximation.distance(result), range / 1000,
513                                     "distance should be less than one thousandth of range");
514                             result = p.closestPointOnLine(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z);
515                             assertEquals(0, approximation.distance(result), range / 1000,
516                                     "distance should be less than one thousandth of range");
517                             if (fraction < -0.001 || fraction > 1.001)
518                             {
519                                 assertNull(new LineSegment3d(p1, p2).projectOrthogonal(p),
520                                         "projectOrthogonal should return null");
521                                 assertEquals(result, new LineSegment3d(p1, p2).projectOrthogonalExtended(p),
522                                         "projectOrthogonalExtended should return same result as closestPointOnLine");
523                             }
524                         }
525                     }
526                 }
527             }
528         }
529 
530         try
531         {
532             p1.closestPointOnLine(null, new Point3d(5, 6, 7));
533             fail("null should have thrown a NullPointerException");
534         }
535         catch (NullPointerException e)
536         {
537             // Ignore expected exception
538         }
539 
540         try
541         {
542             p1.closestPointOnLine(new Point3d(5, 6, 7), null);
543             fail("null should have thrown a NullPointerException");
544         }
545         catch (NullPointerException e)
546         {
547             // Ignore expected exception
548         }
549 
550         try
551         {
552             p1.closestPointOnSegment(Double.NaN, 7, 8, 9, 10, 11);
553             fail("NaN value should have thrown an ArithmeticException");
554         }
555         catch (ArithmeticException e)
556         {
557             // Ignore expected exception
558         }
559 
560         try
561         {
562             p1.closestPointOnSegment(6, Double.NaN, 8, 9, 10, 11);
563             fail("NaN value should have thrown an ArithmeticException");
564         }
565         catch (ArithmeticException e)
566         {
567             // Ignore expected exception
568         }
569 
570         try
571         {
572             p1.closestPointOnSegment(6, 7, Double.NaN, 9, 10, 11);
573             fail("NaN value should have thrown an ArithmeticException");
574         }
575         catch (ArithmeticException e)
576         {
577             // Ignore expected exception
578         }
579 
580         try
581         {
582             p1.closestPointOnSegment(6, 7, 8, Double.NaN, 10, 11);
583             fail("NaN value should have thrown an ArithmeticException");
584         }
585         catch (ArithmeticException e)
586         {
587             // Ignore expected exception
588         }
589 
590         try
591         {
592             p1.closestPointOnSegment(6, 7, 8, 9, Double.NaN, 11);
593             fail("NaN value should have thrown an ArithmeticException");
594         }
595         catch (ArithmeticException e)
596         {
597             // Ignore expected exception
598         }
599 
600         try
601         {
602             p1.closestPointOnSegment(6, 7, 8, 9, 10, Double.NaN);
603             fail("NaN value should have thrown an ArithmeticException");
604         }
605         catch (ArithmeticException e)
606         {
607             // Ignore expected exception
608         }
609 
610         try
611         {
612             p1.closestPointOnLine(Double.NaN, 7, 8, 9, 10, 11);
613             fail("NaN value should have thrown an ArithmeticException");
614         }
615         catch (ArithmeticException e)
616         {
617             // Ignore expected exception
618         }
619 
620         try
621         {
622             p1.closestPointOnLine(6, Double.NaN, 8, 9, 10, 11);
623             fail("NaN value should have thrown an ArithmeticException");
624         }
625         catch (ArithmeticException dere)
626         {
627             // Ignore expected exception
628         }
629 
630         try
631         {
632             p1.closestPointOnLine(6, 7, Double.NaN, 9, 10, 11);
633             fail("NaN value should have thrown an ArithmeticException");
634         }
635         catch (ArithmeticException e)
636         {
637             // Ignore expected exception
638         }
639 
640         try
641         {
642             p1.closestPointOnLine(6, 7, 8, Double.NaN, 10, 11);
643             fail("NaN value should have thrown an ArithmeticException");
644         }
645         catch (ArithmeticException e)
646         {
647             // Ignore expected exception
648         }
649 
650         try
651         {
652             p1.closestPointOnLine(6, 7, 8, 9, Double.NaN, 11);
653             fail("NaN value should have thrown an ArithmeticException");
654         }
655         catch (ArithmeticException e)
656         {
657             // Ignore expected exception
658         }
659 
660         try
661         {
662             p1.closestPointOnLine(6, 7, 8, 9, 10, Double.NaN);
663             fail("NaN value should have thrown an ArithmeticException");
664         }
665         catch (ArithmeticException e)
666         {
667             // Ignore expected exception
668         }
669 
670         try
671         {
672             p1.closestPointOnLine(6, 7, 8, 6, 7, 8);
673             fail("identical points should have thrown a IllegalArgumentException");
674         }
675         catch (IllegalArgumentException dre)
676         {
677             // Ignore expected exception
678         }
679 
680     }
681 
682 }