1/* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV. 2 3Permission is hereby granted, free of charge, to any person obtaining a copy 4of this software and associated documentation files (the "Software"), to deal 5in the Software without restriction, including without limitation the rights 6to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7copies of the Software, and to permit persons to whom the Software is 8furnished to do so, subject to the following conditions: 9 10The above copyright notice and this permission notice shall be included in 11all copies or substantial portions of the Software. 12 13THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19THE SOFTWARE. */ 20 21var glMatrix = require("./common.js"); 22 23/** 24 * @class 2x3 Matrix 25 * @name mat2d 26 * 27 * @description 28 * A mat2d contains six elements defined as: 29 * <pre> 30 * [a, c, tx, 31 * b, d, ty] 32 * </pre> 33 * This is a short form for the 3x3 matrix: 34 * <pre> 35 * [a, c, tx, 36 * b, d, ty, 37 * 0, 0, 1] 38 * </pre> 39 * The last row is ignored so the array is shorter and operations are faster. 40 */ 41var mat2d = {}; 42 43/** 44 * Creates a new identity mat2d 45 * 46 * @returns {mat2d} a new 2x3 matrix 47 */ 48mat2d.create = function() { 49 var out = new glMatrix.ARRAY_TYPE(6); 50 out[0] = 1; 51 out[1] = 0; 52 out[2] = 0; 53 out[3] = 1; 54 out[4] = 0; 55 out[5] = 0; 56 return out; 57}; 58 59/** 60 * Creates a new mat2d initialized with values from an existing matrix 61 * 62 * @param {mat2d} a matrix to clone 63 * @returns {mat2d} a new 2x3 matrix 64 */ 65mat2d.clone = function(a) { 66 var out = new glMatrix.ARRAY_TYPE(6); 67 out[0] = a[0]; 68 out[1] = a[1]; 69 out[2] = a[2]; 70 out[3] = a[3]; 71 out[4] = a[4]; 72 out[5] = a[5]; 73 return out; 74}; 75 76/** 77 * Copy the values from one mat2d to another 78 * 79 * @param {mat2d} out the receiving matrix 80 * @param {mat2d} a the source matrix 81 * @returns {mat2d} out 82 */ 83mat2d.copy = function(out, a) { 84 out[0] = a[0]; 85 out[1] = a[1]; 86 out[2] = a[2]; 87 out[3] = a[3]; 88 out[4] = a[4]; 89 out[5] = a[5]; 90 return out; 91}; 92 93/** 94 * Set a mat2d to the identity matrix 95 * 96 * @param {mat2d} out the receiving matrix 97 * @returns {mat2d} out 98 */ 99mat2d.identity = function(out) { 100 out[0] = 1; 101 out[1] = 0; 102 out[2] = 0; 103 out[3] = 1; 104 out[4] = 0; 105 out[5] = 0; 106 return out; 107}; 108 109/** 110 * Inverts a mat2d 111 * 112 * @param {mat2d} out the receiving matrix 113 * @param {mat2d} a the source matrix 114 * @returns {mat2d} out 115 */ 116mat2d.invert = function(out, a) { 117 var aa = a[0], ab = a[1], ac = a[2], ad = a[3], 118 atx = a[4], aty = a[5]; 119 120 var det = aa * ad - ab * ac; 121 if(!det){ 122 return null; 123 } 124 det = 1.0 / det; 125 126 out[0] = ad * det; 127 out[1] = -ab * det; 128 out[2] = -ac * det; 129 out[3] = aa * det; 130 out[4] = (ac * aty - ad * atx) * det; 131 out[5] = (ab * atx - aa * aty) * det; 132 return out; 133}; 134 135/** 136 * Calculates the determinant of a mat2d 137 * 138 * @param {mat2d} a the source matrix 139 * @returns {Number} determinant of a 140 */ 141mat2d.determinant = function (a) { 142 return a[0] * a[3] - a[1] * a[2]; 143}; 144 145/** 146 * Multiplies two mat2d's 147 * 148 * @param {mat2d} out the receiving matrix 149 * @param {mat2d} a the first operand 150 * @param {mat2d} b the second operand 151 * @returns {mat2d} out 152 */ 153mat2d.multiply = function (out, a, b) { 154 var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5], 155 b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3], b4 = b[4], b5 = b[5]; 156 out[0] = a0 * b0 + a2 * b1; 157 out[1] = a1 * b0 + a3 * b1; 158 out[2] = a0 * b2 + a2 * b3; 159 out[3] = a1 * b2 + a3 * b3; 160 out[4] = a0 * b4 + a2 * b5 + a4; 161 out[5] = a1 * b4 + a3 * b5 + a5; 162 return out; 163}; 164 165/** 166 * Alias for {@link mat2d.multiply} 167 * @function 168 */ 169mat2d.mul = mat2d.multiply; 170 171/** 172 * Rotates a mat2d by the given angle 173 * 174 * @param {mat2d} out the receiving matrix 175 * @param {mat2d} a the matrix to rotate 176 * @param {Number} rad the angle to rotate the matrix by 177 * @returns {mat2d} out 178 */ 179mat2d.rotate = function (out, a, rad) { 180 var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5], 181 s = Math.sin(rad), 182 c = Math.cos(rad); 183 out[0] = a0 * c + a2 * s; 184 out[1] = a1 * c + a3 * s; 185 out[2] = a0 * -s + a2 * c; 186 out[3] = a1 * -s + a3 * c; 187 out[4] = a4; 188 out[5] = a5; 189 return out; 190}; 191 192/** 193 * Scales the mat2d by the dimensions in the given vec2 194 * 195 * @param {mat2d} out the receiving matrix 196 * @param {mat2d} a the matrix to translate 197 * @param {vec2} v the vec2 to scale the matrix by 198 * @returns {mat2d} out 199 **/ 200mat2d.scale = function(out, a, v) { 201 var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5], 202 v0 = v[0], v1 = v[1]; 203 out[0] = a0 * v0; 204 out[1] = a1 * v0; 205 out[2] = a2 * v1; 206 out[3] = a3 * v1; 207 out[4] = a4; 208 out[5] = a5; 209 return out; 210}; 211 212/** 213 * Translates the mat2d by the dimensions in the given vec2 214 * 215 * @param {mat2d} out the receiving matrix 216 * @param {mat2d} a the matrix to translate 217 * @param {vec2} v the vec2 to translate the matrix by 218 * @returns {mat2d} out 219 **/ 220mat2d.translate = function(out, a, v) { 221 var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5], 222 v0 = v[0], v1 = v[1]; 223 out[0] = a0; 224 out[1] = a1; 225 out[2] = a2; 226 out[3] = a3; 227 out[4] = a0 * v0 + a2 * v1 + a4; 228 out[5] = a1 * v0 + a3 * v1 + a5; 229 return out; 230}; 231 232/** 233 * Creates a matrix from a given angle 234 * This is equivalent to (but much faster than): 235 * 236 * mat2d.identity(dest); 237 * mat2d.rotate(dest, dest, rad); 238 * 239 * @param {mat2d} out mat2d receiving operation result 240 * @param {Number} rad the angle to rotate the matrix by 241 * @returns {mat2d} out 242 */ 243mat2d.fromRotation = function(out, rad) { 244 var s = Math.sin(rad), c = Math.cos(rad); 245 out[0] = c; 246 out[1] = s; 247 out[2] = -s; 248 out[3] = c; 249 out[4] = 0; 250 out[5] = 0; 251 return out; 252} 253 254/** 255 * Creates a matrix from a vector scaling 256 * This is equivalent to (but much faster than): 257 * 258 * mat2d.identity(dest); 259 * mat2d.scale(dest, dest, vec); 260 * 261 * @param {mat2d} out mat2d receiving operation result 262 * @param {vec2} v Scaling vector 263 * @returns {mat2d} out 264 */ 265mat2d.fromScaling = function(out, v) { 266 out[0] = v[0]; 267 out[1] = 0; 268 out[2] = 0; 269 out[3] = v[1]; 270 out[4] = 0; 271 out[5] = 0; 272 return out; 273} 274 275/** 276 * Creates a matrix from a vector translation 277 * This is equivalent to (but much faster than): 278 * 279 * mat2d.identity(dest); 280 * mat2d.translate(dest, dest, vec); 281 * 282 * @param {mat2d} out mat2d receiving operation result 283 * @param {vec2} v Translation vector 284 * @returns {mat2d} out 285 */ 286mat2d.fromTranslation = function(out, v) { 287 out[0] = 1; 288 out[1] = 0; 289 out[2] = 0; 290 out[3] = 1; 291 out[4] = v[0]; 292 out[5] = v[1]; 293 return out; 294} 295 296/** 297 * Returns a string representation of a mat2d 298 * 299 * @param {mat2d} a matrix to represent as a string 300 * @returns {String} string representation of the matrix 301 */ 302mat2d.str = function (a) { 303 return 'mat2d(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + 304 a[3] + ', ' + a[4] + ', ' + a[5] + ')'; 305}; 306 307/** 308 * Returns Frobenius norm of a mat2d 309 * 310 * @param {mat2d} a the matrix to calculate Frobenius norm of 311 * @returns {Number} Frobenius norm 312 */ 313mat2d.frob = function (a) { 314 return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + 1)) 315}; 316 317module.exports = mat2d; 318