package toritools.math; import java.awt.Dimension; import java.awt.Point; import org.jbox2d.common.Vec2; /** * 2D Float Vector with basic math functions. Immutable. * * @author efruchter * */ public class Vector2 { public final float x, y; public final static Vector2 ZERO = new Vector2(); public final static Vector2 ONE = new Vector2(1, 1); public final static Vector2 UP_RIGHT = ONE.unit(); public final static Vector2 DOWN_RIGHT = ONE.scale(1, -1).unit(); public final static Vector2 RIGHT = new Vector2(1, 0); public Vector2(final float x, final float y) { this.x = x; this.y = y; } public Vector2(final double x, final double y) { this.x = (float) x; this.y = (float) y; } public Vector2(final Dimension dim) { this.x = dim.width; this.y = dim.height; } public Vector2(final float both) { this(both, both); } public Vector2(final Vector2 base) { this.x = base.getX(); this.y = base.getY(); } public Vector2(final Point base) { this.x = base.x; this.y = base.y; } public Vector2() { this(0, 0); } public float getX() { return this.x; } public float getY() { return this.y; } public Vector2 add(final Vector2 o) { return new Vector2(this.x + o.getX(), this.y + o.getY()); } public Vector2 add(final float x, final float y) { return new Vector2(this.x + x, this.y + y); } public Vector2 add(final float both) { return add(both, both); } public Vector2 sub(final Vector2 o) { return new Vector2(this.x - o.getX(), this.y - o.getY()); } public Vector2 sub(final float o) { return new Vector2(this.x - o, this.y - o); } public Vector2 sub(final float x, final float y) { return new Vector2(this.x - x, this.y - y); } public Vector2 scale(final float scalar) { return new Vector2(this.x * scalar, this.y * scalar); } public Vector2 scale(final float x, final float y) { return new Vector2(this.x * x, this.y * y); } public Vector2 scale(final Vector2 other) { return scale(other.x, other.y); } public float dot(final Vector2 o) { return this.x * o.getX() + this.y * o.getY(); } private float magCache = -1; public float mag() { if (magCache == -1) { magCache = (float) Math.sqrt(x * x + y * y); } return magCache; } public Vector2 unit() { if (x == 0 && y == 0) return Vector2.ZERO; return this.scale(1f / this.mag()); } public static Vector2 min(final Vector2 a, final Vector2 b) { return new Vector2(Math.min(a.getX(), b.getX()), Math.min(a.getY(), b.getY())); } public static Vector2 max(final Vector2 a, final Vector2 b) { return new Vector2(Math.max(a.getX(), b.getX()), Math.max(a.getY(), b.getY())); } public String toString() { return "[" + getX() + ", " + getY() + "]"; } public float dist(final Vector2 o) { return Vector2.dist(this, o); } public static float dist(final Vector2 a, final Vector2 b) { return (float) Math.sqrt(Math.pow(a.getX() - b.getX(), 2) + Math.pow(a.getY() - b.getY(), 2)); } public Point toPoint() { return new Point((int) getX(), (int) getY()); } /** * Rotate the vector by a number of radians. * * @param angle * the angle to rotate by. * @return the rotated vector. */ public Vector2 rotate(final float angle) { return new Vector2((float) (x * Math.cos(angle) - y * Math.sin(angle)), (float) (x * Math.sin(angle) + y * Math.cos(angle))); } /** * Rotate the vector by a number of degrees. * * @param angle * the angle to rotate by. * @return the rotated vector. */ public Vector2 rotateDeg(final float angle) { return rotate((float) Math.toRadians(angle)); } /** * Get the unit direction from start to end. * * @param start * the start vector * @param end * the destination vector * @return the unit vector pointing from start to end */ public static Vector2 getDirectionTo(final Vector2 start, final Vector2 end) { return end.sub(start).unit(); } /** * Build a unit vector out of the direction. * * @param direction * direction in radians. * @return */ public static Vector2 buildVector(final float direction) { return new Vector2((float) Math.cos(direction), (float) Math.sin(direction)).unit(); } /** * Get a unit vector angled from a to b. */ public static Vector2 toward(final Vector2 a, final Vector2 b) { return b.sub(a).unit(); } @Override public boolean equals(final Object o) { return o instanceof Vector2 && (x == ((Vector2) o).x && y == ((Vector2) o).y); } /** * Get the casted version of x. * * @return */ public int getWidth() { return (int) x; } /** * Get the casted version of y. * * @return */ public int getHeight() { return (int) y; } public Vector2(final Vec2 vec2) { x = vec2.x; y = vec2.y; } public Vec2 toVec() { return new Vec2(x, y); } }