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