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} point
 70  * @param {cc.AffineTransform} t
 71  * @return {cc.Point}
 72  */
 73 cc.pointApplyAffineTransform = function (point, t) {
 74     return {x: t.a * point.x + t.c * point.y + t.tx, y: t.b * point.x + t.d * point.y + t.ty};
 75 };
 76 
 77 cc._pointApplyAffineTransform = function (x, y, t) {
 78     return {x: t.a * x + t.c * y + t.tx,
 79         y: t.b * x + t.d * y + t.ty};
 80 };
 81 
 82 /**
 83  * Apply the affine transformation on a size.
 84  * @function
 85  * 
 86  * @param {cc.Size} size
 87  * @param {cc.AffineTransform} t
 88  * @return {cc.Size}
 89  */
 90 cc.sizeApplyAffineTransform = function (size, t) {
 91     return {width: t.a * size.width + t.c * size.height, height: t.b * size.width + t.d * size.height};
 92 };
 93 
 94 /**
 95  * <p>Create a identity transformation matrix: <br/>
 96  * [ 1, 0, 0, <br/>
 97  *   0, 1, 0 ]</p>
 98  * @function
 99  * 
100  * @return {cc.AffineTransform}
101  */
102 cc.affineTransformMakeIdentity = function () {
103     return {a: 1.0, b: 0.0, c: 0.0, d: 1.0, tx: 0.0, ty: 0.0};
104 };
105 
106 /**
107  * <p>Create a identity transformation matrix: <br/>
108  * [ 1, 0, 0, <br/>
109  *   0, 1, 0 ]</p>
110  * @function
111  * 
112  * @return {cc.AffineTransform}
113  * @deprecated since v3.0, please use cc.affineTransformMakeIdentity() instead
114  * @see cc.affineTransformMakeIdentity
115  */
116 cc.affineTransformIdentity = function () {
117     return {a: 1.0, b: 0.0, c: 0.0, d: 1.0, tx: 0.0, ty: 0.0};
118 };
119 
120 /**
121  * Apply the affine transformation on a rect.
122  * @function
123  * 
124  * @param {cc.Rect} rect
125  * @param {cc.AffineTransform} anAffineTransform
126  * @return {cc.Rect}
127  */
128 cc.rectApplyAffineTransform = function (rect, anAffineTransform) {
129     var top = cc.rectGetMinY(rect);
130     var left = cc.rectGetMinX(rect);
131     var right = cc.rectGetMaxX(rect);
132     var bottom = cc.rectGetMaxY(rect);
133 
134     var topLeft = cc._pointApplyAffineTransform(left, top, anAffineTransform);
135     var topRight = cc._pointApplyAffineTransform(right, top, anAffineTransform);
136     var bottomLeft = cc._pointApplyAffineTransform(left, bottom, anAffineTransform);
137     var bottomRight = cc._pointApplyAffineTransform(right, bottom, anAffineTransform);
138 
139     var minX = Math.min(topLeft.x, topRight.x, bottomLeft.x, bottomRight.x);
140     var maxX = Math.max(topLeft.x, topRight.x, bottomLeft.x, bottomRight.x);
141     var minY = Math.min(topLeft.y, topRight.y, bottomLeft.y, bottomRight.y);
142     var maxY = Math.max(topLeft.y, topRight.y, bottomLeft.y, bottomRight.y);
143 
144     return cc.rect(minX, minY, (maxX - minX), (maxY - minY));
145 };
146 
147 cc._rectApplyAffineTransformIn = function(rect, anAffineTransform){
148     var top = cc.rectGetMinY(rect);
149     var left = cc.rectGetMinX(rect);
150     var right = cc.rectGetMaxX(rect);
151     var bottom = cc.rectGetMaxY(rect);
152 
153     var topLeft = cc._pointApplyAffineTransform(left, top, anAffineTransform);
154     var topRight = cc._pointApplyAffineTransform(right, top, anAffineTransform);
155     var bottomLeft = cc._pointApplyAffineTransform(left, bottom, anAffineTransform);
156     var bottomRight = cc._pointApplyAffineTransform(right, bottom, anAffineTransform);
157 
158     var minX = Math.min(topLeft.x, topRight.x, bottomLeft.x, bottomRight.x);
159     var maxX = Math.max(topLeft.x, topRight.x, bottomLeft.x, bottomRight.x);
160     var minY = Math.min(topLeft.y, topRight.y, bottomLeft.y, bottomRight.y);
161     var maxY = Math.max(topLeft.y, topRight.y, bottomLeft.y, bottomRight.y);
162 
163     rect.x = minX;
164     rect.y = minY;
165     rect.width = maxX - minX;
166     rect.height = maxY - minY;
167     return rect;
168 };
169 
170 /**
171  * Create a new affine transformation with a base transformation matrix and a translation based on it.
172  * @function
173  * 
174  * @param {cc.AffineTransform} t The base affine transform object
175  * @param {Number} tx The translation on x axis
176  * @param {Number} ty The translation on y axis
177  * @return {cc.AffineTransform}
178  */
179 cc.affineTransformTranslate = function (t, tx, ty) {
180     return {
181         a: t.a,
182         b: t.b,
183         c: t.c,
184         d: t.d,
185         tx: t.tx + t.a * tx + t.c * ty,
186         ty: t.ty + t.b * tx + t.d * ty
187     };
188 };
189 
190 /**
191  * Create a new affine transformation with a base transformation matrix and a scale based on it.
192  * @function
193  * @param {cc.AffineTransform} t The base affine transform object
194  * @param {Number} sx The scale on x axis
195  * @param {Number} sy The scale on y axis
196  * @return {cc.AffineTransform}
197  */
198 cc.affineTransformScale = function (t, sx, sy) {
199     return {a: t.a * sx, b: t.b * sx, c: t.c * sy, d: t.d * sy, tx: t.tx, ty: t.ty};
200 };
201 
202 /**
203  * Create a new affine transformation with a base transformation matrix and a rotation based on it.
204  * @function
205  * @param {cc.AffineTransform} aTransform The base affine transform object
206  * @param {Number} anAngle  The angle to rotate
207  * @return {cc.AffineTransform}
208  */
209 cc.affineTransformRotate = function (aTransform, anAngle) {
210     var fSin = Math.sin(anAngle);
211     var fCos = Math.cos(anAngle);
212 
213     return {a: aTransform.a * fCos + aTransform.c * fSin,
214         b: aTransform.b * fCos + aTransform.d * fSin,
215         c: aTransform.c * fCos - aTransform.a * fSin,
216         d: aTransform.d * fCos - aTransform.b * fSin,
217         tx: aTransform.tx,
218         ty: aTransform.ty};
219 };
220 
221 /**
222  * Concatenate a transform matrix to another and return the result:<br/>
223  * t' = t1 * t2
224  * @function
225  * @param {cc.AffineTransform} t1 The first transform object
226  * @param {cc.AffineTransform} t2 The transform object to concatenate
227  * @return {cc.AffineTransform} The result of concatenation
228  */
229 cc.affineTransformConcat = function (t1, t2) {
230     return {a: t1.a * t2.a + t1.b * t2.c,                          //a
231         b: t1.a * t2.b + t1.b * t2.d,                               //b
232         c: t1.c * t2.a + t1.d * t2.c,                               //c
233         d: t1.c * t2.b + t1.d * t2.d,                               //d
234         tx: t1.tx * t2.a + t1.ty * t2.c + t2.tx,                    //tx
235         ty: t1.tx * t2.b + t1.ty * t2.d + t2.ty};				    //ty
236 };
237 
238 /**
239  * Return true if an affine transform equals to another, false otherwise.
240  * @function
241  * @param {cc.AffineTransform} t1
242  * @param {cc.AffineTransform} t2
243  * @return {Boolean}
244  */
245 cc.affineTransformEqualToTransform = function (t1, t2) {
246     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));
247 };
248 
249 /**
250  * Get the invert transform of an AffineTransform object
251  * @function
252  * @param {cc.AffineTransform} t
253  * @return {cc.AffineTransform} The inverted transform object
254  */
255 cc.affineTransformInvert = function (t) {
256     var determinant = 1 / (t.a * t.d - t.b * t.c);
257     return {a: determinant * t.d, b: -determinant * t.b, c: -determinant * t.c, d: determinant * t.a,
258         tx: determinant * (t.c * t.ty - t.d * t.tx), ty: determinant * (t.b * t.tx - t.a * t.ty)};
259 };
260