Skip to content

Commit

Permalink
!refactor: Points are now immutable with operator functions, add a lo…
Browse files Browse the repository at this point in the history
…t of useful functions on Point & ObservablePoint.
  • Loading branch information
Ayfri committed Aug 31, 2022
1 parent 639a370 commit b19b0b1
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 80 deletions.
81 changes: 1 addition & 80 deletions pixi/src/main/kotlin/pixi/externals/extensions/_IPointData.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@ import pixi.typings.math.IPointData
import pixi.typings.math.ObservablePoint
import pixi.typings.math.Point
import kotlin.math.abs
import kotlin.math.ceil
import kotlin.math.floor
import kotlin.math.roundToInt
import kotlin.math.sqrt

val IPointData.length get() = sqrt(x * x + y * y)
Expand All @@ -31,66 +28,6 @@ operator fun <T : IPointData> T.unaryPlus(): T {
return this
}

operator fun <T : IPointData> T.plus(other: IPointData): T {
x += other.x
y += other.y
return this
}

operator fun <T : IPointData> T.plus(factor: Number): T {
x += factor.toDouble()
y += factor.toDouble()
return this
}

operator fun <T : IPointData> T.minus(other: IPointData): T {
x -= other.x
y -= other.y
return this
}

operator fun <T : IPointData> T.minus(factor: Number): T {
x -= factor.toDouble()
y -= factor.toDouble()
return this
}

operator fun <T : IPointData> T.times(other: IPointData): T {
x *= other.x
y *= other.y
return this
}

operator fun <T : IPointData> T.times(factor: Number): T {
x *= factor.toDouble()
y *= factor.toDouble()
return this
}

operator fun <T : IPointData> T.div(other: IPointData): T {
x /= other.x
y /= other.y
return this
}

operator fun <T : IPointData> T.div(factor: Number): T {
x /= factor.toDouble()
y /= factor.toDouble()
return this
}

operator fun <T : IPointData> T.rem(other: IPointData): T {
x %= other.x
y %= other.y
return this
}

operator fun <T : IPointData> T.rem(factor: Number): T {
x %= factor.toDouble()
y %= factor.toDouble()
return this
}

operator fun <T : IPointData> T.compareTo(other: IPointData) = squaredLength.compareTo(other.squaredLength)

operator fun <T : IPointData> T.rangeTo(other: IPointData) = Rectangle(this, other)
Expand All @@ -109,23 +46,12 @@ operator fun <T : IPointData> T.set(index: Int, value: Number) {
}
}


fun <T : IPointData> T.abs() = +this

fun IPointData.ceil() {
x = ceil(x)
y = ceil(y)
}

infix fun IPointData.distanceTo(other: IPointData) = sqrt((x - other.x) * (x - other.x) + (y - other.y) * (y - other.y))

infix fun IPointData.dot(other: IPointData) = x * other.x + y * other.y

fun IPointData.floor() {
x = floor(x)
y = floor(y)
}

fun <T : IPointData> T.negate() = -this

fun <T : IPointData> T.normalize(): T {
Expand All @@ -142,11 +68,6 @@ fun IPointData.reset() {
y = 0.0
}

fun IPointData.round() {
x = x.roundToInt().toDouble()
y = y.roundToInt().toDouble()
}

fun <T : Any> IPointData.toObservable(context: T.() -> Unit = {}, scope: T? = null) = ObservablePoint(context, scope ?: null.asDynamic(), x, y)
fun <T : Any> IPointData.toObservable(context: T.() -> Unit = {}, scope: T? = null) = ObservablePoint(context, scope ?: null.unsafeCast<T>(), x, y)
fun IPointData.toObservable() = ObservablePoint({}, null.asDynamic(), x, y)
fun IPointData.toPoint() = Point(x, y)
41 changes: 41 additions & 0 deletions pixi/src/main/kotlin/pixi/externals/extensions/_ObservablePoint.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package pixi.externals.extensions

import pixi.typings.math.IPointData
import pixi.typings.math.ObservablePoint
import kotlin.math.ceil
import kotlin.math.floor
import kotlin.math.roundToInt

operator fun <T> ObservablePoint<T>.plus(other: IPointData) = clone().set(x + other.x, y + other.y)
operator fun <T> ObservablePoint<T>.plus(factor: Number) = clone().set(x + factor.unsafeCast<Double>(), y + factor.unsafeCast<Double>())

operator fun <T> ObservablePoint<T>.minus(other: IPointData) = clone().set(x - other.x, y - other.y)
operator fun <T> ObservablePoint<T>.minus(factor: Number) = clone().set(x - factor.unsafeCast<Double>(), y - factor.unsafeCast<Double>())

operator fun <T> ObservablePoint<T>.times(other: IPointData) = clone().set(x * other.x, y * other.y)
operator fun <T> ObservablePoint<T>.times(factor: Number) = clone().set(x * factor.unsafeCast<Double>(), y * factor.unsafeCast<Double>())

operator fun <T> ObservablePoint<T>.div(other: IPointData) = clone().set(x / other.x, y / other.y)
operator fun <T> ObservablePoint<T>.div(factor: Number) = clone().set(x / factor.unsafeCast<Double>(), y / factor.unsafeCast<Double>())

operator fun <T> ObservablePoint<T>.rem(other: IPointData) = clone().set(x % other.x, y % other.y)
operator fun <T> ObservablePoint<T>.rem(factor: Number) = clone().set(x % factor.unsafeCast<Double>(), y % factor.unsafeCast<Double>())

fun <T> ObservablePoint<T>.floored() = clone().set(floor(x), floor(y))
fun <T> ObservablePoint<T>.ceiled() = clone().set(ceil(x), ceil(y))
fun <T> ObservablePoint<T>.rounded() = clone().set(x.roundToInt().unsafeCast<Double>(), y.roundToInt().unsafeCast<Double>())


fun <T> ObservablePoint<T>.max(vararg points: IPointData) = clone().set(maxOf(x, *points.map { it.x }.toDoubleArray()), maxOf(y, *points.map { it.y }.toDoubleArray()))
fun <T> ObservablePoint<T>.min(vararg points: IPointData) = clone().set(minOf(x, *points.map { it.x }.toDoubleArray()), minOf(y, *points.map { it.y }.toDoubleArray()))
fun <T> ObservablePoint<T>.clamp(min: Number, max: Number) = clone().set(x.coerceIn(min.unsafeCast<Double>(), max.unsafeCast<Double>()), y.coerceIn(min.unsafeCast<Double>(), max.unsafeCast<Double>()))
fun <T> ObservablePoint<T>.clamp(min: IPointData, max: IPointData) = clone().set(x.coerceIn(min.x, max.x), y.coerceIn(min.y, max.y))

fun <T> ObservablePoint<T>.middle(other: IPointData) = clone().set(x + (other.x - x) / 2, y + (other.y - y) / 2)

fun <T> ObservablePoint<T>.normalize(): ObservablePoint<T> {
val len = length

return if (len != 0.0) clone().set(x / len, y / len)
else clone().set(0.0, 0.0)
}
40 changes: 40 additions & 0 deletions pixi/src/main/kotlin/pixi/externals/extensions/_Point.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package pixi.externals.extensions

import pixi.typings.math.IPointData
import pixi.typings.math.Point
import kotlin.math.ceil
import kotlin.math.floor
import kotlin.math.roundToInt

operator fun Point.plus(other: IPointData) = Point(x + other.x, y + other.y)
operator fun Point.plus(factor: Number) = Point(x + factor.unsafeCast<Double>(), y + factor.unsafeCast<Double>())

operator fun Point.minus(other: IPointData) = Point(x - other.x, y - other.y)
operator fun Point.minus(factor: Number) = Point(x - factor.unsafeCast<Double>(), y - factor.unsafeCast<Double>())

operator fun Point.times(other: IPointData) = Point(x * other.x, y * other.y)
operator fun Point.times(factor: Number) = Point(x * factor.unsafeCast<Double>(), y * factor.unsafeCast<Double>())

operator fun Point.div(other: IPointData) = Point(x / other.x, y / other.y)
operator fun Point.div(factor: Number) = Point(x / factor.unsafeCast<Double>(), y / factor.unsafeCast<Double>())

operator fun Point.rem(other: IPointData) = Point(x % other.x, y % other.y)
operator fun Point.rem(factor: Number) = Point(x % factor.unsafeCast<Double>(), y % factor.unsafeCast<Double>())

fun Point.floored() = Point(floor(x), floor(y))
fun Point.ceiled() = Point(ceil(x), ceil(y))
fun Point.rounded() = Point(x.roundToInt().unsafeCast<Double>(), y.roundToInt().unsafeCast<Double>())

fun Point.max(vararg points: IPointData) = Point(maxOf(x, *points.map { it.x }.toDoubleArray()), maxOf(y, *points.map { it.y }.toDoubleArray()))
fun Point.min(vararg points: IPointData) = Point(minOf(x, *points.map { it.x }.toDoubleArray()), minOf(y, *points.map { it.y }.toDoubleArray()))
fun Point.clamp(min: Number, max: Number) = Point(x.coerceIn(min.unsafeCast<Double>(), max.unsafeCast<Double>()), y.coerceIn(min.unsafeCast<Double>(), max.unsafeCast<Double>()))
fun Point.clamp(min: IPointData, max: IPointData) = Point(x.coerceIn(min.x, max.x), y.coerceIn(min.y, max.y))

fun Point.middle(other: IPointData) = Point((x + other.x) / 2, (y + other.y) / 2)

fun Point.normalize(): Point {
val len = length

return if (len != 0.0) Point(x / len, y / len)
else Point(0.0, 0.0)
}

0 comments on commit b19b0b1

Please sign in to comment.