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]" }