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