1 /*****************************************************************************
2  * $LastChangedDate: 2011-04-23 21:07:07 -0400 (Sat, 23 Apr 2011) $
3  * @file
4  * @author  Jim E. Brooks  http://www.palomino3d.org
5  * @brief   Basic graphics types.
6  *//*
7  * LEGAL:   COPYRIGHT (C) 2004 JIM E. BROOKS
8  *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
9  *          OF THE GNU GENERAL PUBLIC LICENSE VERSION 2 (GPL 2).
10  *****************************************************************************/
11 
12 #ifndef GFX_GRAPHICS_HH
13 #define GFX_GRAPHICS_HH 1
14 
15 #include "base/stream.hh"
16 #include "base/funcs_stl.hh"
17 using namespace base;
18 #include "math/module.hh"
19 #include "math/vertex.hh"
20 using namespace math;
21 
22 namespace gfx {
23 
24 // Basic types must be fast.  Virtual functions incur overhead from C++ vtable.
25 #define virtual VIRTUAL_METHODS_IN_BASIC_TYPES_IS_TOO_SLOW
26 
27 ////////////////////////////////////////////////////////////////////////////////
28 /// @brief 2D rectangle.
29 ///
30 /// PRECONDITION: (X1,Y1) < (X2,Y2).
31 ///
32 template<typename T>
33 class Rect
34 {
35 public:
Rect(void)36     Rect( void )
37     :   x1(0), y1(0), x2(0), y2(0)
38     {
39         // NOP
40     }
41 
Rect(T X1,T Y1,T X2,T Y2)42     Rect( T X1, T Y1, T X2, T Y2 )
43 //  :   x1(X1), y1(Y1), x2(X2), y2(Y2)  // use Set() which can correct args
44     {
45         Set( X1, Y1, X2, Y2 );
46     }
47 
Set(T X1,T Y1,T X2,T Y2)48     void Set( T X1, T Y1, T X2, T Y2 )
49     {
50         // Try to maintain assumption that (x1,y1) < (x2,y2).
51         x1 = MIN( X1, X2 );
52         y1 = MIN( Y1, Y2 );
53         x2 = MAX( X1, X2 );
54         y2 = MAX( Y1, Y2 );
55     }
56 
IfZero(void) const57     bool IfZero( void ) const
58     {
59         return (x1 == 0)
60            and (y1 == 0)
61            and (x2 == 0)
62            and (y2 == 0);
63     }
64 
65     /// @return True if a 2D point is inside this rectangle.
IfInside(T x,T y) const66     bool IfInside( T x, T y ) const
67     {
68         return x >= x1   // assumes (x1,y1) < (x2,y2)
69             && x <= x2   // this could be recoded to not assume
70             && y >= y1   // but it'd be slower
71             && y <= y2;
72     }
73 
IfInside(const Vector2 & v) const74     bool IfInside( const Vector2& v ) const
75     {
76         return IfInside( T(v.x), T(v.y) );  // cast to suppress warning
77     }
78 
79     /// @return True if the passed rectangle is ENTIRELY outside this one.
IfOutside(const Rect<T> & rect) const80     bool IfOutside( const Rect<T>& rect ) const
81     {
82         return x2 < rect.x1     // if this right side is left of other
83             || x1 > rect.x2     // if this left side is right of other
84             || y1 > rect.y2     // if top of this is below other
85             || y2 < rect.y1;    // if bottom of this is above other
86     }
87 
88     /// If any part of another rectangle overlaps this one.
IfOverlaps(const Rect & rect) const89     bool IfOverlaps( const Rect& rect ) const
90     {
91         // Not outside means entirely inside or partially inside (overlap).
92         return not IfOutside( rect );
93     }
94 
95     /// Grow rectangle (expand a corner) to enclose a point.
Grow(T x,T y)96     void Grow( T x, T y )
97     {
98         // Try to maintain assumption that (x1,y1) < (x2,y2).
99         x1 = MIN(x1,x);
100         y1 = MIN(y1,y);
101         x2 = MAX(x2,x);
102         y2 = MAX(y2,y);
103     }
104 
GetWidth(void) const105     T GetWidth( void ) const
106     {
107         return x2 - x1;  // right - left
108     }
109 
GetHeight(void) const110     T GetHeight( void ) const
111     {
112         return y2 - y1;  // bottom - top
113     }
114 
115 public:
116     T   x1;  // smallest x (NW)
117     T   y1;  // smallest y
118     T   x2;  // greatest x (SE)
119     T   y2;  // greatest y
120 };
121 
122 template<typename T>
operator ==(const Rect<T> & a,const Rect<T> & b)123 bool operator==( const Rect<T>& a, const Rect<T>& b )
124 {
125     return a.x1 == b.x1
126         && a.y1 == b.y1
127         && a.x2 == b.x2
128         && a.y2 == b.y2;
129 }
130 
131 template<typename T>
operator !=(const Rect<T> & a,const Rect<T> & b)132 bool operator!=( const Rect<T>& a, const Rect<T>& b )
133 {
134     return ! (a == b);  // this operator!=() is based on operator==()
135 }
136 
137 template<typename T>
operator <(const Rect<T> & a,const Rect<T> & b)138 bool operator<( const Rect<T>& a, const Rect<T>& b )
139 {
140     RETURN_LT_TRUE_GT_FALSE( a.x1, b.x1 )
141     RETURN_LT_TRUE_GT_FALSE( a.y1, b.y1 )
142     RETURN_LT_TRUE_GT_FALSE( a.x2, b.x2 )
143     RETURN_LT_TRUE_GT_FALSE( a.y2, b.y2 )
144     return false;  // equal
145 }
146 
147 template<typename T>
operator <<(std::ostream & strm,const Rect<T> & o)148 std::ostream& operator<<( std::ostream& strm, const Rect<T>& o )
149 {
150     std::ios::fmtflags savedFlags = strm.flags();
151     strm << '{'
152          << "x1=" << OMANIP_FIELD(0) << o.x1 << ','
153          << "y1=" << OMANIP_FIELD(0) << o.y1 << ','
154          << "x2=" << OMANIP_FIELD(0) << o.x2 << ','
155          << "y2=" << OMANIP_FIELD(0) << o.y2 << '}';
156     strm.flags(savedFlags);
157     return strm;
158 }
159 
160 ////////////////////////////////////////////////////////////////////////////////
161 /// @brief (width,height) tuple.
162 ///
163 template<typename T=int>
164 struct WidthHeight
165 {
WidthHeightgfx::WidthHeight166                 WidthHeight( void ) : w(0), h(0) { }
WidthHeightgfx::WidthHeight167                 WidthHeight( T W, T H ) : w(W), h(H) { }
WidthHeightgfx::WidthHeight168     explicit    WidthHeight( const Rect<T>& r ) : w(r.x2 - r.x1), h(r.y2 - r.y1) { }
169     T   w, h;
170 };
171 
172 template<typename T>
operator <<(std::ostream & strm,const WidthHeight<T> & o)173 std::ostream& operator<<( std::ostream& strm, const WidthHeight<T>& o )
174 {
175     std::ios::fmtflags savedFlags = strm.flags();
176     strm << "(w=" << OMANIP_FIELD(0) << o.w << ','
177          <<  "h=" << OMANIP_FIELD(0) << o.h << ')';
178     strm.flags(savedFlags);
179     return strm;
180 }
181 
182 ////////////////////////////////////////////////////////////////////////////////
183 /// @brief Defines a volume in 3D space.
184 ///
185 struct BoxVolume
186 {
187     // Ensure that all coordinates of min vertex <= max vertex.
188     // A side-effect is that corners could be redefined.
BoxVolumegfx::BoxVolume189     BoxVolume( const WorldVertex& vmin, const WorldVertex& vmax )
190     {
191         mMin[XX] = MIN( vmin[XX], vmax[XX] );
192         mMin[YY] = MIN( vmin[YY], vmax[YY] );
193         mMin[ZZ] = MIN( vmin[ZZ], vmax[ZZ] );
194 
195         mMax[XX] = MAX( vmax[XX], vmax[XX] );
196         mMax[YY] = MAX( vmax[YY], vmax[YY] );
197         mMax[ZZ] = MAX( vmax[ZZ], vmax[ZZ] );
198     }
199 
200     WorldVertex     mMin;
201     WorldVertex     mMax;
202 };
203 
204 #undef virtual
205 
206 } // namespace gfx
207 
208 #endif // GFX_GRAPHICS_HH
209