1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package triptracker.client.map.core;
21
22 import java.util.Arrays;
23
24 public class SimpleMatrixOps {
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 /*** 3x3 identity matrix. */
55 public static final double[][] identity3x3 = {
56 { 1, 0, 0 },
57 { 0, 1, 0 },
58 { 0, 0, 1 }
59 };
60
61 /*** 90 degrees (anti-clockwise?) rotation matrix. */
62 public static final double[][] rotate90d3x3 = {
63 { 0, -1, 0 },
64 { 1, 0, 0 },
65 { 0, 0, 1 }
66 };
67
68 /*** 180 degrees rotation matrix. */
69 public static final double[][] rotate180d3x3 = {
70 { -1, 0, 0 },
71 { 0, -1, 0 },
72 { 0, 0, 1 }
73 };
74
75 /*** 270 degrees (anti-clockwise?) rotation matrix */
76 public static final double[][] rotate270d3x3 = {
77 { 0, 1, 0 },
78 { -1, 0, 0 },
79 { 0, 0, 1 }
80 };
81
82 /*** X-axis scaling matrix. */
83 public static final double[][] scalex3x3 = {
84 { 1, 0, 0 },
85 { 0, 0, 0 },
86 { 0, 0, 0 }
87 };
88
89 /*** Y-axis scaling matrix. */
90 public static final double[][] scaley3x3 = {
91 { 0, 0, 0 },
92 { 0, 1, 0 },
93 { 0, 0, 0 }
94 };
95
96 /*** X-axis translation matrix. */
97 public static final double[][] translatex3x3 = {
98 { 0, 0, 1 },
99 { 0, 0, 0 },
100 { 0, 0, 0 }
101 };
102
103 /*** Y-axis translation matrix. */
104 public static final double[][] translatey3x3 = {
105 { 0, 0, 0 },
106 { 0, 0, 1 },
107 { 0, 0, 0 }
108 };
109
110 /*** Flip matrix. Scale -1 about the y-axis (invert all x values) */
111 public static final double[][] flip3x3 =
112 add(multiply(-1, scalex3x3), identity3x3);
113
114 /*** Mirror matrix. Scale -1 about the x-axis (invert all y values) */
115 public static final double[][] mirror3x3 =
116 add(multiply(-1, scaley3x3), identity3x3);
117
118
119 /*** All rotation matrices. */
120 public static final double[][][] rotate3x3 = {
121 identity3x3,
122 rotate90d3x3,
123 rotate180d3x3,
124 rotate270d3x3
125 };
126
127 /*** Both scaling matrices. */
128 public static final double[][][] scale3x3 = {
129 scalex3x3,
130 scaley3x3
131 };
132
133 /*** Both translation matrices. */
134 public static final double[][][] translate3x3 = {
135 translatex3x3,
136 translatey3x3
137 };
138
139 /***
140 * Perform a matrix multiplication operation. In matrix multiplication the
141 * order of the matrices is essential to the final result.
142 *
143 * @param mat1 the first matrix
144 * @param mat2 the second matrix
145 * @return resulting multiplied matrix
146 * @throws IllegalArgumentException if not all matrices are the same size
147 */
148 public static double[][] multiply(double[][] mat1, double[][] mat2) {
149 double[][] result = new double[mat1.length][mat2[0].length];
150
151
152 if (mat1[0].length != mat2.length)
153 throw new IllegalArgumentException("incompatible dimensions");
154
155 for (int row = 0; row < result.length; row++) {
156 for (int col = 0; col < result[0].length; col++) {
157 int val = 0;
158 for (int i = 0; i < result.length; i++) {
159 val += mat1[row][i] * mat2[i][col];
160 }
161 result[row][col] = val;
162 }
163 }
164
165 return result;
166 }
167
168 /***
169 * Multiply a matrix by a factor.
170 *
171 * @param factor
172 * @param matrix
173 * @return matrix with elements multiplied by the factor
174 */
175 public static double[][] multiply(double factor, double[][] matrix) {
176 double[][] result = new double[matrix.length][matrix[0].length];
177
178 for (int i = 0; i < matrix.length; i++) {
179 for (int j = 0; j < matrix[0].length; j++) {
180 result[i][j] = factor * matrix[i][j];
181 }
182 }
183
184 return result;
185 }
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202 /***
203 * Perform a matrix addition operation on an abitrary number of matrices.
204 *
205 * @param matrices matrices to perform the addition operation on
206 * @return matrix with all the elements added
207 * @throws IllegalArgumentException if matrix dimensions are incompatible
208 */
209 public static double[][] add(double[][]... matrices) {
210 double[][] result
211 = new double[matrices[0].length][matrices[0][0].length];
212
213
214 for (int mat = 0; mat < matrices.length; mat++) {
215
216 if (result.length != matrices[mat].length
217 || result[0].length != matrices[mat][0].length)
218 throw new IllegalArgumentException("incompatible dimensions");
219
220
221 for (int i = 0; i < result.length; i++) {
222 for (int j = 0; j < result[0].length; j++) {
223 result[i][j] += matrices[mat][i][j];
224 }
225 }
226 }
227
228 return result;
229 }
230
231
232
233
234 public static Matrix2D<? extends Number> add(
235 Matrix2D<? extends Number>... matrices) {
236 Matrix2D<Number> result = new Matrix2D<Number>(
237 new Number[matrices[0].getLength(0)][matrices[0].getLength(1)]);
238
239
240 for (int mat = 0; mat < matrices.length; mat++) {
241
242 if (result.getLength(0) != matrices[mat].getLength(0)
243 || result.getLength(1) != matrices[mat].getLength(1))
244 throw new IllegalArgumentException("incompatible dimensions");
245
246
247
248
249
250
251
252 }
253
254 return result;
255 }
256
257
258 /***
259 * Expand a matrix until it becomes square. The extra rows or columns added,
260 * to give the matrix an equal amount of rows and columns, will be filled
261 * with the value false.
262 *
263 * @param layout matrix
264 * @return squared matrix
265 */
266 public static boolean[][] expandToSquare(boolean[][] layout) {
267 int length = (layout.length > layout[0].length ? layout.length
268 : layout[0].length);
269 boolean[][] matrix = new boolean[length][length];
270
271 Arrays.fill(matrix, false);
272
273
274 for (int i = 0; i < layout.length; i++) {
275 for (int j = 0; j < layout[0].length; j++) {
276 matrix[i][j] = layout[i][j];
277 }
278 }
279
280 return matrix;
281 }
282
283
284 public static Matrix2D<Number> expandToSquares(Matrix2D<Number> mat,
285 Number defaultValue) {
286 int length = (mat.getLength(0) > mat.getLength(1) ? mat.getLength(0)
287 : mat.getLength(1));
288 Matrix2D<Number> mat2d = new Matrix2D<Number>();
289 Number[][] matrix = new Number[length][length];
290
291 Arrays.fill(matrix, defaultValue);
292
293
294
295
296
297
298
299
300
301 mat2d.setMatrix(matrix);
302
303 return new Matrix2D<Number>();
304
305 }
306
307
308
309
310
311 /***
312 * Minimize the matrix by removing rows and columns from either of the four
313 * sides where all the elements are false.
314 */
315 public static boolean[][] minimize(boolean[][] layout) {
316 boolean[][] minimized;
317 int x1 = 0, x2 = 0;
318 int y1 = 0, y2 = 0;
319
320
321
322
323 outer: for (int i = 0; i < layout.length; i++) {
324 y1 = i;
325 for (int j = 0; j < layout[0].length; j++) {
326 if (layout[i][j])
327 break outer;
328 }
329 }
330
331
332 outer: for (int i = layout.length - 1; i >= 0; i--) {
333 y2 = i;
334 for (int j = 0; j < layout[0].length; j++) {
335 if (layout[i][j])
336 break outer;
337 }
338 }
339
340
341 outer: for (int j = 0; j < layout[0].length; j++) {
342 x1 = j;
343 for (int i = 0; i < layout.length; i++) {
344 if (layout[i][j])
345 break outer;
346 }
347 }
348
349
350 outer: for (int j = layout[0].length - 1; j >= 0; j--) {
351 x2 = j;
352 for (int i = 0; i < layout.length; i++) {
353 if (layout[i][j])
354 break outer;
355 }
356 }
357
358
359
360 minimized = new boolean[y2 - y1 + 1][x2 - x1 + 1];
361
362 for (int i = y1; i <= y2; i++) {
363 for (int j = x1; j <= x2; j++) {
364 minimized[i - y1][j - x1] = layout[i][j];
365 }
366 }
367
368 return minimized;
369 }
370
371 }