Gamelib/src/main/java/uulm/teamname/marvelous/gamelibrary/IntVector2.java

295 lines
7.9 KiB
Java

package uulm.teamname.marvelous.gamelibrary;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import uulm.teamname.marvelous.gamelibrary.json.ingame.deserialize.IntVector2Deserializer;
import uulm.teamname.marvelous.gamelibrary.json.ingame.serialize.IntVector2Serializer;
import java.io.Serializable;
import java.util.Objects;
/** Represents a 2d vector of integers. */
@JsonDeserialize(using = IntVector2Deserializer.class)
@JsonSerialize(using = IntVector2Serializer.class)
public class IntVector2 implements Serializable {
private int x;
private int y;
public final static IntVector2 X = new IntVector2(1, 0);
public final static IntVector2 Y = new IntVector2(0, 1);
public final static IntVector2 Zero = new IntVector2(0, 0);
public final static IntVector2[] CardinalDirections = {
new IntVector2(1, 0),
new IntVector2(0, 1),
new IntVector2(1, 1),
new IntVector2(-1, 0),
new IntVector2(0, -1),
new IntVector2(-1, -1),
new IntVector2(1, -1),
new IntVector2(-1, 1),
};
private final static float nearZero = 0.000000001f;
public IntVector2(int x, int y) {
set(x, y);
}
public IntVector2(IntVector2 v) {
set(v);
}
public IntVector2 copy() {
return new IntVector2(this);
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public static float length(int x, int y) {
return (float)Math.sqrt((double) x * x + y * y);
}
public float length() {
return IntVector2.length(this.x, this.y);
}
public static float length2(int x, int y) {
return (float) x * x + y * y;
}
public float length2 () {
return IntVector2.length2(this.x, this.y);
}
public IntVector2 set(int x, int y) {
this.x = x;
this.y = y;
return this;
}
public IntVector2 set(IntVector2 v) {
return set(v.x, v.y);
}
public IntVector2 sub(int x, int y) {
this.x -= x;
this.y -= y;
return this;
}
public IntVector2 sub(IntVector2 v) {
return sub(v.x, v.y);
}
public IntVector2 add(int x, int y) {
this.x += x;
this.y += y;
return this;
}
public IntVector2 add(IntVector2 v) {
return add(v.x, v.y);
}
public static float dot(float x1, float y1, float x2, float y2) {
return x1 * x2 + y1 * y2;
}
public float dot(float ox, float oy) {
return IntVector2.dot(this.x, this.y, ox, oy);
}
public float dot(IntVector2 v) {
return dot(v.x, v.y);
}
// TODO: This returns a new Vector for now, but should scale the actually modified vector
public IntVector2 scale(float x, float y) {
return new IntVector2(Math.round(this.x * x), Math.round(this.y * y));
}
public IntVector2 scale(float scalar) {
return scale(scalar, scalar);
}
public IntVector2 scale(IntVector2 v) {
return scale(v.x, v.y);
}
public static float distance(int x1, int y1, int x2, int y2) {
final float x_d = (float) x2 - x1;
final float y_d = (float) y2 - y1;
return (float)Math.sqrt(x_d * x_d + y_d * y_d);
}
public float distance(int x, int y) {
return IntVector2.distance(this.x, this.y, x, y);
}
public float distance(IntVector2 v) {
return distance(v.x, v.y);
}
/** Equivalent to the minimum amount of king moves to go from A to B in chess */
public static float distanceChebyshev(int x1, int y1, int x2, int y2) {
final float x_d = (float) x2 - x1;
final float y_d = (float) y2 - y1;
return Math.max(Math.abs(x_d), Math.abs(y_d));
}
/** Equivalent to the minimum amount of king moves to go from A to B in chess */
public float distanceChebyshev(int x, int y) {
return IntVector2.distanceChebyshev(this.x, this.y, x, y);
}
/** Equivalent to the minimum amount of king moves to go from A to B in chess */
public float distanceChebyshev(IntVector2 v) {
return distanceChebyshev(v.x, v.y);
}
public static float distanceManhattan(int x1, int y1, int x2, int y2) {
final float x_d = (float) x2 - x1;
final float y_d = (float) y2 - y1;
return Math.abs(x_d) + Math.abs(y_d);
}
public float distanceManhattan(int x, int y) {
return IntVector2.distanceManhattan(this.x, this.y, x, y);
}
public float distanceManhattan(IntVector2 v) {
return distanceManhattan(v.x, v.y);
}
public static float distance2(int x1, int y1, int x2, int y2) {
final float x_d = (float) x2 - x1;
final float y_d = (float) y2 - y1;
return x_d * x_d + y_d * y_d;
}
public float distance2(int x, int y) {
return IntVector2.distance2(this.x, this.y, x, y);
}
public float distance2(IntVector2 v) {
return distance2(v.x, v.y);
}
public IntVector2 setLength(float len) {
return setLength2(len * len);
}
public IntVector2 setLength2(float len2) {
float oldLen2 = length2();
return (oldLen2 == 0 || oldLen2 == len2) ? this : scale((float)Math.sqrt(len2 / oldLen2));
}
public String toString() {
return "(" + x + "," + y + ")";
}
public IntVector2 fromString(String v) throws NumberFormatException {
int s = v.indexOf(',', 1);
if (s != -1 && v.charAt(0) == '(' && v.charAt(v.length() - 1) == ')') {
try {
int x = Integer.parseInt(v.substring(1, s));
int y = Integer.parseInt(v.substring(s + 1, v.length() - 1));
return this.set(x, y);
}catch (NumberFormatException ex) {
//ok
}
}
throw new NumberFormatException("Malformed IntVector2: " + v);
}
public float cross(float x, float y) {
return this.x * y - this.y * x;
}
public float cross(IntVector2 v) {
return cross(v.x, v.y);
}
public boolean isUnit(final float margin) {
return Math.abs(length2() - 1f) < margin;
}
public boolean isUnit() {
return isUnit(nearZero);
}
public boolean isZero() {
return x == 0 && y == 0;
}
public boolean isZero(final float margin) {
return length2() < margin;
}
public boolean isOnLine(IntVector2 other, float epsilon) {
return Math.abs(x * other.y - y * other.x) <= epsilon;
}
public boolean isOnLine(IntVector2 other) {
return isOnLine(other, nearZero);
}
public boolean isCollinear(IntVector2 other, float epsilon) {
return isOnLine(other, epsilon) && dot(other) > 0f;
}
public boolean isCollinear(IntVector2 other) {
return isOnLine(other) && dot(other) > 0f;
}
public boolean isCollinearOpposite(IntVector2 other, float epsilon) {
return isOnLine(other, epsilon) && dot(other) < 0f;
}
public boolean isCollinearOpposite(IntVector2 other) {
return isOnLine(other) && dot(other) < 0f;
}
public boolean isPerpendicular(IntVector2 vector) {
return isPerpendicular(vector,nearZero);
}
public boolean isPerpendicular(IntVector2 vector, float epsilon) {
return Math.abs(dot(vector)) <= epsilon;
}
public boolean hasSameDirection(IntVector2 vector) {
return dot(vector) > 0;
}
public boolean hasOppositeDirection(IntVector2 vector) {
return dot(vector) < 0;
}
public IntVector2 setZero() {
this.x = 0;
this.y = 0;
return this;
}
@Override
public boolean equals(Object o) {
if(this == o) return true;
if(o == null || getClass() != o.getClass()) return false;
IntVector2 that = (IntVector2) o;
return x == that.x && y == that.y;
}
@Override
public int hashCode() {
return Objects.hash(x, y);
}
}