|
1 YUI.add('matrix', function (Y, NAME) { |
|
2 |
|
3 /** |
|
4 * Matrix utilities. |
|
5 * |
|
6 * @class MatrixUtil |
|
7 * @module matrix |
|
8 **/ |
|
9 |
|
10 var MatrixUtil = { |
|
11 /** |
|
12 * Used as value for the _rounding method. |
|
13 * |
|
14 * @property _rounder |
|
15 * @private |
|
16 */ |
|
17 _rounder: 100000, |
|
18 |
|
19 /** |
|
20 * Rounds values |
|
21 * |
|
22 * @method _round |
|
23 * @private |
|
24 */ |
|
25 _round: function(val) { |
|
26 val = Math.round(val * MatrixUtil._rounder) / MatrixUtil._rounder; |
|
27 return val; |
|
28 }, |
|
29 /** |
|
30 * Converts a radian value to a degree. |
|
31 * |
|
32 * @method rad2deg |
|
33 * @param {Number} rad Radian value to be converted. |
|
34 * @return Number |
|
35 */ |
|
36 rad2deg: function(rad) { |
|
37 var deg = rad * (180 / Math.PI); |
|
38 return deg; |
|
39 }, |
|
40 |
|
41 /** |
|
42 * Converts a degree value to a radian. |
|
43 * |
|
44 * @method deg2rad |
|
45 * @param {Number} deg Degree value to be converted to radian. |
|
46 * @return Number |
|
47 */ |
|
48 deg2rad: function(deg) { |
|
49 var rad = deg * (Math.PI / 180); |
|
50 return rad; |
|
51 }, |
|
52 |
|
53 /** |
|
54 * Converts an angle to a radian |
|
55 * |
|
56 * @method angle2rad |
|
57 * @param {Objecxt} val Value to be converted to radian. |
|
58 * @return Number |
|
59 */ |
|
60 angle2rad: function(val) { |
|
61 if (typeof val === 'string' && val.indexOf('rad') > -1) { |
|
62 val = parseFloat(val); |
|
63 } else { // default to deg |
|
64 val = MatrixUtil.deg2rad(parseFloat(val)); |
|
65 } |
|
66 |
|
67 return val; |
|
68 }, |
|
69 |
|
70 /** |
|
71 * Converts a transform object to an array of column vectors. |
|
72 * |
|
73 * / \ |
|
74 * | matrix[0][0] matrix[1][0] matrix[2][0] | |
|
75 * | matrix[0][1] matrix[1][1] matrix[2][1] | |
|
76 * | matrix[0][2] matrix[1][2] matrix[2][2] | |
|
77 * \ / |
|
78 * |
|
79 * @method getnxn |
|
80 * @return Array |
|
81 */ |
|
82 convertTransformToArray: function(matrix) |
|
83 { |
|
84 var matrixArray = [ |
|
85 [matrix.a, matrix.c, matrix.dx], |
|
86 [matrix.b, matrix.d, matrix.dy], |
|
87 [0, 0, 1] |
|
88 ]; |
|
89 return matrixArray; |
|
90 }, |
|
91 |
|
92 /** |
|
93 * Returns the determinant of a given matrix. |
|
94 * |
|
95 * / \ |
|
96 * | matrix[0][0] matrix[1][0] matrix[2][0] | |
|
97 * | matrix[0][1] matrix[1][1] matrix[2][1] | |
|
98 * | matrix[0][2] matrix[1][2] matrix[2][2] | |
|
99 * | matrix[0][3] matrix[1][3] matrix[2][3] | |
|
100 * \ / |
|
101 * |
|
102 * @method getDeterminant |
|
103 * @param {Array} matrix An nxn matrix represented an array of vector (column) arrays. Each vector array has index for each row. |
|
104 * @return Number |
|
105 */ |
|
106 getDeterminant: function(matrix) |
|
107 { |
|
108 var determinant = 0, |
|
109 len = matrix.length, |
|
110 i = 0, |
|
111 multiplier; |
|
112 |
|
113 if(len == 2) |
|
114 { |
|
115 return matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0]; |
|
116 } |
|
117 for(; i < len; ++i) |
|
118 { |
|
119 multiplier = matrix[i][0]; |
|
120 if(i % 2 === 0 || i === 0) |
|
121 { |
|
122 determinant += multiplier * MatrixUtil.getDeterminant(MatrixUtil.getMinors(matrix, i, 0)); |
|
123 } |
|
124 else |
|
125 { |
|
126 determinant -= multiplier * MatrixUtil.getDeterminant(MatrixUtil.getMinors(matrix, i, 0)); |
|
127 } |
|
128 } |
|
129 return determinant; |
|
130 }, |
|
131 |
|
132 /** |
|
133 * Returns the inverse of a matrix |
|
134 * |
|
135 * @method inverse |
|
136 * @param Array matrix An array representing an nxn matrix |
|
137 * @return Array |
|
138 * |
|
139 * / \ |
|
140 * | matrix[0][0] matrix[1][0] matrix[2][0] | |
|
141 * | matrix[0][1] matrix[1][1] matrix[2][1] | |
|
142 * | matrix[0][2] matrix[1][2] matrix[2][2] | |
|
143 * | matrix[0][3] matrix[1][3] matrix[2][3] | |
|
144 * \ / |
|
145 */ |
|
146 inverse: function(matrix) |
|
147 { |
|
148 var determinant = 0, |
|
149 len = matrix.length, |
|
150 i = 0, |
|
151 j, |
|
152 inverse, |
|
153 adjunct = [], |
|
154 //vector representing 2x2 matrix |
|
155 minor = []; |
|
156 if(len === 2) |
|
157 { |
|
158 determinant = matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0]; |
|
159 inverse = [ |
|
160 [matrix[1][1] * determinant, -matrix[1][0] * determinant], |
|
161 [-matrix[0][1] * determinant, matrix[0][0] * determinant] |
|
162 ]; |
|
163 } |
|
164 else |
|
165 { |
|
166 determinant = MatrixUtil.getDeterminant(matrix); |
|
167 for(; i < len; ++i) |
|
168 { |
|
169 adjunct[i] = []; |
|
170 for(j = 0; j < len; ++j) |
|
171 { |
|
172 minor = MatrixUtil.getMinors(matrix, j, i); |
|
173 adjunct[i][j] = MatrixUtil.getDeterminant(minor); |
|
174 if((i + j) % 2 !== 0 && (i + j) !== 0) |
|
175 { |
|
176 adjunct[i][j] *= -1; |
|
177 } |
|
178 } |
|
179 } |
|
180 inverse = MatrixUtil.scalarMultiply(adjunct, 1/determinant); |
|
181 } |
|
182 return inverse; |
|
183 }, |
|
184 |
|
185 /** |
|
186 * Multiplies a matrix by a numeric value. |
|
187 * |
|
188 * @method scalarMultiply |
|
189 * @param {Array} matrix The matrix to be altered. |
|
190 * @param {Number} multiplier The number to multiply against the matrix. |
|
191 * @return Array |
|
192 */ |
|
193 scalarMultiply: function(matrix, multiplier) |
|
194 { |
|
195 var i = 0, |
|
196 j, |
|
197 len = matrix.length; |
|
198 for(; i < len; ++i) |
|
199 { |
|
200 for(j = 0; j < len; ++j) |
|
201 { |
|
202 matrix[i][j] = MatrixUtil._round(matrix[i][j] * multiplier); |
|
203 } |
|
204 } |
|
205 return matrix; |
|
206 }, |
|
207 |
|
208 /** |
|
209 * Returns the transpose for an nxn matrix. |
|
210 * |
|
211 * @method transpose |
|
212 * @param matrix An nxn matrix represented by an array of vector arrays. |
|
213 * @return Array |
|
214 */ |
|
215 transpose: function(matrix) |
|
216 { |
|
217 var len = matrix.length, |
|
218 i = 0, |
|
219 j = 0, |
|
220 transpose = []; |
|
221 for(; i < len; ++i) |
|
222 { |
|
223 transpose[i] = []; |
|
224 for(j = 0; j < len; ++j) |
|
225 { |
|
226 transpose[i].push(matrix[j][i]); |
|
227 } |
|
228 } |
|
229 return transpose; |
|
230 }, |
|
231 |
|
232 /** |
|
233 * Returns a matrix of minors based on a matrix, column index and row index. |
|
234 * |
|
235 * @method getMinors |
|
236 * @param {Array} matrix The matrix from which to extract the matrix of minors. |
|
237 * @param {Number} columnIndex A zero-based index representing the specified column to exclude. |
|
238 * @param {Number} rowIndex A zero-based index represeenting the specified row to exclude. |
|
239 * @return Array |
|
240 */ |
|
241 getMinors: function(matrix, columnIndex, rowIndex) |
|
242 { |
|
243 var minors = [], |
|
244 len = matrix.length, |
|
245 i = 0, |
|
246 j, |
|
247 column; |
|
248 for(; i < len; ++i) |
|
249 { |
|
250 if(i !== columnIndex) |
|
251 { |
|
252 column = []; |
|
253 for(j = 0; j < len; ++j) |
|
254 { |
|
255 if(j !== rowIndex) |
|
256 { |
|
257 column.push(matrix[i][j]); |
|
258 } |
|
259 } |
|
260 minors.push(column); |
|
261 } |
|
262 } |
|
263 return minors; |
|
264 }, |
|
265 |
|
266 /** |
|
267 * Returns the sign of value |
|
268 * |
|
269 * @method sign |
|
270 * @param {Number} val value to be interpreted |
|
271 * @return Number |
|
272 */ |
|
273 sign: function(val) |
|
274 { |
|
275 return val === 0 ? 1 : val/Math.abs(val); |
|
276 }, |
|
277 |
|
278 /** |
|
279 * Multiplies a vector and a matrix |
|
280 * |
|
281 * @method vectorMatrixProduct |
|
282 * @param {Array} vector Array representing a column vector |
|
283 * @param {Array} matrix Array representing an nxn matrix |
|
284 * @return Array |
|
285 */ |
|
286 vectorMatrixProduct: function(vector, matrix) |
|
287 { |
|
288 var i, |
|
289 j, |
|
290 len = vector.length, |
|
291 product = [], |
|
292 rowProduct; |
|
293 for(i = 0; i < len; ++i) |
|
294 { |
|
295 rowProduct = 0; |
|
296 for(j = 0; j < len; ++j) |
|
297 { |
|
298 rowProduct += vector[i] * matrix[i][j]; |
|
299 } |
|
300 product[i] = rowProduct; |
|
301 } |
|
302 return product; |
|
303 }, |
|
304 |
|
305 /** |
|
306 * Breaks up a 2d transform matrix into a series of transform operations. |
|
307 * |
|
308 * @method decompose |
|
309 * @param {Array} matrix A 3x3 multidimensional array |
|
310 * @return Array |
|
311 */ |
|
312 decompose: function(matrix) |
|
313 { |
|
314 var a = parseFloat(matrix[0][0]), |
|
315 b = parseFloat(matrix[1][0]), |
|
316 c = parseFloat(matrix[0][1]), |
|
317 d = parseFloat(matrix[1][1]), |
|
318 dx = parseFloat(matrix[0][2]), |
|
319 dy = parseFloat(matrix[1][2]), |
|
320 rotate, |
|
321 sx, |
|
322 sy, |
|
323 shear; |
|
324 if((a * d - b * c) === 0) |
|
325 { |
|
326 return false; |
|
327 } |
|
328 //get length of vector(ab) |
|
329 sx = MatrixUtil._round(Math.sqrt(a * a + b * b)); |
|
330 //normalize components of vector(ab) |
|
331 a /= sx; |
|
332 b /= sx; |
|
333 shear = MatrixUtil._round(a * c + b * d); |
|
334 c -= a * shear; |
|
335 d -= b * shear; |
|
336 //get length of vector(cd) |
|
337 sy = MatrixUtil._round(Math.sqrt(c * c + d * d)); |
|
338 //normalize components of vector(cd) |
|
339 c /= sy; |
|
340 d /= sy; |
|
341 shear /=sy; |
|
342 shear = MatrixUtil._round(MatrixUtil.rad2deg(Math.atan(shear))); |
|
343 rotate = MatrixUtil._round(MatrixUtil.rad2deg(Math.atan2(matrix[1][0], matrix[0][0]))); |
|
344 |
|
345 return [ |
|
346 ["translate", dx, dy], |
|
347 ["rotate", rotate], |
|
348 ["skewX", shear], |
|
349 ["scale", sx, sy] |
|
350 ]; |
|
351 }, |
|
352 |
|
353 /** |
|
354 * Parses a transform string and returns an array of transform arrays. |
|
355 * |
|
356 * @method getTransformArray |
|
357 * @param {String} val A transform string |
|
358 * @return Array |
|
359 */ |
|
360 getTransformArray: function(transform) { |
|
361 var re = /\s*([a-z]*)\(([\w,\.,\-,\s]*)\)/gi, |
|
362 transforms = [], |
|
363 args, |
|
364 m, |
|
365 decomp, |
|
366 methods = MatrixUtil.transformMethods; |
|
367 |
|
368 while ((m = re.exec(transform))) { |
|
369 if (methods.hasOwnProperty(m[1])) |
|
370 { |
|
371 args = m[2].split(','); |
|
372 args.unshift(m[1]); |
|
373 transforms.push(args); |
|
374 } |
|
375 else if(m[1] == "matrix") |
|
376 { |
|
377 args = m[2].split(','); |
|
378 decomp = MatrixUtil.decompose([ |
|
379 [args[0], args[2], args[4]], |
|
380 [args[1], args[3], args[5]], |
|
381 [0, 0, 1] |
|
382 ]); |
|
383 transforms.push(decomp[0]); |
|
384 transforms.push(decomp[1]); |
|
385 transforms.push(decomp[2]); |
|
386 transforms.push(decomp[3]); |
|
387 } |
|
388 } |
|
389 return transforms; |
|
390 }, |
|
391 |
|
392 /** |
|
393 * Returns an array of transform arrays representing transform functions and arguments. |
|
394 * |
|
395 * @method getTransformFunctionArray |
|
396 * @return Array |
|
397 */ |
|
398 getTransformFunctionArray: function(transform) { |
|
399 var list; |
|
400 switch(transform) |
|
401 { |
|
402 case "skew" : |
|
403 list = [transform, 0, 0]; |
|
404 break; |
|
405 case "scale" : |
|
406 list = [transform, 1, 1]; |
|
407 break; |
|
408 case "scaleX" : |
|
409 list = [transform, 1]; |
|
410 break; |
|
411 case "scaleY" : |
|
412 list = [transform, 1]; |
|
413 break; |
|
414 case "translate" : |
|
415 list = [transform, 0, 0]; |
|
416 break; |
|
417 default : |
|
418 list = [transform, 0]; |
|
419 break; |
|
420 } |
|
421 return list; |
|
422 }, |
|
423 |
|
424 /** |
|
425 * Compares to arrays or transform functions to ensure both contain the same functions in the same |
|
426 * order. |
|
427 * |
|
428 * @method compareTransformSequence |
|
429 * @param {Array} list1 Array to compare |
|
430 * @param {Array} list2 Array to compare |
|
431 * @return Boolean |
|
432 */ |
|
433 compareTransformSequence: function(list1, list2) |
|
434 { |
|
435 var i = 0, |
|
436 len = list1.length, |
|
437 len2 = list2.length, |
|
438 isEqual = len === len2; |
|
439 if(isEqual) |
|
440 { |
|
441 for(; i < len; ++i) |
|
442 { |
|
443 if(list1[i][0] != list2[i][0]) |
|
444 { |
|
445 isEqual = false; |
|
446 break; |
|
447 } |
|
448 } |
|
449 } |
|
450 return isEqual; |
|
451 }, |
|
452 |
|
453 /** |
|
454 * Mapping of possible transform method names. |
|
455 * |
|
456 * @property transformMethods |
|
457 * @type Object |
|
458 */ |
|
459 transformMethods: { |
|
460 rotate: "rotate", |
|
461 skew: "skew", |
|
462 skewX: "skewX", |
|
463 skewY: "skewY", |
|
464 translate: "translate", |
|
465 translateX: "translateX", |
|
466 translateY: "tranlsateY", |
|
467 scale: "scale", |
|
468 scaleX: "scaleX", |
|
469 scaleY: "scaleY" |
|
470 } |
|
471 |
|
472 }; |
|
473 |
|
474 Y.MatrixUtil = MatrixUtil; |
|
475 |
|
476 /** |
|
477 * Matrix is a class that allows for the manipulation of a transform matrix. |
|
478 * This class is a work in progress. |
|
479 * |
|
480 * @class Matrix |
|
481 * @constructor |
|
482 * @module matrix |
|
483 */ |
|
484 var Matrix = function(config) { |
|
485 this.init(config); |
|
486 }; |
|
487 |
|
488 Matrix.prototype = { |
|
489 /** |
|
490 * Used as value for the _rounding method. |
|
491 * |
|
492 * @property _rounder |
|
493 * @private |
|
494 */ |
|
495 _rounder: 100000, |
|
496 |
|
497 /** |
|
498 * Updates the matrix. |
|
499 * |
|
500 * @method multiple |
|
501 * @param {Number} a |
|
502 * @param {Number} b |
|
503 * @param {Number} c |
|
504 * @param {Number} d |
|
505 * @param {Number} dx |
|
506 * @param {Number} dy |
|
507 */ |
|
508 multiply: function(a, b, c, d, dx, dy) { |
|
509 var matrix = this, |
|
510 matrix_a = matrix.a * a + matrix.c * b, |
|
511 matrix_b = matrix.b * a + matrix.d * b, |
|
512 matrix_c = matrix.a * c + matrix.c * d, |
|
513 matrix_d = matrix.b * c + matrix.d * d, |
|
514 matrix_dx = matrix.a * dx + matrix.c * dy + matrix.dx, |
|
515 matrix_dy = matrix.b * dx + matrix.d * dy + matrix.dy; |
|
516 |
|
517 matrix.a = this._round(matrix_a); |
|
518 matrix.b = this._round(matrix_b); |
|
519 matrix.c = this._round(matrix_c); |
|
520 matrix.d = this._round(matrix_d); |
|
521 matrix.dx = this._round(matrix_dx); |
|
522 matrix.dy = this._round(matrix_dy); |
|
523 return this; |
|
524 }, |
|
525 |
|
526 /** |
|
527 * Parses a string and updates the matrix. |
|
528 * |
|
529 * @method applyCSSText |
|
530 * @param {String} val A css transform string |
|
531 */ |
|
532 applyCSSText: function(val) { |
|
533 var re = /\s*([a-z]*)\(([\w,\.,\-,\s]*)\)/gi, |
|
534 args, |
|
535 m; |
|
536 |
|
537 val = val.replace(/matrix/g, "multiply"); |
|
538 while ((m = re.exec(val))) { |
|
539 if (typeof this[m[1]] === 'function') { |
|
540 args = m[2].split(','); |
|
541 this[m[1]].apply(this, args); |
|
542 } |
|
543 } |
|
544 }, |
|
545 |
|
546 /** |
|
547 * Parses a string and returns an array of transform arrays. |
|
548 * |
|
549 * @method getTransformArray |
|
550 * @param {String} val A css transform string |
|
551 * @return Array |
|
552 */ |
|
553 getTransformArray: function(val) { |
|
554 var re = /\s*([a-z]*)\(([\w,\.,\-,\s]*)\)/gi, |
|
555 transforms = [], |
|
556 args, |
|
557 m; |
|
558 |
|
559 val = val.replace(/matrix/g, "multiply"); |
|
560 while ((m = re.exec(val))) { |
|
561 if (typeof this[m[1]] === 'function') { |
|
562 args = m[2].split(','); |
|
563 args.unshift(m[1]); |
|
564 transforms.push(args); |
|
565 } |
|
566 } |
|
567 return transforms; |
|
568 }, |
|
569 |
|
570 /** |
|
571 * Default values for the matrix |
|
572 * |
|
573 * @property _defaults |
|
574 * @private |
|
575 */ |
|
576 _defaults: { |
|
577 a: 1, |
|
578 b: 0, |
|
579 c: 0, |
|
580 d: 1, |
|
581 dx: 0, |
|
582 dy: 0 |
|
583 }, |
|
584 |
|
585 /** |
|
586 * Rounds values |
|
587 * |
|
588 * @method _round |
|
589 * @private |
|
590 */ |
|
591 _round: function(val) { |
|
592 val = Math.round(val * this._rounder) / this._rounder; |
|
593 return val; |
|
594 }, |
|
595 |
|
596 /** |
|
597 * Initializes a matrix. |
|
598 * |
|
599 * @method init |
|
600 * @param {Object} config Specified key value pairs for matrix properties. If a property is not explicitly defined in the config argument, |
|
601 * the default value will be used. |
|
602 */ |
|
603 init: function(config) { |
|
604 var defaults = this._defaults, |
|
605 prop; |
|
606 |
|
607 config = config || {}; |
|
608 |
|
609 for (prop in defaults) { |
|
610 if(defaults.hasOwnProperty(prop)) |
|
611 { |
|
612 this[prop] = (prop in config) ? config[prop] : defaults[prop]; |
|
613 } |
|
614 } |
|
615 |
|
616 this._config = config; |
|
617 }, |
|
618 |
|
619 /** |
|
620 * Applies a scale transform |
|
621 * |
|
622 * @method scale |
|
623 * @param {Number} val |
|
624 */ |
|
625 scale: function(x, y) { |
|
626 this.multiply(x, 0, 0, y, 0, 0); |
|
627 return this; |
|
628 }, |
|
629 |
|
630 /** |
|
631 * Applies a skew transformation. |
|
632 * |
|
633 * @method skew |
|
634 * @param {Number} x The value to skew on the x-axis. |
|
635 * @param {Number} y The value to skew on the y-axis. |
|
636 */ |
|
637 skew: function(x, y) { |
|
638 x = x || 0; |
|
639 y = y || 0; |
|
640 |
|
641 if (x !== undefined) { // null or undef |
|
642 x = Math.tan(this.angle2rad(x)); |
|
643 |
|
644 } |
|
645 |
|
646 if (y !== undefined) { // null or undef |
|
647 y = Math.tan(this.angle2rad(y)); |
|
648 } |
|
649 |
|
650 this.multiply(1, y, x, 1, 0, 0); |
|
651 return this; |
|
652 }, |
|
653 |
|
654 /** |
|
655 * Applies a skew to the x-coordinate |
|
656 * |
|
657 * @method skewX |
|
658 * @param {Number} x x-coordinate |
|
659 */ |
|
660 skewX: function(x) { |
|
661 this.skew(x); |
|
662 return this; |
|
663 }, |
|
664 |
|
665 /** |
|
666 * Applies a skew to the y-coordinate |
|
667 * |
|
668 * @method skewY |
|
669 * @param {Number} y y-coordinate |
|
670 */ |
|
671 skewY: function(y) { |
|
672 this.skew(null, y); |
|
673 return this; |
|
674 }, |
|
675 |
|
676 /** |
|
677 * Returns a string of text that can be used to populate a the css transform property of an element. |
|
678 * |
|
679 * @method toCSSText |
|
680 * @return String |
|
681 */ |
|
682 toCSSText: function() { |
|
683 var matrix = this, |
|
684 text = 'matrix(' + |
|
685 matrix.a + ',' + |
|
686 matrix.b + ',' + |
|
687 matrix.c + ',' + |
|
688 matrix.d + ',' + |
|
689 matrix.dx + ',' + |
|
690 matrix.dy + ')'; |
|
691 return text; |
|
692 }, |
|
693 |
|
694 /** |
|
695 * Returns a string that can be used to populate the css filter property of an element. |
|
696 * |
|
697 * @method toFilterText |
|
698 * @return String |
|
699 */ |
|
700 toFilterText: function() { |
|
701 var matrix = this, |
|
702 text = 'progid:DXImageTransform.Microsoft.Matrix('; |
|
703 text += 'M11=' + matrix.a + ',' + |
|
704 'M21=' + matrix.b + ',' + |
|
705 'M12=' + matrix.c + ',' + |
|
706 'M22=' + matrix.d + ',' + |
|
707 'sizingMethod="auto expand")'; |
|
708 |
|
709 text += ''; |
|
710 |
|
711 return text; |
|
712 }, |
|
713 |
|
714 /** |
|
715 * Converts a radian value to a degree. |
|
716 * |
|
717 * @method rad2deg |
|
718 * @param {Number} rad Radian value to be converted. |
|
719 * @return Number |
|
720 */ |
|
721 rad2deg: function(rad) { |
|
722 var deg = rad * (180 / Math.PI); |
|
723 return deg; |
|
724 }, |
|
725 |
|
726 /** |
|
727 * Converts a degree value to a radian. |
|
728 * |
|
729 * @method deg2rad |
|
730 * @param {Number} deg Degree value to be converted to radian. |
|
731 * @return Number |
|
732 */ |
|
733 deg2rad: function(deg) { |
|
734 var rad = deg * (Math.PI / 180); |
|
735 return rad; |
|
736 }, |
|
737 |
|
738 angle2rad: function(val) { |
|
739 if (typeof val === 'string' && val.indexOf('rad') > -1) { |
|
740 val = parseFloat(val); |
|
741 } else { // default to deg |
|
742 val = this.deg2rad(parseFloat(val)); |
|
743 } |
|
744 |
|
745 return val; |
|
746 }, |
|
747 |
|
748 /** |
|
749 * Applies a rotate transform. |
|
750 * |
|
751 * @method rotate |
|
752 * @param {Number} deg The degree of the rotation. |
|
753 */ |
|
754 rotate: function(deg, x, y) { |
|
755 var rad = this.angle2rad(deg), |
|
756 sin = Math.sin(rad), |
|
757 cos = Math.cos(rad); |
|
758 this.multiply(cos, sin, 0 - sin, cos, 0, 0); |
|
759 return this; |
|
760 }, |
|
761 |
|
762 /** |
|
763 * Applies translate transformation. |
|
764 * |
|
765 * @method translate |
|
766 * @param {Number} x The value to transate on the x-axis. |
|
767 * @param {Number} y The value to translate on the y-axis. |
|
768 */ |
|
769 translate: function(x, y) { |
|
770 x = parseFloat(x) || 0; |
|
771 y = parseFloat(y) || 0; |
|
772 this.multiply(1, 0, 0, 1, x, y); |
|
773 return this; |
|
774 }, |
|
775 |
|
776 /** |
|
777 * Applies a translate to the x-coordinate |
|
778 * |
|
779 * @method translateX |
|
780 * @param {Number} x x-coordinate |
|
781 */ |
|
782 translateX: function(x) { |
|
783 this.translate(x); |
|
784 return this; |
|
785 }, |
|
786 |
|
787 /** |
|
788 * Applies a translate to the y-coordinate |
|
789 * |
|
790 * @method translateY |
|
791 * @param {Number} y y-coordinate |
|
792 */ |
|
793 translateY: function(y) { |
|
794 this.translate(null, y); |
|
795 return this; |
|
796 }, |
|
797 |
|
798 |
|
799 /** |
|
800 * Returns an identity matrix. |
|
801 * |
|
802 * @method identity |
|
803 * @return Object |
|
804 */ |
|
805 identity: function() { |
|
806 var config = this._config, |
|
807 defaults = this._defaults, |
|
808 prop; |
|
809 |
|
810 for (prop in config) { |
|
811 if (prop in defaults) { |
|
812 this[prop] = defaults[prop]; |
|
813 } |
|
814 } |
|
815 return this; |
|
816 }, |
|
817 |
|
818 /** |
|
819 * Returns a 3x3 Matrix array |
|
820 * |
|
821 * / \ |
|
822 * | matrix[0][0] matrix[1][0] matrix[2][0] | |
|
823 * | matrix[0][1] matrix[1][1] matrix[2][1] | |
|
824 * | matrix[0][2] matrix[1][2] matrix[2][2] | |
|
825 * \ / |
|
826 * |
|
827 * @method getMatrixArray |
|
828 * @return Array |
|
829 */ |
|
830 getMatrixArray: function() |
|
831 { |
|
832 var matrix = this, |
|
833 matrixArray = [ |
|
834 [matrix.a, matrix.c, matrix.dx], |
|
835 [matrix.b, matrix.d, matrix.dy], |
|
836 [0, 0, 1] |
|
837 ]; |
|
838 return matrixArray; |
|
839 }, |
|
840 |
|
841 /** |
|
842 * Returns the left, top, right and bottom coordinates for a transformed |
|
843 * item. |
|
844 * |
|
845 * @method getContentRect |
|
846 * @param {Number} width The width of the item. |
|
847 * @param {Number} height The height of the item. |
|
848 * @param {Number} x The x-coordinate of the item. |
|
849 * @param {Number} y The y-coordinate of the item. |
|
850 * @return Object |
|
851 */ |
|
852 getContentRect: function(width, height, x, y) |
|
853 { |
|
854 var left = !isNaN(x) ? x : 0, |
|
855 top = !isNaN(y) ? y : 0, |
|
856 right = left + width, |
|
857 bottom = top + height, |
|
858 matrix = this, |
|
859 a = matrix.a, |
|
860 b = matrix.b, |
|
861 c = matrix.c, |
|
862 d = matrix.d, |
|
863 dx = matrix.dx, |
|
864 dy = matrix.dy, |
|
865 x1 = (a * left + c * top + dx), |
|
866 y1 = (b * left + d * top + dy), |
|
867 //[x2, y2] |
|
868 x2 = (a * right + c * top + dx), |
|
869 y2 = (b * right + d * top + dy), |
|
870 //[x3, y3] |
|
871 x3 = (a * left + c * bottom + dx), |
|
872 y3 = (b * left + d * bottom + dy), |
|
873 //[x4, y4] |
|
874 x4 = (a * right + c * bottom + dx), |
|
875 y4 = (b * right + d * bottom + dy); |
|
876 return { |
|
877 left: Math.min(x3, Math.min(x1, Math.min(x2, x4))), |
|
878 right: Math.max(x3, Math.max(x1, Math.max(x2, x4))), |
|
879 top: Math.min(y2, Math.min(y4, Math.min(y3, y1))), |
|
880 bottom: Math.max(y2, Math.max(y4, Math.max(y3, y1))) |
|
881 }; |
|
882 }, |
|
883 |
|
884 /** |
|
885 * Returns the determinant of the matrix. |
|
886 * |
|
887 * @method getDeterminant |
|
888 * @return Number |
|
889 */ |
|
890 getDeterminant: function() |
|
891 { |
|
892 return Y.MatrixUtil.getDeterminant(this.getMatrixArray()); |
|
893 }, |
|
894 |
|
895 /** |
|
896 * Returns the inverse (in array form) of the matrix. |
|
897 * |
|
898 * @method inverse |
|
899 * @return Array |
|
900 */ |
|
901 inverse: function() |
|
902 { |
|
903 return Y.MatrixUtil.inverse(this.getMatrixArray()); |
|
904 }, |
|
905 |
|
906 /** |
|
907 * Returns the transpose of the matrix |
|
908 * |
|
909 * @method transpose |
|
910 * @return Array |
|
911 */ |
|
912 transpose: function() |
|
913 { |
|
914 return Y.MatrixUtil.transpose(this.getMatrixArray()); |
|
915 }, |
|
916 |
|
917 /** |
|
918 * Returns an array of transform commands that represent the matrix. |
|
919 * |
|
920 * @method decompose |
|
921 * @return Array |
|
922 */ |
|
923 decompose: function() |
|
924 { |
|
925 return Y.MatrixUtil.decompose(this.getMatrixArray()); |
|
926 } |
|
927 }; |
|
928 |
|
929 Y.Matrix = Matrix; |
|
930 |
|
931 |
|
932 }, '@VERSION@', {"requires": ["yui-base"]}); |