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.

236 lines
6.9 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