1 /* 2 SPDX-FileCopyrightText: 2011 See AUTHORS file. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package org.kde.kstars.math; 8 9 import java.io.Serializable; 10 11 /** Encapsulates a 2D vector. Allows chaining methods by returning a reference to itself 12 * @author badlogicgames@gmail.com */ 13 public class Vector2 implements Serializable { 14 private static final long serialVersionUID = 913902788239530931L; 15 16 /** Static temporary vector. Use with care! Use only when sure other code will not also use this. 17 * @see #tmp() **/ 18 public final static Vector2 tmp = new Vector2(), tmp2 = new Vector2(), tmp3 = new Vector2(); 19 20 public final static Vector2 X = new Vector2(1, 0); 21 public final static Vector2 Y = new Vector2(0, 1); 22 public final static Vector2 Zero = new Vector2(0, 0); 23 24 /** the x-component of this vector **/ 25 public float x; 26 /** the y-component of this vector **/ 27 public float y; 28 29 /** Constructs a new vector at (0,0) */ Vector2()30 public Vector2 () { 31 } 32 33 /** Constructs a vector with the given components 34 * @param x The x-component 35 * @param y The y-component */ Vector2(float x, float y)36 public Vector2 (float x, float y) { 37 this.x = x; 38 this.y = y; 39 } 40 41 /** Constructs a vector from the given vector 42 * @param v The vector */ Vector2(Vector2 v)43 public Vector2 (Vector2 v) { 44 set(v); 45 } 46 47 /** @return a copy of this vector */ cpy()48 public Vector2 cpy () { 49 return new Vector2(this); 50 } 51 52 /** @return The euclidian length */ len()53 public float len () { 54 return (float)Math.sqrt(x * x + y * y); 55 } 56 57 /** @return The squared euclidian length */ len2()58 public float len2 () { 59 return x * x + y * y; 60 } 61 62 /** Sets this vector from the given vector 63 * @param v The vector 64 * @return This vector for chaining */ set(Vector2 v)65 public Vector2 set (Vector2 v) { 66 x = v.x; 67 y = v.y; 68 return this; 69 } 70 71 /** Sets the components of this vector 72 * @param x The x-component 73 * @param y The y-component 74 * @return This vector for chaining */ set(float x, float y)75 public Vector2 set (float x, float y) { 76 this.x = x; 77 this.y = y; 78 return this; 79 } 80 81 /** Substracts the given vector from this vector. 82 * @param v The vector 83 * @return This vector for chaining */ sub(Vector2 v)84 public Vector2 sub (Vector2 v) { 85 x -= v.x; 86 y -= v.y; 87 return this; 88 } 89 90 /** Normalizes this vector 91 * @return This vector for chaining */ nor()92 public Vector2 nor () { 93 float len = len(); 94 if (len != 0) { 95 x /= len; 96 y /= len; 97 } 98 return this; 99 } 100 101 /** Adds the given vector to this vector 102 * @param v The vector 103 * @return This vector for chaining */ add(Vector2 v)104 public Vector2 add (Vector2 v) { 105 x += v.x; 106 y += v.y; 107 return this; 108 } 109 110 /** Adds the given components to this vector 111 * @param x The x-component 112 * @param y The y-component 113 * @return This vector for chaining */ add(float x, float y)114 public Vector2 add (float x, float y) { 115 this.x += x; 116 this.y += y; 117 return this; 118 } 119 120 /** @param v The other vector 121 * @return The dot product between this and the other vector */ dot(Vector2 v)122 public float dot (Vector2 v) { 123 return x * v.x + y * v.y; 124 } 125 126 /** Multiplies this vector by a scalar 127 * @param scalar The scalar 128 * @return This vector for chaining */ mul(float scalar)129 public Vector2 mul (float scalar) { 130 x *= scalar; 131 y *= scalar; 132 return this; 133 } 134 135 /** Multiplies this vector by a scalar 136 * @return This vector for chaining */ mul(float x, float y)137 public Vector2 mul (float x, float y) { 138 this.x *= x; 139 this.y *= y; 140 return this; 141 } 142 div(float value)143 public Vector2 div (float value) { 144 return this.mul(1/value); 145 } 146 div(float vx, float vy)147 public Vector2 div (float vx, float vy) { 148 return this.mul(1/vx, 1/vy); 149 } 150 div(Vector2 other)151 public Vector2 div (Vector2 other) { 152 return this.mul(1/other.x, 1/other.y); 153 } 154 155 /** @param v The other vector 156 * @return the distance between this and the other vector */ dst(Vector2 v)157 public float dst (Vector2 v) { 158 final float x_d = v.x - x; 159 final float y_d = v.y - y; 160 return (float)Math.sqrt(x_d * x_d + y_d * y_d); 161 } 162 163 /** @param x The x-component of the other vector 164 * @param y The y-component of the other vector 165 * @return the distance between this and the other vector */ dst(float x, float y)166 public float dst (float x, float y) { 167 final float x_d = x - this.x; 168 final float y_d = y - this.y; 169 return (float)Math.sqrt(x_d * x_d + y_d * y_d); 170 } 171 172 /** @param v The other vector 173 * @return the squared distance between this and the other vector */ dst2(Vector2 v)174 public float dst2 (Vector2 v) { 175 final float x_d = v.x - x; 176 final float y_d = v.y - y; 177 return x_d * x_d + y_d * y_d; 178 } 179 180 /** @param x The x-component of the other vector 181 * @param y The y-component of the other vector 182 * @return the squared distance between this and the other vector */ dst2(float x, float y)183 public float dst2 (float x, float y) { 184 final float x_d = x - this.x; 185 final float y_d = y - this.y; 186 return x_d * x_d + y_d * y_d; 187 } 188 toString()189 public String toString () { 190 return "[" + x + ":" + y + "]"; 191 } 192 193 /** Substracts the other vector from this vector. 194 * @param x The x-component of the other vector 195 * @param y The y-component of the other vector 196 * @return This vector for chaining */ sub(float x, float y)197 public Vector2 sub (float x, float y) { 198 this.x -= x; 199 this.y -= y; 200 return this; 201 } 202 203 /** NEVER EVER SAVE THIS REFERENCE! Do not use this unless you are aware of the side-effects, e.g. other methods might call this 204 * as well. 205 * 206 * @return a temporary copy of this vector. Use with care as this is backed by a single static Vector2 instance. v1.tmp().add( 207 * v2.tmp() ) will not work! */ tmp()208 public Vector2 tmp () { 209 return tmp.set(this); 210 } 211 212 /** Multiplies this vector by the given matrix 213 * @param mat the matrix 214 * @return this vector */ mul(Matrix3 mat)215 public Vector2 mul (Matrix3 mat) { 216 float x = this.x * mat.val[0] + this.y * mat.val[3] + mat.val[6]; 217 float y = this.x * mat.val[1] + this.y * mat.val[4] + mat.val[7]; 218 this.x = x; 219 this.y = y; 220 return this; 221 } 222 223 /** Calculates the 2D cross product between this and the given vector. 224 * @param v the other vector 225 * @return the cross product */ crs(Vector2 v)226 public float crs (Vector2 v) { 227 return this.x * v.y - this.y * v.x; 228 } 229 230 /** Calculates the 2D cross product between this and the given vector. 231 * @param x the x-coordinate of the other vector 232 * @param y the y-coordinate of the other vector 233 * @return the cross product */ crs(float x, float y)234 public float crs (float x, float y) { 235 return this.x * y - this.y * x; 236 } 237 238 /** @return the angle in degrees of this vector (point) relative to the x-axis. Angles are counter-clockwise and between 0 and 239 * 360. */ angle()240 public float angle () { 241 float angle = (float)Math.atan2(y, x) * MathUtils.radiansToDegrees; 242 if (angle < 0) angle += 360; 243 return angle; 244 } 245 246 /** Sets the angle of the vector. 247 * @param angle The angle to set. */ setAngle(float angle)248 public void setAngle (float angle) { 249 this.set(len(), 0f); 250 this.rotate(angle); 251 } 252 253 /** Rotates the Vector2 by the given angle, counter-clockwise. 254 * @param degrees the angle in degrees */ rotate(float degrees)255 public Vector2 rotate (float degrees) { 256 float rad = degrees * MathUtils.degreesToRadians; 257 float cos = (float)Math.cos(rad); 258 float sin = (float)Math.sin(rad); 259 260 float newX = this.x * cos - this.y * sin; 261 float newY = this.x * sin + this.y * cos; 262 263 this.x = newX; 264 this.y = newY; 265 266 return this; 267 } 268 269 /** Linearly interpolates between this vector and the target vector by alpha which is in the range [0,1]. The result is stored 270 * in this vector. 271 * 272 * @param target The target vector 273 * @param alpha The interpolation coefficient 274 * @return This vector for chaining. */ lerp(Vector2 target, float alpha)275 public Vector2 lerp (Vector2 target, float alpha) { 276 Vector2 r = this.mul(1.0f - alpha); 277 r.add(target.tmp().mul(alpha)); 278 return r; 279 } 280 281 @Override hashCode()282 public int hashCode () { 283 final int prime = 31; 284 int result = 1; 285 result = prime * result + NumberUtils.floatToIntBits(x); 286 result = prime * result + NumberUtils.floatToIntBits(y); 287 return result; 288 } 289 290 @Override equals(Object obj)291 public boolean equals (Object obj) { 292 if (this == obj) return true; 293 if (obj == null) return false; 294 if (getClass() != obj.getClass()) return false; 295 Vector2 other = (Vector2)obj; 296 if (NumberUtils.floatToIntBits(x) != NumberUtils.floatToIntBits(other.x)) return false; 297 if (NumberUtils.floatToIntBits(y) != NumberUtils.floatToIntBits(other.y)) return false; 298 return true; 299 } 300 301 /** Compares this vector with the other vector, using the supplied epsilon for fuzzy equality testing. 302 * @param obj 303 * @param epsilon 304 * @return whether the vectors are the same. */ epsilonEquals(Vector2 obj, float epsilon)305 public boolean epsilonEquals (Vector2 obj, float epsilon) { 306 if (obj == null) return false; 307 if (Math.abs(obj.x - x) > epsilon) return false; 308 if (Math.abs(obj.y - y) > epsilon) return false; 309 return true; 310 } 311 } 312