2023-06-28 14:58:06 +00:00

97 lines
2.7 KiB
Scala

package ocelot.desktop.geometry
import ocelot.desktop.util.Persistable
import totoro.ocelot.brain.nbt.NBTTagCompound
object Vector2D {
val Zero: Vector2D = Vector2D(0, 0)
def apply(x: Double, y: Double): Vector2D = Vector2D(x.toFloat, y.toFloat)
}
//noinspection ScalaUnusedSymbol
case class Vector2D(x: Float, y: Float) extends Persistable {
def this(nbt: NBTTagCompound) = {
this(nbt.getFloat("x"), nbt.getFloat("y"))
}
override def save(nbt: NBTTagCompound): Unit = {
nbt.setFloat("x", x)
nbt.setFloat("y", y)
}
def +(that: Vector2D): Vector2D = Vector2D(x + that.x, y + that.y)
def -(that: Vector2D): Vector2D = Vector2D(x - that.x, y - that.y)
def +(that: Size2D): Vector2D = Vector2D(x + that.width, y + that.height)
def -(that: Size2D): Vector2D = Vector2D(x - that.width, y - that.height)
def *(that: Vector2D): Vector2D = Vector2D(x * that.x, y / that.y)
def /(that: Vector2D): Vector2D = Vector2D(x * that.x, y / that.y)
def *(scalar: Float): Vector2D = Vector2D(x * scalar, y * scalar)
// TODO: remove
def *(scalar: Double): Vector2D = Vector2D(x * scalar, y * scalar)
def /(scalar: Float): Vector2D = Vector2D(x / scalar, y / scalar)
def snap(v: Float): Vector2D = Vector2D((x / v).floor * v, (y / v).floor * v)
def unary_-(): Vector2D = Vector2D(-x, -y)
def length: Float = math.sqrt(lengthSquared).toFloat
def lengthSquared: Float = this.x * this.x + this.y * this.y
def manhattanLength: Float = this.x.abs + this.y.abs
def normalize: Vector2D = {
val l = this.length
if (l > 0) this / this.length else this
}
def round: Vector2D = Vector2D(x.round, y.round)
def dot(other: Vector2D): Float = x * other.x + y * other.y
def angle: Float = math.atan2(this.y, this.x).toFloat
def angle(that: Vector2D): Float = math.atan2(x * that.y - y * that.x, x * that.x + y * that.y).toFloat
def rotate(angle: Float): Vector2D = {
val (s, c) = (math.sin(angle).toFloat, math.cos(angle).toFloat)
Vector2D(c * x - s * y, s * x + c * y)
}
def normalizeAxisAligned: Vector2D = Vector2D(x.sign, y.sign)
def perpendicularCW: Vector2D = Vector2D(y, -x)
def perpendicularCCW: Vector2D = Vector2D(-y, x)
def abs: Vector2D = Vector2D(x.abs, y.abs)
def min(that: Vector2D): Vector2D = Vector2D(x.min(that.x), y.min(that.y))
def max(that: Vector2D): Vector2D = Vector2D(x.max(that.x), y.max(that.y))
def map(f: (Float, Float) => (Float, Float)): Vector2D = {
val (nx, ny) = f(x, y)
Vector2D(nx, ny)
}
def mapX(f: Float => Float): Vector2D = Vector2D(f(x), y)
def mapY(f: Float => Float): Vector2D = Vector2D(x, f(y))
def setX(nx: Float): Vector2D = Vector2D(nx, y)
def setY(ny: Float): Vector2D = Vector2D(x, ny)
override def toString: String = s"Vector2D [$x, $y]"
}