1 /*
2 Copyright (c) 2000-2003 Lee Thomason (www.grinninglizard.com)
3 Grinning Lizard Utilities.
4 
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any
7 damages arising from the use of this software.
8 
9 Permission is granted to anyone to use this software for any
10 purpose, including commercial applications, and to alter it and
11 redistribute it freely, subject to the following restrictions:
12 
13 1. The origin of this software must not be misrepresented; you must
14 not claim that you wrote the original software. If you use this
15 software in a product, an acknowledgment in the product documentation
16 would be appreciated but is not required.
17 
18 2. Altered source versions must be plainly marked as such, and
19 must not be misrepresented as being the original software.
20 
21 3. This notice may not be removed or altered from any source
22 distribution.
23 */
24 
25 
26 #ifndef GRINLIZ_RECTANGLE_INCLUDED
27 #define GRINLIZ_RECTANGLE_INCLUDED
28 
29 #include <limits.h>
30 #include "glvector.h"
31 
32 namespace grinliz {
33 
34 /** A rectangle structure.
35 */
36 template< class T >
37 struct Rectangle2
38 {
39 	Vector2< T > min;
40 	Vector2< T > max;
41 
42 	/// Initialize. Convenience function.
SetRectangle243 	void Set( T _xmin, T _ymin, T _xmax, T _ymax )	{
44 		min.x = _xmin; min.y = _ymin; max.x = _xmax; max.y = _ymax;
45 	}
46 	/// Set all the members to zero.
ZeroRectangle247 	void Zero() {
48 		min.x = min.y = max.x = max.y = (T) 0;
49 	}
50 
51 	/** Creates the rectangle from 2 points, which can be
52 		in any relationship to each other.
53 	*/
FromPairRectangle254 	void FromPair( T x0, T y0, T x1, T y1 )
55 	{
56 		min.x = grinliz::Min( x0, x1 );
57 		max.x = grinliz::Max( x0, x1 );
58 		min.y = grinliz::Min( y0, y1 );
59 		max.y = grinliz::Max( y0, y1 );
60 	}
61 
62 	/// Return true if the rectangles intersect.
IntersectRectangle263 	bool Intersect( const Rectangle2<T>& rect ) const
64 	{
65 		if (	rect.max.x < min.x
66 			 || rect.min.x > max.x
67 			 || rect.max.y < min.y
68 			 || rect.min.y > max.y )
69 		{
70 			return false;
71 		}
72 		return true;
73 	}
74 
IntersectRectangle275 	bool Intersect( const Vector2<T>& point ) const
76 	{
77 		if (	point.x < min.x
78 			 || point.x > max.x
79 			 || point.y < min.y
80 			 || point.y > max.y )
81 		{
82 			return false;
83 		}
84 		return true;
85 	}
86 
IntersectRectangle287 	bool Intersect( T x, T y ) const
88 	{
89 		if (	x < min.x
90 			 || x > max.x
91 			 || y < min.y
92 			 || y > max.y )
93 		{
94 			return false;
95 		}
96 		return true;
97 	}
98 
99 
100 	/// Return true if 'rect' is inside this.
ContainsRectangle2101 	bool Contains( const Rectangle2<T>& rect ) const
102 	{
103 		if (	rect.min.x >= min.x
104 			 && rect.max.x <= max.x
105 			 && rect.min.y >= min.y
106 			 && rect.max.y <= max.y )
107 		{
108 			return true;
109 		}
110 		return false;
111 	}
112 
ContainsRectangle2113 	bool Contains( const Vector2<T>& point ) const
114 	{
115 		if (	point.x >= min.x
116 			 && point.x <= max.x
117 			 && point.y >= min.y
118 			 && point.y <= max.y )
119 		{
120 			return true;
121 		}
122 		return false;
123 	}
124 
125 	/// Merge the rect into this.
DoUnionRectangle2126 	void DoUnion( const Rectangle2<T>& rect )
127 	{
128 		min.x = grinliz::Min( min.x, rect.min.x );
129 		max.x = grinliz::Max( max.x, rect.max.x );
130 		min.y = grinliz::Min( min.y, rect.min.y );
131 		max.y = grinliz::Max( max.y, rect.max.y );
132 	}
133 
134 	/// Merge the rect into this.
DoUnionRectangle2135 	void DoUnion( T x, T y )
136 	{
137 		min.x = grinliz::Min( min.x, x );
138 		max.x = grinliz::Max( max.x, x );
139 		min.y = grinliz::Min( min.y, y );
140 		max.y = grinliz::Max( max.y, y );
141 	}
142 
143  	/// Turn this into the intersection.
DoIntersectionRectangle2144 	void DoIntersection( const Rectangle2<T>& rect )
145 	{
146 		min.x = grinliz::Max( min.x, rect.min.x );
147 		max.x = grinliz::Min( max.x, rect.max.x );
148 		min.y = grinliz::Max( min.y, rect.min.y );
149 		max.y = grinliz::Min( max.y, rect.max.y );
150 	}
151 
152 	/// Clip this to the passed in rectangle. Will become invalid if they don't intersect.
DoClipRectangle2153 	void DoClip( const Rectangle2<T>& rect )
154 	{
155 		min.x = rect.min.x > min.x ? rect.min.x : min.x;
156 		max.x = rect.max.x < max.x ? rect.max.x : max.x;
157 		min.y = rect.min.y > min.y ? rect.min.y : min.y;
158 		max.y = rect.max.y < max.y ? rect.max.y : max.y;
159 	}
160 
161 
162 	/// Scale all coordinates by the given ratios:
ScaleRectangle2163 	void Scale( T x, T y )
164 	{
165 		min.x = ( x * min.x );
166 		min.y = ( y * min.y );
167 		max.x = ( x * max.x );
168 		max.y = ( y * max.y );
169 	}
170 
171 	/// Changes the boundaries
EdgeAddRectangle2172 	void EdgeAdd( T i )
173 	{
174 		min.x -= i;
175 		max.x += i;
176 		min.y -= i;
177 		max.y += i;
178 	}
179 
180 	/// Query the edge of the rectangle. The edges are ordered: bottom, right, top, left.
EdgeRectangle2181 	void Edge( int i, Vector2< T >* head, Vector2< T >* tail )
182 	{
183 		switch ( i ) {
184 			case 0:		tail->Set( min.x, min.y );	head->Set( max.x, min.y );	break;
185 			case 1:		tail->Set( max.x, min.y );	head->Set( max.x, max.y );	break;
186 			case 2:		tail->Set( max.x, max.y );	head->Set( min.x, max.y );	break;
187 			case 3:		tail->Set( min.x, max.y );	head->Set( min.x, min.y );	break;
188 			default:	GLASSERT( 0 );
189 		}
190 	}
191 
192 	bool operator==( const Rectangle2<T>& that ) const { return     ( min.x == that.min.x )
193 													&& ( max.x == that.max.x )
194 													&& ( min.y == that.min.y )
195 													&& ( max.y == that.max.y ); }
196 	bool operator!=( const Rectangle2<T>& that ) const { return     ( min.x != that.min.x )
197 													|| ( max.x != that.max.x )
198 													|| ( min.y != that.min.y )
199 													|| ( max.y != that.max.y ); }
200 
201 };
202 
203 
204 struct Rectangle2I : public Rectangle2< int >
205 {
206 	enum { INVALID = INT_MIN };
207 
WidthRectangle2I208 	int Width()	 const 	{ return max.x - min.x + 1; }		///< width of the rectangle
HeightRectangle2I209 	int Height() const	{ return max.y - min.y + 1; }		///< height of the rectangle
AreaRectangle2I210 	int Area()   const	{ return Width() * Height();	}   ///< Area of the rectangle
211 
212 	/// Initialize to an invalid rectangle.
SetInvalidRectangle2I213 	void SetInvalid()	{ min.x = INVALID + 1; max.x = INVALID; min.y = INVALID + 1; max.y = INVALID; }
214 
215 	/// Return true if this is potentially a valid rectangle.
IsValidRectangle2I216 	bool IsValid() const {
217 		return ( min.x <= max.x ) && ( min.y <= max.y );
218 	}
219 
220 	/// Just like DoUnion, except takes validity into account.
DoUnionVRectangle2I221 	void DoUnionV( int x, int y )
222 	{
223 		if ( !IsValid() ) {
224 			min.x = max.x = x;
225 			min.y = max.y = y;
226 		}
227 		else {
228 			min.x = Min( min.x, x );
229 			max.x = Max( max.x, x );
230 			min.y = Min( min.y, y );
231 			max.y = Max( max.y, y );
232 		}
233 	}
234 };
235 
236 struct Rectangle2F : public Rectangle2< float >
237 {
WidthRectangle2F238 	float Width()	 const 	{ return max.x - min.x; }		///< width of the rectangle
HeightRectangle2F239 	float Height() const	{ return max.y - min.y; }		///< height of the rectangle
AreaRectangle2F240 	float Area()   const	{ return Width() * Height();	}   ///< Area of the rectangle
241 };
242 
243 
244 template< class T >
245 struct Rectangle3
246 {
247 	Vector3< T > min;
248 	Vector3< T > max;
249 
250 	/// If i==0 return min, else return max
VecRectangle3251 	const Vector3< T >& Vec( int i ) { return (i==0) ? min : max; }
252 
253 	/// Initialize. Convenience function.
SetRectangle3254 	void Set( T _xmin, T _ymin, T _zmin, T _xmax, T _ymax, T _zmax )	{
255 		min.x = _xmin; min.y = _ymin; min.z = _zmin;
256 		max.x = _xmax; max.y = _ymax; max.z = _zmax;
257 	}
258 	/// Set all the members to zero.
ZeroRectangle3259 	void Zero() {
260 		min.x = min.y = max.x = max.y = min.z = max.z = (T) 0;
261 	}
262 
263 	/// Return true if the rectangles intersect.
IntersectRectangle3264 	bool Intersect( const Rectangle3<T>& rect ) const
265 	{
266 		if (	rect.max.x < min.x
267 			 || rect.min.x > max.x
268 			 || rect.max.y < min.y
269 			 || rect.min.y > max.y
270 			 || rect.max.z < min.z
271 			 || rect.min.z > max.z )
272 		{
273 			return false;
274 		}
275 		return true;
276 	}
277 
IntersectRectangle3278 	bool Intersect( const Vector3<T>& point ) const
279 	{
280 		if (	point.x < min.x
281 			 || point.x > max.x
282 			 || point.y < min.y
283 			 || point.y > max.y
284 			 || point.z < min.z
285 			 || point.z > max.z )
286 		{
287 			return false;
288 		}
289 		return true;
290 	}
291 
IntersectRectangle3292 	bool Intersect( T x, T y, T z ) const
293 	{
294 		if (	x < min.x
295 			 || x > max.x
296 			 || y < min.y
297 			 || y > max.y
298 			 || z < min.z
299 			 || z > max.z )
300 		{
301 			return false;
302 		}
303 		return true;
304 	}
305 
306 
307 	/// Return true if 'rect' is inside this.
ContainsRectangle3308 	bool Contains( const Rectangle3<T>& rect ) const
309 	{
310 		if (	rect.min.x >= min.x
311 			 && rect.max.x <= max.x
312 			 && rect.min.y >= min.y
313 			 && rect.max.y <= max.y
314 			 && rect.min.z >= min.z
315 			 && rect.max.z <= max.z )
316 		{
317 			return true;
318 		}
319 		return false;
320 	}
321 
ContainsRectangle3322 	bool Contains( const Vector3<T>& point ) const
323 	{
324 		if (	point.x >= min.x
325 			 && point.x <= max.x
326 			 && point.y >= min.y
327 			 && point.y <= max.y
328 			 && point.z >= min.z
329 			 && point.z <= max.z )
330 		{
331 			return true;
332 		}
333 		return false;
334 	}
335 
336 	/// Merge the rect into this.
DoUnionRectangle3337 	void DoUnion( const Rectangle3<T>& rect )
338 	{
339 		min.x = grinliz::Min( min.x, rect.min.x );
340 		max.x = grinliz::Max( max.x, rect.max.x );
341 		min.y = grinliz::Min( min.y, rect.min.y );
342 		max.y = grinliz::Max( max.y, rect.max.y );
343 		min.z = grinliz::Min( min.z, rect.min.z );
344 		max.z = grinliz::Max( max.z, rect.max.z );
345 	}
346 
347 	/// Merge the Vector into this.
DoUnionRectangle3348 	void DoUnion( const Vector3<T>& vec )
349 	{
350 		min.x = grinliz::Min( min.x, vec.x );
351 		max.x = grinliz::Max( max.x, vec.x );
352 		min.y = grinliz::Min( min.y, vec.y );
353 		max.y = grinliz::Max( max.y, vec.y );
354 		min.z = grinliz::Min( min.z, vec.z );
355 		max.z = grinliz::Max( max.z, vec.z );
356 	}
357 
358 	/// Turn this into the intersection.
DoIntersectionRectangle3359 	void DoIntersection( const Rectangle2<T>& rect )
360 	{
361 		min.x = grinliz::Max( min.x, rect.min.x );
362 		max.x = grinliz::Min( max.x, rect.max.x );
363 		min.y = grinliz::Max( min.y, rect.min.y );
364 		max.y = grinliz::Min( max.y, rect.max.y );
365 		min.z = grinliz::Max( min.z, rect.min.z );
366 		max.z = grinliz::Min( max.z, rect.max.z );
367 	}
368 
369 	/// Clip this to the passed in rectangle. Will become invalid if they don't intersect.
DoClipRectangle3370 	void DoClip( const Rectangle3<T>& rect )
371 	{
372 		min.x = rect.min.x > min.x ? rect.min.x : min.x;
373 		max.x = rect.max.x < max.x ? rect.max.x : max.x;
374 		min.y = rect.min.y > min.y ? rect.min.y : min.y;
375 		max.y = rect.max.y < max.y ? rect.max.y : max.y;
376 		min.z = rect.min.z > min.z ? rect.min.z : min.z;
377 		max.z = rect.max.z < max.z ? rect.max.z : max.z;
378 	}
379 
380 
381 	/// Scale all coordinates by the given ratios:
ScaleRectangle3382 	void Scale( T x, T y, T z )
383 	{
384 		min.x = ( x * min.x );
385 		max.x = ( x * max.x );
386 		min.y = ( y * min.y );
387 		max.y = ( y * max.y );
388 		min.z = ( z * min.z );
389 		max.z = ( z * max.z );
390 	}
391 
392 	/// Changes the boundaries
EdgeAddRectangle3393 	void EdgeAdd( T i )
394 	{
395 		min.x -= i;
396 		max.x += i;
397 		min.y -= i;
398 		max.y += i;
399 		min.z -= i;
400 		max.z += i;
401 	}
402 
403 	bool operator==( const Rectangle2<T>& that ) const { return	( min.x == that.min.x )
404 																&& ( max.x == that.max.x )
405 																&& ( min.y == that.min.y )
406 																&& ( max.y == that.max.y )
407 																&& ( min.z == that.min.z )
408 																&& ( max.z == that.max.z ); }
409 	bool operator!=( const Rectangle2<T>& that ) const { return	( min.x != that.min.x )
410 																|| ( max.x != that.max.x )
411 																|| ( min.y != that.min.y )
412 																|| ( max.y != that.max.y )
413 																|| ( min.z != that.min.z )
414 																|| ( max.z != that.max.z ); }
415 
416 };
417 
418 
419 
420 struct Rectangle3I : public Rectangle3< int >
421 {
422 	enum { INVALID = INT_MIN };
423 
SizeXRectangle3I424 	int SizeX()	 const 	{ return max.x - min.x + 1; }		///< width of the rectangle
SizeYRectangle3I425 	int SizeY() const	{ return max.y - min.y + 1; }		///< height of the rectangle
SizeZRectangle3I426 	int SizeZ()  const  { return max.z - min.z + 1; }
VolumeRectangle3I427 	int Volume() const	{ return SizeX() * SizeY() * SizeZ();	}   ///< Volume of the 3D rectangle
SizeRectangle3I428 	int Size( int i ) const { return max.X(i) - min.X(i) + 1; }
429 	#ifdef DEBUG
DumpRectangle3I430 	void Dump() { GLOUTPUT(( "(%d,%d,%d)-(%d,%d,%d)", min.x, min.y, min.z, max.x, max.y, max.z )); }
431 	#endif
432 };
433 
434 
435 struct Rectangle3F : public Rectangle3< float >
436 {
SizeXRectangle3F437 	float SizeX() const 	{ return max.x - min.x; }		///< width of the rectangle
SizeYRectangle3F438 	float SizeY() const		{ return max.y - min.y; }		///< height of the rectangle
SizeZRectangle3F439 	float SizeZ() const		{ return max.z - min.z; }		///< depth of the rectangle
VolumeRectangle3F440 	float Volume()const		{ return SizeX() * SizeY() * SizeZ();	}   ///< Volume of the 3D rectangle
SizeRectangle3F441 	float Size( int i ) const { return max.X(i) - min.X(i); }
442 
443 	#ifdef DEBUG
DumpRectangle3F444 	void Dump() {
445 		GLOUTPUT(( "(%.1f,%.1f,%.1f)-(%.1f,%.1f,%.1f)", min.x, min.y, min.z, max.x, max.y, max.z ));
446 	}
447 	#endif
448 };
449 
450 
451 };	// namespace grinliz
452 
453 
454 
455 #endif
456 
457