/***************************************************************** Filename : GTypes2DF.h Content : Geometric 2D floating point types Created : January 14, 1999 Authors : Michael Antonov, Brendan Iribe, Prasad Silva Copyright : (c) 1999-2007 Scaleform Corp. All Rights Reserved. Licensees may use this file in accordance with the valid Scaleform Commercial License Agreement provided with the software. This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR ANY PURPOSE. **********************************************************************/ #ifndef INC_GTYPES2DF_H #define INC_GTYPES2DF_H #ifndef GFC_NO_TYPES2D_FLOAT #include "GTypes.h" #include "GArray.h" #ifdef GFC_MATH_H #include GFC_MATH_H #else #include #endif #include // **************************************************************************** // Size template class // template class GSize { public: // *** GSize data members T Width; T Height; enum BoundsType { Min, Max }; // Constructors GINLINE GSize() { } GINLINE explicit GSize(T val) { SetSize(val); } GINLINE GSize(T width, T height) { SetSize(width, height); } GINLINE GSize(const GSize &sz) { SetSize(sz.Width, sz.Height); } GINLINE GSize(BoundsType bt) { SetSize(bt); } // Initialization GINLINE void SetSize(T val) { Width = val; Height = val; } GINLINE void SetSize(T w, T h) { Width = w; Height = h; } GINLINE void SetSize(const GSize &sz) { SetSize(sz.Width, sz.Height); } //GINLINE void SetSize(BoundsType bt); // this function uses GFC_MAX_T which is not defined GINLINE void SetWidth(T w) { Width = w; } GINLINE void SetHeight(T h) { Height= h; } GINLINE void Clear() { Width=0; Height=0; } // Swaps the two sizes GINLINE void Swap(GSize *psz); GINLINE void Transpose() { G_Swap(Width, Height); } // Set to a + (b - a) * t GINLINE GSize& SetLerp(const GSize& a, const GSize& b, T t); // State GINLINE bool IsEmpty() const { return (Width<=1)||(Height<=1); } GINLINE bool IsNull() const { return (Width==0)&&(Height==0); } GINLINE bool IsValid() const { return (Width>=0)&&(Height>=0); } // Center values GINLINE GSize Center() const { return GSize(HCenter(), VCenter()); } GINLINE T HCenter() const { return Width/2; } GINLINE T VCenter() const { return Height/2; } // Area GINLINE T Area() const { return Width*Height; } // Expand the size GINLINE GSize& Expand(T w, T h) { Width+=w; Height+=h; return *this; } GINLINE GSize& Expand(const GSize &sz) { return Expand(sz.Width, sz.Height); } GINLINE GSize& Expand(T value) { return Expand(value,value); } // Contract the size GINLINE GSize& Contract(T value) { Width-=value; Height-=value; return *this; } GINLINE GSize& Contract(const GSize &sz) { return Contract(sz.Width, sz.Height); } GINLINE GSize& Contract(T w, T h) { Width-=w; Height-=h; return *this; } // Mul (scale) the size GINLINE GSize& Mul(const GSize &sz) { return Mul(sz.Width, sz.Height); } GINLINE GSize& Mul(T value) { Width*=value; Height*=value; return *this; } GINLINE GSize& Mul(T w, T h) { Width*=w; Height*=h; return *this; } // Divide (scale) the size GINLINE GSize& Div(const GSize &sz) { return Div(sz.Width, sz.Height); } GINLINE GSize& Div(T value) { Width/=value; Height/=value; return *this; } GINLINE GSize& Div(T w, T h) { Width/=w; Height/=h; return *this; } // Clamp the size GINLINE GSize& Clamp(const GSize &sz) { return Clamp(sz.Width, sz.Height); } GINLINE GSize& Clamp(T w, T h) { if (Width>w) Width=w; if (Height>h) Height=h; return *this; } GINLINE GSize& ClampWidth(T w) { if (Width>w) Width=w; return *this; } GINLINE GSize& ClampHeight(T h) { if (Height>h) Height=h; return *this; } // Return new adjusted sizes GINLINE GSize ExpandedTo(const GSize &sz) const { return GSize( G_Max(Width, sz.Width), G_Max(Height, sz.Height) ); } GINLINE GSize ExpandedTo(T w, T h) const { return GSize( G_Max(Width, w), G_Max(Height, h) ); } GINLINE GSize ExpandedToWidth(T w) const { return GSize( G_Max(Width, w), Height ); } GINLINE GSize ExpandedToHeight(T h) const { return GSize( Width, G_Max(Height, h) ); } GINLINE GSize ClampedTo(const GSize &sz) const { return GSize( G_Min(Width, sz.Width), G_Min(Height, sz.Height) ); } GINLINE GSize ClampedTo(T w, T h) const { return GSize( G_Min(Width, w), G_Min(Height, h) ); } GINLINE GSize ClampedToWidth(T w) const { return GSize( G_Min(Width, w), Height); } GINLINE GSize ClampedToHeight(T h) const { return GSize( Width, G_Min(Height, h) ); } // Operator overrides GINLINE const GSize& operator = ( const GSize &sz ) { SetSize(sz); return *this; } GINLINE const GSize& operator = ( T value ) { SetSize(value, value); return *this; } GINLINE const GSize& operator = ( BoundsType bt ) { SetSize(bt); return *this; } GINLINE const GSize& operator += ( const GSize &sz ) { return Expand(sz); } GINLINE const GSize& operator += ( T value ) { return Expand(value); } GINLINE const GSize& operator -= ( const GSize &sz ) { return Contract(sz); } GINLINE const GSize& operator -= ( T value ) { return Contract(value); } GINLINE const GSize& operator *= ( const GSize &sz ) { return Mul(sz); } GINLINE const GSize& operator *= ( T value ) { return Mul(value); } GINLINE const GSize& operator /= ( const GSize &sz ) { return Div(sz); } GINLINE const GSize& operator /= ( T value ) { return Div(value); } GINLINE const GSize& operator |= ( const GSize &sz ) { return (*this = ExpandedTo(sz)); } GINLINE const GSize& operator &= ( const GSize &sz ) { return (*this = ClampedTo(sz)); } GINLINE bool operator == ( const GSize &sz ) const { return (Width == sz.Width) && (Height == sz.Height); } GINLINE bool operator != ( const GSize &sz ) const { return (Width != sz.Width) || (Height != sz.Height); } GINLINE const GSize operator - () { return GSize(-Width, -Height); } GINLINE const GSize operator + ( const GSize &sz) { return GSize(Width+sz.Width, Height+sz.Height); } GINLINE const GSize operator + ( T value ) { return GSize(Width+value, Height+value); } GINLINE const GSize operator - ( const GSize &sz) { return GSize(Width-sz.Width, Height-sz.Height); } GINLINE const GSize operator - ( T value ) { return GSize(Width-value, Height-value); } GINLINE const GSize operator * ( const GSize &sz) { return GSize(Width*sz.Width, Height*sz.Height); } GINLINE const GSize operator * ( SInt value ) { return GSize(Width*value, Height*value); } //GINLINE const GSize operator * ( T value, const GSize &sz ) { return GSize(sz.Width*value, sz.Height*value); } GINLINE const GSize operator / ( const GSize &sz) { return GSize(Width/sz.Width, Height/sz.Height); } GINLINE const GSize operator / ( T value ) { return GSize(Width/value, Height/value); } GINLINE const GSize operator | ( const GSize &sz) { return GSize(G_Max(Width,sz.Width), G_Max(Height,sz.Height)); } GINLINE const GSize operator & ( const GSize &sz) { return GSize(G_Min(Width,sz.Width), G_Min(Height,sz.Height)); } }; /* This function uses GFC_MAX_T which is not defined // Set the size template GINLINE void GSize::SetSize(BoundsType bt) { switch (bt) { case Min: SetSize(0, 0); break; case Max: SetSize(GFC_MAX_T, GFC_MAX_T); break; } }*/ // Set to a + (b - a) * t template GINLINE GSize& GSize::SetLerp(const GSize& a, const GSize& b, T t) { Width = a.Width + (b.Width - a.Width) * t; Height = a.Height + (b.Height - a.Height) * t; return *this; } // Swaps the two sizes template GINLINE void GSize::Swap(GSize *psz) { G_Swap(Width, psz->Width); G_Swap(Height, psz->Height); } // ** End Inline Implementation // **************************************************************************** // Size template class // template class GPoint { public: // *** GPoint data members T x; T y; enum BoundsType { Min, Max }; GINLINE GPoint() { } GINLINE explicit GPoint(T value) { SetPoint(value); } GINLINE GPoint(T x2, T y2) { SetPoint(x2,y2); } GINLINE GPoint(const GPoint &pt) { SetPoint(pt); } //GINLINE GPoint(BoundsType bt) { SetPoint(bt); } // *** Initialization GINLINE void SetPoint(T val) { x=y=val; } GINLINE void SetPoint(T x2, T y2) { x=x2; y=y2; } GINLINE void SetPoint(const GPoint &pt) { SetPoint(pt.x, pt.y); } GINLINE void SetPoint(BoundsType bt); GINLINE void Clear() { x=y=0; } GINLINE void Swap(GPoint *ppt); // Set to a + (b - a) * t GINLINE GPoint& SetLerp(const GPoint& a, const GPoint& b, T t); // *** State information GINLINE bool IsNull() const { return (x==0 && y==0); } // Offset the position GINLINE GPoint& Offset(const GPoint &pt) { return Offset(pt.x, pt.y); } GINLINE GPoint& Offset(const GSize &sz) { return Offset(sz.Width, sz.Height); } GINLINE GPoint& Offset(T val) { return Offset(val,val); } GINLINE GPoint& Offset(T x2, T y2) { x+=x2; y+=y2; return *this; } // Multiply the position GINLINE GPoint& Mul(const GPoint &pt) { return Mul(pt.x, pt.y); } GINLINE GPoint& Mul(T val) { return Mul(val,val); } GINLINE GPoint& Mul(T x2, T y2) { x*=x2; y*=y2; return *this; } // Divide the position GINLINE GPoint& Div(const GPoint &pt) { return Div(pt.x, pt.y); } GINLINE GPoint& Div(T val) { return Div(val,val); } GINLINE GPoint& Div(T x2, T y2) { x/=x2; y/=y2; return *this; } // Dot product GINLINE T Dot(T x2,T y2) const { return (x*x2 + y*y2); } GINLINE T Dot(const GPoint &pt) const { return Dot(pt.x, pt.y); } // Angle in radians (between this and the passed point) GINLINE T Angle(T x2,T y2) const { return (T)atan2(y2-y, x2-x); } GINLINE T Angle(const GPoint &pt) const { return Angle(pt.x,pt.y); } // Distance squared (between this and the passed point) GINLINE T DistanceSquared(T x2,T y2) const { return ((x2-x)*(x2-x)+(y2-y)*(y2-y)); } GINLINE T DistanceSquared(const GPoint &pt) const { return DistanceSquared(pt.x, pt.y); } GINLINE T DistanceSquared() const { return Dot(*this); } // Distance GINLINE T Distance(T x2,T y2) const { return T(sqrt(DistanceSquared(x2,y2))); } GINLINE T Distance(const GPoint &pt) const { return Distance(pt.x, pt.y); } GINLINE T Distance() const { return T(sqrt(DistanceSquared())); } // L1 Distance (Manhattan style) // - the equation is: fabs(x1-x2) + fabs(y1-y2) GINLINE T DistanceL1(T x2,T y2) const { return T(fabs(x-x2)+fabs(y-y2)); } GINLINE T DistanceL1(const GPoint &pt) const { return DistanceL1(pt.x, pt.y); } // L Infinite Distance // - the equation is: max(fabs(x1-x2),fabs(y1-y2)) GINLINE T DistanceLn(T x2,T y2) const { return T(G_Max(fabs(x-x2), fabs(y-y2))); } GINLINE T DistanceLn(const GPoint &pt) const { return DistanceLn(pt.x, pt.y); } // Clamping GINLINE void Clamp(T _min, T _max) { if (x<_min) x=_min; else if (x>_max) x=_max; if (y<_min) y=_min; else if (y>_max) y=_max; } GINLINE void ClampMin(T _min) { if (x<_min) x=_min; if (y<_min) y=_min; } GINLINE void ClampMax(T _max) { if (x>_max) x=_max; if (y>_max) y=_max; } // Stores the absolute version of the point GINLINE GPoint& Absolute() { x=(T)fabs(x); y=(T)fabs(y); return *this; } // Bitwise comparison; return true if *this is bitwise identical to p. GINLINE bool BitwiseEqual(const GPoint& p) const { return memcmp(this, &p, sizeof(p)) == 0; } // *** Operators GINLINE const GPoint& operator = (const GPoint &pt) { SetPoint(pt); return *this; } GINLINE const GPoint& operator = (T val) { SetPoint(val); return *this; } GINLINE const GPoint& operator = (BoundsType bt) { SetPoint(bt); return *this; } GINLINE const GPoint operator - () const { return GPoint(-x, -y); } GINLINE const GPoint& operator += (const GPoint &pt) { return Offset(pt); } GINLINE const GPoint& operator += (const GSize &sz) { return Offset(sz); } GINLINE const GPoint& operator += (T val) { return Offset(val); } GINLINE const GPoint& operator -= (const GPoint &pt) { return Offset(-pt.x, -pt.y); } GINLINE const GPoint& operator -= (const GSize &sz) { return Offset(-sz.Width, -sz.Height); } GINLINE const GPoint& operator -= (T val) { return Offset(-val); } GINLINE const GPoint& operator *= (const GPoint &pt) { return Mul(pt); } GINLINE const GPoint& operator *= (T val) { return Mul(val); } GINLINE const GPoint& operator /= (const GPoint &pt) { return Div(pt); } GINLINE const GPoint& operator /= (T val) { return Div(val); } GINLINE bool operator == (const GPoint &pt) const { return ( (x==pt.x)&&(y==pt.y) ); } GINLINE bool operator != (const GPoint &pt) const { return ( (x!=pt.x)||(y!=pt.y) ); } GINLINE const GPoint operator + (const GPoint &pt) { return GPoint(x+pt.x, y+pt.y); } GINLINE const GPoint operator + (const GSize &sz) { return GPoint(x+sz.Width, y+sz.Height); } GINLINE const GPoint operator + (T val) { return GPoint(x+val, y+val); } GINLINE const GPoint operator - (const GPoint &pt) { return GPoint(x-pt.x, y-pt.y); } GINLINE const GPoint operator - (const GSize &sz) { return GPoint(x-sz.Width, y-sz.Height); } GINLINE const GPoint operator - (T val) { return GPoint(x-val, y-val); } GINLINE const GPoint operator * (const GPoint &pt) { return GPoint(x*pt.x, y*pt.y); } GINLINE const GPoint operator * (T val) { return GPoint(x*val, y*val); } //GINLINE const GPoint operator * (T val, const GPoint &pt) { return GPoint(pt.x*val, pt.y*val); } GINLINE const GPoint operator / (const GPoint &pt) { return GPoint(x/pt.x, y/pt.y); } GINLINE const GPoint operator / (T val) { return GPoint(x/val, y/val); } }; // ** Inline Implementation /* This function uses GFC_MAX_T which is not defined template GINLINE void GPoint::SetPoint(BoundsType bt) { switch (bt) { case Min: SetPoint(0, 0); break; case Max: SetPoint(GFC_MAX_T, GFC_MAX_T); break; } }*/ template GINLINE GPoint& GPoint::SetLerp(const GPoint& a, const GPoint& b, T t) { x = a.x + (b.x - a.x) * t; y = a.y + (b.y - a.y) * t; return *this; } // Swaps the two points template GINLINE void GPoint::Swap(GPoint *ppt) { G_Swap(x, ppt->x); G_Swap(y, ppt->y); } // ** End Inline Implementation // **************************************************************************** // Size template class // template class GRect { public: // *** GRect data members T Left; T Top; T Right; T Bottom; enum BoundsType { Min, Max }; // Constructors GINLINE GRect( ) { SetRect(0, 0, 0, 0); } GINLINE explicit GRect(T val) { SetRect(val, val); } GINLINE GRect(const GRect &rc) { SetRect(rc); } GINLINE GRect(const GSize &sz) { SetRect(sz); } GINLINE GRect(T w, T h) { SetRect(w, h); } GINLINE GRect(const GPoint &tl, const GPoint &br) { SetRect(tl, br); } GINLINE GRect(const GPoint &tl, const GSize &sz) { SetRect(tl, sz); } GINLINE GRect(T x, T y, const GSize &sz) { SetRect(x, y, sz); } GINLINE GRect(T left, T top, T right, T bottom) { SetRect(left, top, right, bottom); } GINLINE GRect(BoundsType bt) { SetRect(bt); } // *** Utility functions // Initialization GINLINE void SetRect(T l, T t, T r, T b) { Left=l; Top=t; Right=r; Bottom=b; } GINLINE void SetRect(const GSize &sz) { SetRect(0, 0, sz.Width, sz.Height); } GINLINE void SetRect(T w, T h) { SetRect(0, 0, w, h); } GINLINE void SetRect(const GRect &rc) { SetRect(rc.Left, rc.Top, rc.Right, rc.Bottom); } GINLINE void SetRect(const GPoint &tl, const GPoint &br) { SetRect(tl.x, tl.y, br.x, br.y); } GINLINE void SetRect(T x, T y, const GSize &sz) { SetRect(x, y, x+sz.Width, y+sz.Height); } GINLINE void SetRect(const GPoint &tl, const GSize &sz) { SetRect(tl.x, tl.y, sz); } GINLINE void SetRect(BoundsType bt); // Set to a + (b - a) * t GINLINE GRect& SetLerp(const GRect& a, const GRect& b, T t); GINLINE void Clear() { SetRect(GPoint(0,0),GSize(0,0)); } GINLINE void Swap(GRect *pr); // *** Different rect data conversion // Point/Size rect (values are stored as a point and a size) GINLINE GRect& FromRectPS(const GRect *prc) { SetRect(prc->Left,prc->Top,GSize(prc->Right,prc->Bottom)); return *this; } GINLINE void ToRectPS(GRect *prc) const { prc->SetRect(Left,Top,Width(),Height()); } // *** State functions // - these functions are for Normal rectangles only GINLINE bool IsNull() const { return (Right == Left) && (Bottom == Top); } GINLINE bool IsEmpty() const { return (Left >= Right) || (Top >= Bottom); } GINLINE bool IsNormal() const { return (Right >= Left) && (Bottom >= Top); } // Point properties GINLINE T X1() const { return Left; } GINLINE T Y1() const { return Top; } GINLINE T X2() const { return Right; } GINLINE T Y2() const { return Bottom; } // *** Corner position GINLINE GPoint TopLeft() const { return GPoint(Left, Top); } GINLINE GPoint TopRight() const { return GPoint(Right, Top); } GINLINE GPoint BottomLeft() const { return GPoint(Left, Bottom); } GINLINE GPoint BottomRight() const { return GPoint(Right, Bottom); } GINLINE void SetTopLeft(const GPoint &pt) { Left = pt.x; Top = pt.y; } GINLINE void SetTopRight(const GPoint &pt) { Right = pt.x; Top = pt.y; } GINLINE void SetBottomLeft(const GPoint &pt) { Left = pt.x; Bottom = pt.y; } GINLINE void SetBottomRight(const GPoint &pt) { Right = pt.x; Bottom = pt.y; } // *** Side access // Returns a new rectangle that GINLINE GRect TopSide(T height = 0.0) const { return GRect(Left, Top, Right, (Top+height)); } GINLINE GRect BottomSide(T height = 0.0) const { return GRect(Left, (Bottom-height), Right, Bottom); } GINLINE GRect LeftSide(T width = 0.0) const { return GRect(Left, Top, (Left+width), Bottom); } GINLINE GRect RightSide(T width = 0.0) const { return GRect((Right-width), Top, Right, Bottom); } // *** Center GINLINE GPoint Center() const { return GPoint(HCenter(), VCenter()); } GINLINE T HCenter() const { return (Right+Left)/2; } GINLINE T VCenter() const { return (Bottom+Top)/2; } GINLINE void SetCenter(const GPoint &nc); GINLINE void SetCenter(T x, T y) { SetCenter(GPoint(x,y)); } GINLINE void SetHCenter(T x); GINLINE void SetVCenter(T y); // *** Size functions GINLINE T Width() const { return Right-Left; } GINLINE T Height() const { return Bottom-Top; } // Checked functions return 0 size for non-normal coordinate GINLINE T CheckedWidth() const { return (Right>=Left) ? Width() : 0; } GINLINE T CheckedHeight() const { return (Bottom>=Top) ? Height() : 0; } GINLINE GSize Size() const { return GSize(Width(), Height()); } GINLINE GSize CheckedSize() const { return GSize(CheckedWidth(), CheckedHeight()); } GINLINE void SetSize(T width, T height) { SetWidth(width); SetHeight(height); } GINLINE void SetSize(const GSize &sz) { SetSize(sz.Width, sz.Height); } GINLINE void SetWidth(T width) { Right = (Left+width); } GINLINE void SetHeight(T height) { Bottom = (Top+height); } // *** Area GINLINE T Area() const { return Width()*Height(); } // *** Ranges GINLINE void SetHRange(T l, T r) { Left = l; Right = r; } GINLINE void SetVRange(T t, T b) { Left = t; Right = b; } // *** Sizing/Movement // Offset the rect GINLINE GRect& Offset(T x, T y) { Left+=x; Right+=x; Top+=y; Bottom+=y; return *this; } GINLINE GRect& Offset(const GPoint &pt) { return Offset(pt.x, pt.y); } GINLINE GRect& OffsetX(T x) { Left+=x; Right+=x; return *this; } GINLINE GRect& OffsetY(T y) { Top+=y; Bottom+=y; return *this; } // Expand (inflate) rect GINLINE GRect& Expand(T l, T t, T r, T b) { Left-=l; Right+=r; Top-=t; Bottom+=b; return *this; } GINLINE GRect& Expand(T val) { return Expand(val,val,val,val); } // Applies the value to both sides (h = Left-h & Right+h) GINLINE GRect& Expand(T h, T v) { return Expand(h,v,h,v); } GINLINE GRect& HExpand(T h) { Left-=h; Right+=h; return *this; } GINLINE GRect& HExpand(T l, T r) { Left-=l; Right+=r; return *this; } GINLINE GRect& VExpand(T v) { Top-=v; Bottom+=v; return *this; } GINLINE GRect& VExpand(T t, T b) { Top-=t; Bottom+=b; return *this; } // Expand this rectangle to enclose the given point. GINLINE GRect& ExpandToPoint(const GPoint &pt) { return ExpandToPoint(pt.x, pt.y); } GINLINE GRect& ExpandToPoint(T x, T y); // Contract (deflate) rect GINLINE GRect& Contract(T l, T t, T r, T b) { Left+=l; Right-=r; Top+=t; Bottom-=b; return *this; } GINLINE GRect& Contract(T val) { return Contract(val,val,val,val); } // Applies the value to both sides (w = Left+w & Right-w) GINLINE GRect& Contract(T h, T v) { return Contract(h,v,h,v); } GINLINE GRect& HContract(T h) { Left+=h; Right-=h; return *this; } GINLINE GRect& HContract(T l, T r) { Left+=l; Right-=r; return *this; } GINLINE GRect& VContract(T v) { Top+=v; Bottom-=v; return *this; } GINLINE GRect& VContract(T t, T b) { Top+=t; Bottom-=b; return *this; } // Clamp rect GINLINE GRect& Clamp(const GRect &r) { return Clamp(r.Left,r.Top,r.Right,r.Bottom); } GINLINE GRect& Clamp(T l, T t, T r, T b); GINLINE GRect& HClamp(T l, T r); GINLINE GRect& HClamp(const GRect &r) { return HClamp(r.Left, r.Right); } GINLINE GRect& VClamp(T t, T b); GINLINE GRect& VClamp(const GRect &r) { return VClamp(r.Top, r.Bottom); } // Rectangle becomes the sum of this and r GINLINE GRect& Union(T l, T t, T r, T b); GINLINE GRect& Union(const GRect &r) { return Union(r.Left,r.Top,r.Right,r.Bottom); } // Stores the area inside both rectangles // - clears the rectangle if they don’t intersect GINLINE GRect& Intersect(T l, T t, T r, T b); GINLINE GRect& Intersect(const GRect &r) { return Intersect(r.Left,r.Top,r.Right,r.Bottom); } // Normalize the rectangle GINLINE void Normalize(); GINLINE void NormalizeX(); GINLINE void NormalizeY(); // Returns a normalized copy GINLINE GRect Normal() const; // *** Area Testing // Returns 1 if the passed geometry is completely inside the rectangle GINLINE bool Contains(T x, T y) const { return ((x<=Right)&&(x>=Left)&&(y<=Bottom)&&(y>=Top)); } GINLINE bool Contains(const GPoint &pt) const { return ((pt.x<=Right)&&(pt.x>=Left)&&(pt.y<=Bottom)&&(pt.y>=Top)); } GINLINE bool Contains(const GRect &r) const { return ((Right>=r.Right)&&(Bottom>=r.Bottom)&&(Left<=r.Left)&&(Top<=r.Top)); } // Returns 1 if rectangles overlap at all // - r maybe completely inside GINLINE bool Intersects(const GRect &r) const; // Returns 1 if the rectangle touches one of the edges // - can optionally adjust the edge width GINLINE bool IntersectsEdge(const GRect &r, T ewidth=1) const; // Handles separate widths for each sides edge GINLINE bool IntersectsEdge(const GRect &r, T leftw, T topw, T rightw, T bottomw) const; // *** General calculations // - store new rectangle inside pdest // Clamps a point to the rectangle // - returns a new value that is inside the rect GINLINE GPoint ClampPoint(const GPoint &pt) const; // Calculates area inside both rectangles // Returns 0 if rectangles don’t intersect GINLINE bool IntersectRect(GRect *pdest, const GRect &r) const; // Calculates the area enclosing both rectangles GINLINE void UnionRect(GRect *pdest, const GRect &r) const; // *** Operator overrides GINLINE const GRect& operator = (const GRect &r) { SetRect(r); return *this; } GINLINE const GRect& operator = (BoundsType bt) { SetRect(bt); return *this; } GINLINE const GRect& operator += (const GPoint &pt) { return Offset(pt); } GINLINE const GRect& operator += (T val) { return Offset(val,val); } GINLINE GRect& operator -= (const GPoint &pt) { return Offset(-pt); } GINLINE GRect& operator -= (T val) { return Offset(-val,-val); } GINLINE const GRect& operator |= (const GRect &r); GINLINE const GRect& operator &= (const GRect &r); GINLINE bool operator == (const GRect &r) const { return ((Left==r.Left)&&(Right==r.Right)&&(Top==r.Top)&&(Bottom==r.Bottom) ); } GINLINE bool operator != (const GRect &r) const { return ((Left!=r.Left)||(Right!=r.Right)||(Top!=r.Top)||(Bottom!=r.Bottom) ); } GINLINE const GRect operator - () { return GRect(-Left,-Top,-Right,-Bottom); } GINLINE const GRect operator + ( const GPoint &pt) { return GRect(*this).Offset(pt); } GINLINE const GRect operator + (T val) { return GRect(Left+val, Top+val, Right+val, Bottom+val); } GINLINE const GRect operator - (const GPoint &pt) { return GRect(*this).Offset(-pt); } GINLINE const GRect operator - (T val) { return GRect(Left-val, Top-val, Right-val, Bottom-val); } GINLINE const GRect operator + (const GRect &r) { GRect dest; UnionRect(&dest, r); return dest; } GINLINE const GRect operator | (const GRect &r) { GRect dest; UnionRect(&dest, r); return dest; } GINLINE const GRect operator & (const GRect &r) { GRect dest; IntersectRect(&dest, r); return dest; } }; // ** Inline Implementation template GINLINE void GRect::SetRect(BoundsType bt) { switch (bt) { case Min: SetRect(GPoint(GPoint::Min), GSize(GSize::Min)); break; case Max: SetRect(GPoint(GPoint::Min), GSize(GSize::Max)); break; } } // Set to a + (b - a) * t template GINLINE GRect& GRect::SetLerp(const GRect& a, const GRect& b, T t) { Left = (b.Left - a.Left) * t + a.Left; Top = (b.Top - a.Top) * t + a.Top; Right = (b.Right - a.Right) * t + a.Right; Bottom = (b.Bottom - a.Bottom) * t + a.Bottom; return *this; } // Swaps the two rectangles template GINLINE void GRect::Swap(GRect *pr) { G_Swap(Left, pr->Left); G_Swap(Right, pr->Right); G_Swap(Top, pr->Top); G_Swap(Bottom, pr->Bottom); } // Clamp rect template GINLINE GRect& GRect::Clamp(T left, T top, T right, T bottom) { if (left>Left) Left =left; if (top>Top) Top =top; if (right GINLINE GRect& GRect::HClamp(T left, T right) { if (left>Left) Left =left; if (right GINLINE GRect& GRect::VClamp(T top, T bottom) { if (top>Top) Top =top; if (bottom GINLINE GRect& GRect::ExpandToPoint(T x, T y) { Left = G_Min(Left, x); Top = G_Min(Top, y); Right = G_Max(Right, x); Bottom = G_Max(Bottom, y); return *this; } // Stores the sum of this and r template GINLINE GRect& GRect::Union(T left, T top, T right, T bottom) { GRect ur; UnionRect(&ur, GRect(left, top, right, bottom)); SetRect(ur); return *this; } template GINLINE GRect& GRect::Intersect(T left, T top, T right, T bottom) { GRect r (left, top, right, bottom); if (!Intersects(r)) { Clear(); return *this; } Left = (Left>r.Left) ? Left : r.Left; Right = (Right>r.Right) ? r.Right : Right; Top = (Top>r.Top) ? Top : r.Top; Bottom = (Bottom>r.Bottom) ? r.Bottom : Bottom; return *this; } // Normalize the rectangle template GINLINE void GRect::Normalize() { if (Left>Right) G_Swap(Left, Right); if (Top>Bottom) G_Swap(Top, Bottom); } template GINLINE void GRect::NormalizeX() { if (Left>Right) G_Swap(Left, Right); } template GINLINE void GRect::NormalizeY() { if (Top>Bottom) G_Swap(Top, Bottom); } // Normalize the rectangle template GINLINE GRect GRect::Normal() const { GRect r(*this); r.Normalize(); return r; } // Sets the center template GINLINE void GRect::SetCenter(const GPoint &nc) { GPoint oc = Center(); Offset(nc.x-oc.x, nc.y-oc.y); } // Sets the horizontal center template GINLINE void GRect::SetHCenter(T x) { Offset(x-HCenter(), 0); } // Sets the vertical center template GINLINE void GRect::SetVCenter(T y) { Offset(0, y-VCenter()); } // Returns 1 if the rectangles overlap template GINLINE bool GRect::Intersects(const GRect &r) const { if ( (Bottom>=r.Top)&&(r.Bottom>=Top) ) if ( (r.Right>=Left)&&(Right>=r.Left) ) return 1; return 0; } // Returns 1 if the passed rectangle overlaps the edge template GINLINE bool GRect::IntersectsEdge(const GRect &r, T ew) const { return IntersectsEdge(r, ew, ew, ew, ew); } template GINLINE bool GRect::IntersectsEdge(const GRect &r, T lw, T tw, T rw, T bw) const { GRect inside = *this; inside.Contract(lw, tw, rw, bw); return (Intersects(r) && !inside.Contains(r)); } // Calculates area inside both GRectangles // Return 0 if GRectangles don’t intersect template GINLINE bool GRect::IntersectRect(GRect *pdest, const GRect &r) const { if (!Intersects(r)) return 0; pdest->Left = (Left>r.Left) ? Left : r.Left; pdest->Right = (Right>r.Right) ? r.Right : Right; pdest->Top = (Top>r.Top) ? Top : r.Top; pdest->Bottom = (Bottom>r.Bottom) ? r.Bottom : Bottom; return 1; } // Calculates the area enclosing both GRectangles template GINLINE void GRect::UnionRect(GRect *pdest, const GRect &r) const { pdest->Left = (Left>r.Left) ? r.Left : Left; pdest->Right = (Right>r.Right) ? Right : r.Right; pdest->Top = (Top>r.Top) ? r.Top : Top; pdest->Bottom = (Bottom>r.Bottom) ? Bottom : r.Bottom; } template GINLINE GPoint GRect::ClampPoint(const GPoint &pt) const { GPoint npt; npt.x = (Left>=pt.x) ? Left : (Right<=pt.x) ? Right : pt.x; npt.y = (Top>=pt.y) ? Top : (Bottom<=pt.y) ? Bottom : pt.y; return npt; } template GINLINE const GRect& GRect::operator |= (const GRect &r) { UnionRect(this, r); return *this; } template GINLINE const GRect& GRect::operator &= (const GRect &r) { if (!IntersectRect(this, r)) this->Clear(); return *this; } // ** End Inline Implementation // **************************************************************************** // Backwards compatible typedefs // // Float structures typedef GPoint GPointF; typedef GSize GSizeF; typedef GRect GRectF; // Double structures typedef GPoint GPointD; typedef GSize GSizeD; typedef GRect GRectD; #endif // GFC_NO_TYPES2D_FLOAT #endif