1 /**
  2  * Hilo
  3  * Copyright 2015 alibaba.com
  4  * Licensed under the MIT License
  5  */
  6 
  7 /**
  8  * @class Matrix类表示一个转换矩阵,它确定如何将点从一个坐标空间映射到另一个坐标空间。
  9  * @param {Number} a 缩放或旋转图像时影响像素沿 x 轴定位的值。
 10  * @param {Number} b 旋转或倾斜图像时影响像素沿 y 轴定位的值。
 11  * @param {Number} c 旋转或倾斜图像时影响像素沿 x 轴定位的值。
 12  * @param {Number} d 缩放或旋转图像时影响像素沿 y 轴定位的值。
 13  * @param {Number} tx 沿 x 轴平移每个点的距离。
 14  * @param {Number} ty 沿 y 轴平移每个点的距离。
 15  * @module hilo/geom/Matrix
 16  * @requires hilo/core/Class
 17  */
 18 var Matrix = Class.create(/** @lends Matrix.prototype */{
 19     constructor: function(a, b, c, d, tx, ty){
 20         this.a = a;
 21         this.b = b;
 22         this.c = c;
 23         this.d = d;
 24         this.tx = tx;
 25         this.ty = ty;
 26     },
 27 
 28     /**
 29      * 将某个矩阵与当前矩阵连接,从而将这两个矩阵的几何效果有效地结合在一起。
 30      * @param {Matrix} mtx 要连接到源矩阵的矩阵。
 31      * @returns {Matrix} 一个Matrix对象。
 32      */
 33     concat: function(mtx){
 34         var args = arguments,
 35             a = this.a, b = this.b, c = this.c, d = this.d,
 36             tx = this.tx, ty = this.ty;
 37 
 38         if(args.length >= 6){
 39             var ma = args[0], mb = args[1], mc = args[2],
 40                 md = args[3], mx = args[4], my = args[5];
 41         }else{
 42             ma = mtx.a;
 43             mb = mtx.b;
 44             mc = mtx.c;
 45             md = mtx.d;
 46             mx = mtx.tx;
 47             my = mtx.ty;
 48         }
 49 
 50         this.a = a * ma + b * mc;
 51         this.b = a * mb + b * md;
 52         this.c = c * ma + d * mc;
 53         this.d = c * mb + d * md;
 54         this.tx = tx * ma + ty * mc + mx;
 55         this.ty = tx * mb + ty * md + my;
 56         return this;
 57     },
 58 
 59     /**
 60      * 对 Matrix 对象应用旋转转换。
 61      * @param {Number} angle 旋转的角度。
 62      * @returns {Matrix} 一个Matrix对象。
 63      */
 64     rotate: function(angle){
 65         var sin = Math.sin(angle), cos = Math.cos(angle),
 66             a = this.a, b = this.b, c = this.c, d = this.d,
 67             tx = this.tx, ty = this.ty;
 68 
 69         this.a = a * cos - b * sin;
 70         this.b = a * sin + b * cos;
 71         this.c = c * cos - d * sin;
 72         this.d = c * sin + d * cos;
 73         this.tx = tx * cos - ty * sin;
 74         this.ty = tx * sin + ty * cos;
 75         return this;
 76     },
 77 
 78     /**
 79      * 对矩阵应用缩放转换。
 80      * @param {Number} sx 用于沿 x 轴缩放对象的乘数。
 81      * @param {Number} sy 用于沿 y 轴缩放对象的乘数。
 82      * @returns {Matrix} 一个Matrix对象。
 83      */
 84     scale: function(sx, sy){
 85         this.a *= sx;
 86         this.d *= sy;
 87         this.c *= sx;
 88         this.b *= sy;
 89         this.tx *= sx;
 90         this.ty *= sy;
 91         return this;
 92     },
 93 
 94     /**
 95      * 沿 x 和 y 轴平移矩阵,由 dx 和 dy 参数指定。
 96      * @param {Number} dx 沿 x 轴向右移动的量(以像素为单位)。
 97      * @param {Number} dy 沿 y 轴向右移动的量(以像素为单位)。
 98      * @returns {Matrix} 一个Matrix对象。
 99      */
100     translate: function(dx, dy){
101         this.tx += dx;
102         this.ty += dy;
103         return this;
104     },
105 
106     /**
107      * 为每个矩阵属性设置一个值,该值将导致 null 转换。通过应用恒等矩阵转换的对象将与原始对象完全相同。
108      * @returns {Matrix} 一个Matrix对象。
109      */
110     identity: function(){
111         this.a = this.d = 1;
112         this.b = this.c = this.tx = this.ty = 0;
113         return this;
114     },
115 
116     /**
117      * 执行原始矩阵的逆转换。您可以将一个逆矩阵应用于对象来撤消在应用原始矩阵时执行的转换。
118      * @returns {Matrix} 一个Matrix对象。
119      */
120     invert: function(){
121         var a = this.a;
122         var b = this.b;
123         var c = this.c;
124         var d = this.d;
125         var tx = this.tx;
126         var i = a * d - b * c;
127 
128         this.a = d / i;
129         this.b = -b / i;
130         this.c = -c / i;
131         this.d = a / i;
132         this.tx = (c * this.ty - d * tx) / i;
133         this.ty = -(a * this.ty - b * tx) / i;
134         return this;
135     },
136 
137     /**
138      * 返回将 Matrix 对象表示的几何转换应用于指定点所产生的结果。
139      * @param {Object} point 想要获得其矩阵转换结果的点。
140      * @param {Boolean} round 是否对点的坐标进行向上取整。
141      * @param {Boolean} returnNew 是否返回一个新的点。
142      * @returns {Object} 由应用矩阵转换所产生的点。
143      */
144     transformPoint: function(point, round, returnNew){
145         var x = point.x * this.a + point.y * this.c + this.tx,
146             y = point.x * this.b + point.y * this.d + this.ty;
147 
148         if(round){
149             x = x + 0.5 >> 0;
150             y = y + 0.5 >> 0;
151         }
152         if(returnNew) return {x:x, y:y};
153         point.x = x;
154         point.y = y;
155         return point;
156     }
157 
158 });