1/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.
2
3Redistribution and use in source and binary forms, with or without modification,
4are permitted provided that the following conditions are met:
5
6  * Redistributions of source code must retain the above copyright notice, this
7    list of conditions and the following disclaimer.
8  * Redistributions in binary form must reproduce the above copyright notice,
9    this list of conditions and the following disclaimer in the documentation
10    and/or other materials provided with the distribution.
11
12THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
13ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
16ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
18LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
19ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
22
23/**
24 * @class 2x3 Matrix
25 * @name mat2d
26 *
27 * @description
28 * A mat2d contains six elements defined as:
29 * <pre>
30 * [a, b,
31 *  c, d,
32 *  tx,ty]
33 * </pre>
34 * This is a short form for the 3x3 matrix:
35 * <pre>
36 * [a, b, 0
37 *  c, d, 0
38 *  tx,ty,1]
39 * </pre>
40 * The last column is ignored so the array is shorter and operations are faster.
41 */
42var mat2d = {};
43
44/**
45 * Creates a new identity mat2d
46 *
47 * @returns {mat2d} a new 2x3 matrix
48 */
49mat2d.create = function() {
50    var out = new GLMAT_ARRAY_TYPE(6);
51    out[0] = 1;
52    out[1] = 0;
53    out[2] = 0;
54    out[3] = 1;
55    out[4] = 0;
56    out[5] = 0;
57    return out;
58};
59
60/**
61 * Creates a new mat2d initialized with values from an existing matrix
62 *
63 * @param {mat2d} a matrix to clone
64 * @returns {mat2d} a new 2x3 matrix
65 */
66mat2d.clone = function(a) {
67    var out = new GLMAT_ARRAY_TYPE(6);
68    out[0] = a[0];
69    out[1] = a[1];
70    out[2] = a[2];
71    out[3] = a[3];
72    out[4] = a[4];
73    out[5] = a[5];
74    return out;
75};
76
77/**
78 * Copy the values from one mat2d to another
79 *
80 * @param {mat2d} out the receiving matrix
81 * @param {mat2d} a the source matrix
82 * @returns {mat2d} out
83 */
84mat2d.copy = function(out, a) {
85    out[0] = a[0];
86    out[1] = a[1];
87    out[2] = a[2];
88    out[3] = a[3];
89    out[4] = a[4];
90    out[5] = a[5];
91    return out;
92};
93
94/**
95 * Set a mat2d to the identity matrix
96 *
97 * @param {mat2d} out the receiving matrix
98 * @returns {mat2d} out
99 */
100mat2d.identity = function(out) {
101    out[0] = 1;
102    out[1] = 0;
103    out[2] = 0;
104    out[3] = 1;
105    out[4] = 0;
106    out[5] = 0;
107    return out;
108};
109
110/**
111 * Inverts a mat2d
112 *
113 * @param {mat2d} out the receiving matrix
114 * @param {mat2d} a the source matrix
115 * @returns {mat2d} out
116 */
117mat2d.invert = function(out, a) {
118    var aa = a[0], ab = a[1], ac = a[2], ad = a[3],
119        atx = a[4], aty = a[5];
120
121    var det = aa * ad - ab * ac;
122    if(!det){
123        return null;
124    }
125    det = 1.0 / det;
126
127    out[0] = ad * det;
128    out[1] = -ab * det;
129    out[2] = -ac * det;
130    out[3] = aa * det;
131    out[4] = (ac * aty - ad * atx) * det;
132    out[5] = (ab * atx - aa * aty) * det;
133    return out;
134};
135
136/**
137 * Calculates the determinant of a mat2d
138 *
139 * @param {mat2d} a the source matrix
140 * @returns {Number} determinant of a
141 */
142mat2d.determinant = function (a) {
143    return a[0] * a[3] - a[1] * a[2];
144};
145
146/**
147 * Multiplies two mat2d's
148 *
149 * @param {mat2d} out the receiving matrix
150 * @param {mat2d} a the first operand
151 * @param {mat2d} b the second operand
152 * @returns {mat2d} out
153 */
154mat2d.multiply = function (out, a, b) {
155    var aa = a[0], ab = a[1], ac = a[2], ad = a[3],
156        atx = a[4], aty = a[5],
157        ba = b[0], bb = b[1], bc = b[2], bd = b[3],
158        btx = b[4], bty = b[5];
159
160    out[0] = aa*ba + ab*bc;
161    out[1] = aa*bb + ab*bd;
162    out[2] = ac*ba + ad*bc;
163    out[3] = ac*bb + ad*bd;
164    out[4] = ba*atx + bc*aty + btx;
165    out[5] = bb*atx + bd*aty + bty;
166    return out;
167};
168
169/**
170 * Alias for {@link mat2d.multiply}
171 * @function
172 */
173mat2d.mul = mat2d.multiply;
174
175
176/**
177 * Rotates a mat2d by the given angle
178 *
179 * @param {mat2d} out the receiving matrix
180 * @param {mat2d} a the matrix to rotate
181 * @param {Number} rad the angle to rotate the matrix by
182 * @returns {mat2d} out
183 */
184mat2d.rotate = function (out, a, rad) {
185    var aa = a[0],
186        ab = a[1],
187        ac = a[2],
188        ad = a[3],
189        atx = a[4],
190        aty = a[5],
191        st = Math.sin(rad),
192        ct = Math.cos(rad);
193
194    out[0] = aa*ct + ab*st;
195    out[1] = -aa*st + ab*ct;
196    out[2] = ac*ct + ad*st;
197    out[3] = -ac*st + ct*ad;
198    out[4] = ct*atx + st*aty;
199    out[5] = ct*aty - st*atx;
200    return out;
201};
202
203/**
204 * Scales the mat2d by the dimensions in the given vec2
205 *
206 * @param {mat2d} out the receiving matrix
207 * @param {mat2d} a the matrix to translate
208 * @param {mat2d} v the vec2 to scale the matrix by
209 * @returns {mat2d} out
210 **/
211mat2d.scale = function(out, a, v) {
212    var vx = v[0], vy = v[1];
213    out[0] = a[0] * vx;
214    out[1] = a[1] * vy;
215    out[2] = a[2] * vx;
216    out[3] = a[3] * vy;
217    out[4] = a[4] * vx;
218    out[5] = a[5] * vy;
219    return out;
220};
221
222/**
223 * Translates the mat2d by the dimensions in the given vec2
224 *
225 * @param {mat2d} out the receiving matrix
226 * @param {mat2d} a the matrix to translate
227 * @param {mat2d} v the vec2 to translate the matrix by
228 * @returns {mat2d} out
229 **/
230mat2d.translate = function(out, a, v) {
231    out[0] = a[0];
232    out[1] = a[1];
233    out[2] = a[2];
234    out[3] = a[3];
235    out[4] = a[4] + v[0];
236    out[5] = a[5] + v[1];
237    return out;
238};
239
240/**
241 * Returns a string representation of a mat2d
242 *
243 * @param {mat2d} a matrix to represent as a string
244 * @returns {String} string representation of the matrix
245 */
246mat2d.str = function (a) {
247    return 'mat2d(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' +
248                    a[3] + ', ' + a[4] + ', ' + a[5] + ')';
249};
250
251if(typeof(exports) !== 'undefined') {
252    exports.mat2d = mat2d;
253}
254