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