From dd2b653b3a0fd9e21103f3c38e9ca7743a759b9e Mon Sep 17 00:00:00 2001 From: punchready Date: Thu, 29 Apr 2021 16:39:10 +0200 Subject: [PATCH] feat: add custom int vector class --- .../marvelous/gamelibrary/IntVector2.java | 247 ++++++++++++++++++ 1 file changed, 247 insertions(+) create mode 100644 src/com/uulm/marvelous/gamelibrary/IntVector2.java diff --git a/src/com/uulm/marvelous/gamelibrary/IntVector2.java b/src/com/uulm/marvelous/gamelibrary/IntVector2.java new file mode 100644 index 0000000..ea151d7 --- /dev/null +++ b/src/com/uulm/marvelous/gamelibrary/IntVector2.java @@ -0,0 +1,247 @@ +package com.uulm.marvelous.gamelibrary; + +import java.io.Serializable; +import java.util.Objects; + +/** Represents a 2d vector of integers. + */ +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); + + 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(x * x + y * y); + } + + public float length() { + return IntVector2.length(this.x, this.y); + } + + public static float length2(int x, int y) { + return 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); + } + + public IntVector2 scale(float x, float y) { + this.x *= x; + this.y *= y; + return this; + } + + 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 = x2 - x1; + final float y_d = 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); + } + + public static float distance2(int x1, int y1, int x2, int y2) { + final float x_d = x2 - x1; + final float y_d = 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); + } +}