http://git-wip-us.apache.org/repos/asf/commons-math/blob/a7b4803f/src/main/java/org/apache/commons/math3/geometry/euclidean/threed/FieldVector3D.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math3/geometry/euclidean/threed/FieldVector3D.java b/src/main/java/org/apache/commons/math3/geometry/euclidean/threed/FieldVector3D.java deleted file mode 100644 index 0bd04e5..0000000 --- a/src/main/java/org/apache/commons/math3/geometry/euclidean/threed/FieldVector3D.java +++ /dev/null @@ -1,1185 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.math3.geometry.euclidean.threed; - -import java.io.Serializable; -import java.text.NumberFormat; - -import org.apache.commons.math3.RealFieldElement; -import org.apache.commons.math3.exception.DimensionMismatchException; -import org.apache.commons.math3.exception.MathArithmeticException; -import org.apache.commons.math3.exception.util.LocalizedFormats; -import org.apache.commons.math3.util.FastMath; -import org.apache.commons.math3.util.MathArrays; - -/** - * This class is a re-implementation of {@link Vector3D} using {@link RealFieldElement}. - * <p>Instance of this class are guaranteed to be immutable.</p> - * @param <T> the type of the field elements - * @since 3.2 - */ -public class FieldVector3D<T extends RealFieldElement<T>> implements Serializable { - - /** Serializable version identifier. */ - private static final long serialVersionUID = 20130224L; - - /** Abscissa. */ - private final T x; - - /** Ordinate. */ - private final T y; - - /** Height. */ - private final T z; - - /** Simple constructor. - * Build a vector from its coordinates - * @param x abscissa - * @param y ordinate - * @param z height - * @see #getX() - * @see #getY() - * @see #getZ() - */ - public FieldVector3D(final T x, final T y, final T z) { - this.x = x; - this.y = y; - this.z = z; - } - - /** Simple constructor. - * Build a vector from its coordinates - * @param v coordinates array - * @exception DimensionMismatchException if array does not have 3 elements - * @see #toArray() - */ - public FieldVector3D(final T[] v) throws DimensionMismatchException { - if (v.length != 3) { - throw new DimensionMismatchException(v.length, 3); - } - this.x = v[0]; - this.y = v[1]; - this.z = v[2]; - } - - /** Simple constructor. - * Build a vector from its azimuthal coordinates - * @param alpha azimuth (α) around Z - * (0 is +X, π/2 is +Y, π is -X and 3π/2 is -Y) - * @param delta elevation (δ) above (XY) plane, from -π/2 to +π/2 - * @see #getAlpha() - * @see #getDelta() - */ - public FieldVector3D(final T alpha, final T delta) { - T cosDelta = delta.cos(); - this.x = alpha.cos().multiply(cosDelta); - this.y = alpha.sin().multiply(cosDelta); - this.z = delta.sin(); - } - - /** Multiplicative constructor - * Build a vector from another one and a scale factor. - * The vector built will be a * u - * @param a scale factor - * @param u base (unscaled) vector - */ - public FieldVector3D(final T a, final FieldVector3D<T>u) { - this.x = a.multiply(u.x); - this.y = a.multiply(u.y); - this.z = a.multiply(u.z); - } - - /** Multiplicative constructor - * Build a vector from another one and a scale factor. - * The vector built will be a * u - * @param a scale factor - * @param u base (unscaled) vector - */ - public FieldVector3D(final T a, final Vector3D u) { - this.x = a.multiply(u.getX()); - this.y = a.multiply(u.getY()); - this.z = a.multiply(u.getZ()); - } - - /** Multiplicative constructor - * Build a vector from another one and a scale factor. - * The vector built will be a * u - * @param a scale factor - * @param u base (unscaled) vector - */ - public FieldVector3D(final double a, final FieldVector3D<T> u) { - this.x = u.x.multiply(a); - this.y = u.y.multiply(a); - this.z = u.z.multiply(a); - } - - /** Linear constructor - * Build a vector from two other ones and corresponding scale factors. - * The vector built will be a1 * u1 + a2 * u2 - * @param a1 first scale factor - * @param u1 first base (unscaled) vector - * @param a2 second scale factor - * @param u2 second base (unscaled) vector - */ - public FieldVector3D(final T a1, final FieldVector3D<T> u1, - final T a2, final FieldVector3D<T> u2) { - final T prototype = a1; - this.x = prototype.linearCombination(a1, u1.getX(), a2, u2.getX()); - this.y = prototype.linearCombination(a1, u1.getY(), a2, u2.getY()); - this.z = prototype.linearCombination(a1, u1.getZ(), a2, u2.getZ()); - } - - /** Linear constructor - * Build a vector from two other ones and corresponding scale factors. - * The vector built will be a1 * u1 + a2 * u2 - * @param a1 first scale factor - * @param u1 first base (unscaled) vector - * @param a2 second scale factor - * @param u2 second base (unscaled) vector - */ - public FieldVector3D(final T a1, final Vector3D u1, - final T a2, final Vector3D u2) { - final T prototype = a1; - this.x = prototype.linearCombination(u1.getX(), a1, u2.getX(), a2); - this.y = prototype.linearCombination(u1.getY(), a1, u2.getY(), a2); - this.z = prototype.linearCombination(u1.getZ(), a1, u2.getZ(), a2); - } - - /** Linear constructor - * Build a vector from two other ones and corresponding scale factors. - * The vector built will be a1 * u1 + a2 * u2 - * @param a1 first scale factor - * @param u1 first base (unscaled) vector - * @param a2 second scale factor - * @param u2 second base (unscaled) vector - */ - public FieldVector3D(final double a1, final FieldVector3D<T> u1, - final double a2, final FieldVector3D<T> u2) { - final T prototype = u1.getX(); - this.x = prototype.linearCombination(a1, u1.getX(), a2, u2.getX()); - this.y = prototype.linearCombination(a1, u1.getY(), a2, u2.getY()); - this.z = prototype.linearCombination(a1, u1.getZ(), a2, u2.getZ()); - } - - /** Linear constructor - * Build a vector from three other ones and corresponding scale factors. - * The vector built will be a1 * u1 + a2 * u2 + a3 * u3 - * @param a1 first scale factor - * @param u1 first base (unscaled) vector - * @param a2 second scale factor - * @param u2 second base (unscaled) vector - * @param a3 third scale factor - * @param u3 third base (unscaled) vector - */ - public FieldVector3D(final T a1, final FieldVector3D<T> u1, - final T a2, final FieldVector3D<T> u2, - final T a3, final FieldVector3D<T> u3) { - final T prototype = a1; - this.x = prototype.linearCombination(a1, u1.getX(), a2, u2.getX(), a3, u3.getX()); - this.y = prototype.linearCombination(a1, u1.getY(), a2, u2.getY(), a3, u3.getY()); - this.z = prototype.linearCombination(a1, u1.getZ(), a2, u2.getZ(), a3, u3.getZ()); - } - - /** Linear constructor - * Build a vector from three other ones and corresponding scale factors. - * The vector built will be a1 * u1 + a2 * u2 + a3 * u3 - * @param a1 first scale factor - * @param u1 first base (unscaled) vector - * @param a2 second scale factor - * @param u2 second base (unscaled) vector - * @param a3 third scale factor - * @param u3 third base (unscaled) vector - */ - public FieldVector3D(final T a1, final Vector3D u1, - final T a2, final Vector3D u2, - final T a3, final Vector3D u3) { - final T prototype = a1; - this.x = prototype.linearCombination(u1.getX(), a1, u2.getX(), a2, u3.getX(), a3); - this.y = prototype.linearCombination(u1.getY(), a1, u2.getY(), a2, u3.getY(), a3); - this.z = prototype.linearCombination(u1.getZ(), a1, u2.getZ(), a2, u3.getZ(), a3); - } - - /** Linear constructor - * Build a vector from three other ones and corresponding scale factors. - * The vector built will be a1 * u1 + a2 * u2 + a3 * u3 - * @param a1 first scale factor - * @param u1 first base (unscaled) vector - * @param a2 second scale factor - * @param u2 second base (unscaled) vector - * @param a3 third scale factor - * @param u3 third base (unscaled) vector - */ - public FieldVector3D(final double a1, final FieldVector3D<T> u1, - final double a2, final FieldVector3D<T> u2, - final double a3, final FieldVector3D<T> u3) { - final T prototype = u1.getX(); - this.x = prototype.linearCombination(a1, u1.getX(), a2, u2.getX(), a3, u3.getX()); - this.y = prototype.linearCombination(a1, u1.getY(), a2, u2.getY(), a3, u3.getY()); - this.z = prototype.linearCombination(a1, u1.getZ(), a2, u2.getZ(), a3, u3.getZ()); - } - - /** Linear constructor - * Build a vector from four other ones and corresponding scale factors. - * The vector built will be a1 * u1 + a2 * u2 + a3 * u3 + a4 * u4 - * @param a1 first scale factor - * @param u1 first base (unscaled) vector - * @param a2 second scale factor - * @param u2 second base (unscaled) vector - * @param a3 third scale factor - * @param u3 third base (unscaled) vector - * @param a4 fourth scale factor - * @param u4 fourth base (unscaled) vector - */ - public FieldVector3D(final T a1, final FieldVector3D<T> u1, - final T a2, final FieldVector3D<T> u2, - final T a3, final FieldVector3D<T> u3, - final T a4, final FieldVector3D<T> u4) { - final T prototype = a1; - this.x = prototype.linearCombination(a1, u1.getX(), a2, u2.getX(), a3, u3.getX(), a4, u4.getX()); - this.y = prototype.linearCombination(a1, u1.getY(), a2, u2.getY(), a3, u3.getY(), a4, u4.getY()); - this.z = prototype.linearCombination(a1, u1.getZ(), a2, u2.getZ(), a3, u3.getZ(), a4, u4.getZ()); - } - - /** Linear constructor - * Build a vector from four other ones and corresponding scale factors. - * The vector built will be a1 * u1 + a2 * u2 + a3 * u3 + a4 * u4 - * @param a1 first scale factor - * @param u1 first base (unscaled) vector - * @param a2 second scale factor - * @param u2 second base (unscaled) vector - * @param a3 third scale factor - * @param u3 third base (unscaled) vector - * @param a4 fourth scale factor - * @param u4 fourth base (unscaled) vector - */ - public FieldVector3D(final T a1, final Vector3D u1, - final T a2, final Vector3D u2, - final T a3, final Vector3D u3, - final T a4, final Vector3D u4) { - final T prototype = a1; - this.x = prototype.linearCombination(u1.getX(), a1, u2.getX(), a2, u3.getX(), a3, u4.getX(), a4); - this.y = prototype.linearCombination(u1.getY(), a1, u2.getY(), a2, u3.getY(), a3, u4.getY(), a4); - this.z = prototype.linearCombination(u1.getZ(), a1, u2.getZ(), a2, u3.getZ(), a3, u4.getZ(), a4); - } - - /** Linear constructor - * Build a vector from four other ones and corresponding scale factors. - * The vector built will be a1 * u1 + a2 * u2 + a3 * u3 + a4 * u4 - * @param a1 first scale factor - * @param u1 first base (unscaled) vector - * @param a2 second scale factor - * @param u2 second base (unscaled) vector - * @param a3 third scale factor - * @param u3 third base (unscaled) vector - * @param a4 fourth scale factor - * @param u4 fourth base (unscaled) vector - */ - public FieldVector3D(final double a1, final FieldVector3D<T> u1, - final double a2, final FieldVector3D<T> u2, - final double a3, final FieldVector3D<T> u3, - final double a4, final FieldVector3D<T> u4) { - final T prototype = u1.getX(); - this.x = prototype.linearCombination(a1, u1.getX(), a2, u2.getX(), a3, u3.getX(), a4, u4.getX()); - this.y = prototype.linearCombination(a1, u1.getY(), a2, u2.getY(), a3, u3.getY(), a4, u4.getY()); - this.z = prototype.linearCombination(a1, u1.getZ(), a2, u2.getZ(), a3, u3.getZ(), a4, u4.getZ()); - } - - /** Get the abscissa of the vector. - * @return abscissa of the vector - * @see #FieldVector3D(RealFieldElement, RealFieldElement, RealFieldElement) - */ - public T getX() { - return x; - } - - /** Get the ordinate of the vector. - * @return ordinate of the vector - * @see #FieldVector3D(RealFieldElement, RealFieldElement, RealFieldElement) - */ - public T getY() { - return y; - } - - /** Get the height of the vector. - * @return height of the vector - * @see #FieldVector3D(RealFieldElement, RealFieldElement, RealFieldElement) - */ - public T getZ() { - return z; - } - - /** Get the vector coordinates as a dimension 3 array. - * @return vector coordinates - * @see #FieldVector3D(RealFieldElement[]) - */ - public T[] toArray() { - final T[] array = MathArrays.buildArray(x.getField(), 3); - array[0] = x; - array[1] = y; - array[2] = z; - return array; - } - - /** Convert to a constant vector without derivatives. - * @return a constant vector - */ - public Vector3D toVector3D() { - return new Vector3D(x.getReal(), y.getReal(), z.getReal()); - } - - /** Get the L<sub>1</sub> norm for the vector. - * @return L<sub>1</sub> norm for the vector - */ - public T getNorm1() { - return x.abs().add(y.abs()).add(z.abs()); - } - - /** Get the L<sub>2</sub> norm for the vector. - * @return Euclidean norm for the vector - */ - public T getNorm() { - // there are no cancellation problems here, so we use the straightforward formula - return x.multiply(x).add(y.multiply(y)).add(z.multiply(z)).sqrt(); - } - - /** Get the square of the norm for the vector. - * @return square of the Euclidean norm for the vector - */ - public T getNormSq() { - // there are no cancellation problems here, so we use the straightforward formula - return x.multiply(x).add(y.multiply(y)).add(z.multiply(z)); - } - - /** Get the L<sub>∞</sub> norm for the vector. - * @return L<sub>∞</sub> norm for the vector - */ - public T getNormInf() { - final T xAbs = x.abs(); - final T yAbs = y.abs(); - final T zAbs = z.abs(); - if (xAbs.getReal() <= yAbs.getReal()) { - if (yAbs.getReal() <= zAbs.getReal()) { - return zAbs; - } else { - return yAbs; - } - } else { - if (xAbs.getReal() <= zAbs.getReal()) { - return zAbs; - } else { - return xAbs; - } - } - } - - /** Get the azimuth of the vector. - * @return azimuth (α) of the vector, between -π and +π - * @see #FieldVector3D(RealFieldElement, RealFieldElement) - */ - public T getAlpha() { - return y.atan2(x); - } - - /** Get the elevation of the vector. - * @return elevation (δ) of the vector, between -π/2 and +π/2 - * @see #FieldVector3D(RealFieldElement, RealFieldElement) - */ - public T getDelta() { - return z.divide(getNorm()).asin(); - } - - /** Add a vector to the instance. - * @param v vector to add - * @return a new vector - */ - public FieldVector3D<T> add(final FieldVector3D<T> v) { - return new FieldVector3D<T>(x.add(v.x), y.add(v.y), z.add(v.z)); - } - - /** Add a vector to the instance. - * @param v vector to add - * @return a new vector - */ - public FieldVector3D<T> add(final Vector3D v) { - return new FieldVector3D<T>(x.add(v.getX()), y.add(v.getY()), z.add(v.getZ())); - } - - /** Add a scaled vector to the instance. - * @param factor scale factor to apply to v before adding it - * @param v vector to add - * @return a new vector - */ - public FieldVector3D<T> add(final T factor, final FieldVector3D<T> v) { - return new FieldVector3D<T>(x.getField().getOne(), this, factor, v); - } - - /** Add a scaled vector to the instance. - * @param factor scale factor to apply to v before adding it - * @param v vector to add - * @return a new vector - */ - public FieldVector3D<T> add(final T factor, final Vector3D v) { - return new FieldVector3D<T>(x.add(factor.multiply(v.getX())), - y.add(factor.multiply(v.getY())), - z.add(factor.multiply(v.getZ()))); - } - - /** Add a scaled vector to the instance. - * @param factor scale factor to apply to v before adding it - * @param v vector to add - * @return a new vector - */ - public FieldVector3D<T> add(final double factor, final FieldVector3D<T> v) { - return new FieldVector3D<T>(1.0, this, factor, v); - } - - /** Add a scaled vector to the instance. - * @param factor scale factor to apply to v before adding it - * @param v vector to add - * @return a new vector - */ - public FieldVector3D<T> add(final double factor, final Vector3D v) { - return new FieldVector3D<T>(x.add(factor * v.getX()), - y.add(factor * v.getY()), - z.add(factor * v.getZ())); - } - - /** Subtract a vector from the instance. - * @param v vector to subtract - * @return a new vector - */ - public FieldVector3D<T> subtract(final FieldVector3D<T> v) { - return new FieldVector3D<T>(x.subtract(v.x), y.subtract(v.y), z.subtract(v.z)); - } - - /** Subtract a vector from the instance. - * @param v vector to subtract - * @return a new vector - */ - public FieldVector3D<T> subtract(final Vector3D v) { - return new FieldVector3D<T>(x.subtract(v.getX()), y.subtract(v.getY()), z.subtract(v.getZ())); - } - - /** Subtract a scaled vector from the instance. - * @param factor scale factor to apply to v before subtracting it - * @param v vector to subtract - * @return a new vector - */ - public FieldVector3D<T> subtract(final T factor, final FieldVector3D<T> v) { - return new FieldVector3D<T>(x.getField().getOne(), this, factor.negate(), v); - } - - /** Subtract a scaled vector from the instance. - * @param factor scale factor to apply to v before subtracting it - * @param v vector to subtract - * @return a new vector - */ - public FieldVector3D<T> subtract(final T factor, final Vector3D v) { - return new FieldVector3D<T>(x.subtract(factor.multiply(v.getX())), - y.subtract(factor.multiply(v.getY())), - z.subtract(factor.multiply(v.getZ()))); - } - - /** Subtract a scaled vector from the instance. - * @param factor scale factor to apply to v before subtracting it - * @param v vector to subtract - * @return a new vector - */ - public FieldVector3D<T> subtract(final double factor, final FieldVector3D<T> v) { - return new FieldVector3D<T>(1.0, this, -factor, v); - } - - /** Subtract a scaled vector from the instance. - * @param factor scale factor to apply to v before subtracting it - * @param v vector to subtract - * @return a new vector - */ - public FieldVector3D<T> subtract(final double factor, final Vector3D v) { - return new FieldVector3D<T>(x.subtract(factor * v.getX()), - y.subtract(factor * v.getY()), - z.subtract(factor * v.getZ())); - } - - /** Get a normalized vector aligned with the instance. - * @return a new normalized vector - * @exception MathArithmeticException if the norm is zero - */ - public FieldVector3D<T> normalize() throws MathArithmeticException { - final T s = getNorm(); - if (s.getReal() == 0) { - throw new MathArithmeticException(LocalizedFormats.CANNOT_NORMALIZE_A_ZERO_NORM_VECTOR); - } - return scalarMultiply(s.reciprocal()); - } - - /** Get a vector orthogonal to the instance. - * <p>There are an infinite number of normalized vectors orthogonal - * to the instance. This method picks up one of them almost - * arbitrarily. It is useful when one needs to compute a reference - * frame with one of the axes in a predefined direction. The - * following example shows how to build a frame having the k axis - * aligned with the known vector u : - * <pre><code> - * Vector3D k = u.normalize(); - * Vector3D i = k.orthogonal(); - * Vector3D j = Vector3D.crossProduct(k, i); - * </code></pre></p> - * @return a new normalized vector orthogonal to the instance - * @exception MathArithmeticException if the norm of the instance is null - */ - public FieldVector3D<T> orthogonal() throws MathArithmeticException { - - final double threshold = 0.6 * getNorm().getReal(); - if (threshold == 0) { - throw new MathArithmeticException(LocalizedFormats.ZERO_NORM); - } - - if (FastMath.abs(x.getReal()) <= threshold) { - final T inverse = y.multiply(y).add(z.multiply(z)).sqrt().reciprocal(); - return new FieldVector3D<T>(inverse.getField().getZero(), inverse.multiply(z), inverse.multiply(y).negate()); - } else if (FastMath.abs(y.getReal()) <= threshold) { - final T inverse = x.multiply(x).add(z.multiply(z)).sqrt().reciprocal(); - return new FieldVector3D<T>(inverse.multiply(z).negate(), inverse.getField().getZero(), inverse.multiply(x)); - } else { - final T inverse = x.multiply(x).add(y.multiply(y)).sqrt().reciprocal(); - return new FieldVector3D<T>(inverse.multiply(y), inverse.multiply(x).negate(), inverse.getField().getZero()); - } - - } - - /** Compute the angular separation between two vectors. - * <p>This method computes the angular separation between two - * vectors using the dot product for well separated vectors and the - * cross product for almost aligned vectors. This allows to have a - * good accuracy in all cases, even for vectors very close to each - * other.</p> - * @param v1 first vector - * @param v2 second vector - * @param <T> the type of the field elements - * @return angular separation between v1 and v2 - * @exception MathArithmeticException if either vector has a null norm - */ - public static <T extends RealFieldElement<T>> T angle(final FieldVector3D<T> v1, final FieldVector3D<T> v2) - throws MathArithmeticException { - - final T normProduct = v1.getNorm().multiply(v2.getNorm()); - if (normProduct.getReal() == 0) { - throw new MathArithmeticException(LocalizedFormats.ZERO_NORM); - } - - final T dot = dotProduct(v1, v2); - final double threshold = normProduct.getReal() * 0.9999; - if ((dot.getReal() < -threshold) || (dot.getReal() > threshold)) { - // the vectors are almost aligned, compute using the sine - FieldVector3D<T> v3 = crossProduct(v1, v2); - if (dot.getReal() >= 0) { - return v3.getNorm().divide(normProduct).asin(); - } - return v3.getNorm().divide(normProduct).asin().subtract(FastMath.PI).negate(); - } - - // the vectors are sufficiently separated to use the cosine - return dot.divide(normProduct).acos(); - - } - - /** Compute the angular separation between two vectors. - * <p>This method computes the angular separation between two - * vectors using the dot product for well separated vectors and the - * cross product for almost aligned vectors. This allows to have a - * good accuracy in all cases, even for vectors very close to each - * other.</p> - * @param v1 first vector - * @param v2 second vector - * @param <T> the type of the field elements - * @return angular separation between v1 and v2 - * @exception MathArithmeticException if either vector has a null norm - */ - public static <T extends RealFieldElement<T>> T angle(final FieldVector3D<T> v1, final Vector3D v2) - throws MathArithmeticException { - - final T normProduct = v1.getNorm().multiply(v2.getNorm()); - if (normProduct.getReal() == 0) { - throw new MathArithmeticException(LocalizedFormats.ZERO_NORM); - } - - final T dot = dotProduct(v1, v2); - final double threshold = normProduct.getReal() * 0.9999; - if ((dot.getReal() < -threshold) || (dot.getReal() > threshold)) { - // the vectors are almost aligned, compute using the sine - FieldVector3D<T> v3 = crossProduct(v1, v2); - if (dot.getReal() >= 0) { - return v3.getNorm().divide(normProduct).asin(); - } - return v3.getNorm().divide(normProduct).asin().subtract(FastMath.PI).negate(); - } - - // the vectors are sufficiently separated to use the cosine - return dot.divide(normProduct).acos(); - - } - - /** Compute the angular separation between two vectors. - * <p>This method computes the angular separation between two - * vectors using the dot product for well separated vectors and the - * cross product for almost aligned vectors. This allows to have a - * good accuracy in all cases, even for vectors very close to each - * other.</p> - * @param v1 first vector - * @param v2 second vector - * @param <T> the type of the field elements - * @return angular separation between v1 and v2 - * @exception MathArithmeticException if either vector has a null norm - */ - public static <T extends RealFieldElement<T>> T angle(final Vector3D v1, final FieldVector3D<T> v2) - throws MathArithmeticException { - return angle(v2, v1); - } - - /** Get the opposite of the instance. - * @return a new vector which is opposite to the instance - */ - public FieldVector3D<T> negate() { - return new FieldVector3D<T>(x.negate(), y.negate(), z.negate()); - } - - /** Multiply the instance by a scalar. - * @param a scalar - * @return a new vector - */ - public FieldVector3D<T> scalarMultiply(final T a) { - return new FieldVector3D<T>(x.multiply(a), y.multiply(a), z.multiply(a)); - } - - /** Multiply the instance by a scalar. - * @param a scalar - * @return a new vector - */ - public FieldVector3D<T> scalarMultiply(final double a) { - return new FieldVector3D<T>(x.multiply(a), y.multiply(a), z.multiply(a)); - } - - /** - * Returns true if any coordinate of this vector is NaN; false otherwise - * @return true if any coordinate of this vector is NaN; false otherwise - */ - public boolean isNaN() { - return Double.isNaN(x.getReal()) || Double.isNaN(y.getReal()) || Double.isNaN(z.getReal()); - } - - /** - * Returns true if any coordinate of this vector is infinite and none are NaN; - * false otherwise - * @return true if any coordinate of this vector is infinite and none are NaN; - * false otherwise - */ - public boolean isInfinite() { - return !isNaN() && (Double.isInfinite(x.getReal()) || Double.isInfinite(y.getReal()) || Double.isInfinite(z.getReal())); - } - - /** - * Test for the equality of two 3D vectors. - * <p> - * If all coordinates of two 3D vectors are exactly the same, and none of their - * {@link RealFieldElement#getReal() real part} are <code>NaN</code>, the - * two 3D vectors are considered to be equal. - * </p> - * <p> - * <code>NaN</code> coordinates are considered to affect globally the vector - * and be equals to each other - i.e, if either (or all) real part of the - * coordinates of the 3D vector are <code>NaN</code>, the 3D vector is <code>NaN</code>. - * </p> - * - * @param other Object to test for equality to this - * @return true if two 3D vector objects are equal, false if - * object is null, not an instance of Vector3D, or - * not equal to this Vector3D instance - * - */ - @Override - public boolean equals(Object other) { - - if (this == other) { - return true; - } - - if (other instanceof FieldVector3D) { - @SuppressWarnings("unchecked") - final FieldVector3D<T> rhs = (FieldVector3D<T>) other; - if (rhs.isNaN()) { - return this.isNaN(); - } - - return x.equals(rhs.x) && y.equals(rhs.y) && z.equals(rhs.z); - - } - return false; - } - - /** - * Get a hashCode for the 3D vector. - * <p> - * All NaN values have the same hash code.</p> - * - * @return a hash code value for this object - */ - @Override - public int hashCode() { - if (isNaN()) { - return 409; - } - return 311 * (107 * x.hashCode() + 83 * y.hashCode() + z.hashCode()); - } - - /** Compute the dot-product of the instance and another vector. - * <p> - * The implementation uses specific multiplication and addition - * algorithms to preserve accuracy and reduce cancellation effects. - * It should be very accurate even for nearly orthogonal vectors. - * </p> - * @see MathArrays#linearCombination(double, double, double, double, double, double) - * @param v second vector - * @return the dot product this.v - */ - public T dotProduct(final FieldVector3D<T> v) { - return x.linearCombination(x, v.x, y, v.y, z, v.z); - } - - /** Compute the dot-product of the instance and another vector. - * <p> - * The implementation uses specific multiplication and addition - * algorithms to preserve accuracy and reduce cancellation effects. - * It should be very accurate even for nearly orthogonal vectors. - * </p> - * @see MathArrays#linearCombination(double, double, double, double, double, double) - * @param v second vector - * @return the dot product this.v - */ - public T dotProduct(final Vector3D v) { - return x.linearCombination(v.getX(), x, v.getY(), y, v.getZ(), z); - } - - /** Compute the cross-product of the instance with another vector. - * @param v other vector - * @return the cross product this ^ v as a new Vector3D - */ - public FieldVector3D<T> crossProduct(final FieldVector3D<T> v) { - return new FieldVector3D<T>(x.linearCombination(y, v.z, z.negate(), v.y), - y.linearCombination(z, v.x, x.negate(), v.z), - z.linearCombination(x, v.y, y.negate(), v.x)); - } - - /** Compute the cross-product of the instance with another vector. - * @param v other vector - * @return the cross product this ^ v as a new Vector3D - */ - public FieldVector3D<T> crossProduct(final Vector3D v) { - return new FieldVector3D<T>(x.linearCombination(v.getZ(), y, -v.getY(), z), - y.linearCombination(v.getX(), z, -v.getZ(), x), - z.linearCombination(v.getY(), x, -v.getX(), y)); - } - - /** Compute the distance between the instance and another vector according to the L<sub>1</sub> norm. - * <p>Calling this method is equivalent to calling: - * <code>q.subtract(p).getNorm1()</code> except that no intermediate - * vector is built</p> - * @param v second vector - * @return the distance between the instance and p according to the L<sub>1</sub> norm - */ - public T distance1(final FieldVector3D<T> v) { - final T dx = v.x.subtract(x).abs(); - final T dy = v.y.subtract(y).abs(); - final T dz = v.z.subtract(z).abs(); - return dx.add(dy).add(dz); - } - - /** Compute the distance between the instance and another vector according to the L<sub>1</sub> norm. - * <p>Calling this method is equivalent to calling: - * <code>q.subtract(p).getNorm1()</code> except that no intermediate - * vector is built</p> - * @param v second vector - * @return the distance between the instance and p according to the L<sub>1</sub> norm - */ - public T distance1(final Vector3D v) { - final T dx = x.subtract(v.getX()).abs(); - final T dy = y.subtract(v.getY()).abs(); - final T dz = z.subtract(v.getZ()).abs(); - return dx.add(dy).add(dz); - } - - /** Compute the distance between the instance and another vector according to the L<sub>2</sub> norm. - * <p>Calling this method is equivalent to calling: - * <code>q.subtract(p).getNorm()</code> except that no intermediate - * vector is built</p> - * @param v second vector - * @return the distance between the instance and p according to the L<sub>2</sub> norm - */ - public T distance(final FieldVector3D<T> v) { - final T dx = v.x.subtract(x); - final T dy = v.y.subtract(y); - final T dz = v.z.subtract(z); - return dx.multiply(dx).add(dy.multiply(dy)).add(dz.multiply(dz)).sqrt(); - } - - /** Compute the distance between the instance and another vector according to the L<sub>2</sub> norm. - * <p>Calling this method is equivalent to calling: - * <code>q.subtract(p).getNorm()</code> except that no intermediate - * vector is built</p> - * @param v second vector - * @return the distance between the instance and p according to the L<sub>2</sub> norm - */ - public T distance(final Vector3D v) { - final T dx = x.subtract(v.getX()); - final T dy = y.subtract(v.getY()); - final T dz = z.subtract(v.getZ()); - return dx.multiply(dx).add(dy.multiply(dy)).add(dz.multiply(dz)).sqrt(); - } - - /** Compute the distance between the instance and another vector according to the L<sub>∞</sub> norm. - * <p>Calling this method is equivalent to calling: - * <code>q.subtract(p).getNormInf()</code> except that no intermediate - * vector is built</p> - * @param v second vector - * @return the distance between the instance and p according to the L<sub>∞</sub> norm - */ - public T distanceInf(final FieldVector3D<T> v) { - final T dx = v.x.subtract(x).abs(); - final T dy = v.y.subtract(y).abs(); - final T dz = v.z.subtract(z).abs(); - if (dx.getReal() <= dy.getReal()) { - if (dy.getReal() <= dz.getReal()) { - return dz; - } else { - return dy; - } - } else { - if (dx.getReal() <= dz.getReal()) { - return dz; - } else { - return dx; - } - } - } - - /** Compute the distance between the instance and another vector according to the L<sub>∞</sub> norm. - * <p>Calling this method is equivalent to calling: - * <code>q.subtract(p).getNormInf()</code> except that no intermediate - * vector is built</p> - * @param v second vector - * @return the distance between the instance and p according to the L<sub>∞</sub> norm - */ - public T distanceInf(final Vector3D v) { - final T dx = x.subtract(v.getX()).abs(); - final T dy = y.subtract(v.getY()).abs(); - final T dz = z.subtract(v.getZ()).abs(); - if (dx.getReal() <= dy.getReal()) { - if (dy.getReal() <= dz.getReal()) { - return dz; - } else { - return dy; - } - } else { - if (dx.getReal() <= dz.getReal()) { - return dz; - } else { - return dx; - } - } - } - - /** Compute the square of the distance between the instance and another vector. - * <p>Calling this method is equivalent to calling: - * <code>q.subtract(p).getNormSq()</code> except that no intermediate - * vector is built</p> - * @param v second vector - * @return the square of the distance between the instance and p - */ - public T distanceSq(final FieldVector3D<T> v) { - final T dx = v.x.subtract(x); - final T dy = v.y.subtract(y); - final T dz = v.z.subtract(z); - return dx.multiply(dx).add(dy.multiply(dy)).add(dz.multiply(dz)); - } - - /** Compute the square of the distance between the instance and another vector. - * <p>Calling this method is equivalent to calling: - * <code>q.subtract(p).getNormSq()</code> except that no intermediate - * vector is built</p> - * @param v second vector - * @return the square of the distance between the instance and p - */ - public T distanceSq(final Vector3D v) { - final T dx = x.subtract(v.getX()); - final T dy = y.subtract(v.getY()); - final T dz = z.subtract(v.getZ()); - return dx.multiply(dx).add(dy.multiply(dy)).add(dz.multiply(dz)); - } - - /** Compute the dot-product of two vectors. - * @param v1 first vector - * @param v2 second vector - * @param <T> the type of the field elements - * @return the dot product v1.v2 - */ - public static <T extends RealFieldElement<T>> T dotProduct(final FieldVector3D<T> v1, - final FieldVector3D<T> v2) { - return v1.dotProduct(v2); - } - - /** Compute the dot-product of two vectors. - * @param v1 first vector - * @param v2 second vector - * @param <T> the type of the field elements - * @return the dot product v1.v2 - */ - public static <T extends RealFieldElement<T>> T dotProduct(final FieldVector3D<T> v1, - final Vector3D v2) { - return v1.dotProduct(v2); - } - - /** Compute the dot-product of two vectors. - * @param v1 first vector - * @param v2 second vector - * @param <T> the type of the field elements - * @return the dot product v1.v2 - */ - public static <T extends RealFieldElement<T>> T dotProduct(final Vector3D v1, - final FieldVector3D<T> v2) { - return v2.dotProduct(v1); - } - - /** Compute the cross-product of two vectors. - * @param v1 first vector - * @param v2 second vector - * @param <T> the type of the field elements - * @return the cross product v1 ^ v2 as a new Vector - */ - public static <T extends RealFieldElement<T>> FieldVector3D<T> crossProduct(final FieldVector3D<T> v1, - final FieldVector3D<T> v2) { - return v1.crossProduct(v2); - } - - /** Compute the cross-product of two vectors. - * @param v1 first vector - * @param v2 second vector - * @param <T> the type of the field elements - * @return the cross product v1 ^ v2 as a new Vector - */ - public static <T extends RealFieldElement<T>> FieldVector3D<T> crossProduct(final FieldVector3D<T> v1, - final Vector3D v2) { - return v1.crossProduct(v2); - } - - /** Compute the cross-product of two vectors. - * @param v1 first vector - * @param v2 second vector - * @param <T> the type of the field elements - * @return the cross product v1 ^ v2 as a new Vector - */ - public static <T extends RealFieldElement<T>> FieldVector3D<T> crossProduct(final Vector3D v1, - final FieldVector3D<T> v2) { - return new FieldVector3D<T>(v2.x.linearCombination(v1.getY(), v2.z, -v1.getZ(), v2.y), - v2.y.linearCombination(v1.getZ(), v2.x, -v1.getX(), v2.z), - v2.z.linearCombination(v1.getX(), v2.y, -v1.getY(), v2.x)); - } - - /** Compute the distance between two vectors according to the L<sub>1</sub> norm. - * <p>Calling this method is equivalent to calling: - * <code>v1.subtract(v2).getNorm1()</code> except that no intermediate - * vector is built</p> - * @param v1 first vector - * @param v2 second vector - * @param <T> the type of the field elements - * @return the distance between v1 and v2 according to the L<sub>1</sub> norm - */ - public static <T extends RealFieldElement<T>> T distance1(final FieldVector3D<T> v1, - final FieldVector3D<T> v2) { - return v1.distance1(v2); - } - - /** Compute the distance between two vectors according to the L<sub>1</sub> norm. - * <p>Calling this method is equivalent to calling: - * <code>v1.subtract(v2).getNorm1()</code> except that no intermediate - * vector is built</p> - * @param v1 first vector - * @param v2 second vector - * @param <T> the type of the field elements - * @return the distance between v1 and v2 according to the L<sub>1</sub> norm - */ - public static <T extends RealFieldElement<T>> T distance1(final FieldVector3D<T> v1, - final Vector3D v2) { - return v1.distance1(v2); - } - - /** Compute the distance between two vectors according to the L<sub>1</sub> norm. - * <p>Calling this method is equivalent to calling: - * <code>v1.subtract(v2).getNorm1()</code> except that no intermediate - * vector is built</p> - * @param v1 first vector - * @param v2 second vector - * @param <T> the type of the field elements - * @return the distance between v1 and v2 according to the L<sub>1</sub> norm - */ - public static <T extends RealFieldElement<T>> T distance1(final Vector3D v1, - final FieldVector3D<T> v2) { - return v2.distance1(v1); - } - - /** Compute the distance between two vectors according to the L<sub>2</sub> norm. - * <p>Calling this method is equivalent to calling: - * <code>v1.subtract(v2).getNorm()</code> except that no intermediate - * vector is built</p> - * @param v1 first vector - * @param v2 second vector - * @param <T> the type of the field elements - * @return the distance between v1 and v2 according to the L<sub>2</sub> norm - */ - public static <T extends RealFieldElement<T>> T distance(final FieldVector3D<T> v1, - final FieldVector3D<T> v2) { - return v1.distance(v2); - } - - /** Compute the distance between two vectors according to the L<sub>2</sub> norm. - * <p>Calling this method is equivalent to calling: - * <code>v1.subtract(v2).getNorm()</code> except that no intermediate - * vector is built</p> - * @param v1 first vector - * @param v2 second vector - * @param <T> the type of the field elements - * @return the distance between v1 and v2 according to the L<sub>2</sub> norm - */ - public static <T extends RealFieldElement<T>> T distance(final FieldVector3D<T> v1, - final Vector3D v2) { - return v1.distance(v2); - } - - /** Compute the distance between two vectors according to the L<sub>2</sub> norm. - * <p>Calling this method is equivalent to calling: - * <code>v1.subtract(v2).getNorm()</code> except that no intermediate - * vector is built</p> - * @param v1 first vector - * @param v2 second vector - * @param <T> the type of the field elements - * @return the distance between v1 and v2 according to the L<sub>2</sub> norm - */ - public static <T extends RealFieldElement<T>> T distance(final Vector3D v1, - final FieldVector3D<T> v2) { - return v2.distance(v1); - } - - /** Compute the distance between two vectors according to the L<sub>∞</sub> norm. - * <p>Calling this method is equivalent to calling: - * <code>v1.subtract(v2).getNormInf()</code> except that no intermediate - * vector is built</p> - * @param v1 first vector - * @param v2 second vector - * @param <T> the type of the field elements - * @return the distance between v1 and v2 according to the L<sub>∞</sub> norm - */ - public static <T extends RealFieldElement<T>> T distanceInf(final FieldVector3D<T> v1, - final FieldVector3D<T> v2) { - return v1.distanceInf(v2); - } - - /** Compute the distance between two vectors according to the L<sub>∞</sub> norm. - * <p>Calling this method is equivalent to calling: - * <code>v1.subtract(v2).getNormInf()</code> except that no intermediate - * vector is built</p> - * @param v1 first vector - * @param v2 second vector - * @param <T> the type of the field elements - * @return the distance between v1 and v2 according to the L<sub>∞</sub> norm - */ - public static <T extends RealFieldElement<T>> T distanceInf(final FieldVector3D<T> v1, - final Vector3D v2) { - return v1.distanceInf(v2); - } - - /** Compute the distance between two vectors according to the L<sub>∞</sub> norm. - * <p>Calling this method is equivalent to calling: - * <code>v1.subtract(v2).getNormInf()</code> except that no intermediate - * vector is built</p> - * @param v1 first vector - * @param v2 second vector - * @param <T> the type of the field elements - * @return the distance between v1 and v2 according to the L<sub>∞</sub> norm - */ - public static <T extends RealFieldElement<T>> T distanceInf(final Vector3D v1, - final FieldVector3D<T> v2) { - return v2.distanceInf(v1); - } - - /** Compute the square of the distance between two vectors. - * <p>Calling this method is equivalent to calling: - * <code>v1.subtract(v2).getNormSq()</code> except that no intermediate - * vector is built</p> - * @param v1 first vector - * @param v2 second vector - * @param <T> the type of the field elements - * @return the square of the distance between v1 and v2 - */ - public static <T extends RealFieldElement<T>> T distanceSq(final FieldVector3D<T> v1, - final FieldVector3D<T> v2) { - return v1.distanceSq(v2); - } - - /** Compute the square of the distance between two vectors. - * <p>Calling this method is equivalent to calling: - * <code>v1.subtract(v2).getNormSq()</code> except that no intermediate - * vector is built</p> - * @param v1 first vector - * @param v2 second vector - * @param <T> the type of the field elements - * @return the square of the distance between v1 and v2 - */ - public static <T extends RealFieldElement<T>> T distanceSq(final FieldVector3D<T> v1, - final Vector3D v2) { - return v1.distanceSq(v2); - } - - /** Compute the square of the distance between two vectors. - * <p>Calling this method is equivalent to calling: - * <code>v1.subtract(v2).getNormSq()</code> except that no intermediate - * vector is built</p> - * @param v1 first vector - * @param v2 second vector - * @param <T> the type of the field elements - * @return the square of the distance between v1 and v2 - */ - public static <T extends RealFieldElement<T>> T distanceSq(final Vector3D v1, - final FieldVector3D<T> v2) { - return v2.distanceSq(v1); - } - - /** Get a string representation of this vector. - * @return a string representation of this vector - */ - @Override - public String toString() { - return Vector3DFormat.getInstance().format(toVector3D()); - } - - /** Get a string representation of this vector. - * @param format the custom format for components - * @return a string representation of this vector - */ - public String toString(final NumberFormat format) { - return new Vector3DFormat(format).format(toVector3D()); - } - -}
http://git-wip-us.apache.org/repos/asf/commons-math/blob/a7b4803f/src/main/java/org/apache/commons/math3/geometry/euclidean/threed/Line.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math3/geometry/euclidean/threed/Line.java b/src/main/java/org/apache/commons/math3/geometry/euclidean/threed/Line.java deleted file mode 100644 index e234495..0000000 --- a/src/main/java/org/apache/commons/math3/geometry/euclidean/threed/Line.java +++ /dev/null @@ -1,275 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.commons.math3.geometry.euclidean.threed; - -import org.apache.commons.math3.exception.MathIllegalArgumentException; -import org.apache.commons.math3.exception.util.LocalizedFormats; -import org.apache.commons.math3.geometry.Point; -import org.apache.commons.math3.geometry.Vector; -import org.apache.commons.math3.geometry.euclidean.oned.Euclidean1D; -import org.apache.commons.math3.geometry.euclidean.oned.IntervalsSet; -import org.apache.commons.math3.geometry.euclidean.oned.Vector1D; -import org.apache.commons.math3.geometry.partitioning.Embedding; -import org.apache.commons.math3.util.FastMath; -import org.apache.commons.math3.util.Precision; - -/** The class represent lines in a three dimensional space. - - * <p>Each oriented line is intrinsically associated with an abscissa - * which is a coordinate on the line. The point at abscissa 0 is the - * orthogonal projection of the origin on the line, another equivalent - * way to express this is to say that it is the point of the line - * which is closest to the origin. Abscissa increases in the line - * direction.</p> - - * @since 3.0 - */ -public class Line implements Embedding<Euclidean3D, Euclidean1D> { - - /** Default value for tolerance. */ - private static final double DEFAULT_TOLERANCE = 1.0e-10; - - /** Line direction. */ - private Vector3D direction; - - /** Line point closest to the origin. */ - private Vector3D zero; - - /** Tolerance below which points are considered identical. */ - private final double tolerance; - - /** Build a line from two points. - * @param p1 first point belonging to the line (this can be any point) - * @param p2 second point belonging to the line (this can be any point, different from p1) - * @param tolerance tolerance below which points are considered identical - * @exception MathIllegalArgumentException if the points are equal - * @since 3.3 - */ - public Line(final Vector3D p1, final Vector3D p2, final double tolerance) - throws MathIllegalArgumentException { - reset(p1, p2); - this.tolerance = tolerance; - } - - /** Copy constructor. - * <p>The created instance is completely independent from the - * original instance, it is a deep copy.</p> - * @param line line to copy - */ - public Line(final Line line) { - this.direction = line.direction; - this.zero = line.zero; - this.tolerance = line.tolerance; - } - - /** Build a line from two points. - * @param p1 first point belonging to the line (this can be any point) - * @param p2 second point belonging to the line (this can be any point, different from p1) - * @exception MathIllegalArgumentException if the points are equal - * @deprecated as of 3.3, replaced with {@link #Line(Vector3D, Vector3D, double)} - */ - @Deprecated - public Line(final Vector3D p1, final Vector3D p2) throws MathIllegalArgumentException { - this(p1, p2, DEFAULT_TOLERANCE); - } - - /** Reset the instance as if built from two points. - * @param p1 first point belonging to the line (this can be any point) - * @param p2 second point belonging to the line (this can be any point, different from p1) - * @exception MathIllegalArgumentException if the points are equal - */ - public void reset(final Vector3D p1, final Vector3D p2) throws MathIllegalArgumentException { - final Vector3D delta = p2.subtract(p1); - final double norm2 = delta.getNormSq(); - if (norm2 == 0.0) { - throw new MathIllegalArgumentException(LocalizedFormats.ZERO_NORM); - } - this.direction = new Vector3D(1.0 / FastMath.sqrt(norm2), delta); - zero = new Vector3D(1.0, p1, -p1.dotProduct(delta) / norm2, delta); - } - - /** Get the tolerance below which points are considered identical. - * @return tolerance below which points are considered identical - * @since 3.3 - */ - public double getTolerance() { - return tolerance; - } - - /** Get a line with reversed direction. - * @return a new instance, with reversed direction - */ - public Line revert() { - final Line reverted = new Line(this); - reverted.direction = reverted.direction.negate(); - return reverted; - } - - /** Get the normalized direction vector. - * @return normalized direction vector - */ - public Vector3D getDirection() { - return direction; - } - - /** Get the line point closest to the origin. - * @return line point closest to the origin - */ - public Vector3D getOrigin() { - return zero; - } - - /** Get the abscissa of a point with respect to the line. - * <p>The abscissa is 0 if the projection of the point and the - * projection of the frame origin on the line are the same - * point.</p> - * @param point point to check - * @return abscissa of the point - */ - public double getAbscissa(final Vector3D point) { - return point.subtract(zero).dotProduct(direction); - } - - /** Get one point from the line. - * @param abscissa desired abscissa for the point - * @return one point belonging to the line, at specified abscissa - */ - public Vector3D pointAt(final double abscissa) { - return new Vector3D(1.0, zero, abscissa, direction); - } - - /** Transform a space point into a sub-space point. - * @param vector n-dimension point of the space - * @return (n-1)-dimension point of the sub-space corresponding to - * the specified space point - */ - public Vector1D toSubSpace(Vector<Euclidean3D> vector) { - return toSubSpace((Point<Euclidean3D>) vector); - } - - /** Transform a sub-space point into a space point. - * @param vector (n-1)-dimension point of the sub-space - * @return n-dimension point of the space corresponding to the - * specified sub-space point - */ - public Vector3D toSpace(Vector<Euclidean1D> vector) { - return toSpace((Point<Euclidean1D>) vector); - } - - /** {@inheritDoc} - * @see #getAbscissa(Vector3D) - */ - public Vector1D toSubSpace(final Point<Euclidean3D> point) { - return new Vector1D(getAbscissa((Vector3D) point)); - } - - /** {@inheritDoc} - * @see #pointAt(double) - */ - public Vector3D toSpace(final Point<Euclidean1D> point) { - return pointAt(((Vector1D) point).getX()); - } - - /** Check if the instance is similar to another line. - * <p>Lines are considered similar if they contain the same - * points. This does not mean they are equal since they can have - * opposite directions.</p> - * @param line line to which instance should be compared - * @return true if the lines are similar - */ - public boolean isSimilarTo(final Line line) { - final double angle = Vector3D.angle(direction, line.direction); - return ((angle < tolerance) || (angle > (FastMath.PI - tolerance))) && contains(line.zero); - } - - /** Check if the instance contains a point. - * @param p point to check - * @return true if p belongs to the line - */ - public boolean contains(final Vector3D p) { - return distance(p) < tolerance; - } - - /** Compute the distance between the instance and a point. - * @param p to check - * @return distance between the instance and the point - */ - public double distance(final Vector3D p) { - final Vector3D d = p.subtract(zero); - final Vector3D n = new Vector3D(1.0, d, -d.dotProduct(direction), direction); - return n.getNorm(); - } - - /** Compute the shortest distance between the instance and another line. - * @param line line to check against the instance - * @return shortest distance between the instance and the line - */ - public double distance(final Line line) { - - final Vector3D normal = Vector3D.crossProduct(direction, line.direction); - final double n = normal.getNorm(); - if (n < Precision.SAFE_MIN) { - // lines are parallel - return distance(line.zero); - } - - // signed separation of the two parallel planes that contains the lines - final double offset = line.zero.subtract(zero).dotProduct(normal) / n; - - return FastMath.abs(offset); - - } - - /** Compute the point of the instance closest to another line. - * @param line line to check against the instance - * @return point of the instance closest to another line - */ - public Vector3D closestPoint(final Line line) { - - final double cos = direction.dotProduct(line.direction); - final double n = 1 - cos * cos; - if (n < Precision.EPSILON) { - // the lines are parallel - return zero; - } - - final Vector3D delta0 = line.zero.subtract(zero); - final double a = delta0.dotProduct(direction); - final double b = delta0.dotProduct(line.direction); - - return new Vector3D(1, zero, (a - b * cos) / n, direction); - - } - - /** Get the intersection point of the instance and another line. - * @param line other line - * @return intersection point of the instance and the other line - * or null if there are no intersection points - */ - public Vector3D intersection(final Line line) { - final Vector3D closest = closestPoint(line); - return line.contains(closest) ? closest : null; - } - - /** Build a sub-line covering the whole line. - * @return a sub-line covering the whole line - */ - public SubLine wholeLine() { - return new SubLine(this, new IntervalsSet(tolerance)); - } - -} http://git-wip-us.apache.org/repos/asf/commons-math/blob/a7b4803f/src/main/java/org/apache/commons/math3/geometry/euclidean/threed/NotARotationMatrixException.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math3/geometry/euclidean/threed/NotARotationMatrixException.java b/src/main/java/org/apache/commons/math3/geometry/euclidean/threed/NotARotationMatrixException.java deleted file mode 100644 index 3f1f3d3..0000000 --- a/src/main/java/org/apache/commons/math3/geometry/euclidean/threed/NotARotationMatrixException.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.math3.geometry.euclidean.threed; - -import org.apache.commons.math3.exception.MathIllegalArgumentException; -import org.apache.commons.math3.exception.util.Localizable; - -/** - * This class represents exceptions thrown while building rotations - * from matrices. - * - * @since 1.2 - */ - -public class NotARotationMatrixException - extends MathIllegalArgumentException { - - /** Serializable version identifier */ - private static final long serialVersionUID = 5647178478658937642L; - - /** - * Simple constructor. - * Build an exception by translating and formating a message - * @param specifier format specifier (to be translated) - * @param parts to insert in the format (no translation) - * @since 2.2 - */ - public NotARotationMatrixException(Localizable specifier, Object ... parts) { - super(specifier, parts); - } - -} http://git-wip-us.apache.org/repos/asf/commons-math/blob/a7b4803f/src/main/java/org/apache/commons/math3/geometry/euclidean/threed/OutlineExtractor.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math3/geometry/euclidean/threed/OutlineExtractor.java b/src/main/java/org/apache/commons/math3/geometry/euclidean/threed/OutlineExtractor.java deleted file mode 100644 index 328018b..0000000 --- a/src/main/java/org/apache/commons/math3/geometry/euclidean/threed/OutlineExtractor.java +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.commons.math3.geometry.euclidean.threed; - -import java.util.ArrayList; - -import org.apache.commons.math3.geometry.Point; -import org.apache.commons.math3.geometry.euclidean.twod.Euclidean2D; -import org.apache.commons.math3.geometry.euclidean.twod.PolygonsSet; -import org.apache.commons.math3.geometry.euclidean.twod.Vector2D; -import org.apache.commons.math3.geometry.partitioning.AbstractSubHyperplane; -import org.apache.commons.math3.geometry.partitioning.BSPTree; -import org.apache.commons.math3.geometry.partitioning.BSPTreeVisitor; -import org.apache.commons.math3.geometry.partitioning.BoundaryAttribute; -import org.apache.commons.math3.geometry.partitioning.RegionFactory; -import org.apache.commons.math3.geometry.partitioning.SubHyperplane; -import org.apache.commons.math3.util.FastMath; - -/** Extractor for {@link PolygonsSet polyhedrons sets} outlines. - * <p>This class extracts the 2D outlines from {{@link PolygonsSet - * polyhedrons sets} in a specified projection plane.</p> - * @since 3.0 - */ -public class OutlineExtractor { - - /** Abscissa axis of the projection plane. */ - private Vector3D u; - - /** Ordinate axis of the projection plane. */ - private Vector3D v; - - /** Normal of the projection plane (viewing direction). */ - private Vector3D w; - - /** Build an extractor for a specific projection plane. - * @param u abscissa axis of the projection point - * @param v ordinate axis of the projection point - */ - public OutlineExtractor(final Vector3D u, final Vector3D v) { - this.u = u; - this.v = v; - w = Vector3D.crossProduct(u, v); - } - - /** Extract the outline of a polyhedrons set. - * @param polyhedronsSet polyhedrons set whose outline must be extracted - * @return an outline, as an array of loops. - */ - public Vector2D[][] getOutline(final PolyhedronsSet polyhedronsSet) { - - // project all boundary facets into one polygons set - final BoundaryProjector projector = new BoundaryProjector(polyhedronsSet.getTolerance()); - polyhedronsSet.getTree(true).visit(projector); - final PolygonsSet projected = projector.getProjected(); - - // Remove the spurious intermediate vertices from the outline - final Vector2D[][] outline = projected.getVertices(); - for (int i = 0; i < outline.length; ++i) { - final Vector2D[] rawLoop = outline[i]; - int end = rawLoop.length; - int j = 0; - while (j < end) { - if (pointIsBetween(rawLoop, end, j)) { - // the point should be removed - for (int k = j; k < (end - 1); ++k) { - rawLoop[k] = rawLoop[k + 1]; - } - --end; - } else { - // the point remains in the loop - ++j; - } - } - if (end != rawLoop.length) { - // resize the array - outline[i] = new Vector2D[end]; - System.arraycopy(rawLoop, 0, outline[i], 0, end); - } - } - - return outline; - - } - - /** Check if a point is geometrically between its neighbor in an array. - * <p>The neighbors are computed considering the array is a loop - * (i.e. point at index (n-1) is before point at index 0)</p> - * @param loop points array - * @param n number of points to consider in the array - * @param i index of the point to check (must be between 0 and n-1) - * @return true if the point is exactly between its neighbors - */ - private boolean pointIsBetween(final Vector2D[] loop, final int n, final int i) { - final Vector2D previous = loop[(i + n - 1) % n]; - final Vector2D current = loop[i]; - final Vector2D next = loop[(i + 1) % n]; - final double dx1 = current.getX() - previous.getX(); - final double dy1 = current.getY() - previous.getY(); - final double dx2 = next.getX() - current.getX(); - final double dy2 = next.getY() - current.getY(); - final double cross = dx1 * dy2 - dx2 * dy1; - final double dot = dx1 * dx2 + dy1 * dy2; - final double d1d2 = FastMath.sqrt((dx1 * dx1 + dy1 * dy1) * (dx2 * dx2 + dy2 * dy2)); - return (FastMath.abs(cross) <= (1.0e-6 * d1d2)) && (dot >= 0.0); - } - - /** Visitor projecting the boundary facets on a plane. */ - private class BoundaryProjector implements BSPTreeVisitor<Euclidean3D> { - - /** Projection of the polyhedrons set on the plane. */ - private PolygonsSet projected; - - /** Tolerance below which points are considered identical. */ - private final double tolerance; - - /** Simple constructor. - * @param tolerance tolerance below which points are considered identical - */ - public BoundaryProjector(final double tolerance) { - this.projected = new PolygonsSet(new BSPTree<Euclidean2D>(Boolean.FALSE), tolerance); - this.tolerance = tolerance; - } - - /** {@inheritDoc} */ - public Order visitOrder(final BSPTree<Euclidean3D> node) { - return Order.MINUS_SUB_PLUS; - } - - /** {@inheritDoc} */ - public void visitInternalNode(final BSPTree<Euclidean3D> node) { - @SuppressWarnings("unchecked") - final BoundaryAttribute<Euclidean3D> attribute = - (BoundaryAttribute<Euclidean3D>) node.getAttribute(); - if (attribute.getPlusOutside() != null) { - addContribution(attribute.getPlusOutside(), false); - } - if (attribute.getPlusInside() != null) { - addContribution(attribute.getPlusInside(), true); - } - } - - /** {@inheritDoc} */ - public void visitLeafNode(final BSPTree<Euclidean3D> node) { - } - - /** Add he contribution of a boundary facet. - * @param facet boundary facet - * @param reversed if true, the facet has the inside on its plus side - */ - private void addContribution(final SubHyperplane<Euclidean3D> facet, final boolean reversed) { - - // extract the vertices of the facet - @SuppressWarnings("unchecked") - final AbstractSubHyperplane<Euclidean3D, Euclidean2D> absFacet = - (AbstractSubHyperplane<Euclidean3D, Euclidean2D>) facet; - final Plane plane = (Plane) facet.getHyperplane(); - - final double scal = plane.getNormal().dotProduct(w); - if (FastMath.abs(scal) > 1.0e-3) { - Vector2D[][] vertices = - ((PolygonsSet) absFacet.getRemainingRegion()).getVertices(); - - if ((scal < 0) ^ reversed) { - // the facet is seen from the inside, - // we need to invert its boundary orientation - final Vector2D[][] newVertices = new Vector2D[vertices.length][]; - for (int i = 0; i < vertices.length; ++i) { - final Vector2D[] loop = vertices[i]; - final Vector2D[] newLoop = new Vector2D[loop.length]; - if (loop[0] == null) { - newLoop[0] = null; - for (int j = 1; j < loop.length; ++j) { - newLoop[j] = loop[loop.length - j]; - } - } else { - for (int j = 0; j < loop.length; ++j) { - newLoop[j] = loop[loop.length - (j + 1)]; - } - } - newVertices[i] = newLoop; - } - - // use the reverted vertices - vertices = newVertices; - - } - - // compute the projection of the facet in the outline plane - final ArrayList<SubHyperplane<Euclidean2D>> edges = new ArrayList<SubHyperplane<Euclidean2D>>(); - for (Vector2D[] loop : vertices) { - final boolean closed = loop[0] != null; - int previous = closed ? (loop.length - 1) : 1; - Vector3D previous3D = plane.toSpace((Point<Euclidean2D>) loop[previous]); - int current = (previous + 1) % loop.length; - Vector2D pPoint = new Vector2D(previous3D.dotProduct(u), - previous3D.dotProduct(v)); - while (current < loop.length) { - - final Vector3D current3D = plane.toSpace((Point<Euclidean2D>) loop[current]); - final Vector2D cPoint = new Vector2D(current3D.dotProduct(u), - current3D.dotProduct(v)); - final org.apache.commons.math3.geometry.euclidean.twod.Line line = - new org.apache.commons.math3.geometry.euclidean.twod.Line(pPoint, cPoint, tolerance); - SubHyperplane<Euclidean2D> edge = line.wholeHyperplane(); - - if (closed || (previous != 1)) { - // the previous point is a real vertex - // it defines one bounding point of the edge - final double angle = line.getAngle() + 0.5 * FastMath.PI; - final org.apache.commons.math3.geometry.euclidean.twod.Line l = - new org.apache.commons.math3.geometry.euclidean.twod.Line(pPoint, angle, tolerance); - edge = edge.split(l).getPlus(); - } - - if (closed || (current != (loop.length - 1))) { - // the current point is a real vertex - // it defines one bounding point of the edge - final double angle = line.getAngle() + 0.5 * FastMath.PI; - final org.apache.commons.math3.geometry.euclidean.twod.Line l = - new org.apache.commons.math3.geometry.euclidean.twod.Line(cPoint, angle, tolerance); - edge = edge.split(l).getMinus(); - } - - edges.add(edge); - - previous = current++; - previous3D = current3D; - pPoint = cPoint; - - } - } - final PolygonsSet projectedFacet = new PolygonsSet(edges, tolerance); - - // add the contribution of the facet to the global outline - projected = (PolygonsSet) new RegionFactory<Euclidean2D>().union(projected, projectedFacet); - - } - } - - /** Get the projection of the polyhedrons set on the plane. - * @return projection of the polyhedrons set on the plane - */ - public PolygonsSet getProjected() { - return projected; - } - - } - -}