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