Home | History | Annotate | Download | only in gl-matrix
      1 /* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
      2 
      3 Permission is hereby granted, free of charge, to any person obtaining a copy
      4 of this software and associated documentation files (the "Software"), to deal
      5 in the Software without restriction, including without limitation the rights
      6 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      7 copies of the Software, and to permit persons to whom the Software is
      8 furnished to do so, subject to the following conditions:
      9 
     10 The above copyright notice and this permission notice shall be included in
     11 all copies or substantial portions of the Software.
     12 
     13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     14 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     16 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     17 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     18 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     19 THE SOFTWARE. */
     20 
     21 var 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  */
     41 var mat2d = {};
     42 
     43 /**
     44  * Creates a new identity mat2d
     45  *
     46  * @returns {mat2d} a new 2x3 matrix
     47  */
     48 mat2d.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  */
     65 mat2d.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  */
     83 mat2d.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  */
     99 mat2d.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  */
    116 mat2d.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  */
    141 mat2d.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  */
    153 mat2d.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  */
    169 mat2d.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  */
    179 mat2d.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  **/
    200 mat2d.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  **/
    220 mat2d.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  */
    243 mat2d.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  */
    265 mat2d.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  */
    286 mat2d.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  */
    302 mat2d.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  */
    313 mat2d.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 
    317 module.exports = mat2d;
    318