1 /****************************************************************************
  2  Copyright (c) 2008-2010 Ricardo Quesada
  3  Copyright (c) 2011-2012 cocos2d-x.org
  4  Copyright (c) 2013-2014 Chukong Technologies Inc.
  5 
  6  http://www.cocos2d-x.org
  7 
  8  Permission is hereby granted, free of charge, to any person obtaining a copy
  9  of this software and associated documentation files (the "Software"), to deal
 10  in the Software without restriction, including without limitation the rights
 11  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 12  copies of the Software, and to permit persons to whom the Software is
 13  furnished to do so, subject to the following conditions:
 14 
 15  The above copyright notice and this permission notice shall be included in
 16  all copies or substantial portions of the Software.
 17 
 18  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 19  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 20  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 21  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 22  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 23  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 24  THE SOFTWARE.
 25  ****************************************************************************/
 26 
 27 /**
 28  * <p>cc.AffineTransform class represent an affine transform matrix. It's composed basically by translation, rotation, scale transformations.<br/>
 29  * Please do not use its constructor directly, use cc.affineTransformMake alias function instead.
 30  * </p>
 31  * @class cc.AffineTransform
 32  * @param {Number} a
 33  * @param {Number} b
 34  * @param {Number} c
 35  * @param {Number} d
 36  * @param {Number} tx
 37  * @param {Number} ty
 38  * @see cc.affineTransformMake
 39  */
 40 cc.AffineTransform = function (a, b, c, d, tx, ty) {
 41     this.a = a;
 42     this.b = b;
 43     this.c = c;
 44     this.d = d;
 45     this.tx = tx;
 46     this.ty = ty;
 47 };
 48 
 49 /**
 50  * Create a cc.AffineTransform object with all contents in the matrix
 51  * @function
 52  * 
 53  * @param {Number} a
 54  * @param {Number} b
 55  * @param {Number} c
 56  * @param {Number} d
 57  * @param {Number} tx
 58  * @param {Number} ty
 59  * @return {cc.AffineTransform}
 60  */
 61 cc.affineTransformMake = function (a, b, c, d, tx, ty) {
 62     return {a: a, b: b, c: c, d: d, tx: tx, ty: ty};
 63 };
 64 
 65 /**
 66  * Apply the affine transformation on a point.
 67  * @function
 68  * 
 69  * @param {cc.Point|Number} point or x
 70  * @param {cc.AffineTransform|Number} transOrY transform matrix or y
 71  * @param {cc.AffineTransform} t transform matrix or y
 72  * @return {cc.Point}
 73  */
 74 cc.pointApplyAffineTransform = function (point, transOrY, t) {
 75     var x, y;
 76     if (t === undefined) {
 77         t = transOrY;
 78         x = point.x;
 79         y = point.y;
 80     } else {
 81         x = point;
 82         y = transOrY;
 83     }
 84     return {x: t.a * x + t.c * y + t.tx, y: t.b * x + t.d * y + t.ty};
 85 };
 86 
 87 cc._pointApplyAffineTransform = function (x, y, t) {   //it will remove.
 88     return cc.pointApplyAffineTransform(x, y, t);
 89 };
 90 
 91 /**
 92  * Apply the affine transformation on a size.
 93  * @function
 94  * 
 95  * @param {cc.Size} size
 96  * @param {cc.AffineTransform} t
 97  * @return {cc.Size}
 98  */
 99 cc.sizeApplyAffineTransform = function (size, t) {
100     return {width: t.a * size.width + t.c * size.height, height: t.b * size.width + t.d * size.height};
101 };
102 
103 /**
104  * <p>Create a identity transformation matrix: <br/>
105  * [ 1, 0, 0, <br/>
106  *   0, 1, 0 ]</p>
107  * @function
108  * 
109  * @return {cc.AffineTransform}
110  */
111 cc.affineTransformMakeIdentity = function () {
112     return {a: 1.0, b: 0.0, c: 0.0, d: 1.0, tx: 0.0, ty: 0.0};
113 };
114 
115 /**
116  * <p>Create a identity transformation matrix: <br/>
117  * [ 1, 0, 0, <br/>
118  *   0, 1, 0 ]</p>
119  * @function
120  * 
121  * @return {cc.AffineTransform}
122  * @deprecated since v3.0, please use cc.affineTransformMakeIdentity() instead
123  * @see cc.affineTransformMakeIdentity
124  */
125 cc.affineTransformIdentity = function () {
126     return {a: 1.0, b: 0.0, c: 0.0, d: 1.0, tx: 0.0, ty: 0.0};
127 };
128 
129 /**
130  * Apply the affine transformation on a rect.
131  * @function
132  * 
133  * @param {cc.Rect} rect
134  * @param {cc.AffineTransform} anAffineTransform
135  * @return {cc.Rect}
136  */
137 cc.rectApplyAffineTransform = function (rect, anAffineTransform) {
138     var top = cc.rectGetMinY(rect);
139     var left = cc.rectGetMinX(rect);
140     var right = cc.rectGetMaxX(rect);
141     var bottom = cc.rectGetMaxY(rect);
142 
143     var topLeft = cc.pointApplyAffineTransform(left, top, anAffineTransform);
144     var topRight = cc.pointApplyAffineTransform(right, top, anAffineTransform);
145     var bottomLeft = cc.pointApplyAffineTransform(left, bottom, anAffineTransform);
146     var bottomRight = cc.pointApplyAffineTransform(right, bottom, anAffineTransform);
147 
148     var minX = Math.min(topLeft.x, topRight.x, bottomLeft.x, bottomRight.x);
149     var maxX = Math.max(topLeft.x, topRight.x, bottomLeft.x, bottomRight.x);
150     var minY = Math.min(topLeft.y, topRight.y, bottomLeft.y, bottomRight.y);
151     var maxY = Math.max(topLeft.y, topRight.y, bottomLeft.y, bottomRight.y);
152 
153     return cc.rect(minX, minY, (maxX - minX), (maxY - minY));
154 };
155 
156 cc._rectApplyAffineTransformIn = function(rect, anAffineTransform){
157     var top = cc.rectGetMinY(rect);
158     var left = cc.rectGetMinX(rect);
159     var right = cc.rectGetMaxX(rect);
160     var bottom = cc.rectGetMaxY(rect);
161 
162     var topLeft = cc.pointApplyAffineTransform(left, top, anAffineTransform);
163     var topRight = cc.pointApplyAffineTransform(right, top, anAffineTransform);
164     var bottomLeft = cc.pointApplyAffineTransform(left, bottom, anAffineTransform);
165     var bottomRight = cc.pointApplyAffineTransform(right, bottom, anAffineTransform);
166 
167     var minX = Math.min(topLeft.x, topRight.x, bottomLeft.x, bottomRight.x);
168     var maxX = Math.max(topLeft.x, topRight.x, bottomLeft.x, bottomRight.x);
169     var minY = Math.min(topLeft.y, topRight.y, bottomLeft.y, bottomRight.y);
170     var maxY = Math.max(topLeft.y, topRight.y, bottomLeft.y, bottomRight.y);
171 
172     rect.x = minX;
173     rect.y = minY;
174     rect.width = maxX - minX;
175     rect.height = maxY - minY;
176     return rect;
177 };
178 
179 /**
180  * Create a new affine transformation with a base transformation matrix and a translation based on it.
181  * @function
182  * 
183  * @param {cc.AffineTransform} t The base affine transform object
184  * @param {Number} tx The translation on x axis
185  * @param {Number} ty The translation on y axis
186  * @return {cc.AffineTransform}
187  */
188 cc.affineTransformTranslate = function (t, tx, ty) {
189     return {
190         a: t.a,
191         b: t.b,
192         c: t.c,
193         d: t.d,
194         tx: t.tx + t.a * tx + t.c * ty,
195         ty: t.ty + t.b * tx + t.d * ty
196     };
197 };
198 
199 /**
200  * Create a new affine transformation with a base transformation matrix and a scale based on it.
201  * @function
202  * @param {cc.AffineTransform} t The base affine transform object
203  * @param {Number} sx The scale on x axis
204  * @param {Number} sy The scale on y axis
205  * @return {cc.AffineTransform}
206  */
207 cc.affineTransformScale = function (t, sx, sy) {
208     return {a: t.a * sx, b: t.b * sx, c: t.c * sy, d: t.d * sy, tx: t.tx, ty: t.ty};
209 };
210 
211 /**
212  * Create a new affine transformation with a base transformation matrix and a rotation based on it.
213  * @function
214  * @param {cc.AffineTransform} aTransform The base affine transform object
215  * @param {Number} anAngle  The angle to rotate
216  * @return {cc.AffineTransform}
217  */
218 cc.affineTransformRotate = function (aTransform, anAngle) {
219     var fSin = Math.sin(anAngle);
220     var fCos = Math.cos(anAngle);
221 
222     return {a: aTransform.a * fCos + aTransform.c * fSin,
223         b: aTransform.b * fCos + aTransform.d * fSin,
224         c: aTransform.c * fCos - aTransform.a * fSin,
225         d: aTransform.d * fCos - aTransform.b * fSin,
226         tx: aTransform.tx,
227         ty: aTransform.ty};
228 };
229 
230 /**
231  * Concatenate a transform matrix to another and return the result:<br/>
232  * t' = t1 * t2
233  * @function
234  * @param {cc.AffineTransform} t1 The first transform object
235  * @param {cc.AffineTransform} t2 The transform object to concatenate
236  * @return {cc.AffineTransform} The result of concatenation
237  */
238 cc.affineTransformConcat = function (t1, t2) {
239     return {a: t1.a * t2.a + t1.b * t2.c,                          //a
240         b: t1.a * t2.b + t1.b * t2.d,                               //b
241         c: t1.c * t2.a + t1.d * t2.c,                               //c
242         d: t1.c * t2.b + t1.d * t2.d,                               //d
243         tx: t1.tx * t2.a + t1.ty * t2.c + t2.tx,                    //tx
244         ty: t1.tx * t2.b + t1.ty * t2.d + t2.ty};				    //ty
245 };
246 
247 /**
248  * Return true if an affine transform equals to another, false otherwise.
249  * @function
250  * @param {cc.AffineTransform} t1
251  * @param {cc.AffineTransform} t2
252  * @return {Boolean}
253  */
254 cc.affineTransformEqualToTransform = function (t1, t2) {
255     return ((t1.a === t2.a) && (t1.b === t2.b) && (t1.c === t2.c) && (t1.d === t2.d) && (t1.tx === t2.tx) && (t1.ty === t2.ty));
256 };
257 
258 /**
259  * Get the invert transform of an AffineTransform object
260  * @function
261  * @param {cc.AffineTransform} t
262  * @return {cc.AffineTransform} The inverted transform object
263  */
264 cc.affineTransformInvert = function (t) {
265     var determinant = 1 / (t.a * t.d - t.b * t.c);
266     return {a: determinant * t.d, b: -determinant * t.b, c: -determinant * t.c, d: determinant * t.a,
267         tx: determinant * (t.c * t.ty - t.d * t.tx), ty: determinant * (t.b * t.tx - t.a * t.ty)};
268 };
269