View Javadoc
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.assertTrue;
7   import static org.junit.Assert.fail;
8   
9   import java.util.Iterator;
10  
11  import org.djutils.base.AngleUtil;
12  import org.djutils.draw.DrawRuntimeException;
13  import org.djutils.exceptions.Try;
14  import org.junit.Test;
15  
16  /**
17   * OrientedPoint3dTest.java.
18   * <p>
19   * Copyright (c) 2020-2022 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
20   * BSD-style license. See <a href="https://djutils.org/docs/current/djutils/licenses.html">DJUTILS License</a>.
21   * </p>
22   * @author <a href="https://www.tudelft.nl/averbraeck">Alexander Verbraeck</a>
23   * @author <a href="https://www.tudelft.nl/pknoppers">Peter Knoppers</a>
24   */
25  public class OrientedPoint3dTest
26  {
27      /**
28       * Test the OrientedPoint3d construction methods.
29       */
30      @Test
31      public void testOrientedPoint3dConstruction()
32      {
33          OrientedPoint3d p = new OrientedPoint3d(10.0, -20.0, 5.2);
34          assertEquals("x", 10.0, p.x, 1E-6);
35          assertEquals("y", -20.0, p.y, 1E-6);
36          assertEquals("z", 5.2, p.z, 1E-6);
37          assertEquals("dirX", 0.0, p.getDirX(), 1E-6);
38          assertEquals("dirY", 0.0, p.getDirY(), 1E-6);
39          assertEquals("dirZ", 0.0, p.getDirZ(), 1E-6);
40          assertEquals("dirX", 0.0, p.dirZ, 1E-6);
41          assertEquals("dirY", 0.0, p.dirY, 1E-6);
42          assertEquals("dirZ", 0.0, p.dirZ, 1E-6);
43  
44          p = new OrientedPoint3d(new double[] { -18.7, 3.4, 5.6 });
45          assertEquals("x", -18.7, p.x, 1E-6);
46          assertEquals("y", 3.4, p.y, 1E-6);
47          assertEquals("z", 5.6, p.z, 1E-6);
48          assertEquals("dirX", 0.0, p.getDirX(), 1E-6);
49          assertEquals("dirY", 0.0, p.getDirY(), 1E-6);
50          assertEquals("dirZ", 0.0, p.getDirZ(), 1E-6);
51  
52          p = new OrientedPoint3d(10.0, -20.0, 5.2, 0.1, -0.2, Math.PI);
53          assertEquals("x", 10.0, p.x, 1E-6);
54          assertEquals("y", -20.0, p.y, 1E-6);
55          assertEquals("z", 5.2, p.z, 1E-6);
56          assertEquals("dirX", 0.1, p.getDirX(), 1E-6);
57          assertEquals("dirY", -0.2, p.getDirY(), 1E-6);
58          assertEquals("dirZ", 3.1415926, p.getDirZ(), 1E-6);
59  
60          p = new OrientedPoint3d(new double[] { -18.7, 3.4, 5.6 }, 0.1, -0.2, Math.PI);
61          assertEquals("x", -18.7, p.x, 1E-6);
62          assertEquals("y", 3.4, p.y, 1E-6);
63          assertEquals("z", 5.6, p.z, 1E-6);
64          assertEquals("dirX", 0.1, p.getDirX(), 1E-6);
65          assertEquals("dirY", -0.2, p.getDirY(), 1E-6);
66          assertEquals("dirZ", 3.1415926, p.getDirZ(), 1E-6);
67          assertEquals("dirX", 0.1, p.dirX, 1E-6);
68          assertEquals("dirY", -0.2, p.dirY, 1E-6);
69          assertEquals("dirZ", 3.1415926, p.dirZ, 1E-6);
70  
71          p = new OrientedPoint3d(new Point3d(new double[] { -18.7, 3.4, 5.6 }), 0.1, -0.2, Math.PI);
72          assertEquals("x", -18.7, p.x, 1E-6);
73          assertEquals("y", 3.4, p.y, 1E-6);
74          assertEquals("z", 5.6, p.z, 1E-6);
75          assertEquals("dirX", 0.1, p.getDirX(), 1E-6);
76          assertEquals("dirY", -0.2, p.getDirY(), 1E-6);
77          assertEquals("dirZ", 3.1415926, p.getDirZ(), 1E-6);
78  
79          try
80          {
81              new OrientedPoint3d(0, 0, 0, Double.NaN, 0, 0);
82              fail("NaN rotation should have thrown an IllegalArgumentException");
83          }
84          catch (IllegalArgumentException iae)
85          {
86              // Ignore expected exception
87          }
88  
89          try
90          {
91              new OrientedPoint3d(0, 0, 0, 0, Double.NaN, 0);
92              fail("NaN rotation should have thrown an IllegalArgumentException");
93          }
94          catch (IllegalArgumentException iae)
95          {
96              // Ignore expected exception
97          }
98  
99          try
100         {
101             new OrientedPoint3d(0, 0, 0, 0, 0, Double.NaN);
102             fail("NaN rotation should have thrown an IllegalArgumentException");
103         }
104         catch (IllegalArgumentException iae)
105         {
106             // Ignore expected exception
107         }
108 
109         try
110         {
111             new OrientedPoint3d(new double[3], Double.NaN, 0, 0);
112             fail("NaN rotation should have thrown an IllegalArgumentException");
113         }
114         catch (IllegalArgumentException iae)
115         {
116             // Ignore expected exception
117         }
118 
119         try
120         {
121             new OrientedPoint3d(new double[3], 0, Double.NaN, 0);
122             fail("NaN rotation should have thrown an IllegalArgumentException");
123         }
124         catch (IllegalArgumentException iae)
125         {
126             // Ignore expected exception
127         }
128 
129         try
130         {
131             new OrientedPoint3d(new double[3], 0, 0, Double.NaN);
132             fail("NaN rotation should have thrown an IllegalArgumentException");
133         }
134         catch (IllegalArgumentException iae)
135         {
136             // Ignore expected exception
137         }
138 
139         try
140         {
141             new OrientedPoint3d(new Point3d(1, 2, 3), Double.NaN, 0, 0);
142             fail("NaN rotation should have thrown an IllegalArgumentException");
143         }
144         catch (IllegalArgumentException iae)
145         {
146             // Ignore expected exception
147         }
148 
149         try
150         {
151             new OrientedPoint3d(new Point3d(1, 2, 3), 0, Double.NaN, 0);
152             fail("NaN rotation should have thrown an IllegalArgumentException");
153         }
154         catch (IllegalArgumentException iae)
155         {
156             // Ignore expected exception
157         }
158 
159         try
160         {
161             new OrientedPoint3d(new Point3d(1, 2, 3), 0, 0, Double.NaN);
162             fail("NaN rotation should have thrown an IllegalArgumentException");
163         }
164         catch (IllegalArgumentException iae)
165         {
166             // Ignore expected exception
167         }
168 
169         double[] p3Arr = new double[] { 5.0, 6.0, 7.0 };
170         double[] rotArr = new double[] { 0.1, -0.2, 0.3 };
171         p = new OrientedPoint3d(5.0, 6.0, 7.0, rotArr);
172         assertEquals("x", 5.0, p.x, 0);
173         assertEquals("y", 6.0, p.y, 0);
174         assertEquals("z", 7.0, p.z, 0);
175         assertEquals("dirX", 0.1, p.getDirX(), 1E-6);
176         assertEquals("dirY", -0.2, p.getDirY(), 1E-6);
177         assertEquals("dirZ", 0.3, p.getDirZ(), 1E-6);
178 
179         p = new OrientedPoint3d(p3Arr, rotArr);
180         assertEquals("x", 5.0, p.x, 0);
181         assertEquals("y", 6.0, p.y, 0);
182         assertEquals("z", 7.0, p.z, 0);
183         assertEquals("dirX", 0.1, p.getDirX(), 1E-6);
184         assertEquals("dirY", -0.2, p.getDirY(), 1E-6);
185         assertEquals("dirZ", 0.3, p.getDirZ(), 1E-6);
186 
187         Try.testFail(new Try.Execution()
188         {
189             @Override
190             public void execute() throws Throwable
191             {
192                 new OrientedPoint3d(0.1, 0.2, 0.3, new double[] {});
193             }
194         }, "Should throw IAE", IllegalArgumentException.class);
195 
196         Try.testFail(new Try.Execution()
197         {
198             @Override
199             public void execute() throws Throwable
200             {
201                 new OrientedPoint3d(0.1, 0.2, 0.3, new double[] { 0.1, 0.2 });
202             }
203         }, "Should throw IAE", IllegalArgumentException.class);
204 
205         Try.testFail(new Try.Execution()
206         {
207             @Override
208             public void execute() throws Throwable
209             {
210                 new OrientedPoint3d(0.1, 0.2, 0.3, new double[] { 0.1, 0.2, 0.3, 0.4 });
211             }
212         }, "Should throw IAE", IllegalArgumentException.class);
213 
214         Try.testFail(new Try.Execution()
215         {
216             @Override
217             public void execute() throws Throwable
218             {
219                 new OrientedPoint3d(new double[] {});
220             }
221         }, "Should throw IAE", IllegalArgumentException.class);
222 
223         Try.testFail(new Try.Execution()
224         {
225             @Override
226             public void execute() throws Throwable
227             {
228                 new OrientedPoint3d(new double[] { 0.1, 0.2 });
229             }
230         }, "Should throw IAE", IllegalArgumentException.class);
231 
232         Try.testFail(new Try.Execution()
233         {
234             @Override
235             public void execute() throws Throwable
236             {
237                 new OrientedPoint3d(new double[] { 0.1, 0.2, 0.3, 0.4 });
238             }
239         }, "Should throw IAE", IllegalArgumentException.class);
240 
241         Try.testFail(new Try.Execution()
242         {
243             @Override
244             public void execute() throws Throwable
245             {
246                 new OrientedPoint3d(new double[] { 1, 2, 3 }, new double[] { 0.1, 0.2 });
247             }
248         }, "Should throw IAE", IllegalArgumentException.class);
249 
250         Try.testFail(new Try.Execution()
251         {
252             @Override
253             public void execute() throws Throwable
254             {
255                 new OrientedPoint3d(new double[] { 1, 2, 3 }, new double[] { 0.1, 0.2, 0.3, 0.4 });
256             }
257         }, "Should throw IAE", IllegalArgumentException.class);
258 
259     }
260 
261     /**
262      * Test the OrientedPoint3d construction methods.
263      */
264     @SuppressWarnings("unlikely-arg-type")
265     @Test
266     public void testOrientedPointEquals()
267     {
268         // equals and hashCode
269         OrientedPoint3d p = new OrientedPoint3d(10.0, 20.0, 30.0, 0.1, 0.2, 0.3);
270         assertTrue(p.equals(p));
271         assertEquals(p.hashCode(), p.hashCode());
272         assertFalse(p.equals(new Point2d(10.0, 20.0)));
273         assertFalse(p.equals(null));
274         assertNotEquals(new Point2d(10.0, 20.0), p.hashCode());
275         assertEquals(0.3, p.getDirZ(), 1E-6);
276         assertTrue(p.equals(p.translate(0.0, 0.0, 0.0)));
277         assertFalse(p.equals(p.translate(1.0, 0.0, 0.0)));
278         assertFalse(p.equals(p.translate(0.0, 1.0, 0.0)));
279         assertFalse(p.equals(p.translate(0.0, 0.0, 1.0)));
280         assertFalse(p.equals(p.rotate(0.1)));
281         assertFalse(p.equals(p.rotate(0.1, 0.0, 0.0)));
282         assertFalse(p.equals(p.rotate(0.0, 0.1, 0.0)));
283         assertFalse(p.equals(p.rotate(0.0, 0.0, 0.1)));
284 
285         // toString
286         p = new OrientedPoint3d(10.0, 20.0, 30.0, 0.1, 0.2, 0.3);
287         assertEquals("OrientedPoint3d [x=10.000000, y=20.000000, z=30.000000, rotX=0.100000, rotY=0.200000, rotZ=0.300000]",
288                 p.toString());
289         assertEquals("OrientedPoint3d [x=10.0, y=20.0, z=30.0, rotX=0.1, rotY=0.2, rotZ=0.3]", p.toString("%.1f"));
290         assertEquals("[x=10, y=20, z=30, rotX=0, rotY=0, rotZ=0]", p.toString("%.0f", true));
291 
292         // epsilonEquals
293         assertTrue(p.epsilonEquals(p, 0.1, 999));
294         assertTrue(p.epsilonEquals(p, 0.001, 999));
295         assertTrue(p.epsilonEquals(p, 0.0, 999));
296         OrientedPoint3d p3 = p.translate(0.001, 0.0, 0.0);
297         assertTrue(p.epsilonEquals(p3, 0.09, 0.001));
298         assertTrue(p3.epsilonEquals(p, 0.09, 0.001));
299         assertFalse(p.epsilonEquals(p3, 0.0009, 0.001));
300         assertFalse(p3.epsilonEquals(p, 0.0009, 0.001));
301         p3 = p.translate(0.0, 0.001, 0.0);
302         assertTrue(p.epsilonEquals(p3, 0.09, 0.001));
303         assertTrue(p3.epsilonEquals(p, 0.09, 0.001));
304         assertFalse(p.epsilonEquals(p3, 0.0009, 0.001));
305         assertFalse(p3.epsilonEquals(p, 0.0009, 0.001));
306         p3 = p.translate(0.0, 0.0, 0.001);
307         assertTrue(p.epsilonEquals(p3, 0.09, 0.001));
308         assertTrue(p3.epsilonEquals(p, 0.09, 0.001));
309         assertFalse(p.epsilonEquals(p3, 0.0009, 0.001));
310         assertFalse(p3.epsilonEquals(p, 0.0009, 0.001));
311         p3 = p.rotate(0.001);
312         assertTrue(p.epsilonEquals(p3, 0.09, 0.009));
313         assertTrue(p3.epsilonEquals(p, 0.09, 0.009));
314         assertFalse(p.epsilonEquals(p3, 0.0009, 0.0009));
315         assertFalse(p3.epsilonEquals(p, 0.0009, 0.0009));
316         p3 = p.rotate(0.001, 0, 0);
317         assertTrue(p.epsilonEquals(p3, 0.09, 0.009));
318         assertTrue(p3.epsilonEquals(p, 0.09, 0.009));
319         assertFalse(p.epsilonEquals(p3, 0.0009, 0.0009));
320         assertFalse(p3.epsilonEquals(p, 0.0009, 0.0009));
321         p3 = p.rotate(0, 0.001, 0);
322         assertTrue(p.epsilonEquals(p3, 0.09, 0.009));
323         assertTrue(p3.epsilonEquals(p, 0.09, 0.009));
324         assertFalse(p.epsilonEquals(p3, 0.0009, 0.0009));
325         assertFalse(p3.epsilonEquals(p, 0.0009, 0.0009));
326         p3 = p.rotate(0, 0, 0.001);
327         assertTrue(p.epsilonEquals(p3, 0.09, 0.009));
328         assertTrue(p3.epsilonEquals(p, 0.09, 0.009));
329         assertFalse(p.epsilonEquals(p3, 0.0009, 0.0009));
330         assertFalse(p3.epsilonEquals(p, 0.0009, 0.0009));
331     }
332 
333     /**
334      * Test the OrientedPoint3d operators.
335      */
336     @Test
337     public void testOrientedPoint3dOperators()
338     {
339         OrientedPoint3d p = new OrientedPoint3d(-0.1, -0.2, -0.3, Math.PI / 4, -Math.PI / 4, Math.PI / 2);
340         assertEquals(0.1, p.abs().x, 1E-6);
341         assertEquals(0.2, p.abs().y, 1E-6);
342         assertEquals(0.3, p.abs().z, 1E-6);
343         assertEquals(Math.PI / 4, p.abs().getDirX(), 1E-6);
344         assertEquals(-Math.PI / 4, p.abs().getDirY(), 1E-6);
345         assertEquals(Math.PI / 2, p.abs().getDirZ(), 1E-6);
346 
347         Iterator<OrientedPoint3d> i = p.getPoints();
348         assertTrue("iterator has one point", i.hasNext());
349         assertEquals("iterator returns p", p, i.next());
350         assertFalse("iterator does not have another point", i.hasNext());
351 
352         OrientedPoint3d p2 = p.neg();
353         assertEquals("negated x", -p.x, p2.x, 1E-6);
354         assertEquals("negated y", -p.y, p2.y, 1E-6);
355         assertEquals("negated z", -p.z, p2.z, 1E-6);
356         assertEquals("negated dirX", AngleUtil.normalizeAroundZero(p.getDirX() + Math.PI), p2.getDirX(), 1E-6);
357         assertEquals("negated dirY", AngleUtil.normalizeAroundZero(p.getDirY() + Math.PI), p2.getDirY(), 1E-6);
358         assertEquals("negated dirZ", AngleUtil.normalizeAroundZero(p.getDirZ() + Math.PI), p2.getDirZ(), 1E-6);
359 
360         p2 = p.scale(1.0);
361         assertEquals("unity scaled x", p.x, p2.x, 0);
362         assertEquals("unity scaled y", p.y, p2.y, 0);
363         assertEquals("unity scaled z", p.z, p2.z, 0);
364         assertEquals("unity scaled dirX", p.getDirX(), p2.getDirX(), 0);
365         assertEquals("unity scaled dirY", p.getDirY(), p2.getDirY(), 0);
366         assertEquals("unity scaled dirZ", p.getDirZ(), p2.getDirZ(), 0);
367 
368         p2 = p.scale(10.0);
369         assertEquals("10 scaled x", 10 * p.x, p2.x, 1E-6);
370         assertEquals("10 scaled y", 10 * p.y, p2.y, 1E-6);
371         assertEquals("10 scaled z", 10 * p.z, p2.z, 1E-6);
372         assertEquals("10 scaled dirX", p.getDirX(), p2.getDirX(), 0);
373         assertEquals("10 scaled dirY", p.getDirY(), p2.getDirY(), 0);
374         assertEquals("10 scaled dirZ", p.getDirZ(), p2.getDirZ(), 0);
375 
376         try
377         {
378             p.translate(Double.NaN, 2);
379             fail("NaN value should have thrown an IllegalArgumentException");
380         }
381         catch (IllegalArgumentException iae)
382         {
383             // Ignore expected exception
384         }
385 
386         try
387         {
388             p.translate(1, Double.NaN);
389             fail("NaN value should have thrown an IllegalArgumentException");
390         }
391         catch (IllegalArgumentException iae)
392         {
393             // Ignore expected exception
394         }
395 
396         try
397         {
398             p.translate(Double.NaN, 2, 3);
399             fail("NaN value should have thrown an IllegalArgumentException");
400         }
401         catch (IllegalArgumentException iae)
402         {
403             // Ignore expected exception
404         }
405 
406         try
407         {
408             p.translate(1, Double.NaN, 3);
409             fail("NaN value should have thrown an IllegalArgumentException");
410         }
411         catch (IllegalArgumentException iae)
412         {
413             // Ignore expected exception
414         }
415 
416         try
417         {
418             p.translate(1, 2, Double.NaN);
419             fail("NaN value should have thrown an IllegalArgumentException");
420         }
421         catch (IllegalArgumentException iae)
422         {
423             // Ignore expected exception
424         }
425 
426         p2 = p.translate(5.0, -1.0, 2.0);
427         assertEquals("translated x", p.x + 5.0, p2.x, 1E-6);
428         assertEquals("translated y", p.y - 1.0, p2.y, 1E-6);
429         assertEquals("translated z", p.z + 2.0, p2.z, 1E-6);
430         assertEquals("translated dirX", p.getDirX(), p2.getDirX(), 1E-6);
431         assertEquals("translated dirY", p.getDirY(), p2.getDirY(), 1E-6);
432         assertEquals("translated dirZ", p.getDirZ(), p2.getDirZ(), 1E-6);
433 
434         p2 = p.translate(5.0, -1.0);
435         assertEquals("translated x", p.x + 5.0, p2.x, 1E-6);
436         assertEquals("translated y", p.y - 1.0, p2.y, 1E-6);
437         assertEquals("not translated z", p.z, p2.z, 1E-6);
438         assertEquals("translated dirX", p.getDirX(), p2.getDirX(), 1E-6);
439         assertEquals("translated dirY", p.getDirY(), p2.getDirY(), 1E-6);
440         assertEquals("translated dirZ", p.getDirZ(), p2.getDirZ(), 1E-6);
441 
442         p2 = p.rotate(15 * Math.PI / 4, -Math.PI / 4, Math.PI);
443         assertEquals("rotated x", p.x, p2.x, 1E-6);
444         assertEquals("rotated y", p.y, p2.y, 1E-6);
445         assertEquals("rotated z", p.z, p2.z, 1E-6);
446         assertEquals("rotated dirX", AngleUtil.normalizeAroundZero(p.getDirX() + 15 * Math.PI / 4), p2.getDirX(), 1E-6);
447         assertEquals("rotated dirY", AngleUtil.normalizeAroundZero(p.getDirY() - Math.PI / 4), p2.getDirY(), 1E-6);
448         assertEquals("rotated dirZ", AngleUtil.normalizeAroundZero(p.getDirZ() + Math.PI), p2.getDirZ(), 1E-6);
449 
450         p2 = p.rotate(17 * Math.PI / 4);
451         assertEquals("rotated x", p.x, p2.x, 1E-6);
452         assertEquals("rotated y", p.y, p2.y, 1E-6);
453         assertEquals("rotated z", p.z, p2.z, 1E-6);
454         assertEquals("not rotated dirX", p.getDirX(), p2.getDirX(), 1E-6);
455         assertEquals("not rotated dirY", p.getDirY(), p2.getDirY(), 1E-6);
456         assertEquals("rotated dirZ", AngleUtil.normalizeAroundZero(p.getDirZ() + 17 * Math.PI / 4), p2.getDirZ(), 1E-6);
457 
458         // interpolate
459         OrientedPoint3d p1 = new OrientedPoint3d(1.0, 2.0, 3.0, 0.2, 0.3, 0.4);
460         p2 = new OrientedPoint3d(5.0, 7.0, 9.0, 0.4, 0.5, 0.6);
461         assertEquals("p1 interpolated to p2 at 0", p1, p1.interpolate(p2, 0.0));
462         assertEquals("p1 interpolated to p2 at 1", p2, p1.interpolate(p2, 1.0));
463         assertEquals("p2 interpolated to p1 at 0", p2, p2.interpolate(p1, 0.0));
464         assertEquals("p2 interpolated to p1 at 1", p1, p2.interpolate(p1, 1.0));
465         assertEquals("p1 interpolated to itself at 0", p1, p1.interpolate(p1, 0.0));
466         assertTrue("p1 interpolated to p2 at 0.5",
467                 new OrientedPoint3d(3.0, 4.5, 6.0, 0.3, 0.4, 0.5).epsilonEquals(p1.interpolate(p2, 0.5), 1E-6, 1E-6));
468         assertTrue("p1 extrapolated to p2 at 2",
469                 new OrientedPoint3d(9.0, 12.0, 15.0, 0.6, 0.7, 0.8).epsilonEquals(p1.interpolate(p2, 2), 1E-6, 1E-6));
470         assertTrue("p1 extrapolated to p2 at -1",
471                 new OrientedPoint3d(-3.0, -3.0, -3.0, 0.0, 0.1, 0.2).epsilonEquals(p1.interpolate(p2, -1), 1E-6, 1E-6));
472 
473         // distance
474         assertEquals("Distance", Math.sqrt(16 + 25 + 36), p1.distance(p2), 0.001);
475         assertEquals("Distance squared", 16 + 25 + 36, p1.distanceSquared(p2), 0.001);
476         assertEquals("Horizontal distance", Math.sqrt(16 + 25), p1.horizontalDistance(p2), 0.001);
477         assertEquals("Horizontal distance squared", 16 + 25, p1.horizontalDistanceSquared(p2), 0.001);
478 
479         // direction
480         assertEquals("Horizontal direction", Math.atan2(7, 5), p2.horizontalDirection(), 0.001);
481         assertEquals("Horizontal direction", Math.atan2(p2.y - p1.y, p2.x - p1.x), p1.horizontalDirection(p2), 0.001);
482         assertEquals(0.0, new OrientedPoint3d(0.0, 0.0, 0.0).horizontalDirection(), 0.001);
483 
484         // normalize
485         OrientedPoint3d pn = p2.normalize();
486         assertEquals("normalized x", p2.x / Math.sqrt(25 + 49 + 81), pn.x, 0.001);
487         assertEquals("normalized y", p2.y / Math.sqrt(25 + 49 + 81), pn.y, 0.001);
488         assertEquals("normalized z", p2.z / Math.sqrt(25 + 49 + 81), pn.z, 0.001);
489         assertEquals("normalized dirX", p2.getDirX(), pn.getDirX(), 0);
490         assertEquals("normalized dirY", p2.getDirY(), pn.getDirY(), 0);
491         assertEquals("normalized dirZ", p2.getDirZ(), pn.getDirZ(), 0);
492 
493         Try.testFail(new Try.Execution()
494         {
495             @Override
496             public void execute() throws Throwable
497             {
498                 new OrientedPoint3d(0.0, 0.0, 0.0, Math.PI / 4.0, Math.PI / 4.0, Math.PI / 4.0).normalize();
499             }
500         }, "Should throw DRtE", DrawRuntimeException.class);
501 
502         Try.testFail(new Try.Execution()
503         {
504             @Override
505             public void execute() throws Throwable
506             {
507                 p1.rotate(Double.NaN, 0, 0);
508             }
509         }, "Should throw IAE", IllegalArgumentException.class);
510 
511         Try.testFail(new Try.Execution()
512         {
513             @Override
514             public void execute() throws Throwable
515             {
516                 p1.rotate(0, Double.NaN, 0);
517             }
518         }, "Should throw IAE", IllegalArgumentException.class);
519 
520         Try.testFail(new Try.Execution()
521         {
522             @Override
523             public void execute() throws Throwable
524             {
525                 p1.rotate(0, 0, Double.NaN);
526             }
527         }, "Should throw IAE", IllegalArgumentException.class);
528 
529         Try.testFail(new Try.Execution()
530         {
531             @Override
532             public void execute() throws Throwable
533             {
534                 p1.translate(Double.NaN, 2);
535             }
536         }, "Should throw IAE", IllegalArgumentException.class);
537 
538         Try.testFail(new Try.Execution()
539         {
540             @Override
541             public void execute() throws Throwable
542             {
543                 p1.translate(1, Double.NaN);
544             }
545         }, "Should throw IAE", IllegalArgumentException.class);
546 
547         Try.testFail(new Try.Execution()
548         {
549             @Override
550             public void execute() throws Throwable
551             {
552                 p1.translate(Double.NaN, 2, 3);
553             }
554         }, "Should throw IAE", IllegalArgumentException.class);
555 
556         Try.testFail(new Try.Execution()
557         {
558             @Override
559             public void execute() throws Throwable
560             {
561                 p1.translate(1, Double.NaN, 3);
562             }
563         }, "Should throw IAE", IllegalArgumentException.class);
564 
565         Try.testFail(new Try.Execution()
566         {
567             @Override
568             public void execute() throws Throwable
569             {
570                 p1.translate(1, 2, Double.NaN);
571             }
572         }, "Should throw IAE", IllegalArgumentException.class);
573 
574     }
575 
576     /**
577      * Test the OrientedPoint3d operators for NPE.
578      */
579     @Test
580     public void testOrientedPoint3dOperatorsNPE()
581     {
582         final OrientedPoint3d p1 = new OrientedPoint3d(1.0, 1.0, Math.PI / 4.0);
583 
584         Try.testFail(new Try.Execution()
585         {
586             @Override
587             public void execute() throws Throwable
588             {
589                 p1.interpolate(null, 0.5);
590             }
591         }, "Should throw NPE", NullPointerException.class);
592 
593         Try.testFail(new Try.Execution()
594         {
595             @Override
596             public void execute() throws Throwable
597             {
598                 p1.distance(null);
599             }
600         }, "Should throw NPE", NullPointerException.class);
601 
602         Try.testFail(new Try.Execution()
603         {
604             @Override
605             public void execute() throws Throwable
606             {
607                 p1.distanceSquared(null);
608             }
609         }, "Should throw NPE", NullPointerException.class);
610 
611         Try.testFail(new Try.Execution()
612         {
613             @Override
614             public void execute() throws Throwable
615             {
616                 p1.horizontalDistance((OrientedPoint3d) null);
617             }
618         }, "Should throw NPE", NullPointerException.class);
619 
620         Try.testFail(new Try.Execution()
621         {
622             @Override
623             public void execute() throws Throwable
624             {
625                 p1.horizontalDistanceSquared((OrientedPoint3d) null);
626             }
627         }, "Should throw NPE", NullPointerException.class);
628 
629     }
630 
631 }