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