View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  /*
19   * This is not the original file distributed by the Apache Software Foundation
20   * It has been modified by the Hipparchus project
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         // Given
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         // When
313         final Vector2D blendedVector = v1.blendArithmeticallyWith(v2, blendingValue);
314 
315         // Then
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 }