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