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