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.assertTrue;
7 import static org.junit.jupiter.api.Assertions.fail;
8
9 import java.awt.geom.Point2D;
10 import java.util.Iterator;
11 import java.util.NoSuchElementException;
12
13 import org.djutils.exceptions.Try;
14 import org.djutils.math.AngleUtil;
15 import org.junit.jupiter.api.Test;
16
17
18
19
20
21
22
23
24
25
26
27
28
29 public class DirectedPoint2dTest
30 {
31
32
33
34 @SuppressWarnings({"unlikely-arg-type"})
35 @Test
36 public void testMethods()
37 {
38 DirectedPoint2d dp = new DirectedPoint2d(1, 2, 3);
39 assertEquals(1, dp.getX(), 0.0, "x can be retrieved");
40 assertEquals(2, dp.getY(), 0.0, "y can be retrieved");
41 assertEquals(3, dp.getDirZ(), 0.0, "DirZ can be retrieved");
42 assertEquals(1, dp.size(), "size is 1");
43 Iterator<Point2d> it = dp.iterator();
44 assertTrue(it.hasNext(), "iterator has at least one point to provide");
45 Point2d p = it.next();
46 assertEquals(p.x, dp.x, 0, "x matches");
47 assertEquals(p.y, dp.y, 0, "y matches");
48 assertFalse(it.hasNext(), "iterator is now exhausted");
49 DirectedPoint2d neg = dp.neg();
50 assertEquals(-1, neg.x, 0, "x is negated");
51 assertEquals(-2, neg.y, 0, "y is negated");
52 assertEquals(AngleUtil.normalizeAroundZero(3 + Math.PI), neg.dirZ, 0.0001, "dirZ is altered by pi");
53 try
54 {
55 it.next();
56 fail("exhausted iterator should have thrown an exception");
57 }
58 catch (NoSuchElementException nse)
59 {
60
61 }
62 assertTrue(dp.toString().startsWith("DirectedPoint2d"));
63 assertTrue(dp.toString(false).startsWith("DirectedPoint2d"));
64 assertTrue(dp.toString(true).startsWith("["));
65 assertEquals(dp, dp, "Equals to itself");
66 assertFalse(dp.equals("bla"), "Not equal to some random string");
67 }
68
69
70
71
72 @SuppressWarnings("unlikely-arg-type")
73 @Test
74 public void testDirectedPoint2dConstruction()
75 {
76 DirectedPoint2d p = new DirectedPoint2d(10.0, -20.0, Math.PI);
77 assertEquals(10.0, p.x, 0, "x");
78 assertEquals(-20.0, p.y, 0, "y");
79 assertEquals(3.1415926, p.getDirZ(), 1E-6, "dirZ");
80
81 Point2d p2d = new Point2d(10, -20);
82 p = new DirectedPoint2d(p2d, Math.PI);
83 assertEquals(10.0, p.x, 0, "x");
84 assertEquals(-20.0, p.y, 0, "y");
85 assertEquals(3.1415926, p.getDirZ(), 1E-6, "dirZ");
86 assertEquals(3.1415926, p.dirZ, 1E-6, "dirZ");
87
88 try
89 {
90 new DirectedPoint2d(Double.NaN, 0, 0);
91 fail("NaN coordinate should have thrown an ArithmeticException");
92 }
93 catch (ArithmeticException e)
94 {
95
96 }
97
98 try
99 {
100 new DirectedPoint2d(0, Double.NaN, 0);
101 fail("NaN coordinate should have thrown an ArithmeticException");
102 }
103 catch (ArithmeticException e)
104 {
105
106 }
107
108 try
109 {
110 new DirectedPoint2d(0, 0, Double.NaN);
111 fail("NaN coordinate should have thrown an ArithmeticException");
112 }
113 catch (ArithmeticException e)
114 {
115
116 }
117
118 double[] p2Arr = new double[] {5.0, 6.0};
119 p = new DirectedPoint2d(p2Arr, Math.PI / 2.0);
120 assertEquals(5.0, p.x, 1E-6);
121 assertEquals(6.0, p.y, 1E-6);
122 assertEquals(3.1415926 / 2.0, p.getDirZ(), 1E-6);
123 Point2D.Double p2DD = new Point2D.Double(-0.1, -0.2);
124 p = new DirectedPoint2d(p2DD, Math.PI / 4.0);
125 assertEquals(-0.1, p.x, 1E-6);
126 assertEquals(-0.2, p.y, 1E-6);
127 assertEquals(p2DD, p.toPoint2D());
128 assertEquals(3.1415926 / 4.0, p.getDirZ(), 1E-6);
129
130 Try.testFail(new Try.Execution()
131 {
132 @Override
133 public void execute() throws Throwable
134 {
135 new DirectedPoint2d((Point2D.Double) null, 0.0);
136 }
137 }, "Should throw NPE", NullPointerException.class);
138
139 Try.testFail(new Try.Execution()
140 {
141 @Override
142 public void execute() throws Throwable
143 {
144 new DirectedPoint2d((Point2D.Double) null, Math.PI);
145 }
146 }, "Should throw NPE", NullPointerException.class);
147
148 Try.testFail(new Try.Execution()
149 {
150 @Override
151 public void execute() throws Throwable
152 {
153 new DirectedPoint2d(new double[] {}, Math.PI / 2.0);
154 }
155 }, "Should throw IAE", IllegalArgumentException.class);
156
157 Try.testFail(new Try.Execution()
158 {
159 @Override
160 public void execute() throws Throwable
161 {
162 new DirectedPoint2d(new double[] {1.0}, Math.PI / 4.0);
163 }
164 }, "Should throw IAE", IllegalArgumentException.class);
165
166 Try.testFail(new Try.Execution()
167 {
168 @Override
169 public void execute() throws Throwable
170 {
171 new DirectedPoint2d(new double[] {1.0, 2.0, 3.0}, Math.PI);
172 }
173 }, "Should throw IAE", IllegalArgumentException.class);
174
175
176 assertTrue(p.equals(p));
177 assertEquals(p.hashCode(), p.hashCode());
178 DirectedPoint3d p3d = p.translate(1, 2, 3);
179 assertFalse(p.equals(p3d));
180 assertFalse(p.equals(null));
181 assertNotEquals(p3d.hashCode(), p.hashCode());
182 assertEquals(p.x + 1.0, p3d.x, 0.00001, "translated x");
183 assertEquals(p.y + 2.0, p3d.y, 0.00001, "translated y");
184 assertEquals(0 + 3.0, p3d.z, 0.00001, "translated z");
185 assertEquals(Math.PI / 4.0, p.getDirZ(), 1E-6);
186 assertTrue(p.equals(p.translate(0.0, 0.0)));
187 assertFalse(p.equals(p.translate(1.0, 0.0)));
188 assertFalse(p.equals(p.translate(0.0, 1.0)));
189 assertFalse(p.equals(p.rotate(0.1)));
190
191
192 p = new DirectedPoint2d(10.0, 20.0, Math.PI);
193 assertEquals("DirectedPoint2d [x=10.000000, y=20.000000, dirZ=3.141593]", p.toString());
194 assertEquals("DirectedPoint2d [x=10.0, y=20.0, dirZ=3.1]", p.toString("%.1f"));
195 assertEquals("[x=10, y=20, dirZ=3]", p.toString("%.0f", true));
196
197
198 DirectedPoint3d p3 = new DirectedPoint3d(p.translate(0.001, 0.0, 0.0), 0, p.dirZ);
199 DirectedPoint3d ref = new DirectedPoint3d(p.translate(0, 0, 0), 0, p.dirZ);
200 assertTrue(ref.epsilonEquals(p3, 0.09, 0.001));
201 assertTrue(p3.epsilonEquals(ref, 0.09, 0.001));
202 assertFalse(ref.epsilonEquals(p3, 0.0009, 0.001));
203 assertFalse(p3.epsilonEquals(ref, 0.0009, 0.001));
204 p3 = p.translate(0.0, 0.001, 0.0);
205 assertTrue(ref.epsilonEquals(p3, 0.09, 0.001));
206 assertTrue(p3.epsilonEquals(ref, 0.09, 0.001));
207 assertFalse(ref.epsilonEquals(p3, 0.0009, 0.001));
208 assertFalse(p3.epsilonEquals(ref, 0.0009, 0.001));
209 DirectedPoint2d p2 = p.translate(0.001, 0.0);
210 assertTrue(p.epsilonEquals(p2, 0.09, 0.001), "all");
211 assertFalse(p.epsilonEquals(p2, 0.0009, 0.001), "dx");
212 p2 = p.translate(0.0, 0.001);
213 assertTrue(p.epsilonEquals(p2, 0.09, 0.001), "all");
214 assertFalse(p.epsilonEquals(p2, 0.0009, 0.001), "dy");
215 p3 = p.translate(0.0, 0.0, 0.001);
216 assertTrue(ref.epsilonEquals(p3, 0.09, 0.001));
217 assertTrue(p3.epsilonEquals(ref, 0.09, 0.001));
218 assertFalse(ref.epsilonEquals(p3, 0.0009, 0.001));
219 assertFalse(p3.epsilonEquals(ref, 0.0009, 0.001));
220 DirectedPoint2d dp2 = p.rotate(0.001);
221 assertTrue(p.epsilonEquals(dp2, 0.09, 0.009));
222 assertTrue(dp2.epsilonEquals(p, 0.09, 0.009));
223 assertFalse(p.epsilonEquals(dp2, 0.0009, 0.0009));
224 assertFalse(dp2.epsilonEquals(p, 0.0009, 0.0009));
225 }
226
227
228
229
230 @Test
231 public void testDirectedPoint2dOperators()
232 {
233 DirectedPoint2d p = new DirectedPoint2d(-0.1, -0.2, -Math.PI / 7);
234 DirectedPoint2d out = new DirectedPoint2d(p.abs(), p.dirZ);
235 assertEquals(0.1, out.x, 1E-6, "x");
236 assertEquals(0.2, out.y, 1E-6, "y");
237 assertEquals(-Math.PI / 7, out.getDirZ(), 1E-6, "dirZ");
238
239 Iterator<Point2d> i = p.iterator();
240 assertTrue(i.hasNext(), "iterator has one point");
241 assertEquals(p, i.next(), "iterator returns p");
242 assertFalse(i.hasNext(), "iterator does not have another point");
243
244 out = p.neg();
245 assertEquals(0.1, out.x, 1E-6, "neg x");
246 assertEquals(0.2, out.y, 1E-6, "neg y");
247 assertEquals(Math.PI - Math.PI / 7, out.getDirZ(), 1E-6, "neg dirZ");
248
249 out = p.scale(1.0);
250 assertEquals(-0.1, out.x, 1E-6, "x");
251 assertEquals(-0.2, out.y, 1E-6, "y");
252 assertEquals(-Math.PI / 7, out.getDirZ(), 1E-6, "dirZ");
253
254 out = p.scale(10.0);
255 assertEquals(-1.0, out.x, 1E-6, "10 x");
256 assertEquals(-2.0, out.y, 1E-6, "10 y");
257 assertEquals(-Math.PI / 7, out.getDirZ(), 1E-6, "dirZ");
258
259 out = p.translate(5.0, -1.0);
260 assertEquals(4.9, out.x, 1E-6, "x");
261 assertEquals(-1.2, out.y, 1E-6, "y");
262 assertEquals(-Math.PI / 7, out.getDirZ(), 1E-6, "dirZ");
263
264 out = p.translate(1.0, 3.0);
265 assertEquals(0.9, out.x, 1E-6, "x");
266 assertEquals(2.8, out.y, 1E-6, "y");
267 assertEquals(-Math.PI / 7, out.getDirZ(), 1E-6, "dirZ");
268
269 out = p.rotate(-Math.PI / 4);
270 assertEquals(-0.1, out.x, 1E-6, "x");
271 assertEquals(-0.2, out.y, 1E-6, "y");
272 assertEquals(-Math.PI / 7 - Math.PI / 4, out.getDirZ(), 1E-6, "dirZ");
273
274
275 DirectedPoint2d p1 = new DirectedPoint2d(1.0, 1.0, 0.0);
276 DirectedPoint2d p2 = new DirectedPoint2d(5.0, 5.0, Math.PI / 2.0);
277 assertEquals(p1, p1.interpolate(p2, 0.0), "p1 interpolated to p2 at 0");
278 assertEquals(p2, p1.interpolate(p2, 1.0), "p1 interpolated to p2 at 1");
279 assertEquals(p2, p2.interpolate(p1, 0.0), "p2 interpolated to p1 at 0");
280 assertEquals(p1, p2.interpolate(p1, 1.0), "p2 interpolated to p1 at 1");
281 assertEquals(p1, p1.interpolate(p1, 0.0), "p1 interpolated to itself at 0");
282 assertEquals(new DirectedPoint2d(3.0, 3.0, Math.PI / 4.0), p1.interpolate(p2, 0.5), "interpolated at halfway");
283
284
285 assertEquals(Math.sqrt(32.0), p1.distance(p2), 0.001);
286 assertEquals(32.0, p1.distanceSquared(p2), 0.001);
287
288
289
290
291
292
293
294
295
296
297 DirectedPoint2d pn = new DirectedPoint2d(p2.normalize(), p.dirZ);
298 assertEquals(1.0 / Math.sqrt(2.0), pn.x, 0.001);
299 assertEquals(1.0 / Math.sqrt(2.0), pn.y, 0.001);
300
301 Try.testFail(new Try.Execution()
302 {
303 @Override
304 public void execute() throws Throwable
305 {
306 new DirectedPoint2d(0.0, 0.0, Math.PI / 4.0).normalize();
307 }
308 }, "Should throw exception", IllegalArgumentException.class);
309
310 Try.testFail(new Try.Execution()
311 {
312 @Override
313 public void execute() throws Throwable
314 {
315 p1.translate(Double.NaN, 2);
316 }
317 }, "Should throw ArithmeticException", ArithmeticException.class);
318
319 Try.testFail(new Try.Execution()
320 {
321 @Override
322 public void execute() throws Throwable
323 {
324 p1.translate(1, Double.NaN);
325 }
326 }, "Should throw ArithmeticException", ArithmeticException.class);
327
328 Try.testFail(new Try.Execution()
329 {
330 @Override
331 public void execute() throws Throwable
332 {
333 p1.translate(Double.NaN, 2, 3);
334 }
335 }, "Should throw ArithmeticException", ArithmeticException.class);
336
337 Try.testFail(new Try.Execution()
338 {
339 @Override
340 public void execute() throws Throwable
341 {
342 p1.translate(1, Double.NaN, 3);
343 }
344 }, "Should throw ArithmeticException", ArithmeticException.class);
345
346 Try.testFail(new Try.Execution()
347 {
348 @Override
349 public void execute() throws Throwable
350 {
351 p1.translate(1, 2, Double.NaN);
352 }
353 }, "Should throw ArithmeticException", ArithmeticException.class);
354
355 }
356
357
358
359
360 @Test
361 public void testDirectedPoint2dOperatorsNPE()
362 {
363 final DirectedPoint2d p1 = new DirectedPoint2d(1.0, 1.0, Math.PI / 4.0);
364
365 Try.testFail(new Try.Execution()
366 {
367 @Override
368 public void execute() throws Throwable
369 {
370 p1.interpolate(null, 0.5);
371 }
372 }, "Should throw NPE", NullPointerException.class);
373
374 Try.testFail(new Try.Execution()
375 {
376 @Override
377 public void execute() throws Throwable
378 {
379 p1.distance(null);
380 }
381 }, "Should throw NPE", NullPointerException.class);
382
383 Try.testFail(new Try.Execution()
384 {
385 @Override
386 public void execute() throws Throwable
387 {
388 p1.distanceSquared(null);
389 }
390 }, "Should throw NPE", NullPointerException.class);
391
392 }
393
394 }