View difference between Paste ID: DSrfj3Lz and ZuxSkcwy
SHOW: | | - or go back to the newest paste.
1
package ASUtil.Math
2
{
3
	import flash.geom.Matrix;
4
	import flash.geom.Matrix3D;
5
	
6-
	public class matrix extends Object
6+
	public final class matrix extends Object
7
	{
8
		
9
		public static const opMul:String = "Multiplication";
10
		public static const opAdd:String = "Addition";
11
		public static const opSub:String = "Subtract";
12
		public static const opInv:String = "Inverse";
13
		public static const opFMX:String = "ToFlashMatrix";
14
		public static const opFM3:String = "ToFlashMatrix3D";
15
		
16
		private var data:Vector.<Number>;
17
		private var W:uint;
18
		private var H:uint;
19
		
20
		public var newLine:Boolean = true;
21
		
22
		//Constructor. Takes in width, height, and an array of data. You do not have to fill the matrix early, but you can't over-flow it.
23
		public function matrix ( width:uint, height:uint, ... dat )
24
		{
25
			
26
			data = new Vector.<Number> ( width * height, true );
27
			
28
			W = width;
29
			H = height;
30
			
31
			if ( dat.length > W * H )
32
				throw new Error ( "More data provided than fits in matrix.", 0 );
33
			
34
			for ( var n:uint = 0; n < dat.length; n ++ )
35
				data [ n ] = dat [ n ];
36
			
37
		};
38
		
39
		//Set a specific element to a value, in X-Y form, top left being the origin, going down and to the right.
40
		public function setElement ( x:uint, y:uint, value:Number ) : void
41
		{
42
			
43
			if ( x >= W || y >= H )
44
				throw new Error ( "The coordinance ( " + x + ", " + y + " ) is out of the matrix bounds.", 1 );
45
			
46
			data [ x + y * W ] = value;
47
			
48
		};
49
		
50
		//Add similar matrices.
51
		public function add ( mat:matrix ) : matrix
52
		{
53
			
54
			if ( mat.width != W || mat.height != H )
55
				throw new Error ( "Mismatched dimensions for adding.", 2 );
56
			
57
			var ret:matrix = new matrix ( W, H );
58
			
59
			for ( var x:uint = 0; x < W; x ++ )
60
			{
61
				
62
				for ( var y:uint = 0; y < H; y ++ )
63
				{
64
					
65
					ret.setElement ( x, y, data [ x + y * H ] + mat.getElement ( x, y ) );
66
					
67
				}
68
				
69
			}
70
			
71
			return ret;
72
			
73
		};
74
		
75
		//Subtract similar matrices
76
		public function sub ( mat:matrix ) : matrix
77
		{
78
			
79
			if ( mat.width != W || mat.height != H )
80
				throw new Error ( "Mismatched dimensions for adding.", 3 );
81
			
82
			var ret:matrix = new matrix ( W, H );
83
			
84
			for ( var x:uint = 0; x < W; x ++ )
85
			{
86
				
87
				for ( var y:uint = 0; y < H; y ++ )
88
				{
89
					
90
					ret.setElement ( x, y, data [ x + y * H ] - mat.getElement ( x, y ) );
91
					
92
				}
93
				
94
			}
95
			
96
			return ret;
97
			
98
		};
99
		
100
		//Multiply all the elements of an array my a value.
101
		public function mulUniform ( val:Number ):matrix
102
		{
103
			
104
			var ret:matrix = new matrix ( W, H );
105
			
106
			for ( var n:uint = 0; n < W * H; n ++ )
107
			{
108
				
109
				ret.setElement ( n % W, ( n - n % W ) / W, val * data [ n ] );
110
				
111
			}
112
			
113
			return ret;
114
			
115
		};
116
		
117
		//Multiply two matrices.
118
		public function mulMatrix ( mat:matrix ) : matrix
119
		{
120
			
121
			if ( W != mat.height )
122
				throw new Error ( "Mismatched dimensions for multiplication.", 4 );
123
			
124
			var ret:matrix = new matrix ( mat.width, H );
125
			var curr:Number;
126
			
127
			for ( var x:uint = 0; x < mat.width; x ++ )
128
				for ( var y:uint = 0; y < H; y ++ )
129
				{
130
					
131
					curr = 0;
132
					
133
					for ( var n:uint = 0; n < W; n ++ )
134
						curr += mat.getElement ( x, n ) * data [ n * W + y ];
135
					
136
					ret.setElement ( x, y, curr );
137
					
138
				}
139
			
140
			return ret;
141
			
142
		};
143
		
144
		//Get the inverse of the matrix. ( Only works with 1x1, 2x2, or 3x3 matrices.
145
		public function inverse () : matrix
146
		{
147
			
148
			if ( !operationSupported ( opInv ) )
149
				throw new Error ( "inversion is not possible on this matrix.", 5 );
150
			
151
			var ret:matrix = new matrix ( W, H );
152
			var mul:Number;
153
			
154
			if ( W == 1 )
155
				ret.setElement ( 0, 0, 1 / data [ 0 ] );
156
			
157
			if ( W == 2 )
158
			{
159
				
160
				mul = 1 / ( data [ 0 ] * data [ 3 ] - data [ 1 ] * data [ 2 ] );
161
				
162
				ret.setElement ( 0, 0, data [ 3 ] * mul );
163
				ret.setElement ( 1, 0, -data [ 1 ] * mul );
164
				
165
				ret.setElement ( 0, 1, -data [ 2 ] * mul );
166
				ret.setElement ( 1, 1, data [ 0 ] * mul );
167
				
168
			}
169
			
170
			if ( W == 3 )
171
			{
172
				
173
				mul = 1 / ( data [ 0 ] * ( ( data [ 4 ] * data [ 8 ] ) - ( data [ 5 ] * data [ 7 ] ) ) + data [ 1 ] * ( ( data [ 5 ] * data [ 6 ] ) - ( data [ 8 ] * data [ 3 ] ) ) + data [ 2 ] * ( ( data [ 3 ] * data [ 7 ] ) - ( data [ 4 ] * data [ 6 ] ) ) );
174
				
175
				ret.setElement ( 0, 0, ( data [ 4 ] * data [ 8 ] - data [ 5 ] * data [ 7 ] ) );
176
				ret.setElement ( 0, 1, ( data [ 2 ] * data [ 7 ] - data [ 1 ] * data [ 8 ] ) );
177
				ret.setElement ( 0, 2, ( data [ 1 ] * data [ 5 ] - data [ 2 ] * data [ 4 ] ) );
178
				
179
				ret.setElement ( 1, 0, ( data [ 5 ] * data [ 6 ] - data [ 3 ] * data [ 8 ] ) );
180
				ret.setElement ( 1, 1, ( data [ 0 ] * data [ 8 ] - data [ 2 ] * data [ 6 ] ) );
181
				ret.setElement ( 1, 2, ( data [ 2 ] * data [ 3 ] - data [ 0 ] * data [ 5 ] ) );
182
				
183
				ret.setElement ( 2, 0, ( data [ 3 ] * data [ 7 ] - data [ 4 ] * data [ 6 ] ) );
184
				ret.setElement ( 2, 1, ( data [ 6 ] * data [ 1 ] - data [ 0 ] * data [ 7 ] ) );
185
				ret.setElement ( 2, 2, ( data [ 0 ] * data [ 4 ] - data [ 1 ] * data [ 3 ] ) );
186
				
187
				ret = ret.mulUniform ( mul );
188
				
189
			}
190
			
191
			return ret;
192
				
193
		}
194
		
195
		//Get the value of a specific element, similarly to setElement.
196
		public function getElement ( x:uint, y:uint ) : Number
197
		{
198
			
199
			return data [ x + y * W ];
200
			
201
		};
202
		
203
		//Width getter
204
		public function get width () : uint
205
		{
206
			
207
			return W;
208
			
209
		};
210
		
211
		//Height getter
212
		public function get height () : uint
213
		{
214
			
215
			return H;
216
			
217
		};
218
		
219
		//Returns the raw number data in an array.
220
		public function getRawData () : Vector.<Number>
221
		{
222
			
223
			return data;
224
			
225
		};
226
		
227
		/*Test if a matrix can have a certain operation 
228
		preformed on it. This includes multiplication, 
229
		addition and subtraction with other matricies,
230
		getting the inverse, and converting to flash 
231
		display transform matrices.
232
		*/
233
		public function operationSupported ( operation:String, second:matrix = null ) : Boolean
234
		{
235
			
236
			if ( !( operation == opFMX || operation == opFM3 || operation == opInv || second != null ) )
237
				throw new Error ( "Second matrix not provided to test for operability.", 6 );
238
			
239
			switch ( operation )
240
			{
241
				
242
				case opInv:
243
					if ( ( W == 3 && H == 3 ) || ( W == 2 && H == 2 ) || ( W == 1 && H == 1 ) )
244
						return true;
245
					else
246
						return false;
247
					break;
248
				
249
				case opAdd:
250
					if ( W == second.width && H == second.height )
251
						return true;
252
					else
253
						return false;
254
					break;
255
				
256
				case opSub:
257
					if ( W == second.width && H == second.height )
258
						return true;
259
					else
260
						return false;
261
					break;
262
				
263
				case opMul:
264
					
265
					if ( W == second.height )
266
						return true;
267
					else
268
						return false;
269
					
270
				case opFMX:
271
					
272
					if ( W == 3 && H == 3 || W == 3 && H == 2 )
273
						return true;
274
					else
275
						return false;
276
					break;
277
				
278
				case opFM3:
279
					
280
					if ( W == 4 && H == 4 )
281
						return true;
282
					else
283
						return false;
284
					
285
					break;
286
					
287
				default:
288
					
289
					throw new Error ( operation + " is not an operation you can test for.", 7 );
290
					
291
					break;
292
					
293
			}
294
			
295
			return false;
296
			
297
		};
298
		
299
		public function toString () : String
300
		{
301
			
302
			var out:String = ( newLine ) ? '' : '[ ';
303
			var maxL:Vector.<uint> = new Vector.<uint> ( W, true );
304
			
305
			var qx:uint;
306
			var sp:String;
307
			var sa:String;
308
			
309
			for ( var n:uint = 0; n < W * H; n ++ )
310
			{
311
				
312
				qx = n % W;
313
				maxL [ qx ] = Math.max ( maxL [ qx ], data [ n ].toString ().length );
314
				
315
			}
316
			
317
			for ( var y:uint = 0; y < H; y ++ )
318
			for ( var x:uint = 0; x < W; x ++ )
319
			{
320
				
321
				sp = '';
322
				sa = data [ x + y * W ].toString ( 10 );
323
				
324
				while ( sa.length < maxL [ x ] && newLine )
325
					sa = ' ' + sa;
326
				
327
				if ( x == 0 )
328
					out += '[ ';
329
				
330
				out += sa;
331
				
332
				if ( x < W - 1 )
333
					out += ', ';
334
				else
335
				{
336
					
337
					out += ' ]';
338
						if ( y < H - 1 )
339
							out += ( newLine ) ? '\n' : ' ';
340
				
341
				}
342
				
343
			}
344
			
345
			out += ( newLine ) ? '' : ' ]';
346
			
347
			var t:String = '';
348
			
349
			if ( out.indexOf ( "\n" ) != 0 )
350
			{
351
				
352
				var u:uint = 0;
353
				while ( u ++ < out.indexOf ( "\n" ) )
354
					t += '-';
355
				
356
			}
357
			else
358
			{
359
				
360
				var g:uint = 0;
361
				while ( g ++ < out.length )
362
					t += '-';
363
				
364
			}
365
			
366
			if ( newLine )
367
				out = "Matrix:\n" + t + '\n' + out + '\n' + t;
368
			
369
			return out;
370
			
371
		};
372
		
373
		//Makes the matrix into a flash transform matrix.
374
		public function toFlashMatrix () : flash.geom.Matrix
375
		{
376
			
377
			if ( ! operationSupported ( opFMX ) )
378
				throw new Error ( "Cannot convert to flash matrix. ( wrond dimentions )", 8 );
379
			
380
			var ret:flash.geom.Matrix = new flash.geom.Matrix ( data [ 0 ], data [ 1 ], data [ 3 ], data [ 4 ], data [ 2 ], data [ 5 ] );
381
			return ret;
382
			
383
		}
384
		
385
		//Makes the matrix a Flash 3D transform matrix.
386
		public function toFlashMatrix3D () : flash.geom.Matrix3D
387
		{
388
			
389
			if ( ! operationSupported ( opFM3 ) )
390
				throw new Error ( "Cannot convert to flash matrix. ( wrond dimentions )", 9 );
391
			
392
			var ret:flash.geom.Matrix3D = new flash.geom.Matrix3D ( data );
393
			return ret;
394
			
395
		}
396
		
397
		//Generates an identity matrix of a specific size.
398
		public static function generateIdentity ( size:uint ) : matrix
399
		{
400
			
401
			var ret:matrix = new matrix ( size, size );
402
			var i:uint = 0;
403
			
404
			while ( i ++ < size )
405
				ret.setElement ( i - 1, i - 1, 1 );
406
			
407
			return ret;
408
			
409
		};
410
		
411
		//Creates a matrix from a flash transform matrix.
412
		public static function fromFlashMatrix ( mat:flash.geom.Matrix ) : matrix
413
		{
414
			
415
			return new matrix ( 3, 3, mat.a, mat.b, mat.tx, mat.c, mat.d, mat.ty, 0, 0, 1 );
416
			
417
		}
418
		
419
		//Creates a matrix from a flash 3D transform matrix.
420
		public static function fromFlashMatrix3D ( mat:flash.geom.Matrix3D ) : matrix
421
		{
422
			
423
			return new matrix ( 4, 4, mat.rawData );
424
			
425
		}
426
		
427
	};
428
	
429
};