-
-
Notifications
You must be signed in to change notification settings - Fork 71
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #161 from jcornaz/feature/immutable-vectors
Immutable Vector 2D. #152
- Loading branch information
Showing
6 changed files
with
1,958 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
dependencies { | ||
provided "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion" | ||
|
||
testCompile "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,208 @@ | ||
@file:Suppress("NOTHING_TO_INLINE") | ||
|
||
package ktx.math | ||
|
||
import com.badlogic.gdx.math.Interpolation | ||
import com.badlogic.gdx.math.MathUtils | ||
import com.badlogic.gdx.math.Vector | ||
import java.util.* | ||
import kotlin.math.abs | ||
import kotlin.math.sqrt | ||
|
||
/** | ||
* Represent an immutable vector. | ||
* | ||
* This is the root interface of immutable alternatives to the default mutable vectors provided by LibDGX | ||
*/ | ||
interface ImmutableVector<T : ImmutableVector<T>> : Comparable<T> { | ||
|
||
/** | ||
* Returns the squared euclidean length | ||
* | ||
* This method is faster than [Vector.len] because it avoids calculating a square root. It is useful for comparisons, | ||
* but not for getting exact lengths, as the return value is the square of the actual length. | ||
*/ | ||
val len2: Float | ||
|
||
/** Returns the euclidean length */ | ||
val len: Float get() = sqrt(len2) | ||
|
||
/** | ||
* Returns the unit vector of same direction or this vector if it is zero. | ||
*/ | ||
val nor: T | ||
|
||
/** Returns whether the length of this vector is smaller than the given [margin] */ | ||
fun isZero(margin: Float = MathUtils.FLOAT_ROUNDING_ERROR): Boolean | ||
|
||
/** Returns whether this vector is a unit length vector within the given [margin]. (no margin by default) */ | ||
fun isUnit(margin: Float = MathUtils.FLOAT_ROUNDING_ERROR): Boolean = abs(1f - len2) < margin | ||
|
||
/** Returns the opposite vector of same length */ | ||
operator fun unaryMinus(): T | ||
|
||
/** Returns the result of subtracting the [other] vector from this vector */ | ||
operator fun minus(other: T): T | ||
|
||
/** Returns the result of adding the [other] vector to this vector */ | ||
operator fun plus(other: T): T | ||
|
||
/** Returns a new vector instance with all members incremented by 1 */ | ||
operator fun inc(): T | ||
|
||
/** Returns a new vector instance with all members decremented by 1 */ | ||
operator fun dec(): T | ||
|
||
/** Returns a new vector instance scaled by the given [scalar] */ | ||
operator fun times(scalar: Float): T | ||
|
||
/** Returns a new vector instance scaled by the given [vector] */ | ||
operator fun times(vector: T): T | ||
|
||
/** Returns a vector of the same direction and a squared length of [length2] */ | ||
fun withLength2(length2: Float): T | ||
|
||
/** Returns the dot product of this vector by the given [vector] */ | ||
infix fun dot(vector: T): Float | ||
|
||
/** | ||
* Returns the squared distance between this and the other [vector] | ||
* | ||
* This method is faster than [dst] because it avoids calculating a square root. It is useful for comparisons, | ||
* but not for getting exact distance, as the return value is the square of the actual distance. | ||
*/ | ||
infix fun dst2(vector: T): Float | ||
|
||
/** Linearly interpolates between this vector and the [target] vector by [alpha] */ | ||
fun withLerp(target: T, alpha: Float): T | ||
|
||
/** | ||
* Returns a vector of same length and a random direction. | ||
* | ||
* @param rng Random number generator to use ([MathUtils.random] by default) | ||
*/ | ||
fun withRandomDirection(rng: Random = MathUtils.random): T | ||
|
||
/** Returns a vector of same direction and the given [length] */ | ||
fun withLength(length: Float): T = withLength2(length * length) | ||
|
||
/** Returns this vector if the [ImmutableVector.len] is <= [limit] or a vector with the same direction and length [limit] otherwise */ | ||
fun withLimit(limit: Float): T = withLimit2(limit * limit) | ||
|
||
/** Returns this vector if the [ImmutableVector.len2] is <= [limit2] or a vector with the same direction and length [limit2] otherwise */ | ||
fun withLimit2(limit2: Float): T | ||
|
||
/** Returns a vector of same direction and the length clamped between [min] and [max] */ | ||
fun withClamp(min: Float, max: Float): T = withClamp2(min * min, max * max) | ||
|
||
/** Returns a vector of same direction and the squared length clamped between [min2] and [max2] */ | ||
fun withClamp2(min2: Float, max2: Float): T | ||
|
||
/** Returns the result of interpolation between this vector and the given [target] vector by [alpha] (within range [0,1]) using the given [interpolation] method. */ | ||
fun withInterpolation(target: T, alpha: Float, interpolation: Interpolation): T = | ||
withLerp(target, interpolation.apply(alpha)) | ||
|
||
/** | ||
* Returns true if this vector is on-line with the [other] vector (either in the same or the opposite direction) | ||
* | ||
* @param epsilon Acceptable margin. | ||
*/ | ||
fun isOnLine(other: T, epsilon: Float = MathUtils.FLOAT_ROUNDING_ERROR): Boolean | ||
|
||
/** | ||
* Compares this vector with the [other] vector, using the supplied [epsilon] for fuzzy equality testing | ||
* | ||
* @param epsilon Acceptable difference for members. A small value makes equality it stricter, while a big value makes equality fuzzier. | ||
*/ | ||
fun epsilonEquals(other: T, epsilon: Float): Boolean | ||
|
||
override fun compareTo(other: T): Int = len2.compareTo(other.len2) | ||
|
||
@Deprecated(MUTABLE_METHOD_DEPRECATION_MESSAGE, ReplaceWith("withLerp(target, alpha)"), DeprecationLevel.ERROR) | ||
fun lerp(target: T, alpha: Float): T = withLerp(target, alpha) | ||
|
||
@Deprecated(MUTABLE_METHOD_DEPRECATION_MESSAGE, ReplaceWith("withLength2(len2)"), DeprecationLevel.ERROR) | ||
fun setLength2(len2: Float): T = withLength2(len2) | ||
|
||
@Deprecated(MUTABLE_METHOD_DEPRECATION_MESSAGE, ReplaceWith("this * scalar"), DeprecationLevel.ERROR) | ||
fun scl(scalar: Float): T = this * scalar | ||
|
||
@Deprecated(MUTABLE_METHOD_DEPRECATION_MESSAGE, ReplaceWith("this * v"), DeprecationLevel.ERROR) | ||
fun scl(v: T): T = this * v | ||
|
||
@Deprecated(MUTABLE_METHOD_DEPRECATION_MESSAGE, ReplaceWith("this + v"), DeprecationLevel.ERROR) | ||
fun add(v: T): T = this + v | ||
|
||
@Deprecated(MUTABLE_METHOD_DEPRECATION_MESSAGE, ReplaceWith("withRandomDirection()"), DeprecationLevel.ERROR) | ||
fun setToRandomDirection(): T = withRandomDirection() | ||
|
||
@Deprecated(MUTABLE_METHOD_DEPRECATION_MESSAGE, ReplaceWith("this + (v * scalar)"), DeprecationLevel.ERROR) | ||
fun mulAdd(v: T, scalar: Float): T = this + (v * scalar) | ||
|
||
@Deprecated(MUTABLE_METHOD_DEPRECATION_MESSAGE, ReplaceWith("this + (v * mulVec)"), DeprecationLevel.ERROR) | ||
fun mulAdd(v: T, mulVec: T): T = this + (v * mulVec) | ||
|
||
@Deprecated(MUTABLE_METHOD_DEPRECATION_MESSAGE, ReplaceWith("withLimit(limit)"), DeprecationLevel.ERROR) | ||
fun limit(limit: Float): T = withLimit(limit) | ||
|
||
@Deprecated(MUTABLE_METHOD_DEPRECATION_MESSAGE, ReplaceWith("withClamp(min, max)"), DeprecationLevel.ERROR) | ||
fun clamp(min: Float, max: Float): T = withClamp(min, max) | ||
|
||
@Deprecated(MUTABLE_METHOD_DEPRECATION_MESSAGE, ReplaceWith("v"), DeprecationLevel.ERROR) | ||
fun set(v: T): T = v | ||
|
||
@Deprecated(MUTABLE_METHOD_DEPRECATION_MESSAGE, ReplaceWith("withInterpolation(target, alpha, interpolator)"), DeprecationLevel.ERROR) | ||
fun interpolate(target: T, alpha: Float, interpolator: Interpolation): T = withInterpolation(target, alpha, interpolator) | ||
|
||
@Deprecated(MUTABLE_METHOD_DEPRECATION_MESSAGE, ReplaceWith("withLength(len)"), DeprecationLevel.ERROR) | ||
fun setLength(len: Float): T = withLength(len) | ||
|
||
@Deprecated(MUTABLE_METHOD_DEPRECATION_MESSAGE, ReplaceWith("withLimit2(limit2)"), DeprecationLevel.ERROR) | ||
fun limit2(limit2: Float): T = withLimit2(limit2) | ||
|
||
@Deprecated(MUTABLE_METHOD_DEPRECATION_MESSAGE, ReplaceWith("this - v"), DeprecationLevel.ERROR) | ||
fun sub(v: T): T = this - v | ||
|
||
@Deprecated(MUTABLE_METHOD_DEPRECATION_MESSAGE, ReplaceWith("nor"), DeprecationLevel.ERROR) | ||
fun nor(): T = nor | ||
} | ||
|
||
/** Returns the distance between this and the [other] vector */ | ||
inline infix fun <T : ImmutableVector<T>> T.dst(other: T): Float = sqrt(dst2(other)) | ||
|
||
/** Returns this vector scaled by (1 / [scalar]) */ | ||
inline operator fun <T : ImmutableVector<T>> T.div(scalar: Float): T = times(1 / scalar) | ||
|
||
/** | ||
* Returns true if this vector is collinear with the [other] vector | ||
* | ||
* @param epsilon Acceptable margin. | ||
*/ | ||
fun <T : ImmutableVector<T>> T.isCollinear(other: T, epsilon: Float = MathUtils.FLOAT_ROUNDING_ERROR): Boolean = | ||
isOnLine(other, epsilon) && hasSameDirection(other) | ||
|
||
/** | ||
* Returns true if this vector is opposite collinear with the [other] vector | ||
* | ||
* @param epsilon Acceptable margin. | ||
*/ | ||
fun <T : ImmutableVector<T>> T.isCollinearOpposite(other: T, epsilon: Float = MathUtils.FLOAT_ROUNDING_ERROR): Boolean = | ||
isOnLine(other, epsilon) && hasOppositeDirection(other) | ||
|
||
/** | ||
* Returns true if this vector is opposite perpendicular with the [other] vector | ||
* | ||
* @param epsilon Acceptable margin. | ||
*/ | ||
fun <T : ImmutableVector<T>> T.isPerpendicular(other: T, epsilon: Float = MathUtils.FLOAT_ROUNDING_ERROR): Boolean = | ||
MathUtils.isZero(dot(other), epsilon) | ||
|
||
/** Returns whether this vector has similar direction compared to the [other] vector. */ | ||
fun <T : ImmutableVector<T>> T.hasSameDirection(other: T): Boolean = | ||
dot(other) > 0f | ||
|
||
/** Returns whether this vector has opposite direction compared to the [other] vector. */ | ||
fun <T : ImmutableVector<T>> T.hasOppositeDirection(other: T): Boolean = | ||
dot(other) < 0f | ||
|
||
internal const val MUTABLE_METHOD_DEPRECATION_MESSAGE = "Unlike its equivalent in LibGDX, this function does not change the internal state of the vector and returns a new instance instead. This might break existing code designed with mutable vectors in mind." |
Oops, something went wrong.