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 java.text.NumberFormat;
25
26 import org.hipparchus.exception.LocalizedCoreFormats;
27 import org.hipparchus.exception.MathIllegalArgumentException;
28 import org.hipparchus.exception.MathRuntimeException;
29 import org.hipparchus.geometry.Point;
30 import org.hipparchus.geometry.Space;
31 import org.hipparchus.geometry.Vector;
32 import org.hipparchus.util.FastMath;
33 import org.hipparchus.util.MathArrays;
34 import org.hipparchus.util.MathUtils;
35
36
37
38
39 public class Vector2D implements Vector<Euclidean2D, Vector2D> {
40
41
42 public static final Vector2D ZERO = new Vector2D(0, 0);
43
44
45
46
47 public static final Vector2D PLUS_I = new Vector2D(1, 0);
48
49
50
51
52 public static final Vector2D MINUS_I = new Vector2D(-1, 0);
53
54
55
56
57 public static final Vector2D PLUS_J = new Vector2D(0, 1);
58
59
60
61
62 public static final Vector2D MINUS_J = new Vector2D(0, -1);
63
64
65
66 public static final Vector2D NaN = new Vector2D(Double.NaN, Double.NaN);
67
68
69
70 public static final Vector2D POSITIVE_INFINITY =
71 new Vector2D(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
72
73
74 public static final Vector2D NEGATIVE_INFINITY =
75 new Vector2D(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY);
76
77
78 private static final long serialVersionUID = 266938651998679754L;
79
80
81 private final double x;
82
83
84 private final double y;
85
86
87
88
89
90
91
92
93 public Vector2D(double x, double y) {
94 this.x = x;
95 this.y = y;
96 }
97
98
99
100
101
102
103
104 public Vector2D(double[] v) throws MathIllegalArgumentException {
105 if (v.length != 2) {
106 throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
107 v.length, 2);
108 }
109 this.x = v[0];
110 this.y = v[1];
111 }
112
113
114
115
116
117
118
119 public Vector2D(double a, Vector2D u) {
120 this.x = a * u.x;
121 this.y = a * u.y;
122 }
123
124
125
126
127
128
129
130
131
132 public Vector2D(double a1, Vector2D u1, double a2, Vector2D u2) {
133 this.x = a1 * u1.x + a2 * u2.x;
134 this.y = a1 * u1.y + a2 * u2.y;
135 }
136
137
138
139
140
141
142
143
144
145
146
147 public Vector2D(double a1, Vector2D u1, double a2, Vector2D u2,
148 double a3, Vector2D u3) {
149 this.x = a1 * u1.x + a2 * u2.x + a3 * u3.x;
150 this.y = a1 * u1.y + a2 * u2.y + a3 * u3.y;
151 }
152
153
154
155
156
157
158
159
160
161
162
163
164
165 public Vector2D(double a1, Vector2D u1, double a2, Vector2D u2,
166 double a3, Vector2D u3, double a4, Vector2D u4) {
167 this.x = a1 * u1.x + a2 * u2.x + a3 * u3.x + a4 * u4.x;
168 this.y = a1 * u1.y + a2 * u2.y + a3 * u3.y + a4 * u4.y;
169 }
170
171
172
173
174
175 public double getX() {
176 return x;
177 }
178
179
180
181
182
183 public double getY() {
184 return y;
185 }
186
187
188
189
190
191 public double[] toArray() {
192 return new double[] { x, y };
193 }
194
195
196 @Override
197 public Space getSpace() {
198 return Euclidean2D.getInstance();
199 }
200
201
202 @Override
203 public Vector2D getZero() {
204 return ZERO;
205 }
206
207
208 @Override
209 public double getNorm1() {
210 return FastMath.abs(x) + FastMath.abs(y);
211 }
212
213
214 @Override
215 public double getNorm() {
216 return FastMath.sqrt (x * x + y * y);
217 }
218
219
220 @Override
221 public double getNormSq() {
222 return x * x + y * y;
223 }
224
225
226 @Override
227 public double getNormInf() {
228 return FastMath.max(FastMath.abs(x), FastMath.abs(y));
229 }
230
231
232 @Override
233 public Vector2D add(Vector<Euclidean2D, Vector2D> v) {
234 Vector2D v2 = (Vector2D) v;
235 return new Vector2D(x + v2.getX(), y + v2.getY());
236 }
237
238
239 @Override
240 public Vector2D add(double factor, Vector<Euclidean2D, Vector2D> v) {
241 Vector2D v2 = (Vector2D) v;
242 return new Vector2D(x + factor * v2.getX(), y + factor * v2.getY());
243 }
244
245
246 @Override
247 public Vector2D subtract(Vector<Euclidean2D, Vector2D> p) {
248 Vector2D p3 = (Vector2D) p;
249 return new Vector2D(x - p3.x, y - p3.y);
250 }
251
252
253 @Override
254 public Vector2D subtract(double factor, Vector<Euclidean2D, Vector2D> v) {
255 Vector2D v2 = (Vector2D) v;
256 return new Vector2D(x - factor * v2.getX(), y - factor * v2.getY());
257 }
258
259
260
261
262
263
264
265
266
267
268
269
270 public static double angle(Vector2D v1, Vector2D v2) throws MathRuntimeException {
271
272 double normProduct = v1.getNorm() * v2.getNorm();
273 if (normProduct == 0) {
274 throw new MathRuntimeException(LocalizedCoreFormats.ZERO_NORM);
275 }
276
277 double dot = v1.dotProduct(v2);
278 double threshold = normProduct * 0.9999;
279 if (FastMath.abs(dot) > threshold) {
280
281 final double n = FastMath.abs(MathArrays.linearCombination(v1.x, v2.y, -v1.y, v2.x));
282 if (dot >= 0) {
283 return FastMath.asin(n / normProduct);
284 }
285 return FastMath.PI - FastMath.asin(n / normProduct);
286 }
287
288
289 return FastMath.acos(dot / normProduct);
290
291 }
292
293
294 @Override
295 public Vector2D negate() {
296 return new Vector2D(-x, -y);
297 }
298
299
300 @Override
301 public Vector2D scalarMultiply(double a) {
302 return new Vector2D(a * x, a * y);
303 }
304
305
306 @Override
307 public boolean isNaN() {
308 return Double.isNaN(x) || Double.isNaN(y);
309 }
310
311
312 @Override
313 public boolean isInfinite() {
314 return !isNaN() && (Double.isInfinite(x) || Double.isInfinite(y));
315 }
316
317
318 @Override
319 public double distance1(Vector<Euclidean2D, Vector2D> p) {
320 Vector2D p3 = (Vector2D) p;
321 final double dx = FastMath.abs(p3.x - x);
322 final double dy = FastMath.abs(p3.y - y);
323 return dx + dy;
324 }
325
326
327 @Override
328 public double distance(Point<Euclidean2D> p) {
329 Vector2D p3 = (Vector2D) p;
330 final double dx = p3.x - x;
331 final double dy = p3.y - y;
332 return FastMath.sqrt(dx * dx + dy * dy);
333 }
334
335
336 @Override
337 public double distanceInf(Vector<Euclidean2D, Vector2D> p) {
338 Vector2D p3 = (Vector2D) p;
339 final double dx = FastMath.abs(p3.x - x);
340 final double dy = FastMath.abs(p3.y - y);
341 return FastMath.max(dx, dy);
342 }
343
344
345 @Override
346 public double distanceSq(Vector<Euclidean2D, Vector2D> p) {
347 Vector2D p3 = (Vector2D) p;
348 final double dx = p3.x - x;
349 final double dy = p3.y - y;
350 return dx * dx + dy * dy;
351 }
352
353
354 @Override
355 public double dotProduct(final Vector<Euclidean2D, Vector2D> v) {
356 final Vector2D v2 = (Vector2D) v;
357 return MathArrays.linearCombination(x, v2.x, y, v2.y);
358 }
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380 public double crossProduct(final Vector2D p1, final Vector2D p2) {
381 final double x1 = p2.getX() - p1.getX();
382 final double y1 = getY() - p1.getY();
383 final double x2 = getX() - p1.getX();
384 final double y2 = p2.getY() - p1.getY();
385 return MathArrays.linearCombination(x1, y1, -x2, y2);
386 }
387
388
389
390
391
392
393
394
395
396
397 public static double distance1(Vector2D p1, Vector2D p2) {
398 return p1.distance1(p2);
399 }
400
401
402
403
404
405
406
407
408
409 public static double distance(Vector2D p1, Vector2D p2) {
410 return p1.distance(p2);
411 }
412
413
414
415
416
417
418
419
420
421 public static double distanceInf(Vector2D p1, Vector2D p2) {
422 return p1.distanceInf(p2);
423 }
424
425
426
427
428
429
430
431
432
433 public static double distanceSq(Vector2D p1, Vector2D p2) {
434 return p1.distanceSq(p2);
435 }
436
437
438
439
440
441
442
443
444
445
446 public static double orientation(final Vector2D p, final Vector2D q, final Vector2D r) {
447 return MathArrays.linearCombination(new double[] {
448 p.getX(), -p.getX(), q.getX(), -q.getX(), r.getX(), -r.getX()
449 }, new double[] {
450 q.getY(), r.getY(), r.getY(), p.getY(), p.getY(), q.getY()
451 });
452 }
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472 @Override
473 public boolean equals(Object other) {
474
475 if (this == other) {
476 return true;
477 }
478
479 if (other instanceof Vector2D) {
480 final Vector2D rhs = (Vector2D)other;
481 return x == rhs.x && y == rhs.y || isNaN() && rhs.isNaN();
482 }
483
484 return false;
485
486 }
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507 public boolean equalsIeee754(Object other) {
508
509 if (this == other && !isNaN()) {
510 return true;
511 }
512
513 if (other instanceof Vector2D) {
514 final Vector2D rhs = (Vector2D) other;
515 return x == rhs.x && y == rhs.y;
516 }
517 return false;
518 }
519
520
521
522
523
524
525
526
527 @Override
528 public int hashCode() {
529 if (isNaN()) {
530 return 542;
531 }
532 return 122 * (76 * MathUtils.hash(x) + MathUtils.hash(y));
533 }
534
535
536
537
538 @Override
539 public String toString() {
540 return Vector2DFormat.getVector2DFormat().format(this);
541 }
542
543
544 @Override
545 public String toString(final NumberFormat format) {
546 return new Vector2DFormat(format).format(this);
547 }
548
549 }