1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.hipparchus.geometry.euclidean.twod;
23
24 import org.hipparchus.exception.LocalizedCoreFormats;
25 import org.hipparchus.exception.MathIllegalArgumentException;
26 import org.hipparchus.exception.MathRuntimeException;
27 import org.hipparchus.geometry.LocalizedGeometryFormats;
28 import org.hipparchus.util.Binary64Field;
29 import org.hipparchus.util.FastMath;
30 import org.hipparchus.util.MathUtils;
31 import org.hipparchus.util.SinCos;
32 import org.junit.jupiter.api.Test;
33
34 import java.text.NumberFormat;
35 import java.util.Locale;
36
37 import static org.junit.jupiter.api.Assertions.assertEquals;
38 import static org.junit.jupiter.api.Assertions.assertFalse;
39 import static org.junit.jupiter.api.Assertions.assertNotEquals;
40 import static org.junit.jupiter.api.Assertions.assertSame;
41 import static org.junit.jupiter.api.Assertions.assertTrue;
42 import static org.junit.jupiter.api.Assertions.fail;
43
44 class Vector2DTest {
45
46 @Test
47 void testConstructors() {
48 final double p40 = 4.0;
49 final double p20 = 2.0;
50 final double p25 = 2.5;
51 final double p10 = 1.0;
52 final double m05 = -0.5;
53 final double m30 = -3.0;
54 check(new Vector2D(p25, m05), 2.5, -0.5, 1.0e-15);
55 final double[] a = new double[2];
56 a[0] = 1.0;
57 a[1] = 0.0;
58 check(new Vector2D(a), 1.0, 0.0, 1.0e-15);
59 try {
60 new Vector2D(new double[3]);
61 fail("an exception should have been thrown");
62 } catch (MathIllegalArgumentException miae) {
63 assertEquals(LocalizedCoreFormats.DIMENSIONS_MISMATCH, miae.getSpecifier());
64 assertEquals(3, ((Integer) miae.getParts()[0]).intValue());
65 assertEquals(2, ((Integer) miae.getParts()[1]).intValue());
66 }
67 check(new Vector2D(p20, new Vector2D(p25, m05)), 5.0, -1.0, 1.0e-15);
68 check(new Vector2D(p20, new Vector2D(2.5, -0.5)), 5.0, -1.0, 1.0e-15);
69 check(new Vector2D(2, new Vector2D(p25, m05)), 5.0, -1.0, 1.0e-15);
70 check(new Vector2D(p20, new Vector2D(p25, m05), m30, new Vector2D(m05, p40)),
71 6.5, -13.0, 1.0e-15);
72 check(new Vector2D(p20, new Vector2D(2.5, -0.5), m30, new Vector2D(-0.5, 4.0)),
73 6.5, -13.0, 1.0e-15);
74 check(new Vector2D(2.0, new Vector2D(p25, m05), -3.0, new Vector2D(m05, p40)),
75 6.5, -13.0, 1.0e-15);
76 check(new Vector2D(p20, new Vector2D(p25, m05), m30, new Vector2D(m05, p40),
77 p40, new Vector2D(p25, m30)),
78 16.5, -25.0, 1.0e-15);
79 check(new Vector2D(p20, new Vector2D(2.5, -0.5), m30, new Vector2D(-0.5, 4.0),
80 p40, new Vector2D(2.5, -3.0)),
81 16.5, -25.0, 1.0e-15);
82 check(new Vector2D(2.0, new Vector2D(p25, m05), -3.0, new Vector2D(m05, p40),
83 4.0, new Vector2D(p25, m30)),
84 16.5, -25.0, 1.0e-15);
85 check(new Vector2D(p20, new Vector2D(p25, m05), m30, new Vector2D(m05, p40),
86 p40, new Vector2D(p25, m30), p10, new Vector2D(p10, p10)),
87 17.5, -24.0, 1.0e-15);
88 check(new Vector2D(p20, new Vector2D(2.5, -0.5), m30, new Vector2D(-0.5, 4.0),
89 p40, new Vector2D(2.5, -3.0), p10, new Vector2D(1.0, 1.0)),
90 17.5, -24.0, 1.0e-15);
91 check(new Vector2D(2.0, new Vector2D(p25, m05), -3.0, new Vector2D(m05, p40),
92 4.0, new Vector2D(p25, m30), 1.0, new Vector2D(p10, p10)),
93 17.5, -24.0, 1.0e-15);
94 }
95
96 @Test
97 void testConstants() {
98 check(Vector2D.ZERO, 0.0, 0.0, 1.0e-15);
99 check(Vector2D.PLUS_I, 1.0, 0.0, 1.0e-15);
100 check(Vector2D.MINUS_I, -1.0, 0.0, 1.0e-15);
101 check(Vector2D.PLUS_J, 0.0, 1.0, 1.0e-15);
102 check(Vector2D.MINUS_J, 0.0, -1.0, 1.0e-15);
103 check(Vector2D.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, 1.0e-15);
104 check(Vector2D.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, 1.0e-15);
105 assertTrue(Double.isNaN(Vector2D.NaN.getX()));
106 assertTrue(Double.isNaN(Vector2D.NaN.getY()));
107 assertSame(Euclidean2D.getInstance(), Vector2D.NaN.getSpace());
108 assertSame(Vector2D.ZERO, new Vector2D(1.0, 2.0).getZero());
109 }
110
111 @Test
112 void testToMethods() {
113 final Vector2D v = new Vector2D(2.5, -0.5);
114 assertEquals( 2, v.toArray().length);
115 assertEquals( 2.5, v.toArray()[0], 1.0e-15);
116 assertEquals(-0.5, v.toArray()[1], 1.0e-15);
117 assertEquals("{2.5; -0.5}", v.toString().replaceAll(",", "."));
118 assertEquals("{2,5; -0,5}", v.toString(NumberFormat.getInstance(Locale.FRENCH)));
119 }
120
121 @Test
122 void testNorms() {
123 final Vector2D v = new Vector2D(3.0, -4.0);
124 assertEquals( 7.0, v.getNorm1(), 1.0e-15);
125 assertEquals( 5.0, v.getNorm(), 1.0e-15);
126 assertEquals(25.0, v.getNormSq(), 1.0e-15);
127 assertEquals( 4.0, v.getNormInf(), 1.0e-15);
128 }
129
130 @Test
131 void testDistances() {
132 final Vector2D u = new Vector2D( 2.0, -2.0);
133 final Vector2D v = new Vector2D(-1.0, 2.0);
134 assertEquals( 7.0, Vector2D.distance1(u, v), 1.0e-15);
135 assertEquals( 5.0, Vector2D.distance(u, v), 1.0e-15);
136 assertEquals(25.0, Vector2D.distanceSq(u, v), 1.0e-15);
137 assertEquals( 4.0, Vector2D.distanceInf(u, v), 1.0e-15);
138 }
139
140 @Test
141 void testAdd() {
142 final Vector2D u = new Vector2D( 2.0, -2.0);
143 final Vector2D v = new Vector2D(-1.0, 2.0);
144 check(u.add(v), 1.0, 0.0, 1.0e-15);
145 check(u.add(5.0, v), -3.0, 8.0, 1.0e-15);
146 }
147
148 @Test
149 void testSubtract() {
150 final Vector2D u = new Vector2D( 2.0, -2.0);
151 final Vector2D v = new Vector2D( 1.0, -2.0);
152 check(u.subtract(v), 1.0, 0.0, 1.0e-15);
153 check(u.subtract(5, v), -3.0, 8.0, 1.0e-15);
154 }
155
156 @Test
157 void testNormalize() {
158 try {
159 Vector2D.ZERO.normalize();
160 fail("an exception should habe been thrown");
161 } catch (MathRuntimeException mre) {
162 assertEquals(LocalizedGeometryFormats.CANNOT_NORMALIZE_A_ZERO_NORM_VECTOR, mre.getSpecifier());
163 }
164 check(new Vector2D(3, -4).normalize(), 0.6, -0.8, 1.0e-15);
165 }
166
167 @Test
168 void testAngle() {
169 try {
170 Vector2D.angle(Vector2D.ZERO, Vector2D.PLUS_I);
171 fail("an exception should habe been thrown");
172 } catch (MathRuntimeException mre) {
173 assertEquals(LocalizedCoreFormats.ZERO_NORM, mre.getSpecifier());
174 }
175 final double alpha = 0.01;
176 final SinCos sc = FastMath.sinCos(alpha);
177 assertEquals(alpha,
178 Vector2D.angle(new Vector2D(sc.cos(), sc.sin()), Vector2D.PLUS_I),
179 1.0e-15);
180 assertEquals(FastMath.PI - alpha,
181 Vector2D.angle(new Vector2D(-sc.cos(), sc.sin()), Vector2D.PLUS_I),
182 1.0e-15);
183 assertEquals(MathUtils.SEMI_PI - alpha,
184 Vector2D.angle(new Vector2D(sc.sin(), sc.cos()), Vector2D.PLUS_I),
185 1.0e-15);
186 assertEquals(MathUtils.SEMI_PI + alpha,
187 Vector2D.angle(new Vector2D(-sc.sin(), sc.cos()), Vector2D.PLUS_I),
188 1.0e-15);
189 }
190
191
192 @Test
193 void testNegate() {
194 check(new Vector2D(3.0, -4.0).negate(), -3.0, 4.0, 1.0e-15);
195 }
196
197 @Test
198 void testScalarMultiply() {
199 check(new Vector2D(3.0, -4.0).scalarMultiply(2.0), 6.0, -8.0, 1.0e-15);
200 }
201
202 @Test
203 void testIsNaN() {
204 assertTrue(new Vector2D(Double.NaN, 0.0).isNaN());
205 assertTrue(new Vector2D(0.0, Double.NaN).isNaN());
206 assertTrue(new Vector2D(Double.NaN, Double.NaN).isNaN());
207 assertTrue(Vector2D.NaN.isNaN());
208 assertFalse(new Vector2D(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY).isNaN());
209 assertFalse(Vector2D.MINUS_I.isNaN());
210 }
211
212 @Test
213 void testIsInfinite() {
214 assertFalse(new Vector2D(Double.NaN, 0.0).isInfinite());
215 assertTrue(new Vector2D(Double.POSITIVE_INFINITY, 0.0).isInfinite());
216 assertTrue(new Vector2D(0.0, Double.POSITIVE_INFINITY).isInfinite());
217 assertTrue(new Vector2D(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY).isInfinite());
218 assertTrue(new Vector2D(Double.NEGATIVE_INFINITY, 0.0).isInfinite());
219 assertTrue(new Vector2D(0.0, Double.NEGATIVE_INFINITY).isInfinite());
220 assertTrue(new Vector2D(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY).isInfinite());
221 assertFalse(Vector2D.NaN.isInfinite());
222 assertFalse(Vector2D.MINUS_I.isInfinite());
223 }
224
225 @SuppressWarnings("unlikely-arg-type")
226 @Test
227 void testEquals() {
228 final Vector2D u1 = Vector2D.PLUS_I;
229 final Vector2D u2 = Vector2D.MINUS_I.negate();
230 final Vector2D v1 = new Vector2D(1.0, 0.001);
231 final Vector2D v2 = new Vector2D(0.001, 1.0);
232 assertEquals(u1, u1);
233 assertEquals(u1, u2);
234 assertNotEquals(u1, v1);
235 assertNotEquals(u1, v2);
236 assertNotEquals(u1, FieldVector2D.getPlusI(Binary64Field.getInstance()));
237 assertEquals(Vector2D.NaN, new Vector2D(Double.NaN, u1));
238 assertNotEquals(Vector2D.NaN, u1);
239 assertNotEquals(Vector2D.NaN, v2);
240 }
241
242 @Test
243 void testEqualsIeee754() {
244 final Vector2D u1 = Vector2D.PLUS_I;
245 final Vector2D u2 = Vector2D.MINUS_I.negate();
246 final Vector2D v1 = new Vector2D(1.0, 0.001);
247 final Vector2D v2 = new Vector2D(0.001, 1.0);
248 assertTrue(u1.equalsIeee754(u1));
249 assertTrue(u1.equalsIeee754(u2));
250 assertFalse(u1.equalsIeee754(v1));
251 assertFalse(u1.equalsIeee754(v2));
252 assertFalse(u1.equalsIeee754(FieldVector2D.getPlusI(Binary64Field.getInstance())));
253 assertFalse(new Vector2D(Double.NaN, u1).equalsIeee754(Vector2D.NaN));
254 assertFalse(u1.equalsIeee754(Vector2D.NaN));
255 assertFalse(Vector2D.NaN.equalsIeee754(v2));
256 assertFalse(Vector2D.NaN.equalsIeee754(Vector2D.NaN));
257 }
258
259 @Test
260 void testHashCode() {
261 assertEquals(542, Vector2D.NaN.hashCode());
262 assertEquals(1325400064, new Vector2D(1.5, -0.5).hashCode());
263 }
264
265 @Test
266 void testCrossProduct() {
267 final double epsilon = 1e-10;
268
269 Vector2D p1 = new Vector2D(1, 1);
270 Vector2D p2 = new Vector2D(2, 2);
271
272 Vector2D p3 = new Vector2D(3, 3);
273 assertEquals(0.0, p3.crossProduct(p1, p2), epsilon);
274
275 Vector2D p4 = new Vector2D(1, 2);
276 assertEquals(1.0, p4.crossProduct(p1, p2), epsilon);
277
278 Vector2D p5 = new Vector2D(2, 1);
279 assertEquals(-1.0, p5.crossProduct(p1, p2), epsilon);
280
281 }
282
283 @Test
284 void testOrientation() {
285 assertTrue(Vector2D.orientation(new Vector2D(0, 0),
286 new Vector2D(1, 0),
287 new Vector2D(1, 1)) > 0);
288 assertTrue(Vector2D.orientation(new Vector2D(1, 0),
289 new Vector2D(0, 0),
290 new Vector2D(1, 1)) < 0);
291 assertEquals(0.0,
292 Vector2D.orientation(new Vector2D(0, 0),
293 new Vector2D(1, 0),
294 new Vector2D(1, 0)),
295 1.0e-15);
296 assertEquals(0.0,
297 Vector2D.orientation(new Vector2D(0, 0),
298 new Vector2D(1, 0),
299 new Vector2D(2, 0)),
300 1.0e-15);
301 }
302
303 @Test
304 void testArithmeticBlending() {
305
306
307 final Vector2D v1 = new Vector2D(1,2);
308 final Vector2D v2 = new Vector2D(3,4);
309
310 final double blendingValue = 0.7;
311
312
313 final Vector2D blendedVector = v1.blendArithmeticallyWith(v2, blendingValue);
314
315
316 check(blendedVector, 2.4, 3.4, 1e-12);
317 }
318
319 @Test
320 void testMoveTowards() {
321 check(new Vector2D(5.0, -1.0).moveTowards(new Vector2D(3.0, 4.0), 0.0), 5.0, -1.0, 1.0e-15);
322 check(new Vector2D(5.0, -1.0).moveTowards(new Vector2D(3.0, 4.0), 0.5), 4.0, 1.5, 1.0e-15);
323 check(new Vector2D(5.0, -1.0).moveTowards(new Vector2D(3.0, 4.0), 1.0), 3.0, 4.0, 1.0e-15);
324 }
325
326 private void check(final Vector2D v, final double x, final double y, final double tol) {
327 assertEquals(x, v.getX(), tol);
328 assertEquals(y, v.getY(), tol);
329 }
330
331 }