Added Vector and friends, and Transform interface.

This commit is contained in:
Michael Bayne
2011-07-05 08:57:44 -07:00
parent 339ea761d1
commit b6f87af8a0
5 changed files with 594 additions and 0 deletions
@@ -0,0 +1,198 @@
//
// Pythagoras - a collection of geometry classes
// http://github.com/samskivert/pythagoras
package pythagoras.f;
import pythagoras.util.Platform;
/**
* Provides most of the implementation of {@link IVector}, obtaining only x and y from the derived
* class.
*/
public abstract class AbstractVector implements IVector
{
@Override // from interface IVector
public float dot (IVector other) {
return getX()*other.getX() + getY()*other.getY();
}
@Override // from interface IVector
public Vector negate () {
return negate(new Vector());
}
@Override // from interface IVector
public Vector negate (Vector result) {
return result.set(-getX(), -getY());
}
@Override // from interface IVector
public Vector normalize () {
return normalize(new Vector());
}
@Override // from interface IVector
public Vector normalize (Vector result) {
return mult(1f / length(), result);
}
@Override // from interface IVector
public float angle (IVector other) {
float cos = dot(other) / (length() * other.length());
return cos >= 1f ? 0f : FloatMath.acos(cos);
}
@Override // from interface IVector
public float direction (IVector other) {
return FloatMath.atan2(other.getY() - getY(), other.getX() - getX());
}
@Override // from interface IVector
public float length () {
return FloatMath.sqrt(lengthSq());
}
@Override // from interface IVector
public float lengthSq () {
float x = getX(), y = getY();
return (x*x + y*y);
}
@Override // from interface IVector
public float distance (IVector other) {
return FloatMath.sqrt(distanceSq(other));
}
@Override // from interface IVector
public float distanceSq (IVector other) {
float dx = getX() - other.getX(), dy = getY() - other.getY();
return dx*dx + dy*dy;
}
@Override // from interface IVector
public Vector mult (float v) {
return mult(v, new Vector());
}
@Override // from interface IVector
public Vector mult (float v, Vector result) {
return result.set(getX()*v, getY()*v);
}
@Override // from interface IVector
public Vector mult (IVector other) {
return mult(other, new Vector());
}
@Override // from interface IVector
public Vector mult (IVector other, Vector result) {
return result.set(getX()*other.getX(), getY()*other.getY());
}
@Override // from interface IVector
public Vector add (IVector other) {
return add(other, new Vector());
}
@Override // from interface IVector
public Vector add (IVector other, Vector result) {
return add(other.getX(), other.getY(), result);
}
@Override // from interface IVector
public Vector subtract (IVector other) {
return subtract(other, new Vector());
}
@Override // from interface IVector
public Vector subtract (IVector other, Vector result) {
return add(-other.getX(), -other.getY(), result);
}
@Override // from interface IVector
public Vector add (float x, float y) {
return add(x, y, new Vector());
}
@Override // from interface IVector
public Vector add (float x, float y, Vector result) {
return result.set(getX() + x, getY() + y);
}
@Override // from interface IVector
public Vector addScaled (IVector other, float v) {
return addScaled(other, v, new Vector());
}
@Override // from interface IVector
public Vector addScaled (IVector other, float v, Vector result) {
return result.set(getX() + other.getX()*v, getY() + other.getY()*v);
}
@Override // from interface IVector
public Vector rotate (float angle) {
return rotate(angle, new Vector());
}
@Override // from interface IVector
public Vector rotate (float angle, Vector result) {
float x = getX(), y = getY();
float sina = FloatMath.sin(angle), cosa = FloatMath.cos(angle);
return result.set(x*cosa - y*sina, x*sina + y*cosa);
}
@Override // from interface IVector
public Vector rotateAndAdd (float angle, IVector add, Vector result) {
float x = getX(), y = getY();
float sina = FloatMath.sin(angle), cosa = FloatMath.cos(angle);
return result.set(x*cosa - y*sina + add.getX(), x*sina + y*cosa + add.getY());
}
@Override // from interface IVector
public Vector rotateScaleAndAdd (float angle, float scale, IVector add, Vector result) {
float x = getX(), y = getY();
float sina = FloatMath.sin(angle), cosa = FloatMath.cos(angle);
return result.set((x*cosa - y*sina)*scale + add.getX(),
(x*sina + y*cosa)*scale + add.getY());
}
@Override // from interface IVector
public Vector lerp (IVector other, float t) {
return lerp(other, t, new Vector());
}
@Override // from interface IVector
public Vector lerp (IVector other, float t, Vector result) {
float x = getX(), y = getY();
float dx = other.getX() - x, dy = other.getY() - y;
return result.set(x + t*dx, y + t*dy);
}
@Override // from interface IVector
public Vector clone () {
return new Vector(this);
}
@Override
public boolean equals (Object obj) {
if (obj == this) {
return true;
}
if (obj instanceof AbstractVector) {
AbstractVector p = (AbstractVector)obj;
return getX() == p.getX() && getY() == p.getY();
}
return false;
}
@Override
public int hashCode () {
return Platform.hashCode(getX()) ^ Platform.hashCode(getY());
}
@Override
public String toString () {
return Vectors.vectorToString(getX(), getY());
}
}
+132
View File
@@ -0,0 +1,132 @@
//
// Pythagoras - a collection of geometry classes
// http://github.com/samskivert/pythagoras
package pythagoras.f;
/**
* Provides read-only access to a {@link Vector}.
*/
public interface IVector
{
/** Returns the x-component of this vector. */
float getX ();
/** Returns the y-component of this vector. */
float getY ();
/** Computes and returns the dot product of this and the specified other vector. */
float dot (IVector other);
/** Negates this vector.
* @return a new vector containing the result. */
Vector negate ();
/** Negates this vector, storing the result in the supplied object.
* @return a reference to the result, for chaining. */
Vector negate (Vector result);
/** Normalizes this vector.
* @return a new vector containing the result. */
Vector normalize ();
/** Normalizes this vector, storing the result in the object supplied.
* @return a reference to the result, for chaining. */
Vector normalize (Vector result);
/** Returns the angle between this vector and the specified other vector. */
float angle (IVector other);
/** Returns the direction of a vector pointing from this point to the specified other point. */
float direction (IVector other);
/** Returns the length of this vector. */
float length ();
/** Returns the squared length of this vector. */
float lengthSq ();
/** Returns the distance from this vector to the specified other vector. */
float distance (IVector other);
/** Returns the squared distance from this vector to the specified other. */
float distanceSq (IVector other);
/** Multiplies this vector by a scalar.
* @return a new vector containing the result. */
Vector mult (float v);
/** Multiplies this vector by a scalar and places the result in the supplied object.
* @return a reference to the result, for chaining. */
Vector mult (float v, Vector result);
/** Multiplies this vector by another.
* @return a new vector containing the result. */
Vector mult (IVector other);
/** Multiplies this vector by another, storing the result in the object provided.
* @return a reference to the result vector, for chaining. */
Vector mult (IVector other, Vector result);
/** Adds a vector to this one.
* @return a new vector containing the result. */
Vector add (IVector other);
/** Adds a vector to this one, storing the result in the object provided.
* @return a reference to the result, for chaining. */
Vector add (IVector other, Vector result);
/** Adds a vector to this one.
* @return a new vector containing the result. */
Vector add (float x, float y);
/** Adds a vector to this one and stores the result in the object provided.
* @return a reference to the result, for chaining. */
Vector add (float x, float y, Vector result);
/** Adds a scaled vector to this one.
* @return a new vector containing the result. */
Vector addScaled (IVector other, float v);
/** Adds a scaled vector to this one and stores the result in the supplied vector.
* @return a reference to the result, for chaining. */
Vector addScaled (IVector other, float v, Vector result);
/** Subtracts a vector from this one.
* @return a new vector containing the result. */
Vector subtract (IVector other);
/** Subtracts a vector from this one and places the result in the supplied object.
* @return a reference to the result, for chaining. */
Vector subtract (IVector other, Vector result);
/** Rotates this vector by the specified angle.
* @return a new vector containing the result. */
Vector rotate (float angle);
/** Rotates this vector by the specified angle, storing the result in the vector provided.
* @return a reference to the result vector, for chaining. */
Vector rotate (float angle, Vector result);
/** Rotates this vector by the specified angle and adds another vector to it, placing the
* result in the object provided.
* @return a reference to the result, for chaining. */
Vector rotateAndAdd (float angle, IVector add, Vector result);
/** Rotates this vector by the specified angle, applies a uniform scale, and adds another
* vector to it, placing the result in the object provided.
* @return a reference to the result, for chaining. */
Vector rotateScaleAndAdd (float angle, float scale, IVector add, Vector result);
/** Linearly interpolates between this and the specified other vector by the supplied amount.
* @return a new vector containing the result. */
Vector lerp (IVector other, float t);
/** Linearly interpolates between this and the supplied other vector by the supplied amount,
* storing the result in the supplied object.
* @return a reference to the result, for chaining. */
Vector lerp (IVector other, float t, Vector result);
/** Returns a mutable copy of this vector. */
Vector clone ();
}
+103
View File
@@ -0,0 +1,103 @@
//
// Pythagoras - a collection of geometry classes
// http://github.com/samskivert/pythagoras
package pythagoras.f;
/**
* Represents a geometric transform. Specialized implementations exist for identity, rigid body,
* uniform, affine and general transforms.
*/
public interface Transform
{
/** Sets the translation component of this transform.
* @throws UnsupportedOperationException if the transform is not rigid body or greater. */
void setTranslation (float tx, float ty);
/** Sets the x-component of this transform's translation.
* @throws UnsupportedOperationException if the transform is not rigid body or greater. */
void setTx (float tx);
/** Sets the y-component of this transform's translation.
* @throws UnsupportedOperationException if the transform is not rigid body or greater. */
void setTy (float ty);
/** Sets the rotation component of this transform.
* @throws UnsupportedOperationException if the transform is not rigid body or greater. */
void setRotation (float angle);
/** Sets the uniform scale of this transform.
* @throws UnsupportedOperationException if the transform is not uniform or greater. */
void setScale (float scale);
/** Sets the x and y scale of this transform.
* @throws UnsupportedOperationException if the transform is not affine or greater. */
void setScale (float scaleX, float scaleY);
/** Sets the x scale of this transform.
* @throws UnsupportedOperationException if the transform is not affine or greater. */
void setScaleX (float scaleX);
/** Sets the y scale of this transform.
* @throws UnsupportedOperationException if the transform is not affine or greater. */
void setScaleY (float scaleY);
/** Sets the affine transform matrix.
* @throws UnsupportedOperationException if the transform is not affine or greater. */
void setTransform (float m00, float m01, float m10, float m11,
float tx, float ty);
/** Sets the general transform matrix.
* @throws UnsupportedOperationException if the transform is not general. */
void setTransform (float m00, float m01, float m02,
float m10, float m11, float m12,
float m20, float m21, float m22);
/** Returns the x-coordinate of the translation component. */
float getTx ();
/** Returns the y-coordinate of the translation component. */
float getTy ();
/** Returns the rotation applied by this transform. Note that the rotation is extracted and
* therefore approximate for affine and general transforms. */
float getRotation (); // will be extracted from affine+
/** Returns the uniform scale applied by this transform. Note that the uniform scale will be
* approximated for non-uniform transforms (affine and general). */
float getScale (); // will be extracted/approximated for affine+
/** Returns the x-component of the scale applied by this transform. */
float getScaleX (); // will be extracted from affine+
/** Returns the y-component of the scale applied by this transform. */
float getScaleY (); // will be extracted from affine+
/** Returns the inverse of this transform.
* @throws NoninvertibleTransformException if the transform is not invertible. */
Transform invert ();
/** Composes this transform with the supplied transform (i.e. {@code this x other}). */
Transform compose (Transform other);
/** Returns the linear interpolation between this transform and the specified other. */
Transform lerp (Transform other, float t);
/** Transforms the supplied point, writing the result into {@code into}, which may reference
* the same object as {@code p}. */
void transform (IPoint p, Point into);
/** Inverse transforms the supplied point, writing the result into {@code into}, which may
* reference the same object as {@code p}.
* @throws NoninvertibleTransformException if the transform is not invertible. */
void inverseTransform (IPoint p, Point into);
/** Transforms the supplied vector, writing the result into {@code into}, which may reference
* the same object as {@code v}. */
void transform (IVector v, Vector into);
/** Inverse transforms the supplied vector, writing the result into {@code into}, which may
* reference the same object as {@code v}.
* @throws NoninvertibleTransformException if the transform is not invertible. */
void inverseTransform (IVector v, Vector into);
}
+121
View File
@@ -0,0 +1,121 @@
//
// Pythagoras - a collection of geometry classes
// http://github.com/samskivert/pythagoras
package pythagoras.f;
/**
* Represents a vector in a plane.
*/
public class Vector extends AbstractVector
{
/** The x-component of the vector. */
public float x;
/** The y-component of the vector. */
public float y;
/** Creates a vector with the specified x and y components. */
public Vector (float x, float y) {
set(x, y);
}
/** Creates a vector equal to {@code other}. */
public Vector (IVector other) {
set(other);
}
/** Creates a vector with zero x and y components. */
public Vector () {
}
@Override // from AbstractVector
public float getX () {
return x;
}
@Override // from AbstractVector
public float getY () {
return y;
}
/** Negates this vector in-place.
* @return a reference to this vector, for chaining. */
public Vector negateLocal () {
return negate(this);
}
/** Normalizes this vector in-place.
* @return a reference to this vector, for chaining. */
public Vector normalizeLocal () {
return normalize(this);
}
/** Multiplies this vector in-place by a scalar.
* @return a reference to this vector, for chaining. */
public Vector multLocal (float v) {
return mult(v, this);
}
/** Multiplies this vector in-place by another.
* @return a reference to this vector, for chaining. */
public Vector multLocal (IVector other) {
return mult(other, this);
}
/** Adds a vector in-place to this one.
* @return a reference to this vector, for chaining. */
public Vector addLocal (IVector other) {
return add(other, this);
}
/** Subtracts a vector in-place from this one.
* @return a reference to this vector, for chaining. */
public Vector subtractLocal (IVector other) {
return subtract(other, this);
}
/** Adds a vector in-place to this one.
* @return a reference to this vector, for chaining. */
public Vector addLocal (float x, float y) {
return add(x, y, this);
}
/** Adds a scaled vector in-place to this one.
* @return a reference to this vector, for chaining. */
public Vector addScaledLocal (IVector other, float v) {
return addScaled(other, v, this);
}
/** Rotates this vector in-place by the specified angle.
* @return a reference to this vector, for chaining. */
public Vector rotateLocal (float angle) {
return rotate(angle, this);
}
/** Linearly interpolates between this and {@code other} in-place by the supplied amount.
* @return a reference to this vector, for chaining. */
public Vector lerpLocal (IVector other, float t) {
return lerp(other, t, this);
}
/** Copies the elements of another vector.
* @return a reference to this vector, for chaining. */
public Vector set (IVector other) {
return set(other.getX(), other.getY());
}
/** Copies the elements of an array.
* @return a reference to this vector, for chaining. */
public Vector set (float[] values) {
return set(values[0], values[1]);
}
/** Sets all of the elements of the vector.
* @return a reference to this vector, for chaining. */
public Vector set (float x, float y) {
this.x = x;
this.y = y;
return this;
}
}
+40
View File
@@ -0,0 +1,40 @@
//
// Pythagoras - a collection of geometry classes
// http://github.com/samskivert/pythagoras
package pythagoras.f;
/**
* Vector-related utility methods.
*/
public class Vectors
{
/** A unit vector in the X+ direction. */
public static final IVector UNIT_X = new Vector(1f, 0f);
/** A unit vector in the Y+ direction. */
public static final IVector UNIT_Y = new Vector(0f, 1f);
/** The zero vector. */
public static final IVector ZERO = new Vector(0f, 0f);
/** A vector containing the minimum floating point value for all components
* (note: the components are -{@link Float#MAX_VALUE}, not {@link Float#MIN_VALUE}). */
public static final IVector MIN_VALUE = new Vector(-Float.MAX_VALUE, -Float.MAX_VALUE);
/** A vector containing the maximum floating point value for all components. */
public static final IVector MAX_VALUE = new Vector(Float.MAX_VALUE, Float.MAX_VALUE);
/**
* Returns a string describing the supplied vector, of the form <code>+x+y</code>,
* <code>+x-y</code>, <code>-x-y</code>, etc.
*/
public static String vectorToString (float x, float y) {
StringBuilder buf = new StringBuilder();
if (x >= 0) buf.append("+");
buf.append(x);
if (y >= 0) buf.append("+");
buf.append(y);
return buf.toString();
}
}