From f3050736bebb04cac75c952696d68fa97ef38e1a Mon Sep 17 00:00:00 2001 From: Song Minjae Date: Sun, 1 May 2016 20:05:39 +0900 Subject: [PATCH] ball, raw injector float -> double Former-commit-id: 19e44a1a5400bcf423a9cbb0c076eda48a1313d8 Former-commit-id: 73b3c09b0949f7b463de45b7f436b986445554f6 --- .../terrarum/gameactors/ActorWithBody.kt | 3 +- .../gameactors/CreatureRawInjector.kt | 28 +- .../terrarum/gameactors/PhysTestBall.kt | 2 +- src/org/dyn4j/geometry/Vector2.java | 766 ---------------- src/org/dyn4j/geometry/Vector2.kt | 860 ++++++++++++++++++ 5 files changed, 877 insertions(+), 782 deletions(-) delete mode 100644 src/org/dyn4j/geometry/Vector2.java create mode 100644 src/org/dyn4j/geometry/Vector2.kt diff --git a/src/net/torvald/terrarum/gameactors/ActorWithBody.kt b/src/net/torvald/terrarum/gameactors/ActorWithBody.kt index 516ef959d..a3680eba4 100644 --- a/src/net/torvald/terrarum/gameactors/ActorWithBody.kt +++ b/src/net/torvald/terrarum/gameactors/ActorWithBody.kt @@ -71,8 +71,9 @@ open class ActorWithBody constructor() : Actor(), Visible { var scale: Double get() = actorValue.getAsDouble(AVKey.SCALE) ?: 1.0 set(value) = actorValue.set(AVKey.SCALE, value) - val mass: Double + var mass: Double get() = actorValue.getAsDouble(AVKey.BASEMASS) ?: MASS_DEFAULT * Math.pow(scale, 3.0) + set(value) = actorValue.set(AVKey.BASEMASS, value) @Transient private val MASS_LOWEST = 2.0 /** Valid range: [0, 1] */ var elasticity = 0.0 diff --git a/src/net/torvald/terrarum/gameactors/CreatureRawInjector.kt b/src/net/torvald/terrarum/gameactors/CreatureRawInjector.kt index c2d95276c..ebdbff12d 100644 --- a/src/net/torvald/terrarum/gameactors/CreatureRawInjector.kt +++ b/src/net/torvald/terrarum/gameactors/CreatureRawInjector.kt @@ -27,19 +27,19 @@ object CreatureRawInjector { val jsonObj = JsonFetcher.readJson(JSONPATH + jsonFileName) val elementsString = arrayOf(AVKey.RACENAME, AVKey.RACENAMEPLURAL) - val elementsFloat = arrayOf(AVKey.BASEHEIGHT, AVKey.BASEMASS, AVKey.ACCEL, AVKey.TOOLSIZE, AVKey.ENCUMBRANCE) - val elementsFloatVariable = arrayOf(AVKey.STRENGTH, AVKey.SPEED, AVKey.JUMPPOWER, AVKey.SCALE, AVKey.SPEED) + val elementsDouble = arrayOf(AVKey.BASEHEIGHT, AVKey.BASEMASS, AVKey.ACCEL, AVKey.TOOLSIZE, AVKey.ENCUMBRANCE) + val elementsDoubleVariable = arrayOf(AVKey.STRENGTH, AVKey.SPEED, AVKey.JUMPPOWER, AVKey.SCALE, AVKey.SPEED) val elementsBoolean = arrayOf(AVKey.INTELLIGENT) // val elementsMultiplyFromOne = arrayOf() setAVStrings(actorValueRef, elementsString, jsonObj) - setAVFloats(actorValueRef, elementsFloat, jsonObj) - setAVFloatsVariable(actorValueRef, elementsFloatVariable, jsonObj) + setAVDoubles(actorValueRef, elementsDouble, jsonObj) + setAVDoublesVariable(actorValueRef, elementsDoubleVariable, jsonObj) // setAVMultiplyFromOne(actorValueRef, elementsMultiplyFromOne, jsonObj) setAVBooleans(actorValueRef, elementsBoolean, jsonObj) actorValueRef[AVKey.ACCEL] = Player.WALK_ACCEL_BASE - actorValueRef[AVKey.ACCELMULT] = 1f + actorValueRef[AVKey.ACCELMULT] = 1.0 } /** @@ -50,17 +50,17 @@ object CreatureRawInjector { * * * @param jsonObject */ - private fun setAVFloatsVariable(avRef: ActorValue, elemSet: Array, jsonObject: JsonObject) { + private fun setAVDoublesVariable(avRef: ActorValue, elemSet: Array, jsonObject: JsonObject) { for (s in elemSet) { - val baseValue = jsonObject.get(s).asFloat + val baseValue = jsonObject.get(s).asDouble // roll fudge dice and get value [-3, 3] as [0, 6] val varSelected = Fudge3(SecureRandom()).rollForArray() // get multiplier from json. Assuming percentile val multiplier = jsonObject.get(s + MULTIPLIER_RAW_ELEM_SUFFIX).asJsonArray.get(varSelected).asInt - val realValue = baseValue * multiplier / 100f + val realValue = baseValue * multiplier / 100.0 avRef[s] = realValue - avRef[s + MULTIPLIER_RAW_ELEM_SUFFIX] = 1.0f // use multiplied value as 'base' for all sort of things + avRef[s + MULTIPLIER_RAW_ELEM_SUFFIX] = 1.0 // use multiplied value as 'base' for all sort of things } } @@ -80,16 +80,16 @@ object CreatureRawInjector { } /** - * Fetch and set float actor values + * Fetch and set double actor values * @param avRef * * * @param elemSet * * * @param jsonObject */ - private fun setAVFloats(avRef: ActorValue, elemSet: Array, jsonObject: JsonObject) { + private fun setAVDoubles(avRef: ActorValue, elemSet: Array, jsonObject: JsonObject) { for (s in elemSet) { - avRef[s] = jsonObject.get(s).asFloat + avRef[s] = jsonObject.get(s).asDouble } } @@ -104,12 +104,12 @@ object CreatureRawInjector { */ private fun setAVMultiplyFromOne(avRef: ActorValue, elemSet: Array, jsonObject: JsonObject) { for (s in elemSet) { - val baseValue = 1f + val baseValue = 1.0 // roll fudge dice and get value [-3, 3] as [0, 6] val varSelected = Fudge3(SecureRandom()).rollForArray() // get multiplier from json. Assuming percentile val multiplier = jsonObject.get(s).asJsonArray.get(varSelected).asInt - val realValue = baseValue * multiplier / 100f + val realValue = baseValue * multiplier / 100.0 avRef[s] = realValue } diff --git a/src/net/torvald/terrarum/gameactors/PhysTestBall.kt b/src/net/torvald/terrarum/gameactors/PhysTestBall.kt index 8353fd6f9..6faec5c35 100644 --- a/src/net/torvald/terrarum/gameactors/PhysTestBall.kt +++ b/src/net/torvald/terrarum/gameactors/PhysTestBall.kt @@ -15,7 +15,7 @@ class PhysTestBall : ActorWithBody { constructor(): super() { setHitboxDimension(16, 16, 0, 0) isVisible = true - actorValue[AVKey.BASEMASS] = 10f + actorValue[AVKey.BASEMASS] = 10.0 color = RoguelikeRandomiser.composeColourFrom(RoguelikeRandomiser.POTION_PRIMARY_COLSET) } diff --git a/src/org/dyn4j/geometry/Vector2.java b/src/org/dyn4j/geometry/Vector2.java deleted file mode 100644 index 721b83cbb..000000000 --- a/src/org/dyn4j/geometry/Vector2.java +++ /dev/null @@ -1,766 +0,0 @@ -/* - * 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. - */ -package org.dyn4j.geometry; - -import org.dyn4j.Epsilon; - -/** - * This class represents a vector or point in 2D space. - *

- * The operations {@link Vector2#setMagnitude(double)}, {@link Vector2#getNormalized()}, - * {@link Vector2#project(Vector2)}, and {@link Vector2#normalize()} require the {@link Vector2} - * to be non-zero in length. - *

- * Some methods also return the vector to facilitate chaining. For example: - *

- * Vector a = new Vector();
- * a.zero().add(1, 2).multiply(2);
- * 
- * @author William Bittle - * @version 3.1.11 - * @since 1.0.0 - */ -public class Vector2 { - /** A vector representing the x-axis; this vector should not be changed at runtime; used internally */ - static final Vector2 X_AXIS = new Vector2(1.0, 0.0); - - /** A vector representing the y-axis; this vector should not be changed at runtime; used internally */ - static final Vector2 Y_AXIS = new Vector2(0.0, 1.0); - - /** The magnitude of the x component of this {@link Vector2} */ - public double x; - - /** The magnitude of the y component of this {@link Vector2} */ - public double y; - - /** Default constructor. */ - public Vector2() {} - - /** - * Copy constructor. - * @param vector the {@link Vector2} to copy from - */ - public Vector2(Vector2 vector) { - this.x = vector.x; - this.y = vector.y; - } - - /** - * Optional constructor. - * @param x the x component - * @param y the y component - */ - public Vector2(double x, double y) { - this.x = x; - this.y = y; - } - - /** - * Creates a {@link 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 - */ - public Vector2(double x1, double y1, double x2, double y2) { - this.x = x2 - x1; - this.y = y2 - y1; - } - - /** - * Creates a {@link Vector2} from the first point to the second point. - * @param p1 the first point - * @param p2 the second point - */ - public Vector2(Vector2 p1, Vector2 p2) { - 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 - */ - public Vector2(double direction) { - this.x = Math.cos(direction); - this.y = Math.sin(direction); - } - - /** - * Returns a new {@link Vector2} given the magnitude and direction. - * @param magnitude the magnitude of the {@link Vector2} - * @param direction the direction of the {@link Vector2} in radians - * @return {@link Vector2} - */ - public static Vector2 create(double magnitude, double direction) { - double x = magnitude * Math.cos(direction); - double y = magnitude * Math.sin(direction); - return new Vector2(x, y); - } - - /** - * Returns a copy of this {@link Vector2}. - * @return {@link Vector2} - */ - public Vector2 copy() { - return new 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 - */ - public double distance(double x, double y) { - //return Math.hypot(this.x - x, this.y - y); - double dx = this.x - x; - double 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 - */ - public double distance(Vector2 point) { - //return Math.hypot(this.x - point.x, this.y - point.y); - double dx = this.x - point.x; - double 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 - */ - public double distanceSquared(double x, double y) { - //return (this.x - x) * (this.x - x) + (this.y - y) * (this.y - y); - double dx = this.x - x; - double 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 - */ - public double distanceSquared(Vector2 point) { - //return (this.x - point.x) * (this.x - point.x) + (this.y - point.y) * (this.y - point.y); - double dx = this.x - point.x; - double dy = this.y - point.y; - return dx * dx + dy * dy; - } - - /** - * The triple product of {@link 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 {@link Vector2} in the above equation - * @param b the b {@link Vector2} in the above equation - * @param c the c {@link Vector2} in the above equation - * @return {@link Vector2} - */ - public static Vector2 tripleProduct(Vector2 a, Vector2 b, Vector2 c) { - // expanded version of above formula - Vector2 r = new Vector2(); - // perform a.dot(c) - double ac = a.x * c.x + a.y * c.y; - // perform b.dot(c) - double 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; - } - - /* (non-Javadoc) - * @see java.lang.Object#hashCode() - */ - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - long temp; - temp = Double.doubleToLongBits(x); - result = prime * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(y); - result = prime * result + (int) (temp ^ (temp >>> 32)); - return result; - } - - /* (non-Javadoc) - * @see java.lang.Object#equals(java.lang.Object) - */ - @Override - public boolean equals(Object obj) { - if (obj == null) return false; - if (obj == this) return true; - if (obj instanceof Vector2) { - Vector2 vector = (Vector2)obj; - return this.x == vector.x && this.y == vector.y; - } - return false; - } - - /** - * Returns true if the x and y components of this {@link Vector2} - * are the same as the given {@link Vector2}. - * @param vector the {@link Vector2} to compare to - * @return boolean - */ - public boolean equals(Vector2 vector) { - 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 {@link Vector2} - * are the same as the given x and y components. - * @param x the x coordinate of the {@link Vector2} to compare to - * @param y the y coordinate of the {@link Vector2} to compare to - * @return boolean - */ - public boolean equals(double x, double y) { - return this.x == x && this.y == y; - } - - /* (non-Javadoc) - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(") - .append(this.x) - .append(", ") - .append(this.y) - .append(")"); - return sb.toString(); - } - - /** - * Sets this {@link Vector2} to the given {@link Vector2}. - * @param vector the {@link Vector2} to set this {@link Vector2} to - * @return {@link Vector2} this vector - */ - public Vector2 set(Vector2 vector) { - this.x = vector.x; - this.y = vector.y; - return this; - } - - /** - * Sets this {@link Vector2} to the given {@link Vector2}. - * @param x the x component of the {@link Vector2} to set this {@link Vector2} to - * @param y the y component of the {@link Vector2} to set this {@link Vector2} to - * @return {@link Vector2} this vector - */ - public Vector2 set(double x, double y) { - this.x = x; - this.y = y; - return this; - } - - /** - * Returns the x component of this {@link Vector2}. - * @return {@link Vector2} - */ - public Vector2 getXComponent() { - return new Vector2(this.x, 0.0); - } - - /** - * Returns the y component of this {@link Vector2}. - * @return {@link Vector2} - */ - public Vector2 getYComponent() { - return new Vector2(0.0, this.y); - } - - /** - * Returns the magnitude of this {@link Vector2}. - * @return double - */ - public double getMagnitude() { - // the magnitude is just the pathagorean theorem - return Math.sqrt(this.x * this.x + this.y * this.y); - } - - /** - * Returns the magnitude of this {@link Vector2} squared. - * @return double - */ - public double getMagnitudeSquared() { - return this.x * this.x + this.y * this.y; - } - - /** - * Sets the magnitude of the {@link Vector2}. - * @param magnitude the magnitude - * @return {@link Vector2} this vector - */ - public Vector2 setMagnitude(double magnitude) { - // check the given magnitude - if (Math.abs(magnitude) <= Epsilon.E) { - this.x = 0.0; - this.y = 0.0; - return this; - } - // is this vector a zero vector? - if (this.isZero()) { - return this; - } - // get the magnitude - double mag = Math.sqrt(this.x * this.x + this.y * this.y); - // normalize and multiply by the new magnitude - mag = magnitude / mag; - this.x *= mag; - this.y *= mag; - return this; - } - - /** - * Returns the direction of this {@link Vector2} - * as an angle in radians. - * @return double angle in radians [-π, π] - */ - public double getDirection() { - return Math.atan2(this.y, this.x); - } - - /** - * Sets the direction of this {@link Vector2}. - * @param angle angle in radians - * @return {@link Vector2} this vector - */ - public Vector2 setDirection(double angle) { - //double magnitude = Math.hypot(this.x, this.y); - double magnitude = Math.sqrt(this.x * this.x + this.y * this.y); - this.x = magnitude * Math.cos(angle); - this.y = magnitude * Math.sin(angle); - return this; - } - - /** - * Adds the given {@link Vector2} to this {@link Vector2}. - * @param vector the {@link Vector2} - * @return {@link Vector2} this vector - */ - public Vector2 add(Vector2 vector) { - this.x += vector.x; - this.y += vector.y; - return this; - } - - /** - * Adds the given {@link Vector2} to this {@link Vector2}. - * @param x the x component of the {@link Vector2} - * @param y the y component of the {@link Vector2} - * @return {@link Vector2} this vector - */ - public Vector2 add(double x, double y) { - this.x += x; - this.y += y; - return this; - } - - /** - * Adds this {@link Vector2} and the given {@link Vector2} returning - * a new {@link Vector2} containing the result. - * @param vector the {@link Vector2} - * @return {@link Vector2} - */ - public Vector2 sum(Vector2 vector) { - return new Vector2(this.x + vector.x, this.y + vector.y); - } - - /** - * Adds this {@link Vector2} and the given {@link Vector2} returning - * a new {@link Vector2} containing the result. - * @param x the x component of the {@link Vector2} - * @param y the y component of the {@link Vector2} - * @return {@link Vector2} - */ - public Vector2 sum(double x, double y) { - return new Vector2(this.x + x, this.y + y); - } - - /** - * Subtracts the given {@link Vector2} from this {@link Vector2}. - * @param vector the {@link Vector2} - * @return {@link Vector2} this vector - */ - public Vector2 subtract(Vector2 vector) { - this.x -= vector.x; - this.y -= vector.y; - return this; - } - - /** - * Subtracts the given {@link Vector2} from this {@link Vector2}. - * @param x the x component of the {@link Vector2} - * @param y the y component of the {@link Vector2} - * @return {@link Vector2} this vector - */ - public Vector2 subtract(double x, double y) { - this.x -= x; - this.y -= y; - return this; - } - - /** - * Subtracts the given {@link Vector2} from this {@link Vector2} returning - * a new {@link Vector2} containing the result. - * @param vector the {@link Vector2} - * @return {@link Vector2} - */ - public Vector2 difference(Vector2 vector) { - return new Vector2(this.x - vector.x, this.y - vector.y); - } - - /** - * Subtracts the given {@link Vector2} from this {@link Vector2} returning - * a new {@link Vector2} containing the result. - * @param x the x component of the {@link Vector2} - * @param y the y component of the {@link Vector2} - * @return {@link Vector2} - */ - public Vector2 difference(double x, double y) { - return new Vector2(this.x - x, this.y - y); - } - - /** - * Creates a {@link Vector2} from this {@link Vector2} to the given {@link Vector2}. - * @param vector the {@link Vector2} - * @return {@link Vector2} - */ - public Vector2 to(Vector2 vector) { - return new Vector2(vector.x - this.x, vector.y - this.y); - } - - /** - * Creates a {@link Vector2} from this {@link Vector2} to the given {@link Vector2}. - * @param x the x component of the {@link Vector2} - * @param y the y component of the {@link Vector2} - * @return {@link Vector2} - */ - public Vector2 to(double x, double y) { - return new Vector2(x - this.x, y - this.y); - } - - /** - * Multiplies this {@link Vector2} by the given scalar. - * @param scalar the scalar - * @return {@link Vector2} this vector - */ - public Vector2 multiply(double scalar) { - this.x *= scalar; - this.y *= scalar; - return this; - } - - /** - * Multiplies this {@link Vector2} by the given scalar returning - * a new {@link Vector2} containing the result. - * @param scalar the scalar - * @return {@link Vector2} - */ - public Vector2 product(double scalar) { - return new Vector2(this.x * scalar, this.y * scalar); - } - - /** - * Returns the dot product of the given {@link Vector2} - * and this {@link Vector2}. - * @param vector the {@link Vector2} - * @return double - */ - public double dot(Vector2 vector) { - return this.x * vector.x + this.y * vector.y; - } - - /** - * Returns the dot product of the given {@link Vector2} - * and this {@link Vector2}. - * @param x the x component of the {@link Vector2} - * @param y the y component of the {@link Vector2} - * @return double - */ - public double dot(double x, double y) { - return this.x * x + this.y * y; - } - - /** - * Returns the cross product of the this {@link Vector2} and the given {@link Vector2}. - * @param vector the {@link Vector2} - * @return double - */ - public double cross(Vector2 vector) { - return this.x * vector.y - this.y * vector.x; - } - - /** - * Returns the cross product of the this {@link Vector2} and the given {@link Vector2}. - * @param x the x component of the {@link Vector2} - * @param y the y component of the {@link Vector2} - * @return double - */ - public double cross(double x, double y) { - return this.x * y - this.y * x; - } - - /** - * Returns the cross product of this {@link Vector2} and the z value of the right {@link Vector2}. - * @param z the z component of the {@link Vector2} - * @return {@link Vector2} - */ - public Vector2 cross(double z) { - return new Vector2(-1.0 * this.y * z, this.x * z); - } - - /** - * Returns true if the given {@link Vector2} is orthogonal (perpendicular) - * to this {@link Vector2}. - *

- * If the dot product of this vector and the given vector is - * zero then we know that they are perpendicular - * @param vector the {@link Vector2} - * @return boolean - */ - public boolean isOrthogonal(Vector2 vector) { - return Math.abs(this.x * vector.x + this.y * vector.y) <= Epsilon.E ? true : false; - } - - /** - * Returns true if the given {@link Vector2} is orthogonal (perpendicular) - * to this {@link 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 {@link Vector2} - * @param y the y component of the {@link Vector2} - * @return boolean - */ - public boolean isOrthogonal(double x, double y) { - return Math.abs(this.x * x + this.y * y) <= Epsilon.E ? true : false; - } - - /** - * Returns true if this {@link Vector2} is the zero {@link Vector2}. - * @return boolean - */ - public boolean isZero() { - return Math.abs(this.x) <= Epsilon.E && Math.abs(this.y) <= Epsilon.E; - } - - /** - * Negates this {@link Vector2}. - * @return {@link Vector2} this vector - */ - public Vector2 negate() { - this.x *= -1.0; - this.y *= -1.0; - return this; - } - - /** - * Returns a {@link Vector2} which is the negative of this {@link Vector2}. - * @return {@link Vector2} - */ - public Vector2 getNegative() { - return new Vector2(-this.x, -this.y); - } - - /** - * Sets the {@link Vector2} to the zero {@link Vector2} - * @return {@link Vector2} this vector - */ - public Vector2 zero() { - this.x = 0.0; - this.y = 0.0; - return this; - } - - /** - * Rotates about the origin. - * @param theta the rotation angle in radians - * @return {@link Vector2} this vector - */ - public Vector2 rotate(double theta) { - double cos = Math.cos(theta); - double sin = Math.sin(theta); - double x = this.x; - double y = this.y; - this.x = x * cos - y * sin; - this.y = x * sin + y * cos; - return this; - } - - /** - * Rotates the {@link Vector2} about the given coordinates. - * @param theta the rotation angle in radians - * @param x the x coordinate to rotate about - * @param y the y coordinate to rotate about - * @return {@link Vector2} this vector - */ - public Vector2 rotate(double theta, double x, double y) { - this.x -= x; - this.y -= y; - this.rotate(theta); - this.x += x; - this.y += y; - return this; - } - - /** - * Rotates the {@link Vector2} about the given point. - * @param theta the rotation angle in radians - * @param point the point to rotate about - * @return {@link Vector2} this vector - */ - public Vector2 rotate(double theta, Vector2 point) { - return this.rotate(theta, point.x, point.y); - } - - /** - * Projects this {@link Vector2} onto the given {@link Vector2}. - * @param vector the {@link Vector2} - * @return {@link Vector2} the projected {@link Vector2} - */ - public Vector2 project(Vector2 vector) { - double dotProd = this.dot(vector); - double denominator = vector.dot(vector); - if (denominator <= Epsilon.E) return new Vector2(); - denominator = dotProd / denominator; - return new Vector2(denominator * vector.x, denominator * vector.y); - } - - /** - * Returns the right-handed normal of this vector. - * @return {@link Vector2} the right hand orthogonal {@link Vector2} - */ - public Vector2 getRightHandOrthogonalVector() { - return new Vector2(-this.y, this.x); - } - - /** - * Sets this vector to the right-handed normal of this vector. - * @return {@link Vector2} this vector - * @see #getRightHandOrthogonalVector() - */ - public Vector2 right() { - double temp = this.x; - this.x = -this.y; - this.y = temp; - return this; - } - - /** - * Returns the left-handed normal of this vector. - * @return {@link Vector2} the left hand orthogonal {@link Vector2} - */ - public Vector2 getLeftHandOrthogonalVector() { - return new Vector2(this.y, -this.x); - } - - /** - * Sets this vector to the left-handed normal of this vector. - * @return {@link Vector2} this vector - * @see #getLeftHandOrthogonalVector() - */ - public Vector2 left() { - double temp = this.x; - this.x = this.y; - this.y = -temp; - return this; - } - - /** - * Returns a unit {@link Vector2} of this {@link Vector2}. - *

- * This method requires the length of this {@link Vector2} is not zero. - * @return {@link Vector2} - */ - public Vector2 getNormalized() { - double magnitude = this.getMagnitude(); - if (magnitude <= Epsilon.E) return new Vector2(); - magnitude = 1.0 / magnitude; - return new Vector2(this.x * magnitude, this.y * magnitude); - } - - /** - * Converts this {@link Vector2} into a unit {@link Vector2} and returns - * the magnitude before normalization. - *

- * This method requires the length of this {@link Vector2} is not zero. - * @return double - */ - public double normalize() { - double magnitude = Math.sqrt(this.x * this.x + this.y * this.y); - if (magnitude <= Epsilon.E) return 0; - double m = 1.0 / magnitude; - this.x *= m; - this.y *= m; - //return 1.0 / m; - return magnitude; - } - - /** - * Returns the smallest angle between the given {@link Vector2}s. - *

- * Returns the angle in radians in the range -π to π. - * @param vector the {@link Vector2} - * @return angle in radians [-π, π] - */ - public double getAngleBetween(Vector2 vector) { - double 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; - } -} \ No newline at end of file diff --git a/src/org/dyn4j/geometry/Vector2.kt b/src/org/dyn4j/geometry/Vector2.kt new file mode 100644 index 000000000..b9048d5fe --- /dev/null +++ b/src/org/dyn4j/geometry/Vector2.kt @@ -0,0 +1,860 @@ +/* + * 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 Torvald aka skyhi14. + */ +package org.dyn4j.geometry + +import org.dyn4j.Epsilon + +/** + * 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. + * + * + * Some methods also return the vector to facilitate chaining. For example: + * + * Vector a = new Vector(); + * a.zero().plus(1, 2).times(2); + * + * In this Kotlin code, you can use regular operations like + - * /. + * + * |operator|function| + * |--------|--------| + * |a + b|a.plus(b)| + * |a - b|a.minus(b)| + * |a * b|a.times(b)| + * |a / b|a.div(b)| + * |a dot b|a.dot(b)| + * |a cross b|a.cross(b)| + * |!a|negate(a)| + * |a rotate th|a.rotate(th)| + * + * @author William Bittle + * * + * @version 3.1.11 + * * + * @since 1.0.0 + */ +class Vector2 { + + /** The magnitude of the x component of this [Vector2] */ + var x: Double = 0.toDouble() + + /** The magnitude of the y component of this [Vector2] */ + var y: Double = 0.toDouble() + + /** 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) + } + + /** + * 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): Vector2 { + this.x = vector.x + this.y = vector.y + return this + } + + /** + * 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): Vector2 { + this.x = x + this.y = y + return this + } + + /** + * 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) { + this.x = 0.0 + this.y = 0.0 + return this + } + // is this vector a zero vector? + if (this.isZero) { + return this + } + // 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 + this.x *= mag + this.y *= mag + return this + } + + /** + * 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) + this.x = magnitude * Math.cos(angle) + this.y = magnitude * Math.sin(angle) + return this + } + + /** + * Adds the given [Vector2] to this [Vector2]. + * @param vector the [Vector2] + * * + * @return [Vector2] this vector + */ + operator fun plus(vector: Vector2): Vector2 { + this.x += vector.x + this.y += vector.y + return this + } + + /** + * Adds the given [Vector2] to this [Vector2]. + * @param x the x component of the [Vector2] + * * + * @param y the y component of the [Vector2] + * * + * @return [Vector2] this vector + */ + fun plus(x: Double, y: Double): Vector2 { + this.x += x + this.y += y + return this + } + + /** + * Adds this [Vector2] and the given [Vector2] returning + * a new [Vector2] containing the result. + * @param vector the [Vector2] + * * + * @return [Vector2] + */ + fun sum(vector: Vector2): Vector2 { + return Vector2(this.x + vector.x, this.y + vector.y) + } + + /** + * Adds this [Vector2] and the given [Vector2] returning + * a new [Vector2] containing the result. + * @param x the x component of the [Vector2] + * * + * @param y the y component of the [Vector2] + * * + * @return [Vector2] + */ + fun sum(x: Double, y: Double): Vector2 { + return Vector2(this.x + x, this.y + y) + } + + /** + * Subtracts the given [Vector2] from this [Vector2]. + * @param vector the [Vector2] + * * + * @return [Vector2] this vector + */ + operator fun minus(vector: Vector2): Vector2 { + this.x -= vector.x + this.y -= vector.y + return this + } + + /** + * Subtracts the given [Vector2] from this [Vector2]. + * @param x the x component of the [Vector2] + * * + * @param y the y component of the [Vector2] + * * + * @return [Vector2] this vector + */ + fun minus(x: Double, y: Double): Vector2 { + this.x -= x + this.y -= y + return this + } + + /** + * Subtracts the given [Vector2] from this [Vector2] returning + * a new [Vector2] containing the result. + * @param vector the [Vector2] + * * + * @return [Vector2] + */ + fun difference(vector: Vector2): Vector2 { + return Vector2(this.x - vector.x, this.y - vector.y) + } + + /** + * Subtracts the given [Vector2] from this [Vector2] returning + * a new [Vector2] containing the result. + * @param x the x component of the [Vector2] + * * + * @param y the y component of the [Vector2] + * * + * @return [Vector2] + */ + fun difference(x: Double, y: Double): Vector2 { + return Vector2(this.x - x, this.y - y) + } + + /** + * Creates a [Vector2] from this [Vector2] to the given [Vector2]. + * @param vector the [Vector2] + * * + * @return [Vector2] + */ + fun to(vector: Vector2): Vector2 { + return Vector2(vector.x - this.x, vector.y - this.y) + } + + /** + * Creates a [Vector2] from this [Vector2] to the given [Vector2]. + * @param x the x component of the [Vector2] + * * + * @param y the y component of the [Vector2] + * * + * @return [Vector2] + */ + fun to(x: Double, y: Double): Vector2 { + return Vector2(x - this.x, y - this.y) + } + + /** + * Multiplies this [Vector2] by the given scalar. + * @param scalar the scalar + * * + * @return [Vector2] this vector + */ + operator fun times(scalar: Double): Vector2 { + this.x *= scalar + this.y *= scalar + return this + } + + /** + * Multiplies this [Vector2] by the given scalar. + * @param scalar the scalar + * * + * @return [Vector2] this vector + */ + operator fun div(scalar: Double): Vector2 { + this.x /= scalar + this.y /= scalar + return this + } + + /** + * 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 + + /** + * Negates this [Vector2]. + * @return [Vector2] this vector + */ + operator fun not() = negate() + + /** + * Negates this [Vector2]. + * @return [Vector2] this vector + */ + fun negate(): Vector2 { + this.x *= -1.0 + this.y *= -1.0 + return this + } + + /** + * 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(): Vector2 { + this.x = 0.0 + this.y = 0.0 + return this + } + + /** + * 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 + this.x = x * cos - y * sin + this.y = x * sin + y * cos + return this + } + + /** + * Rotates the [Vector2] about the given coordinates. + * @param theta the rotation angle in radians + * * + * @param x the x coordinate to rotate about + * * + * @param y the y coordinate to rotate about + * * + * @return [Vector2] this vector + */ + fun rotate(theta: Double, x: Double, y: Double): Vector2 { + this.x -= x + this.y -= y + this.rotate(theta) + this.x += x + this.y += y + return this + } + + /** + * Rotates the [Vector2] about the given point. + * @param theta the rotation angle in radians + * * + * @param point the point to rotate about + * * + * @return [Vector2] this vector + */ + fun rotate(theta: Double, point: Vector2): Vector2 { + return this.rotate(theta, point.x, point.y) + } + + /** + * 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 + this.x = -this.y + this.y = temp + return this + } + + /** + * 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 + this.x = this.y + this.y = -temp + return this + } + + /** + * 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 + } + + 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 + } + } +} \ No newline at end of file