1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.hipparchus.geometry.euclidean.twod;
18
19 import org.hipparchus.CalculusFieldElement;
20 import org.hipparchus.Field;
21 import org.hipparchus.exception.LocalizedCoreFormats;
22 import org.hipparchus.exception.MathIllegalArgumentException;
23 import org.hipparchus.exception.MathRuntimeException;
24 import org.hipparchus.geometry.LocalizedGeometryFormats;
25 import org.hipparchus.util.Binary64Field;
26 import org.hipparchus.util.FastMath;
27 import org.hipparchus.util.MathArrays;
28 import org.hipparchus.util.MathUtils;
29 import org.hipparchus.util.SinCos;
30 import org.junit.jupiter.api.Test;
31
32 import java.text.NumberFormat;
33 import java.util.Locale;
34
35 import static org.junit.jupiter.api.Assertions.assertEquals;
36 import static org.junit.jupiter.api.Assertions.assertFalse;
37 import static org.junit.jupiter.api.Assertions.assertNotEquals;
38 import static org.junit.jupiter.api.Assertions.assertTrue;
39 import static org.junit.jupiter.api.Assertions.fail;
40
41 class FieldVector2DTest {
42
43 @Test
44 void testConstructors() {
45 doTestConstructors(Binary64Field.getInstance());
46 }
47
48 @Test
49 void testConstants() {
50 doTestConstants(Binary64Field.getInstance());
51 }
52
53 @Test
54 void testToMethods() {
55 doTestToMethods(Binary64Field.getInstance());
56 }
57
58 @Test
59 void testNorms() {
60 doTestNorms(Binary64Field.getInstance());
61 }
62
63 @Test
64 void testDistances() {
65 doTestDistances(Binary64Field.getInstance());
66 }
67
68 @Test
69 void testAdd() {
70 doTestAdd(Binary64Field.getInstance());
71 }
72
73 @Test
74 void testSubtract() {
75 doTestSubtract(Binary64Field.getInstance());
76 }
77
78 @Test
79 void testNormalize() {
80 doTestNormalize(Binary64Field.getInstance());
81 }
82
83 @Test
84 void testAngle() {
85 doTestAngle(Binary64Field.getInstance());
86 }
87
88 @Test
89 void testNegate() {
90 doTestNegate(Binary64Field.getInstance());
91 }
92
93 @Test
94 void testScalarMultiply() {
95 doTestScalarMultiply(Binary64Field.getInstance());
96 }
97
98 @Test
99 void testIsNaN() {
100 doTestIsNaN(Binary64Field.getInstance());
101 }
102
103 @Test
104 void testIsInfinite() {
105 doTestIsInfinite(Binary64Field.getInstance());
106 }
107
108 @Test
109 void testEquals() {
110 doTestEquals(Binary64Field.getInstance());
111 }
112
113 @Test
114 void testHashCode() {
115 doTestHashCode(Binary64Field.getInstance());
116 }
117
118 @Test
119 void testCrossProduct() {
120 doTestCrossProduct(Binary64Field.getInstance());
121 }
122
123 @Test
124 void testOrientation() {
125 doTestOrientation(Binary64Field.getInstance());
126 }
127
128 private <T extends CalculusFieldElement<T>> void doTestConstructors(final Field<T> field) {
129 final T p40 = field.getZero().add( 4.0);
130 final T p20 = field.getZero().add( 2.0);
131 final T p25 = field.getZero().add( 2.5);
132 final T p10 = field.getOne();
133 final T m05 = field.getZero().add(-0.5);
134 final T m30 = field.getZero().add(-3.0);
135 check(new FieldVector2D<>(p25, m05), 2.5, -0.5, 1.0e-15);
136 final T[] a = MathArrays.buildArray(field, 2);
137 a[0] = field.getOne();
138 a[1] = field.getZero();
139 check(new FieldVector2D<>(a), 1.0, 0.0, 1.0e-15);
140 try {
141 new FieldVector2D<>(MathArrays.buildArray(field, 3));
142 fail("an exception should have been thrown");
143 } catch (MathIllegalArgumentException miae) {
144 assertEquals(LocalizedCoreFormats.DIMENSIONS_MISMATCH, miae.getSpecifier());
145 assertEquals(3, ((Integer) miae.getParts()[0]).intValue());
146 assertEquals(2, ((Integer) miae.getParts()[1]).intValue());
147 }
148 check(new FieldVector2D<>(p20, new FieldVector2D<>(p25, m05)), 5.0, -1.0, 1.0e-15);
149 check(new FieldVector2D<>(p20, new Vector2D(2.5, -0.5)), 5.0, -1.0, 1.0e-15);
150 check(new FieldVector2D<>(2, new FieldVector2D<>(p25, m05)), 5.0, -1.0, 1.0e-15);
151 check(new FieldVector2D<>(p20, new FieldVector2D<>(p25, m05), m30, new FieldVector2D<>(m05, p40)),
152 6.5, -13.0, 1.0e-15);
153 check(new FieldVector2D<>(p20, new Vector2D(2.5, -0.5), m30, new Vector2D(-0.5, 4.0)),
154 6.5, -13.0, 1.0e-15);
155 check(new FieldVector2D<>(2.0, new FieldVector2D<>(p25, m05), -3.0, new FieldVector2D<>(m05, p40)),
156 6.5, -13.0, 1.0e-15);
157 check(new FieldVector2D<>(p20, new FieldVector2D<>(p25, m05), m30, new FieldVector2D<>(m05, p40),
158 p40, new FieldVector2D<>(p25, m30)),
159 16.5, -25.0, 1.0e-15);
160 check(new FieldVector2D<>(p20, new Vector2D(2.5, -0.5), m30, new Vector2D(-0.5, 4.0),
161 p40, new Vector2D(2.5, -3.0)),
162 16.5, -25.0, 1.0e-15);
163 check(new FieldVector2D<>(2.0, new FieldVector2D<>(p25, m05), -3.0, new FieldVector2D<>(m05, p40),
164 4.0, new FieldVector2D<>(p25, m30)),
165 16.5, -25.0, 1.0e-15);
166 check(new FieldVector2D<>(p20, new FieldVector2D<>(p25, m05), m30, new FieldVector2D<>(m05, p40),
167 p40, new FieldVector2D<>(p25, m30), p10, new FieldVector2D<>(p10, p10)),
168 17.5, -24.0, 1.0e-15);
169 check(new FieldVector2D<>(p20, new Vector2D(2.5, -0.5), m30, new Vector2D(-0.5, 4.0),
170 p40, new Vector2D(2.5, -3.0), p10, new Vector2D(1.0, 1.0)),
171 17.5, -24.0, 1.0e-15);
172 check(new FieldVector2D<>(2.0, new FieldVector2D<>(p25, m05), -3.0, new FieldVector2D<>(m05, p40),
173 4.0, new FieldVector2D<>(p25, m30), 1.0, new FieldVector2D<>(p10, p10)),
174 17.5, -24.0, 1.0e-15);
175 }
176
177 private <T extends CalculusFieldElement<T>> void doTestConstants(final Field<T> field) {
178 check(FieldVector2D.getZero(field), 0.0, 0.0, 1.0e-15);
179 check(FieldVector2D.getPlusI(field), 1.0, 0.0, 1.0e-15);
180 check(FieldVector2D.getMinusI(field), -1.0, 0.0, 1.0e-15);
181 check(FieldVector2D.getPlusJ(field), 0.0, 1.0, 1.0e-15);
182 check(FieldVector2D.getMinusJ(field), 0.0, -1.0, 1.0e-15);
183 check(FieldVector2D.getPositiveInfinity(field), Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, 1.0e-15);
184 check(FieldVector2D.getNegativeInfinity(field), Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, 1.0e-15);
185 assertTrue(Double.isNaN(FieldVector2D.getNaN(field).getX().getReal()));
186 assertTrue(Double.isNaN(FieldVector2D.getNaN(field).getY().getReal()));
187 }
188
189 private <T extends CalculusFieldElement<T>> void doTestToMethods(final Field<T> field) {
190 final FieldVector2D<T> v = new FieldVector2D<>(field, new Vector2D(2.5, -0.5));
191 assertEquals( 2, v.toArray().length);
192 assertEquals( 2.5, v.toArray()[0].getReal(), 1.0e-15);
193 assertEquals(-0.5, v.toArray()[1].getReal(), 1.0e-15);
194 assertEquals(new Vector2D(2.5, -0.5), v.toVector2D());
195 assertEquals("{2.5; -0.5}", v.toString().replaceAll(",", "."));
196 assertEquals("{2,5; -0,5}", v.toString(NumberFormat.getInstance(Locale.FRENCH)));
197 }
198
199 private <T extends CalculusFieldElement<T>> void doTestNorms(final Field<T> field) {
200 final FieldVector2D<T> v = new FieldVector2D<>(field, new Vector2D(3.0, -4.0));
201 assertEquals( 7.0, v.getNorm1().getReal(), 1.0e-15);
202 assertEquals( 5.0, v.getNorm().getReal(), 1.0e-15);
203 assertEquals(25.0, v.getNormSq().getReal(), 1.0e-15);
204 assertEquals( 4.0, v.getNormInf().getReal(), 1.0e-15);
205 }
206
207 private <T extends CalculusFieldElement<T>> void doTestDistances(final Field<T> field) {
208 final FieldVector2D<T> u = new FieldVector2D<>(field, new Vector2D( 2.0, -2.0));
209 final FieldVector2D<T> v = new FieldVector2D<>(field, new Vector2D(-1.0, 2.0));
210 assertEquals( 7.0, FieldVector2D.distance1(u, v).getReal(), 1.0e-15);
211 assertEquals( 5.0, FieldVector2D.distance(u, v).getReal(), 1.0e-15);
212 assertEquals(25.0, FieldVector2D.distanceSq(u, v).getReal(), 1.0e-15);
213 assertEquals( 4.0, FieldVector2D.distanceInf(u, v).getReal(), 1.0e-15);
214 assertEquals( 7.0, FieldVector2D.distance1(u, v.toVector2D()).getReal(), 1.0e-15);
215 assertEquals( 5.0, FieldVector2D.distance(u, v.toVector2D()).getReal(), 1.0e-15);
216 assertEquals(25.0, FieldVector2D.distanceSq(u, v.toVector2D()).getReal(), 1.0e-15);
217 assertEquals( 4.0, FieldVector2D.distanceInf(u, v.toVector2D()).getReal(), 1.0e-15);
218 assertEquals( 7.0, FieldVector2D.distance1(u.toVector2D(), v).getReal(), 1.0e-15);
219 assertEquals( 5.0, FieldVector2D.distance(u.toVector2D(), v).getReal(), 1.0e-15);
220 assertEquals(25.0, FieldVector2D.distanceSq(u.toVector2D(), v).getReal(), 1.0e-15);
221 assertEquals( 4.0, FieldVector2D.distanceInf(u.toVector2D(), v).getReal(), 1.0e-15);
222 }
223
224 private <T extends CalculusFieldElement<T>> void doTestAdd(final Field<T> field) {
225 final FieldVector2D<T> u = new FieldVector2D<>(field, new Vector2D( 2.0, -2.0));
226 final FieldVector2D<T> v = new FieldVector2D<>(field, new Vector2D(-1.0, 2.0));
227 check(u.add(v), 1.0, 0.0, 1.0e-15);
228 check(u.add(v.toVector2D()), 1.0, 0.0, 1.0e-15);
229 check(u.add(field.getZero().add(5), v), -3.0, 8.0, 1.0e-15);
230 check(u.add(field.getZero().add(5), v.toVector2D()), -3.0, 8.0, 1.0e-15);
231 check(u.add(5.0, v), -3.0, 8.0, 1.0e-15);
232 check(u.add(5.0, v.toVector2D()), -3.0, 8.0, 1.0e-15);
233 }
234
235 private <T extends CalculusFieldElement<T>> void doTestSubtract(final Field<T> field) {
236 final FieldVector2D<T> u = new FieldVector2D<>(field, new Vector2D( 2.0, -2.0));
237 final FieldVector2D<T> v = new FieldVector2D<>(field, new Vector2D( 1.0, -2.0));
238 check(u.subtract(v), 1.0, 0.0, 1.0e-15);
239 check(u.subtract(v.toVector2D()), 1.0, 0.0, 1.0e-15);
240 check(u.subtract(field.getZero().add(5), v), -3.0, 8.0, 1.0e-15);
241 check(u.subtract(field.getZero().add(5), v.toVector2D()), -3.0, 8.0, 1.0e-15);
242 check(u.subtract(5.0, v), -3.0, 8.0, 1.0e-15);
243 check(u.subtract(5.0, v.toVector2D()), -3.0, 8.0, 1.0e-15);
244 }
245
246 private <T extends CalculusFieldElement<T>> void doTestNormalize(final Field<T> field) {
247 try {
248 FieldVector2D.getZero(field).normalize();
249 fail("an exception should habe been thrown");
250 } catch (MathRuntimeException mre) {
251 assertEquals(LocalizedGeometryFormats.CANNOT_NORMALIZE_A_ZERO_NORM_VECTOR, mre.getSpecifier());
252 }
253 check(new FieldVector2D<>(field, new Vector2D(3, -4)).normalize(), 0.6, -0.8, 1.0e-15);
254 }
255
256 private <T extends CalculusFieldElement<T>> void doTestAngle(final Field<T> field) {
257 try {
258 FieldVector2D.angle(FieldVector2D.getZero(field), FieldVector2D.getPlusI(field));
259 fail("an exception should habe been thrown");
260 } catch (MathRuntimeException mre) {
261 assertEquals(LocalizedCoreFormats.ZERO_NORM, mre.getSpecifier());
262 }
263 final double alpha = 0.01;
264 final SinCos sc = FastMath.sinCos(alpha);
265 assertEquals(alpha,
266 FieldVector2D.angle(new FieldVector2D<>(field, new Vector2D(sc.cos(), sc.sin())),
267 FieldVector2D.getPlusI(field)).getReal(),
268 1.0e-15);
269 assertEquals(FastMath.PI - alpha,
270 FieldVector2D.angle(new FieldVector2D<>(field, new Vector2D(-sc.cos(), sc.sin())),
271 FieldVector2D.getPlusI(field)).getReal(),
272 1.0e-15);
273 assertEquals(MathUtils.SEMI_PI - alpha,
274 FieldVector2D.angle(new FieldVector2D<>(field, new Vector2D(sc.sin(), sc.cos())),
275 FieldVector2D.getPlusI(field)).getReal(),
276 1.0e-15);
277 assertEquals(MathUtils.SEMI_PI + alpha,
278 FieldVector2D.angle(new FieldVector2D<>(field, new Vector2D(-sc.sin(), sc.cos())),
279 FieldVector2D.getPlusI(field)).getReal(),
280 1.0e-15);
281 try {
282 FieldVector2D.angle(FieldVector2D.getZero(field), Vector2D.PLUS_I);
283 fail("an exception should habe been thrown");
284 } catch (MathRuntimeException mre) {
285 assertEquals(LocalizedCoreFormats.ZERO_NORM, mre.getSpecifier());
286 }
287 assertEquals(alpha,
288 FieldVector2D.angle(new FieldVector2D<>(field, new Vector2D(sc.cos(), sc.sin())),
289 Vector2D.PLUS_I).getReal(),
290 1.0e-15);
291 assertEquals(FastMath.PI - alpha,
292 FieldVector2D.angle(new FieldVector2D<>(field, new Vector2D(-sc.cos(), sc.sin())),
293 Vector2D.PLUS_I).getReal(),
294 1.0e-15);
295 assertEquals(MathUtils.SEMI_PI - alpha,
296 FieldVector2D.angle(new FieldVector2D<>(field, new Vector2D(sc.sin(), sc.cos())),
297 Vector2D.PLUS_I).getReal(),
298 1.0e-15);
299 assertEquals(MathUtils.SEMI_PI + alpha,
300 FieldVector2D.angle(new FieldVector2D<>(field, new Vector2D(-sc.sin(), sc.cos())),
301 Vector2D.PLUS_I).getReal(),
302 1.0e-15);
303 try {
304 FieldVector2D.angle(Vector2D.ZERO, FieldVector2D.getPlusI(field));
305 fail("an exception should habe been thrown");
306 } catch (MathRuntimeException mre) {
307 assertEquals(LocalizedCoreFormats.ZERO_NORM, mre.getSpecifier());
308 }
309 assertEquals(alpha,
310 FieldVector2D.angle(new Vector2D(sc.cos(), sc.sin()),
311 FieldVector2D.getPlusI(field)).getReal(),
312 1.0e-15);
313 assertEquals(FastMath.PI - alpha,
314 FieldVector2D.angle(new Vector2D(-sc.cos(), sc.sin()),
315 FieldVector2D.getPlusI(field)).getReal(),
316 1.0e-15);
317 assertEquals(MathUtils.SEMI_PI - alpha,
318 FieldVector2D.angle(new Vector2D(sc.sin(), sc.cos()),
319 FieldVector2D.getPlusI(field)).getReal(),
320 1.0e-15);
321 assertEquals(MathUtils.SEMI_PI + alpha,
322 FieldVector2D.angle(new Vector2D(-sc.sin(), sc.cos()),
323 FieldVector2D.getPlusI(field)).getReal(),
324 1.0e-15);
325 }
326
327
328 private <T extends CalculusFieldElement<T>> void doTestNegate(final Field<T> field) {
329 check(new FieldVector2D<>(field, new Vector2D(3.0, -4.0)).negate(), -3.0, 4.0, 1.0e-15);
330 }
331
332 private <T extends CalculusFieldElement<T>> void doTestScalarMultiply(final Field<T> field) {
333 check(new FieldVector2D<>(field, new Vector2D(3.0, -4.0)).scalarMultiply(2.0), 6.0, -8.0, 1.0e-15);
334 check(new FieldVector2D<>(field, new Vector2D(3.0, -4.0)).scalarMultiply(field.getZero().add(2.0)), 6.0, -8.0, 1.0e-15);
335 }
336
337 private <T extends CalculusFieldElement<T>> void doTestIsNaN(final Field<T> field) {
338 assertTrue(new FieldVector2D<>(field, new Vector2D(Double.NaN, 0.0)).isNaN());
339 assertTrue(new FieldVector2D<>(field, new Vector2D(0.0, Double.NaN)).isNaN());
340 assertTrue(new FieldVector2D<>(field, new Vector2D(Double.NaN, Double.NaN)).isNaN());
341 assertTrue(FieldVector2D.getNaN(field).isNaN());
342 assertFalse(new FieldVector2D<>(field, new Vector2D(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY)).isNaN());
343 assertFalse(FieldVector2D.getMinusI(field).isNaN());
344 }
345
346 private <T extends CalculusFieldElement<T>> void doTestIsInfinite(final Field<T> field) {
347 assertFalse(new FieldVector2D<>(field, new Vector2D(Double.NaN, 0.0)).isInfinite());
348 assertTrue(new FieldVector2D<>(field, new Vector2D(Double.POSITIVE_INFINITY, 0.0)).isInfinite());
349 assertTrue(new FieldVector2D<>(field, new Vector2D(0.0, Double.POSITIVE_INFINITY)).isInfinite());
350 assertTrue(new FieldVector2D<>(field, new Vector2D(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY)).isInfinite());
351 assertTrue(new FieldVector2D<>(field, new Vector2D(Double.NEGATIVE_INFINITY, 0.0)).isInfinite());
352 assertTrue(new FieldVector2D<>(field, new Vector2D(0.0, Double.NEGATIVE_INFINITY)).isInfinite());
353 assertTrue(new FieldVector2D<>(field, new Vector2D(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY)).isInfinite());
354 assertFalse(FieldVector2D.getNaN(field).isInfinite());
355 assertFalse(FieldVector2D.getMinusI(field).isInfinite());
356 }
357
358 private <T extends CalculusFieldElement<T>> void doTestEquals(final Field<T> field) {
359 final FieldVector2D<T> u1 = new FieldVector2D<>(field, Vector2D.PLUS_I);
360 final FieldVector2D<T> u2 = new FieldVector2D<>(field, Vector2D.MINUS_I.negate());
361 final FieldVector2D<T> v1 = new FieldVector2D<>(field, new Vector2D(1.0, 0.001));
362 final FieldVector2D<T> v2 = new FieldVector2D<>(field, new Vector2D(0.001, 1.0));
363 assertEquals(u1, u1);
364 assertEquals(u1, u2);
365 assertNotEquals(u1, v1);
366 assertNotEquals(u1, v2);
367 assertNotEquals(Vector2D.PLUS_I, u1);
368 assertEquals(Vector2D.PLUS_I, u1.toVector2D());
369 assertEquals(new FieldVector2D<>(Double.NaN, u1), FieldVector2D.getNaN(field));
370 assertNotEquals(u1, FieldVector2D.getNaN(field));
371 assertNotEquals(FieldVector2D.getNaN(field), v2);
372 }
373
374 private <T extends CalculusFieldElement<T>> void doTestHashCode(final Field<T> field) {
375 assertEquals(542, FieldVector2D.getNaN(field).hashCode());
376 assertEquals(1325400064, new FieldVector2D<>(field, new Vector2D(1.5, -0.5)).hashCode());
377 }
378
379 private <T extends CalculusFieldElement<T>> void doTestCrossProduct(final Field<T> field) {
380 final double epsilon = 1e-10;
381
382 FieldVector2D<T> p1 = new FieldVector2D<>(field, new Vector2D(1, 1));
383 FieldVector2D<T> p2 = new FieldVector2D<>(field, new Vector2D(2, 2));
384
385 FieldVector2D<T> p3 = new FieldVector2D<>(field, new Vector2D(3, 3));
386 assertEquals(0.0, p3.crossProduct(p1, p2).getReal(), epsilon);
387
388 FieldVector2D<T> p4 = new FieldVector2D<>(field, new Vector2D(1, 2));
389 assertEquals(1.0, p4.crossProduct(p1, p2).getReal(), epsilon);
390
391 FieldVector2D<T> p5 = new FieldVector2D<>(field, new Vector2D(2, 1));
392 assertEquals(-1.0, p5.crossProduct(p1, p2).getReal(), epsilon);
393 assertEquals(-1.0, p5.crossProduct(p1.toVector2D(), p2.toVector2D()).getReal(), epsilon);
394 }
395
396 private <T extends CalculusFieldElement<T>> void doTestOrientation(final Field<T> field) {
397 assertTrue(FieldVector2D.orientation(new FieldVector2D<>(field, new Vector2D(0, 0)),
398 new FieldVector2D<>(field, new Vector2D(1, 0)),
399 new FieldVector2D<>(field, new Vector2D(1, 1))).getReal() > 0);
400 assertTrue(FieldVector2D.orientation(new FieldVector2D<>(field, new Vector2D(1, 0)),
401 new FieldVector2D<>(field, new Vector2D(0, 0)),
402 new FieldVector2D<>(field, new Vector2D(1, 1))).getReal() < 0);
403 assertEquals(0.0,
404 FieldVector2D.orientation(new FieldVector2D<>(field, new Vector2D(0, 0)),
405 new FieldVector2D<>(field, new Vector2D(1, 0)),
406 new FieldVector2D<>(field, new Vector2D(1, 0))).getReal(),
407 1.0e-15);
408 assertEquals(0.0,
409 FieldVector2D.orientation(new FieldVector2D<>(field, new Vector2D(0, 0)),
410 new FieldVector2D<>(field, new Vector2D(1, 0)),
411 new FieldVector2D<>(field, new Vector2D(2, 0))).getReal(),
412 1.0e-15);
413 }
414
415 private <T extends CalculusFieldElement<T>> void check(final FieldVector2D<T> v,
416 final double x, final double y, final double tol) {
417 assertEquals(x, v.getX().getReal(), tol);
418 assertEquals(y, v.getY().getReal(), tol);
419 }
420
421 }