/* * Runtime Math - Java 3D math classes * Copyright (C) 2009 Kostas Michalopoulos * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. * * Kostas Michalopoulos <badsector@runtimelegend.com> */package com.runtimeterror.math.algebra;/** * A vector in 3D space. * * @author Bad Sector */public class Vector3D{ /** Zero */ public static final int ZERO = 0; /** X axis */ public static final int X_AXIS = 1; /** Y axis */ public static final int Y_AXIS = 2; /** Z axis */ public static final int Z_AXIS = 3; /** The vector's x component */ public double x; /** The vector's y component */ public double y; /** The vector's z component */ public double z; /** * Construct a zero vector. */ public Vector3D() { } /** * Construct a vector with all components set to v. * * @param v the value for the vector's components */ public Vector3D(double v) { x = y = z = v; } /** * Construct a clone of the given vector. * * @param v the source vector */ public Vector3D(Vector3D v) { x = v.x; y = v.y; z = v.z; } /** * Construct a vector using the given coordinates. * * @param x the x component * @param y the y component * @param z the z component */ public Vector3D(double x, double y, double z) { this.x = x; this.y = y; this.z = z; } /** * Construct a vector using the first 3 values of the given array. * * @param values the values array. */ public Vector3D(double[] values) { x = values[0]; y = values[1]; z = values[2]; } /** * Zero the vector. */ public void zero() { x = y = z = 0.0; } /** * Set the vector's components to the given value. * * @param v the value to use */ public void set(double v) { x = y = z = v; } /** * Set the vector's component to the components of the given vector. * * @param v the source vector */ public void set(Vector3D v) { x = v.x; y = v.y; z = v.z; } /** * Set the vector's components to the given coordinates. * * @param x the x component * @param y the y component * @param z the z component */ public void set(double x, double y, double z) { this.x = x; this.y = y; this.z = z; } /** * Set the vector's components to the first 3 values of the given array. * * @param values the values array. */ public void set(double[] values) { x = values[0]; y = values[1]; z = values[2]; } /** * Add the given vector to this vector. * * @param v the vector to add */ public void add(Vector3D v) { x += v.x; y += v.y; z += v.z; } /** * Add the vector v to this vector and store the result in vector r. * * @param r the vector to store the result in * @param v the vector to add */ public void addTo(Vector3D r, Vector3D v) { r.x = x + v.x; r.y = y + v.y; r.z = z + v.z; } /** * Create a clone of this vector with the given vector added to it. * * @param v the vector to add * @return the new vector */ public Vector3D added(Vector3D v) { return new Vector3D(x + v.x, y + v.y, z + v.z); } /** * Add the given coordinates to this vector's components. * * @param vx the x coordinate * @param vy the y coordinate * @param vz the z coordinate */ public void add(double vx, double vy, double vz) { x += vx; y += vy; z += vz; } /** * Add the given coordinates to this vector's components and store the * result in r. * * @param r the vector to store the result of the addition into * @param vx the x coordinate * @param vy the y coordinate * @param vz the z coordinate */ public void addTo(Vector3D r, double vx, double vy, double vz) { r.x = x + vx; r.y = y + vy; r.z = z + vz; } /** * Create a clone of this vector with the given coordinates added to its * components. * * @param vx the x coordinate * @param vy the y coordinate * @param vz the z coordinate * @return the new vector */ public Vector3D added(double vx, double vy, double vz) { return new Vector3D(x + vx, y + vy, z + vz); } /** * Subtract the given vector from this vector. * * @param v the vector to subtract */ public void sub(Vector3D v) { x -= v.x; y -= v.y; z -= v.z; } /** * Subtract the vector v from this vector and store the result in the * vector r. * * @param r the vector to store the subtraction result into * @param v the vector to subtract */ public void subTo(Vector3D r, Vector3D v) { r.x = x - v.x; r.y = y - v.y; r.z = z - v.z; } /** * Create a clone of this vector with the given vector subtracted from it. * * @param v the vector to subtract * @return the new vector */ public Vector3D subbed(Vector3D v) { return new Vector3D(x - v.x, y - v.y, z - v.z); } /** * Subtract the given coordinates from this vector's components. * * @param vx the x coordinate * @param vy the y coordinate * @param vz the z coordinate */ public void sub(double vx, double vy, double vz) { x -= vx; y -= vy; z -= vz; } /** * Subtract the given coordinates from this vector's components and store * the result in the vector r. * * @param r the vector to store the result into * @param vx the x coordinate * @param vy the y coordinate * @param vz the z coordinate */ public void subTo(Vector3D r, double vx, double vy, double vz) { r.x = x - vx; r.y = y - vy; r.z = z - vz; } /** * Create a clone of this vector with the given coordinates subtracted * from its components. * * @param vx the x coordinate * @param vy the y coordinate * @param vz the z coordinate * @return the new vector */ public Vector3D subbed(double vx, double vy, double vz) { return new Vector3D(x - vx, y - vy, z - vz); } /** * Scale the vector. * * @param s the scalar */ public void scale(double s) { x *= s; y *= s; z *= s; } /** * Scale the vector and store the result in the vector r. * * @param r the vector to store the result into * @param s the scalar */ public void scaleTo(Vector3D r, double s) { r.x = x*s; r.y = y*s; r.z = z*s; } /** * Create a scaled clone of this vector. * * @param s the scalar * @return the new vector */ public Vector3D scaled(double s) { return new Vector3D(x*s, y*s, z*s); } /** * Scale this vector's components irregularly using the given vector's * components as scalars for each coordinate. * * @param s the vector to use for scaling */ public void scale(Vector3D s) { x *= s.x; y *= s.y; z *= s.z; } /** * Scale this vector's components irregularly using the given vector's * components as scalars for each coordinate. The result will be stored in * the vector r. * * @param r the vector to store the result into * @param s the vector to use for scaling */ public void scaleTo(Vector3D r, Vector3D s) { r.x = x*s.x; r.y = y*s.y; r.z = z*s.z; } /** * Create an irregularly scaled clone of this vector using the given * vector's components as scalars for each coordinate. * * @param s the vector to use for scaling * @return the new vector */ public Vector3D scaled(Vector3D s) { return new Vector3D(x*s.x, y*s.y, z*s.z); } /** * Scale this vector's components irregularly using the given scalars for * each component * * @param sx the scalar for the x component * @param sy the scalar for the y component * @param sz the scalar for the z component */ public void scale(double sx, double sy, double sz) { x *= sx; y *= sy; z *= sz; } /** * Scale this vector's components irregularly using the given scalars for * each component and store the result in the vector r. * * @param r the vector to store the result into * @param sx the scalar for the x component * @param sy the scalar for the y component * @param sz the scalar for the z component */ public void scaleTo(Vector3D r, double sx, double sy, double sz) { r.x = x*sx; r.y = y*sy; r.z = z*sz; } /** * Create a new irregularly scaled clone of this vector using the given * scalars for each component. * * @param sx the scalar for the x component * @param sy the scalar for the y component * @param sz the scalar for the z component * @return the new vector */ public Vector3D scaled(double sx, double sy, double sz) { return new Vector3D(x*sx, y*sy, z*sz); } /** * Return the vector's length. Note that since this function uses a square * root calculation, if the actual length is not desired but only comparison * between lengths is needed (like, for example, which point is nearest to * some othe reference point), it is highly recommended to use the * {@link #lengthSq()} instead. * * @return the vector's length */ public double length() { return Math.sqrt(x*x + y*y + z*z); } /** * Return the square of the vector's length. This is the preferred method * to use when comparing lengths. */ public double lengthSq() { return x*x + y*y + z*z; } /** * Return the distance between this vector (as point) and the given vector * (as point). Note that since this function uses a square root calculation, * if the actual distance is not desired but only comparison between * distances is needed (like, for example, which point is nearest to some * othe reference point), it is highly recommended to use the * {@link #distanceSq} instead. * * @param v the other point * @return the distance between this and v */ public double distance(Vector3D v) { double xx = x - v.x; double yy = y - v.y; double zz = z - v.z; return Math.sqrt(xx*xx + yy*yy + zz*zz); } /** * Return the square of the distance between this vector (as point) and the * given vector (as point). This is the recommended method when comparing * distance between two vectors because no expensive square root is * calculated. * * @param v the other vector * @return the square of the distance between this and v. */ public double distanceSq(Vector3D v) { double xx = x - v.x; double yy = y - v.y; double zz = z - v.z; return xx*xx + yy*yy + zz*zz; } /** * Return the distance between this vector and the point indicated by the * given coordinates. Note that since this function uses a square root * calculation, if the actual distance is not desired but only comparison * between distances is needed (like, for example, which point is nearest to * some othe reference point), it is highly recommended to use the * {@link #distanceSq} instead. * * @param vx the point's x coordinate * @param vy the point's y coordinate * @param vz the point's z coordinate * @return the distance between this and v */ public double distance(double vx, double vy, double vz) { double xx = x - vx; double yy = y - vy; double zz = z - vz; return Math.sqrt(xx*xx + yy*yy + zz*zz); } /** * Return the square of the distance between this vector (as point) and the * point indicated by the given coordinates. This is the recommended method * when comparing distance between two vectors because no expensive square * root is calculated. * * @param vx the point's x coordinate * @param vy the point's y coordinate * @param vz the point's z coordinate * @return the distance between this and v */ public double distanceSq(double vx, double vy, double vz) { double xx = x - vx; double yy = y - vy; double zz = z - vz; return xx*xx + yy*yy + zz*zz; } /** * Normalize this vector. */ public void normalize() { double len = length(); if (len != 0.0) { x /= len; y /= len; z /= len; } } /** * Normalize this vector and store the normalized version in the given * vector. * * @param r the vector to store the normalized version into */ public void normalizeTo(Vector3D r) { double len = length(); if (len != 0.0) { r.x = x/len; r.y = y/len; r.z = z/len; } else { r.x = r.y = r.z = 0.0; } } /** * Create a normalized clone of this vector. */ public Vector3D normalized() { double len = length(); if (len != 0.0) { return new Vector3D(x/len, y/len, z/len); } else { return new Vector3D(); } } /** * Return the dot product between this vector and the given vector. * * @param v the other vector * @return the dot product */ public double dot(Vector3D v) { return x*v.x + y*v.y + z*v.z; } /** * Calculate the cross product between this vector and the given vector and * replace this vector's components with the result. * * @param v the other vector */ public void cross(Vector3D v) { double nx = y*v.z - v.y*z; double ny = z*v.x - v.z*x; z = x*v.y - v.x*y; x = nx; y = ny; } /** * Calculate the cross product between this vector and the given vector and * store the result into the vector r. * * @param r the vector to store the result into * @param v the other vector to use for cross product calculation */ public void crossTo(Vector3D r, Vector3D v) { r.x = y*v.z - v.y*z; r.y = z*v.x - v.z*x; r.z = x*v.y - v.x*y; } /** * Return a new vector containing the cross product between this vector * and the given vector. * * @param v the other vector * @return a new vector containing the cross product */ public Vector3D crossed(Vector3D v) { return new Vector3D(y*v.z - v.y*z, z*v.x - v.z*x, x*v.y - v.x*y); } /** * Calculate the normal for the given triangle. * * @param a the first point of the triangle * @param b the second point of the triangle * @param c the third point of the triangle * @return the triangle's normal */ public static Vector3D getNormal(Vector3D a, Vector3D b, Vector3D c) { double abx = b.x - a.x; double aby = b.y - a.y; double abz = b.z - a.z; double acx = c.x - a.x; double acy = c.y - a.y; double acz = c.z - a.z; Vector3D n = new Vector3D(aby*acz - acy*abz, abz*acx - acz*abx, abx*acy - acx*aby); n.normalize(); return n; } /** * Return the major axis of this vector. The major axis is the axis that * the greatest absolute value of the vector represents. For example in the * vector (7, 5, 3), the major axis is {@link #X_AXIS}, for (5, 8, 6) the * major axis is {@link #Y_AXIS} and for (4, 8, 12) the major axis is * {@link #Z_AXIS}. Note that since the absolute value is used, for the * vector (4, -9, 6) the major axis is {@link #Y_AXIS}, not {@link #Z_AXIS}! * * @return the major axis */ public int getMajorAxis() { double ax = Math.abs(x); double ay = Math.abs(y); double az = Math.abs(z); if (ax > ay) { if (ax > az) return X_AXIS; else return Z_AXIS; } else { if (ay > az) return Y_AXIS; else return Z_AXIS; } } /** * Return the major axis for the vector that the given coordinates * indicate. See {@link #getMajorAxis()} for more information. * * @param x the vector's x component * @param y the vector's y component * @param z the vector's z component * @return the major axis */ public static int getMajorAxis(double x, double y, double z) { double ax = Math.abs(x); double ay = Math.abs(y); double az = Math.abs(z); if (ax > ay) { if (ax > az) return X_AXIS; else return Z_AXIS; } else { if (ay > az) return Y_AXIS; else return Z_AXIS; } } /** * Convert this vector to an array containing the vector's components. */ public double[] toArray() { double[] values = new double[3]; values[0] = x; values[1] = y; values[2] = z; return values; } /** * Convert this vector to an array containing the vector's components. * * @param values the array to store the value components into */ public void toArray(double[] values) { values[0] = x; values[1] = y; values[2] = z; } /** * Return a string representation of the vector. */ public String toString() { return "(" + x + "," + y + "," + z + ")"; }}