1 /*
  2  * Copyright 2010 Scriptoid s.r.l
  3  */
  4 
  5 /**
  6  * A matrix math library.
  7  * Instead of creating of a so called Object we will only use matrixes as
  8  * array or arrays so Matrix will function more like a namespace instead
  9  * as an object.
 10  *
 11  * All function are "static" / class methods...so no need to instanciate a Matrix object
 12  * 
 13  * @namespace
 14  */
 15 
 16 function Matrix(){
 17 }
 18 
 19 
 20 /**Add two matrixes.
 21  *It can be used to combine multiple transformations into one.
 22  *@param {Array} m1 - first matrix
 23  *@param {Array} m2 - second matrix
 24  *@return {Array} the sum of those 2 matrix
 25  *@see <a href="http://en.wikipedia.org/wiki/Transformation_matrix#Composing_and_inverting_transformations">http://en.wikipedia.org/wiki/Transformation_matrix#Composing_and_inverting_transformations></a>
 26  **/
 27 Matrix.add = function(m1, m2){
 28     var mReturn=[];
 29     if(m1.length==m2.length){
 30         for(var row=0; row<m1.length; row++){
 31             mReturn[row]=[];
 32             for(var column=0; column<m1[row].length; column++){
 33                 mReturn[row][column] = m1[row][column] + m2[row][column];
 34             }
 35         }
 36     }
 37     return mReturn;
 38 };
 39 
 40 
 41 /**Clones a matrix. Recursivelly
 42  *@param {Array} m - the matrix to clone
 43  *@return {Array} - the clone of orriginal matrix
 44  *@author Alex Gheorghiu <alex@scriptoid.com>
 45  **/
 46 Matrix.clone = function(m){
 47     if(typeof(m) == 'undefined' || m == null){
 48         return null;
 49     }
 50     
 51     var mReturn=[];
 52     for(var i=0; i<m.length; i++){
 53         /*If the element is also an array. As we can not tell if this is an array or object as both array and object return objects
 54          *we will at least try to see if it's object and if it has some length */
 55         if(typeof(m) == 'object' && m[i].length){ 
 56             mReturn.push(Matrix.clone(m[i]));
 57         }
 58         else{
 59             mReturn.push(m[i]);
 60         }
 61     }
 62     return mReturn;
 63 };
 64 
 65 
 66 
 67 
 68 /**Substract matrix m2 from m1
 69  *@param {Array} m1 - first matrix
 70  *@param {Array} m2 - second matrix
 71  *@return {Array} the m1 - m2 matrix
 72  **/
 73 Matrix.subtract = function(m1, m2){
 74     var mReturn=[];
 75     if(m1.length == m2.length){
 76         for(var row=0; row<m1.length; row++){
 77             mReturn[row]=[];
 78             for(var column=0; column<m1[row].length; column++){
 79                 mReturn[row][column] = m1[row][column] - m2[row][column];
 80             }
 81         }
 82     }
 83     return mReturn;
 84 };
 85 
 86 
 87 /**Multiply matrix m2 with m1
 88  *@param {Array} m1 - first matrix
 89  *@param {Array} m2 - second matrix
 90  *@return {Array} the multiplication of those 2 matrix
 91  *@see <a href="http://en.wikipedia.org/wiki/Matrix_multiplication">http://en.wikipedia.org/wiki/Matrix_multiplication</a>
 92  **/
 93 Matrix.multiply = function(m1, m2){
 94     var mReturn = [];
 95     if(m1[0].length==m2.length){//check that width=height
 96         for(var m1Row=0; m1Row<m1.length; m1Row++){
 97             mReturn[m1Row] = [];
 98             for(var m2Column=0; m2Column<m2[0].length; m2Column++){
 99                 mReturn[m1Row][m2Column] = 0
100                 for(var m2Row=0; m2Row<m2.length; m2Row++){
101                     mReturn[m1Row][m2Column] += m1[m1Row][m2Row] * m2[m2Row][m2Column];
102                 }
103             }
104         }
105     }
106     return mReturn;
107 };
108 
109 /**Compares two matrixes
110   *@param {Array} m1 - first matrix
111   *@param {Array} m2 - second matrix
112   *@return {Boolean} true if matrixes are equal , false otherwise
113 **/
114 Matrix.equals = function(m1, m2){
115     if(m1.length != m2.length){ //nr or rows not equal
116         return false;
117     }
118     else{
119         for(var i in m1){
120             if(m1[i].length != m2[i].length){ //nr or cols not equal
121                 return false;
122             }
123             else{
124                 for(var j in m1[i]){
125                     if(m1[i][j] != m2[i][j]){
126                         return false;
127                     }
128                 }
129             }
130         }
131     }
132 
133     return true;
134 }
135 
136 
137 /**Creates a clockwise rotation matrix around the origin.
138  *
139  *Note: don't use this to rotate a Figure. You must first move it to origin.
140  *(by using a translation)
141  *@param {Number} angle - the angle expressed in radians
142  *@return {Array} - the ready to use rotation matrix
143  *@see <a href="http://en.wikipedia.org/wiki/Rotation_matrix#In_an_oriented_plane">http://en.wikipedia.org/wiki/Rotation_matrix#In_an_oriented_plane</a>
144  *@see <a href="http://en.wikipedia.org/wiki/Rotation_matrix">http://en.wikipedia.org/wiki/Rotation_matrix</a>
145  *@see <a href="http://en.wikipedia.org/wiki/Transformation_matrix#Rotation">http://en.wikipedia.org/wiki/Transformation_matrix#Rotation</a>
146  **/
147 Matrix.rotationMatrix = function(angle){
148     var mReturn=[
149     [Math.cos(angle), -Math.sin(angle), 0],
150     [Math.sin(angle), Math.cos(angle),   0],
151     [0,0, 1]];
152     return mReturn;
153 };
154 
155     
156 /**Creates a translation matrix
157  *@param {Number} dx - variation of movement on [Ox axis
158  *@param {Number} dy - variation of movement on [Oy axis
159  *@return {Array} - the ready to use translation matrix
160  **/
161 Matrix.translationMatrix = function(dx, dy){
162     return [
163     [1, 0, dx],
164     [0, 1, dy],
165     [0, 0,  1]
166     ];
167 };
168     
169 /**Creates a scale matrix
170  *@param {Number} sx - scale factor by which the x will be multiply
171  *@param {Number} sy - scale factor by which the y will be multiply
172  *@return {Array} - the ready to use scale matrix
173  *@see <a href="http://en.wikipedia.org/wiki/Transformation_matrix#Scaling">http://en.wikipedia.org/wiki/Transformation_matrix#Scaling</a>
174  **/
175 Matrix.scaleMatrix = function(sx, sy){
176     if(sy == null) {
177         sy=sx;
178     }
179 
180     
181     return [
182     [sx,0,0],
183     [0,sy,0],
184     [0,0,1]
185     ];
186 //we should allow a single parameter too, in which case we will have sx = sy
187 };
188 
189 
190 /**A ready to use matrix to make a 90 degree rotation.
191  *It acts like a singleton.
192  *It's more used for example and testings
193  **/
194 Matrix.R90 = [[0, -1, 0], [0,  1, 0], [0,  0, 1]];
195 
196 /**The identity matrix*/
197 Matrix.IDENTITY = [[1,0,0],[0,1,0],[0,0,1]];
198 
199 
200 
201