FieldVector3D.java

  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.  * This is not the original file distributed by the Apache Software Foundation
  19.  * It has been modified by the Hipparchus project
  20.  */

  21. package org.hipparchus.geometry.euclidean.threed;

  22. import java.io.Serializable;
  23. import java.text.NumberFormat;

  24. import org.hipparchus.CalculusFieldElement;
  25. import org.hipparchus.Field;
  26. import org.hipparchus.analysis.polynomials.SmoothStepFactory;
  27. import org.hipparchus.exception.LocalizedCoreFormats;
  28. import org.hipparchus.exception.MathIllegalArgumentException;
  29. import org.hipparchus.exception.MathRuntimeException;
  30. import org.hipparchus.geometry.LocalizedGeometryFormats;
  31. import org.hipparchus.util.FastMath;
  32. import org.hipparchus.util.FieldBlendable;
  33. import org.hipparchus.util.FieldSinCos;
  34. import org.hipparchus.util.MathArrays;

  35. /**
  36.  * This class is a re-implementation of {@link Vector3D} using {@link CalculusFieldElement}.
  37.  * <p>Instance of this class are guaranteed to be immutable.</p>
  38.  * @param <T> the type of the field elements
  39.  */
  40. public class FieldVector3D<T extends CalculusFieldElement<T>> implements FieldBlendable<FieldVector3D<T>, T>, Serializable {

  41.     /** Serializable version identifier. */
  42.     private static final long serialVersionUID = 20130224L;

  43.     /** Abscissa. */
  44.     private final T x;

  45.     /** Ordinate. */
  46.     private final T y;

  47.     /** Height. */
  48.     private final T z;

  49.     /** Simple constructor.
  50.      * Build a vector from its coordinates
  51.      * @param x abscissa
  52.      * @param y ordinate
  53.      * @param z height
  54.      * @see #getX()
  55.      * @see #getY()
  56.      * @see #getZ()
  57.      */
  58.     public FieldVector3D(final T x, final T y, final T z) {
  59.         this.x = x;
  60.         this.y = y;
  61.         this.z = z;
  62.     }

  63.     /** Simple constructor.
  64.      * Build a vector from its coordinates
  65.      * @param v coordinates array
  66.      * @exception MathIllegalArgumentException if array does not have 3 elements
  67.      * @see #toArray()
  68.      */
  69.     public FieldVector3D(final T[] v) throws MathIllegalArgumentException {
  70.         if (v.length != 3) {
  71.             throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
  72.                                                    v.length, 3);
  73.         }
  74.         this.x = v[0];
  75.         this.y = v[1];
  76.         this.z = v[2];
  77.     }

  78.     /** Simple constructor.
  79.      * Build a vector from its azimuthal coordinates
  80.      * @param alpha azimuth (&alpha;) around Z
  81.      *              (0 is +X, &pi;/2 is +Y, &pi; is -X and 3&pi;/2 is -Y)
  82.      * @param delta elevation (&delta;) above (XY) plane, from -&pi;/2 to +&pi;/2
  83.      * @see #getAlpha()
  84.      * @see #getDelta()
  85.      */
  86.     public FieldVector3D(final T alpha, final T delta) {
  87.         FieldSinCos<T> sinCosAlpha = FastMath.sinCos(alpha);
  88.         FieldSinCos<T> sinCosDelta = FastMath.sinCos(delta);
  89.         this.x = sinCosAlpha.cos().multiply(sinCosDelta.cos());
  90.         this.y = sinCosAlpha.sin().multiply(sinCosDelta.cos());
  91.         this.z = sinCosDelta.sin();
  92.     }

  93.     /** Multiplicative constructor.
  94.      * Build a vector from another one and a scale factor.
  95.      * The vector built will be a * u
  96.      * @param a scale factor
  97.      * @param u base (unscaled) vector
  98.      */
  99.     public FieldVector3D(final T a, final FieldVector3D<T>u) {
  100.         this.x = a.multiply(u.x);
  101.         this.y = a.multiply(u.y);
  102.         this.z = a.multiply(u.z);
  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 Vector3D u) {
  111.         this.x = a.multiply(u.getX());
  112.         this.y = a.multiply(u.getY());
  113.         this.z = a.multiply(u.getZ());
  114.     }

  115.     /** Multiplicative constructor.
  116.      * Build a vector from another one and a scale factor.
  117.      * The vector built will be a * u
  118.      * @param a scale factor
  119.      * @param u base (unscaled) vector
  120.      */
  121.     public FieldVector3D(final double a, final FieldVector3D<T> u) {
  122.         this.x = u.x.multiply(a);
  123.         this.y = u.y.multiply(a);
  124.         this.z = u.z.multiply(a);
  125.     }

  126.     /** Linear constructor.
  127.      * Build a vector from two other ones and corresponding scale factors.
  128.      * The vector built will be a1 * u1 + a2 * u2
  129.      * @param a1 first scale factor
  130.      * @param u1 first base (unscaled) vector
  131.      * @param a2 second scale factor
  132.      * @param u2 second base (unscaled) vector
  133.      */
  134.     public FieldVector3D(final T a1, final FieldVector3D<T> u1,
  135.                          final T a2, final FieldVector3D<T> u2) {
  136.         final T prototype = a1;
  137.         this.x = prototype.linearCombination(a1, u1.getX(), a2, u2.getX());
  138.         this.y = prototype.linearCombination(a1, u1.getY(), a2, u2.getY());
  139.         this.z = prototype.linearCombination(a1, u1.getZ(), a2, u2.getZ());
  140.     }

  141.     /** Linear constructor.
  142.      * Build a vector from two other ones and corresponding scale factors.
  143.      * The vector built will be a1 * u1 + a2 * u2
  144.      * @param a1 first scale factor
  145.      * @param u1 first base (unscaled) vector
  146.      * @param a2 second scale factor
  147.      * @param u2 second base (unscaled) vector
  148.      */
  149.     public FieldVector3D(final T a1, final Vector3D u1,
  150.                          final T a2, final Vector3D u2) {
  151.         final T prototype = a1;
  152.         this.x = prototype.linearCombination(u1.getX(), a1, u2.getX(), a2);
  153.         this.y = prototype.linearCombination(u1.getY(), a1, u2.getY(), a2);
  154.         this.z = prototype.linearCombination(u1.getZ(), a1, u2.getZ(), a2);
  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 double a1, final FieldVector3D<T> u1,
  165.                          final double a2, final FieldVector3D<T> u2) {
  166.         final T prototype = u1.getX();
  167.         this.x = prototype.linearCombination(a1, u1.getX(), a2, u2.getX());
  168.         this.y = prototype.linearCombination(a1, u1.getY(), a2, u2.getY());
  169.         this.z = prototype.linearCombination(a1, u1.getZ(), a2, u2.getZ());
  170.     }

  171.     /** Linear constructor.
  172.      * Build a vector from three other ones and corresponding scale factors.
  173.      * The vector built will be a1 * u1 + a2 * u2 + a3 * u3
  174.      * @param a1 first scale factor
  175.      * @param u1 first base (unscaled) vector
  176.      * @param a2 second scale factor
  177.      * @param u2 second base (unscaled) vector
  178.      * @param a3 third scale factor
  179.      * @param u3 third base (unscaled) vector
  180.      */
  181.     public FieldVector3D(final T a1, final FieldVector3D<T> u1,
  182.                          final T a2, final FieldVector3D<T> u2,
  183.                          final T a3, final FieldVector3D<T> u3) {
  184.         final T prototype = a1;
  185.         this.x = prototype.linearCombination(a1, u1.getX(), a2, u2.getX(), a3, u3.getX());
  186.         this.y = prototype.linearCombination(a1, u1.getY(), a2, u2.getY(), a3, u3.getY());
  187.         this.z = prototype.linearCombination(a1, u1.getZ(), a2, u2.getZ(), a3, u3.getZ());
  188.     }

  189.     /** Linear constructor.
  190.      * Build a vector from three other ones and corresponding scale factors.
  191.      * The vector built will be a1 * u1 + a2 * u2 + a3 * u3
  192.      * @param a1 first scale factor
  193.      * @param u1 first base (unscaled) vector
  194.      * @param a2 second scale factor
  195.      * @param u2 second base (unscaled) vector
  196.      * @param a3 third scale factor
  197.      * @param u3 third base (unscaled) vector
  198.      */
  199.     public FieldVector3D(final T a1, final Vector3D u1,
  200.                          final T a2, final Vector3D u2,
  201.                          final T a3, final Vector3D u3) {
  202.         final T prototype = a1;
  203.         this.x = prototype.linearCombination(u1.getX(), a1, u2.getX(), a2, u3.getX(), a3);
  204.         this.y = prototype.linearCombination(u1.getY(), a1, u2.getY(), a2, u3.getY(), a3);
  205.         this.z = prototype.linearCombination(u1.getZ(), a1, u2.getZ(), a2, u3.getZ(), a3);
  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 double a1, final FieldVector3D<T> u1,
  218.                          final double a2, final FieldVector3D<T> u2,
  219.                          final double a3, final FieldVector3D<T> u3) {
  220.         final T prototype = u1.getX();
  221.         this.x = prototype.linearCombination(a1, u1.getX(), a2, u2.getX(), a3, u3.getX());
  222.         this.y = prototype.linearCombination(a1, u1.getY(), a2, u2.getY(), a3, u3.getY());
  223.         this.z = prototype.linearCombination(a1, u1.getZ(), a2, u2.getZ(), a3, u3.getZ());
  224.     }

  225.     /** Linear constructor.
  226.      * Build a vector from four other ones and corresponding scale factors.
  227.      * The vector built will be a1 * u1 + a2 * u2 + a3 * u3 + a4 * u4
  228.      * @param a1 first scale factor
  229.      * @param u1 first base (unscaled) vector
  230.      * @param a2 second scale factor
  231.      * @param u2 second base (unscaled) vector
  232.      * @param a3 third scale factor
  233.      * @param u3 third base (unscaled) vector
  234.      * @param a4 fourth scale factor
  235.      * @param u4 fourth base (unscaled) vector
  236.      */
  237.     public FieldVector3D(final T a1, final FieldVector3D<T> u1,
  238.                          final T a2, final FieldVector3D<T> u2,
  239.                          final T a3, final FieldVector3D<T> u3,
  240.                          final T a4, final FieldVector3D<T> u4) {
  241.         final T prototype = a1;
  242.         this.x = prototype.linearCombination(a1, u1.getX(), a2, u2.getX(), a3, u3.getX(), a4, u4.getX());
  243.         this.y = prototype.linearCombination(a1, u1.getY(), a2, u2.getY(), a3, u3.getY(), a4, u4.getY());
  244.         this.z = prototype.linearCombination(a1, u1.getZ(), a2, u2.getZ(), a3, u3.getZ(), a4, u4.getZ());
  245.     }

  246.     /** Linear constructor.
  247.      * Build a vector from four other ones and corresponding scale factors.
  248.      * The vector built will be a1 * u1 + a2 * u2 + a3 * u3 + a4 * u4
  249.      * @param a1 first scale factor
  250.      * @param u1 first base (unscaled) vector
  251.      * @param a2 second scale factor
  252.      * @param u2 second base (unscaled) vector
  253.      * @param a3 third scale factor
  254.      * @param u3 third base (unscaled) vector
  255.      * @param a4 fourth scale factor
  256.      * @param u4 fourth base (unscaled) vector
  257.      */
  258.     public FieldVector3D(final T a1, final Vector3D u1,
  259.                          final T a2, final Vector3D u2,
  260.                          final T a3, final Vector3D u3,
  261.                          final T a4, final Vector3D u4) {
  262.         final T prototype = a1;
  263.         this.x = prototype.linearCombination(u1.getX(), a1, u2.getX(), a2, u3.getX(), a3, u4.getX(), a4);
  264.         this.y = prototype.linearCombination(u1.getY(), a1, u2.getY(), a2, u3.getY(), a3, u4.getY(), a4);
  265.         this.z = prototype.linearCombination(u1.getZ(), a1, u2.getZ(), a2, u3.getZ(), a3, u4.getZ(), a4);
  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 double a1, final FieldVector3D<T> u1,
  280.                          final double a2, final FieldVector3D<T> u2,
  281.                          final double a3, final FieldVector3D<T> u3,
  282.                          final double a4, final FieldVector3D<T> u4) {
  283.         final T prototype = u1.getX();
  284.         this.x = prototype.linearCombination(a1, u1.getX(), a2, u2.getX(), a3, u3.getX(), a4, u4.getX());
  285.         this.y = prototype.linearCombination(a1, u1.getY(), a2, u2.getY(), a3, u3.getY(), a4, u4.getY());
  286.         this.z = prototype.linearCombination(a1, u1.getZ(), a2, u2.getZ(), a3, u3.getZ(), a4, u4.getZ());
  287.     }

  288.     /** Build a {@link FieldVector3D} from a {@link Vector3D}.
  289.      * @param field field for the components
  290.      * @param v vector to convert
  291.      */
  292.     public FieldVector3D(final Field<T> field, final Vector3D v) {
  293.         this.x = field.getZero().add(v.getX());
  294.         this.y = field.getZero().add(v.getY());
  295.         this.z = field.getZero().add(v.getZ());
  296.     }

  297.     /** Get null vector (coordinates: 0, 0, 0).
  298.      * @param field field for the components
  299.      * @return a new vector
  300.      * @param <T> the type of the field elements
  301.      */
  302.     public static <T extends CalculusFieldElement<T>> FieldVector3D<T> getZero(final Field<T> field) {
  303.         return new FieldVector3D<>(field, Vector3D.ZERO);
  304.     }

  305.     /** Get first canonical vector (coordinates: 1, 0, 0).
  306.      * @param field field for the components
  307.      * @return a new vector
  308.      * @param <T> the type of the field elements
  309.      */
  310.     public static <T extends CalculusFieldElement<T>> FieldVector3D<T> getPlusI(final Field<T> field) {
  311.         return new FieldVector3D<>(field, Vector3D.PLUS_I);
  312.     }

  313.     /** Get opposite of the first canonical vector (coordinates: -1, 0, 0).
  314.      * @param field field for the components
  315.      * @return a new vector
  316.      * @param <T> the type of the field elements
  317.      */
  318.     public static <T extends CalculusFieldElement<T>> FieldVector3D<T> getMinusI(final Field<T> field) {
  319.         return new FieldVector3D<>(field, Vector3D.MINUS_I);
  320.     }

  321.     /** Get second canonical vector (coordinates: 0, 1, 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> getPlusJ(final Field<T> field) {
  327.         return new FieldVector3D<>(field, Vector3D.PLUS_J);
  328.     }

  329.     /** Get opposite of the second canonical vector (coordinates: 0, -1, 0).
  330.      * @param field field for the components
  331.      * @return a new vector
  332.      * @param <T> the type of the field elements
  333.      */
  334.     public static <T extends CalculusFieldElement<T>> FieldVector3D<T> getMinusJ(final Field<T> field) {
  335.         return new FieldVector3D<>(field, Vector3D.MINUS_J);
  336.     }

  337.     /** Get third canonical vector (coordinates: 0, 0, 1).
  338.      * @param field field for the components
  339.      * @return a new vector
  340.      * @param <T> the type of the field elements
  341.      */
  342.     public static <T extends CalculusFieldElement<T>> FieldVector3D<T> getPlusK(final Field<T> field) {
  343.         return new FieldVector3D<>(field, Vector3D.PLUS_K);
  344.     }

  345.     /** Get opposite of the third canonical vector (coordinates: 0, 0, -1).
  346.      * @param field field for the components
  347.      * @return a new vector
  348.      * @param <T> the type of the field elements
  349.      */
  350.     public static <T extends CalculusFieldElement<T>> FieldVector3D<T> getMinusK(final Field<T> field) {
  351.         return new FieldVector3D<>(field, Vector3D.MINUS_K);
  352.     }

  353.     /** Get a vector with all coordinates set to NaN.
  354.      * @param field field for the components
  355.      * @return a new vector
  356.      * @param <T> the type of the field elements
  357.      */
  358.     public static <T extends CalculusFieldElement<T>> FieldVector3D<T> getNaN(final Field<T> field) {
  359.         return new FieldVector3D<>(field, Vector3D.NaN);
  360.     }

  361.     /** Get a vector with all coordinates set to positive infinity.
  362.      * @param field field for the components
  363.      * @return a new vector
  364.      * @param <T> the type of the field elements
  365.      */
  366.     public static <T extends CalculusFieldElement<T>> FieldVector3D<T> getPositiveInfinity(final Field<T> field) {
  367.         return new FieldVector3D<>(field, Vector3D.POSITIVE_INFINITY);
  368.     }

  369.     /** Get a vector with all coordinates set to negative infinity.
  370.      * @param field field for the components
  371.      * @return a new vector
  372.      * @param <T> the type of the field elements
  373.      */
  374.     public static <T extends CalculusFieldElement<T>> FieldVector3D<T> getNegativeInfinity(final Field<T> field) {
  375.         return new FieldVector3D<>(field, Vector3D.NEGATIVE_INFINITY);
  376.     }

  377.     /** Get the abscissa of the vector.
  378.      * @return abscissa of the vector
  379.      * @see #FieldVector3D(CalculusFieldElement, CalculusFieldElement, CalculusFieldElement)
  380.      */
  381.     public T getX() {
  382.         return x;
  383.     }

  384.     /** Get the ordinate of the vector.
  385.      * @return ordinate of the vector
  386.      * @see #FieldVector3D(CalculusFieldElement, CalculusFieldElement, CalculusFieldElement)
  387.      */
  388.     public T getY() {
  389.         return y;
  390.     }

  391.     /** Get the height of the vector.
  392.      * @return height of the vector
  393.      * @see #FieldVector3D(CalculusFieldElement, CalculusFieldElement, CalculusFieldElement)
  394.      */
  395.     public T getZ() {
  396.         return z;
  397.     }

  398.     /** Get the vector coordinates as a dimension 3 array.
  399.      * @return vector coordinates
  400.      * @see #FieldVector3D(CalculusFieldElement[])
  401.      */
  402.     public T[] toArray() {
  403.         final T[] array = MathArrays.buildArray(x.getField(), 3);
  404.         array[0] = x;
  405.         array[1] = y;
  406.         array[2] = z;
  407.         return array;
  408.     }

  409.     /** Convert to a constant vector without extra field parts.
  410.      * @return a constant vector
  411.      */
  412.     public Vector3D toVector3D() {
  413.         return new Vector3D(x.getReal(), y.getReal(), z.getReal());
  414.     }

  415.     /** Get the L<sub>1</sub> norm for the vector.
  416.      * @return L<sub>1</sub> norm for the vector
  417.      */
  418.     public T getNorm1() {
  419.         return x.abs().add(y.abs()).add(z.abs());
  420.     }

  421.     /** Get the L<sub>2</sub> norm for the vector.
  422.      * @return Euclidean norm for the vector
  423.      */
  424.     public T getNorm() {
  425.         // there are no cancellation problems here, so we use the straightforward formula
  426.         return x.square().add(y.square()).add(z.square()).sqrt();
  427.     }

  428.     /** Get the square of the norm for the vector.
  429.      * @return square of the Euclidean norm for the vector
  430.      */
  431.     public T getNormSq() {
  432.         // there are no cancellation problems here, so we use the straightforward formula
  433.         return x.square().add(y.square()).add(z.square());
  434.     }

  435.     /** Get the L<sub>&infin;</sub> norm for the vector.
  436.      * @return L<sub>&infin;</sub> norm for the vector
  437.      */
  438.     public T getNormInf() {
  439.         return FastMath.max(FastMath.abs(x), FastMath.max(FastMath.abs(y), FastMath.abs(z)));
  440.     }

  441.     /** Get the azimuth of the vector.
  442.      * @return azimuth (&alpha;) of the vector, between -&pi; and +&pi;
  443.      * @see #FieldVector3D(CalculusFieldElement, CalculusFieldElement)
  444.      */
  445.     public T getAlpha() {
  446.         return y.atan2(x);
  447.     }

  448.     /** Get the elevation of the vector.
  449.      * @return elevation (&delta;) of the vector, between -&pi;/2 and +&pi;/2
  450.      * @see #FieldVector3D(CalculusFieldElement, CalculusFieldElement)
  451.      */
  452.     public T getDelta() {
  453.         return z.divide(getNorm()).asin();
  454.     }

  455.     /** Add a vector to the instance.
  456.      * @param v vector to add
  457.      * @return a new vector
  458.      */
  459.     public FieldVector3D<T> add(final FieldVector3D<T> v) {
  460.         return new FieldVector3D<>(x.add(v.x), y.add(v.y), z.add(v.z));
  461.     }

  462.     /** Add a vector to the instance.
  463.      * @param v vector to add
  464.      * @return a new vector
  465.      */
  466.     public FieldVector3D<T> add(final Vector3D v) {
  467.         return new FieldVector3D<>(x.add(v.getX()), y.add(v.getY()), z.add(v.getZ()));
  468.     }

  469.     /** Add a scaled vector to the instance.
  470.      * @param factor scale factor to apply to v before adding it
  471.      * @param v vector to add
  472.      * @return a new vector
  473.      */
  474.     public FieldVector3D<T> add(final T factor, final FieldVector3D<T> v) {
  475.         return new FieldVector3D<>(x.getField().getOne(), this, factor, v);
  476.     }

  477.     /** Add a scaled vector to the instance.
  478.      * @param factor scale factor to apply to v before adding it
  479.      * @param v vector to add
  480.      * @return a new vector
  481.      */
  482.     public FieldVector3D<T> add(final T factor, final Vector3D v) {
  483.         return new FieldVector3D<>(x.add(factor.multiply(v.getX())),
  484.                 y.add(factor.multiply(v.getY())),
  485.                 z.add(factor.multiply(v.getZ())));
  486.     }

  487.     /** Add a scaled vector to the instance.
  488.      * @param factor scale factor to apply to v before adding it
  489.      * @param v vector to add
  490.      * @return a new vector
  491.      */
  492.     public FieldVector3D<T> add(final double factor, final FieldVector3D<T> v) {
  493.         return new FieldVector3D<>(1.0, this, factor, v);
  494.     }

  495.     /** Add a scaled vector to the instance.
  496.      * @param factor scale factor to apply to v before adding it
  497.      * @param v vector to add
  498.      * @return a new vector
  499.      */
  500.     public FieldVector3D<T> add(final double factor, final Vector3D v) {
  501.         return new FieldVector3D<>(x.add(factor * v.getX()),
  502.                 y.add(factor * v.getY()),
  503.                 z.add(factor * v.getZ()));
  504.     }

  505.     /** Subtract a vector from the instance.
  506.      * @param v vector to subtract
  507.      * @return a new vector
  508.      */
  509.     public FieldVector3D<T> subtract(final FieldVector3D<T> v) {
  510.         return new FieldVector3D<>(x.subtract(v.x), y.subtract(v.y), z.subtract(v.z));
  511.     }

  512.     /** Subtract a vector from the instance.
  513.      * @param v vector to subtract
  514.      * @return a new vector
  515.      */
  516.     public FieldVector3D<T> subtract(final Vector3D v) {
  517.         return new FieldVector3D<>(x.subtract(v.getX()), y.subtract(v.getY()), z.subtract(v.getZ()));
  518.     }

  519.     /** Subtract a scaled vector from the instance.
  520.      * @param factor scale factor to apply to v before subtracting it
  521.      * @param v vector to subtract
  522.      * @return a new vector
  523.      */
  524.     public FieldVector3D<T> subtract(final T factor, final FieldVector3D<T> v) {
  525.         return new FieldVector3D<>(x.getField().getOne(), this, factor.negate(), v);
  526.     }

  527.     /** Subtract a scaled vector from the instance.
  528.      * @param factor scale factor to apply to v before subtracting it
  529.      * @param v vector to subtract
  530.      * @return a new vector
  531.      */
  532.     public FieldVector3D<T> subtract(final T factor, final Vector3D v) {
  533.         return new FieldVector3D<>(x.subtract(factor.multiply(v.getX())),
  534.                 y.subtract(factor.multiply(v.getY())),
  535.                 z.subtract(factor.multiply(v.getZ())));
  536.     }

  537.     /** Subtract a scaled vector from the instance.
  538.      * @param factor scale factor to apply to v before subtracting it
  539.      * @param v vector to subtract
  540.      * @return a new vector
  541.      */
  542.     public FieldVector3D<T> subtract(final double factor, final FieldVector3D<T> v) {
  543.         return new FieldVector3D<>(1.0, this, -factor, v);
  544.     }

  545.     /** Subtract a scaled vector from the instance.
  546.      * @param factor scale factor to apply to v before subtracting it
  547.      * @param v vector to subtract
  548.      * @return a new vector
  549.      */
  550.     public FieldVector3D<T> subtract(final double factor, final Vector3D v) {
  551.         return new FieldVector3D<>(x.subtract(factor * v.getX()),
  552.                 y.subtract(factor * v.getY()),
  553.                 z.subtract(factor * v.getZ()));
  554.     }

  555.     /** Get a normalized vector aligned with the instance.
  556.      * @return a new normalized vector
  557.      * @exception MathRuntimeException if the norm is zero
  558.      */
  559.     public FieldVector3D<T> normalize() throws MathRuntimeException {
  560.         final T s = getNorm();
  561.         if (s.getReal() == 0) {
  562.             throw new MathRuntimeException(LocalizedGeometryFormats.CANNOT_NORMALIZE_A_ZERO_NORM_VECTOR);
  563.         }
  564.         return scalarMultiply(s.reciprocal());
  565.     }

  566.     /** Get a vector orthogonal to the instance.
  567.      * <p>There are an infinite number of normalized vectors orthogonal
  568.      * to the instance. This method picks up one of them almost
  569.      * arbitrarily. It is useful when one needs to compute a reference
  570.      * frame with one of the axes in a predefined direction. The
  571.      * following example shows how to build a frame having the k axis
  572.      * aligned with the known vector u :
  573.      * </p>
  574.      * <pre><code>
  575.      *   Vector3D k = u.normalize();
  576.      *   Vector3D i = k.orthogonal();
  577.      *   Vector3D j = Vector3D.crossProduct(k, i);
  578.      * </code></pre>
  579.      * @return a new normalized vector orthogonal to the instance
  580.      * @exception MathRuntimeException if the norm of the instance is null
  581.      */
  582.     public FieldVector3D<T> orthogonal() throws MathRuntimeException {

  583.         final double threshold = 0.6 * getNorm().getReal();
  584.         if (threshold == 0) {
  585.             throw new MathRuntimeException(LocalizedCoreFormats.ZERO_NORM);
  586.         }

  587.         if (FastMath.abs(x.getReal()) <= threshold) {
  588.             final T inverse  = y.square().add(z.square()).sqrt().reciprocal();
  589.             return new FieldVector3D<>(inverse.getField().getZero(), inverse.multiply(z), inverse.multiply(y).negate());
  590.         } else if (FastMath.abs(y.getReal()) <= threshold) {
  591.             final T inverse  = x.square().add(z.square()).sqrt().reciprocal();
  592.             return new FieldVector3D<>(inverse.multiply(z).negate(), inverse.getField().getZero(), inverse.multiply(x));
  593.         } else {
  594.             final T inverse  = x.square().add(y.square()).sqrt().reciprocal();
  595.             return new FieldVector3D<>(inverse.multiply(y), inverse.multiply(x).negate(), inverse.getField().getZero());
  596.         }

  597.     }

  598.     /** Compute the angular separation between two vectors.
  599.      * <p>This method computes the angular separation between two
  600.      * vectors using the dot product for well separated vectors and the
  601.      * cross product for almost aligned vectors. This allows to have a
  602.      * good accuracy in all cases, even for vectors very close to each
  603.      * other.</p>
  604.      * @param v1 first vector
  605.      * @param v2 second vector
  606.      * @param <T> the type of the field elements
  607.      * @return angular separation between v1 and v2
  608.      * @exception MathRuntimeException if either vector has a null norm
  609.      */
  610.     public static <T extends CalculusFieldElement<T>> T angle(final FieldVector3D<T> v1, final FieldVector3D<T> v2)
  611.         throws MathRuntimeException {

  612.         final T normProduct = v1.getNorm().multiply(v2.getNorm());
  613.         if (normProduct.getReal() == 0) {
  614.             throw new MathRuntimeException(LocalizedCoreFormats.ZERO_NORM);
  615.         }

  616.         final T dot = dotProduct(v1, v2);
  617.         final double threshold = normProduct.getReal() * 0.9999;
  618.         if ((dot.getReal() < -threshold) || (dot.getReal() > threshold)) {
  619.             // the vectors are almost aligned, compute using the sine
  620.             FieldVector3D<T> v3 = crossProduct(v1, v2);
  621.             if (dot.getReal() >= 0) {
  622.                 return v3.getNorm().divide(normProduct).asin();
  623.             }
  624.             return v3.getNorm().divide(normProduct).asin().subtract(dot.getPi()).negate();
  625.         }

  626.         // the vectors are sufficiently separated to use the cosine
  627.         return dot.divide(normProduct).acos();

  628.     }

  629.     /** Compute the angular separation between two vectors.
  630.      * <p>This method computes the angular separation between two
  631.      * vectors using the dot product for well separated vectors and the
  632.      * cross product for almost aligned vectors. This allows to have a
  633.      * good accuracy in all cases, even for vectors very close to each
  634.      * other.</p>
  635.      * @param v1 first vector
  636.      * @param v2 second vector
  637.      * @param <T> the type of the field elements
  638.      * @return angular separation between v1 and v2
  639.      * @exception MathRuntimeException if either vector has a null norm
  640.      */
  641.     public static <T extends CalculusFieldElement<T>> T angle(final FieldVector3D<T> v1, final Vector3D v2)
  642.         throws MathRuntimeException {

  643.         final T normProduct = v1.getNorm().multiply(v2.getNorm());
  644.         if (normProduct.getReal() == 0) {
  645.             throw new MathRuntimeException(LocalizedCoreFormats.ZERO_NORM);
  646.         }

  647.         final T dot = dotProduct(v1, v2);
  648.         final double threshold = normProduct.getReal() * 0.9999;
  649.         if ((dot.getReal() < -threshold) || (dot.getReal() > threshold)) {
  650.             // the vectors are almost aligned, compute using the sine
  651.             FieldVector3D<T> v3 = crossProduct(v1, v2);
  652.             if (dot.getReal() >= 0) {
  653.                 return v3.getNorm().divide(normProduct).asin();
  654.             }
  655.             return v3.getNorm().divide(normProduct).asin().subtract(dot.getPi()).negate();
  656.         }

  657.         // the vectors are sufficiently separated to use the cosine
  658.         return dot.divide(normProduct).acos();

  659.     }

  660.     /** Compute the angular separation between two vectors.
  661.      * <p>This method computes the angular separation between two
  662.      * vectors using the dot product for well separated vectors and the
  663.      * cross product for almost aligned vectors. This allows to have a
  664.      * good accuracy in all cases, even for vectors very close to each
  665.      * other.</p>
  666.      * @param v1 first vector
  667.      * @param v2 second vector
  668.      * @param <T> the type of the field elements
  669.      * @return angular separation between v1 and v2
  670.      * @exception MathRuntimeException if either vector has a null norm
  671.      */
  672.     public static <T extends CalculusFieldElement<T>> T angle(final Vector3D v1, final FieldVector3D<T> v2)
  673.         throws MathRuntimeException {
  674.         return angle(v2, v1);
  675.     }

  676.     /** Get the opposite of the instance.
  677.      * @return a new vector which is opposite to the instance
  678.      */
  679.     public FieldVector3D<T> negate() {
  680.         return new FieldVector3D<>(x.negate(), y.negate(), z.negate());
  681.     }

  682.     /** Multiply the instance by a scalar.
  683.      * @param a scalar
  684.      * @return a new vector
  685.      */
  686.     public FieldVector3D<T> scalarMultiply(final T a) {
  687.         return new FieldVector3D<>(x.multiply(a), y.multiply(a), z.multiply(a));
  688.     }

  689.     /** Multiply the instance by a scalar.
  690.      * @param a scalar
  691.      * @return a new vector
  692.      */
  693.     public FieldVector3D<T> scalarMultiply(final double a) {
  694.         return new FieldVector3D<>(x.multiply(a), y.multiply(a), z.multiply(a));
  695.     }

  696.     /**
  697.      * Returns true if any coordinate of this vector is NaN; false otherwise
  698.      * @return  true if any coordinate of this vector is NaN; false otherwise
  699.      */
  700.     public boolean isNaN() {
  701.         return Double.isNaN(x.getReal()) || Double.isNaN(y.getReal()) || Double.isNaN(z.getReal());
  702.     }

  703.     /**
  704.      * Returns true if any coordinate of this vector is infinite and none are NaN;
  705.      * false otherwise
  706.      * @return  true if any coordinate of this vector is infinite and none are NaN;
  707.      * false otherwise
  708.      */
  709.     public boolean isInfinite() {
  710.         return !isNaN() && (Double.isInfinite(x.getReal()) || Double.isInfinite(y.getReal()) || Double.isInfinite(z.getReal()));
  711.     }

  712.     /**
  713.      * Test for the equality of two 3D vectors.
  714.      * <p>
  715.      * If all coordinates of two 3D vectors are exactly the same, and none of their
  716.      * {@link CalculusFieldElement#getReal() real part} are <code>NaN</code>, the
  717.      * two 3D vectors are considered to be equal.
  718.      * </p>
  719.      * <p>
  720.      * <code>NaN</code> coordinates are considered to affect globally the vector
  721.      * and be equals to each other - i.e, if either (or all) real part of the
  722.      * coordinates of the 3D vector are <code>NaN</code>, the 3D vector is <code>NaN</code>.
  723.      * </p>
  724.      *
  725.      * @param other Object to test for equality to this
  726.      * @return true if two 3D vector objects are equal, false if
  727.      *         object is null, not an instance of FieldVector3D, or
  728.      *         not equal to this FieldVector3D instance
  729.      *
  730.      */
  731.     @Override
  732.     public boolean equals(Object other) {

  733.         if (this == other) {
  734.             return true;
  735.         }

  736.         if (other instanceof FieldVector3D) {
  737.             @SuppressWarnings("unchecked")
  738.             final FieldVector3D<T> rhs = (FieldVector3D<T>) other;
  739.             if (rhs.isNaN()) {
  740.                 return this.isNaN();
  741.             }

  742.             return x.equals(rhs.x) && y.equals(rhs.y) && z.equals(rhs.z);

  743.         }
  744.         return false;
  745.     }

  746.     /**
  747.      * Get a hashCode for the 3D vector.
  748.      * <p>
  749.      * All NaN values have the same hash code.</p>
  750.      *
  751.      * @return a hash code value for this object
  752.      */
  753.     @Override
  754.     public int hashCode() {
  755.         if (isNaN()) {
  756.             return 409;
  757.         }
  758.         return 311 * (107 * x.hashCode() + 83 * y.hashCode() +  z.hashCode());
  759.     }

  760.     /** Compute the dot-product of the instance and another vector.
  761.      * <p>
  762.      * The implementation uses specific multiplication and addition
  763.      * algorithms to preserve accuracy and reduce cancellation effects.
  764.      * It should be very accurate even for nearly orthogonal vectors.
  765.      * </p>
  766.      * @see MathArrays#linearCombination(double, double, double, double, double, double)
  767.      * @param v second vector
  768.      * @return the dot product this.v
  769.      */
  770.     public T dotProduct(final FieldVector3D<T> v) {
  771.         return x.linearCombination(x, v.x, y, v.y, z, v.z);
  772.     }

  773.     /** Compute the dot-product of the instance and another vector.
  774.      * <p>
  775.      * The implementation uses specific multiplication and addition
  776.      * algorithms to preserve accuracy and reduce cancellation effects.
  777.      * It should be very accurate even for nearly orthogonal vectors.
  778.      * </p>
  779.      * @see MathArrays#linearCombination(double, double, double, double, double, double)
  780.      * @param v second vector
  781.      * @return the dot product this.v
  782.      */
  783.     public T dotProduct(final Vector3D v) {
  784.         return x.linearCombination(v.getX(), x, v.getY(), y, v.getZ(), z);
  785.     }

  786.     /** Compute the cross-product of the instance with another vector.
  787.      * @param v other vector
  788.      * @return the cross product this ^ v as a new Vector3D
  789.      */
  790.     public FieldVector3D<T> crossProduct(final FieldVector3D<T> v) {
  791.         return new FieldVector3D<>(x.linearCombination(y, v.z, z.negate(), v.y),
  792.                 y.linearCombination(z, v.x, x.negate(), v.z),
  793.                 z.linearCombination(x, v.y, y.negate(), v.x));
  794.     }

  795.     /** Compute the cross-product of the instance with another vector.
  796.      * @param v other vector
  797.      * @return the cross product this ^ v as a new Vector3D
  798.      */
  799.     public FieldVector3D<T> crossProduct(final Vector3D v) {
  800.         return new FieldVector3D<>(x.linearCombination(v.getZ(), y, -v.getY(), z),
  801.                 y.linearCombination(v.getX(), z, -v.getZ(), x),
  802.                 z.linearCombination(v.getY(), x, -v.getX(), y));
  803.     }

  804.     /** Compute the distance between the instance and another vector according to the L<sub>1</sub> norm.
  805.      * <p>Calling this method is equivalent to calling:
  806.      * <code>q.subtract(p).getNorm1()</code> except that no intermediate
  807.      * vector is built</p>
  808.      * @param v second vector
  809.      * @return the distance between the instance and p according to the L<sub>1</sub> norm
  810.      */
  811.     public T distance1(final FieldVector3D<T> v) {
  812.         final T dx = v.x.subtract(x).abs();
  813.         final T dy = v.y.subtract(y).abs();
  814.         final T dz = v.z.subtract(z).abs();
  815.         return dx.add(dy).add(dz);
  816.     }

  817.     /** Compute the distance between the instance and another vector according to the L<sub>1</sub> norm.
  818.      * <p>Calling this method is equivalent to calling:
  819.      * <code>q.subtract(p).getNorm1()</code> except that no intermediate
  820.      * vector is built</p>
  821.      * @param v second vector
  822.      * @return the distance between the instance and p according to the L<sub>1</sub> norm
  823.      */
  824.     public T distance1(final Vector3D v) {
  825.         final T dx = x.subtract(v.getX()).abs();
  826.         final T dy = y.subtract(v.getY()).abs();
  827.         final T dz = z.subtract(v.getZ()).abs();
  828.         return dx.add(dy).add(dz);
  829.     }

  830.     /** Compute the distance between the instance and another vector according to the L<sub>2</sub> norm.
  831.      * <p>Calling this method is equivalent to calling:
  832.      * <code>q.subtract(p).getNorm()</code> except that no intermediate
  833.      * vector is built</p>
  834.      * @param v second vector
  835.      * @return the distance between the instance and p according to the L<sub>2</sub> norm
  836.      */
  837.     public T distance(final FieldVector3D<T> v) {
  838.         final T dx = v.x.subtract(x);
  839.         final T dy = v.y.subtract(y);
  840.         final T dz = v.z.subtract(z);
  841.         return dx.square().add(dy.square()).add(dz.square()).sqrt();
  842.     }

  843.     /** Compute the distance between the instance and another vector according to the L<sub>2</sub> norm.
  844.      * <p>Calling this method is equivalent to calling:
  845.      * <code>q.subtract(p).getNorm()</code> except that no intermediate
  846.      * vector is built</p>
  847.      * @param v second vector
  848.      * @return the distance between the instance and p according to the L<sub>2</sub> norm
  849.      */
  850.     public T distance(final Vector3D v) {
  851.         final T dx = x.subtract(v.getX());
  852.         final T dy = y.subtract(v.getY());
  853.         final T dz = z.subtract(v.getZ());
  854.         return dx.square().add(dy.square()).add(dz.square()).sqrt();
  855.     }

  856.     /** Compute the distance between the instance and another vector according to the L<sub>&infin;</sub> norm.
  857.      * <p>Calling this method is equivalent to calling:
  858.      * <code>q.subtract(p).getNormInf()</code> except that no intermediate
  859.      * vector is built</p>
  860.      * @param v second vector
  861.      * @return the distance between the instance and p according to the L<sub>&infin;</sub> norm
  862.      */
  863.     public T distanceInf(final FieldVector3D<T> v) {
  864.         final T dx = v.x.subtract(x).abs();
  865.         final T dy = v.y.subtract(y).abs();
  866.         final T dz = v.z.subtract(z).abs();
  867.         if (dx.getReal() <= dy.getReal()) {
  868.             if (dy.getReal() <= dz.getReal()) {
  869.                 return dz;
  870.             } else {
  871.                 return dy;
  872.             }
  873.         } else {
  874.             if (dx.getReal() <= dz.getReal()) {
  875.                 return dz;
  876.             } else {
  877.                 return dx;
  878.             }
  879.         }
  880.     }

  881.     /** Compute the distance between the instance and another vector according to the L<sub>&infin;</sub> norm.
  882.      * <p>Calling this method is equivalent to calling:
  883.      * <code>q.subtract(p).getNormInf()</code> except that no intermediate
  884.      * vector is built</p>
  885.      * @param v second vector
  886.      * @return the distance between the instance and p according to the L<sub>&infin;</sub> norm
  887.      */
  888.     public T distanceInf(final Vector3D v) {
  889.         final T dx = x.subtract(v.getX()).abs();
  890.         final T dy = y.subtract(v.getY()).abs();
  891.         final T dz = z.subtract(v.getZ()).abs();
  892.         if (dx.getReal() <= dy.getReal()) {
  893.             if (dy.getReal() <= dz.getReal()) {
  894.                 return dz;
  895.             } else {
  896.                 return dy;
  897.             }
  898.         } else {
  899.             if (dx.getReal() <= dz.getReal()) {
  900.                 return dz;
  901.             } else {
  902.                 return dx;
  903.             }
  904.         }
  905.     }

  906.     /** Compute the square of the distance between the instance and another vector.
  907.      * <p>Calling this method is equivalent to calling:
  908.      * <code>q.subtract(p).getNormSq()</code> except that no intermediate
  909.      * vector is built</p>
  910.      * @param v second vector
  911.      * @return the square of the distance between the instance and p
  912.      */
  913.     public T distanceSq(final FieldVector3D<T> v) {
  914.         final T dx = v.x.subtract(x);
  915.         final T dy = v.y.subtract(y);
  916.         final T dz = v.z.subtract(z);
  917.         return dx.square().add(dy.square()).add(dz.square());
  918.     }

  919.     /** Compute the square of the distance between the instance and another vector.
  920.      * <p>Calling this method is equivalent to calling:
  921.      * <code>q.subtract(p).getNormSq()</code> except that no intermediate
  922.      * vector is built</p>
  923.      * @param v second vector
  924.      * @return the square of the distance between the instance and p
  925.      */
  926.     public T distanceSq(final Vector3D v) {
  927.         final T dx = x.subtract(v.getX());
  928.         final T dy = y.subtract(v.getY());
  929.         final T dz = z.subtract(v.getZ());
  930.         return dx.square().add(dy.square()).add(dz.square());
  931.     }

  932.     /** Compute the dot-product of two vectors.
  933.      * @param v1 first vector
  934.      * @param v2 second vector
  935.      * @param <T> the type of the field elements
  936.      * @return the dot product v1.v2
  937.      */
  938.     public static <T extends CalculusFieldElement<T>> T dotProduct(final FieldVector3D<T> v1,
  939.                                                                    final FieldVector3D<T> v2) {
  940.         return v1.dotProduct(v2);
  941.     }

  942.     /** Compute the dot-product of two vectors.
  943.      * @param v1 first vector
  944.      * @param v2 second vector
  945.      * @param <T> the type of the field elements
  946.      * @return the dot product v1.v2
  947.      */
  948.     public static <T extends CalculusFieldElement<T>> T dotProduct(final FieldVector3D<T> v1,
  949.                                                                    final Vector3D v2) {
  950.         return v1.dotProduct(v2);
  951.     }

  952.     /** Compute the dot-product of two vectors.
  953.      * @param v1 first vector
  954.      * @param v2 second vector
  955.      * @param <T> the type of the field elements
  956.      * @return the dot product v1.v2
  957.      */
  958.     public static <T extends CalculusFieldElement<T>> T dotProduct(final Vector3D v1,
  959.                                                                    final FieldVector3D<T> v2) {
  960.         return v2.dotProduct(v1);
  961.     }

  962.     /** Compute the cross-product of two vectors.
  963.      * @param v1 first vector
  964.      * @param v2 second vector
  965.      * @param <T> the type of the field elements
  966.      * @return the cross product v1 ^ v2 as a new Vector
  967.      */
  968.     public static <T extends CalculusFieldElement<T>> FieldVector3D<T> crossProduct(final FieldVector3D<T> v1,
  969.                                                                                     final FieldVector3D<T> v2) {
  970.         return v1.crossProduct(v2);
  971.     }

  972.     /** Compute the cross-product of two vectors.
  973.      * @param v1 first vector
  974.      * @param v2 second vector
  975.      * @param <T> the type of the field elements
  976.      * @return the cross product v1 ^ v2 as a new Vector
  977.      */
  978.     public static <T extends CalculusFieldElement<T>> FieldVector3D<T> crossProduct(final FieldVector3D<T> v1,
  979.                                                                                     final Vector3D v2) {
  980.         return v1.crossProduct(v2);
  981.     }

  982.     /** Compute the cross-product of two vectors.
  983.      * @param v1 first vector
  984.      * @param v2 second vector
  985.      * @param <T> the type of the field elements
  986.      * @return the cross product v1 ^ v2 as a new Vector
  987.      */
  988.     public static <T extends CalculusFieldElement<T>> FieldVector3D<T> crossProduct(final Vector3D v1,
  989.                                                                                     final FieldVector3D<T> v2) {
  990.         return new FieldVector3D<>(v2.x.linearCombination(v1.getY(), v2.z, -v1.getZ(), v2.y),
  991.                 v2.y.linearCombination(v1.getZ(), v2.x, -v1.getX(), v2.z),
  992.                 v2.z.linearCombination(v1.getX(), v2.y, -v1.getY(), v2.x));
  993.     }

  994.     /** Compute the distance between two vectors according to the L<sub>1</sub> norm.
  995.      * <p>Calling this method is equivalent to calling:
  996.      * <code>v1.subtract(v2).getNorm1()</code> except that no intermediate
  997.      * vector is built</p>
  998.      * @param v1 first vector
  999.      * @param v2 second vector
  1000.      * @param <T> the type of the field elements
  1001.      * @return the distance between v1 and v2 according to the L<sub>1</sub> norm
  1002.      */
  1003.     public static <T extends CalculusFieldElement<T>> T distance1(final FieldVector3D<T> v1,
  1004.                                                                   final FieldVector3D<T> v2) {
  1005.         return v1.distance1(v2);
  1006.     }

  1007.     /** Compute the distance between two vectors according to the L<sub>1</sub> norm.
  1008.      * <p>Calling this method is equivalent to calling:
  1009.      * <code>v1.subtract(v2).getNorm1()</code> except that no intermediate
  1010.      * vector is built</p>
  1011.      * @param v1 first vector
  1012.      * @param v2 second vector
  1013.      * @param <T> the type of the field elements
  1014.      * @return the distance between v1 and v2 according to the L<sub>1</sub> norm
  1015.      */
  1016.     public static <T extends CalculusFieldElement<T>> T distance1(final FieldVector3D<T> v1,
  1017.                                                                   final Vector3D v2) {
  1018.         return v1.distance1(v2);
  1019.     }

  1020.     /** Compute the distance between two vectors according to the L<sub>1</sub> norm.
  1021.      * <p>Calling this method is equivalent to calling:
  1022.      * <code>v1.subtract(v2).getNorm1()</code> except that no intermediate
  1023.      * vector is built</p>
  1024.      * @param v1 first vector
  1025.      * @param v2 second vector
  1026.      * @param <T> the type of the field elements
  1027.      * @return the distance between v1 and v2 according to the L<sub>1</sub> norm
  1028.      */
  1029.     public static <T extends CalculusFieldElement<T>> T distance1(final Vector3D v1,
  1030.                                                                   final FieldVector3D<T> v2) {
  1031.         return v2.distance1(v1);
  1032.     }

  1033.     /** Compute the distance between two vectors according to the L<sub>2</sub> norm.
  1034.      * <p>Calling this method is equivalent to calling:
  1035.      * <code>v1.subtract(v2).getNorm()</code> except that no intermediate
  1036.      * vector is built</p>
  1037.      * @param v1 first vector
  1038.      * @param v2 second vector
  1039.      * @param <T> the type of the field elements
  1040.      * @return the distance between v1 and v2 according to the L<sub>2</sub> norm
  1041.      */
  1042.     public static <T extends CalculusFieldElement<T>> T distance(final FieldVector3D<T> v1,
  1043.                                                                  final FieldVector3D<T> v2) {
  1044.         return v1.distance(v2);
  1045.     }

  1046.     /** Compute the distance between two vectors according to the L<sub>2</sub> norm.
  1047.      * <p>Calling this method is equivalent to calling:
  1048.      * <code>v1.subtract(v2).getNorm()</code> except that no intermediate
  1049.      * vector is built</p>
  1050.      * @param v1 first vector
  1051.      * @param v2 second vector
  1052.      * @param <T> the type of the field elements
  1053.      * @return the distance between v1 and v2 according to the L<sub>2</sub> norm
  1054.      */
  1055.     public static <T extends CalculusFieldElement<T>> T distance(final FieldVector3D<T> v1,
  1056.                                                                  final Vector3D v2) {
  1057.         return v1.distance(v2);
  1058.     }

  1059.     /** Compute the distance between two vectors according to the L<sub>2</sub> norm.
  1060.      * <p>Calling this method is equivalent to calling:
  1061.      * <code>v1.subtract(v2).getNorm()</code> except that no intermediate
  1062.      * vector is built</p>
  1063.      * @param v1 first vector
  1064.      * @param v2 second vector
  1065.      * @param <T> the type of the field elements
  1066.      * @return the distance between v1 and v2 according to the L<sub>2</sub> norm
  1067.      */
  1068.     public static <T extends CalculusFieldElement<T>> T distance(final Vector3D v1,
  1069.                                                                  final FieldVector3D<T> v2) {
  1070.         return v2.distance(v1);
  1071.     }

  1072.     /** Compute the distance between two vectors according to the L<sub>&infin;</sub> norm.
  1073.      * <p>Calling this method is equivalent to calling:
  1074.      * <code>v1.subtract(v2).getNormInf()</code> except that no intermediate
  1075.      * vector is built</p>
  1076.      * @param v1 first vector
  1077.      * @param v2 second vector
  1078.      * @param <T> the type of the field elements
  1079.      * @return the distance between v1 and v2 according to the L<sub>&infin;</sub> norm
  1080.      */
  1081.     public static <T extends CalculusFieldElement<T>> T distanceInf(final FieldVector3D<T> v1,
  1082.                                                                     final FieldVector3D<T> v2) {
  1083.         return v1.distanceInf(v2);
  1084.     }

  1085.     /** Compute the distance between two vectors according to the L<sub>&infin;</sub> norm.
  1086.      * <p>Calling this method is equivalent to calling:
  1087.      * <code>v1.subtract(v2).getNormInf()</code> except that no intermediate
  1088.      * vector is built</p>
  1089.      * @param v1 first vector
  1090.      * @param v2 second vector
  1091.      * @param <T> the type of the field elements
  1092.      * @return the distance between v1 and v2 according to the L<sub>&infin;</sub> norm
  1093.      */
  1094.     public static <T extends CalculusFieldElement<T>> T distanceInf(final FieldVector3D<T> v1,
  1095.                                                                     final Vector3D v2) {
  1096.         return v1.distanceInf(v2);
  1097.     }

  1098.     /** Compute the distance between two vectors according to the L<sub>&infin;</sub> norm.
  1099.      * <p>Calling this method is equivalent to calling:
  1100.      * <code>v1.subtract(v2).getNormInf()</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>&infin;</sub> norm
  1106.      */
  1107.     public static <T extends CalculusFieldElement<T>> T distanceInf(final Vector3D v1,
  1108.                                                                     final FieldVector3D<T> v2) {
  1109.         return v2.distanceInf(v1);
  1110.     }

  1111.     /** Compute the square of the distance between two vectors.
  1112.      * <p>Calling this method is equivalent to calling:
  1113.      * <code>v1.subtract(v2).getNormSq()</code> except that no intermediate
  1114.      * vector is built</p>
  1115.      * @param v1 first vector
  1116.      * @param v2 second vector
  1117.      * @param <T> the type of the field elements
  1118.      * @return the square of the distance between v1 and v2
  1119.      */
  1120.     public static <T extends CalculusFieldElement<T>> T distanceSq(final FieldVector3D<T> v1,
  1121.                                                                    final FieldVector3D<T> v2) {
  1122.         return v1.distanceSq(v2);
  1123.     }

  1124.     /** Compute the square of the distance between two vectors.
  1125.      * <p>Calling this method is equivalent to calling:
  1126.      * <code>v1.subtract(v2).getNormSq()</code> except that no intermediate
  1127.      * vector is built</p>
  1128.      * @param v1 first vector
  1129.      * @param v2 second vector
  1130.      * @param <T> the type of the field elements
  1131.      * @return the square of the distance between v1 and v2
  1132.      */
  1133.     public static <T extends CalculusFieldElement<T>> T distanceSq(final FieldVector3D<T> v1,
  1134.                                                                    final Vector3D v2) {
  1135.         return v1.distanceSq(v2);
  1136.     }

  1137.     /** Compute the square of the distance between two vectors.
  1138.      * <p>Calling this method is equivalent to calling:
  1139.      * <code>v1.subtract(v2).getNormSq()</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 square of the distance between v1 and v2
  1145.      */
  1146.     public static <T extends CalculusFieldElement<T>> T distanceSq(final Vector3D v1,
  1147.                                                                    final FieldVector3D<T> v2) {
  1148.         return v2.distanceSq(v1);
  1149.     }

  1150.     /** Get a string representation of this vector.
  1151.      * @return a string representation of this vector
  1152.      */
  1153.     @Override
  1154.     public String toString() {
  1155.         return Vector3DFormat.getVector3DFormat().format(toVector3D());
  1156.     }

  1157.     /** Get a string representation of this vector.
  1158.      * @param format the custom format for components
  1159.      * @return a string representation of this vector
  1160.      */
  1161.     public String toString(final NumberFormat format) {
  1162.         return new Vector3DFormat(format).format(toVector3D());
  1163.     }

  1164.     /** {@inheritDoc} */
  1165.     @Override
  1166.     public FieldVector3D<T> blendArithmeticallyWith(final FieldVector3D<T> other, final T blendingValue)
  1167.             throws MathIllegalArgumentException {
  1168.         SmoothStepFactory.checkBetweenZeroAndOneIncluded(blendingValue.getReal());
  1169.         final T one = x.getField().getOne();
  1170.         return this.scalarMultiply(one.subtract(blendingValue)).add(other.scalarMultiply(blendingValue));
  1171.     }
  1172. }