You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
235 lines
9.6 KiB
235 lines
9.6 KiB
|
|
struct HS_RECT_NAME { |
|
HS_RECT_TYPE fLeft, fTop, fRight, fBottom; |
|
|
|
HS_RECT_TYPE Width() const { return fRight - fLeft; } |
|
HS_RECT_TYPE Height() const { return fBottom - fTop; } |
|
hsBool IsEmpty() const { return fLeft >= fRight || fTop >= fBottom; } |
|
|
|
void SetEmpty() { fLeft = fTop = fRight = fBottom = 0; } |
|
HS_RECT_NAME* Set(HS_RECT_TYPE left, HS_RECT_TYPE top, HS_RECT_TYPE right, HS_RECT_TYPE bottom) |
|
{ |
|
fLeft = left; fTop = top; fRight = right; fBottom = bottom; |
|
return this; |
|
} |
|
HS_RECT_NAME* Set(const HS_RECT_POINT* p1, const HS_RECT_POINT* p2) |
|
{ |
|
if (p1->fX < p2->fX) |
|
{ fLeft = p1->fX; |
|
fRight = p2->fX; |
|
} else |
|
{ fLeft = p2->fX; |
|
fRight = p1->fX; |
|
} |
|
|
|
if (p1->fY < p2->fY) |
|
{ fTop = p1->fY; |
|
fBottom = p2->fY; |
|
} else |
|
{ fTop = p2->fY; |
|
fBottom = p1->fY; |
|
} |
|
return this; |
|
} |
|
HS_RECT_NAME* Set(UInt32 count, const HS_RECT_POINT pts[]) |
|
{ |
|
if (count > 0) |
|
{ fLeft = fRight = pts[0].fX; |
|
fTop = fBottom = pts[0].fY; |
|
(void)this->Union(count - 1, &pts[1]); |
|
} |
|
return this; |
|
} |
|
|
|
hsBool Contains(HS_RECT_TYPE x, HS_RECT_TYPE y) const |
|
{ |
|
return x >= fLeft && x < fRight && y >= fTop && y < fBottom; |
|
} |
|
hsBool Contains(const HS_RECT_POINT* p) const |
|
{ |
|
return this->Contains(p->fX, p->fY); |
|
} |
|
hsBool Contains(const HS_RECT_NAME* r) const |
|
{ |
|
return fLeft <= r->fLeft && fTop <= r->fTop && fRight >= r->fRight && fBottom >= r->fBottom; |
|
} |
|
hsBool Contains(HS_RECT_TYPE left, HS_RECT_TYPE top, HS_RECT_TYPE right, HS_RECT_TYPE bottom) const |
|
{ |
|
return fLeft <= left && fTop <= top && fRight >= right && fBottom >= bottom; |
|
} |
|
HS_RECT_NAME* Offset(HS_RECT_TYPE dx, HS_RECT_TYPE dy) |
|
{ |
|
fLeft += dx; fTop += dy; fRight += dx; fBottom += dy; |
|
return this; |
|
} |
|
HS_RECT_NAME* MoveTo(HS_RECT_TYPE x, HS_RECT_TYPE y) |
|
{ |
|
this->fRight += x - this->fLeft; |
|
this->fBottom += y - this->fTop; |
|
this->fLeft = x; |
|
this->fTop = y; |
|
return this; |
|
} |
|
HS_RECT_NAME* Inset(HS_RECT_TYPE dx, HS_RECT_TYPE dy) |
|
{ |
|
fLeft += dx; fRight -= dx; |
|
fTop += dy; fBottom -= dy; |
|
return this; |
|
} |
|
|
|
HS_RECT_NAME* UnionX(HS_RECT_TYPE x) |
|
{ |
|
if (x < fLeft) fLeft = x; else |
|
if (x > fRight) fRight = x; |
|
return this; |
|
} |
|
HS_RECT_NAME* UnionY(HS_RECT_TYPE y) |
|
{ |
|
if (y < fTop) fTop = y; else |
|
if (y > fBottom) fBottom = y; |
|
return this; |
|
} |
|
HS_RECT_NAME* Union(const HS_RECT_NAME* r) |
|
{ |
|
if (r->fLeft < fLeft) fLeft = r->fLeft; |
|
if (r->fTop < fTop) fTop = r->fTop; |
|
if (r->fRight > fRight) fRight = r->fRight; |
|
if (r->fBottom > fBottom) fBottom = r->fBottom; |
|
return this; |
|
} |
|
HS_RECT_NAME* Union(const HS_RECT_POINT* p) |
|
{ |
|
if (p->fX < fLeft) fLeft = p->fX; |
|
if (p->fX > fRight) fRight = p->fX; |
|
if (p->fY < fTop) fTop = p->fY; |
|
if (p->fY> fBottom) fBottom = p->fY; |
|
return this; |
|
} |
|
HS_RECT_NAME* Union(UInt32 count, const HS_RECT_POINT p[]) |
|
{ |
|
HS_RECT_TYPE left = this->fLeft; |
|
HS_RECT_TYPE top = this->fTop; |
|
HS_RECT_TYPE right = this->fRight; |
|
HS_RECT_TYPE bottom = this->fBottom; |
|
|
|
for (; count > 0; ++p, --count) |
|
{ HS_RECT_TYPE value = p->fX; |
|
if (value < left) left = value; |
|
else if (value > right) right = value; |
|
|
|
value = p->fY; |
|
if (value < top) top = value; |
|
else if (value > bottom) bottom = value; |
|
} |
|
return this->Set(left, top, right, bottom); |
|
} |
|
|
|
#if 0 // Havok reeks |
|
friend int operator==(const HS_RECT_NAME& a, const HS_RECT_NAME& b) |
|
{ |
|
return a.fLeft == b.fLeft && a.fTop == b.fTop && |
|
a.fRight == b.fRight && a.fBottom == b.fBottom; |
|
} |
|
friend int operator!=(const HS_RECT_NAME& a, const HS_RECT_NAME& b) |
|
{ |
|
return !(a == b); |
|
} |
|
#else // Havok reeks |
|
int operator==(const HS_RECT_NAME& aa) const |
|
{ |
|
return aa.fLeft == fLeft && aa.fTop == fTop && |
|
aa.fRight == fRight && aa.fBottom == fBottom; |
|
} |
|
int operator!=(const HS_RECT_NAME& aa) const |
|
{ |
|
return !(aa == *this); |
|
} |
|
#endif // Havok reeks |
|
|
|
// Intersect Test |
|
friend int operator&&(const HS_RECT_NAME& a, const HS_RECT_NAME& b) |
|
{ |
|
return a.fLeft < b.fRight && a.fRight > b.fLeft && |
|
a.fTop < b.fBottom && a.fBottom > b.fTop; |
|
} |
|
|
|
hsBool Intersect(const HS_RECT_NAME* r) |
|
{ |
|
return this->Intersect(r->fLeft, r->fTop, r->fRight, r->fBottom); |
|
} |
|
hsBool Intersect(HS_RECT_TYPE left, HS_RECT_TYPE top, HS_RECT_TYPE right, HS_RECT_TYPE bottom) |
|
{ |
|
if (left < fRight && top < fBottom && fLeft < right && fTop < bottom) |
|
{ if (left > fLeft) fLeft = left; |
|
if (top > fTop) fTop = top; |
|
if (right < fRight) fRight = right; |
|
if (bottom < fBottom) fBottom = bottom; |
|
return true; |
|
} |
|
return false; |
|
} |
|
hsBool Intersect(const HS_RECT_NAME* a, const HS_RECT_NAME* b) |
|
{ |
|
if (a->fLeft < b->fRight && a->fTop < b->fBottom && b->fLeft < a->fRight && b->fTop < a->fBottom) |
|
{ *this = *b; |
|
if (a->fLeft > fLeft) fLeft = a->fLeft; |
|
if (a->fTop > fTop) fTop = a->fTop; |
|
if (a->fRight < fRight) fRight = a->fRight; |
|
if (a->fBottom < fBottom) fBottom = a->fBottom; |
|
return true; |
|
} |
|
return false; // "this" is not changed |
|
} |
|
|
|
HS_RECT_POINT* ToQuad(HS_RECT_POINT quad[4]) const |
|
{ |
|
quad[0].fX = fLeft; quad[0].fY = fTop; |
|
quad[1].fX = fRight; quad[1].fY = fTop; |
|
quad[2].fX = fRight; quad[2].fY = fBottom; |
|
quad[3].fX = fLeft; quad[3].fY = fBottom; |
|
return quad; |
|
} |
|
|
|
hsBool CornerTest(const HS_RECT_NAME* area, |
|
HS_RECT_POINT* hitPt = nil, HS_RECT_POINT* oppositePt = nil) const |
|
{ |
|
if (area->Contains(fLeft, fTop)) |
|
{ if (hitPt) hitPt->Set(fLeft, fTop); |
|
if (oppositePt) oppositePt->Set(fRight, fBottom); |
|
return true; |
|
} |
|
if (area->Contains(fLeft, fBottom)) |
|
{ if (hitPt) hitPt->Set(fLeft, fBottom); |
|
if (oppositePt) oppositePt->Set(fRight, fTop); |
|
return true; |
|
} |
|
if (area->Contains(fRight, fTop)) |
|
{ if (hitPt) hitPt->Set(fRight, fTop); |
|
if (oppositePt) oppositePt->Set(fLeft, fBottom); |
|
return true; |
|
} |
|
if (area->Contains(fRight, fBottom)) |
|
{ if (hitPt) hitPt->Set(fRight, fBottom); |
|
if (oppositePt) oppositePt->Set(fLeft, fTop); |
|
return true; |
|
} |
|
return false; |
|
} |
|
hsBool CornerTest(HS_RECT_POINT* pt, HS_RECT_TYPE tolerance, |
|
HS_RECT_POINT* hitPt = nil, HS_RECT_POINT* oppositePt = nil) const |
|
{ |
|
HS_RECT_NAME area = { pt->fX - tolerance, pt->fY - tolerance, |
|
pt->fX + tolerance, pt->fY + tolerance }; |
|
|
|
return this->CornerTest(&area, hitPt, oppositePt); |
|
} |
|
|
|
#if !(HS_RECT_EXTEND) |
|
}; |
|
#endif |
|
|
|
#undef HS_RECT_NAME |
|
#undef HS_RECT_POINT |
|
#undef HS_RECT_TYPE |
|
#undef HS_RECT_EXTEND |
|
|
|
|