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
23 package org.hipparchus.geometry.euclidean.threed;
24
25 import java.io.Serializable;
26 import java.text.NumberFormat;
27
28 import org.hipparchus.CalculusFieldElement;
29 import org.hipparchus.Field;
30 import org.hipparchus.analysis.polynomials.SmoothStepFactory;
31 import org.hipparchus.exception.LocalizedCoreFormats;
32 import org.hipparchus.exception.MathIllegalArgumentException;
33 import org.hipparchus.exception.MathRuntimeException;
34 import org.hipparchus.geometry.LocalizedGeometryFormats;
35 import org.hipparchus.util.FastMath;
36 import org.hipparchus.util.FieldBlendable;
37 import org.hipparchus.util.FieldSinCos;
38 import org.hipparchus.util.MathArrays;
39
40 /**
41 * This class is a re-implementation of {@link Vector3D} using {@link CalculusFieldElement}.
42 * <p>Instance of this class are guaranteed to be immutable.</p>
43 * @param <T> the type of the field elements
44 */
45 public class FieldVector3D<T extends CalculusFieldElement<T>> implements FieldBlendable<FieldVector3D<T>, T>, Serializable {
46
47 /** Serializable version identifier. */
48 private static final long serialVersionUID = 20130224L;
49
50 /** Abscissa. */
51 private final T x;
52
53 /** Ordinate. */
54 private final T y;
55
56 /** Height. */
57 private final T z;
58
59 /** Simple constructor.
60 * Build a vector from its coordinates
61 * @param x abscissa
62 * @param y ordinate
63 * @param z height
64 * @see #getX()
65 * @see #getY()
66 * @see #getZ()
67 */
68 public FieldVector3D(final T x, final T y, final T z) {
69 this.x = x;
70 this.y = y;
71 this.z = z;
72 }
73
74 /** Simple constructor.
75 * Build a vector from its coordinates
76 * @param v coordinates array
77 * @exception MathIllegalArgumentException if array does not have 3 elements
78 * @see #toArray()
79 */
80 public FieldVector3D(final T[] v) throws MathIllegalArgumentException {
81 if (v.length != 3) {
82 throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
83 v.length, 3);
84 }
85 this.x = v[0];
86 this.y = v[1];
87 this.z = v[2];
88 }
89
90 /** Simple constructor.
91 * Build a vector from its azimuthal coordinates
92 * @param alpha azimuth (α) around Z
93 * (0 is +X, π/2 is +Y, π is -X and 3π/2 is -Y)
94 * @param delta elevation (δ) above (XY) plane, from -π/2 to +π/2
95 * @see #getAlpha()
96 * @see #getDelta()
97 */
98 public FieldVector3D(final T alpha, final T delta) {
99 FieldSinCos<T> sinCosAlpha = FastMath.sinCos(alpha);
100 FieldSinCos<T> sinCosDelta = FastMath.sinCos(delta);
101 this.x = sinCosAlpha.cos().multiply(sinCosDelta.cos());
102 this.y = sinCosAlpha.sin().multiply(sinCosDelta.cos());
103 this.z = sinCosDelta.sin();
104 }
105
106 /** Multiplicative constructor.
107 * Build a vector from another one and a scale factor.
108 * The vector built will be a * u
109 * @param a scale factor
110 * @param u base (unscaled) vector
111 */
112 public FieldVector3D(final T a, final FieldVector3D<T>u) {
113 this.x = a.multiply(u.x);
114 this.y = a.multiply(u.y);
115 this.z = a.multiply(u.z);
116 }
117
118 /** Multiplicative constructor.
119 * Build a vector from another one and a scale factor.
120 * The vector built will be a * u
121 * @param a scale factor
122 * @param u base (unscaled) vector
123 */
124 public FieldVector3D(final T a, final Vector3D u) {
125 this.x = a.multiply(u.getX());
126 this.y = a.multiply(u.getY());
127 this.z = a.multiply(u.getZ());
128 }
129
130 /** Multiplicative constructor.
131 * Build a vector from another one and a scale factor.
132 * The vector built will be a * u
133 * @param a scale factor
134 * @param u base (unscaled) vector
135 */
136 public FieldVector3D(final double a, final FieldVector3D<T> u) {
137 this.x = u.x.multiply(a);
138 this.y = u.y.multiply(a);
139 this.z = u.z.multiply(a);
140 }
141
142 /** Linear constructor.
143 * Build a vector from two other ones and corresponding scale factors.
144 * The vector built will be a1 * u1 + a2 * u2
145 * @param a1 first scale factor
146 * @param u1 first base (unscaled) vector
147 * @param a2 second scale factor
148 * @param u2 second base (unscaled) vector
149 */
150 public FieldVector3D(final T a1, final FieldVector3D<T> u1,
151 final T a2, final FieldVector3D<T> u2) {
152 final T prototype = a1;
153 this.x = prototype.linearCombination(a1, u1.getX(), a2, u2.getX());
154 this.y = prototype.linearCombination(a1, u1.getY(), a2, u2.getY());
155 this.z = prototype.linearCombination(a1, u1.getZ(), a2, u2.getZ());
156 }
157
158 /** Linear constructor.
159 * Build a vector from two other ones and corresponding scale factors.
160 * The vector built will be a1 * u1 + a2 * u2
161 * @param a1 first scale factor
162 * @param u1 first base (unscaled) vector
163 * @param a2 second scale factor
164 * @param u2 second base (unscaled) vector
165 */
166 public FieldVector3D(final T a1, final Vector3D u1,
167 final T a2, final Vector3D u2) {
168 final T prototype = a1;
169 this.x = prototype.linearCombination(u1.getX(), a1, u2.getX(), a2);
170 this.y = prototype.linearCombination(u1.getY(), a1, u2.getY(), a2);
171 this.z = prototype.linearCombination(u1.getZ(), a1, u2.getZ(), a2);
172 }
173
174 /** Linear constructor.
175 * Build a vector from two other ones and corresponding scale factors.
176 * The vector built will be a1 * u1 + a2 * u2
177 * @param a1 first scale factor
178 * @param u1 first base (unscaled) vector
179 * @param a2 second scale factor
180 * @param u2 second base (unscaled) vector
181 */
182 public FieldVector3D(final double a1, final FieldVector3D<T> u1,
183 final double a2, final FieldVector3D<T> u2) {
184 final T prototype = u1.getX();
185 this.x = prototype.linearCombination(a1, u1.getX(), a2, u2.getX());
186 this.y = prototype.linearCombination(a1, u1.getY(), a2, u2.getY());
187 this.z = prototype.linearCombination(a1, u1.getZ(), a2, u2.getZ());
188 }
189
190 /** Linear constructor.
191 * Build a vector from three other ones and corresponding scale factors.
192 * The vector built will be a1 * u1 + a2 * u2 + a3 * u3
193 * @param a1 first scale factor
194 * @param u1 first base (unscaled) vector
195 * @param a2 second scale factor
196 * @param u2 second base (unscaled) vector
197 * @param a3 third scale factor
198 * @param u3 third base (unscaled) vector
199 */
200 public FieldVector3D(final T a1, final FieldVector3D<T> u1,
201 final T a2, final FieldVector3D<T> u2,
202 final T a3, final FieldVector3D<T> u3) {
203 final T prototype = a1;
204 this.x = prototype.linearCombination(a1, u1.getX(), a2, u2.getX(), a3, u3.getX());
205 this.y = prototype.linearCombination(a1, u1.getY(), a2, u2.getY(), a3, u3.getY());
206 this.z = prototype.linearCombination(a1, u1.getZ(), a2, u2.getZ(), a3, u3.getZ());
207 }
208
209 /** Linear constructor.
210 * Build a vector from three other ones and corresponding scale factors.
211 * The vector built will be a1 * u1 + a2 * u2 + a3 * u3
212 * @param a1 first scale factor
213 * @param u1 first base (unscaled) vector
214 * @param a2 second scale factor
215 * @param u2 second base (unscaled) vector
216 * @param a3 third scale factor
217 * @param u3 third base (unscaled) vector
218 */
219 public FieldVector3D(final T a1, final Vector3D u1,
220 final T a2, final Vector3D u2,
221 final T a3, final Vector3D u3) {
222 final T prototype = a1;
223 this.x = prototype.linearCombination(u1.getX(), a1, u2.getX(), a2, u3.getX(), a3);
224 this.y = prototype.linearCombination(u1.getY(), a1, u2.getY(), a2, u3.getY(), a3);
225 this.z = prototype.linearCombination(u1.getZ(), a1, u2.getZ(), a2, u3.getZ(), a3);
226 }
227
228 /** Linear constructor.
229 * Build a vector from three other ones and corresponding scale factors.
230 * The vector built will be a1 * u1 + a2 * u2 + a3 * u3
231 * @param a1 first scale factor
232 * @param u1 first base (unscaled) vector
233 * @param a2 second scale factor
234 * @param u2 second base (unscaled) vector
235 * @param a3 third scale factor
236 * @param u3 third base (unscaled) vector
237 */
238 public FieldVector3D(final double a1, final FieldVector3D<T> u1,
239 final double a2, final FieldVector3D<T> u2,
240 final double a3, final FieldVector3D<T> u3) {
241 final T prototype = u1.getX();
242 this.x = prototype.linearCombination(a1, u1.getX(), a2, u2.getX(), a3, u3.getX());
243 this.y = prototype.linearCombination(a1, u1.getY(), a2, u2.getY(), a3, u3.getY());
244 this.z = prototype.linearCombination(a1, u1.getZ(), a2, u2.getZ(), a3, u3.getZ());
245 }
246
247 /** Linear constructor.
248 * Build a vector from four other ones and corresponding scale factors.
249 * The vector built will be a1 * u1 + a2 * u2 + a3 * u3 + a4 * u4
250 * @param a1 first scale factor
251 * @param u1 first base (unscaled) vector
252 * @param a2 second scale factor
253 * @param u2 second base (unscaled) vector
254 * @param a3 third scale factor
255 * @param u3 third base (unscaled) vector
256 * @param a4 fourth scale factor
257 * @param u4 fourth base (unscaled) vector
258 */
259 public FieldVector3D(final T a1, final FieldVector3D<T> u1,
260 final T a2, final FieldVector3D<T> u2,
261 final T a3, final FieldVector3D<T> u3,
262 final T a4, final FieldVector3D<T> u4) {
263 final T prototype = a1;
264 this.x = prototype.linearCombination(a1, u1.getX(), a2, u2.getX(), a3, u3.getX(), a4, u4.getX());
265 this.y = prototype.linearCombination(a1, u1.getY(), a2, u2.getY(), a3, u3.getY(), a4, u4.getY());
266 this.z = prototype.linearCombination(a1, u1.getZ(), a2, u2.getZ(), a3, u3.getZ(), a4, u4.getZ());
267 }
268
269 /** Linear constructor.
270 * Build a vector from four other ones and corresponding scale factors.
271 * The vector built will be a1 * u1 + a2 * u2 + a3 * u3 + a4 * u4
272 * @param a1 first scale factor
273 * @param u1 first base (unscaled) vector
274 * @param a2 second scale factor
275 * @param u2 second base (unscaled) vector
276 * @param a3 third scale factor
277 * @param u3 third base (unscaled) vector
278 * @param a4 fourth scale factor
279 * @param u4 fourth base (unscaled) vector
280 */
281 public FieldVector3D(final T a1, final Vector3D u1,
282 final T a2, final Vector3D u2,
283 final T a3, final Vector3D u3,
284 final T a4, final Vector3D u4) {
285 final T prototype = a1;
286 this.x = prototype.linearCombination(u1.getX(), a1, u2.getX(), a2, u3.getX(), a3, u4.getX(), a4);
287 this.y = prototype.linearCombination(u1.getY(), a1, u2.getY(), a2, u3.getY(), a3, u4.getY(), a4);
288 this.z = prototype.linearCombination(u1.getZ(), a1, u2.getZ(), a2, u3.getZ(), a3, u4.getZ(), a4);
289 }
290
291 /** Linear constructor.
292 * Build a vector from four other ones and corresponding scale factors.
293 * The vector built will be a1 * u1 + a2 * u2 + a3 * u3 + a4 * u4
294 * @param a1 first scale factor
295 * @param u1 first base (unscaled) vector
296 * @param a2 second scale factor
297 * @param u2 second base (unscaled) vector
298 * @param a3 third scale factor
299 * @param u3 third base (unscaled) vector
300 * @param a4 fourth scale factor
301 * @param u4 fourth base (unscaled) vector
302 */
303 public FieldVector3D(final double a1, final FieldVector3D<T> u1,
304 final double a2, final FieldVector3D<T> u2,
305 final double a3, final FieldVector3D<T> u3,
306 final double a4, final FieldVector3D<T> u4) {
307 final T prototype = u1.getX();
308 this.x = prototype.linearCombination(a1, u1.getX(), a2, u2.getX(), a3, u3.getX(), a4, u4.getX());
309 this.y = prototype.linearCombination(a1, u1.getY(), a2, u2.getY(), a3, u3.getY(), a4, u4.getY());
310 this.z = prototype.linearCombination(a1, u1.getZ(), a2, u2.getZ(), a3, u3.getZ(), a4, u4.getZ());
311 }
312
313 /** Build a {@link FieldVector3D} from a {@link Vector3D}.
314 * @param field field for the components
315 * @param v vector to convert
316 */
317 public FieldVector3D(final Field<T> field, final Vector3D v) {
318 this.x = field.getZero().add(v.getX());
319 this.y = field.getZero().add(v.getY());
320 this.z = field.getZero().add(v.getZ());
321 }
322
323 /** Get null vector (coordinates: 0, 0, 0).
324 * @param field field for the components
325 * @return a new vector
326 * @param <T> the type of the field elements
327 */
328 public static <T extends CalculusFieldElement<T>> FieldVector3D<T> getZero(final Field<T> field) {
329 return new FieldVector3D<>(field, Vector3D.ZERO);
330 }
331
332 /** Get first canonical vector (coordinates: 1, 0, 0).
333 * @param field field for the components
334 * @return a new vector
335 * @param <T> the type of the field elements
336 */
337 public static <T extends CalculusFieldElement<T>> FieldVector3D<T> getPlusI(final Field<T> field) {
338 return new FieldVector3D<>(field, Vector3D.PLUS_I);
339 }
340
341 /** Get opposite of the first canonical vector (coordinates: -1, 0, 0).
342 * @param field field for the components
343 * @return a new vector
344 * @param <T> the type of the field elements
345 */
346 public static <T extends CalculusFieldElement<T>> FieldVector3D<T> getMinusI(final Field<T> field) {
347 return new FieldVector3D<>(field, Vector3D.MINUS_I);
348 }
349
350 /** Get second canonical vector (coordinates: 0, 1, 0).
351 * @param field field for the components
352 * @return a new vector
353 * @param <T> the type of the field elements
354 */
355 public static <T extends CalculusFieldElement<T>> FieldVector3D<T> getPlusJ(final Field<T> field) {
356 return new FieldVector3D<>(field, Vector3D.PLUS_J);
357 }
358
359 /** Get opposite of the second canonical vector (coordinates: 0, -1, 0).
360 * @param field field for the components
361 * @return a new vector
362 * @param <T> the type of the field elements
363 */
364 public static <T extends CalculusFieldElement<T>> FieldVector3D<T> getMinusJ(final Field<T> field) {
365 return new FieldVector3D<>(field, Vector3D.MINUS_J);
366 }
367
368 /** Get third canonical vector (coordinates: 0, 0, 1).
369 * @param field field for the components
370 * @return a new vector
371 * @param <T> the type of the field elements
372 */
373 public static <T extends CalculusFieldElement<T>> FieldVector3D<T> getPlusK(final Field<T> field) {
374 return new FieldVector3D<>(field, Vector3D.PLUS_K);
375 }
376
377 /** Get opposite of the third canonical vector (coordinates: 0, 0, -1).
378 * @param field field for the components
379 * @return a new vector
380 * @param <T> the type of the field elements
381 */
382 public static <T extends CalculusFieldElement<T>> FieldVector3D<T> getMinusK(final Field<T> field) {
383 return new FieldVector3D<>(field, Vector3D.MINUS_K);
384 }
385
386 /** Get a vector with all coordinates set to NaN.
387 * @param field field for the components
388 * @return a new vector
389 * @param <T> the type of the field elements
390 */
391 public static <T extends CalculusFieldElement<T>> FieldVector3D<T> getNaN(final Field<T> field) {
392 return new FieldVector3D<>(field, Vector3D.NaN);
393 }
394
395 /** Get a vector with all coordinates set to positive infinity.
396 * @param field field for the components
397 * @return a new vector
398 * @param <T> the type of the field elements
399 */
400 public static <T extends CalculusFieldElement<T>> FieldVector3D<T> getPositiveInfinity(final Field<T> field) {
401 return new FieldVector3D<>(field, Vector3D.POSITIVE_INFINITY);
402 }
403
404 /** Get a vector with all coordinates set to negative infinity.
405 * @param field field for the components
406 * @return a new vector
407 * @param <T> the type of the field elements
408 */
409 public static <T extends CalculusFieldElement<T>> FieldVector3D<T> getNegativeInfinity(final Field<T> field) {
410 return new FieldVector3D<>(field, Vector3D.NEGATIVE_INFINITY);
411 }
412
413 /** Get the abscissa of the vector.
414 * @return abscissa of the vector
415 * @see #FieldVector3D(CalculusFieldElement, CalculusFieldElement, CalculusFieldElement)
416 */
417 public T getX() {
418 return x;
419 }
420
421 /** Get the ordinate of the vector.
422 * @return ordinate of the vector
423 * @see #FieldVector3D(CalculusFieldElement, CalculusFieldElement, CalculusFieldElement)
424 */
425 public T getY() {
426 return y;
427 }
428
429 /** Get the height of the vector.
430 * @return height of the vector
431 * @see #FieldVector3D(CalculusFieldElement, CalculusFieldElement, CalculusFieldElement)
432 */
433 public T getZ() {
434 return z;
435 }
436
437 /** Get the vector coordinates as a dimension 3 array.
438 * @return vector coordinates
439 * @see #FieldVector3D(CalculusFieldElement[])
440 */
441 public T[] toArray() {
442 final T[] array = MathArrays.buildArray(x.getField(), 3);
443 array[0] = x;
444 array[1] = y;
445 array[2] = z;
446 return array;
447 }
448
449 /** Convert to a constant vector without extra field parts.
450 * @return a constant vector
451 */
452 public Vector3D toVector3D() {
453 return new Vector3D(x.getReal(), y.getReal(), z.getReal());
454 }
455
456 /** Get the L<sub>1</sub> norm for the vector.
457 * @return L<sub>1</sub> norm for the vector
458 */
459 public T getNorm1() {
460 return x.abs().add(y.abs()).add(z.abs());
461 }
462
463 /** Get the L<sub>2</sub> norm for the vector.
464 * @return Euclidean norm for the vector
465 */
466 public T getNorm() {
467 // there are no cancellation problems here, so we use the straightforward formula
468 return x.square().add(y.square()).add(z.square()).sqrt();
469 }
470
471 /** Get the square of the norm for the vector.
472 * @return square of the Euclidean norm for the vector
473 */
474 public T getNormSq() {
475 // there are no cancellation problems here, so we use the straightforward formula
476 return x.square().add(y.square()).add(z.square());
477 }
478
479 /** Get the L<sub>∞</sub> norm for the vector.
480 * @return L<sub>∞</sub> norm for the vector
481 */
482 public T getNormInf() {
483 return FastMath.max(FastMath.abs(x), FastMath.max(FastMath.abs(y), FastMath.abs(z)));
484 }
485
486 /** Get the azimuth of the vector.
487 * @return azimuth (α) of the vector, between -π and +π
488 * @see #FieldVector3D(CalculusFieldElement, CalculusFieldElement)
489 */
490 public T getAlpha() {
491 return y.atan2(x);
492 }
493
494 /** Get the elevation of the vector.
495 * @return elevation (δ) of the vector, between -π/2 and +π/2
496 * @see #FieldVector3D(CalculusFieldElement, CalculusFieldElement)
497 */
498 public T getDelta() {
499 return z.divide(getNorm()).asin();
500 }
501
502 /** Add a vector to the instance.
503 * @param v vector to add
504 * @return a new vector
505 */
506 public FieldVector3D<T> add(final FieldVector3D<T> v) {
507 return new FieldVector3D<T>(x.add(v.x), y.add(v.y), z.add(v.z));
508 }
509
510 /** Add a vector to the instance.
511 * @param v vector to add
512 * @return a new vector
513 */
514 public FieldVector3D<T> add(final Vector3D v) {
515 return new FieldVector3D<T>(x.add(v.getX()), y.add(v.getY()), z.add(v.getZ()));
516 }
517
518 /** Add a scaled vector to the instance.
519 * @param factor scale factor to apply to v before adding it
520 * @param v vector to add
521 * @return a new vector
522 */
523 public FieldVector3D<T> add(final T factor, final FieldVector3D<T> v) {
524 return new FieldVector3D<T>(x.getField().getOne(), this, factor, v);
525 }
526
527 /** Add a scaled vector to the instance.
528 * @param factor scale factor to apply to v before adding it
529 * @param v vector to add
530 * @return a new vector
531 */
532 public FieldVector3D<T> add(final T factor, final Vector3D v) {
533 return new FieldVector3D<T>(x.add(factor.multiply(v.getX())),
534 y.add(factor.multiply(v.getY())),
535 z.add(factor.multiply(v.getZ())));
536 }
537
538 /** Add a scaled vector to the instance.
539 * @param factor scale factor to apply to v before adding it
540 * @param v vector to add
541 * @return a new vector
542 */
543 public FieldVector3D<T> add(final double factor, final FieldVector3D<T> v) {
544 return new FieldVector3D<T>(1.0, this, factor, v);
545 }
546
547 /** Add a scaled vector to the instance.
548 * @param factor scale factor to apply to v before adding it
549 * @param v vector to add
550 * @return a new vector
551 */
552 public FieldVector3D<T> add(final double factor, final Vector3D v) {
553 return new FieldVector3D<T>(x.add(factor * v.getX()),
554 y.add(factor * v.getY()),
555 z.add(factor * v.getZ()));
556 }
557
558 /** Subtract a vector from the instance.
559 * @param v vector to subtract
560 * @return a new vector
561 */
562 public FieldVector3D<T> subtract(final FieldVector3D<T> v) {
563 return new FieldVector3D<T>(x.subtract(v.x), y.subtract(v.y), z.subtract(v.z));
564 }
565
566 /** Subtract a vector from the instance.
567 * @param v vector to subtract
568 * @return a new vector
569 */
570 public FieldVector3D<T> subtract(final Vector3D v) {
571 return new FieldVector3D<T>(x.subtract(v.getX()), y.subtract(v.getY()), z.subtract(v.getZ()));
572 }
573
574 /** Subtract a scaled vector from the instance.
575 * @param factor scale factor to apply to v before subtracting it
576 * @param v vector to subtract
577 * @return a new vector
578 */
579 public FieldVector3D<T> subtract(final T factor, final FieldVector3D<T> v) {
580 return new FieldVector3D<T>(x.getField().getOne(), this, factor.negate(), v);
581 }
582
583 /** Subtract a scaled vector from the instance.
584 * @param factor scale factor to apply to v before subtracting it
585 * @param v vector to subtract
586 * @return a new vector
587 */
588 public FieldVector3D<T> subtract(final T factor, final Vector3D v) {
589 return new FieldVector3D<T>(x.subtract(factor.multiply(v.getX())),
590 y.subtract(factor.multiply(v.getY())),
591 z.subtract(factor.multiply(v.getZ())));
592 }
593
594 /** Subtract a scaled vector from the instance.
595 * @param factor scale factor to apply to v before subtracting it
596 * @param v vector to subtract
597 * @return a new vector
598 */
599 public FieldVector3D<T> subtract(final double factor, final FieldVector3D<T> v) {
600 return new FieldVector3D<T>(1.0, this, -factor, v);
601 }
602
603 /** Subtract a scaled vector from the instance.
604 * @param factor scale factor to apply to v before subtracting it
605 * @param v vector to subtract
606 * @return a new vector
607 */
608 public FieldVector3D<T> subtract(final double factor, final Vector3D v) {
609 return new FieldVector3D<T>(x.subtract(factor * v.getX()),
610 y.subtract(factor * v.getY()),
611 z.subtract(factor * v.getZ()));
612 }
613
614 /** Get a normalized vector aligned with the instance.
615 * @return a new normalized vector
616 * @exception MathRuntimeException if the norm is zero
617 */
618 public FieldVector3D<T> normalize() throws MathRuntimeException {
619 final T s = getNorm();
620 if (s.getReal() == 0) {
621 throw new MathRuntimeException(LocalizedGeometryFormats.CANNOT_NORMALIZE_A_ZERO_NORM_VECTOR);
622 }
623 return scalarMultiply(s.reciprocal());
624 }
625
626 /** Get a vector orthogonal to the instance.
627 * <p>There are an infinite number of normalized vectors orthogonal
628 * to the instance. This method picks up one of them almost
629 * arbitrarily. It is useful when one needs to compute a reference
630 * frame with one of the axes in a predefined direction. The
631 * following example shows how to build a frame having the k axis
632 * aligned with the known vector u :
633 * </p>
634 * <pre><code>
635 * Vector3D k = u.normalize();
636 * Vector3D i = k.orthogonal();
637 * Vector3D j = Vector3D.crossProduct(k, i);
638 * </code></pre>
639 * @return a new normalized vector orthogonal to the instance
640 * @exception MathRuntimeException if the norm of the instance is null
641 */
642 public FieldVector3D<T> orthogonal() throws MathRuntimeException {
643
644 final double threshold = 0.6 * getNorm().getReal();
645 if (threshold == 0) {
646 throw new MathRuntimeException(LocalizedCoreFormats.ZERO_NORM);
647 }
648
649 if (FastMath.abs(x.getReal()) <= threshold) {
650 final T inverse = y.square().add(z.square()).sqrt().reciprocal();
651 return new FieldVector3D<T>(inverse.getField().getZero(), inverse.multiply(z), inverse.multiply(y).negate());
652 } else if (FastMath.abs(y.getReal()) <= threshold) {
653 final T inverse = x.square().add(z.square()).sqrt().reciprocal();
654 return new FieldVector3D<T>(inverse.multiply(z).negate(), inverse.getField().getZero(), inverse.multiply(x));
655 } else {
656 final T inverse = x.square().add(y.square()).sqrt().reciprocal();
657 return new FieldVector3D<T>(inverse.multiply(y), inverse.multiply(x).negate(), inverse.getField().getZero());
658 }
659
660 }
661
662 /** Compute the angular separation between two vectors.
663 * <p>This method computes the angular separation between two
664 * vectors using the dot product for well separated vectors and the
665 * cross product for almost aligned vectors. This allows to have a
666 * good accuracy in all cases, even for vectors very close to each
667 * other.</p>
668 * @param v1 first vector
669 * @param v2 second vector
670 * @param <T> the type of the field elements
671 * @return angular separation between v1 and v2
672 * @exception MathRuntimeException if either vector has a null norm
673 */
674 public static <T extends CalculusFieldElement<T>> T angle(final FieldVector3D<T> v1, final FieldVector3D<T> v2)
675 throws MathRuntimeException {
676
677 final T normProduct = v1.getNorm().multiply(v2.getNorm());
678 if (normProduct.getReal() == 0) {
679 throw new MathRuntimeException(LocalizedCoreFormats.ZERO_NORM);
680 }
681
682 final T dot = dotProduct(v1, v2);
683 final double threshold = normProduct.getReal() * 0.9999;
684 if ((dot.getReal() < -threshold) || (dot.getReal() > threshold)) {
685 // the vectors are almost aligned, compute using the sine
686 FieldVector3D<T> v3 = crossProduct(v1, v2);
687 if (dot.getReal() >= 0) {
688 return v3.getNorm().divide(normProduct).asin();
689 }
690 return v3.getNorm().divide(normProduct).asin().subtract(dot.getPi()).negate();
691 }
692
693 // the vectors are sufficiently separated to use the cosine
694 return dot.divide(normProduct).acos();
695
696 }
697
698 /** Compute the angular separation between two vectors.
699 * <p>This method computes the angular separation between two
700 * vectors using the dot product for well separated vectors and the
701 * cross product for almost aligned vectors. This allows to have a
702 * good accuracy in all cases, even for vectors very close to each
703 * other.</p>
704 * @param v1 first vector
705 * @param v2 second vector
706 * @param <T> the type of the field elements
707 * @return angular separation between v1 and v2
708 * @exception MathRuntimeException if either vector has a null norm
709 */
710 public static <T extends CalculusFieldElement<T>> T angle(final FieldVector3D<T> v1, final Vector3D v2)
711 throws MathRuntimeException {
712
713 final T normProduct = v1.getNorm().multiply(v2.getNorm());
714 if (normProduct.getReal() == 0) {
715 throw new MathRuntimeException(LocalizedCoreFormats.ZERO_NORM);
716 }
717
718 final T dot = dotProduct(v1, v2);
719 final double threshold = normProduct.getReal() * 0.9999;
720 if ((dot.getReal() < -threshold) || (dot.getReal() > threshold)) {
721 // the vectors are almost aligned, compute using the sine
722 FieldVector3D<T> v3 = crossProduct(v1, v2);
723 if (dot.getReal() >= 0) {
724 return v3.getNorm().divide(normProduct).asin();
725 }
726 return v3.getNorm().divide(normProduct).asin().subtract(dot.getPi()).negate();
727 }
728
729 // the vectors are sufficiently separated to use the cosine
730 return dot.divide(normProduct).acos();
731
732 }
733
734 /** Compute the angular separation between two vectors.
735 * <p>This method computes the angular separation between two
736 * vectors using the dot product for well separated vectors and the
737 * cross product for almost aligned vectors. This allows to have a
738 * good accuracy in all cases, even for vectors very close to each
739 * other.</p>
740 * @param v1 first vector
741 * @param v2 second vector
742 * @param <T> the type of the field elements
743 * @return angular separation between v1 and v2
744 * @exception MathRuntimeException if either vector has a null norm
745 */
746 public static <T extends CalculusFieldElement<T>> T angle(final Vector3D v1, final FieldVector3D<T> v2)
747 throws MathRuntimeException {
748 return angle(v2, v1);
749 }
750
751 /** Get the opposite of the instance.
752 * @return a new vector which is opposite to the instance
753 */
754 public FieldVector3D<T> negate() {
755 return new FieldVector3D<T>(x.negate(), y.negate(), z.negate());
756 }
757
758 /** Multiply the instance by a scalar.
759 * @param a scalar
760 * @return a new vector
761 */
762 public FieldVector3D<T> scalarMultiply(final T a) {
763 return new FieldVector3D<T>(x.multiply(a), y.multiply(a), z.multiply(a));
764 }
765
766 /** Multiply the instance by a scalar.
767 * @param a scalar
768 * @return a new vector
769 */
770 public FieldVector3D<T> scalarMultiply(final double a) {
771 return new FieldVector3D<T>(x.multiply(a), y.multiply(a), z.multiply(a));
772 }
773
774 /**
775 * Returns true if any coordinate of this vector is NaN; false otherwise
776 * @return true if any coordinate of this vector is NaN; false otherwise
777 */
778 public boolean isNaN() {
779 return Double.isNaN(x.getReal()) || Double.isNaN(y.getReal()) || Double.isNaN(z.getReal());
780 }
781
782 /**
783 * Returns true if any coordinate of this vector is infinite and none are NaN;
784 * false otherwise
785 * @return true if any coordinate of this vector is infinite and none are NaN;
786 * false otherwise
787 */
788 public boolean isInfinite() {
789 return !isNaN() && (Double.isInfinite(x.getReal()) || Double.isInfinite(y.getReal()) || Double.isInfinite(z.getReal()));
790 }
791
792 /**
793 * Test for the equality of two 3D vectors.
794 * <p>
795 * If all coordinates of two 3D vectors are exactly the same, and none of their
796 * {@link CalculusFieldElement#getReal() real part} are <code>NaN</code>, the
797 * two 3D vectors are considered to be equal.
798 * </p>
799 * <p>
800 * <code>NaN</code> coordinates are considered to affect globally the vector
801 * and be equals to each other - i.e, if either (or all) real part of the
802 * coordinates of the 3D vector are <code>NaN</code>, the 3D vector is <code>NaN</code>.
803 * </p>
804 *
805 * @param other Object to test for equality to this
806 * @return true if two 3D vector objects are equal, false if
807 * object is null, not an instance of FieldVector3D, or
808 * not equal to this FieldVector3D instance
809 *
810 */
811 @Override
812 public boolean equals(Object other) {
813
814 if (this == other) {
815 return true;
816 }
817
818 if (other instanceof FieldVector3D) {
819 @SuppressWarnings("unchecked")
820 final FieldVector3D<T> rhs = (FieldVector3D<T>) other;
821 if (rhs.isNaN()) {
822 return this.isNaN();
823 }
824
825 return x.equals(rhs.x) && y.equals(rhs.y) && z.equals(rhs.z);
826
827 }
828 return false;
829 }
830
831 /**
832 * Get a hashCode for the 3D vector.
833 * <p>
834 * All NaN values have the same hash code.</p>
835 *
836 * @return a hash code value for this object
837 */
838 @Override
839 public int hashCode() {
840 if (isNaN()) {
841 return 409;
842 }
843 return 311 * (107 * x.hashCode() + 83 * y.hashCode() + z.hashCode());
844 }
845
846 /** Compute the dot-product of the instance and another vector.
847 * <p>
848 * The implementation uses specific multiplication and addition
849 * algorithms to preserve accuracy and reduce cancellation effects.
850 * It should be very accurate even for nearly orthogonal vectors.
851 * </p>
852 * @see MathArrays#linearCombination(double, double, double, double, double, double)
853 * @param v second vector
854 * @return the dot product this.v
855 */
856 public T dotProduct(final FieldVector3D<T> v) {
857 return x.linearCombination(x, v.x, y, v.y, z, v.z);
858 }
859
860 /** Compute the dot-product of the instance and another vector.
861 * <p>
862 * The implementation uses specific multiplication and addition
863 * algorithms to preserve accuracy and reduce cancellation effects.
864 * It should be very accurate even for nearly orthogonal vectors.
865 * </p>
866 * @see MathArrays#linearCombination(double, double, double, double, double, double)
867 * @param v second vector
868 * @return the dot product this.v
869 */
870 public T dotProduct(final Vector3D v) {
871 return x.linearCombination(v.getX(), x, v.getY(), y, v.getZ(), z);
872 }
873
874 /** Compute the cross-product of the instance with another vector.
875 * @param v other vector
876 * @return the cross product this ^ v as a new Vector3D
877 */
878 public FieldVector3D<T> crossProduct(final FieldVector3D<T> v) {
879 return new FieldVector3D<T>(x.linearCombination(y, v.z, z.negate(), v.y),
880 y.linearCombination(z, v.x, x.negate(), v.z),
881 z.linearCombination(x, v.y, y.negate(), v.x));
882 }
883
884 /** Compute the cross-product of the instance with another vector.
885 * @param v other vector
886 * @return the cross product this ^ v as a new Vector3D
887 */
888 public FieldVector3D<T> crossProduct(final Vector3D v) {
889 return new FieldVector3D<T>(x.linearCombination(v.getZ(), y, -v.getY(), z),
890 y.linearCombination(v.getX(), z, -v.getZ(), x),
891 z.linearCombination(v.getY(), x, -v.getX(), y));
892 }
893
894 /** Compute the distance between the instance and another vector according to the L<sub>1</sub> norm.
895 * <p>Calling this method is equivalent to calling:
896 * <code>q.subtract(p).getNorm1()</code> except that no intermediate
897 * vector is built</p>
898 * @param v second vector
899 * @return the distance between the instance and p according to the L<sub>1</sub> norm
900 */
901 public T distance1(final FieldVector3D<T> v) {
902 final T dx = v.x.subtract(x).abs();
903 final T dy = v.y.subtract(y).abs();
904 final T dz = v.z.subtract(z).abs();
905 return dx.add(dy).add(dz);
906 }
907
908 /** Compute the distance between the instance and another vector according to the L<sub>1</sub> norm.
909 * <p>Calling this method is equivalent to calling:
910 * <code>q.subtract(p).getNorm1()</code> except that no intermediate
911 * vector is built</p>
912 * @param v second vector
913 * @return the distance between the instance and p according to the L<sub>1</sub> norm
914 */
915 public T distance1(final Vector3D v) {
916 final T dx = x.subtract(v.getX()).abs();
917 final T dy = y.subtract(v.getY()).abs();
918 final T dz = z.subtract(v.getZ()).abs();
919 return dx.add(dy).add(dz);
920 }
921
922 /** Compute the distance between the instance and another vector according to the L<sub>2</sub> norm.
923 * <p>Calling this method is equivalent to calling:
924 * <code>q.subtract(p).getNorm()</code> except that no intermediate
925 * vector is built</p>
926 * @param v second vector
927 * @return the distance between the instance and p according to the L<sub>2</sub> norm
928 */
929 public T distance(final FieldVector3D<T> v) {
930 final T dx = v.x.subtract(x);
931 final T dy = v.y.subtract(y);
932 final T dz = v.z.subtract(z);
933 return dx.square().add(dy.square()).add(dz.square()).sqrt();
934 }
935
936 /** Compute the distance between the instance and another vector according to the L<sub>2</sub> norm.
937 * <p>Calling this method is equivalent to calling:
938 * <code>q.subtract(p).getNorm()</code> except that no intermediate
939 * vector is built</p>
940 * @param v second vector
941 * @return the distance between the instance and p according to the L<sub>2</sub> norm
942 */
943 public T distance(final Vector3D v) {
944 final T dx = x.subtract(v.getX());
945 final T dy = y.subtract(v.getY());
946 final T dz = z.subtract(v.getZ());
947 return dx.square().add(dy.square()).add(dz.square()).sqrt();
948 }
949
950 /** Compute the distance between the instance and another vector according to the L<sub>∞</sub> norm.
951 * <p>Calling this method is equivalent to calling:
952 * <code>q.subtract(p).getNormInf()</code> except that no intermediate
953 * vector is built</p>
954 * @param v second vector
955 * @return the distance between the instance and p according to the L<sub>∞</sub> norm
956 */
957 public T distanceInf(final FieldVector3D<T> v) {
958 final T dx = v.x.subtract(x).abs();
959 final T dy = v.y.subtract(y).abs();
960 final T dz = v.z.subtract(z).abs();
961 if (dx.getReal() <= dy.getReal()) {
962 if (dy.getReal() <= dz.getReal()) {
963 return dz;
964 } else {
965 return dy;
966 }
967 } else {
968 if (dx.getReal() <= dz.getReal()) {
969 return dz;
970 } else {
971 return dx;
972 }
973 }
974 }
975
976 /** Compute the distance between the instance and another vector according to the L<sub>∞</sub> norm.
977 * <p>Calling this method is equivalent to calling:
978 * <code>q.subtract(p).getNormInf()</code> except that no intermediate
979 * vector is built</p>
980 * @param v second vector
981 * @return the distance between the instance and p according to the L<sub>∞</sub> norm
982 */
983 public T distanceInf(final Vector3D v) {
984 final T dx = x.subtract(v.getX()).abs();
985 final T dy = y.subtract(v.getY()).abs();
986 final T dz = z.subtract(v.getZ()).abs();
987 if (dx.getReal() <= dy.getReal()) {
988 if (dy.getReal() <= dz.getReal()) {
989 return dz;
990 } else {
991 return dy;
992 }
993 } else {
994 if (dx.getReal() <= dz.getReal()) {
995 return dz;
996 } else {
997 return dx;
998 }
999 }
1000 }
1001
1002 /** Compute the square of the distance between the instance and another vector.
1003 * <p>Calling this method is equivalent to calling:
1004 * <code>q.subtract(p).getNormSq()</code> except that no intermediate
1005 * vector is built</p>
1006 * @param v second vector
1007 * @return the square of the distance between the instance and p
1008 */
1009 public T distanceSq(final FieldVector3D<T> v) {
1010 final T dx = v.x.subtract(x);
1011 final T dy = v.y.subtract(y);
1012 final T dz = v.z.subtract(z);
1013 return dx.square().add(dy.square()).add(dz.square());
1014 }
1015
1016 /** Compute the square of the distance between the instance and another vector.
1017 * <p>Calling this method is equivalent to calling:
1018 * <code>q.subtract(p).getNormSq()</code> except that no intermediate
1019 * vector is built</p>
1020 * @param v second vector
1021 * @return the square of the distance between the instance and p
1022 */
1023 public T distanceSq(final Vector3D v) {
1024 final T dx = x.subtract(v.getX());
1025 final T dy = y.subtract(v.getY());
1026 final T dz = z.subtract(v.getZ());
1027 return dx.square().add(dy.square()).add(dz.square());
1028 }
1029
1030 /** Compute the dot-product of two vectors.
1031 * @param v1 first vector
1032 * @param v2 second vector
1033 * @param <T> the type of the field elements
1034 * @return the dot product v1.v2
1035 */
1036 public static <T extends CalculusFieldElement<T>> T dotProduct(final FieldVector3D<T> v1,
1037 final FieldVector3D<T> v2) {
1038 return v1.dotProduct(v2);
1039 }
1040
1041 /** Compute the dot-product of two vectors.
1042 * @param v1 first vector
1043 * @param v2 second vector
1044 * @param <T> the type of the field elements
1045 * @return the dot product v1.v2
1046 */
1047 public static <T extends CalculusFieldElement<T>> T dotProduct(final FieldVector3D<T> v1,
1048 final Vector3D v2) {
1049 return v1.dotProduct(v2);
1050 }
1051
1052 /** Compute the dot-product of two vectors.
1053 * @param v1 first vector
1054 * @param v2 second vector
1055 * @param <T> the type of the field elements
1056 * @return the dot product v1.v2
1057 */
1058 public static <T extends CalculusFieldElement<T>> T dotProduct(final Vector3D v1,
1059 final FieldVector3D<T> v2) {
1060 return v2.dotProduct(v1);
1061 }
1062
1063 /** Compute the cross-product of two vectors.
1064 * @param v1 first vector
1065 * @param v2 second vector
1066 * @param <T> the type of the field elements
1067 * @return the cross product v1 ^ v2 as a new Vector
1068 */
1069 public static <T extends CalculusFieldElement<T>> FieldVector3D<T> crossProduct(final FieldVector3D<T> v1,
1070 final FieldVector3D<T> v2) {
1071 return v1.crossProduct(v2);
1072 }
1073
1074 /** Compute the cross-product of two vectors.
1075 * @param v1 first vector
1076 * @param v2 second vector
1077 * @param <T> the type of the field elements
1078 * @return the cross product v1 ^ v2 as a new Vector
1079 */
1080 public static <T extends CalculusFieldElement<T>> FieldVector3D<T> crossProduct(final FieldVector3D<T> v1,
1081 final Vector3D v2) {
1082 return v1.crossProduct(v2);
1083 }
1084
1085 /** Compute the cross-product of two vectors.
1086 * @param v1 first vector
1087 * @param v2 second vector
1088 * @param <T> the type of the field elements
1089 * @return the cross product v1 ^ v2 as a new Vector
1090 */
1091 public static <T extends CalculusFieldElement<T>> FieldVector3D<T> crossProduct(final Vector3D v1,
1092 final FieldVector3D<T> v2) {
1093 return new FieldVector3D<T>(v2.x.linearCombination(v1.getY(), v2.z, -v1.getZ(), v2.y),
1094 v2.y.linearCombination(v1.getZ(), v2.x, -v1.getX(), v2.z),
1095 v2.z.linearCombination(v1.getX(), v2.y, -v1.getY(), v2.x));
1096 }
1097
1098 /** Compute the distance between two vectors according to the L<sub>1</sub> norm.
1099 * <p>Calling this method is equivalent to calling:
1100 * <code>v1.subtract(v2).getNorm1()</code> except that no intermediate
1101 * vector is built</p>
1102 * @param v1 first vector
1103 * @param v2 second vector
1104 * @param <T> the type of the field elements
1105 * @return the distance between v1 and v2 according to the L<sub>1</sub> norm
1106 */
1107 public static <T extends CalculusFieldElement<T>> T distance1(final FieldVector3D<T> v1,
1108 final FieldVector3D<T> v2) {
1109 return v1.distance1(v2);
1110 }
1111
1112 /** Compute the distance between two vectors according to the L<sub>1</sub> norm.
1113 * <p>Calling this method is equivalent to calling:
1114 * <code>v1.subtract(v2).getNorm1()</code> except that no intermediate
1115 * vector is built</p>
1116 * @param v1 first vector
1117 * @param v2 second vector
1118 * @param <T> the type of the field elements
1119 * @return the distance between v1 and v2 according to the L<sub>1</sub> norm
1120 */
1121 public static <T extends CalculusFieldElement<T>> T distance1(final FieldVector3D<T> v1,
1122 final Vector3D v2) {
1123 return v1.distance1(v2);
1124 }
1125
1126 /** Compute the distance between two vectors according to the L<sub>1</sub> norm.
1127 * <p>Calling this method is equivalent to calling:
1128 * <code>v1.subtract(v2).getNorm1()</code> except that no intermediate
1129 * vector is built</p>
1130 * @param v1 first vector
1131 * @param v2 second vector
1132 * @param <T> the type of the field elements
1133 * @return the distance between v1 and v2 according to the L<sub>1</sub> norm
1134 */
1135 public static <T extends CalculusFieldElement<T>> T distance1(final Vector3D v1,
1136 final FieldVector3D<T> v2) {
1137 return v2.distance1(v1);
1138 }
1139
1140 /** Compute the distance between two vectors according to the L<sub>2</sub> norm.
1141 * <p>Calling this method is equivalent to calling:
1142 * <code>v1.subtract(v2).getNorm()</code> except that no intermediate
1143 * vector is built</p>
1144 * @param v1 first vector
1145 * @param v2 second vector
1146 * @param <T> the type of the field elements
1147 * @return the distance between v1 and v2 according to the L<sub>2</sub> norm
1148 */
1149 public static <T extends CalculusFieldElement<T>> T distance(final FieldVector3D<T> v1,
1150 final FieldVector3D<T> v2) {
1151 return v1.distance(v2);
1152 }
1153
1154 /** Compute the distance between two vectors according to the L<sub>2</sub> norm.
1155 * <p>Calling this method is equivalent to calling:
1156 * <code>v1.subtract(v2).getNorm()</code> except that no intermediate
1157 * vector is built</p>
1158 * @param v1 first vector
1159 * @param v2 second vector
1160 * @param <T> the type of the field elements
1161 * @return the distance between v1 and v2 according to the L<sub>2</sub> norm
1162 */
1163 public static <T extends CalculusFieldElement<T>> T distance(final FieldVector3D<T> v1,
1164 final Vector3D v2) {
1165 return v1.distance(v2);
1166 }
1167
1168 /** Compute the distance between two vectors according to the L<sub>2</sub> norm.
1169 * <p>Calling this method is equivalent to calling:
1170 * <code>v1.subtract(v2).getNorm()</code> except that no intermediate
1171 * vector is built</p>
1172 * @param v1 first vector
1173 * @param v2 second vector
1174 * @param <T> the type of the field elements
1175 * @return the distance between v1 and v2 according to the L<sub>2</sub> norm
1176 */
1177 public static <T extends CalculusFieldElement<T>> T distance(final Vector3D v1,
1178 final FieldVector3D<T> v2) {
1179 return v2.distance(v1);
1180 }
1181
1182 /** Compute the distance between two vectors according to the L<sub>∞</sub> norm.
1183 * <p>Calling this method is equivalent to calling:
1184 * <code>v1.subtract(v2).getNormInf()</code> except that no intermediate
1185 * vector is built</p>
1186 * @param v1 first vector
1187 * @param v2 second vector
1188 * @param <T> the type of the field elements
1189 * @return the distance between v1 and v2 according to the L<sub>∞</sub> norm
1190 */
1191 public static <T extends CalculusFieldElement<T>> T distanceInf(final FieldVector3D<T> v1,
1192 final FieldVector3D<T> v2) {
1193 return v1.distanceInf(v2);
1194 }
1195
1196 /** Compute the distance between two vectors according to the L<sub>∞</sub> norm.
1197 * <p>Calling this method is equivalent to calling:
1198 * <code>v1.subtract(v2).getNormInf()</code> except that no intermediate
1199 * vector is built</p>
1200 * @param v1 first vector
1201 * @param v2 second vector
1202 * @param <T> the type of the field elements
1203 * @return the distance between v1 and v2 according to the L<sub>∞</sub> norm
1204 */
1205 public static <T extends CalculusFieldElement<T>> T distanceInf(final FieldVector3D<T> v1,
1206 final Vector3D v2) {
1207 return v1.distanceInf(v2);
1208 }
1209
1210 /** Compute the distance between two vectors according to the L<sub>∞</sub> norm.
1211 * <p>Calling this method is equivalent to calling:
1212 * <code>v1.subtract(v2).getNormInf()</code> except that no intermediate
1213 * vector is built</p>
1214 * @param v1 first vector
1215 * @param v2 second vector
1216 * @param <T> the type of the field elements
1217 * @return the distance between v1 and v2 according to the L<sub>∞</sub> norm
1218 */
1219 public static <T extends CalculusFieldElement<T>> T distanceInf(final Vector3D v1,
1220 final FieldVector3D<T> v2) {
1221 return v2.distanceInf(v1);
1222 }
1223
1224 /** Compute the square of the distance between two vectors.
1225 * <p>Calling this method is equivalent to calling:
1226 * <code>v1.subtract(v2).getNormSq()</code> except that no intermediate
1227 * vector is built</p>
1228 * @param v1 first vector
1229 * @param v2 second vector
1230 * @param <T> the type of the field elements
1231 * @return the square of the distance between v1 and v2
1232 */
1233 public static <T extends CalculusFieldElement<T>> T distanceSq(final FieldVector3D<T> v1,
1234 final FieldVector3D<T> v2) {
1235 return v1.distanceSq(v2);
1236 }
1237
1238 /** Compute the square of the distance between two vectors.
1239 * <p>Calling this method is equivalent to calling:
1240 * <code>v1.subtract(v2).getNormSq()</code> except that no intermediate
1241 * vector is built</p>
1242 * @param v1 first vector
1243 * @param v2 second vector
1244 * @param <T> the type of the field elements
1245 * @return the square of the distance between v1 and v2
1246 */
1247 public static <T extends CalculusFieldElement<T>> T distanceSq(final FieldVector3D<T> v1,
1248 final Vector3D v2) {
1249 return v1.distanceSq(v2);
1250 }
1251
1252 /** Compute the square of the distance between two vectors.
1253 * <p>Calling this method is equivalent to calling:
1254 * <code>v1.subtract(v2).getNormSq()</code> except that no intermediate
1255 * vector is built</p>
1256 * @param v1 first vector
1257 * @param v2 second vector
1258 * @param <T> the type of the field elements
1259 * @return the square of the distance between v1 and v2
1260 */
1261 public static <T extends CalculusFieldElement<T>> T distanceSq(final Vector3D v1,
1262 final FieldVector3D<T> v2) {
1263 return v2.distanceSq(v1);
1264 }
1265
1266 /** Get a string representation of this vector.
1267 * @return a string representation of this vector
1268 */
1269 @Override
1270 public String toString() {
1271 return Vector3DFormat.getVector3DFormat().format(toVector3D());
1272 }
1273
1274 /** Get a string representation of this vector.
1275 * @param format the custom format for components
1276 * @return a string representation of this vector
1277 */
1278 public String toString(final NumberFormat format) {
1279 return new Vector3DFormat(format).format(toVector3D());
1280 }
1281
1282 /** {@inheritDoc} */
1283 @Override
1284 public FieldVector3D<T> blendArithmeticallyWith(final FieldVector3D<T> other, final T blendingValue)
1285 throws MathIllegalArgumentException {
1286 SmoothStepFactory.checkBetweenZeroAndOneIncluded(blendingValue.getReal());
1287 final T one = x.getField().getOne();
1288 return this.scalarMultiply(one.subtract(blendingValue)).add(other.scalarMultiply(blendingValue));
1289 }
1290 }