closed #2494: add isLineOverlap, isLineParallel, isSegmentOverlap method to Point.

This commit is contained in:
boyu0 2013-08-26 13:45:45 +08:00
parent 9a3a03d6ef
commit 1e452bf0bc
2 changed files with 96 additions and 54 deletions

View File

@ -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;
}

View File

@ -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