Various Vector enhancements.
- Moved Vector.direction to Point.direction as that makes more sense. If you want to know the angle of the vector between two points, you should do that on points, not vectors. - Added Vector.angle() which returns the angle of the vector (in polar coordinates), which matches Vector.length() which returns the magnitude of the vector (in polar coordinates). - Added Vectors.fromPolar to create a vector from polar coordinates, and added Vector.setLength and Vector.setAngle to set the one whilst preserving the other.
This commit is contained in:
@@ -32,6 +32,11 @@ public abstract class AbstractPoint implements IPoint
|
||||
return Points.distance(x(), y(), p.x(), p.y());
|
||||
}
|
||||
|
||||
@Override // from interface IPoint
|
||||
public double direction (IPoint other) {
|
||||
return Math.atan2(other.y() - y(), other.x() - x());
|
||||
}
|
||||
|
||||
@Override // from IPoint
|
||||
public Point mult (double s) {
|
||||
return mult(s, new Point());
|
||||
|
||||
@@ -37,17 +37,6 @@ public abstract class AbstractVector implements IVector
|
||||
return scale(1f / length(), result);
|
||||
}
|
||||
|
||||
@Override // from interface IVector
|
||||
public double angle (IVector other) {
|
||||
double cos = dot(other) / (length() * other.length());
|
||||
return cos >= 1f ? 0f : Math.acos(cos);
|
||||
}
|
||||
|
||||
@Override // from interface IVector
|
||||
public double direction (IVector other) {
|
||||
return Math.atan2(other.y() - y(), other.x() - x());
|
||||
}
|
||||
|
||||
@Override // from interface IVector
|
||||
public double length () {
|
||||
return Math.sqrt(lengthSq());
|
||||
@@ -70,6 +59,17 @@ public abstract class AbstractVector implements IVector
|
||||
return dx*dx + dy*dy;
|
||||
}
|
||||
|
||||
@Override // from interface IVector
|
||||
public double angle () {
|
||||
return Math.atan2(y(), x());
|
||||
}
|
||||
|
||||
@Override // from interface IVector
|
||||
public double angleBetween (IVector other) {
|
||||
double cos = dot(other) / (length() * other.length());
|
||||
return cos >= 1f ? 0f : Math.acos(cos);
|
||||
}
|
||||
|
||||
@Override // from interface IVector
|
||||
public Vector scale (double v) {
|
||||
return scale(v, new Vector());
|
||||
|
||||
@@ -27,6 +27,10 @@ public interface IPoint extends Cloneable
|
||||
/** Returns the Euclidian distance between this point and the supplied point. */
|
||||
double distance (IPoint p);
|
||||
|
||||
/** Returns the angle (in radians) of the vector starting at this point and ending at the
|
||||
* supplied other point. */
|
||||
double direction (IPoint other);
|
||||
|
||||
/** Multiplies this point by a scale factor.
|
||||
* @return a new point containing the result. */
|
||||
Point mult (double s);
|
||||
|
||||
@@ -34,13 +34,7 @@ public interface IVector
|
||||
* @return a reference to the result, for chaining. */
|
||||
Vector normalize (Vector result);
|
||||
|
||||
/** Returns the angle between this vector and the specified other vector. */
|
||||
double angle (IVector other);
|
||||
|
||||
/** Returns the direction of a vector pointing from this point to the specified other point. */
|
||||
double direction (IVector other);
|
||||
|
||||
/** Returns the length of this vector. */
|
||||
/** Returns the length (magnitude) of this vector. */
|
||||
double length ();
|
||||
|
||||
/** Returns the squared length of this vector. */
|
||||
@@ -52,6 +46,12 @@ public interface IVector
|
||||
/** Returns the squared distance from this vector to the specified other. */
|
||||
double distanceSq (IVector other);
|
||||
|
||||
/** Returns the angle of this vector. */
|
||||
double angle ();
|
||||
|
||||
/** Returns the angle between this vector and the specified other vector. */
|
||||
double angleBetween (IVector other);
|
||||
|
||||
/** Scales this vector uniformly by the specified magnitude.
|
||||
* @return a new vector containing the result. */
|
||||
Vector scale (double v);
|
||||
|
||||
@@ -110,6 +110,22 @@ public class Vector extends AbstractVector
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this vector's angle, preserving its magnitude.
|
||||
* @return a reference to this vector, for chaining.
|
||||
*/
|
||||
public Vector setAngle (double angle) {
|
||||
double l = length();
|
||||
return set(l * Math.cos(angle), l * Math.sin(angle));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this vector's magnitude, preserving its angle.
|
||||
*/
|
||||
public Vector setLength (double length) {
|
||||
return normalizeLocal().scaleLocal(length);
|
||||
}
|
||||
|
||||
@Override // from AbstractVector
|
||||
public double x () {
|
||||
return x;
|
||||
|
||||
@@ -25,6 +25,13 @@ public class Vectors
|
||||
/** A vector containing the maximum doubleing point value for all components. */
|
||||
public static final IVector MAX_VALUE = new Vector(Float.MAX_VALUE, Float.MAX_VALUE);
|
||||
|
||||
/**
|
||||
* Creates a new vector from polar coordinates.
|
||||
*/
|
||||
public static final Vector fromPolar (double magnitude, double angle) {
|
||||
return new Vector(magnitude * Math.cos(angle), magnitude * Math.sin(angle));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the magnitude of the specified vector.
|
||||
*/
|
||||
|
||||
@@ -32,6 +32,11 @@ public abstract class AbstractPoint implements IPoint
|
||||
return Points.distance(x(), y(), p.x(), p.y());
|
||||
}
|
||||
|
||||
@Override // from interface IPoint
|
||||
public float direction (IPoint other) {
|
||||
return FloatMath.atan2(other.y() - y(), other.x() - x());
|
||||
}
|
||||
|
||||
@Override // from IPoint
|
||||
public Point mult (float s) {
|
||||
return mult(s, new Point());
|
||||
|
||||
@@ -37,17 +37,6 @@ public abstract class AbstractVector implements IVector
|
||||
return scale(1f / length(), result);
|
||||
}
|
||||
|
||||
@Override // from interface IVector
|
||||
public float angleBetween (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.y() - y(), other.x() - x());
|
||||
}
|
||||
|
||||
@Override // from interface IVector
|
||||
public float length () {
|
||||
return FloatMath.sqrt(lengthSq());
|
||||
@@ -70,6 +59,17 @@ public abstract class AbstractVector implements IVector
|
||||
return dx*dx + dy*dy;
|
||||
}
|
||||
|
||||
@Override // from interface IVector
|
||||
public float angle () {
|
||||
return FloatMath.atan2(y(), x());
|
||||
}
|
||||
|
||||
@Override // from interface IVector
|
||||
public float angleBetween (IVector other) {
|
||||
float cos = dot(other) / (length() * other.length());
|
||||
return cos >= 1f ? 0f : FloatMath.acos(cos);
|
||||
}
|
||||
|
||||
@Override // from interface IVector
|
||||
public Vector scale (float v) {
|
||||
return scale(v, new Vector());
|
||||
|
||||
@@ -27,6 +27,10 @@ public interface IPoint extends Cloneable
|
||||
/** Returns the Euclidian distance between this point and the supplied point. */
|
||||
float distance (IPoint p);
|
||||
|
||||
/** Returns the angle (in radians) of the vector starting at this point and ending at the
|
||||
* supplied other point. */
|
||||
float direction (IPoint other);
|
||||
|
||||
/** Multiplies this point by a scale factor.
|
||||
* @return a new point containing the result. */
|
||||
Point mult (float s);
|
||||
|
||||
@@ -34,13 +34,7 @@ public interface IVector
|
||||
* @return a reference to the result, for chaining. */
|
||||
Vector normalize (Vector result);
|
||||
|
||||
/** Returns the angle between this vector and the specified other vector. */
|
||||
float angleBetween (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. */
|
||||
/** Returns the length (magnitude) of this vector. */
|
||||
float length ();
|
||||
|
||||
/** Returns the squared length of this vector. */
|
||||
@@ -52,6 +46,12 @@ public interface IVector
|
||||
/** Returns the squared distance from this vector to the specified other. */
|
||||
float distanceSq (IVector other);
|
||||
|
||||
/** Returns the angle of this vector. */
|
||||
float angle ();
|
||||
|
||||
/** Returns the angle between this vector and the specified other vector. */
|
||||
float angleBetween (IVector other);
|
||||
|
||||
/** Scales this vector uniformly by the specified magnitude.
|
||||
* @return a new vector containing the result. */
|
||||
Vector scale (float v);
|
||||
|
||||
@@ -110,6 +110,22 @@ public class Vector extends AbstractVector
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this vector's angle, preserving its magnitude.
|
||||
* @return a reference to this vector, for chaining.
|
||||
*/
|
||||
public Vector setAngle (float angle) {
|
||||
float l = length();
|
||||
return set(l * FloatMath.cos(angle), l * FloatMath.sin(angle));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this vector's magnitude, preserving its angle.
|
||||
*/
|
||||
public Vector setLength (float length) {
|
||||
return normalizeLocal().scaleLocal(length);
|
||||
}
|
||||
|
||||
@Override // from AbstractVector
|
||||
public float x () {
|
||||
return x;
|
||||
|
||||
@@ -25,6 +25,13 @@ public class Vectors
|
||||
/** 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);
|
||||
|
||||
/**
|
||||
* Creates a new vector from polar coordinates.
|
||||
*/
|
||||
public static final Vector fromPolar (float magnitude, float angle) {
|
||||
return new Vector(magnitude * FloatMath.cos(angle), magnitude * FloatMath.sin(angle));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the magnitude of the specified vector.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
//
|
||||
// Pythagoras - a collection of geometry classes
|
||||
// http://github.com/samskivert/pythagoras
|
||||
|
||||
package pythagoras.f;
|
||||
|
||||
import org.junit.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Tests aspects of the {@link Vector} class.
|
||||
*/
|
||||
public class VectorTest
|
||||
{
|
||||
@Test
|
||||
public void testFromPolar () {
|
||||
for (float length = 0.05f; length < 5; length += 0.05f) {
|
||||
// stay away from -PI and PI because the signs might be flipped
|
||||
for (float theta = -FloatMath.PI + 0.05f; theta < FloatMath.PI; theta += 0.05f) {
|
||||
Vector v = Vectors.fromPolar(length, theta);
|
||||
assertEquals(length, v.length(), MathUtil.EPSILON);
|
||||
assertEquals(theta, v.angle(), MathUtil.EPSILON);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetLength () {
|
||||
for (float length = 0.05f; length < 5; length += 0.05f) {
|
||||
// stay away from -PI and PI because the signs might be flipped
|
||||
for (float theta = -FloatMath.PI + 0.05f; theta < FloatMath.PI; theta += 0.05f) {
|
||||
Vector v = Vectors.fromPolar(length, theta);
|
||||
v.setLength(10);
|
||||
// make sure setting length actually sets the length
|
||||
assertEquals(10, v.length(), MathUtil.EPSILON);
|
||||
// make sure setting length doesn't bork angle
|
||||
assertEquals(theta, v.angle(), MathUtil.EPSILON);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetAngle () {
|
||||
for (float length = 0.05f; length < 5; length += 0.05f) {
|
||||
// stay away from -PI and PI because the signs might be flipped
|
||||
for (float theta = 0.05f; theta < FloatMath.PI; theta += 0.05f) {
|
||||
Vector v = Vectors.fromPolar(length, theta);
|
||||
v.setAngle(FloatMath.PI - theta);
|
||||
// make sure setting angle actually sets the angle
|
||||
assertEquals(FloatMath.PI - theta, v.angle(), MathUtil.EPSILON);
|
||||
// make sure setting length doesn't bork length
|
||||
assertEquals(length, v.length(), MathUtil.EPSILON);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user