Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 110C8200C72 for ; Fri, 12 May 2017 23:32:23 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id 0F5CA160BA8; Fri, 12 May 2017 21:32:23 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 8F481160BCE for ; Fri, 12 May 2017 23:32:20 +0200 (CEST) Received: (qmail 18845 invoked by uid 500); 12 May 2017 21:32:11 -0000 Mailing-List: contact commits-help@commons.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@commons.apache.org Delivered-To: mailing list commits@commons.apache.org Received: (qmail 17174 invoked by uid 99); 12 May 2017 21:32:10 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 12 May 2017 21:32:10 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id BDB05ED49E; Fri, 12 May 2017 21:32:10 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: raydecampo@apache.org To: commits@commons.apache.org Date: Fri, 12 May 2017 21:32:31 -0000 Message-Id: <0566375cf8e541f998e69c29667a514b@git.apache.org> In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [22/31] [math] MATH-1284: Replace/rename Coordinate?D classes (nee Vector?D) as Cartesian?D classes as per discussion. When there are existing overridden methods accepting Vector and Point, add a disambiguating method accepting archived-at: Fri, 12 May 2017 21:32:23 -0000 MATH-1284: Replace/rename Coordinate?D classes (nee Vector?D) as Cartesian?D classes as per discussion. When there are existing overridden methods accepting Vector and Point, add a disambiguating method accepting a Cartesian?D. Eliminate casts where possible. Project: http://git-wip-us.apache.org/repos/asf/commons-math/repo Commit: http://git-wip-us.apache.org/repos/asf/commons-math/commit/e21d4d43 Tree: http://git-wip-us.apache.org/repos/asf/commons-math/tree/e21d4d43 Diff: http://git-wip-us.apache.org/repos/asf/commons-math/diff/e21d4d43 Branch: refs/heads/master Commit: e21d4d436b51d88f9554751982cd7b8552854c49 Parents: b815d2a Author: Ray DeCampo Authored: Sat Apr 29 20:29:29 2017 -0400 Committer: Ray DeCampo Committed: Sat Apr 29 20:29:29 2017 -0400 ---------------------------------------------------------------------- .../geometry/euclidean/oned/Cartesian1D.java | 386 ++++++ .../geometry/euclidean/oned/Coordinates1D.java | 386 ------ .../geometry/euclidean/oned/IntervalsSet.java | 18 +- .../geometry/euclidean/oned/OrientedPoint.java | 8 +- .../geometry/euclidean/oned/Vector1DFormat.java | 12 +- .../geometry/euclidean/threed/Cartesian3D.java | 621 +++++++++ .../euclidean/threed/Coordinates3D.java | 621 --------- .../euclidean/threed/FieldRotation.java | 52 +- .../euclidean/threed/FieldVector3D.java | 78 +- .../math4/geometry/euclidean/threed/Line.java | 80 +- .../euclidean/threed/OutlineExtractor.java | 46 +- .../math4/geometry/euclidean/threed/Plane.java | 131 +- .../euclidean/threed/PolyhedronsSet.java | 96 +- .../geometry/euclidean/threed/Rotation.java | 136 +- .../euclidean/threed/RotationOrder.java | 38 +- .../geometry/euclidean/threed/Segment.java | 10 +- .../euclidean/threed/SphereGenerator.java | 22 +- .../euclidean/threed/SphericalCoordinates.java | 10 +- .../geometry/euclidean/threed/SubLine.java | 14 +- .../geometry/euclidean/threed/SubPlane.java | 14 +- .../euclidean/threed/Vector3DFormat.java | 22 +- .../geometry/euclidean/twod/Cartesian2D.java | 492 +++++++ .../geometry/euclidean/twod/Coordinates2D.java | 492 ------- .../geometry/euclidean/twod/DiskGenerator.java | 16 +- .../math4/geometry/euclidean/twod/Line.java | 93 +- .../geometry/euclidean/twod/NestedLoops.java | 12 +- .../geometry/euclidean/twod/PolygonsSet.java | 78 +- .../math4/geometry/euclidean/twod/Segment.java | 14 +- .../math4/geometry/euclidean/twod/SubLine.java | 18 +- .../geometry/euclidean/twod/Vector2DFormat.java | 12 +- .../hull/AbstractConvexHullGenerator2D.java | 10 +- .../twod/hull/AklToussaintHeuristic.java | 34 +- .../euclidean/twod/hull/ConvexHull2D.java | 32 +- .../twod/hull/ConvexHullGenerator2D.java | 6 +- .../euclidean/twod/hull/MonotoneChain.java | 28 +- .../math4/geometry/spherical/oned/S1Point.java | 14 +- .../math4/geometry/spherical/twod/Circle.java | 34 +- .../math4/geometry/spherical/twod/Edge.java | 4 +- .../geometry/spherical/twod/EdgesBuilder.java | 10 +- .../spherical/twod/PropertiesComputer.java | 30 +- .../math4/geometry/spherical/twod/S2Point.java | 32 +- .../spherical/twod/SphericalPolygonsSet.java | 26 +- .../geometry/spherical/twod/SubCircle.java | 4 +- .../commons/math4/complex/QuaternionTest.java | 30 +- ...stractLeastSquaresOptimizerAbstractTest.java | 6 +- .../fitting/leastsquares/CircleVectorial.java | 18 +- .../GaussNewtonOptimizerWithSVDTest.java | 6 +- .../LevenbergMarquardtOptimizerTest.java | 6 +- .../RandomCirclePointGenerator.java | 10 +- .../geometry/enclosing/WelzlEncloser2DTest.java | 56 +- .../geometry/enclosing/WelzlEncloser3DTest.java | 110 +- .../euclidean/oned/IntervalsSetTest.java | 44 +- .../oned/Vector1DFormatAbstractTest.java | 69 +- .../geometry/euclidean/oned/Vector1DTest.java | 129 +- .../euclidean/threed/FieldRotationDSTest.java | 20 +- .../euclidean/threed/FieldRotationDfpTest.java | 6 +- .../euclidean/threed/FieldVector3DTest.java | 70 +- .../geometry/euclidean/threed/LineTest.java | 76 +- .../geometry/euclidean/threed/PLYParser.java | 8 +- .../geometry/euclidean/threed/PlaneTest.java | 88 +- .../euclidean/threed/PolyhedronsSetTest.java | 146 +- .../geometry/euclidean/threed/RotationTest.java | 250 ++-- .../euclidean/threed/SphereGeneratorTest.java | 114 +- .../threed/SphericalCoordinatesTest.java | 30 +- .../geometry/euclidean/threed/SubLineTest.java | 60 +- .../threed/Vector3DFormatAbstractTest.java | 74 +- .../geometry/euclidean/threed/Vector3DTest.java | 246 ++-- .../euclidean/twod/DiskGeneratorTest.java | 58 +- .../math4/geometry/euclidean/twod/LineTest.java | 65 +- .../euclidean/twod/NestedLoopsTest.java | 16 +- .../euclidean/twod/PolygonsSetTest.java | 1260 +++++++++--------- .../geometry/euclidean/twod/SegmentTest.java | 14 +- .../geometry/euclidean/twod/SubLineTest.java | 60 +- .../twod/Vector2DFormatAbstractTest.java | 74 +- .../geometry/euclidean/twod/Vector2DTest.java | 110 +- .../twod/hull/AklToussaintHeuristicTest.java | 4 +- .../hull/ConvexHullGenerator2DAbstractTest.java | 226 ++-- .../euclidean/twod/hull/MonotoneChainTest.java | 22 +- .../geometry/partitioning/RegionDumper.java | 10 +- .../geometry/partitioning/RegionParser.java | 16 +- .../geometry/spherical/twod/CircleTest.java | 80 +- .../twod/SphericalPolygonsSetTest.java | 152 +-- .../geometry/spherical/twod/SubCircleTest.java | 34 +- .../MultiStartMultivariateOptimizerTest.java | 4 +- .../nonlinear/scalar/gradient/CircleScalar.java | 18 +- ...NonLinearConjugateGradientOptimizerTest.java | 4 +- 86 files changed, 4118 insertions(+), 4073 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/commons-math/blob/e21d4d43/src/main/java/org/apache/commons/math4/geometry/euclidean/oned/Cartesian1D.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/geometry/euclidean/oned/Cartesian1D.java b/src/main/java/org/apache/commons/math4/geometry/euclidean/oned/Cartesian1D.java new file mode 100644 index 0000000..0a248a1 --- /dev/null +++ b/src/main/java/org/apache/commons/math4/geometry/euclidean/oned/Cartesian1D.java @@ -0,0 +1,386 @@ +/* + * 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.math4.geometry.euclidean.oned; + +import java.text.NumberFormat; + +import org.apache.commons.math4.exception.MathArithmeticException; +import org.apache.commons.math4.exception.util.LocalizedFormats; +import org.apache.commons.math4.geometry.Point; +import org.apache.commons.math4.geometry.Space; +import org.apache.commons.math4.geometry.Vector; +import org.apache.commons.math4.util.FastMath; +import org.apache.commons.math4.util.MathUtils; + +/** This class represents a 1D point or a 1D vector. + *

An instance of Cartesian1D represents the point with the corresponding + * Cartesian coordinates.

+ *

An instance of Cartesian1D also represents the vector which begins at + * the origin and ends at the point corresponding to the coordinates.

+ *

Instances of this class are guaranteed to be immutable.

+ * @since 4.0 + */ +public class Cartesian1D implements Point, Vector { + + /** Origin (coordinates: 0). */ + public static final Cartesian1D ZERO = new Cartesian1D(0.0); + + /** Unit (coordinates: 1). */ + public static final Cartesian1D ONE = new Cartesian1D(1.0); + + // CHECKSTYLE: stop ConstantName + /** A vector with all coordinates set to NaN. */ + public static final Cartesian1D NaN = new Cartesian1D(Double.NaN); + // CHECKSTYLE: resume ConstantName + + /** A vector with all coordinates set to positive infinity. */ + public static final Cartesian1D POSITIVE_INFINITY = + new Cartesian1D(Double.POSITIVE_INFINITY); + + /** A vector with all coordinates set to negative infinity. */ + public static final Cartesian1D NEGATIVE_INFINITY = + new Cartesian1D(Double.NEGATIVE_INFINITY); + + /** Serializable UID. */ + private static final long serialVersionUID = 7556674948671647925L; + + /** Abscissa. */ + private final double x; + + /** Simple constructor. + * Build a vector from its coordinates + * @param x abscissa + * @see #getX() + */ + public Cartesian1D(double x) { + this.x = x; + } + + /** 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 Cartesian1D(double a, Cartesian1D u) { + this.x = a * u.x; + } + + /** 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 Cartesian1D(double a1, Cartesian1D u1, double a2, Cartesian1D u2) { + this.x = a1 * u1.x + a2 * u2.x; + } + + /** 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 Cartesian1D(double a1, Cartesian1D u1, double a2, Cartesian1D u2, + double a3, Cartesian1D u3) { + this.x = a1 * u1.x + a2 * u2.x + a3 * u3.x; + } + + /** 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 Cartesian1D(double a1, Cartesian1D u1, double a2, Cartesian1D u2, + double a3, Cartesian1D u3, double a4, Cartesian1D u4) { + this.x = a1 * u1.x + a2 * u2.x + a3 * u3.x + a4 * u4.x; + } + + /** Get the abscissa of the vector. + * @return abscissa of the vector + * @see #Vector1D(double) + */ + public double getX() { + return x; + } + + /** {@inheritDoc} */ + @Override + public Space getSpace() { + return Euclidean1D.getInstance(); + } + + /** {@inheritDoc} */ + @Override + public Cartesian1D getZero() { + return ZERO; + } + + /** {@inheritDoc} */ + @Override + public double getNorm1() { + return FastMath.abs(x); + } + + /** {@inheritDoc} */ + @Override + public double getNorm() { + return FastMath.abs(x); + } + + /** {@inheritDoc} */ + @Override + public double getNormSq() { + return x * x; + } + + /** {@inheritDoc} */ + @Override + public double getNormInf() { + return FastMath.abs(x); + } + + /** {@inheritDoc} */ + @Override + public Cartesian1D add(Vector v) { + Cartesian1D v1 = (Cartesian1D) v; + return new Cartesian1D(x + v1.getX()); + } + + /** {@inheritDoc} */ + @Override + public Cartesian1D add(double factor, Vector v) { + Cartesian1D v1 = (Cartesian1D) v; + return new Cartesian1D(x + factor * v1.getX()); + } + + /** {@inheritDoc} */ + @Override + public Cartesian1D subtract(Vector p) { + Cartesian1D p3 = (Cartesian1D) p; + return new Cartesian1D(x - p3.x); + } + + /** {@inheritDoc} */ + @Override + public Cartesian1D subtract(double factor, Vector v) { + Cartesian1D v1 = (Cartesian1D) v; + return new Cartesian1D(x - factor * v1.getX()); + } + + /** {@inheritDoc} */ + @Override + public Cartesian1D normalize() throws MathArithmeticException { + double s = getNorm(); + if (s == 0) { + throw new MathArithmeticException(LocalizedFormats.CANNOT_NORMALIZE_A_ZERO_NORM_VECTOR); + } + return scalarMultiply(1 / s); + } + /** {@inheritDoc} */ + @Override + public Cartesian1D negate() { + return new Cartesian1D(-x); + } + + /** {@inheritDoc} */ + @Override + public Cartesian1D scalarMultiply(double a) { + return new Cartesian1D(a * x); + } + + /** {@inheritDoc} */ + @Override + public boolean isNaN() { + return Double.isNaN(x); + } + + /** {@inheritDoc} */ + @Override + public boolean isInfinite() { + return !isNaN() && Double.isInfinite(x); + } + + /** {@inheritDoc} */ + @Override + public double distance1(Vector p) { + Cartesian1D p1 = (Cartesian1D) p; + final double dx = FastMath.abs(p1.x - x); + return dx; + } + + /** {@inheritDoc} */ + @Override + public double distance(Point p) { + return distance((Cartesian1D) p); + } + + /** {@inheritDoc} */ + @Override + public double distance(Vector v) { + return distance((Cartesian1D) v); + } + + /** Compute the distance between the instance and other coordinates. + * @param c other coordinates + * @return the distance between the instance and c + */ + public double distance(Cartesian1D c) { + final double dx = c.x - x; + return FastMath.abs(dx); + } + + /** {@inheritDoc} */ + @Override + public double distanceInf(Vector p) { + Cartesian1D p1 = (Cartesian1D) p; + final double dx = FastMath.abs(p1.x - x); + return dx; + } + + /** {@inheritDoc} */ + @Override + public double distanceSq(Vector p) { + Cartesian1D p1 = (Cartesian1D) p; + final double dx = p1.x - x; + return dx * dx; + } + + /** {@inheritDoc} */ + @Override + public double dotProduct(final Vector v) { + final Cartesian1D v1 = (Cartesian1D) v; + return x * v1.x; + } + + /** Compute the distance between two points according to the L2 norm. + *

Calling this method is equivalent to calling: + * p1.subtract(p2).getNorm() except that no intermediate + * vector is built

+ * @param p1 first vector + * @param p2 second vector + * @return the distance between p1 and p2 according to the L2 norm + */ + public static double distance(Cartesian1D p1, Cartesian1D p2) { + return p1.distance(p2); + } + + /** Compute the distance between two points according to the L norm. + *

Calling this method is equivalent to calling: + * p1.subtract(p2).getNormInf() except that no intermediate + * vector is built

+ * @param p1 first vector + * @param p2 second vector + * @return the distance between p1 and p2 according to the L norm + */ + public static double distanceInf(Cartesian1D p1, Cartesian1D p2) { + return p1.distanceInf(p2); + } + + /** Compute the square of the distance between two points. + *

Calling this method is equivalent to calling: + * p1.subtract(p2).getNormSq() except that no intermediate + * vector is built

+ * @param p1 first vector + * @param p2 second vector + * @return the square of the distance between p1 and p2 + */ + public static double distanceSq(Cartesian1D p1, Cartesian1D p2) { + return p1.distanceSq(p2); + } + + /** + * Test for the equality of two 1D vectors. + *

+ * If all coordinates of two 1D vectors are exactly the same, and none are + * Double.NaN, the two 1D vectors are considered to be equal. + *

+ *

+ * NaN coordinates are considered to affect globally the vector + * and be equals to each other - i.e, if either (or all) coordinates of the + * 1D vector are equal to Double.NaN, the 1D vector is equal to + * {@link #NaN}. + *

+ * + * @param other Object to test for equality to this + * @return true if two 1D vector objects are equal, false if + * object is null, not an instance of Vector1D, or + * not equal to this Vector1D instance + * + */ + @Override + public boolean equals(Object other) { + + if (this == other) { + return true; + } + + if (other instanceof Cartesian1D) { + final Cartesian1D rhs = (Cartesian1D)other; + if (rhs.isNaN()) { + return this.isNaN(); + } + + return x == rhs.x; + } + return false; + } + + /** + * Get a hashCode for the 1D vector. + *

+ * All NaN values have the same hash code.

+ * + * @return a hash code value for this object + */ + @Override + public int hashCode() { + if (isNaN()) { + return 7785; + } + return 997 * MathUtils.hash(x); + } + + /** Get a string representation of this vector. + * @return a string representation of this vector + */ + @Override + public String toString() { + return Vector1DFormat.getInstance().format(this); + } + + /** {@inheritDoc} */ + @Override + public String toString(final NumberFormat format) { + return new Vector1DFormat(format).format(this); + } + +} http://git-wip-us.apache.org/repos/asf/commons-math/blob/e21d4d43/src/main/java/org/apache/commons/math4/geometry/euclidean/oned/Coordinates1D.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/geometry/euclidean/oned/Coordinates1D.java b/src/main/java/org/apache/commons/math4/geometry/euclidean/oned/Coordinates1D.java deleted file mode 100644 index 1f31594..0000000 --- a/src/main/java/org/apache/commons/math4/geometry/euclidean/oned/Coordinates1D.java +++ /dev/null @@ -1,386 +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.math4.geometry.euclidean.oned; - -import java.text.NumberFormat; - -import org.apache.commons.math4.exception.MathArithmeticException; -import org.apache.commons.math4.exception.util.LocalizedFormats; -import org.apache.commons.math4.geometry.Point; -import org.apache.commons.math4.geometry.Space; -import org.apache.commons.math4.geometry.Vector; -import org.apache.commons.math4.util.FastMath; -import org.apache.commons.math4.util.MathUtils; - -/** This class represents a 1D point or a 1D vector. - *

An instance of Coordinates1D represents the point with the corresponding - * coordinates.

- *

An instance of Coordinates1D also represents the vector which begins at - * the origin and ends at the point corresponding to the coordinates.

- *

Instances of this class are guaranteed to be immutable.

- * @since 4.0 - */ -public class Coordinates1D implements Point, Vector { - - /** Origin (coordinates: 0). */ - public static final Coordinates1D ZERO = new Coordinates1D(0.0); - - /** Unit (coordinates: 1). */ - public static final Coordinates1D ONE = new Coordinates1D(1.0); - - // CHECKSTYLE: stop ConstantName - /** A vector with all coordinates set to NaN. */ - public static final Coordinates1D NaN = new Coordinates1D(Double.NaN); - // CHECKSTYLE: resume ConstantName - - /** A vector with all coordinates set to positive infinity. */ - public static final Coordinates1D POSITIVE_INFINITY = - new Coordinates1D(Double.POSITIVE_INFINITY); - - /** A vector with all coordinates set to negative infinity. */ - public static final Coordinates1D NEGATIVE_INFINITY = - new Coordinates1D(Double.NEGATIVE_INFINITY); - - /** Serializable UID. */ - private static final long serialVersionUID = 7556674948671647925L; - - /** Abscissa. */ - private final double x; - - /** Simple constructor. - * Build a vector from its coordinates - * @param x abscissa - * @see #getX() - */ - public Coordinates1D(double x) { - this.x = x; - } - - /** 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 Coordinates1D(double a, Coordinates1D u) { - this.x = a * u.x; - } - - /** 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 Coordinates1D(double a1, Coordinates1D u1, double a2, Coordinates1D u2) { - this.x = a1 * u1.x + a2 * u2.x; - } - - /** 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 Coordinates1D(double a1, Coordinates1D u1, double a2, Coordinates1D u2, - double a3, Coordinates1D u3) { - this.x = a1 * u1.x + a2 * u2.x + a3 * u3.x; - } - - /** 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 Coordinates1D(double a1, Coordinates1D u1, double a2, Coordinates1D u2, - double a3, Coordinates1D u3, double a4, Coordinates1D u4) { - this.x = a1 * u1.x + a2 * u2.x + a3 * u3.x + a4 * u4.x; - } - - /** Get the abscissa of the vector. - * @return abscissa of the vector - * @see #Vector1D(double) - */ - public double getX() { - return x; - } - - /** {@inheritDoc} */ - @Override - public Space getSpace() { - return Euclidean1D.getInstance(); - } - - /** {@inheritDoc} */ - @Override - public Coordinates1D getZero() { - return ZERO; - } - - /** {@inheritDoc} */ - @Override - public double getNorm1() { - return FastMath.abs(x); - } - - /** {@inheritDoc} */ - @Override - public double getNorm() { - return FastMath.abs(x); - } - - /** {@inheritDoc} */ - @Override - public double getNormSq() { - return x * x; - } - - /** {@inheritDoc} */ - @Override - public double getNormInf() { - return FastMath.abs(x); - } - - /** {@inheritDoc} */ - @Override - public Coordinates1D add(Vector v) { - Coordinates1D v1 = (Coordinates1D) v; - return new Coordinates1D(x + v1.getX()); - } - - /** {@inheritDoc} */ - @Override - public Coordinates1D add(double factor, Vector v) { - Coordinates1D v1 = (Coordinates1D) v; - return new Coordinates1D(x + factor * v1.getX()); - } - - /** {@inheritDoc} */ - @Override - public Coordinates1D subtract(Vector p) { - Coordinates1D p3 = (Coordinates1D) p; - return new Coordinates1D(x - p3.x); - } - - /** {@inheritDoc} */ - @Override - public Coordinates1D subtract(double factor, Vector v) { - Coordinates1D v1 = (Coordinates1D) v; - return new Coordinates1D(x - factor * v1.getX()); - } - - /** {@inheritDoc} */ - @Override - public Coordinates1D normalize() throws MathArithmeticException { - double s = getNorm(); - if (s == 0) { - throw new MathArithmeticException(LocalizedFormats.CANNOT_NORMALIZE_A_ZERO_NORM_VECTOR); - } - return scalarMultiply(1 / s); - } - /** {@inheritDoc} */ - @Override - public Coordinates1D negate() { - return new Coordinates1D(-x); - } - - /** {@inheritDoc} */ - @Override - public Coordinates1D scalarMultiply(double a) { - return new Coordinates1D(a * x); - } - - /** {@inheritDoc} */ - @Override - public boolean isNaN() { - return Double.isNaN(x); - } - - /** {@inheritDoc} */ - @Override - public boolean isInfinite() { - return !isNaN() && Double.isInfinite(x); - } - - /** {@inheritDoc} */ - @Override - public double distance1(Vector p) { - Coordinates1D p3 = (Coordinates1D) p; - final double dx = FastMath.abs(p3.x - x); - return dx; - } - - /** {@inheritDoc} */ - @Override - public double distance(Point p) { - return distance((Coordinates1D) p); - } - - /** {@inheritDoc} */ - @Override - public double distance(Vector v) { - return distance((Coordinates1D) v); - } - - /** Compute the distance between the instance and other coordinates. - * @param c other coordinates - * @return the distance between the instance and c - */ - public double distance(Coordinates1D c) { - final double dx = c.x - x; - return FastMath.abs(dx); - } - - /** {@inheritDoc} */ - @Override - public double distanceInf(Vector p) { - Coordinates1D p3 = (Coordinates1D) p; - final double dx = FastMath.abs(p3.x - x); - return dx; - } - - /** {@inheritDoc} */ - @Override - public double distanceSq(Vector p) { - Coordinates1D p3 = (Coordinates1D) p; - final double dx = p3.x - x; - return dx * dx; - } - - /** {@inheritDoc} */ - @Override - public double dotProduct(final Vector v) { - final Coordinates1D v1 = (Coordinates1D) v; - return x * v1.x; - } - - /** Compute the distance between two vectors according to the L2 norm. - *

Calling this method is equivalent to calling: - * p1.subtract(p2).getNorm() except that no intermediate - * vector is built

- * @param p1 first vector - * @param p2 second vector - * @return the distance between p1 and p2 according to the L2 norm - */ - public static double distance(Coordinates1D p1, Coordinates1D p2) { - return p1.distance(p2); - } - - /** Compute the distance between two vectors according to the L norm. - *

Calling this method is equivalent to calling: - * p1.subtract(p2).getNormInf() except that no intermediate - * vector is built

- * @param p1 first vector - * @param p2 second vector - * @return the distance between p1 and p2 according to the L norm - */ - public static double distanceInf(Coordinates1D p1, Coordinates1D p2) { - return p1.distanceInf(p2); - } - - /** Compute the square of the distance between two vectors. - *

Calling this method is equivalent to calling: - * p1.subtract(p2).getNormSq() except that no intermediate - * vector is built

- * @param p1 first vector - * @param p2 second vector - * @return the square of the distance between p1 and p2 - */ - public static double distanceSq(Coordinates1D p1, Coordinates1D p2) { - return p1.distanceSq(p2); - } - - /** - * Test for the equality of two 1D vectors. - *

- * If all coordinates of two 1D vectors are exactly the same, and none are - * Double.NaN, the two 1D vectors are considered to be equal. - *

- *

- * NaN coordinates are considered to affect globally the vector - * and be equals to each other - i.e, if either (or all) coordinates of the - * 1D vector are equal to Double.NaN, the 1D vector is equal to - * {@link #NaN}. - *

- * - * @param other Object to test for equality to this - * @return true if two 1D vector objects are equal, false if - * object is null, not an instance of Vector1D, or - * not equal to this Vector1D instance - * - */ - @Override - public boolean equals(Object other) { - - if (this == other) { - return true; - } - - if (other instanceof Coordinates1D) { - final Coordinates1D rhs = (Coordinates1D)other; - if (rhs.isNaN()) { - return this.isNaN(); - } - - return x == rhs.x; - } - return false; - } - - /** - * Get a hashCode for the 1D vector. - *

- * All NaN values have the same hash code.

- * - * @return a hash code value for this object - */ - @Override - public int hashCode() { - if (isNaN()) { - return 7785; - } - return 997 * MathUtils.hash(x); - } - - /** Get a string representation of this vector. - * @return a string representation of this vector - */ - @Override - public String toString() { - return Vector1DFormat.getInstance().format(this); - } - - /** {@inheritDoc} */ - @Override - public String toString(final NumberFormat format) { - return new Vector1DFormat(format).format(this); - } - -} http://git-wip-us.apache.org/repos/asf/commons-math/blob/e21d4d43/src/main/java/org/apache/commons/math4/geometry/euclidean/oned/IntervalsSet.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/geometry/euclidean/oned/IntervalsSet.java b/src/main/java/org/apache/commons/math4/geometry/euclidean/oned/IntervalsSet.java index 78c50c1..acab5a6 100644 --- a/src/main/java/org/apache/commons/math4/geometry/euclidean/oned/IntervalsSet.java +++ b/src/main/java/org/apache/commons/math4/geometry/euclidean/oned/IntervalsSet.java @@ -112,14 +112,14 @@ public class IntervalsSet extends AbstractRegion imple } // the tree must be open on the negative infinity side final SubHyperplane upperCut = - new OrientedPoint(new Coordinates1D(upper), true, tolerance).wholeHyperplane(); + new OrientedPoint(new Cartesian1D(upper), true, tolerance).wholeHyperplane(); return new BSPTree<>(upperCut, new BSPTree(Boolean.FALSE), new BSPTree(Boolean.TRUE), null); } final SubHyperplane lowerCut = - new OrientedPoint(new Coordinates1D(lower), false, tolerance).wholeHyperplane(); + new OrientedPoint(new Cartesian1D(lower), false, tolerance).wholeHyperplane(); if (Double.isInfinite(upper) && (upper > 0)) { // the tree must be open on the positive infinity side return new BSPTree<>(lowerCut, @@ -130,7 +130,7 @@ public class IntervalsSet extends AbstractRegion imple // the tree must be bounded on the two sides final SubHyperplane upperCut = - new OrientedPoint(new Coordinates1D(upper), true, tolerance).wholeHyperplane(); + new OrientedPoint(new Cartesian1D(upper), true, tolerance).wholeHyperplane(); return new BSPTree<>(lowerCut, new BSPTree(Boolean.FALSE), new BSPTree<>(upperCut, @@ -151,7 +151,7 @@ public class IntervalsSet extends AbstractRegion imple @Override protected void computeGeometricalProperties() { if (getTree(false).getCut() == null) { - setBarycenter((Point) Coordinates1D.NaN); + setBarycenter((Point) Cartesian1D.NaN); setSize(((Boolean) getTree(false).getAttribute()) ? Double.POSITIVE_INFINITY : 0); } else { double size = 0.0; @@ -162,9 +162,9 @@ public class IntervalsSet extends AbstractRegion imple } setSize(size); if (Double.isInfinite(size)) { - setBarycenter((Point) Coordinates1D.NaN); + setBarycenter((Point) Cartesian1D.NaN); } else if (size >= Precision.SAFE_MIN) { - setBarycenter((Point) new Coordinates1D(sum / size)); + setBarycenter((Point) new Cartesian1D(sum / size)); } else { setBarycenter((Point) ((OrientedPoint) getTree(false).getCut().getHyperplane()).getLocation()); } @@ -212,7 +212,7 @@ public class IntervalsSet extends AbstractRegion imple public BoundaryProjection projectToBoundary(final Point point) { // get position of test point - final double x = ((Coordinates1D) point).getX(); + final double x = ((Cartesian1D) point).getX(); double previous = Double.NEGATIVE_INFINITY; for (final double[] a : this) { @@ -249,8 +249,8 @@ public class IntervalsSet extends AbstractRegion imple * @param x abscissa of the point * @return a new point for finite abscissa, null otherwise */ - private Coordinates1D finiteOrNullPoint(final double x) { - return Double.isInfinite(x) ? null : new Coordinates1D(x); + private Cartesian1D finiteOrNullPoint(final double x) { + return Double.isInfinite(x) ? null : new Cartesian1D(x); } /** Build an ordered list of intervals representing the instance. http://git-wip-us.apache.org/repos/asf/commons-math/blob/e21d4d43/src/main/java/org/apache/commons/math4/geometry/euclidean/oned/OrientedPoint.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/geometry/euclidean/oned/OrientedPoint.java b/src/main/java/org/apache/commons/math4/geometry/euclidean/oned/OrientedPoint.java index 2f719a2..f917bcc 100644 --- a/src/main/java/org/apache/commons/math4/geometry/euclidean/oned/OrientedPoint.java +++ b/src/main/java/org/apache/commons/math4/geometry/euclidean/oned/OrientedPoint.java @@ -29,7 +29,7 @@ import org.apache.commons.math4.geometry.partitioning.Hyperplane; public class OrientedPoint implements Hyperplane { /** Vector location. */ - private final Coordinates1D location; + private final Cartesian1D location; /** Orientation. */ private boolean direct; @@ -44,7 +44,7 @@ public class OrientedPoint implements Hyperplane { * @param tolerance tolerance below which points are considered to belong to the hyperplane * @since 3.3 */ - public OrientedPoint(final Coordinates1D location, final boolean direct, final double tolerance) { + public OrientedPoint(final Cartesian1D location, final boolean direct, final double tolerance) { this.location = location; this.direct = direct; this.tolerance = tolerance; @@ -71,7 +71,7 @@ public class OrientedPoint implements Hyperplane { /** {@inheritDoc} */ @Override public double getOffset(final Point point) { - final double delta = ((Coordinates1D) point).getX() - location.getX(); + final double delta = ((Cartesian1D) point).getX() - location.getX(); return direct ? delta : -delta; } @@ -125,7 +125,7 @@ public class OrientedPoint implements Hyperplane { /** Get the hyperplane location on the real line. * @return the hyperplane location */ - public Coordinates1D getLocation() { + public Cartesian1D getLocation() { return location; } http://git-wip-us.apache.org/repos/asf/commons-math/blob/e21d4d43/src/main/java/org/apache/commons/math4/geometry/euclidean/oned/Vector1DFormat.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/geometry/euclidean/oned/Vector1DFormat.java b/src/main/java/org/apache/commons/math4/geometry/euclidean/oned/Vector1DFormat.java index 4b40bb3..c5cead3 100644 --- a/src/main/java/org/apache/commons/math4/geometry/euclidean/oned/Vector1DFormat.java +++ b/src/main/java/org/apache/commons/math4/geometry/euclidean/oned/Vector1DFormat.java @@ -105,31 +105,31 @@ public class Vector1DFormat extends VectorFormat { @Override public StringBuffer format(final Vector vector, final StringBuffer toAppendTo, final FieldPosition pos) { - final Coordinates1D p1 = (Coordinates1D) vector; + final Cartesian1D p1 = (Cartesian1D) vector; return format(toAppendTo, pos, p1.getX()); } /** {@inheritDoc} */ @Override - public Coordinates1D parse(final String source) throws MathParseException { + public Cartesian1D parse(final String source) throws MathParseException { ParsePosition parsePosition = new ParsePosition(0); - Coordinates1D result = parse(source, parsePosition); + Cartesian1D result = parse(source, parsePosition); if (parsePosition.getIndex() == 0) { throw new MathParseException(source, parsePosition.getErrorIndex(), - Coordinates1D.class); + Cartesian1D.class); } return result; } /** {@inheritDoc} */ @Override - public Coordinates1D parse(final String source, final ParsePosition pos) { + public Cartesian1D parse(final String source, final ParsePosition pos) { final double[] coordinates = parseCoordinates(1, source, pos); if (coordinates == null) { return null; } - return new Coordinates1D(coordinates[0]); + return new Cartesian1D(coordinates[0]); } } http://git-wip-us.apache.org/repos/asf/commons-math/blob/e21d4d43/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/Cartesian3D.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/Cartesian3D.java b/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/Cartesian3D.java new file mode 100644 index 0000000..85696f6 --- /dev/null +++ b/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/Cartesian3D.java @@ -0,0 +1,621 @@ +/* + * 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.math4.geometry.euclidean.threed; + +import java.io.Serializable; +import java.text.NumberFormat; + +import org.apache.commons.math4.exception.DimensionMismatchException; +import org.apache.commons.math4.exception.MathArithmeticException; +import org.apache.commons.math4.exception.util.LocalizedFormats; +import org.apache.commons.math4.geometry.Point; +import org.apache.commons.math4.geometry.Space; +import org.apache.commons.math4.geometry.Vector; +import org.apache.commons.math4.util.FastMath; +import org.apache.commons.math4.util.MathArrays; +import org.apache.commons.math4.util.MathUtils; + +/** + * This class represents points or vectors in a three-dimensional space. + *

An instance of Cartesian3D represents the point with the corresponding + * coordinates.

+ *

An instance of Cartesian3D also represents the vector which begins at + * the origin and ends at the point corresponding to the coordinates.

+ *

Instance of this class are guaranteed to be immutable.

+ * @since 4.0 + */ +public class Cartesian3D implements Serializable, Point, Vector { + + /** Null vector (coordinates: 0, 0, 0). */ + public static final Cartesian3D ZERO = new Cartesian3D(0, 0, 0); + + /** First canonical vector (coordinates: 1, 0, 0). */ + public static final Cartesian3D PLUS_I = new Cartesian3D(1, 0, 0); + + /** Opposite of the first canonical vector (coordinates: -1, 0, 0). */ + public static final Cartesian3D MINUS_I = new Cartesian3D(-1, 0, 0); + + /** Second canonical vector (coordinates: 0, 1, 0). */ + public static final Cartesian3D PLUS_J = new Cartesian3D(0, 1, 0); + + /** Opposite of the second canonical vector (coordinates: 0, -1, 0). */ + public static final Cartesian3D MINUS_J = new Cartesian3D(0, -1, 0); + + /** Third canonical vector (coordinates: 0, 0, 1). */ + public static final Cartesian3D PLUS_K = new Cartesian3D(0, 0, 1); + + /** Opposite of the third canonical vector (coordinates: 0, 0, -1). */ + public static final Cartesian3D MINUS_K = new Cartesian3D(0, 0, -1); + + // CHECKSTYLE: stop ConstantName + /** A vector with all coordinates set to NaN. */ + public static final Cartesian3D NaN = new Cartesian3D(Double.NaN, Double.NaN, Double.NaN); + // CHECKSTYLE: resume ConstantName + + /** A vector with all coordinates set to positive infinity. */ + public static final Cartesian3D POSITIVE_INFINITY = + new Cartesian3D(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY); + + /** A vector with all coordinates set to negative infinity. */ + public static final Cartesian3D NEGATIVE_INFINITY = + new Cartesian3D(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY); + + /** Serializable version identifier. */ + private static final long serialVersionUID = 1313493323784566947L; + + /** Abscissa. */ + private final double x; + + /** Ordinate. */ + private final double y; + + /** Height. */ + private final double 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 Cartesian3D(double x, double y, double 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 Cartesian3D(double[] 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 Cartesian3D(double alpha, double delta) { + double cosDelta = FastMath.cos(delta); + this.x = FastMath.cos(alpha) * cosDelta; + this.y = FastMath.sin(alpha) * cosDelta; + this.z = FastMath.sin(delta); + } + + /** 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 Cartesian3D(double a, Cartesian3D u) { + this.x = a * u.x; + this.y = a * u.y; + this.z = a * u.z; + } + + /** 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 Cartesian3D(double a1, Cartesian3D u1, double a2, Cartesian3D u2) { + this.x = MathArrays.linearCombination(a1, u1.x, a2, u2.x); + this.y = MathArrays.linearCombination(a1, u1.y, a2, u2.y); + this.z = MathArrays.linearCombination(a1, u1.z, a2, u2.z); + } + + /** 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 Cartesian3D(double a1, Cartesian3D u1, double a2, Cartesian3D u2, + double a3, Cartesian3D u3) { + this.x = MathArrays.linearCombination(a1, u1.x, a2, u2.x, a3, u3.x); + this.y = MathArrays.linearCombination(a1, u1.y, a2, u2.y, a3, u3.y); + this.z = MathArrays.linearCombination(a1, u1.z, a2, u2.z, a3, u3.z); + } + + /** 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 Cartesian3D(double a1, Cartesian3D u1, double a2, Cartesian3D u2, + double a3, Cartesian3D u3, double a4, Cartesian3D u4) { + this.x = MathArrays.linearCombination(a1, u1.x, a2, u2.x, a3, u3.x, a4, u4.x); + this.y = MathArrays.linearCombination(a1, u1.y, a2, u2.y, a3, u3.y, a4, u4.y); + this.z = MathArrays.linearCombination(a1, u1.z, a2, u2.z, a3, u3.z, a4, u4.z); + } + + /** Get the abscissa of the vector. + * @return abscissa of the vector + * @see #Vector3D(double, double, double) + */ + public double getX() { + return x; + } + + /** Get the ordinate of the vector. + * @return ordinate of the vector + * @see #Vector3D(double, double, double) + */ + public double getY() { + return y; + } + + /** Get the height of the vector. + * @return height of the vector + * @see #Vector3D(double, double, double) + */ + public double getZ() { + return z; + } + + /** Get the vector coordinates as a dimension 3 array. + * @return vector coordinates + * @see #Vector3D(double[]) + */ + public double[] toArray() { + return new double[] { x, y, z }; + } + + /** {@inheritDoc} */ + @Override + public Space getSpace() { + return Euclidean3D.getInstance(); + } + + /** {@inheritDoc} */ + @Override + public Cartesian3D getZero() { + return ZERO; + } + + /** {@inheritDoc} */ + @Override + public double getNorm1() { + return FastMath.abs(x) + FastMath.abs(y) + FastMath.abs(z); + } + + /** {@inheritDoc} */ + @Override + public double getNorm() { + // there are no cancellation problems here, so we use the straightforward formula + return FastMath.sqrt (x * x + y * y + z * z); + } + + /** {@inheritDoc} */ + @Override + public double getNormSq() { + // there are no cancellation problems here, so we use the straightforward formula + return x * x + y * y + z * z; + } + + /** {@inheritDoc} */ + @Override + public double getNormInf() { + return FastMath.max(FastMath.max(FastMath.abs(x), FastMath.abs(y)), FastMath.abs(z)); + } + + /** Get the azimuth of the vector. + * @return azimuth (α) of the vector, between -π and +π + * @see #Vector3D(double, double) + */ + public double getAlpha() { + return FastMath.atan2(y, x); + } + + /** Get the elevation of the vector. + * @return elevation (δ) of the vector, between -π/2 and +π/2 + * @see #Vector3D(double, double) + */ + public double getDelta() { + return FastMath.asin(z / getNorm()); + } + + /** {@inheritDoc} */ + @Override + public Cartesian3D add(final Vector v) { + final Cartesian3D v3 = (Cartesian3D) v; + return new Cartesian3D(x + v3.x, y + v3.y, z + v3.z); + } + + /** {@inheritDoc} */ + @Override + public Cartesian3D add(double factor, final Vector v) { + return new Cartesian3D(1, this, factor, (Cartesian3D) v); + } + + /** {@inheritDoc} */ + @Override + public Cartesian3D subtract(final Vector v) { + final Cartesian3D v3 = (Cartesian3D) v; + return new Cartesian3D(x - v3.x, y - v3.y, z - v3.z); + } + + /** {@inheritDoc} */ + @Override + public Cartesian3D subtract(final double factor, final Vector v) { + return new Cartesian3D(1, this, -factor, (Cartesian3D) v); + } + + /** {@inheritDoc} */ + @Override + public Cartesian3D normalize() throws MathArithmeticException { + double s = getNorm(); + if (s == 0) { + throw new MathArithmeticException(LocalizedFormats.CANNOT_NORMALIZE_A_ZERO_NORM_VECTOR); + } + return scalarMultiply(1 / s); + } + + /** Get a vector orthogonal to the instance. + *

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 : + *


+     *   Vector3D k = u.normalize();
+     *   Vector3D i = k.orthogonal();
+     *   Vector3D j = Vector3D.crossProduct(k, i);
+     * 

+ * @return a new normalized vector orthogonal to the instance + * @exception MathArithmeticException if the norm of the instance is null + */ + public Cartesian3D orthogonal() throws MathArithmeticException { + + double threshold = 0.6 * getNorm(); + if (threshold == 0) { + throw new MathArithmeticException(LocalizedFormats.ZERO_NORM); + } + + if (FastMath.abs(x) <= threshold) { + double inverse = 1 / FastMath.sqrt(y * y + z * z); + return new Cartesian3D(0, inverse * z, -inverse * y); + } else if (FastMath.abs(y) <= threshold) { + double inverse = 1 / FastMath.sqrt(x * x + z * z); + return new Cartesian3D(-inverse * z, 0, inverse * x); + } + double inverse = 1 / FastMath.sqrt(x * x + y * y); + return new Cartesian3D(inverse * y, -inverse * x, 0); + + } + + /** Compute the angular separation between two vectors. + *

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.

+ * @param v1 first vector + * @param v2 second vector + * @return angular separation between v1 and v2 + * @exception MathArithmeticException if either vector has a null norm + */ + public static double angle(Cartesian3D v1, Cartesian3D v2) throws MathArithmeticException { + + double normProduct = v1.getNorm() * v2.getNorm(); + if (normProduct == 0) { + throw new MathArithmeticException(LocalizedFormats.ZERO_NORM); + } + + double dot = v1.dotProduct(v2); + double threshold = normProduct * 0.9999; + if ((dot < -threshold) || (dot > threshold)) { + // the vectors are almost aligned, compute using the sine + Cartesian3D v3 = crossProduct(v1, v2); + if (dot >= 0) { + return FastMath.asin(v3.getNorm() / normProduct); + } + return FastMath.PI - FastMath.asin(v3.getNorm() / normProduct); + } + + // the vectors are sufficiently separated to use the cosine + return FastMath.acos(dot / normProduct); + + } + + /** {@inheritDoc} */ + @Override + public Cartesian3D negate() { + return new Cartesian3D(-x, -y, -z); + } + + /** {@inheritDoc} */ + @Override + public Cartesian3D scalarMultiply(double a) { + return new Cartesian3D(a * x, a * y, a * z); + } + + /** {@inheritDoc} */ + @Override + public boolean isNaN() { + return Double.isNaN(x) || Double.isNaN(y) || Double.isNaN(z); + } + + /** {@inheritDoc} */ + @Override + public boolean isInfinite() { + return !isNaN() && (Double.isInfinite(x) || Double.isInfinite(y) || Double.isInfinite(z)); + } + + /** + * Test for the equality of two 3D vectors. + *

+ * If all coordinates of two 3D vectors are exactly the same, and none are + * Double.NaN, the two 3D vectors are considered to be equal. + *

+ *

+ * NaN coordinates are considered to affect globally the vector + * and be equals to each other - i.e, if either (or all) coordinates of the + * 3D vector are equal to Double.NaN, the 3D vector is equal to + * {@link #NaN}. + *

+ * + * @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 Cartesian3D) { + final Cartesian3D rhs = (Cartesian3D)other; + if (rhs.isNaN()) { + return this.isNaN(); + } + + return (x == rhs.x) && (y == rhs.y) && (z == rhs.z); + } + return false; + } + + /** + * Get a hashCode for the 3D vector. + *

+ * All NaN values have the same hash code.

+ * + * @return a hash code value for this object + */ + @Override + public int hashCode() { + if (isNaN()) { + return 642; + } + return 643 * (164 * MathUtils.hash(x) + 3 * MathUtils.hash(y) + MathUtils.hash(z)); + } + + /** {@inheritDoc} + *

+ * 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. + *

+ * @see MathArrays#linearCombination(double, double, double, double, double, double) + */ + @Override + public double dotProduct(final Vector v) { + final Cartesian3D v3 = (Cartesian3D) v; + return MathArrays.linearCombination(x, v3.x, y, v3.y, z, v3.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 Cartesian3D crossProduct(final Vector v) { + final Cartesian3D v3 = (Cartesian3D) v; + return new Cartesian3D(MathArrays.linearCombination(y, v3.z, -z, v3.y), + MathArrays.linearCombination(z, v3.x, -x, v3.z), + MathArrays.linearCombination(x, v3.y, -y, v3.x)); + } + + /** {@inheritDoc} */ + @Override + public double distance1(Vector v) { + final Cartesian3D v3 = (Cartesian3D) v; + final double dx = FastMath.abs(v3.x - x); + final double dy = FastMath.abs(v3.y - y); + final double dz = FastMath.abs(v3.z - z); + return dx + dy + dz; + } + + /** {@inheritDoc} */ + @Override + public double distance(Point p) { + return distance((Cartesian3D) p); + } + + /** {@inheritDoc} */ + @Override + public double distance(Vector v) { + return distance((Cartesian3D) v); + } + + /** Compute the distance between the instance and other coordinates. + * @param c other coordinates + * @return the distance between the instance and c + */ + public double distance(Cartesian3D c) { + final double dx = c.x - x; + final double dy = c.y - y; + final double dz = c.z - z; + return FastMath.sqrt(dx * dx + dy * dy + dz * dz); + } + + /** {@inheritDoc} */ + @Override + public double distanceInf(Vector v) { + final Cartesian3D v3 = (Cartesian3D) v; + final double dx = FastMath.abs(v3.x - x); + final double dy = FastMath.abs(v3.y - y); + final double dz = FastMath.abs(v3.z - z); + return FastMath.max(FastMath.max(dx, dy), dz); + } + + /** {@inheritDoc} */ + @Override + public double distanceSq(Vector v) { + final Cartesian3D v3 = (Cartesian3D) v; + final double dx = v3.x - x; + final double dy = v3.y - y; + final double dz = v3.z - z; + return dx * dx + dy * dy + dz * dz; + } + + /** Compute the dot-product of two vectors. + * @param v1 first vector + * @param v2 second vector + * @return the dot product v1.v2 + */ + public static double dotProduct(Cartesian3D v1, Cartesian3D v2) { + return v1.dotProduct(v2); + } + + /** Compute the cross-product of two vectors. + * @param v1 first vector + * @param v2 second vector + * @return the cross product v1 ^ v2 as a new Vector + */ + public static Cartesian3D crossProduct(final Cartesian3D v1, final Cartesian3D v2) { + return v1.crossProduct(v2); + } + + /** Compute the distance between two vectors according to the L1 norm. + *

Calling this method is equivalent to calling: + * v1.subtract(v2).getNorm1() except that no intermediate + * vector is built

+ * @param v1 first vector + * @param v2 second vector + * @return the distance between v1 and v2 according to the L1 norm + */ + public static double distance1(Cartesian3D v1, Cartesian3D v2) { + return v1.distance1(v2); + } + + /** Compute the distance between two vectors according to the L2 norm. + *

Calling this method is equivalent to calling: + * v1.subtract(v2).getNorm() except that no intermediate + * vector is built

+ * @param v1 first vector + * @param v2 second vector + * @return the distance between v1 and v2 according to the L2 norm + */ + public static double distance(Cartesian3D v1, Cartesian3D v2) { + return v1.distance(v2); + } + + /** Compute the distance between two vectors according to the L norm. + *

Calling this method is equivalent to calling: + * v1.subtract(v2).getNormInf() except that no intermediate + * vector is built

+ * @param v1 first vector + * @param v2 second vector + * @return the distance between v1 and v2 according to the L norm + */ + public static double distanceInf(Cartesian3D v1, Cartesian3D v2) { + return v1.distanceInf(v2); + } + + /** Compute the square of the distance between two vectors. + *

Calling this method is equivalent to calling: + * v1.subtract(v2).getNormSq() except that no intermediate + * vector is built

+ * @param v1 first vector + * @param v2 second vector + * @return the square of the distance between v1 and v2 + */ + public static double distanceSq(Cartesian3D v1, Cartesian3D v2) { + return v1.distanceSq(v2); + } + + /** Get a string representation of this vector. + * @return a string representation of this vector + */ + @Override + public String toString() { + return Vector3DFormat.getInstance().format(this); + } + + /** {@inheritDoc} */ + @Override + public String toString(final NumberFormat format) { + return new Vector3DFormat(format).format(this); + } + +} http://git-wip-us.apache.org/repos/asf/commons-math/blob/e21d4d43/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/Coordinates3D.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/Coordinates3D.java b/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/Coordinates3D.java deleted file mode 100644 index ee2376c..0000000 --- a/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/Coordinates3D.java +++ /dev/null @@ -1,621 +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.math4.geometry.euclidean.threed; - -import java.io.Serializable; -import java.text.NumberFormat; - -import org.apache.commons.math4.exception.DimensionMismatchException; -import org.apache.commons.math4.exception.MathArithmeticException; -import org.apache.commons.math4.exception.util.LocalizedFormats; -import org.apache.commons.math4.geometry.Point; -import org.apache.commons.math4.geometry.Space; -import org.apache.commons.math4.geometry.Vector; -import org.apache.commons.math4.util.FastMath; -import org.apache.commons.math4.util.MathArrays; -import org.apache.commons.math4.util.MathUtils; - -/** - * This class represents points or vectors in a three-dimensional space. - *

An instance of Coordinates3D represents the point with the corresponding - * coordinates.

- *

An instance of Coordinates3D also represents the vector which begins at - * the origin and ends at the point corresponding to the coordinates.

- *

Instance of this class are guaranteed to be immutable.

- * @since 4.0 - */ -public class Coordinates3D implements Serializable, Point, Vector { - - /** Null vector (coordinates: 0, 0, 0). */ - public static final Coordinates3D ZERO = new Coordinates3D(0, 0, 0); - - /** First canonical vector (coordinates: 1, 0, 0). */ - public static final Coordinates3D PLUS_I = new Coordinates3D(1, 0, 0); - - /** Opposite of the first canonical vector (coordinates: -1, 0, 0). */ - public static final Coordinates3D MINUS_I = new Coordinates3D(-1, 0, 0); - - /** Second canonical vector (coordinates: 0, 1, 0). */ - public static final Coordinates3D PLUS_J = new Coordinates3D(0, 1, 0); - - /** Opposite of the second canonical vector (coordinates: 0, -1, 0). */ - public static final Coordinates3D MINUS_J = new Coordinates3D(0, -1, 0); - - /** Third canonical vector (coordinates: 0, 0, 1). */ - public static final Coordinates3D PLUS_K = new Coordinates3D(0, 0, 1); - - /** Opposite of the third canonical vector (coordinates: 0, 0, -1). */ - public static final Coordinates3D MINUS_K = new Coordinates3D(0, 0, -1); - - // CHECKSTYLE: stop ConstantName - /** A vector with all coordinates set to NaN. */ - public static final Coordinates3D NaN = new Coordinates3D(Double.NaN, Double.NaN, Double.NaN); - // CHECKSTYLE: resume ConstantName - - /** A vector with all coordinates set to positive infinity. */ - public static final Coordinates3D POSITIVE_INFINITY = - new Coordinates3D(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY); - - /** A vector with all coordinates set to negative infinity. */ - public static final Coordinates3D NEGATIVE_INFINITY = - new Coordinates3D(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY); - - /** Serializable version identifier. */ - private static final long serialVersionUID = 1313493323784566947L; - - /** Abscissa. */ - private final double x; - - /** Ordinate. */ - private final double y; - - /** Height. */ - private final double 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 Coordinates3D(double x, double y, double 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 Coordinates3D(double[] 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 Coordinates3D(double alpha, double delta) { - double cosDelta = FastMath.cos(delta); - this.x = FastMath.cos(alpha) * cosDelta; - this.y = FastMath.sin(alpha) * cosDelta; - this.z = FastMath.sin(delta); - } - - /** 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 Coordinates3D(double a, Coordinates3D u) { - this.x = a * u.x; - this.y = a * u.y; - this.z = a * u.z; - } - - /** 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 Coordinates3D(double a1, Coordinates3D u1, double a2, Coordinates3D u2) { - this.x = MathArrays.linearCombination(a1, u1.x, a2, u2.x); - this.y = MathArrays.linearCombination(a1, u1.y, a2, u2.y); - this.z = MathArrays.linearCombination(a1, u1.z, a2, u2.z); - } - - /** 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 Coordinates3D(double a1, Coordinates3D u1, double a2, Coordinates3D u2, - double a3, Coordinates3D u3) { - this.x = MathArrays.linearCombination(a1, u1.x, a2, u2.x, a3, u3.x); - this.y = MathArrays.linearCombination(a1, u1.y, a2, u2.y, a3, u3.y); - this.z = MathArrays.linearCombination(a1, u1.z, a2, u2.z, a3, u3.z); - } - - /** 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 Coordinates3D(double a1, Coordinates3D u1, double a2, Coordinates3D u2, - double a3, Coordinates3D u3, double a4, Coordinates3D u4) { - this.x = MathArrays.linearCombination(a1, u1.x, a2, u2.x, a3, u3.x, a4, u4.x); - this.y = MathArrays.linearCombination(a1, u1.y, a2, u2.y, a3, u3.y, a4, u4.y); - this.z = MathArrays.linearCombination(a1, u1.z, a2, u2.z, a3, u3.z, a4, u4.z); - } - - /** Get the abscissa of the vector. - * @return abscissa of the vector - * @see #Vector3D(double, double, double) - */ - public double getX() { - return x; - } - - /** Get the ordinate of the vector. - * @return ordinate of the vector - * @see #Vector3D(double, double, double) - */ - public double getY() { - return y; - } - - /** Get the height of the vector. - * @return height of the vector - * @see #Vector3D(double, double, double) - */ - public double getZ() { - return z; - } - - /** Get the vector coordinates as a dimension 3 array. - * @return vector coordinates - * @see #Vector3D(double[]) - */ - public double[] toArray() { - return new double[] { x, y, z }; - } - - /** {@inheritDoc} */ - @Override - public Space getSpace() { - return Euclidean3D.getInstance(); - } - - /** {@inheritDoc} */ - @Override - public Coordinates3D getZero() { - return ZERO; - } - - /** {@inheritDoc} */ - @Override - public double getNorm1() { - return FastMath.abs(x) + FastMath.abs(y) + FastMath.abs(z); - } - - /** {@inheritDoc} */ - @Override - public double getNorm() { - // there are no cancellation problems here, so we use the straightforward formula - return FastMath.sqrt (x * x + y * y + z * z); - } - - /** {@inheritDoc} */ - @Override - public double getNormSq() { - // there are no cancellation problems here, so we use the straightforward formula - return x * x + y * y + z * z; - } - - /** {@inheritDoc} */ - @Override - public double getNormInf() { - return FastMath.max(FastMath.max(FastMath.abs(x), FastMath.abs(y)), FastMath.abs(z)); - } - - /** Get the azimuth of the vector. - * @return azimuth (α) of the vector, between -π and +π - * @see #Vector3D(double, double) - */ - public double getAlpha() { - return FastMath.atan2(y, x); - } - - /** Get the elevation of the vector. - * @return elevation (δ) of the vector, between -π/2 and +π/2 - * @see #Vector3D(double, double) - */ - public double getDelta() { - return FastMath.asin(z / getNorm()); - } - - /** {@inheritDoc} */ - @Override - public Coordinates3D add(final Vector v) { - final Coordinates3D v3 = (Coordinates3D) v; - return new Coordinates3D(x + v3.x, y + v3.y, z + v3.z); - } - - /** {@inheritDoc} */ - @Override - public Coordinates3D add(double factor, final Vector v) { - return new Coordinates3D(1, this, factor, (Coordinates3D) v); - } - - /** {@inheritDoc} */ - @Override - public Coordinates3D subtract(final Vector v) { - final Coordinates3D v3 = (Coordinates3D) v; - return new Coordinates3D(x - v3.x, y - v3.y, z - v3.z); - } - - /** {@inheritDoc} */ - @Override - public Coordinates3D subtract(final double factor, final Vector v) { - return new Coordinates3D(1, this, -factor, (Coordinates3D) v); - } - - /** {@inheritDoc} */ - @Override - public Coordinates3D normalize() throws MathArithmeticException { - double s = getNorm(); - if (s == 0) { - throw new MathArithmeticException(LocalizedFormats.CANNOT_NORMALIZE_A_ZERO_NORM_VECTOR); - } - return scalarMultiply(1 / s); - } - - /** Get a vector orthogonal to the instance. - *

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 : - *


-     *   Vector3D k = u.normalize();
-     *   Vector3D i = k.orthogonal();
-     *   Vector3D j = Vector3D.crossProduct(k, i);
-     * 

- * @return a new normalized vector orthogonal to the instance - * @exception MathArithmeticException if the norm of the instance is null - */ - public Coordinates3D orthogonal() throws MathArithmeticException { - - double threshold = 0.6 * getNorm(); - if (threshold == 0) { - throw new MathArithmeticException(LocalizedFormats.ZERO_NORM); - } - - if (FastMath.abs(x) <= threshold) { - double inverse = 1 / FastMath.sqrt(y * y + z * z); - return new Coordinates3D(0, inverse * z, -inverse * y); - } else if (FastMath.abs(y) <= threshold) { - double inverse = 1 / FastMath.sqrt(x * x + z * z); - return new Coordinates3D(-inverse * z, 0, inverse * x); - } - double inverse = 1 / FastMath.sqrt(x * x + y * y); - return new Coordinates3D(inverse * y, -inverse * x, 0); - - } - - /** Compute the angular separation between two vectors. - *

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.

- * @param v1 first vector - * @param v2 second vector - * @return angular separation between v1 and v2 - * @exception MathArithmeticException if either vector has a null norm - */ - public static double angle(Coordinates3D v1, Coordinates3D v2) throws MathArithmeticException { - - double normProduct = v1.getNorm() * v2.getNorm(); - if (normProduct == 0) { - throw new MathArithmeticException(LocalizedFormats.ZERO_NORM); - } - - double dot = v1.dotProduct(v2); - double threshold = normProduct * 0.9999; - if ((dot < -threshold) || (dot > threshold)) { - // the vectors are almost aligned, compute using the sine - Coordinates3D v3 = crossProduct(v1, v2); - if (dot >= 0) { - return FastMath.asin(v3.getNorm() / normProduct); - } - return FastMath.PI - FastMath.asin(v3.getNorm() / normProduct); - } - - // the vectors are sufficiently separated to use the cosine - return FastMath.acos(dot / normProduct); - - } - - /** {@inheritDoc} */ - @Override - public Coordinates3D negate() { - return new Coordinates3D(-x, -y, -z); - } - - /** {@inheritDoc} */ - @Override - public Coordinates3D scalarMultiply(double a) { - return new Coordinates3D(a * x, a * y, a * z); - } - - /** {@inheritDoc} */ - @Override - public boolean isNaN() { - return Double.isNaN(x) || Double.isNaN(y) || Double.isNaN(z); - } - - /** {@inheritDoc} */ - @Override - public boolean isInfinite() { - return !isNaN() && (Double.isInfinite(x) || Double.isInfinite(y) || Double.isInfinite(z)); - } - - /** - * Test for the equality of two 3D vectors. - *

- * If all coordinates of two 3D vectors are exactly the same, and none are - * Double.NaN, the two 3D vectors are considered to be equal. - *

- *

- * NaN coordinates are considered to affect globally the vector - * and be equals to each other - i.e, if either (or all) coordinates of the - * 3D vector are equal to Double.NaN, the 3D vector is equal to - * {@link #NaN}. - *

- * - * @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 Coordinates3D) { - final Coordinates3D rhs = (Coordinates3D)other; - if (rhs.isNaN()) { - return this.isNaN(); - } - - return (x == rhs.x) && (y == rhs.y) && (z == rhs.z); - } - return false; - } - - /** - * Get a hashCode for the 3D vector. - *

- * All NaN values have the same hash code.

- * - * @return a hash code value for this object - */ - @Override - public int hashCode() { - if (isNaN()) { - return 642; - } - return 643 * (164 * MathUtils.hash(x) + 3 * MathUtils.hash(y) + MathUtils.hash(z)); - } - - /** {@inheritDoc} - *

- * 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. - *

- * @see MathArrays#linearCombination(double, double, double, double, double, double) - */ - @Override - public double dotProduct(final Vector v) { - final Coordinates3D v3 = (Coordinates3D) v; - return MathArrays.linearCombination(x, v3.x, y, v3.y, z, v3.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 Coordinates3D crossProduct(final Vector v) { - final Coordinates3D v3 = (Coordinates3D) v; - return new Coordinates3D(MathArrays.linearCombination(y, v3.z, -z, v3.y), - MathArrays.linearCombination(z, v3.x, -x, v3.z), - MathArrays.linearCombination(x, v3.y, -y, v3.x)); - } - - /** {@inheritDoc} */ - @Override - public double distance1(Vector v) { - final Coordinates3D v3 = (Coordinates3D) v; - final double dx = FastMath.abs(v3.x - x); - final double dy = FastMath.abs(v3.y - y); - final double dz = FastMath.abs(v3.z - z); - return dx + dy + dz; - } - - /** {@inheritDoc} */ - @Override - public double distance(Point p) { - return distance((Coordinates3D) p); - } - - /** {@inheritDoc} */ - @Override - public double distance(Vector v) { - return distance((Coordinates3D) v); - } - - /** Compute the distance between the instance and other coordinates. - * @param c other coordinates - * @return the distance between the instance and c - */ - public double distance(Coordinates3D c) { - final double dx = c.x - x; - final double dy = c.y - y; - final double dz = c.z - z; - return FastMath.sqrt(dx * dx + dy * dy + dz * dz); - } - - /** {@inheritDoc} */ - @Override - public double distanceInf(Vector v) { - final Coordinates3D v3 = (Coordinates3D) v; - final double dx = FastMath.abs(v3.x - x); - final double dy = FastMath.abs(v3.y - y); - final double dz = FastMath.abs(v3.z - z); - return FastMath.max(FastMath.max(dx, dy), dz); - } - - /** {@inheritDoc} */ - @Override - public double distanceSq(Vector v) { - final Coordinates3D v3 = (Coordinates3D) v; - final double dx = v3.x - x; - final double dy = v3.y - y; - final double dz = v3.z - z; - return dx * dx + dy * dy + dz * dz; - } - - /** Compute the dot-product of two vectors. - * @param v1 first vector - * @param v2 second vector - * @return the dot product v1.v2 - */ - public static double dotProduct(Coordinates3D v1, Coordinates3D v2) { - return v1.dotProduct(v2); - } - - /** Compute the cross-product of two vectors. - * @param v1 first vector - * @param v2 second vector - * @return the cross product v1 ^ v2 as a new Vector - */ - public static Coordinates3D crossProduct(final Coordinates3D v1, final Coordinates3D v2) { - return v1.crossProduct(v2); - } - - /** Compute the distance between two vectors according to the L1 norm. - *

Calling this method is equivalent to calling: - * v1.subtract(v2).getNorm1() except that no intermediate - * vector is built

- * @param v1 first vector - * @param v2 second vector - * @return the distance between v1 and v2 according to the L1 norm - */ - public static double distance1(Coordinates3D v1, Coordinates3D v2) { - return v1.distance1(v2); - } - - /** Compute the distance between two vectors according to the L2 norm. - *

Calling this method is equivalent to calling: - * v1.subtract(v2).getNorm() except that no intermediate - * vector is built

- * @param v1 first vector - * @param v2 second vector - * @return the distance between v1 and v2 according to the L2 norm - */ - public static double distance(Coordinates3D v1, Coordinates3D v2) { - return v1.distance(v2); - } - - /** Compute the distance between two vectors according to the L norm. - *

Calling this method is equivalent to calling: - * v1.subtract(v2).getNormInf() except that no intermediate - * vector is built

- * @param v1 first vector - * @param v2 second vector - * @return the distance between v1 and v2 according to the L norm - */ - public static double distanceInf(Coordinates3D v1, Coordinates3D v2) { - return v1.distanceInf(v2); - } - - /** Compute the square of the distance between two vectors. - *

Calling this method is equivalent to calling: - * v1.subtract(v2).getNormSq() except that no intermediate - * vector is built

- * @param v1 first vector - * @param v2 second vector - * @return the square of the distance between v1 and v2 - */ - public static double distanceSq(Coordinates3D v1, Coordinates3D v2) { - return v1.distanceSq(v2); - } - - /** Get a string representation of this vector. - * @return a string representation of this vector - */ - @Override - public String toString() { - return Vector3DFormat.getInstance().format(this); - } - - /** {@inheritDoc} */ - @Override - public String toString(final NumberFormat format) { - return new Vector3DFormat(format).format(this); - } - -}