/* * $Id$ * * Copyright (C) 2010-2012 Stephane GALLAND. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * This program is free software; you can redistribute it and/or modify */ package org.arakhne.afc.math.geometry.d3.continuous; import org.arakhne.afc.math.geometry.d3.FunctionalVector3D; import org.arakhne.afc.math.geometry.d3.Tuple3D; import org.arakhne.afc.math.geometry.d3.Vector3D; import org.eclipse.xtext.xbase.lib.Pure; /** 3D Vector with 3 floating-point values. * * @author $Author: sgalland$ * @version $FullVersion$ * @mavengroupid $GroupId$ * @mavenartifactid $ArtifactId$ */ public class Vector3f extends Tuple3f<Vector3D> implements FunctionalVector3D { private static final long serialVersionUID = -1222875298451525734L; // /** Compute the determinant of three vectors. // * // * @param x1 // * @param y1 // * @param z1 // * @param x2 // * @param y2 // * @param z2 // * @param x3 // * @param y3 // * @param z3 // * @return the determinant // * @see #perpProduct(double, double, double, double, double, double) // */ // public static double determinant( // double x1, double y1, double z1, // double x2, double y2, double z2, // double x3, double y3, double z3) { // return // x1 * (y2 * z3 - y3 * z2) // + x2 * (y3 * z1 - y1 * z3) // + x3 * (y1 * z2 - y2 * z1); // } // // /** Compute the determinant of two vectors. // * <p> // * <pre><code>det(X1,X2) = |X1|.|X2|.sin(a)</code></pre> // * where <code>X1</code> and <code>X2</code> are two vectors // * and <code>a</code> is the angle between <code>X1</code> // * and <code>X2</code>. // * // * @param x1 // * @param y1 // * @param z1 // * @param x2 // * @param y2 // * @param z2 // * @return the determinant // * @see #determinant(double, double, double, double, double, double, double, double, double) // */ // public static double perpProduct(double x1, double y1, double z1, double x2, double y2, double z2) { // /* First method: // * // * det(A,B) = |A|.|B|.sin(theta) // * A x B = |A|.|B|.sin(theta).N, where N is the unit vector // * A x B = det(A,B).N // * A x B = [ y1*z2 - z1*y2 ] = det(A,B).N // * [ z1*x2 - x1*z2 ] // * [ x1*y2 - y1*x2 ] // * det(A,B) = sum(A x B) // * // * Second method: // * // * det(A,B) = det( [ x1 x2 1 ] // * [ y1 y2 1 ] // * [ z1 z2 1 ] ) // * det(A,B) = x1*y2*1 + y1*z2*1 + z1*x2*1 - 1*y2*z1 - 1*z2*x1 - 1*x2*y1 // */ // return x1*y2 + y1*z2 + z1*x2 - y2*z1 - z2*x1 - x2*y1; // } // // /** // * Replies if two vectors are colinear. // * <p> // * This function uses the equal-to-zero test with the error {@link MathConstants#EPSILON}. // * // * @param x1 // * is the X coordinate of the first vector // * @param y1 // * is the Y coordinate of the first vector // * @param z1 // * is the Z coordinate of the first vector // * @param x2 // * is the X coordinate of the second vector // * @param y2 // * is the Y coordinate of the second vector // * @param z2 // * is the Z coordinate of the second vector // * @return <code>true</code> if the two given vectors are colinear. // * @since 3.0 // * @see MathUtil#isEpsilonZero(double) // */ // public static boolean isCollinearVectors(double x1, double y1, double z1, double x2, double y2, double z2) { // // Cross product // double cx = y1 * z2 - z1 * y2; // double cy = z1 * x2 - x1 * z2; // double cz = x1 * y2 - y1 * x2; // // double sum = cx * cx + cy * cy + cz * cz; // // return MathUtil.isEpsilonZero(sum); // } // // /** // * Compute the dot product of two 3D vectors. // * // * @param x1 // * @param y1 // * @param z1 // * @param x2 // * @param y2 // * @param z2 // * @return the dot product. // */ // public static double dotProduct(double x1, double y1, double z1, double x2, // double y2, double z2) { // return x1 * x2 + y1 * y2 + z1 * z2; // } // // /** // * Computes the cross product of the vectors v1 and v2. // * This function uses the // * {@link #crossProductLeftHand(double, double, double, double, double, double, Vector3D) left-handed cross product} // * if the default coordinate system is left-handed. Otherwise, it uses the // * {@link #crossProductRightHand(double, double, double, double, double, double, Vector3D) right-handed cross product}. // * The default coordinate system is given by // * {@link CoordinateSystem3D#getDefaultCoordinateSystem()}. // * // * <img src="doc-files/left_handed_cross_product.png" alt="[Left-Handed Cross Product]"> // * <img src="doc-files/left_handed_cross_product.png" alt="[Right-Handed Cross Product]"> // * // * @param x1 x coordinate of the vector v1. // * @param y1 y coordinate of the vector v1. // * @param z1 z coordinate of the vector v1. // * @param x2 x coordinate of the vector v2. // * @param y2 y coordinate of the vector v2. // * @param z2 z coordinate of the vector v2. // * @param result is the result of the cross product. // */ // public static void crossProduct( // double x1, double y1, double z1, // double x2, double y2, double z2, Vector3D result) { // crossProduct(x1, y1, z1, x2, y2, z2, // CoordinateSystem3D.getDefaultCoordinateSystem(), result); // } // // /** // * Computes the cross product of the vectors v1 and v2. // * This function uses the // * {@link #crossProductLeftHand(double, double, double, double, double, double, Vector3D) left-handed cross product} // * if the given coordinate system is left-handed. Otherwise, it uses the // * {@link #crossProductRightHand(double, double, double, double, double, double, Vector3D) right-handed cross product}. // * // * <img src="doc-files/left_handed_cross_product.png" alt="[Left-Handed Cross Product]"> // * <img src="doc-files/left_handed_cross_product.png" alt="[Right-Handed Cross Product]"> // * // * @param x1 x coordinate of the vector v1. // * @param y1 y coordinate of the vector v1. // * @param z1 z coordinate of the vector v1. // * @param x2 x coordinate of the vector v2. // * @param y2 y coordinate of the vector v2. // * @param z2 z coordinate of the vector v2. // * @param system the coordinate system to consider for computing the cross product. // * @param result is the result of the cross product. // */ // public static void crossProduct( // double x1, double y1, double z1, // double x2, double y2, double z2, // CoordinateSystem3D system, Vector3D result) { // if (system.isLeftHanded()) { // crossProductLeftHand( // x1, y1, z1, // x2, y2, z2, // result); // } // else { // crossProductRightHand( // x1, y1, z1, // x2, y2, z2, // result); // } // } // // /** // * Computes the cross product of the vectors v1 and v2 // * as if the vectors are inside a left-hand coordinate system; // * // * <img src="doc-files/left_handed_cross_product.png"> // * // * @param x1 x coordinate of the vector v1. // * @param y1 y coordinate of the vector v1. // * @param z1 z coordinate of the vector v1. // * @param x2 x coordinate of the vector v2. // * @param y2 y coordinate of the vector v2. // * @param z2 z coordinate of the vector v2. // * @param result is the result of the cross product. // */ // public static void crossProductLeftHand( // double x1, double y1, double z1, // double x2, double y2, double z2, Vector3D result) { // double x = y2*z1 - z2*y1; // double y = z2*x1 - x2*z1; // double z = x2*y1 - y2*x1; // result.set(x, y, z); // } // // /** // * Computes the cross product of the vectors v1 and v2 // * as if the vectors are inside a right-hand coordinate system; // * // * <img src="doc-files/right_handed_cross_product.png"> // * // * @param x1 x coordinate of the vector v1. // * @param y1 y coordinate of the vector v1. // * @param z1 z coordinate of the vector v1. // * @param x2 x coordinate of the vector v2. // * @param y2 y coordinate of the vector v2. // * @param z2 z coordinate of the vector v2. // * @param result is the result of the cross product. // */ // public static void crossProductRightHand( // double x1, double y1, double z1, // double x2, double y2, double z2, Vector3D result) { // double x = y1*z2 - z1*y2; // double y = z1*x2 - x1*z2; // double z = x1*y2 - y1*x2; // result.set(x,y,z); // } // // /** // * Compute the signed angle between two vectors. // * // * @param x1 // * @param y1 // * @param z1 // * @param x2 // * @param y2 // * @param z2 // * @return the angle between <code>-PI</code> and <code>PI</code>. // */ // public static double signedAngle(double x1, double y1, double z1, double x2, double y2, double z2) { // double lengths = Math.sqrt(x1 * x1 + y1 * y1 + z1 * z1) * Math.sqrt(x2 * x2 + y2 * y2 + z2 * z2); // if (lengths == 0.) // return Double.NaN; // // // First method // // Angle // // A . B = |A|.|B|.cos(theta) // double dot = dotProduct(x1, y1, z1, x2, y2, z2) / lengths; // if (dot < -1.0) // dot = -1.0; // if (dot > 1.0) // dot = 1.0; // double angle = Math.acos(dot); // // // On which side of A, B is located? // if ((dot > -1) && (dot < 1)) { // // det(A,B) = |A|.|B|.sin(theta) // dot = perpProduct(x1, y1, z1, x2, y2, z2) / lengths; // if (dot < 0) // angle = -angle; // } // // return angle; // } /** */ public Vector3f() { // } /** * @param tuple is the tuple to copy. */ public Vector3f(Tuple3D<?> tuple) { super(tuple); } /** * @param tuple is the tuple to copy. */ public Vector3f(int[] tuple) { super(tuple); } /** * @param tuple is the tuple to copy. */ public Vector3f(double[] tuple) { super(tuple); } /** * @param x * @param y * @param z */ public Vector3f(int x1, int y1, int z1) { super(x1,y1,z1); } /** * @param x * @param y * @param z */ public Vector3f(float x1, float y1, float z1) { super(x1,y1,z1); } /** * @param x * @param y * @param z */ public Vector3f(double x1, double y1, double z1) { super(x1,y1,z1); } /** * @param x * @param y * @param z */ public Vector3f(long x1, long y1, long z1) { super(x1,y1,z1); } /** {@inheritDoc} */ @Pure @Override public Vector3f clone() { return (Vector3f)super.clone(); } // /** // * {@inheritDoc} // */ // @Override // public double angle(Vector3D v1) { // double vDot = dot(v1) / ( length()*v1.length() ); // if( vDot < -1.) vDot = -1.; // if( vDot > 1.) vDot = 1.; // return ((Math.acos( vDot ))); // } // // /** // * {@inheritDoc} // */ // public double signedAngle(Vector3D v1) { // return signedAngle(this.getX(), this.getY(), this.getZ(), v1.getX(), v1.getY(), v1.getZ()); // } // // /** // * {@inheritDoc} // */ // @Override // public double dot(Vector3D v1) { // return dotProduct(this.x,this.y,this.z,v1.getX(),v1.getY(),v1.getZ()); // } // // /** // * Multiply this vector, transposed, by the given matrix and replies the resulting vector. // * // * @param m // * @return transpose(this * m) // */ // public final Vector3f mul(Matrix3f m) { // Vector3f r = new Vector3f(); // r.x = this.getX() * m.m00 + this.getY() * m.m01 + this.getZ() * m.m02; // r.y = this.getX() * m.m10 + this.getY() * m.m11 + this.getZ() * m.m12; // r.z = this.getX() * m.m20 + this.getY() * m.m21 + this.getZ() * m.m22; // return r; // } // // /** {@inheritDoc} // * // * @see #determinant(double, double, double, double, double, double, double, double, double) // */ // @Override // public double perp(Vector3D v) { // return perpProduct(this.x, this.y, this.z, v.getX(), v.getY(), v.getZ()); // } // // @Override // public Vector3D cross(Vector3D v1) { // Vector3f v = new Vector3f(); // crossProduct( // getX(), getY(), getZ(), // v1.getX(), v1.getY(), v1.getZ(), // v); // return v; // } // // @Override // public void cross(Vector3D v1, Vector3D v2) { // crossProduct( // v1.getX(), v1.getY(), v1.getZ(), // v2.getX(), v2.getY(), v2.getZ(), // this); // } // // @Override // public Vector3D crossLeftHand(Vector3D v1) { // Vector3f v = new Vector3f(); // crossProductLeftHand( // this.getX(), this.getY(), this.getZ(), // v1.getX(), v1.getY(), v1.getZ(), // v); // return v; // } // // @Override // public void crossLeftHand(Vector3D v1, Vector3D v2) { // crossProductLeftHand( // v1.getX(), v1.getY(), v1.getZ(), // v2.getX(), v2.getY(), v2.getZ(), // this); // } // // @Override // public Vector3D crossRightHand(Vector3D v1) { // Vector3f v = new Vector3f(); // crossProductRightHand( // this.getX(), this.getY(), this.getZ(), // v1.getX(), v1.getY(), v1.getZ(), // v); // return v; // } // // @Override // public void crossRightHand(Vector3D v1, Vector3D v2) { // crossProductRightHand( // v1.getX(), v1.getY(), v1.getZ(), // v2.getX(), v2.getY(), v2.getZ(), // this); // } // // /** // * {@inheritDoc} // */ // @Override // public double length() { // return Math.sqrt(this.x*this.x + this.y*this.y + this.z*this.z); // } // // /** // * {@inheritDoc} // */ // @Override // public double lengthSquared() { // return (this.x*this.x + this.y*this.y + this.z*this.z); // } // // /** // * {@inheritDoc} // */ // @Override // public void normalize(Vector3D v1) { // if(v1.length()==0){ // throw new ArithmeticException(); // } // else { // double norm = 1f / v1.length(); // this.x = (int)(v1.getX()*norm); // this.y = (int)(v1.getY()*norm); // this.z = (int)(v1.getZ()*norm); // } // } // // /** // * {@inheritDoc} // */ // @Override // public void normalize() { // double norm; // double length = this.length(); // // if(length==0){ // throw new ArithmeticException(); // } // else { // norm = 1./Math.sqrt(this.x*this.x + this.y*this.y + this.z*this.z); // this.x *= norm; // this.y *= norm; // this.z *= norm; // } // } // // /** // * Unstable function, sometimes works, and sometimes not // */ // @Override // public void turnVector(Vector3D axis, double angle) { // Transform3D mat = new Transform3D(); // mat.setRotation(new Quaternion(axis, angle)); // mat.transform(this); // } // // /** // * {@inheritDoc} // */ // @Override // public void add(Vector3D t1, Vector3D t2) { // this.x = t1.getX() + t2.getX(); // this.y = t1.getY() + t2.getY(); // this.z = t1.getZ() + t2.getZ(); // } // // /** // * {@inheritDoc} // */ // @Override // public void add(Vector3D t1) { // this.x += t1.getX(); // this.y += t1.getY(); // this.z += t1.getZ(); // } // // /** // * {@inheritDoc} // */ // @Override // public void scaleAdd(int s, Vector3D t1, Vector3D t2) { // this.x = s * t1.getX() + t2.getX(); // this.y = s * t1.getY() + t2.getY(); // this.z = s * t1.getZ() + t2.getZ(); // } // // /** // * {@inheritDoc} // */ // @Override // public void scaleAdd(double s, Vector3D t1, Vector3D t2) { // this.x = s * t1.getX() + t2.getX(); // this.y = s * t1.getY() + t2.getY(); // this.z = s * t1.getZ() + t2.getZ(); // } // // /** // * {@inheritDoc} // */ // @Override // public void scaleAdd(int s, Vector3D t1) { // this.x = s * this.x + t1.getX(); // this.y = s * this.y + t1.getY(); // this.z = s * this.z + t1.getZ(); // } // // /** // * {@inheritDoc} // */ // @Override // public void scaleAdd(double s, Vector3D t1) { // this.x = s * this.x + t1.getX(); // this.y = s * this.y + t1.getY(); // this.z = s * this.z + t1.getZ(); // } // // /** // * {@inheritDoc} // */ // @Override // public void sub(Vector3D t1, Vector3D t2) { // this.x = t1.getX() - t2.getX(); // this.y = t1.getY() - t2.getY(); // this.z = t1.getZ() - t2.getZ(); // } // // @Override // public void sub(Point3D t1, Point3D t2) { // this.x = t1.getX() - t2.getX(); // this.y = t1.getY() - t2.getY(); // this.z = t1.getZ() - t2.getZ(); // } // // /** // * {@inheritDoc} // */ // @Override // public void sub(Vector3D t1) { // this.x -= t1.getX(); // this.y -= t1.getY(); // this.z -= t1.getZ(); // } // // @Override // public boolean isUnitVector() { // return MathUtil.isEpsilonEqual(length(), 1.); // } // // @Override // public boolean isColinear(Vector3D v) { // return isCollinearVectors(getX(), getY(), getZ(), v.getX(), v.getY(), v.getZ()); // } // // // @Override // public void setLength(double newLength) { // double nl = Math.max(0, newLength); // double l = length(); // if (l != 0) { // double f = nl / l; // this.x *= f; // this.y *= f; // this.z *= f; // } else { // this.x = newLength; // this.y = 0; // this.z = 0; // } // } @Pure @Override public Vector3D toUnmodifiable() { return new UnmodifiableVector3f(); } /** * @author $Author: sgalland$ * @version $Name$ $Revision$ $Date$ * @mavengroupid $GroupId$ * @mavenartifactid $ArtifactId$ */ private class UnmodifiableVector3f implements FunctionalVector3D.UnmodifiableVector3D { private static final long serialVersionUID = 6113750458070037483L; public UnmodifiableVector3f() { // } @Pure @Override public Vector3D clone() { try { return (Vector3D) super.clone(); } catch (CloneNotSupportedException e) { throw new Error(e); } } @Override public void get(Vector3D t) { Vector3f.this.get(t); } @Override public void get(int[] t) { Vector3f.this.get(t); } @Override public void get(double[] t) { Vector3f.this.get(t); } @Pure @Override public double getX() { return Vector3f.this.getX(); } @Pure @Override public int ix() { return Vector3f.this.ix(); } @Pure @Override public double getY() { return Vector3f.this.getY(); } @Pure @Override public int iy() { return Vector3f.this.iy(); } @Pure @Override public double getZ() { return Vector3f.this.getZ(); } @Pure @Override public int iz() { return Vector3f.this.iz(); } @Pure @Override public boolean equals(Tuple3D<?> t1) { return Vector3f.this.equals(t1); } @Pure @Override public int hashCode() { return Vector3f.this.hashCode(); } @Pure @Override public boolean epsilonEquals(Vector3D t1, double epsilon) { return Vector3f.this.epsilonEquals(t1, epsilon); } @Pure @Override public double dot(Vector3D v1) { return Vector3f.this.dot(v1); } @Pure @Override public Vector3D cross(Vector3D v1) { return Vector3f.this.cross(v1); } @Pure @Override public Vector3D crossLeftHand(Vector3D v1) { return Vector3f.this.crossLeftHand(v1); } @Pure @Override public Vector3D crossRightHand(Vector3D v1) { return Vector3f.this.crossRightHand(v1); } @Pure @Override public double length() { return Vector3f.this.length(); } @Pure @Override public double lengthSquared() { return Vector3f.this.lengthSquared(); } @Pure @Override public double angle(Vector3D v1) { return Vector3f.this.angle(v1); } @Pure @Override public boolean isUnitVector() { return Vector3f.this.isUnitVector(); } @Pure @Override public boolean isColinear(Vector3D v) { return Vector3f.this.isColinear(v); } @Pure @Override public Vector3D toUnmodifiable() { return this; } @Pure @Override public double perp(Vector3D v) { return Vector3f.this.perp(v); } } }