http://git-wip-us.apache.org/repos/asf/commons-math/blob/b815d2af/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/Rotation.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/Rotation.java b/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/Rotation.java index 5de70a5..ff8f17e 100644 --- a/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/Rotation.java +++ b/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/Rotation.java @@ -48,8 +48,8 @@ import org.apache.commons.math4.util.MathArrays; * <p>Focus is oriented on what a rotation <em>do</em> rather than on its * underlying representation. Once it has been built, and regardless of its * internal representation, a rotation is an <em>operator</em> which basically - * transforms three dimensional {@link Vector3D vectors} into other three - * dimensional {@link Vector3D vectors}. Depending on the application, the + * transforms three dimensional {@link Coordinates3D vectors} into other three + * dimensional {@link Coordinates3D vectors}. Depending on the application, the * meaning of these vectors may vary and the semantics of the rotation also.</p> * <p>For example in an spacecraft attitude simulation tool, users will often * consider the vectors are fixed (say the Earth direction for example) and the @@ -88,7 +88,7 @@ import org.apache.commons.math4.util.MathArrays; * * <p>Rotations are guaranteed to be immutable objects.</p> * - * @see Vector3D + * @see Coordinates3D * @see RotationOrder * @since 1.2 */ @@ -162,7 +162,7 @@ public class Rotation implements Serializable { * @deprecated as of 3.6, replaced with {@link #Rotation(Vector3D, double, RotationConvention)} */ @Deprecated - public Rotation(Vector3D axis, double angle) throws MathIllegalArgumentException { + public Rotation(Coordinates3D axis, double angle) throws MathIllegalArgumentException { this(axis, angle, RotationConvention.VECTOR_OPERATOR); } @@ -173,7 +173,7 @@ public class Rotation implements Serializable { * @exception MathIllegalArgumentException if the axis norm is zero * @since 3.6 */ - public Rotation(final Vector3D axis, final double angle, final RotationConvention convention) + public Rotation(final Coordinates3D axis, final double angle, final RotationConvention convention) throws MathIllegalArgumentException { double norm = axis.getNorm(); @@ -272,18 +272,18 @@ public class Rotation implements Serializable { * @exception MathArithmeticException if the norm of one of the vectors is zero, * or if one of the pair is degenerated (i.e. the vectors of the pair are collinear) */ - public Rotation(Vector3D u1, Vector3D u2, Vector3D v1, Vector3D v2) + public Rotation(Coordinates3D u1, Coordinates3D u2, Coordinates3D v1, Coordinates3D v2) throws MathArithmeticException { // build orthonormalized base from u1, u2 // this fails when vectors are null or collinear, which is forbidden to define a rotation - final Vector3D u3 = u1.crossProduct(u2).normalize(); + final Coordinates3D u3 = u1.crossProduct(u2).normalize(); u2 = u3.crossProduct(u1).normalize(); u1 = u1.normalize(); // build an orthonormalized base from v1, v2 // this fails when vectors are null or collinear, which is forbidden to define a rotation - final Vector3D v3 = v1.crossProduct(v2).normalize(); + final Coordinates3D v3 = v1.crossProduct(v2).normalize(); v2 = v3.crossProduct(v1).normalize(); v1 = v1.normalize(); @@ -327,7 +327,7 @@ public class Rotation implements Serializable { * @param v desired image of u by the rotation * @exception MathArithmeticException if the norm of one of the vectors is zero */ - public Rotation(Vector3D u, Vector3D v) throws MathArithmeticException { + public Rotation(Coordinates3D u, Coordinates3D v) throws MathArithmeticException { double normProduct = u.getNorm() * v.getNorm(); if (normProduct == 0) { @@ -339,7 +339,7 @@ public class Rotation implements Serializable { if (dot < ((2.0e-15 - 1.0) * normProduct)) { // special case u = -v: we select a PI angle rotation around // an arbitrary vector orthogonal to u - Vector3D w = u.orthogonal(); + Coordinates3D w = u.orthogonal(); q0 = 0.0; q1 = -w.getX(); q2 = -w.getY(); @@ -349,7 +349,7 @@ public class Rotation implements Serializable { // the shortest possible rotation: axis orthogonal to this plane q0 = FastMath.sqrt(0.5 * (1.0 + dot / normProduct)); double coeff = 1.0 / (2.0 * q0 * normProduct); - Vector3D q = v.crossProduct(u); + Coordinates3D q = v.crossProduct(u); q1 = coeff * q.getX(); q2 = coeff * q.getY(); q3 = coeff * q.getZ(); @@ -522,7 +522,7 @@ public class Rotation implements Serializable { * @deprecated as of 3.6, replaced with {@link #getAxis(RotationConvention)} */ @Deprecated - public Vector3D getAxis() { + public Coordinates3D getAxis() { return getAxis(RotationConvention.VECTOR_OPERATOR); } @@ -537,18 +537,18 @@ public class Rotation implements Serializable { * @see #Rotation(Vector3D, double, RotationConvention) * @since 3.6 */ - public Vector3D getAxis(final RotationConvention convention) { + public Coordinates3D getAxis(final RotationConvention convention) { final double squaredSine = q1 * q1 + q2 * q2 + q3 * q3; if (squaredSine == 0) { - return convention == RotationConvention.VECTOR_OPERATOR ? Vector3D.PLUS_I : Vector3D.MINUS_I; + return convention == RotationConvention.VECTOR_OPERATOR ? Coordinates3D.PLUS_I : Coordinates3D.MINUS_I; } else { final double sgn = convention == RotationConvention.VECTOR_OPERATOR ? +1 : -1; if (q0 < 0) { final double inverse = sgn / FastMath.sqrt(squaredSine); - return new Vector3D(q1 * inverse, q2 * inverse, q3 * inverse); + return new Coordinates3D(q1 * inverse, q2 * inverse, q3 * inverse); } final double inverse = -sgn / FastMath.sqrt(squaredSine); - return new Vector3D(q1 * inverse, q2 * inverse, q3 * inverse); + return new Coordinates3D(q1 * inverse, q2 * inverse, q3 * inverse); } } @@ -633,8 +633,8 @@ public class Rotation implements Serializable { // (-r) (Vector3D.plusI) coordinates are : // cos (psi) cos (theta), -sin (psi) cos (theta), sin (theta) // and we can choose to have theta in the interval [-PI/2 ; +PI/2] - Vector3D v1 = applyTo(Vector3D.PLUS_K); - Vector3D v2 = applyInverseTo(Vector3D.PLUS_I); + Coordinates3D v1 = applyTo(Coordinates3D.PLUS_K); + Coordinates3D v2 = applyInverseTo(Coordinates3D.PLUS_I); if ((v2.getZ() < -0.9999999999) || (v2.getZ() > 0.9999999999)) { throw new CardanEulerSingularityException(true); } @@ -651,8 +651,8 @@ public class Rotation implements Serializable { // (-r) (Vector3D.plusI) coordinates are : // cos (theta) cos (psi), -sin (psi), sin (theta) cos (psi) // and we can choose to have psi in the interval [-PI/2 ; +PI/2] - Vector3D v1 = applyTo(Vector3D.PLUS_J); - Vector3D v2 = applyInverseTo(Vector3D.PLUS_I); + Coordinates3D v1 = applyTo(Coordinates3D.PLUS_J); + Coordinates3D v2 = applyInverseTo(Coordinates3D.PLUS_I); if ((v2.getY() < -0.9999999999) || (v2.getY() > 0.9999999999)) { throw new CardanEulerSingularityException(true); } @@ -669,8 +669,8 @@ public class Rotation implements Serializable { // (-r) (Vector3D.plusJ) coordinates are : // sin (psi) cos (phi), cos (psi) cos (phi), -sin (phi) // and we can choose to have phi in the interval [-PI/2 ; +PI/2] - Vector3D v1 = applyTo(Vector3D.PLUS_K); - Vector3D v2 = applyInverseTo(Vector3D.PLUS_J); + Coordinates3D v1 = applyTo(Coordinates3D.PLUS_K); + Coordinates3D v2 = applyInverseTo(Coordinates3D.PLUS_J); if ((v2.getZ() < -0.9999999999) || (v2.getZ() > 0.9999999999)) { throw new CardanEulerSingularityException(true); } @@ -687,8 +687,8 @@ public class Rotation implements Serializable { // (-r) (Vector3D.plusJ) coordinates are : // sin (psi), cos (phi) cos (psi), -sin (phi) cos (psi) // and we can choose to have psi in the interval [-PI/2 ; +PI/2] - Vector3D v1 = applyTo(Vector3D.PLUS_I); - Vector3D v2 = applyInverseTo(Vector3D.PLUS_J); + Coordinates3D v1 = applyTo(Coordinates3D.PLUS_I); + Coordinates3D v2 = applyInverseTo(Coordinates3D.PLUS_J); if ((v2.getX() < -0.9999999999) || (v2.getX() > 0.9999999999)) { throw new CardanEulerSingularityException(true); } @@ -705,8 +705,8 @@ public class Rotation implements Serializable { // (-r) (Vector3D.plusK) coordinates are : // -sin (theta) cos (phi), sin (phi), cos (theta) cos (phi) // and we can choose to have phi in the interval [-PI/2 ; +PI/2] - Vector3D v1 = applyTo(Vector3D.PLUS_J); - Vector3D v2 = applyInverseTo(Vector3D.PLUS_K); + Coordinates3D v1 = applyTo(Coordinates3D.PLUS_J); + Coordinates3D v2 = applyInverseTo(Coordinates3D.PLUS_K); if ((v2.getY() < -0.9999999999) || (v2.getY() > 0.9999999999)) { throw new CardanEulerSingularityException(true); } @@ -723,8 +723,8 @@ public class Rotation implements Serializable { // (-r) (Vector3D.plusK) coordinates are : // -sin (theta), sin (phi) cos (theta), cos (phi) cos (theta) // and we can choose to have theta in the interval [-PI/2 ; +PI/2] - Vector3D v1 = applyTo(Vector3D.PLUS_I); - Vector3D v2 = applyInverseTo(Vector3D.PLUS_K); + Coordinates3D v1 = applyTo(Coordinates3D.PLUS_I); + Coordinates3D v2 = applyInverseTo(Coordinates3D.PLUS_K); if ((v2.getX() < -0.9999999999) || (v2.getX() > 0.9999999999)) { throw new CardanEulerSingularityException(true); } @@ -741,8 +741,8 @@ public class Rotation implements Serializable { // (-r) (Vector3D.plusI) coordinates are : // cos (theta), sin (theta) sin (phi2), sin (theta) cos (phi2) // and we can choose to have theta in the interval [0 ; PI] - Vector3D v1 = applyTo(Vector3D.PLUS_I); - Vector3D v2 = applyInverseTo(Vector3D.PLUS_I); + Coordinates3D v1 = applyTo(Coordinates3D.PLUS_I); + Coordinates3D v2 = applyInverseTo(Coordinates3D.PLUS_I); if ((v2.getX() < -0.9999999999) || (v2.getX() > 0.9999999999)) { throw new CardanEulerSingularityException(false); } @@ -759,8 +759,8 @@ public class Rotation implements Serializable { // (-r) (Vector3D.plusI) coordinates are : // cos (psi), -sin (psi) cos (phi2), sin (psi) sin (phi2) // and we can choose to have psi in the interval [0 ; PI] - Vector3D v1 = applyTo(Vector3D.PLUS_I); - Vector3D v2 = applyInverseTo(Vector3D.PLUS_I); + Coordinates3D v1 = applyTo(Coordinates3D.PLUS_I); + Coordinates3D v2 = applyInverseTo(Coordinates3D.PLUS_I); if ((v2.getX() < -0.9999999999) || (v2.getX() > 0.9999999999)) { throw new CardanEulerSingularityException(false); } @@ -777,8 +777,8 @@ public class Rotation implements Serializable { // (-r) (Vector3D.plusJ) coordinates are : // sin (phi) sin (theta2), cos (phi), -sin (phi) cos (theta2) // and we can choose to have phi in the interval [0 ; PI] - Vector3D v1 = applyTo(Vector3D.PLUS_J); - Vector3D v2 = applyInverseTo(Vector3D.PLUS_J); + Coordinates3D v1 = applyTo(Coordinates3D.PLUS_J); + Coordinates3D v2 = applyInverseTo(Coordinates3D.PLUS_J); if ((v2.getY() < -0.9999999999) || (v2.getY() > 0.9999999999)) { throw new CardanEulerSingularityException(false); } @@ -795,8 +795,8 @@ public class Rotation implements Serializable { // (-r) (Vector3D.plusJ) coordinates are : // sin (psi) cos (theta2), cos (psi), sin (psi) sin (theta2) // and we can choose to have psi in the interval [0 ; PI] - Vector3D v1 = applyTo(Vector3D.PLUS_J); - Vector3D v2 = applyInverseTo(Vector3D.PLUS_J); + Coordinates3D v1 = applyTo(Coordinates3D.PLUS_J); + Coordinates3D v2 = applyInverseTo(Coordinates3D.PLUS_J); if ((v2.getY() < -0.9999999999) || (v2.getY() > 0.9999999999)) { throw new CardanEulerSingularityException(false); } @@ -813,8 +813,8 @@ public class Rotation implements Serializable { // (-r) (Vector3D.plusK) coordinates are : // sin (phi) sin (psi2), sin (phi) cos (psi2), cos (phi) // and we can choose to have phi in the interval [0 ; PI] - Vector3D v1 = applyTo(Vector3D.PLUS_K); - Vector3D v2 = applyInverseTo(Vector3D.PLUS_K); + Coordinates3D v1 = applyTo(Coordinates3D.PLUS_K); + Coordinates3D v2 = applyInverseTo(Coordinates3D.PLUS_K); if ((v2.getZ() < -0.9999999999) || (v2.getZ() > 0.9999999999)) { throw new CardanEulerSingularityException(false); } @@ -831,8 +831,8 @@ public class Rotation implements Serializable { // (-r) (Vector3D.plusK) coordinates are : // -sin (theta) cos (psi2), sin (theta) sin (psi2), cos (theta) // and we can choose to have theta in the interval [0 ; PI] - Vector3D v1 = applyTo(Vector3D.PLUS_K); - Vector3D v2 = applyInverseTo(Vector3D.PLUS_K); + Coordinates3D v1 = applyTo(Coordinates3D.PLUS_K); + Coordinates3D v2 = applyInverseTo(Coordinates3D.PLUS_K); if ((v2.getZ() < -0.9999999999) || (v2.getZ() > 0.9999999999)) { throw new CardanEulerSingularityException(false); } @@ -851,8 +851,8 @@ public class Rotation implements Serializable { // (-r) (Vector3D.plusK) coordinates are : // sin (theta), -sin (phi) cos (theta), cos (phi) cos (theta) // and we can choose to have theta in the interval [-PI/2 ; +PI/2] - Vector3D v1 = applyTo(Vector3D.PLUS_I); - Vector3D v2 = applyInverseTo(Vector3D.PLUS_K); + Coordinates3D v1 = applyTo(Coordinates3D.PLUS_I); + Coordinates3D v2 = applyInverseTo(Coordinates3D.PLUS_K); if ((v2.getX() < -0.9999999999) || (v2.getX() > 0.9999999999)) { throw new CardanEulerSingularityException(true); } @@ -869,8 +869,8 @@ public class Rotation implements Serializable { // (-r) (Vector3D.plusJ) coordinates are : // -sin (psi), cos (phi) cos (psi), sin (phi) cos (psi) // and we can choose to have psi in the interval [-PI/2 ; +PI/2] - Vector3D v1 = applyTo(Vector3D.PLUS_I); - Vector3D v2 = applyInverseTo(Vector3D.PLUS_J); + Coordinates3D v1 = applyTo(Coordinates3D.PLUS_I); + Coordinates3D v2 = applyInverseTo(Coordinates3D.PLUS_J); if ((v2.getX() < -0.9999999999) || (v2.getX() > 0.9999999999)) { throw new CardanEulerSingularityException(true); } @@ -887,8 +887,8 @@ public class Rotation implements Serializable { // (-r) (Vector3D.plusK) coordinates are : // sin (theta) cos (phi), -sin (phi), cos (theta) cos (phi) // and we can choose to have phi in the interval [-PI/2 ; +PI/2] - Vector3D v1 = applyTo(Vector3D.PLUS_J); - Vector3D v2 = applyInverseTo(Vector3D.PLUS_K); + Coordinates3D v1 = applyTo(Coordinates3D.PLUS_J); + Coordinates3D v2 = applyInverseTo(Coordinates3D.PLUS_K); if ((v2.getY() < -0.9999999999) || (v2.getY() > 0.9999999999)) { throw new CardanEulerSingularityException(true); } @@ -905,8 +905,8 @@ public class Rotation implements Serializable { // (-r) (Vector3D.plusI) coordinates are : // cos (theta) cos (psi), sin (psi), -sin (theta) cos (psi) // and we can choose to have psi in the interval [-PI/2 ; +PI/2] - Vector3D v1 = applyTo(Vector3D.PLUS_J); - Vector3D v2 = applyInverseTo(Vector3D.PLUS_I); + Coordinates3D v1 = applyTo(Coordinates3D.PLUS_J); + Coordinates3D v2 = applyInverseTo(Coordinates3D.PLUS_I); if ((v2.getY() < -0.9999999999) || (v2.getY() > 0.9999999999)) { throw new CardanEulerSingularityException(true); } @@ -923,8 +923,8 @@ public class Rotation implements Serializable { // (-r) (Vector3D.plusJ) coordinates are : // -sin (psi) cos (phi), cos (psi) cos (phi), sin (phi) // and we can choose to have phi in the interval [-PI/2 ; +PI/2] - Vector3D v1 = applyTo(Vector3D.PLUS_K); - Vector3D v2 = applyInverseTo(Vector3D.PLUS_J); + Coordinates3D v1 = applyTo(Coordinates3D.PLUS_K); + Coordinates3D v2 = applyInverseTo(Coordinates3D.PLUS_J); if ((v2.getZ() < -0.9999999999) || (v2.getZ() > 0.9999999999)) { throw new CardanEulerSingularityException(true); } @@ -941,8 +941,8 @@ public class Rotation implements Serializable { // (-r) (Vector3D.plusI) coordinates are : // cos (psi) cos (theta), sin (psi) cos (theta), -sin (theta) // and we can choose to have theta in the interval [-PI/2 ; +PI/2] - Vector3D v1 = applyTo(Vector3D.PLUS_K); - Vector3D v2 = applyInverseTo(Vector3D.PLUS_I); + Coordinates3D v1 = applyTo(Coordinates3D.PLUS_K); + Coordinates3D v2 = applyInverseTo(Coordinates3D.PLUS_I); if ((v2.getZ() < -0.9999999999) || (v2.getZ() > 0.9999999999)) { throw new CardanEulerSingularityException(true); } @@ -959,8 +959,8 @@ public class Rotation implements Serializable { // (-r) (Vector3D.plusI) coordinates are : // cos (theta), sin (theta) sin (phi1), -sin (theta) cos (phi1) // and we can choose to have theta in the interval [0 ; PI] - Vector3D v1 = applyTo(Vector3D.PLUS_I); - Vector3D v2 = applyInverseTo(Vector3D.PLUS_I); + Coordinates3D v1 = applyTo(Coordinates3D.PLUS_I); + Coordinates3D v2 = applyInverseTo(Coordinates3D.PLUS_I); if ((v2.getX() < -0.9999999999) || (v2.getX() > 0.9999999999)) { throw new CardanEulerSingularityException(false); } @@ -977,8 +977,8 @@ public class Rotation implements Serializable { // (-r) (Vector3D.plusI) coordinates are : // cos (psi), sin (psi) cos (phi1), sin (psi) sin (phi1) // and we can choose to have psi in the interval [0 ; PI] - Vector3D v1 = applyTo(Vector3D.PLUS_I); - Vector3D v2 = applyInverseTo(Vector3D.PLUS_I); + Coordinates3D v1 = applyTo(Coordinates3D.PLUS_I); + Coordinates3D v2 = applyInverseTo(Coordinates3D.PLUS_I); if ((v2.getX() < -0.9999999999) || (v2.getX() > 0.9999999999)) { throw new CardanEulerSingularityException(false); } @@ -995,8 +995,8 @@ public class Rotation implements Serializable { // (-r) (Vector3D.plusJ) coordinates are : // sin (theta1) sin (phi), cos (phi), cos (theta1) sin (phi) // and we can choose to have phi in the interval [0 ; PI] - Vector3D v1 = applyTo(Vector3D.PLUS_J); - Vector3D v2 = applyInverseTo(Vector3D.PLUS_J); + Coordinates3D v1 = applyTo(Coordinates3D.PLUS_J); + Coordinates3D v2 = applyInverseTo(Coordinates3D.PLUS_J); if ((v2.getY() < -0.9999999999) || (v2.getY() > 0.9999999999)) { throw new CardanEulerSingularityException(false); } @@ -1013,8 +1013,8 @@ public class Rotation implements Serializable { // (-r) (Vector3D.plusJ) coordinates are : // -cos (theta1) sin (psi), cos (psi), sin (theta1) sin (psi) // and we can choose to have psi in the interval [0 ; PI] - Vector3D v1 = applyTo(Vector3D.PLUS_J); - Vector3D v2 = applyInverseTo(Vector3D.PLUS_J); + Coordinates3D v1 = applyTo(Coordinates3D.PLUS_J); + Coordinates3D v2 = applyInverseTo(Coordinates3D.PLUS_J); if ((v2.getY() < -0.9999999999) || (v2.getY() > 0.9999999999)) { throw new CardanEulerSingularityException(false); } @@ -1031,8 +1031,8 @@ public class Rotation implements Serializable { // (-r) (Vector3D.plusK) coordinates are : // sin (psi1) sin (phi), -cos (psi1) sin (phi), cos (phi) // and we can choose to have phi in the interval [0 ; PI] - Vector3D v1 = applyTo(Vector3D.PLUS_K); - Vector3D v2 = applyInverseTo(Vector3D.PLUS_K); + Coordinates3D v1 = applyTo(Coordinates3D.PLUS_K); + Coordinates3D v2 = applyInverseTo(Coordinates3D.PLUS_K); if ((v2.getZ() < -0.9999999999) || (v2.getZ() > 0.9999999999)) { throw new CardanEulerSingularityException(false); } @@ -1049,8 +1049,8 @@ public class Rotation implements Serializable { // (-r) (Vector3D.plusK) coordinates are : // cos (psi1) sin (theta), sin (psi1) sin (theta), cos (theta) // and we can choose to have theta in the interval [0 ; PI] - Vector3D v1 = applyTo(Vector3D.PLUS_K); - Vector3D v2 = applyInverseTo(Vector3D.PLUS_K); + Coordinates3D v1 = applyTo(Coordinates3D.PLUS_K); + Coordinates3D v2 = applyInverseTo(Coordinates3D.PLUS_K); if ((v2.getZ() < -0.9999999999) || (v2.getZ() > 0.9999999999)) { throw new CardanEulerSingularityException(false); } @@ -1108,7 +1108,7 @@ public class Rotation implements Serializable { * @param u vector to apply the rotation to * @return a new vector which is the image of u by the rotation */ - public Vector3D applyTo(Vector3D u) { + public Coordinates3D applyTo(Coordinates3D u) { double x = u.getX(); double y = u.getY(); @@ -1116,7 +1116,7 @@ public class Rotation implements Serializable { double s = q1 * x + q2 * y + q3 * z; - return new Vector3D(2 * (q0 * (x * q0 - (q2 * z - q3 * y)) + s * q1) - x, + return new Coordinates3D(2 * (q0 * (x * q0 - (q2 * z - q3 * y)) + s * q1) - x, 2 * (q0 * (y * q0 - (q3 * x - q1 * z)) + s * q2) - y, 2 * (q0 * (z * q0 - (q1 * y - q2 * x)) + s * q3) - z); @@ -1145,7 +1145,7 @@ public class Rotation implements Serializable { * @param u vector to apply the inverse of the rotation to * @return a new vector which such that u is its image by the rotation */ - public Vector3D applyInverseTo(Vector3D u) { + public Coordinates3D applyInverseTo(Coordinates3D u) { double x = u.getX(); double y = u.getY(); @@ -1154,7 +1154,7 @@ public class Rotation implements Serializable { double s = q1 * x + q2 * y + q3 * z; double m0 = -q0; - return new Vector3D(2 * (m0 * (x * m0 - (q2 * z - q3 * y)) + s * q1) - x, + return new Coordinates3D(2 * (m0 * (x * m0 - (q2 * z - q3 * y)) + s * q1) - x, 2 * (m0 * (y * m0 - (q3 * x - q1 * z)) + s * q2) - y, 2 * (m0 * (z * m0 - (q1 * y - q2 * x)) + s * q3) - z);
http://git-wip-us.apache.org/repos/asf/commons-math/blob/b815d2af/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/RotationOrder.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/RotationOrder.java b/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/RotationOrder.java index 83822e5..0eec6d0 100644 --- a/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/RotationOrder.java +++ b/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/RotationOrder.java @@ -35,96 +35,96 @@ public final class RotationOrder { * around Z */ public static final RotationOrder XYZ = - new RotationOrder("XYZ", Vector3D.PLUS_I, Vector3D.PLUS_J, Vector3D.PLUS_K); + new RotationOrder("XYZ", Coordinates3D.PLUS_I, Coordinates3D.PLUS_J, Coordinates3D.PLUS_K); /** Set of Cardan angles. * this ordered set of rotations is around X, then around Z, then * around Y */ public static final RotationOrder XZY = - new RotationOrder("XZY", Vector3D.PLUS_I, Vector3D.PLUS_K, Vector3D.PLUS_J); + new RotationOrder("XZY", Coordinates3D.PLUS_I, Coordinates3D.PLUS_K, Coordinates3D.PLUS_J); /** Set of Cardan angles. * this ordered set of rotations is around Y, then around X, then * around Z */ public static final RotationOrder YXZ = - new RotationOrder("YXZ", Vector3D.PLUS_J, Vector3D.PLUS_I, Vector3D.PLUS_K); + new RotationOrder("YXZ", Coordinates3D.PLUS_J, Coordinates3D.PLUS_I, Coordinates3D.PLUS_K); /** Set of Cardan angles. * this ordered set of rotations is around Y, then around Z, then * around X */ public static final RotationOrder YZX = - new RotationOrder("YZX", Vector3D.PLUS_J, Vector3D.PLUS_K, Vector3D.PLUS_I); + new RotationOrder("YZX", Coordinates3D.PLUS_J, Coordinates3D.PLUS_K, Coordinates3D.PLUS_I); /** Set of Cardan angles. * this ordered set of rotations is around Z, then around X, then * around Y */ public static final RotationOrder ZXY = - new RotationOrder("ZXY", Vector3D.PLUS_K, Vector3D.PLUS_I, Vector3D.PLUS_J); + new RotationOrder("ZXY", Coordinates3D.PLUS_K, Coordinates3D.PLUS_I, Coordinates3D.PLUS_J); /** Set of Cardan angles. * this ordered set of rotations is around Z, then around Y, then * around X */ public static final RotationOrder ZYX = - new RotationOrder("ZYX", Vector3D.PLUS_K, Vector3D.PLUS_J, Vector3D.PLUS_I); + new RotationOrder("ZYX", Coordinates3D.PLUS_K, Coordinates3D.PLUS_J, Coordinates3D.PLUS_I); /** Set of Euler angles. * this ordered set of rotations is around X, then around Y, then * around X */ public static final RotationOrder XYX = - new RotationOrder("XYX", Vector3D.PLUS_I, Vector3D.PLUS_J, Vector3D.PLUS_I); + new RotationOrder("XYX", Coordinates3D.PLUS_I, Coordinates3D.PLUS_J, Coordinates3D.PLUS_I); /** Set of Euler angles. * this ordered set of rotations is around X, then around Z, then * around X */ public static final RotationOrder XZX = - new RotationOrder("XZX", Vector3D.PLUS_I, Vector3D.PLUS_K, Vector3D.PLUS_I); + new RotationOrder("XZX", Coordinates3D.PLUS_I, Coordinates3D.PLUS_K, Coordinates3D.PLUS_I); /** Set of Euler angles. * this ordered set of rotations is around Y, then around X, then * around Y */ public static final RotationOrder YXY = - new RotationOrder("YXY", Vector3D.PLUS_J, Vector3D.PLUS_I, Vector3D.PLUS_J); + new RotationOrder("YXY", Coordinates3D.PLUS_J, Coordinates3D.PLUS_I, Coordinates3D.PLUS_J); /** Set of Euler angles. * this ordered set of rotations is around Y, then around Z, then * around Y */ public static final RotationOrder YZY = - new RotationOrder("YZY", Vector3D.PLUS_J, Vector3D.PLUS_K, Vector3D.PLUS_J); + new RotationOrder("YZY", Coordinates3D.PLUS_J, Coordinates3D.PLUS_K, Coordinates3D.PLUS_J); /** Set of Euler angles. * this ordered set of rotations is around Z, then around X, then * around Z */ public static final RotationOrder ZXZ = - new RotationOrder("ZXZ", Vector3D.PLUS_K, Vector3D.PLUS_I, Vector3D.PLUS_K); + new RotationOrder("ZXZ", Coordinates3D.PLUS_K, Coordinates3D.PLUS_I, Coordinates3D.PLUS_K); /** Set of Euler angles. * this ordered set of rotations is around Z, then around Y, then * around Z */ public static final RotationOrder ZYZ = - new RotationOrder("ZYZ", Vector3D.PLUS_K, Vector3D.PLUS_J, Vector3D.PLUS_K); + new RotationOrder("ZYZ", Coordinates3D.PLUS_K, Coordinates3D.PLUS_J, Coordinates3D.PLUS_K); /** Name of the rotations order. */ private final String name; /** Axis of the first rotation. */ - private final Vector3D a1; + private final Coordinates3D a1; /** Axis of the second rotation. */ - private final Vector3D a2; + private final Coordinates3D a2; /** Axis of the third rotation. */ - private final Vector3D a3; + private final Coordinates3D a3; /** Private constructor. * This is a utility class that cannot be instantiated by the user, @@ -135,7 +135,7 @@ public final class RotationOrder { * @param a3 axis of the third rotation */ private RotationOrder(final String name, - final Vector3D a1, final Vector3D a2, final Vector3D a3) { + final Coordinates3D a1, final Coordinates3D a2, final Coordinates3D a3) { this.name = name; this.a1 = a1; this.a2 = a2; @@ -153,21 +153,21 @@ public final class RotationOrder { /** Get the axis of the first rotation. * @return axis of the first rotation */ - public Vector3D getA1() { + public Coordinates3D getA1() { return a1; } /** Get the axis of the second rotation. * @return axis of the second rotation */ - public Vector3D getA2() { + public Coordinates3D getA2() { return a2; } /** Get the axis of the second rotation. * @return axis of the second rotation */ - public Vector3D getA3() { + public Coordinates3D getA3() { return a3; } http://git-wip-us.apache.org/repos/asf/commons-math/blob/b815d2af/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/Segment.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/Segment.java b/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/Segment.java index 2f765de..bf7e81f 100644 --- a/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/Segment.java +++ b/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/Segment.java @@ -23,10 +23,10 @@ package org.apache.commons.math4.geometry.euclidean.threed; public class Segment { /** Start point of the segment. */ - private final Vector3D start; + private final Coordinates3D start; /** End point of the segments. */ - private final Vector3D end; + private final Coordinates3D end; /** Line containing the segment. */ private final Line line; @@ -36,7 +36,7 @@ public class Segment { * @param end end point of the segment * @param line line containing the segment */ - public Segment(final Vector3D start, final Vector3D end, final Line line) { + public Segment(final Coordinates3D start, final Coordinates3D end, final Line line) { this.start = start; this.end = end; this.line = line; @@ -45,14 +45,14 @@ public class Segment { /** Get the start point of the segment. * @return start point of the segment */ - public Vector3D getStart() { + public Coordinates3D getStart() { return start; } /** Get the end point of the segment. * @return end point of the segment */ - public Vector3D getEnd() { + public Coordinates3D getEnd() { return end; } http://git-wip-us.apache.org/repos/asf/commons-math/blob/b815d2af/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/SphereGenerator.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/SphereGenerator.java b/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/SphereGenerator.java index deef1e9..08163dd 100644 --- a/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/SphereGenerator.java +++ b/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/SphereGenerator.java @@ -24,38 +24,38 @@ import org.apache.commons.math4.geometry.enclosing.EnclosingBall; import org.apache.commons.math4.geometry.enclosing.SupportBallGenerator; import org.apache.commons.math4.geometry.euclidean.twod.DiskGenerator; import org.apache.commons.math4.geometry.euclidean.twod.Euclidean2D; -import org.apache.commons.math4.geometry.euclidean.twod.Vector2D; +import org.apache.commons.math4.geometry.euclidean.twod.Coordinates2D; import org.apache.commons.math4.util.FastMath; /** Class generating an enclosing ball from its support points. * @since 3.3 */ -public class SphereGenerator implements SupportBallGenerator<Euclidean3D, Vector3D> { +public class SphereGenerator implements SupportBallGenerator<Euclidean3D, Coordinates3D> { /** {@inheritDoc} */ @Override - public EnclosingBall<Euclidean3D, Vector3D> ballOnSupport(final List<Vector3D> support) { + public EnclosingBall<Euclidean3D, Coordinates3D> ballOnSupport(final List<Coordinates3D> support) { if (support.size() < 1) { - return new EnclosingBall<>(Vector3D.ZERO, Double.NEGATIVE_INFINITY); + return new EnclosingBall<>(Coordinates3D.ZERO, Double.NEGATIVE_INFINITY); } else { - final Vector3D vA = support.get(0); + final Coordinates3D vA = support.get(0); if (support.size() < 2) { return new EnclosingBall<>(vA, 0, vA); } else { - final Vector3D vB = support.get(1); + final Coordinates3D vB = support.get(1); if (support.size() < 3) { - return new EnclosingBall<>(new Vector3D(0.5, vA, 0.5, vB), + return new EnclosingBall<>(new Coordinates3D(0.5, vA, 0.5, vB), 0.5 * vA.distance(vB), vA, vB); } else { - final Vector3D vC = support.get(2); + final Coordinates3D vC = support.get(2); if (support.size() < 4) { // delegate to 2D disk generator final Plane p = new Plane(vA, vB, vC, 1.0e-10 * (vA.getNorm1() + vB.getNorm1() + vC.getNorm1())); - final EnclosingBall<Euclidean2D, Vector2D> disk = + final EnclosingBall<Euclidean2D, Coordinates2D> disk = new DiskGenerator().ballOnSupport(Arrays.asList(p.toSubSpace(vA), p.toSubSpace(vB), p.toSubSpace(vC))); @@ -65,7 +65,7 @@ public class SphereGenerator implements SupportBallGenerator<Euclidean3D, Vector disk.getRadius(), vA, vB, vC); } else { - final Vector3D vD = support.get(3); + final Coordinates3D vD = support.get(3); // a sphere is 3D can be defined as: // (1) (x - x_0)^2 + (y - y_0)^2 + (z - z_0)^2 = r^2 // which can be written: @@ -118,7 +118,7 @@ public class SphereGenerator implements SupportBallGenerator<Euclidean3D, Vector final BigFraction dy = c3[0].subtract(centerY); final BigFraction dz = c4[0].subtract(centerZ); final BigFraction r2 = dx.multiply(dx).add(dy.multiply(dy)).add(dz.multiply(dz)); - return new EnclosingBall<>(new Vector3D(centerX.doubleValue(), + return new EnclosingBall<>(new Coordinates3D(centerX.doubleValue(), centerY.doubleValue(), centerZ.doubleValue()), FastMath.sqrt(r2.doubleValue()), http://git-wip-us.apache.org/repos/asf/commons-math/blob/b815d2af/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/SphericalCoordinates.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/SphericalCoordinates.java b/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/SphericalCoordinates.java index 97155b6..aa4582a 100644 --- a/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/SphericalCoordinates.java +++ b/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/SphericalCoordinates.java @@ -55,7 +55,7 @@ public class SphericalCoordinates implements Serializable { private static final long serialVersionUID = 20130206L; /** Cartesian coordinates. */ - private final Vector3D v; + private final Coordinates3D v; /** Radius. */ private final double r; @@ -81,7 +81,7 @@ public class SphericalCoordinates implements Serializable { /** Build a spherical coordinates transformer from Cartesian coordinates. * @param v Cartesian coordinates */ - public SphericalCoordinates(final Vector3D v) { + public SphericalCoordinates(final Coordinates3D v) { // Cartesian coordinates this.v = v; @@ -111,7 +111,7 @@ public class SphericalCoordinates implements Serializable { this.phi = phi; // Cartesian coordinates - this.v = new Vector3D(r * cosTheta * sinPhi, + this.v = new Coordinates3D(r * cosTheta * sinPhi, r * sinTheta * sinPhi, r * cosPhi); @@ -120,7 +120,7 @@ public class SphericalCoordinates implements Serializable { /** Get the Cartesian coordinates. * @return Cartesian coordinates */ - public Vector3D getCartesian() { + public Coordinates3D getCartesian() { return v; } @@ -387,7 +387,7 @@ public class SphericalCoordinates implements Serializable { * @return replacement {@link SphericalCoordinates} */ private Object readResolve() { - return new SphericalCoordinates(new Vector3D(x, y, z)); + return new SphericalCoordinates(new Coordinates3D(x, y, z)); } } http://git-wip-us.apache.org/repos/asf/commons-math/blob/b815d2af/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/SubLine.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/SubLine.java b/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/SubLine.java index 61499d9..1dc0361 100644 --- a/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/SubLine.java +++ b/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/SubLine.java @@ -24,7 +24,7 @@ import org.apache.commons.math4.geometry.Point; import org.apache.commons.math4.geometry.euclidean.oned.Euclidean1D; import org.apache.commons.math4.geometry.euclidean.oned.Interval; import org.apache.commons.math4.geometry.euclidean.oned.IntervalsSet; -import org.apache.commons.math4.geometry.euclidean.oned.Vector1D; +import org.apache.commons.math4.geometry.euclidean.oned.Coordinates1D; import org.apache.commons.math4.geometry.partitioning.Region.Location; /** This class represents a subset of a {@link Line}. @@ -54,7 +54,7 @@ public class SubLine { * @exception MathIllegalArgumentException if the points are equal * @since 3.3 */ - public SubLine(final Vector3D start, final Vector3D end, final double tolerance) + public SubLine(final Coordinates3D start, final Coordinates3D end, final double tolerance) throws MathIllegalArgumentException { this(new Line(start, end, tolerance), buildIntervalSet(start, end, tolerance)); } @@ -88,8 +88,8 @@ public class SubLine { final List<Segment> segments = new ArrayList<>(list.size()); for (final Interval interval : list) { - final Vector3D start = line.toSpace((Point<Euclidean1D>) new Vector1D(interval.getInf())); - final Vector3D end = line.toSpace((Point<Euclidean1D>) new Vector1D(interval.getSup())); + final Coordinates3D start = line.toSpace((Point<Euclidean1D>) new Coordinates1D(interval.getInf())); + final Coordinates3D end = line.toSpace((Point<Euclidean1D>) new Coordinates1D(interval.getSup())); segments.add(new Segment(start, end, line)); } @@ -111,10 +111,10 @@ public class SubLine { * occurring on endpoints lead to null being returned * @return the intersection point if there is one, null if the sub-lines don't intersect */ - public Vector3D intersection(final SubLine subLine, final boolean includeEndPoints) { + public Coordinates3D intersection(final SubLine subLine, final boolean includeEndPoints) { // compute the intersection on infinite line - Vector3D v1D = line.intersection(subLine.line); + Coordinates3D v1D = line.intersection(subLine.line); if (v1D == null) { return null; } @@ -140,7 +140,7 @@ public class SubLine { * @param tolerance tolerance below which points are considered identical * @exception MathIllegalArgumentException if the points are equal */ - private static IntervalsSet buildIntervalSet(final Vector3D start, final Vector3D end, final double tolerance) + private static IntervalsSet buildIntervalSet(final Coordinates3D start, final Coordinates3D end, final double tolerance) throws MathIllegalArgumentException { final Line line = new Line(start, end, tolerance); return new IntervalsSet(line.toSubSpace((Point<Euclidean3D>) start).getX(), http://git-wip-us.apache.org/repos/asf/commons-math/blob/b815d2af/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/SubPlane.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/SubPlane.java b/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/SubPlane.java index 0c89584..bb2de1b 100644 --- a/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/SubPlane.java +++ b/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/SubPlane.java @@ -18,10 +18,10 @@ package org.apache.commons.math4.geometry.euclidean.threed; import org.apache.commons.math4.geometry.Point; import org.apache.commons.math4.geometry.euclidean.oned.Euclidean1D; -import org.apache.commons.math4.geometry.euclidean.oned.Vector1D; +import org.apache.commons.math4.geometry.euclidean.oned.Coordinates1D; import org.apache.commons.math4.geometry.euclidean.twod.Euclidean2D; import org.apache.commons.math4.geometry.euclidean.twod.PolygonsSet; -import org.apache.commons.math4.geometry.euclidean.twod.Vector2D; +import org.apache.commons.math4.geometry.euclidean.twod.Coordinates2D; import org.apache.commons.math4.geometry.partitioning.AbstractSubHyperplane; import org.apache.commons.math4.geometry.partitioning.BSPTree; import org.apache.commons.math4.geometry.partitioning.Hyperplane; @@ -76,11 +76,11 @@ public class SubPlane extends AbstractSubHyperplane<Euclidean3D, Euclidean2D> { } // the hyperplanes do intersect - Vector2D p = thisPlane.toSubSpace((Point<Euclidean3D>) inter.toSpace((Point<Euclidean1D>) Vector1D.ZERO)); - Vector2D q = thisPlane.toSubSpace((Point<Euclidean3D>) inter.toSpace((Point<Euclidean1D>) Vector1D.ONE)); - Vector3D crossP = Vector3D.crossProduct(inter.getDirection(), thisPlane.getNormal()); + Coordinates2D p = thisPlane.toSubSpace((Point<Euclidean3D>) inter.toSpace((Point<Euclidean1D>) Coordinates1D.ZERO)); + Coordinates2D q = thisPlane.toSubSpace((Point<Euclidean3D>) inter.toSpace((Point<Euclidean1D>) Coordinates1D.ONE)); + Coordinates3D crossP = Coordinates3D.crossProduct(inter.getDirection(), thisPlane.getNormal()); if (crossP.dotProduct(otherPlane.getNormal()) < 0) { - final Vector2D tmp = p; + final Coordinates2D tmp = p; p = q; q = tmp; } http://git-wip-us.apache.org/repos/asf/commons-math/blob/b815d2af/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/Vector3D.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/Vector3D.java b/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/Vector3D.java deleted file mode 100644 index 7e43245..0000000 --- a/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/Vector3D.java +++ /dev/null @@ -1,604 +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 implements vectors in a three-dimensional space. - * <p>Instance of this class are guaranteed to be immutable.</p> - * @since 1.2 - */ -public class Vector3D implements Serializable, Vector<Euclidean3D> { - - /** Null vector (coordinates: 0, 0, 0). */ - public static final Vector3D ZERO = new Vector3D(0, 0, 0); - - /** First canonical vector (coordinates: 1, 0, 0). */ - public static final Vector3D PLUS_I = new Vector3D(1, 0, 0); - - /** Opposite of the first canonical vector (coordinates: -1, 0, 0). */ - public static final Vector3D MINUS_I = new Vector3D(-1, 0, 0); - - /** Second canonical vector (coordinates: 0, 1, 0). */ - public static final Vector3D PLUS_J = new Vector3D(0, 1, 0); - - /** Opposite of the second canonical vector (coordinates: 0, -1, 0). */ - public static final Vector3D MINUS_J = new Vector3D(0, -1, 0); - - /** Third canonical vector (coordinates: 0, 0, 1). */ - public static final Vector3D PLUS_K = new Vector3D(0, 0, 1); - - /** Opposite of the third canonical vector (coordinates: 0, 0, -1). */ - public static final Vector3D MINUS_K = new Vector3D(0, 0, -1); - - // CHECKSTYLE: stop ConstantName - /** A vector with all coordinates set to NaN. */ - public static final Vector3D NaN = new Vector3D(Double.NaN, Double.NaN, Double.NaN); - // CHECKSTYLE: resume ConstantName - - /** A vector with all coordinates set to positive infinity. */ - public static final Vector3D POSITIVE_INFINITY = - new Vector3D(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY); - - /** A vector with all coordinates set to negative infinity. */ - public static final Vector3D NEGATIVE_INFINITY = - new Vector3D(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 Vector3D(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 Vector3D(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 Vector3D(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 Vector3D(double a, Vector3D 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 Vector3D(double a1, Vector3D u1, double a2, Vector3D 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 Vector3D(double a1, Vector3D u1, double a2, Vector3D u2, - double a3, Vector3D 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 Vector3D(double a1, Vector3D u1, double a2, Vector3D u2, - double a3, Vector3D u3, double a4, Vector3D 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 Vector3D 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 Vector3D add(final Vector<Euclidean3D> v) { - final Vector3D v3 = (Vector3D) v; - return new Vector3D(x + v3.x, y + v3.y, z + v3.z); - } - - /** {@inheritDoc} */ - @Override - public Vector3D add(double factor, final Vector<Euclidean3D> v) { - return new Vector3D(1, this, factor, (Vector3D) v); - } - - /** {@inheritDoc} */ - @Override - public Vector3D subtract(final Vector<Euclidean3D> v) { - final Vector3D v3 = (Vector3D) v; - return new Vector3D(x - v3.x, y - v3.y, z - v3.z); - } - - /** {@inheritDoc} */ - @Override - public Vector3D subtract(final double factor, final Vector<Euclidean3D> v) { - return new Vector3D(1, this, -factor, (Vector3D) v); - } - - /** {@inheritDoc} */ - @Override - public Vector3D 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. - * <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 Vector3D 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 Vector3D(0, inverse * z, -inverse * y); - } else if (FastMath.abs(y) <= threshold) { - double inverse = 1 / FastMath.sqrt(x * x + z * z); - return new Vector3D(-inverse * z, 0, inverse * x); - } - double inverse = 1 / FastMath.sqrt(x * x + y * y); - return new Vector3D(inverse * y, -inverse * x, 0); - - } - - /** 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 - * @return angular separation between v1 and v2 - * @exception MathArithmeticException if either vector has a null norm - */ - public static double angle(Vector3D v1, Vector3D 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 - Vector3D 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 Vector3D negate() { - return new Vector3D(-x, -y, -z); - } - - /** {@inheritDoc} */ - @Override - public Vector3D scalarMultiply(double a) { - return new Vector3D(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. - * <p> - * If all coordinates of two 3D vectors are exactly the same, and none are - * <code>Double.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) coordinates of the - * 3D vector are equal to <code>Double.NaN</code>, the 3D vector is equal to - * {@link #NaN}. - * </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 Vector3D) { - final Vector3D rhs = (Vector3D)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. - * <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 642; - } - return 643 * (164 * MathUtils.hash(x) + 3 * MathUtils.hash(y) + MathUtils.hash(z)); - } - - /** {@inheritDoc} - * <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) - */ - @Override - public double dotProduct(final Vector<Euclidean3D> v) { - final Vector3D v3 = (Vector3D) 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 Vector3D crossProduct(final Vector<Euclidean3D> v) { - final Vector3D v3 = (Vector3D) v; - return new Vector3D(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<Euclidean3D> v) { - final Vector3D v3 = (Vector3D) 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<Euclidean3D> v) { - final Vector3D v3 = (Vector3D) v; - final double dx = v3.x - x; - final double dy = v3.y - y; - final double dz = v3.z - z; - return FastMath.sqrt(dx * dx + dy * dy + dz * dz); - } - - /** {@inheritDoc} */ - @Override - public double distanceInf(Vector<Euclidean3D> v) { - final Vector3D v3 = (Vector3D) 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<Euclidean3D> v) { - final Vector3D v3 = (Vector3D) 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(Vector3D v1, Vector3D 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 Vector3D crossProduct(final Vector3D v1, final Vector3D v2) { - return v1.crossProduct(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 - * @return the distance between v1 and v2 according to the L<sub>1</sub> norm - */ - public static double distance1(Vector3D v1, Vector3D v2) { - return v1.distance1(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 - * @return the distance between v1 and v2 according to the L<sub>2</sub> norm - */ - public static double distance(Vector3D v1, Vector3D v2) { - return v1.distance(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 - * @return the distance between v1 and v2 according to the L<sub>∞</sub> norm - */ - public static double distanceInf(Vector3D v1, Vector3D v2) { - return v1.distanceInf(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 - * @return the square of the distance between v1 and v2 - */ - public static double distanceSq(Vector3D v1, Vector3D 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/b815d2af/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/Vector3DFormat.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/Vector3DFormat.java b/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/Vector3DFormat.java index e6033ae..fd6cce9 100644 --- a/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/Vector3DFormat.java +++ b/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/Vector3DFormat.java @@ -104,7 +104,7 @@ public class Vector3DFormat extends VectorFormat<Euclidean3D> { } /** - * Formats a {@link Vector3D} object to produce a string. + * Formats a {@link Coordinates3D} object to produce a string. * @param vector the object to format. * @param toAppendTo where the text is to be appended * @param pos On input: an alignment field, if desired. On output: the @@ -114,42 +114,42 @@ public class Vector3DFormat extends VectorFormat<Euclidean3D> { @Override public StringBuffer format(final Vector<Euclidean3D> vector, final StringBuffer toAppendTo, final FieldPosition pos) { - final Vector3D v3 = (Vector3D) vector; + final Coordinates3D v3 = (Coordinates3D) vector; return format(toAppendTo, pos, v3.getX(), v3.getY(), v3.getZ()); } /** - * Parses a string to produce a {@link Vector3D} object. + * Parses a string to produce a {@link Coordinates3D} object. * @param source the string to parse - * @return the parsed {@link Vector3D} object. + * @return the parsed {@link Coordinates3D} object. * @throws MathParseException if the beginning of the specified string * cannot be parsed. */ @Override - public Vector3D parse(final String source) throws MathParseException { + public Coordinates3D parse(final String source) throws MathParseException { ParsePosition parsePosition = new ParsePosition(0); - Vector3D result = parse(source, parsePosition); + Coordinates3D result = parse(source, parsePosition); if (parsePosition.getIndex() == 0) { throw new MathParseException(source, parsePosition.getErrorIndex(), - Vector3D.class); + Coordinates3D.class); } return result; } /** - * Parses a string to produce a {@link Vector3D} object. + * Parses a string to produce a {@link Coordinates3D} object. * @param source the string to parse * @param pos input/ouput parsing parameter. - * @return the parsed {@link Vector3D} object. + * @return the parsed {@link Coordinates3D} object. */ @Override - public Vector3D parse(final String source, final ParsePosition pos) { + public Coordinates3D parse(final String source, final ParsePosition pos) { final double[] coordinates = parseCoordinates(3, source, pos); if (coordinates == null) { return null; } - return new Vector3D(coordinates[0], coordinates[1], coordinates[2]); + return new Coordinates3D(coordinates[0], coordinates[1], coordinates[2]); } } http://git-wip-us.apache.org/repos/asf/commons-math/blob/b815d2af/src/main/java/org/apache/commons/math4/geometry/euclidean/twod/Coordinates2D.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/geometry/euclidean/twod/Coordinates2D.java b/src/main/java/org/apache/commons/math4/geometry/euclidean/twod/Coordinates2D.java new file mode 100644 index 0000000..e68342e --- /dev/null +++ b/src/main/java/org/apache/commons/math4/geometry/euclidean/twod/Coordinates2D.java @@ -0,0 +1,492 @@ +/* + * 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.twod; + +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 a 2D point or a 2D vector. + * <p>An instance of Coordinates2D represents the point with the corresponding + * coordinates.</p> + * <p>An instance of Coordinates2D also represents the vector which begins at + * the origin and ends at the point corresponding to the coordinates.</p> + * <p>Instances of this class are guaranteed to be immutable.</p> + * @since 4.0 + */ +public class Coordinates2D implements Point<Euclidean2D>, Vector<Euclidean2D> { + + /** Origin (coordinates: 0, 0). */ + public static final Coordinates2D ZERO = new Coordinates2D(0, 0); + + // CHECKSTYLE: stop ConstantName + /** A vector with all coordinates set to NaN. */ + public static final Coordinates2D NaN = new Coordinates2D(Double.NaN, Double.NaN); + // CHECKSTYLE: resume ConstantName + + /** A vector with all coordinates set to positive infinity. */ + public static final Coordinates2D POSITIVE_INFINITY = + new Coordinates2D(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY); + + /** A vector with all coordinates set to negative infinity. */ + public static final Coordinates2D NEGATIVE_INFINITY = + new Coordinates2D(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY); + + /** Serializable UID. */ + private static final long serialVersionUID = 266938651998679754L; + + /** Abscissa. */ + private final double x; + + /** Ordinate. */ + private final double y; + + /** Simple constructor. + * Build a vector from its coordinates + * @param x abscissa + * @param y ordinate + * @see #getX() + * @see #getY() + */ + public Coordinates2D(double x, double y) { + this.x = x; + this.y = y; + } + + /** Simple constructor. + * Build a vector from its coordinates + * @param v coordinates array + * @exception DimensionMismatchException if array does not have 2 elements + * @see #toArray() + */ + public Coordinates2D(double[] v) throws DimensionMismatchException { + if (v.length != 2) { + throw new DimensionMismatchException(v.length, 2); + } + this.x = v[0]; + this.y = v[1]; + } + + /** 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 Coordinates2D(double a, Coordinates2D u) { + this.x = a * u.x; + this.y = a * u.y; + } + + /** 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 Coordinates2D(double a1, Coordinates2D u1, double a2, Coordinates2D u2) { + this.x = a1 * u1.x + a2 * u2.x; + this.y = a1 * u1.y + a2 * u2.y; + } + + /** 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 Coordinates2D(double a1, Coordinates2D u1, double a2, Coordinates2D u2, + double a3, Coordinates2D u3) { + this.x = a1 * u1.x + a2 * u2.x + a3 * u3.x; + this.y = a1 * u1.y + a2 * u2.y + a3 * u3.y; + } + + /** 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 Coordinates2D(double a1, Coordinates2D u1, double a2, Coordinates2D u2, + double a3, Coordinates2D u3, double a4, Coordinates2D u4) { + this.x = a1 * u1.x + a2 * u2.x + a3 * u3.x + a4 * u4.x; + this.y = a1 * u1.y + a2 * u2.y + a3 * u3.y + a4 * u4.y; + } + + /** Get the abscissa of the vector. + * @return abscissa of the vector + * @see #Vector2D(double, double) + */ + public double getX() { + return x; + } + + /** Get the ordinate of the vector. + * @return ordinate of the vector + * @see #Vector2D(double, double) + */ + public double getY() { + return y; + } + + /** Get the vector coordinates as a dimension 2 array. + * @return vector coordinates + * @see #Vector2D(double[]) + */ + public double[] toArray() { + return new double[] { x, y }; + } + + /** {@inheritDoc} */ + @Override + public Space getSpace() { + return Euclidean2D.getInstance(); + } + + /** {@inheritDoc} */ + @Override + public Coordinates2D getZero() { + return ZERO; + } + + /** {@inheritDoc} */ + @Override + public double getNorm1() { + return FastMath.abs(x) + FastMath.abs(y); + } + + /** {@inheritDoc} */ + @Override + public double getNorm() { + return FastMath.sqrt (x * x + y * y); + } + + /** {@inheritDoc} */ + @Override + public double getNormSq() { + return x * x + y * y; + } + + /** {@inheritDoc} */ + @Override + public double getNormInf() { + return FastMath.max(FastMath.abs(x), FastMath.abs(y)); + } + + /** {@inheritDoc} */ + @Override + public Coordinates2D add(Vector<Euclidean2D> v) { + Coordinates2D v2 = (Coordinates2D) v; + return new Coordinates2D(x + v2.getX(), y + v2.getY()); + } + + /** {@inheritDoc} */ + @Override + public Coordinates2D add(double factor, Vector<Euclidean2D> v) { + Coordinates2D v2 = (Coordinates2D) v; + return new Coordinates2D(x + factor * v2.getX(), y + factor * v2.getY()); + } + + /** {@inheritDoc} */ + @Override + public Coordinates2D subtract(Vector<Euclidean2D> p) { + Coordinates2D p3 = (Coordinates2D) p; + return new Coordinates2D(x - p3.x, y - p3.y); + } + + /** {@inheritDoc} */ + @Override + public Coordinates2D subtract(double factor, Vector<Euclidean2D> v) { + Coordinates2D v2 = (Coordinates2D) v; + return new Coordinates2D(x - factor * v2.getX(), y - factor * v2.getY()); + } + + /** {@inheritDoc} */ + @Override + public Coordinates2D normalize() throws MathArithmeticException { + double s = getNorm(); + if (s == 0) { + throw new MathArithmeticException(LocalizedFormats.CANNOT_NORMALIZE_A_ZERO_NORM_VECTOR); + } + return scalarMultiply(1 / s); + } + + /** 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 + * @return angular separation between v1 and v2 + * @exception MathArithmeticException if either vector has a null norm + */ + public static double angle(Coordinates2D v1, Coordinates2D 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 + final double n = FastMath.abs(MathArrays.linearCombination(v1.x, v2.y, -v1.y, v2.x)); + if (dot >= 0) { + return FastMath.asin(n / normProduct); + } + return FastMath.PI - FastMath.asin(n / normProduct); + } + + // the vectors are sufficiently separated to use the cosine + return FastMath.acos(dot / normProduct); + + } + + /** {@inheritDoc} */ + @Override + public Coordinates2D negate() { + return new Coordinates2D(-x, -y); + } + + /** {@inheritDoc} */ + @Override + public Coordinates2D scalarMultiply(double a) { + return new Coordinates2D(a * x, a * y); + } + + /** {@inheritDoc} */ + @Override + public boolean isNaN() { + return Double.isNaN(x) || Double.isNaN(y); + } + + /** {@inheritDoc} */ + @Override + public boolean isInfinite() { + return !isNaN() && (Double.isInfinite(x) || Double.isInfinite(y)); + } + + /** {@inheritDoc} */ + @Override + public double distance1(Vector<Euclidean2D> p) { + Coordinates2D p3 = (Coordinates2D) p; + final double dx = FastMath.abs(p3.x - x); + final double dy = FastMath.abs(p3.y - y); + return dx + dy; + } + + /** {@inheritDoc} */ + @Override + public double distance(Point<Euclidean2D> p) { + return distance((Coordinates2D) p); + } + + /** {@inheritDoc} */ + @Override + public double distance(Vector<Euclidean2D> v) { + return distance((Coordinates2D) 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(Coordinates2D c) { + final double dx = c.x - x; + final double dy = c.y - y; + return FastMath.sqrt(dx * dx + dy * dy); + } + + /** {@inheritDoc} */ + @Override + public double distanceInf(Vector<Euclidean2D> p) { + Coordinates2D p3 = (Coordinates2D) p; + final double dx = FastMath.abs(p3.x - x); + final double dy = FastMath.abs(p3.y - y); + return FastMath.max(dx, dy); + } + + /** {@inheritDoc} */ + @Override + public double distanceSq(Vector<Euclidean2D> p) { + Coordinates2D p3 = (Coordinates2D) p; + final double dx = p3.x - x; + final double dy = p3.y - y; + return dx * dx + dy * dy; + } + + /** {@inheritDoc} */ + @Override + public double dotProduct(final Vector<Euclidean2D> v) { + final Coordinates2D v2 = (Coordinates2D) v; + return MathArrays.linearCombination(x, v2.x, y, v2.y); + } + + /** + * Compute the cross-product of the instance and the given points. + * <p> + * The cross product can be used to determine the location of a point + * with regard to the line formed by (p1, p2) and is calculated as: + * \[ + * P = (x_2 - x_1)(y_3 - y_1) - (y_2 - y_1)(x_3 - x_1) + * \] + * with \(p3 = (x_3, y_3)\) being this instance. + * <p> + * If the result is 0, the points are collinear, i.e. lie on a single straight line L; + * if it is positive, this point lies to the left, otherwise to the right of the line + * formed by (p1, p2). + * + * @param p1 first point of the line + * @param p2 second point of the line + * @return the cross-product + * + * @see <a href="http://en.wikipedia.org/wiki/Cross_product">Cross product (Wikipedia)</a> + */ + public double crossProduct(final Coordinates2D p1, final Coordinates2D p2) { + final double x1 = p2.getX() - p1.getX(); + final double y1 = getY() - p1.getY(); + final double x2 = getX() - p1.getX(); + final double y2 = p2.getY() - p1.getY(); + return MathArrays.linearCombination(x1, y1, -x2, y2); + } + + /** Compute the distance between two vectors according to the L<sub>2</sub> norm. + * <p>Calling this method is equivalent to calling: + * <code>p1.subtract(p2).getNorm()</code> except that no intermediate + * vector is built</p> + * @param p1 first vector + * @param p2 second vector + * @return the distance between p1 and p2 according to the L<sub>2</sub> norm + */ + public static double distance(Coordinates2D p1, Coordinates2D p2) { + return p1.distance(p2); + } + + /** Compute the distance between two vectors according to the L<sub>∞</sub> norm. + * <p>Calling this method is equivalent to calling: + * <code>p1.subtract(p2).getNormInf()</code> except that no intermediate + * vector is built</p> + * @param p1 first vector + * @param p2 second vector + * @return the distance between p1 and p2 according to the L<sub>∞</sub> norm + */ + public static double distanceInf(Coordinates2D p1, Coordinates2D p2) { + return p1.distanceInf(p2); + } + + /** Compute the square of the distance between two vectors. + * <p>Calling this method is equivalent to calling: + * <code>p1.subtract(p2).getNormSq()</code> except that no intermediate + * vector is built</p> + * @param p1 first vector + * @param p2 second vector + * @return the square of the distance between p1 and p2 + */ + public static double distanceSq(Coordinates2D p1, Coordinates2D p2) { + return p1.distanceSq(p2); + } + + /** + * Test for the equality of two 2D vectors. + * <p> + * If all coordinates of two 2D vectors are exactly the same, and none are + * <code>Double.NaN</code>, the two 2D 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) coordinates of the + * 2D vector are equal to <code>Double.NaN</code>, the 2D vector is equal to + * {@link #NaN}. + * </p> + * + * @param other Object to test for equality to this + * @return true if two 2D vector objects are equal, false if + * object is null, not an instance of Vector2D, or + * not equal to this Vector2D instance + * + */ + @Override + public boolean equals(Object other) { + + if (this == other) { + return true; + } + + if (other instanceof Coordinates2D) { + final Coordinates2D rhs = (Coordinates2D)other; + if (rhs.isNaN()) { + return this.isNaN(); + } + + return (x == rhs.x) && (y == rhs.y); + } + return false; + } + + /** + * Get a hashCode for the 2D 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 542; + } + return 122 * (76 * MathUtils.hash(x) + MathUtils.hash(y)); + } + + /** Get a string representation of this vector. + * @return a string representation of this vector + */ + @Override + public String toString() { + return Vector2DFormat.getInstance().format(this); + } + + /** {@inheritDoc} */ + @Override + public String toString(final NumberFormat format) { + return new Vector2DFormat(format).format(this); + } + +}