package com.srbenoit.geom;
import com.srbenoit.log.LoggedObject;
/**
* A simple three-dimensional vector.
*/
public class Vector3 extends LoggedObject implements Vector3Int {
/** the X component */
private double vecX;
/** the Y component */
private double vecY;
/** the Z component */
private double vecZ;
/** the length, computed lazily */
private double len;
/**
* Constructs a null vector.
*/
public Vector3() {
this.vecX = 0;
this.vecY = 0;
this.vecZ = 0;
this.len = 0;
}
/**
* Constructs a vector.
*
* @param xCoord the X component
* @param yCoord the Y component
* @param zCoord the Z component
*/
public Vector3(final double xCoord, final double yCoord, final double zCoord) {
this.vecX = xCoord;
this.vecY = yCoord;
this.vecZ = zCoord;
this.len = -1;
}
/**
* Constructs a vector.
*
* @param source the vector whose components are to be copied
*/
public Vector3(final Vector3Int source) {
this.vecX = source.getVecX();
this.vecY = source.getVecY();
this.vecZ = source.getVecZ();
this.len = source.lazyLength();
}
/**
* Gets the X component of the vector.
*
* @return the X component
*/
public double getVecX() {
return this.vecX;
}
/**
* Sets the X component of the vector.
*
* @param xComp the X component
*/
public void setVecX(final double xComp) {
this.vecX = xComp;
this.len = -1;
}
/**
* Gets the Y component of the vector.
*
* @return the Y component
*/
public double getVecY() {
return this.vecY;
}
/**
* Sets the Y component of the vector.
*
* @param yComp the Y component
*/
public void setVecY(final double yComp) {
this.vecY = yComp;
this.len = -1;
}
/**
* Gets the Z component of the vector.
*
* @return the Z component
*/
public double getVecZ() {
return this.vecZ;
}
/**
* Sets the Z component of the vector.
*
* @param zComp the Z component
*/
public void setVecZ(final double zComp) {
this.vecZ = zComp;
this.len = -1;
}
/**
* Sets the coordinates of the vector.
*
* @param xComp the x component
* @param yComp the y component
* @param zComp the z component
*/
public void setVec(final double xComp, final double yComp, final double zComp) {
this.vecX = xComp;
this.vecY = yComp;
this.vecZ = zComp;
this.len = -1;
}
/**
* Sets the coordinates of the vector from another vector.
*
* @param source the vector whose components are to be copied
*/
public void setVec(final Vector3Int source) {
this.vecX = source.getVecX();
this.vecY = source.getVecY();
this.vecZ = source.getVecZ();
this.len = source.lazyLength();
}
/**
* Adds to the components of the vector.
*
* @param xDelta the change to the x component
* @param yDelta the change to the y component
* @param zDelta the change to the z component
*/
public void addVec(final double xDelta, final double yDelta, final double zDelta) {
this.vecX += xDelta;
this.vecY += yDelta;
this.vecZ += zDelta;
this.len = -1;
}
/**
* Adds a vector to this vector.
*
* @param vector the vector to add to this vector
*/
public void addVec(final Vector3Int vector) {
this.vecX += vector.getVecX();
this.vecY += vector.getVecY();
this.vecZ += vector.getVecZ();
this.len = -1;
}
/**
* Subtracts a vector from this vector.
*
* @param vector the vector to subtract from this vector
*/
public void subVec(final Vector3Int vector) {
this.vecX -= vector.getVecX();
this.vecY -= vector.getVecY();
this.vecZ -= vector.getVecZ();
this.len = -1;
}
/**
* Subtracts vector2
from vector1
and stores the result in this
* vector.
*
* @param vector1 the vector from which to subtract
* @param vector2 the vector to subtract
*/
public void subVec(final Vector3Int vector1, final Vector3Int vector2) {
this.vecX = vector2.getVecX() - vector1.getVecX();
this.vecY = vector2.getVecY() - vector1.getVecY();
this.vecZ = vector2.getVecZ() - vector1.getVecZ();
this.len = -1;
}
/**
* Adds a scaled version of a vector to this vector (this = this + scale tuple).
*
* @param scale the scalar value
* @param vector the vector to be scaled then added
*/
public void addVecScaled(final double scale, final Vector3Int vector) {
this.vecX += vector.getVecX() * scale;
this.vecY += vector.getVecY() * scale;
this.vecZ += vector.getVecZ() * scale;
this.len = -1;
}
/**
* Sets this vector to the vector from point1
to point2
(this =
* point2 - point1).
*
* @param fromPoint the first point
* @param toPoint the second point
*/
public void vectorBetween(final Point3Int fromPoint, final Point3Int toPoint) {
this.vecX = toPoint.getPosX() - fromPoint.getPosX();
this.vecY = toPoint.getPosY() - fromPoint.getPosY();
this.vecZ = toPoint.getPosZ() - fromPoint.getPosZ();
this.len = -1;
}
/**
* Negates this vector in place.
*/
public void negateVec() {
// Length is not affected
this.vecX = -this.vecX;
this.vecY = -this.vecY;
this.vecZ = -this.vecZ;
}
/**
* Scales this vector by a scalar factor.
*
* @param scale the scalar factor
*/
public void scaleVec(final double scale) {
this.vecX *= scale;
this.vecY *= scale;
this.vecZ *= scale;
// if a length is known, the length is scaled by the absolute value of scale
if (this.len != -1) {
if (scale < 0) {
this.len *= -scale;
} else {
this.len *= scale;
}
}
}
/**
* Sets this vector to a scaled version of another vector.
*
* @param scale the scalar factor
* @param vec the vector to scale
*/
public void scaleVec(double scale, Vector3Int vec) {
this.vecX = vec.getVecX() * scale;
this.vecY = vec.getVecY() * scale;
this.vecZ = vec.getVecZ() * scale;
// if a length is known, the length is scaled by the absolute value of scale
this.len = vec.lazyLength();
if (vec.lazyLength() != -1) {
if (scale < 0) {
this.len *= -scale;
} else {
this.len *= scale;
}
}
}
/**
* Gets the lazily computed length of the vector.
*
* @return the length of the vector, or -1 if the length has not yet been computed
*/
public double lazyLength() {
return this.len;
}
/**
* Gets the squared length of the vector.
*
* @return the squared length of the vector
*/
public double lengthSquared() {
double result;
if (this.len == -1) {
result = (this.vecX * this.vecX) + (this.vecY * this.vecY) + (this.vecZ * this.vecZ);
} else {
result = this.len * this.len;
}
return result;
}
/**
* Gets the length of the vector.
*
* @return the length of the vector
*/
public double length() {
double result;
if (this.len == -1) {
this.len = Math.sqrt((this.vecX * this.vecX) + (this.vecY * this.vecY)
+ (this.vecZ * this.vecZ));
}
return this.len;
}
/**
* Computes the dot product of this vector with another vector.
*
* @param vector the other vector
* @return the dot product
*/
public double dot(final Vector3Int vector) {
return (this.vecX * vector.getVecX()) + (this.vecY * vector.getVecY())
+ (this.vecZ * vector.getVecZ());
}
/**
* Computes the cross product of first
and second
and stores the
* result in this vector.
*
* @param first the first tuple in the cross product
* @param second the second tuple in the cross product
*/
public void cross(final Vector3Int first, final Vector3Int second) {
this.vecZ = (first.getVecY() * second.getVecZ()) - (first.getVecZ() * second.getVecY());
this.vecY = (first.getVecZ() * second.getVecX()) - (first.getVecX() * second.getVecZ());
this.vecZ = (first.getVecX() * second.getVecY()) - (first.getVecY() * second.getVecX());
this.len = -1;
}
/**
* Normalizes this vector in place. The null vector is normalized to (1,0).
*/
public void normalize() {
double before;
before = length();
if (before < Double.MIN_NORMAL) {
// Don't want to divide by that, so consider it zero.
this.vecX = 1;
this.vecY = 0;
this.vecZ = 0;
} else {
this.vecX /= before;
this.vecY /= before;
this.vecZ /= before;
}
this.len = 1;
}
/**
* Generates the string representation of the point.
*
* @return the String
representation
*/
@Override public String toString() {
StringBuilder str;
str = new StringBuilder(50);
str.append('[');
str.append(this.vecX);
str.append(", ");
str.append(this.vecY);
str.append(", ");
str.append(this.vecZ);
str.append(']');
return str.toString();
}
}