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  
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 (&alpha;) around Z
93       *              (0 is +X, &pi;/2 is +Y, &pi; is -X and 3&pi;/2 is -Y)
94       * @param delta elevation (&delta;) above (XY) plane, from -&pi;/2 to +&pi;/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.multiply(x).add(y.multiply(y)).add(z.multiply(z)).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.multiply(x).add(y.multiply(y)).add(z.multiply(z));
477     }
478 
479     /** Get the L<sub>&infin;</sub> norm for the vector.
480      * @return L<sub>&infin;</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 (&alpha;) of the vector, between -&pi; and +&pi;
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 (&delta;) of the vector, between -&pi;/2 and +&pi;/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.multiply(y).add(z.multiply(z)).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.multiply(x).add(z.multiply(z)).sqrt().reciprocal();
654             return new FieldVector3D<T>(inverse.multiply(z).negate(), inverse.getField().getZero(), inverse.multiply(x));
655         } else {
656             final T inverse  = x.multiply(x).add(y.multiply(y)).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.multiply(dx).add(dy.multiply(dy)).add(dz.multiply(dz)).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.multiply(dx).add(dy.multiply(dy)).add(dz.multiply(dz)).sqrt();
948     }
949 
950     /** Compute the distance between the instance and another vector according to the L<sub>&infin;</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>&infin;</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>&infin;</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>&infin;</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.multiply(dx).add(dy.multiply(dy)).add(dz.multiply(dz));
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.multiply(dx).add(dy.multiply(dy)).add(dz.multiply(dz));
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>&infin;</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>&infin;</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>&infin;</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>&infin;</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>&infin;</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>&infin;</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 }