Advertisement
Guest User

matrix.as

a guest
Apr 2nd, 2012
441
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. package ASUtil.Math
  2. {
  3.     import flash.geom.Matrix;
  4.     import flash.geom.Matrix3D;
  5.    
  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. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement