mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-07 12:21:52 +09:00
765 lines
22 KiB
Kotlin
765 lines
22 KiB
Kotlin
/*
|
|
* Copyright (c) 2010-2015 William Bittle http://www.dyn4j.org/
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
|
* provided that the following conditions are met:
|
|
*
|
|
* * Redistributions of source code must retain the above copyright notice, this list of conditions
|
|
* and the following disclaimer.
|
|
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
|
|
* and the following disclaimer in the documentation and/or other materials provided with the
|
|
* distribution.
|
|
* * Neither the name of dyn4j nor the names of its contributors may be used to endorse or
|
|
* promote products derived from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
|
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
|
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
/*
|
|
* Kotlin translated and modified code Copyright (c) 2016 Minjaesong (CuriousTorvald).
|
|
*/
|
|
package org.dyn4j.geometry
|
|
|
|
import org.dyn4j.Epsilon
|
|
import kotlin.math.sign
|
|
|
|
/**
|
|
* This class represents a vector or point in 2D space.
|
|
*
|
|
*
|
|
* The operations [Vector2.setMagnitude], [Vector2.getNormalized],
|
|
* [Vector2.project], and [Vector2.normalize] require the [Vector2]
|
|
* to be non-zero in length.
|
|
*
|
|
* ===============================================================================
|
|
*
|
|
* In this Kotlin code, you can use regular operators like + - * /.
|
|
*
|
|
* |operator |function |
|
|
* |-----------|---------------------|
|
|
* |a + b |Vector2(a).plus(b) |
|
|
* |a - b |Vector2(a).minus(b) |
|
|
* |a * b |Vector2(a).times(b) |
|
|
* |a / b |Vector2(a).div(b) |
|
|
* |a += b |a.plusAssign(b) |
|
|
* |a -= b |a.minusAssign(b) |
|
|
* |a *= b |a.timesAssign(b) |
|
|
* |a /= b |a.divAssign(b) |
|
|
* |a dot b |Vector2(a).dot(b) |
|
|
* |a cross b |Vector2(a).cross(b) |
|
|
* |!a |this.negative |
|
|
* |a rotate th|Vector2(a).rotate(th)|
|
|
* |a to b |Vector2(a).to(b) |
|
|
*
|
|
* @author William Bittle and Minjaesong (CuriousTorvald)
|
|
* *
|
|
* @version 3.1.11
|
|
* *
|
|
* @since 1.0.0
|
|
*/
|
|
class Vector2 {
|
|
|
|
/** The magnitude of the x component of this [Vector2] */
|
|
var x: Double = 0.0
|
|
|
|
/** The magnitude of the y component of this [Vector2] */
|
|
var y: Double = 0.0
|
|
|
|
/** Default constructor. */
|
|
constructor() {
|
|
}
|
|
|
|
/**
|
|
* Copy constructor.
|
|
* @param vector the [Vector2] to copy from
|
|
*/
|
|
constructor(vector: Vector2) {
|
|
this.x = vector.x
|
|
this.y = vector.y
|
|
}
|
|
|
|
/**
|
|
* Optional constructor.
|
|
* @param x the x component
|
|
* *
|
|
* @param y the y component
|
|
*/
|
|
constructor(x: Double, y: Double) {
|
|
this.x = x
|
|
this.y = y
|
|
}
|
|
|
|
/**
|
|
* Creates a [Vector2] from the first point to the second point.
|
|
* @param x1 the x coordinate of the first point
|
|
* *
|
|
* @param y1 the y coordinate of the first point
|
|
* *
|
|
* @param x2 the x coordinate of the second point
|
|
* *
|
|
* @param y2 the y coordinate of the second point
|
|
*/
|
|
constructor(x1: Double, y1: Double, x2: Double, y2: Double) {
|
|
this.x = x2 - x1
|
|
this.y = y2 - y1
|
|
}
|
|
|
|
/**
|
|
* Creates a [Vector2] from the first point to the second point.
|
|
* @param p1 the first point
|
|
* *
|
|
* @param p2 the second point
|
|
*/
|
|
constructor(p1: Vector2, p2: Vector2) {
|
|
this.x = p2.x - p1.x
|
|
this.y = p2.y - p1.y
|
|
}
|
|
|
|
/**
|
|
* Creates a unit length vector in the given direction.
|
|
* @param direction the direction in radians
|
|
* *
|
|
* @since 3.0.1
|
|
*/
|
|
constructor(direction: Double) {
|
|
this.x = Math.cos(direction)
|
|
this.y = Math.sin(direction)
|
|
}
|
|
|
|
operator fun component1() = x
|
|
operator fun component2() = y
|
|
|
|
/**
|
|
* Returns a copy of this [Vector2].
|
|
* @return [Vector2]
|
|
*/
|
|
fun copy(): Vector2 {
|
|
return Vector2(this.x, this.y)
|
|
}
|
|
|
|
/**
|
|
* Returns the distance from this point to the given point.
|
|
* @param x the x coordinate of the point
|
|
* *
|
|
* @param y the y coordinate of the point
|
|
* *
|
|
* @return double
|
|
*/
|
|
fun distance(x: Double, y: Double): Double {
|
|
//return Math.hypot(this.x - x, this.y - y);
|
|
val dx = this.x - x
|
|
val dy = this.y - y
|
|
return Math.sqrt(dx * dx + dy * dy)
|
|
}
|
|
|
|
/**
|
|
* Returns the distance from this point to the given point.
|
|
* @param point the point
|
|
* *
|
|
* @return double
|
|
*/
|
|
fun distance(point: Vector2): Double {
|
|
//return Math.hypot(this.x - point.x, this.y - point.y);
|
|
val dx = this.x - point.x
|
|
val dy = this.y - point.y
|
|
return Math.sqrt(dx * dx + dy * dy)
|
|
}
|
|
|
|
/**
|
|
* Returns the distance from this point to the given point squared.
|
|
* @param x the x coordinate of the point
|
|
* *
|
|
* @param y the y coordinate of the point
|
|
* *
|
|
* @return double
|
|
*/
|
|
fun distanceSquared(x: Double, y: Double): Double {
|
|
//return (this.x - x) * (this.x - x) + (this.y - y) * (this.y - y);
|
|
val dx = this.x - x
|
|
val dy = this.y - y
|
|
return dx * dx + dy * dy
|
|
}
|
|
|
|
/**
|
|
* Returns the distance from this point to the given point squared.
|
|
* @param point the point
|
|
* *
|
|
* @return double
|
|
*/
|
|
fun distanceSquared(point: Vector2): Double {
|
|
//return (this.x - point.x) * (this.x - point.x) + (this.y - point.y) * (this.y - point.y);
|
|
val dx = this.x - point.x
|
|
val dy = this.y - point.y
|
|
return dx * dx + dy * dy
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see java.lang.Object#hashCode()
|
|
*/
|
|
override fun hashCode(): Int {
|
|
val prime = 31
|
|
var result = 1
|
|
var temp: Long
|
|
temp = java.lang.Double.doubleToLongBits(x)
|
|
result = prime * result + (temp xor temp.ushr(32)).toInt()
|
|
temp = java.lang.Double.doubleToLongBits(y)
|
|
result = prime * result + (temp xor temp.ushr(32)).toInt()
|
|
return result
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see java.lang.Object#equals(java.lang.Object)
|
|
*/
|
|
override fun equals(obj: Any?): Boolean {
|
|
if (obj == null) return false
|
|
if (obj === this) return true
|
|
if (obj is Vector2) {
|
|
return this.x == obj.x && this.y == obj.y
|
|
}
|
|
return false
|
|
}
|
|
|
|
/**
|
|
* Returns true if the x and y components of this [Vector2]
|
|
* are the same as the given [Vector2].
|
|
* @param vector the [Vector2] to compare to
|
|
* *
|
|
* @return boolean
|
|
*/
|
|
fun equals(vector: Vector2?): Boolean {
|
|
if (vector == null) return false
|
|
if (this === vector) {
|
|
return true
|
|
}
|
|
else {
|
|
return this.x == vector.x && this.y == vector.y
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns true if the x and y components of this [Vector2]
|
|
* are the same as the given x and y components.
|
|
* @param x the x coordinate of the [Vector2] to compare to
|
|
* *
|
|
* @param y the y coordinate of the [Vector2] to compare to
|
|
* *
|
|
* @return boolean
|
|
*/
|
|
fun equals(x: Double, y: Double): Boolean {
|
|
return this.x == x && this.y == y
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see java.lang.Object#toString()
|
|
*/
|
|
override fun toString(): String {
|
|
val sb = StringBuilder()
|
|
sb.append("(").append(this.x).append(", ").append(this.y).append(")")
|
|
return sb.toString()
|
|
}
|
|
|
|
/**
|
|
* Sets this [Vector2] to the given [Vector2].
|
|
* @param vector the [Vector2] to set this [Vector2] to
|
|
* *
|
|
* @return [Vector2] this vector
|
|
*/
|
|
fun set(vector: Vector2) {
|
|
this.x = vector.x
|
|
this.y = vector.y
|
|
}
|
|
|
|
/**
|
|
* Sets this [Vector2] to the given [Vector2].
|
|
* @param x the x component of the [Vector2] to set this [Vector2] to
|
|
* *
|
|
* @param y the y component of the [Vector2] to set this [Vector2] to
|
|
* *
|
|
* @return [Vector2] this vector
|
|
*/
|
|
fun set(x: Double, y: Double) {
|
|
this.x = x
|
|
this.y = y
|
|
}
|
|
|
|
fun setPolar(magnitude: Double, direction: Double) {
|
|
this.x = Math.cos(direction) * magnitude
|
|
this.y = Math.sin(direction) * magnitude
|
|
}
|
|
|
|
|
|
/**
|
|
* Returns the x component of this [Vector2].
|
|
* @return [Vector2]
|
|
*/
|
|
val xComponent: Vector2
|
|
get() = Vector2(this.x, 0.0)
|
|
|
|
/**
|
|
* Returns the y component of this [Vector2].
|
|
* @return [Vector2]
|
|
*/
|
|
val yComponent: Vector2
|
|
get() = Vector2(0.0, this.y)
|
|
|
|
/**
|
|
* Returns the magnitude of this [Vector2].
|
|
* @return double
|
|
*/
|
|
// the magnitude is just the pathagorean theorem
|
|
val magnitude: Double
|
|
get() = Math.sqrt(this.x * this.x + this.y * this.y)
|
|
|
|
/**
|
|
* Returns the magnitude of this [Vector2] squared.
|
|
* @return double
|
|
*/
|
|
val magnitudeSquared: Double
|
|
get() = this.x * this.x + this.y * this.y
|
|
|
|
/**
|
|
* Sets the magnitude of the [Vector2].
|
|
* @param magnitude the magnitude
|
|
* *
|
|
* @return [Vector2] this vector
|
|
*/
|
|
fun setMagnitude(magnitude: Double): Vector2 {
|
|
// check the given magnitude
|
|
if (Math.abs(magnitude) <= Epsilon.E) {
|
|
return Vector2(0.0, 0.0)
|
|
}
|
|
// is this vector a zero vector?
|
|
if (this.isZero) {
|
|
return Vector2(0.0, 0.0)
|
|
}
|
|
// get the magnitude
|
|
var mag = Math.sqrt(this.x * this.x + this.y * this.y)
|
|
// normalize and multiply by the new magnitude
|
|
mag = magnitude / mag
|
|
val newX = this.x * mag
|
|
val newY = this.y * mag
|
|
return Vector2(newX, newY)
|
|
}
|
|
|
|
/**
|
|
* Returns the direction of this [Vector2]
|
|
* as an angle in radians.
|
|
* @return double angle in radians [-, ]
|
|
*/
|
|
val direction: Double
|
|
get() = Math.atan2(this.y, this.x)
|
|
|
|
/**
|
|
* Sets the direction of this [Vector2].
|
|
* @param angle angle in radians
|
|
* *
|
|
* @return [Vector2] this vector
|
|
*/
|
|
fun setDirection(angle: Double): Vector2 {
|
|
//double magnitude = Math.hypot(this.x, this.y);
|
|
val magnitude = Math.sqrt(this.x * this.x + this.y * this.y)
|
|
val newX = magnitude * Math.cos(angle)
|
|
val newY = magnitude * Math.sin(angle)
|
|
return Vector2(newX, newY)
|
|
}
|
|
|
|
/**
|
|
* Adds the given [Vector2] to this [Vector2].
|
|
* @param vector the [Vector2]
|
|
* *
|
|
* @return [Vector2] this vector
|
|
*/
|
|
operator fun plus(vector: Vector2?): Vector2 {
|
|
return Vector2(this.x + (vector?.x ?: 0.0), this.y + (vector?.y ?: 0.0))
|
|
}
|
|
|
|
operator fun plusAssign(vector: Vector2) {
|
|
this.x += vector.x
|
|
this.y += vector.y
|
|
}
|
|
|
|
/**
|
|
* Subtracts the given [Vector2] from this [Vector2].
|
|
* @param vector the [Vector2]
|
|
* *
|
|
* @return [Vector2] this vector
|
|
*/
|
|
operator fun minus(vector: Vector2): Vector2 {
|
|
return Vector2(this.x - vector.x, this.y - vector.y)
|
|
}
|
|
|
|
operator fun minusAssign(vector: Vector2) {
|
|
this.x -= vector.x
|
|
this.y -= vector.y
|
|
}
|
|
|
|
/**
|
|
* Creates a [Vector2] from this [Vector2] to the given [Vector2].
|
|
* @param other : the other [Vector2]
|
|
* *
|
|
* @return [Vector2]
|
|
*/
|
|
infix fun to(other: Vector2): Vector2 {
|
|
return Vector2(other.x - this.x, other.y - this.y)
|
|
}
|
|
|
|
/**
|
|
* Get product of this vector.
|
|
* @param scalar the scalar
|
|
* *
|
|
* @return [Vector2] this vector
|
|
*/
|
|
operator fun times(scalar: Double): Vector2 {
|
|
return product(scalar)
|
|
}
|
|
|
|
operator fun timesAssign(scalar: Double) {
|
|
this.x *= scalar
|
|
this.y *= scalar
|
|
}
|
|
|
|
/**
|
|
* Multiplies this [Vector2] by the given scalar.
|
|
* @param scalar the scalar
|
|
* *
|
|
* @return [Vector2] this vector
|
|
*/
|
|
operator fun div(scalar: Double): Vector2 {
|
|
return Vector2(this.x / scalar, this.y / scalar)
|
|
}
|
|
|
|
operator fun divAssign(scalar: Double) {
|
|
this.x /= scalar
|
|
this.y /= scalar
|
|
}
|
|
|
|
/**
|
|
* Multiplies this [Vector2] by the given scalar returning
|
|
* a new [Vector2] containing the result.
|
|
* @param scalar the scalar
|
|
* *
|
|
* @return [Vector2]
|
|
*/
|
|
infix fun product(scalar: Double): Vector2 {
|
|
return Vector2(this.x * scalar, this.y * scalar)
|
|
}
|
|
|
|
/**
|
|
* Returns the dot product of the given [Vector2]
|
|
* and this [Vector2].
|
|
* @param vector the [Vector2]
|
|
* *
|
|
* @return double
|
|
*/
|
|
infix fun dot(vector: Vector2): Double {
|
|
return this.x * vector.x + this.y * vector.y
|
|
}
|
|
|
|
/**
|
|
* Returns the dot product of the given [Vector2]
|
|
* and this [Vector2].
|
|
* @param x the x component of the [Vector2]
|
|
* *
|
|
* @param y the y component of the [Vector2]
|
|
* *
|
|
* @return double
|
|
*/
|
|
fun dot(x: Double, y: Double): Double {
|
|
return this.x * x + this.y * y
|
|
}
|
|
|
|
/**
|
|
* Returns the cross product of the this [Vector2] and the given [Vector2].
|
|
* @param vector the [Vector2]
|
|
* *
|
|
* @return double
|
|
*/
|
|
infix fun cross(vector: Vector2): Double {
|
|
return this.x * vector.y - this.y * vector.x
|
|
}
|
|
|
|
/**
|
|
* Returns the cross product of the this [Vector2] and the given [Vector2].
|
|
* @param x the x component of the [Vector2]
|
|
* *
|
|
* @param y the y component of the [Vector2]
|
|
* *
|
|
* @return double
|
|
*/
|
|
fun cross(x: Double, y: Double): Double {
|
|
return this.x * y - this.y * x
|
|
}
|
|
|
|
/**
|
|
* Returns the cross product of this [Vector2] and the z value of the right [Vector2].
|
|
* @param z the z component of the [Vector2]
|
|
* *
|
|
* @return [Vector2]
|
|
*/
|
|
infix fun cross(z: Double): Vector2 {
|
|
return Vector2(-1.0 * this.y * z, this.x * z)
|
|
}
|
|
|
|
/**
|
|
* Returns true if the given [Vector2] is orthogonal (perpendicular)
|
|
* to this [Vector2].
|
|
*
|
|
*
|
|
* If the dot product of this vector and the given vector is
|
|
* zero then we know that they are perpendicular
|
|
* @param vector the [Vector2]
|
|
* *
|
|
* @return boolean
|
|
*/
|
|
fun isOrthogonal(vector: Vector2): Boolean {
|
|
return if (Math.abs(this.x * vector.x + this.y * vector.y) <= Epsilon.E) true else false
|
|
}
|
|
|
|
/**
|
|
* Returns true if the given [Vector2] is orthogonal (perpendicular)
|
|
* to this [Vector2].
|
|
*
|
|
*
|
|
* If the dot product of this vector and the given vector is
|
|
* zero then we know that they are perpendicular
|
|
* @param x the x component of the [Vector2]
|
|
* *
|
|
* @param y the y component of the [Vector2]
|
|
* *
|
|
* @return boolean
|
|
*/
|
|
fun isOrthogonal(x: Double, y: Double): Boolean {
|
|
return if (Math.abs(this.x * x + this.y * y) <= Epsilon.E) true else false
|
|
}
|
|
|
|
/**
|
|
* Returns true if this [Vector2] is the zero [Vector2].
|
|
* @return boolean
|
|
*/
|
|
val isZero: Boolean
|
|
get() = Math.abs(this.x) <= Epsilon.E && Math.abs(this.y) <= Epsilon.E
|
|
|
|
/**
|
|
* Returns false if this [Vector2] is the zero [Vector2].
|
|
* @return boolean
|
|
*/
|
|
val isNotZero: Boolean
|
|
get() = !isZero
|
|
|
|
/**
|
|
* Negates this [Vector2].
|
|
* @return [Vector2] this vector
|
|
*/
|
|
operator fun not() = this.negative
|
|
|
|
/**
|
|
* Negates this [Vector2].
|
|
* @return [Vector2] this vector
|
|
*/
|
|
operator fun unaryMinus() = this.negative
|
|
|
|
/**
|
|
* Returns a [Vector2] which is the negative of this [Vector2].
|
|
* @return [Vector2]
|
|
*/
|
|
val negative: Vector2
|
|
get() = Vector2(-this.x, -this.y)
|
|
|
|
/**
|
|
* Sets the [Vector2] to the zero [Vector2]
|
|
* @return [Vector2] this vector
|
|
*/
|
|
fun zero() {
|
|
this.x = 0.0
|
|
this.y = 0.0
|
|
}
|
|
|
|
/**
|
|
* Rotates about the origin.
|
|
* @param theta the rotation angle in radians
|
|
* *
|
|
* @return [Vector2] this vector
|
|
*/
|
|
infix fun rotate(theta: Double): Vector2 {
|
|
val cos = Math.cos(theta)
|
|
val sin = Math.sin(theta)
|
|
val x = this.x
|
|
val y = this.y
|
|
val newX = x * cos - y * sin
|
|
val newY = x * sin + y * cos
|
|
return Vector2(newX, newY)
|
|
}
|
|
|
|
/**
|
|
* Projects this [Vector2] onto the given [Vector2].
|
|
* @param vector the [Vector2]
|
|
* *
|
|
* @return [Vector2] the projected [Vector2]
|
|
*/
|
|
fun project(vector: Vector2): Vector2 {
|
|
val dotProd = this.dot(vector)
|
|
var denominator = vector.dot(vector)
|
|
if (denominator <= Epsilon.E) return Vector2()
|
|
denominator = dotProd / denominator
|
|
return Vector2(denominator * vector.x, denominator * vector.y)
|
|
}
|
|
|
|
/**
|
|
* Returns the right-handed normal of this vector.
|
|
* @return [Vector2] the right hand orthogonal [Vector2]
|
|
*/
|
|
val rightHandOrthogonalVector: Vector2
|
|
get() = Vector2(-this.y, this.x)
|
|
|
|
/**
|
|
* Sets this vector to the right-handed normal of this vector.
|
|
* @return [Vector2] this vector
|
|
* *
|
|
* @see .getRightHandOrthogonalVector
|
|
*/
|
|
fun right(): Vector2 {
|
|
val temp = this.x
|
|
val newX = -this.y
|
|
val newY = temp
|
|
return Vector2(newX, newY)
|
|
}
|
|
|
|
/**
|
|
* Returns the left-handed normal of this vector.
|
|
* @return [Vector2] the left hand orthogonal [Vector2]
|
|
*/
|
|
val leftHandOrthogonalVector: Vector2
|
|
get() = Vector2(this.y, -this.x)
|
|
|
|
/**
|
|
* Sets this vector to the left-handed normal of this vector.
|
|
* @return [Vector2] this vector
|
|
* *
|
|
* @see .getLeftHandOrthogonalVector
|
|
*/
|
|
fun left(): Vector2 {
|
|
val temp = this.x
|
|
val newX = this.y
|
|
val newY = -temp
|
|
return Vector2(newX, newY)
|
|
}
|
|
|
|
/**
|
|
* Returns a unit [Vector2] of this [Vector2].
|
|
*
|
|
*
|
|
* This method requires the length of this [Vector2] is not zero.
|
|
* @return [Vector2]
|
|
*/
|
|
val normalized: Vector2
|
|
get() {
|
|
var magnitude = this.magnitude
|
|
if (magnitude <= Epsilon.E) return Vector2()
|
|
magnitude = 1.0 / magnitude
|
|
return Vector2(this.x * magnitude, this.y * magnitude)
|
|
}
|
|
|
|
/**
|
|
* Converts this [Vector2] into a unit [Vector2] and returns
|
|
* the magnitude before normalization.
|
|
*
|
|
*
|
|
* This method requires the length of this [Vector2] is not zero.
|
|
* @return double
|
|
*/
|
|
fun normalize(): Double {
|
|
val magnitude = Math.sqrt(this.x * this.x + this.y * this.y)
|
|
if (magnitude <= Epsilon.E) return 0.0
|
|
val m = 1.0 / magnitude
|
|
this.x *= m
|
|
this.y *= m
|
|
//return 1.0 / m;
|
|
return magnitude
|
|
}
|
|
|
|
/**
|
|
* Returns the smallest angle between the given [Vector2]s.
|
|
*
|
|
*
|
|
* Returns the angle in radians in the range - to .
|
|
* @param vector the [Vector2]
|
|
* *
|
|
* @return angle in radians [-, ]
|
|
*/
|
|
fun getAngleBetween(vector: Vector2): Double {
|
|
val a = Math.atan2(vector.y, vector.x) - Math.atan2(this.y, this.x)
|
|
if (a > Math.PI) return a - 2.0 * Math.PI
|
|
if (a < -Math.PI) return a + 2.0 * Math.PI
|
|
return a
|
|
}
|
|
|
|
val signum: Vector2
|
|
get() = Vector2(this.x.sign, this.y.sign)
|
|
|
|
companion object {
|
|
/** A vector representing the x-axis; this vector should not be changed at runtime; used internally */
|
|
internal val X_AXIS = Vector2(1.0, 0.0)
|
|
|
|
/** A vector representing the y-axis; this vector should not be changed at runtime; used internally */
|
|
internal val Y_AXIS = Vector2(0.0, 1.0)
|
|
|
|
/**
|
|
* Returns a new [Vector2] given the magnitude and direction.
|
|
* @param magnitude the magnitude of the [Vector2]
|
|
* *
|
|
* @param direction the direction of the [Vector2] in radians
|
|
* *
|
|
* @return [Vector2]
|
|
*/
|
|
fun create(magnitude: Double, direction: Double): Vector2 {
|
|
val x = magnitude * Math.cos(direction)
|
|
val y = magnitude * Math.sin(direction)
|
|
return Vector2(x, y)
|
|
}
|
|
|
|
/**
|
|
* The triple product of [Vector2]s is defined as:
|
|
*
|
|
* a x (b x c)
|
|
*
|
|
* However, this method performs the following triple product:
|
|
*
|
|
* (a x b) x c
|
|
*
|
|
* this can be simplified to:
|
|
*
|
|
* -a * (b c) + b * (a c)
|
|
*
|
|
* or:
|
|
*
|
|
* b * (a c) - a * (b c)
|
|
*
|
|
* @param a the a [Vector2] in the above equation
|
|
* *
|
|
* @param b the b [Vector2] in the above equation
|
|
* *
|
|
* @param c the c [Vector2] in the above equation
|
|
* *
|
|
* @return [Vector2]
|
|
*/
|
|
fun tripleProduct(a: Vector2, b: Vector2, c: Vector2): Vector2 {
|
|
// expanded version of above formula
|
|
val r = Vector2()
|
|
// perform a.dot(c)
|
|
val ac = a.x * c.x + a.y * c.y
|
|
// perform b.dot(c)
|
|
val bc = b.x * c.x + b.y * c.y
|
|
// perform b * a.dot(c) - a * b.dot(c)
|
|
r.x = b.x * ac - a.x * bc
|
|
r.y = b.y * ac - a.y * bc
|
|
return r
|
|
}
|
|
}
|
|
} |