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 /** from libgdx: https://github.com/libgdx/libgdx */
10 import java.io.Serializable;
11 
12 /** A 3x3 <a href="http://en.wikipedia.org/wiki/Row-major_order">column major</a> matrix; useful for 2D transforms.
13  *
14  * @author mzechner */
15 public class Matrix3 implements Serializable {
16 	private static final long serialVersionUID = 7907569533774959788L;
17 	private final static float DEGREE_TO_RAD = (float)Math.PI / 180;
18 	public static final int M00 = 0;
19 	public static final int M01 = 3;
20 	public static final int M02 = 6;
21 	public static final int M10 = 1;
22 	public static final int M11 = 4;
23 	public static final int M12 = 7;
24 	public static final int M20 = 2;
25 	public static final int M21 = 5;
26 	public static final int M22 = 8;
27 	public float[] val = new float[9];
28 	private float[] tmp = new float[9];
29 
Matrix3()30 	public Matrix3 () {
31 		idt();
32 	}
33 
Matrix3(Matrix3 matrix)34 	public Matrix3 (Matrix3 matrix) {
35 		set(matrix);
36 	}
37 
38 	/** Sets this matrix to the identity matrix
39 	 * @return This matrix for the purpose of chaining operations. */
idt()40 	public Matrix3 idt () {
41 		val[M00] = 1;
42 		val[M10] = 0;
43 		val[M20] = 0;
44 		val[M01] = 0;
45 		val[M11] = 1;
46 		val[M21] = 0;
47 		val[M02] = 0;
48 		val[M12] = 0;
49 		val[M22] = 1;
50 		return this;
51 	}
52 
53 	/** Multiplies this matrix with the provided matrix and stores the result in this matrix. For example:
54 	 *
55 	 * <pre>
56 	 * A.mul(B) results in A := AB
57 	 * </pre>
58 	 * @param m Matrix to multiply by.
59 	 * @return This matrix for the purpose of chaining operations together. */
mul(Matrix3 m)60 	public Matrix3 mul (Matrix3 m) {
61 		float v00 = val[M00] * m.val[M00] + val[M01] * m.val[M10] + val[M02] * m.val[M20];
62 		float v01 = val[M00] * m.val[M01] + val[M01] * m.val[M11] + val[M02] * m.val[M21];
63 		float v02 = val[M00] * m.val[M02] + val[M01] * m.val[M12] + val[M02] * m.val[M22];
64 
65 		float v10 = val[M10] * m.val[M00] + val[M11] * m.val[M10] + val[M12] * m.val[M20];
66 		float v11 = val[M10] * m.val[M01] + val[M11] * m.val[M11] + val[M12] * m.val[M21];
67 		float v12 = val[M10] * m.val[M02] + val[M11] * m.val[M12] + val[M12] * m.val[M22];
68 
69 		float v20 = val[M20] * m.val[M00] + val[M21] * m.val[M10] + val[M22] * m.val[M20];
70 		float v21 = val[M20] * m.val[M01] + val[M21] * m.val[M11] + val[M22] * m.val[M21];
71 		float v22 = val[M20] * m.val[M02] + val[M21] * m.val[M12] + val[M22] * m.val[M22];
72 
73 		val[M00] = v00;
74 		val[M10] = v10;
75 		val[M20] = v20;
76 		val[M01] = v01;
77 		val[M11] = v11;
78 		val[M21] = v21;
79 		val[M02] = v02;
80 		val[M12] = v12;
81 		val[M22] = v22;
82 
83 		return this;
84 	}
85 
86 	/** Sets this matrix to a rotation matrix that will rotate any vector in counter-clockwise order around the z-axis.
87 	 * @param degrees the angle in degrees.
88 	 * @return This matrix for the purpose of chaining operations. */
setToRotation(float degrees)89 	public Matrix3 setToRotation (float degrees) {
90 		float angle = DEGREE_TO_RAD * degrees;
91 		float cos = (float)Math.cos(angle);
92 		float sin = (float)Math.sin(angle);
93 
94 		this.val[M00] = cos;
95 		this.val[M10] = sin;
96 		this.val[M20] = 0;
97 
98 		this.val[M01] = -sin;
99 		this.val[M11] = cos;
100 		this.val[M21] = 0;
101 
102 		this.val[M02] = 0;
103 		this.val[M12] = 0;
104 		this.val[M22] = 1;
105 
106 		return this;
107 	}
108 
109 	/** Sets this matrix to a translation matrix.
110 	 * @param x the translation in x
111 	 * @param y the translation in y
112 	 * @return This matrix for the purpose of chaining operations. */
setToTranslation(float x, float y)113 	public Matrix3 setToTranslation (float x, float y) {
114 		this.val[M00] = 1;
115 		this.val[M10] = 0;
116 		this.val[M20] = 0;
117 
118 		this.val[M01] = 0;
119 		this.val[M11] = 1;
120 		this.val[M21] = 0;
121 
122 		this.val[M02] = x;
123 		this.val[M12] = y;
124 		this.val[M22] = 1;
125 
126 		return this;
127 	}
128 
129 	/** Sets this matrix to a translation matrix.
130 	 * @param translation The translation vector.
131 	 * @return This matrix for the purpose of chaining operations. */
setToTranslation(Vector2 translation)132 	public Matrix3 setToTranslation (Vector2 translation) {
133 		this.val[M00] = 1;
134 		this.val[M10] = 0;
135 		this.val[M20] = 0;
136 
137 		this.val[M01] = 0;
138 		this.val[M11] = 1;
139 		this.val[M21] = 0;
140 
141 		this.val[M02] = translation.x;
142 		this.val[M12] = translation.y;
143 		this.val[M22] = 1;
144 
145 		return this;
146 	}
147 
148 	/** Sets this matrix to a scaling matrix.
149 	 *
150 	 * @param scaleX the scale in x
151 	 * @param scaleY the scale in y
152 	 * @return This matrix for the purpose of chaining operations. */
setToScaling(float scaleX, float scaleY)153 	public Matrix3 setToScaling (float scaleX, float scaleY) {
154 		val[M00] = scaleX;
155 		val[M10] = 0;
156 		val[M20] = 0;
157 		val[M01] = 0;
158 		val[M11] = scaleY;
159 		val[M21] = 0;
160 		val[M02] = 0;
161 		val[M12] = 0;
162 		val[M22] = 1;
163 		return this;
164 	}
165 
toString()166 	public String toString () {
167 		return "[" + val[0] + "|" + val[3] + "|" + val[6] + "]\n" + "[" + val[1] + "|" + val[4] + "|" + val[7] + "]\n" + "["
168 				+ val[2] + "|" + val[5] + "|" + val[8] + "]";
169 	}
170 
171 	/** @return The determinant of this matrix */
det()172 	public float det () {
173 		return val[M00] * val[M11] * val[M22] + val[M01] * val[M12] * val[M20] + val[M02] * val[M10] * val[M21] - val[M00]
174 			* val[M12] * val[M21] - val[M01] * val[M10] * val[M22] - val[M02] * val[M11] * val[M20];
175 	}
176 
177 	/** Inverts this matrix given that the determinant is != 0.
178 	 * @return This matrix for the purpose of chaining operations. */
inv()179 	public Matrix3 inv () {
180 		float det = det();
181 		if (det == 0) throw new Error("Can't invert a singular matrix"); // changed to error from GdxRuntimeException
182 
183 		float inv_det = 1.0f / det;
184 
185 		tmp[M00] = val[M11] * val[M22] - val[M21] * val[M12];
186 		tmp[M10] = val[M20] * val[M12] - val[M10] * val[M22];
187 		tmp[M20] = val[M10] * val[M21] - val[M20] * val[M11];
188 		tmp[M01] = val[M21] * val[M02] - val[M01] * val[M22];
189 		tmp[M11] = val[M00] * val[M22] - val[M20] * val[M02];
190 		tmp[M21] = val[M20] * val[M01] - val[M00] * val[M21];
191 		tmp[M02] = val[M01] * val[M12] - val[M11] * val[M02];
192 		tmp[M12] = val[M10] * val[M02] - val[M00] * val[M12];
193 		tmp[M22] = val[M00] * val[M11] - val[M10] * val[M01];
194 
195 		val[M00] = inv_det * tmp[M00];
196 		val[M10] = inv_det * tmp[M10];
197 		val[M20] = inv_det * tmp[M20];
198 		val[M01] = inv_det * tmp[M01];
199 		val[M11] = inv_det * tmp[M11];
200 		val[M21] = inv_det * tmp[M21];
201 		val[M02] = inv_det * tmp[M02];
202 		val[M12] = inv_det * tmp[M12];
203 		val[M22] = inv_det * tmp[M22];
204 
205 		return this;
206 	}
207 
208 	/** Copies the values from the provided matrix to this matrix.
209 	 * @param mat The matrix to copy.
210 	 * @return This matrix for the purposes of chaining. */
set(Matrix3 mat)211 	public Matrix3 set (Matrix3 mat) {
212 		System.arraycopy(mat.val, 0, val, 0, val.length);
213 		return this;
214 	}
215 
216 	/** Sets this 3x3 matrix to the top left 3x3 corner of the provided 4x4 matrix.
217 	 * @param mat The matrix whose top left corner will be copied. This matrix will not be modified.
218 	 * @return This matrix for the purpose of chaining operations. */
set(Matrix4 mat)219 	public Matrix3 set (Matrix4 mat) {
220 		val[M00] = mat.val[Matrix4.M00];
221 		val[M10] = mat.val[Matrix4.M10];
222 		val[M20] = mat.val[Matrix4.M20];
223 		val[M01] = mat.val[Matrix4.M01];
224 		val[M11] = mat.val[Matrix4.M11];
225 		val[M21] = mat.val[Matrix4.M21];
226 		val[M02] = mat.val[Matrix4.M02];
227 		val[M12] = mat.val[Matrix4.M12];
228 		val[M22] = mat.val[Matrix4.M22];
229 		return this;
230 	}
231 
232 	/** Adds a translational component to the matrix in the 3rd column. The other columns are untouched.
233 	 * @param vector The translation vector.
234 	 * @return This matrix for the purpose of chaining. */
trn(Vector2 vector)235 	public Matrix3 trn (Vector2 vector) {
236 		val[M02] += vector.x;
237 		val[M12] += vector.y;
238 		return this;
239 	}
240 
241 	/** Adds a translational component to the matrix in the 3rd column. The other columns are untouched.
242 	 * @param x The x-component of the translation vector.
243 	 * @param y The y-component of the translation vector.
244 	 * @return This matrix for the purpose of chaining. */
trn(float x, float y)245 	public Matrix3 trn (float x, float y) {
246 		val[M02] += x;
247 		val[M12] += y;
248 		return this;
249 	}
250 
251 	/** Adds a translational component to the matrix in the 3rd column. The other columns are untouched.
252 	 * @param vector The translation vector. (The z-component of the vector is ignored because this is a 3x3 matrix)
253 	 * @return This matrix for the purpose of chaining. */
trn(Vector3 vector)254 	public Matrix3 trn (Vector3 vector) {
255 		val[M02] += vector.x;
256 		val[M12] += vector.y;
257 		return this;
258 	}
259 
260 	/** Postmultiplies this matrix by a translation matrix. Postmultiplication is also used by OpenGL ES' 1.x
261 	 * glTranslate/glRotate/glScale.
262 	 * @param x The x-component of the translation vector.
263 	 * @param y The y-component of the translation vector.
264 	 * @return This matrix for the purpose of chaining. */
translate(float x, float y)265 	public Matrix3 translate (float x, float y) {
266 		tmp[M00] = 1;
267 		tmp[M10] = 0;
268 		tmp[M20] = 0;
269 
270 		tmp[M01] = 0;
271 		tmp[M11] = 1;
272 		tmp[M21] = 0;
273 
274 		tmp[M02] = x;
275 		tmp[M12] = y;
276 		tmp[M22] = 1;
277 		mul(val, tmp);
278 		return this;
279 	}
280 
281 	/** Postmultiplies this matrix by a translation matrix. Postmultiplication is also used by OpenGL ES' 1.x
282 	 * glTranslate/glRotate/glScale.
283 	 * @param translation The translation vector.
284 	 * @return This matrix for the purpose of chaining. */
translate(Vector2 translation)285 	public Matrix3 translate (Vector2 translation) {
286 		tmp[M00] = 1;
287 		tmp[M10] = 0;
288 		tmp[M20] = 0;
289 
290 		tmp[M01] = 0;
291 		tmp[M11] = 1;
292 		tmp[M21] = 0;
293 
294 		tmp[M02] = translation.x;
295 		tmp[M12] = translation.y;
296 		tmp[M22] = 1;
297 		mul(val, tmp);
298 		return this;
299 	}
300 
301 	/** Postmultiplies this matrix with a (counter-clockwise) rotation matrix. Postmultiplication is also used by OpenGL ES' 1.x
302 	 * glTranslate/glRotate/glScale.
303 	 * @param angle The angle in degrees
304 	 * @return This matrix for the purpose of chaining. */
rotate(float angle)305 	public Matrix3 rotate (float angle) {
306 		if (angle == 0) return this;
307 		angle = DEGREE_TO_RAD * angle;
308 		float cos = (float)Math.cos(angle);
309 		float sin = (float)Math.sin(angle);
310 
311 		tmp[M00] = cos;
312 		tmp[M10] = sin;
313 		tmp[M20] = 0;
314 
315 		tmp[M01] = -sin;
316 		tmp[M11] = cos;
317 		tmp[M21] = 0;
318 
319 		tmp[M02] = 0;
320 		tmp[M12] = 0;
321 		tmp[M22] = 1;
322 		mul(val, tmp);
323 		return this;
324 	}
325 
326 	/** Postmultiplies this matrix with a scale matrix. Postmultiplication is also used by OpenGL ES' 1.x
327 	 * glTranslate/glRotate/glScale.
328 	 * @param scaleX The scale in the x-axis.
329 	 * @param scaleY The scale in the y-axis.
330 	 * @return This matrix for the purpose of chaining. */
scale(float scaleX, float scaleY)331 	public Matrix3 scale (float scaleX, float scaleY) {
332 		tmp[M00] = scaleX;
333 		tmp[M10] = 0;
334 		tmp[M20] = 0;
335 		tmp[M01] = 0;
336 		tmp[M11] = scaleY;
337 		tmp[M21] = 0;
338 		tmp[M02] = 0;
339 		tmp[M12] = 0;
340 		tmp[M22] = 1;
341 		mul(val, tmp);
342 		return this;
343 	}
344 
345 	/** Postmultiplies this matrix with a scale matrix. Postmultiplication is also used by OpenGL ES' 1.x
346 	 * glTranslate/glRotate/glScale.
347 	 * @param scale The vector to scale the matrix by.
348 	 * @return This matrix for the purpose of chaining. */
scale(Vector2 scale)349 	public Matrix3 scale (Vector2 scale) {
350 		tmp[M00] = scale.x;
351 		tmp[M10] = 0;
352 		tmp[M20] = 0;
353 		tmp[M01] = 0;
354 		tmp[M11] = scale.y;
355 		tmp[M21] = 0;
356 		tmp[M02] = 0;
357 		tmp[M12] = 0;
358 		tmp[M22] = 1;
359 		mul(val, tmp);
360 		return this;
361 	}
362 
363 	/** Get the values in this matrix.
364 	 * @return The float values that make up this matrix in column-major order. */
getValues()365 	public float[] getValues () {
366 		return val;
367 	}
368 
369 	/** Scale the matrix in the both the x and y components by the scalar value.
370 	 * @param scale The single value that will be used to scale both the x and y components.
371 	 * @return This matrix for the purpose of chaining methods together. */
scl(float scale)372 	public Matrix3 scl (float scale) {
373 		val[M00] *= scale;
374 		val[M11] *= scale;
375 		return this;
376 	}
377 
378 	/** Scale this matrix using the x and y components of the vector but leave the rest of the matrix alone.
379 	 * @param scale The {@link Vector3} to use to scale this matrix.
380 	 * @return This matrix for the purpose of chaining methods together. */
scl(Vector2 scale)381 	public Matrix3 scl (Vector2 scale) {
382 		val[M00] *= scale.x;
383 		val[M11] *= scale.y;
384 		return this;
385 	}
386 
387 	/** Scale this matrix using the x and y components of the vector but leave the rest of the matrix alone.
388 	 * @param scale The {@link Vector3} to use to scale this matrix. The z component will be ignored.
389 	 * @return This matrix for the purpose of chaining methods together. */
scl(Vector3 scale)390 	public Matrix3 scl (Vector3 scale) {
391 		val[M00] *= scale.x;
392 		val[M11] *= scale.y;
393 		return this;
394 	}
395 
396 	/** Transposes the current matrix.
397 	 * @return This matrix for the purpose of chaining methods together. */
transpose()398 	public Matrix3 transpose () {
399 		// Where MXY you do not have to change MXX
400 		float v01 = val[M10];
401 		float v02 = val[M20];
402 		float v10 = val[M01];
403 		float v12 = val[M21];
404 		float v20 = val[M02];
405 		float v21 = val[M12];
406 		val[M01] = v01;
407 		val[M02] = v02;
408 		val[M10] = v10;
409 		val[M12] = v12;
410 		val[M20] = v20;
411 		val[M21] = v21;
412 		return this;
413 	}
414 
415 	/** Multiplies matrix a with matrix b in the following manner:
416 	 *
417 	 * <pre>
418 	 * mul(A, B) => A := AB
419 	 * </pre>
420 	 * @param mata The float array representing the first matrix. Must have at least 9 elements.
421 	 * @param matb The float array representing the second matrix. Must have at least 9 elements. */
mul(float[] mata, float[] matb)422 	private static void mul (float[] mata, float[] matb) {
423 		float v00 = mata[M00] * matb[M00] + mata[M01] * matb[M10] + mata[M02] * matb[M20];
424 		float v01 = mata[M00] * matb[M01] + mata[M01] * matb[M11] + mata[M02] * matb[M21];
425 		float v02 = mata[M00] * matb[M02] + mata[M01] * matb[M12] + mata[M02] * matb[M22];
426 
427 		float v10 = mata[M10] * matb[M00] + mata[M11] * matb[M10] + mata[M12] * matb[M20];
428 		float v11 = mata[M10] * matb[M01] + mata[M11] * matb[M11] + mata[M12] * matb[M21];
429 		float v12 = mata[M10] * matb[M02] + mata[M11] * matb[M12] + mata[M12] * matb[M22];
430 
431 		float v20 = mata[M20] * matb[M00] + mata[M21] * matb[M10] + mata[M22] * matb[M20];
432 		float v21 = mata[M20] * matb[M01] + mata[M21] * matb[M11] + mata[M22] * matb[M21];
433 		float v22 = mata[M20] * matb[M02] + mata[M21] * matb[M12] + mata[M22] * matb[M22];
434 
435 		mata[M00] = v00;
436 		mata[M10] = v10;
437 		mata[M20] = v20;
438 		mata[M01] = v01;
439 		mata[M11] = v11;
440 		mata[M21] = v21;
441 		mata[M02] = v02;
442 		mata[M12] = v12;
443 		mata[M22] = v22;
444 	}
445 }
446