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.Point extensions based on Chipmunk's cpVect file.<br />
 29  * These extensions work both with cc.Point</p>
 30  *
 31  * <p>The "ccp" prefix means: "CoCos2d Point"</p>
 32  *
 33  * <p> //Examples:<br />
 34  * - cc.pAdd( cc.p(1,1), cc.p(2,2) ); // preferred cocos2d way<br />
 35  * - cc.pAdd( cc.p(1,1), cc.p(2,2) ); // also ok but more verbose<br />
 36  * - cc.pAdd( cc.cpv(1,1), cc.cpv(2,2) ); // mixing chipmunk and cocos2d (avoid)</p>
 37  */
 38 
 39 /**
 40  * smallest such that 1.0+FLT_EPSILON != 1.0
 41  * @constant
 42  * @type Number
 43  */
 44 cc.POINT_EPSILON = parseFloat('1.192092896e-07F');
 45 
 46 /**
 47  * Returns opposite of point.
 48  * @param {cc.Point} point
 49  * @return {cc.Point}
 50  */
 51 cc.pNeg = function (point) {
 52     return cc.p(-point.x, -point.y);
 53 };
 54 
 55 /**
 56  * Calculates sum of two points.
 57  * @param {cc.Point} v1
 58  * @param {cc.Point} v2
 59  * @return {cc.Point}
 60  */
 61 cc.pAdd = function (v1, v2) {
 62     return cc.p(v1.x + v2.x, v1.y + v2.y);
 63 };
 64 
 65 /**
 66  * Calculates difference of two points.
 67  * @param {cc.Point} v1
 68  * @param {cc.Point} v2
 69  * @return {cc.Point}
 70  */
 71 cc.pSub = function (v1, v2) {
 72     return cc.p(v1.x - v2.x, v1.y - v2.y);
 73 };
 74 
 75 /**
 76  * Returns point multiplied by given factor.
 77  * @param {cc.Point} point
 78  * @param {Number} floatVar
 79  * @return {cc.Point}
 80  */
 81 cc.pMult = function (point, floatVar) {
 82     return cc.p(point.x * floatVar, point.y * floatVar);
 83 };
 84 
 85 /**
 86  * Calculates midpoint between two points.
 87  * @param {cc.Point} v1
 88  * @param {cc.Point} v2
 89  * @return {cc.pMult}
 90  */
 91 cc.pMidpoint = function (v1, v2) {
 92     return cc.pMult(cc.pAdd(v1, v2), 0.5);
 93 };
 94 
 95 /**
 96  * Calculates dot product of two points.
 97  * @param {cc.Point} v1
 98  * @param {cc.Point} v2
 99  * @return {Number}
100  */
101 cc.pDot = function (v1, v2) {
102     return v1.x * v2.x + v1.y * v2.y;
103 };
104 
105 /**
106  * Calculates cross product of two points.
107  * @param {cc.Point} v1
108  * @param {cc.Point} v2
109  * @return {Number}
110  */
111 cc.pCross = function (v1, v2) {
112     return v1.x * v2.y - v1.y * v2.x;
113 };
114 
115 /**
116  * Calculates perpendicular of v, rotated 90 degrees counter-clockwise -- cross(v, perp(v)) >= 0
117  * @param {cc.Point} point
118  * @return {cc.Point}
119  */
120 cc.pPerp = function (point) {
121     return cc.p(-point.y, point.x);
122 };
123 
124 /**
125  * Calculates perpendicular of v, rotated 90 degrees clockwise -- cross(v, rperp(v)) <= 0
126  * @param {cc.Point} point
127  * @return {cc.Point}
128  */
129 cc.pRPerp = function (point) {
130     return cc.p(point.y, -point.x);
131 };
132 
133 /**
134  * Calculates the projection of v1 over v2.
135  * @param {cc.Point} v1
136  * @param {cc.Point} v2
137  * @return {cc.pMult}
138  */
139 cc.pProject = function (v1, v2) {
140     return cc.pMult(v2, cc.pDot(v1, v2) / cc.pDot(v2, v2));
141 };
142 
143 /**
144  * Rotates two points.
145  * @param  {cc.Point} v1
146  * @param  {cc.Point} v2
147  * @return {cc.Point}
148  */
149 cc.pRotate = function (v1, v2) {
150     return cc.p(v1.x * v2.x - v1.y * v2.y, v1.x * v2.y + v1.y * v2.x);
151 };
152 
153 /**
154  * Unrotates two points.
155  * @param  {cc.Point} v1
156  * @param  {cc.Point} v2
157  * @return {cc.Point}
158  */
159 cc.pUnrotate = function (v1, v2) {
160     return cc.p(v1.x * v2.x + v1.y * v2.y, v1.y * v2.x - v1.x * v2.y);
161 };
162 
163 /**
164  * Calculates the square length of a cc.Point (not calling sqrt() )
165  * @param  {cc.Point} v
166  *@return {Number}
167  */
168 cc.pLengthSQ = function (v) {
169     return cc.pDot(v, v);
170 };
171 
172 /**
173  * Calculates the square distance between two points (not calling sqrt() )
174  * @param {cc.Point} point1
175  * @param {cc.Point} point2
176  * @return {Number}
177  */
178 cc.pDistanceSQ = function(point1, point2){
179     return cc.pLengthSQ(cc.pSub(point1,point2));
180 };
181 
182 /**
183  * Calculates distance between point an origin
184  * @param  {cc.Point} v
185  * @return {Number}
186  */
187 cc.pLength = function (v) {
188     return Math.sqrt(cc.pLengthSQ(v));
189 };
190 
191 /**
192  * Calculates the distance between two points
193  * @param {cc.Point} v1
194  * @param {cc.Point} v2
195  * @return {Number}
196  */
197 cc.pDistance = function (v1, v2) {
198     return cc.pLength(cc.pSub(v1, v2));
199 };
200 
201 /**
202  * Returns point multiplied to a length of 1.
203  * @param {cc.Point} v
204  * @return {cc.Point}
205  */
206 cc.pNormalize = function (v) {
207     var n = cc.pLength(v);
208     return n === 0 ? cc.p(v) : cc.pMult(v, 1.0 / n);
209 };
210 
211 /**
212  * Converts radians to a normalized vector.
213  * @param {Number} a
214  * @return {cc.Point}
215  */
216 cc.pForAngle = function (a) {
217     return cc.p(Math.cos(a), Math.sin(a));
218 };
219 
220 /**
221  * Converts a vector to radians.
222  * @param {cc.Point} v
223  * @return {Number}
224  */
225 cc.pToAngle = function (v) {
226     return Math.atan2(v.y, v.x);
227 };
228 
229 /**
230  * Clamp a value between from and to.
231  * @param {Number} value
232  * @param {Number} min_inclusive
233  * @param {Number} max_inclusive
234  * @return {Number}
235  */
236 cc.clampf = function (value, min_inclusive, max_inclusive) {
237     if (min_inclusive > max_inclusive) {
238         var temp = min_inclusive;
239         min_inclusive = max_inclusive;
240         max_inclusive = temp;
241     }
242     return value < min_inclusive ? min_inclusive : value < max_inclusive ? value : max_inclusive;
243 };
244 
245 /**
246  * Clamp a point between from and to.
247  * @param {Point} p
248  * @param {Number} min_inclusive
249  * @param {Number} max_inclusive
250  * @return {cc.Point}
251  */
252 cc.pClamp = function (p, min_inclusive, max_inclusive) {
253     return cc.p(cc.clampf(p.x, min_inclusive.x, max_inclusive.x), cc.clampf(p.y, min_inclusive.y, max_inclusive.y));
254 };
255 
256 /**
257  * Quickly convert cc.Size to a cc.Point
258  * @param {cc.Size} s
259  * @return {cc.Point}
260  */
261 cc.pFromSize = function (s) {
262     return cc.p(s.width, s.height);
263 };
264 
265 /**
266  * Run a math operation function on each point component <br />
267  * Math.abs, Math.fllor, Math.ceil, Math.round.
268  * @param {cc.Point} p
269  * @param {Function} opFunc
270  * @return {cc.Point}
271  * @example
272  * //For example: let's try to take the floor of x,y
273  * var p = cc.pCompOp(cc.p(10,10),Math.abs);
274  */
275 cc.pCompOp = function (p, opFunc) {
276     return cc.p(opFunc(p.x), opFunc(p.y));
277 };
278 
279 /**
280  * Linear Interpolation between two points a and b
281  * alpha == 0 ? a
282  * alpha == 1 ? b
283  * otherwise a value between a..b
284  * @param {cc.Point} a
285  * @param {cc.Point} b
286  * @param {Number} alpha
287  * @return {cc.pAdd}
288  */
289 cc.pLerp = function (a, b, alpha) {
290     return cc.pAdd(cc.pMult(a, 1 - alpha), cc.pMult(b, alpha));
291 };
292 
293 /**
294  * @param {cc.Point} a
295  * @param {cc.Point} b
296  * @param {Number} variance
297  * @return {Boolean} if points have fuzzy equality which means equal with some degree of variance.
298  */
299 cc.pFuzzyEqual = function (a, b, variance) {
300     if (a.x - variance <= b.x && b.x <= a.x + variance) {
301         if (a.y - variance <= b.y && b.y <= a.y + variance)
302             return true;
303     }
304     return false;
305 };
306 
307 /**
308  * Multiplies a nd b components, a.x*b.x, a.y*b.y
309  * @param {cc.Point} a
310  * @param {cc.Point} b
311  * @return {cc.Point}
312  */
313 cc.pCompMult = function (a, b) {
314     return cc.p(a.x * b.x, a.y * b.y);
315 };
316 
317 /**
318  * @param {cc.Point} a
319  * @param {cc.Point} b
320  * @return {Number} the signed angle in radians between two vector directions
321  */
322 cc.pAngleSigned = function (a, b) {
323     var a2 = cc.pNormalize(a);
324     var b2 = cc.pNormalize(b);
325     var angle = Math.atan2(a2.x * b2.y - a2.y * b2.x, cc.pDot(a2, b2));
326     if (Math.abs(angle) < cc.POINT_EPSILON)
327         return 0.0;
328     return angle;
329 };
330 
331 /**
332  * @param {cc.Point} a
333  * @param {cc.Point} b
334  * @return {Number} the angle in radians between two vector directions
335  */
336 cc.pAngle = function (a, b) {
337     var angle = Math.acos(cc.pDot(cc.pNormalize(a), cc.pNormalize(b)));
338     if (Math.abs(angle) < cc.POINT_EPSILON) return 0.0;
339     return angle;
340 };
341 
342 /**
343  * Rotates a point counter clockwise by the angle around a pivot
344  * @param {cc.Point} v v is the point to rotate
345  * @param {cc.Point} pivot pivot is the pivot, naturally
346  * @param {Number} angle angle is the angle of rotation cw in radians
347  * @return {cc.Point} the rotated point
348  */
349 cc.pRotateByAngle = function (v, pivot, angle) {
350     var r = cc.pSub(v, pivot);
351     var cosa = Math.cos(angle), sina = Math.sin(angle);
352     var t = r.x;
353     r.x = t * cosa - r.y * sina + pivot.x;
354     r.y = t * sina + r.y * cosa + pivot.y;
355     return r;
356 };
357 
358 /**
359  * A general line-line intersection test
360  * indicating successful intersection of a line<br />
361  * note that to truly test intersection for segments we have to make<br />
362  * sure that s & t lie within [0..1] and for rays, make sure s & t > 0<br />
363  * the hit point is        p3 + t * (p4 - p3);<br />
364  * the hit point also is    p1 + s * (p2 - p1);
365  * @param {cc.Point} A A is the startpoint for the first line P1 = (p1 - p2).
366  * @param {cc.Point} B B is the endpoint for the first line P1 = (p1 - p2).
367  * @param {cc.Point} C C is the startpoint for the second line P2 = (p3 - p4).
368  * @param {cc.Point} D D is the endpoint for the second line P2 = (p3 - p4).
369  * @param {cc.Point} retP retP.x is the range for a hitpoint in P1 (pa = p1 + s*(p2 - p1)), <br />
370  * retP.y is the range for a hitpoint in P3 (pa = p2 + t*(p4 - p3)).
371  * @return {Boolean}
372  */
373 cc.pLineIntersect = function (A, B, C, D, retP) {
374     if ((A.x === B.x && A.y === B.y) || (C.x === D.x && C.y === D.y)) {
375         return false;
376     }
377     var BAx = B.x - A.x;
378     var BAy = B.y - A.y;
379     var DCx = D.x - C.x;
380     var DCy = D.y - C.y;
381     var ACx = A.x - C.x;
382     var ACy = A.y - C.y;
383 
384     var denom = DCy * BAx - DCx * BAy;
385 
386     retP.x = DCx * ACy - DCy * ACx;
387     retP.y = BAx * ACy - BAy * ACx;
388 
389     if (denom === 0) {
390         if (retP.x === 0 || retP.y === 0) {
391             // Lines incident
392             return true;
393         }
394         // Lines parallel and not incident
395         return false;
396     }
397 
398     retP.x = retP.x / denom;
399     retP.y = retP.y / denom;
400 
401     return true;
402 };
403 
404 /**
405  * ccpSegmentIntersect return YES if Segment A-B intersects with segment C-D.
406  * @param {cc.Point} A
407  * @param {cc.Point} B
408  * @param {cc.Point} C
409  * @param {cc.Point} D
410  * @return {Boolean}
411  */
412 cc.pSegmentIntersect = function (A, B, C, D) {
413     var retP = cc.p(0, 0);
414     if (cc.pLineIntersect(A, B, C, D, retP))
415         if (retP.x >= 0.0 && retP.x <= 1.0 && retP.y >= 0.0 && retP.y <= 1.0)
416             return true;
417     return false;
418 };
419 
420 /**
421  * ccpIntersectPoint return the intersection point of line A-B, C-D
422  * @param {cc.Point} A
423  * @param {cc.Point} B
424  * @param {cc.Point} C
425  * @param {cc.Point} D
426  * @return {cc.Point}
427  */
428 cc.pIntersectPoint = function (A, B, C, D) {
429     var retP = cc.p(0, 0);
430 
431     if (cc.pLineIntersect(A, B, C, D, retP)) {
432         // Point of intersection
433         var P = cc.p(0, 0);
434         P.x = A.x + retP.x * (B.x - A.x);
435         P.y = A.y + retP.x * (B.y - A.y);
436         return P;
437     }
438 
439     return cc.p(0,0);
440 };
441 
442 /**
443  * check to see if both points are equal
444  * @param {cc.Point} A A ccp a
445  * @param {cc.Point} B B ccp b to be compared
446  * @return {Boolean} the true if both ccp are same
447  */
448 cc.pSameAs = function (A, B) {
449     if ((A != null) && (B != null)) {
450         return (A.x === B.x && A.y === B.y);
451     }
452     return false;
453 };
454 
455 
456 
457 // High Perfomance In Place Operationrs ---------------------------------------
458 
459 /**
460  * sets the position of the point to 0
461  * @param {cc.Point} v
462  */
463 cc.pZeroIn = function(v) {
464     v.x = 0;
465     v.y = 0;
466 };
467 
468 /**
469  * copies the position of one point to another
470  * @param {cc.Point} v1
471  * @param {cc.Point} v2
472  */
473 cc.pIn = function(v1, v2) {
474     v1.x = v2.x;
475     v1.y = v2.y;
476 };
477 
478 /**
479  * multiplies the point with the given factor (inplace)
480  * @param {cc.Point} point
481  * @param {Number} floatVar
482  */
483 cc.pMultIn = function(point, floatVar) {
484     point.x *= floatVar;
485     point.y *= floatVar;
486 };
487 
488 /**
489  * subtracts one point from another (inplace)
490  * @param {cc.Point} v1
491  * @param {cc.Point} v2
492  */
493 cc.pSubIn = function(v1, v2) {
494     v1.x -= v2.x;
495     v1.y -= v2.y;
496 };
497 
498 /**
499  * adds one point to another (inplace)
500  * @param {cc.Point} v1
501  * @param {cc.point} v2
502  */
503 cc.pAddIn = function(v1, v2) {
504     v1.x += v2.x;
505     v1.y += v2.y;
506 };
507 
508 /**
509  * normalizes the point (inplace)
510  * @param {cc.Point} v
511  */
512 cc.pNormalizeIn = function(v) {
513     cc.pMultIn(v, 1.0 / Math.sqrt(v.x * v.x + v.y * v.y));
514 };
515 
516