From 1e452bf0bcb1042997fa6971a6003220583a6196 Mon Sep 17 00:00:00 2001 From: boyu0 Date: Mon, 26 Aug 2013 13:45:45 +0800 Subject: [PATCH] closed #2494: add isLineOverlap, isLineParallel, isSegmentOverlap method to Point. --- cocos2dx/cocoa/CCGeometry.cpp | 105 +++++++++++++++++++++------------- cocos2dx/cocoa/CCGeometry.h | 45 ++++++++++----- 2 files changed, 96 insertions(+), 54 deletions(-) diff --git a/cocos2dx/cocoa/CCGeometry.cpp b/cocos2dx/cocoa/CCGeometry.cpp index 59f0d750b4..e62247cbc4 100644 --- a/cocos2dx/cocoa/CCGeometry.cpp +++ b/cocos2dx/cocoa/CCGeometry.cpp @@ -116,7 +116,7 @@ Point Point::rotateByAngle(const Point& pivot, float angle) const return pivot + (*this - pivot).rotate(Point::forAngle(angle)); } -bool Point::isOneDemensionLineIntersect(float A, float B, float C, float D, float *S) +bool Point::isOneDemensionSegmentOverlap(float A, float B, float C, float D, float *S, float *E) { float ABmin = MIN(A, B); float ABmax = MAX(A, B); @@ -126,7 +126,6 @@ bool Point::isOneDemensionLineIntersect(float A, float B, float C, float D, floa if (ABmax < CDmin || CDmax < ABmin) { // ABmin->ABmax->CDmin->CDmax or CDmin->CDmax->ABmin->ABmax - *S = (CDmin - A) / (B - A); return false; } else @@ -134,17 +133,20 @@ bool Point::isOneDemensionLineIntersect(float A, float B, float C, float D, floa if (ABmin >= CDmin && ABmin <= CDmax) { // CDmin->ABmin->CDmax->ABmax or CDmin->ABmin->ABmax->CDmax - *S = ABmin==A ? 0 : 1; + if (S != nullptr) *S = ABmin; + if (E != nullptr) *E = CDmax < ABmax ? CDmax : ABmax; } else if (ABmax >= CDmin && ABmax <= CDmax) { // ABmin->CDmin->ABmax->CDmax - *S = ABmax==A ? 0 : 1; + if (S != nullptr) *S = CDmin; + if (E != nullptr) *E = ABmax; } else { // ABmin->CDmin->CDmax->ABmax - *S = (CDmin - A) / (B - A); + if (S != nullptr) *S = CDmin; + if (E != nullptr) *E = CDmax; } return true; } @@ -159,58 +161,83 @@ bool Point::isLineIntersect(const Point& A, const Point& B, { return false; } - const float BAx = B.x - A.x; - const float BAy = B.y - A.y; - const float DCx = D.x - C.x; - const float DCy = D.y - C.y; - const float ACx = A.x - C.x; - const float ACy = A.y - C.y; - const float denom = DCy*BAx - DCx*BAy; - - *S = DCx*ACy - DCy*ACx; - *T = BAx*ACy - BAy*ACx; + const float denom = crossProduct2Vector(A, B, C, D); if (denom == 0) { - if (*S == 0 || *T == 0) - { - // Lines incident - if (A.x != B.x) - { - isOneDemensionLineIntersect(A.x, B.x, C.x, D.x, S); - } - else - { - isOneDemensionLineIntersect(A.y, B.y, C.y, D.y, T); - } - - return true; - } - // Lines parallel and not incident + // Lines parallel or overlap return false; } - *S = *S / denom; - *T = *T / denom; - - // Point of intersection - // CGPoint P; - // P.x = A.x + *S * (B.x - A.x); - // P.y = A.y + *S * (B.y - A.y); + if (S != nullptr) *S = crossProduct2Vector(C, D, C, A) / denom; + if (T != nullptr) *T = crossProduct2Vector(A, B, C, A) / denom; return true; } +bool Point::isLineParallel(const Point& A, const Point& B, + const Point& C, const Point& D) +{ + // FAIL: Line undefined + if ( (A.x==B.x && A.y==B.y) || (C.x==D.x && C.y==D.y) ) + { + return false; + } + + if (crossProduct2Vector(A, B, C, D) == 0) + { + // line overlap + if (crossProduct2Vector(C, D, C, A) == 0 || crossProduct2Vector(A, B, C, A) == 0) + { + return false; + } + + return true; + } + + return false; +} + +bool Point::isLineOverlap(const Point& A, const Point& B, + const Point& C, const Point& D) +{ + // FAIL: Line undefined + if ( (A.x==B.x && A.y==B.y) || (C.x==D.x && C.y==D.y) ) + { + return false; + } + + if (crossProduct2Vector(A, B, C, D) == 0 && + (crossProduct2Vector(C, D, C, A) == 0 || crossProduct2Vector(A, B, C, A) == 0)) + { + return true; + } + + return false; +} + +bool Point::isSegmentOverlap(const Point& A, const Point& B, const Point& C, const Point& D, Point* S, Point* E) +{ + + if (isLineOverlap(A, B, C, D)) + { + return isOneDemensionSegmentOverlap(A.x, B.x, C.x, D.x, &S->x, &E->x) && + isOneDemensionSegmentOverlap(A.y, B.y, C.y, D.y, &S->y, &E->y); + } + + return false; +} + bool Point::isSegmentIntersect(const Point& A, const Point& B, const Point& C, const Point& D) { float S, T; if (isLineIntersect(A, B, C, D, &S, &T )&& - (S >= 0.0f && S <= 1.0f && T >= 0.0f && T <= 1.0f)) + (S >= 0.0f && S <= 1.0f && T >= 0.0f && T <= 1.0f)) { return true; - } + } return false; } diff --git a/cocos2dx/cocoa/CCGeometry.h b/cocos2dx/cocoa/CCGeometry.h index ccfe3b5616..eb66763412 100644 --- a/cocos2dx/cocoa/CCGeometry.h +++ b/cocos2dx/cocoa/CCGeometry.h @@ -245,20 +245,6 @@ public: return Point(cosf(a), sinf(a)); } - /** A general line-line intersection test - @param A the startpoint for the first line L1 = (A - B) - @param B the endpoint for the first line L1 = (A - B) - @param C the startpoint for the second line L2 = (C - D) - @param D the endpoint for the second line L2 = (C - D) - @param S the range for a hitpoint in L1 (p = A + S*(B - A)) - @returns whether these two lines interects. - - Note that if two line is intersection, S in line in [0..1] - the hit point also is A + S * (B - A); - @since 3.0 - */ - static bool isOneDemensionLineIntersect(float A, float B, float C, float D, float *S); - /** A general line-line intersection test @param A the startpoint for the first line L1 = (A - B) @param B the endpoint for the first line L1 = (A - B) @@ -276,7 +262,29 @@ public: */ static bool isLineIntersect(const Point& A, const Point& B, const Point& C, const Point& D, - float *S, float *T); + float *S = nullptr, float *T = nullptr); + + /* + returns true if Line A-B overlap with segment C-D + @since v3.0 + */ + static bool isLineOverlap(const Point& A, const Point& B, + const Point& C, const Point& D); + + /* + returns true if Line A-B parallel with segment C-D + @since v3.0 + */ + static bool isLineParallel(const Point& A, const Point& B, + const Point& C, const Point& D); + + /* + returns true if Segment A-B overlap with segment C-D + @since v3.0 + */ + static bool isSegmentOverlap(const Point& A, const Point& B, + const Point& C, const Point& D, + Point* S = nullptr, Point* E = nullptr); /* returns true if Segment A-B intersects with segment C-D @@ -291,6 +299,13 @@ public: static Point getIntersectPoint(const Point& A, const Point& B, const Point& C, const Point& D); static const Point ZERO; + +private: + // returns true if segment A-B intersects with segment C-D. S->E is the ovderlap part + static bool isOneDemensionSegmentOverlap(float A, float B, float C, float D, float *S, float * E); + + // cross procuct of 2 vector. A->B X C->D + static float crossProduct2Vector(const Point& A, const Point& B, const Point& C, const Point& D) { return (D.y - C.y) * (B.x - A.x) - (D.x - C.x) * (B.y - A.y); } }; class CC_DLL Size