package dwarf.util;
import dwarf.DwarfException;
/**
* A 3-dimensional, single-precision, double-point vector.
*
* @author Matthew 'siD' Van der Bijl
*
* @see java.lang.Object
* @see java.lang.Cloneable
*/
public class Vector3 extends java.lang.Object implements Cloneable {
public final static Vector3 ZERO = new Vector3(0, 0, 0);
public final static Vector3 UNIT_X = new Vector3(1, 0, 0);
public final static Vector3 UNIT_Y = new Vector3(0, 1, 0);
public final static Vector3 UNIT_Z = new Vector3(0, 0, 1);
public final static Vector3 UNIT_XYZ = new Vector3(1, 1, 1);
/**
* A constant holding a Not-a-Number (NaN) value of type
* <code>Vector3</code>.
*/
public final static Vector3 NaN = new Vector3(Double.NaN, Double.NaN, Double.NaN);
/**
* A constant holding the positive infinity of type <code>Vector3</code>.
*/
public final static Vector3 POSITIVE_INFINITY = new Vector3(
Double.POSITIVE_INFINITY,
Double.POSITIVE_INFINITY,
Double.POSITIVE_INFINITY
);
/**
* A constant holding the negative infinity of type <code>Vector3</code>.
*/
public final static Vector3 NEGATIVE_INFINITY = new Vector3(
Double.NEGATIVE_INFINITY,
Double.NEGATIVE_INFINITY,
Double.NEGATIVE_INFINITY
);
/**
* the x-component of this <code>Vector3</code>
*/
private double x;
/**
* the y-component of this <code>Vector3</code>
*/
private double y;
/**
* the z-component of this <code>Vector3</code>
*/
private double z;
/**
* Default constructor.
*/
public Vector3() {
this(0, 0, 0);
}
public Vector3(double x, double y, double z) {
super();
this.x = x;
this.y = y;
this.z = z;
}
public Vector3(Vector3 v) {
this(v.getX(), v.getY(), v.getZ());
}
public Vector3(double[] ds) throws DwarfException {
super();
if (ds.length == 3) {
this.x = ds[0];
this.y = ds[1];
this.z = ds[2];
} else {
throw new DwarfException("illegal argument");
}
}
public Vector3(float[] fs) throws DwarfException {
super();
if (fs.length == 3) {
this.x = fs[0];
this.y = fs[1];
this.z = fs[2];
} else {
throw new DwarfException("illegal argument");
}
}
public double length() {
return Math.sqrt(
this.getX() * this.getX()
+ this.getY() * this.getY()
+ this.getZ() * this.getZ());
}
public double dot(Vector3 input) {
return (this.getX() * input.getX())
+ (this.getY() * input.getY())
+ (this.getZ() * input.getZ());
}
public Vector3 cross(Vector3 input) {
double deltaX = (this.getY() * input.getZ()) - (this.getZ() * input.getY());
double deltaY = (this.getZ() * input.getX()) - (this.getX() * input.getZ());
double deltaZ = (this.getX() * input.getY()) - (this.getY() * input.getX());
return new Vector3(deltaX, deltaY, deltaZ);
}
public Vector3 normalized() {
double length = length();
return new Vector3(
this.getX() / length,
this.getY() / length,
this.getZ() / length);
}
public void add(Vector3 input) {
this.x += input.getX();
this.y += input.getY();
this.z += input.getZ();
}
public void add(double input) {
this.x += input;
this.y += input;
this.z += input;
}
public void sub(Vector3 input) {
this.x -= input.getX();
this.y -= input.getY();
this.z -= input.getZ();
}
public void sub(double input) {
this.x -= input;
this.y -= input;
this.z -= input;
}
public void mul(Vector3 input) {
this.x *= input.getX();
this.y *= input.getY();
this.z *= input.getZ();
}
public void mul(double input) {
this.x *= input;
this.y *= input;
this.z *= input;
}
public void div(Vector3 input) {
this.x /= input.getX();
this.y /= input.getY();
this.z /= input.getZ();
}
public void div(double input) {
this.x /= input;
this.y /= input;
this.z /= input;
}
public void mod(Vector3 input) {
this.x %= input.getX();
this.y %= input.getY();
this.z %= input.getZ();
}
public void mod(double input) {
this.x %= input;
this.y %= input;
this.z %= input;
}
public Vector3 abs() {
return new Vector3(
Math.abs(getX()),
Math.abs(getY()),
Math.abs(getZ()));
}
/**
* Returns a string representation of the object.
* <p>
* In general, the toString method returns a string that "textually
* represents" this object. The result should be a concise but informative
* representation that is easy for a person to read. It is recommended that
* all subclasses override this method.</p>
*
* @return a textually representation of this object
*/
@Override
public String toString() {
return "Vector3d[" + getX() + ", " + getY() + ", " + getZ() + "]";
}
public Vector2 getXY() {
return new Vector2(getX(), getY());
}
public Vector2 getYZ() {
return new Vector2(getY(), getZ());
}
public Vector2 getZX() {
return new Vector2(getZ(), getX());
}
public Vector2 getYX() {
return new Vector2(getY(), getX());
}
public Vector2 getZY() {
return new Vector2(getZ(), getY());
}
public Vector2 getXZ() {
return new Vector2(getX(), getZ());
}
public void set(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
public void set(Vector3 v) {
this.x = v.getX();
this.y = v.getY();
this.z = v.getZ();
}
public double getX() {
return this.x;
}
public void setX(double xPos) {
this.x = xPos;
}
public double getY() {
return this.y;
}
public void setY(double yPos) {
this.y = yPos;
}
public double getZ() {
return this.z;
}
public void setZ(double zPos) {
this.z = zPos;
}
/**
* Class Object is the root of the class hierarchy. Every class has Object
* as a superclass. All objects, including arrays, implement the methods of
* this class.
*
* @return a hash code value for this object.
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public int hashCode() {
int hash = 5;
hash = 43 * hash + (int) (Double.doubleToLongBits(getX()) ^ (Double.doubleToLongBits(getX()) >>> 32));
hash = 43 * hash + (int) (Double.doubleToLongBits(getY()) ^ (Double.doubleToLongBits(getY()) >>> 32));
hash = 43 * hash + (int) (Double.doubleToLongBits(getZ()) ^ (Double.doubleToLongBits(getZ()) >>> 32));
return hash;
}
/**
* Returns true if the <code>this</code> is equal to the argument and false
* otherwise. Consequently, if both argument are null, true is returned,
* false is returned. Otherwise, equality is determined by using the equals
* method of the first argument.
*
* @param obj the <code>Object</code> to be tested
* @see java.lang.Object#equals(java.lang.Object)
*
* @return true if the argument is equal to <code>this</code> other and
* false otherwise
*/
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
} else if (getClass() != obj.getClass()) {
return false;
} else if (!super.equals(obj)) {
return false;
}
final Vector3 v = (Vector3) obj;
if (Double.doubleToLongBits(getX()) != Double.doubleToLongBits(v.getX())) {
return false;
} else if (Double.doubleToLongBits(getY()) != Double.doubleToLongBits(v.getY())) {
return false;
} else if (Double.doubleToLongBits(getZ()) != Double.doubleToLongBits(v.getZ())) {
return false;
}
return true;
}
public void translate(Vector3 delta) {
this.x += delta.getX();
this.y += delta.getY();
this.z += delta.getZ();
}
public void translate(double delta) {
this.x += delta;
this.y += delta;
this.z += delta;
}
public void translateX(double deltaX) {
this.x += deltaX;
}
public void trannslateY(double deltaY) {
this.y += deltaY;
}
public void translateZ(double deltaZ) {
this.z += deltaZ;
}
public void flipX() {
this.x = -x;
}
public void flipY() {
this.y = -y;
}
public void flipZ() {
this.z = -z;
}
public void flip() {
this.x = -x;
this.y = -y;
this.z = -z;
}
public double absX() {
return Math.abs(this.getX());
}
public double absY() {
return Math.abs(this.getY());
}
public double absZ() {
return Math.abs(this.getZ());
}
/**
* Creates a new object of the same class as this object.
*
* @exception OutOfMemoryError if there is not enough memory.
* @throws java.lang.CloneNotSupportedException if clone is not supported
* thought this should not happen.
*
* @return a clone of this instance.
*/
@Override
public Vector3 clone() throws CloneNotSupportedException {
return new Vector3(this);
}
public double[] toArray() {
return new double[]{x, y, z};
}
public double get(int index) {
switch (index) {
case 0:
return x;
case 1:
return y;
case 2:
return z;
}
throw new dwarf.DwarfException("illegal argument");
}
public double angleBetween(Vector3 otherVector) {
double dotProduct = dot(otherVector);
double angle = Math.acos(dotProduct);
return angle;
}
}