rect.h

Go to the documentation of this file.
00001 /*
00002 **  ClanLib SDK
00003 **  Copyright (c) 1997-2011 The ClanLib Team
00004 **
00005 **  This software is provided 'as-is', without any express or implied
00006 **  warranty.  In no event will the authors be held liable for any damages
00007 **  arising from the use of this software.
00008 **
00009 **  Permission is granted to anyone to use this software for any purpose,
00010 **  including commercial applications, and to alter it and redistribute it
00011 **  freely, subject to the following restrictions:
00012 **
00013 **  1. The origin of this software must not be misrepresented; you must not
00014 **     claim that you wrote the original software. If you use this software
00015 **     in a product, an acknowledgment in the product documentation would be
00016 **     appreciated but is not required.
00017 **  2. Altered source versions must be plainly marked as such, and must not be
00018 **     misrepresented as being the original software.
00019 **  3. This notice may not be removed or altered from any source distribution.
00020 **
00021 **  Note: Some of the libraries ClanLib may link to may have additional
00022 **  requirements or restrictions.
00023 **
00024 **  File Author(s):
00025 **
00026 **    Magnus Norddahl
00027 **    Kenneth Gangstoe
00028 **    Harry Storbacka
00029 **    Mark Page
00030 */
00031 
00034 
00035 #pragma once
00036 
00037 #include "../api_core.h"
00038 #include "vec2.h"
00039 #include "size.h"
00040 #include "point.h"
00041 #include "origin.h"
00042 #include "cl_math.h"
00043 
00049 template<typename Type>
00050 class CL_API_CORE CL_Rectx
00051 {
00054 public:
00058         CL_Rectx() { left = right = top = bottom = 0; }
00059 
00063         CL_Rectx(const CL_Sizex<Type> &s) { left = 0; top = 0; right = s.width; bottom = s.height; }
00064 
00071         CL_Rectx(Type new_left, Type new_top, Type new_right, Type new_bottom)
00072         { left = new_left; top = new_top; right = new_right; bottom = new_bottom; }
00073 
00078         CL_Rectx(const CL_Pointx<Type> &p, const CL_Sizex<Type> &size)
00079         { left = p.x; top = p.y; right = left + size.width; bottom = top + size.height; }
00080 
00086         CL_Rectx(Type new_left, Type new_top, const CL_Sizex<Type> &size)
00087         { left = new_left; top = new_top; right = left + size.width; bottom = top + size.height; }
00088 
00092         CL_Rectx(const CL_Rectx<int> &rect);
00093 
00097         CL_Rectx(const CL_Rectx<float> &rect);
00098 
00102         CL_Rectx(const CL_Rectx<double> &rect);
00103 
00105         bool operator==(const CL_Rectx<Type> &r) const
00106         { return (left == r.left && top == r.top && right == r.right && bottom == r.bottom); }
00107 
00109         bool operator!=(const CL_Rectx<Type> &r) const
00110         { return (left != r.left || top != r.top || right != r.right || bottom != r.bottom); }
00111 
00115 public:
00117         Type left;
00118 
00120         Type top;
00121 
00123         Type right;
00124 
00126         Type bottom;
00127 
00129         Type get_width() const { return right - left; }
00130 
00132         Type get_height() const { return bottom - top; }
00133 
00135         CL_Sizex<Type> get_size() const { return CL_Sizex<Type>(right - left, bottom - top); }
00136 
00138         bool contains(const CL_Vec2<Type> &p) const
00139         {
00140                 return ((p.x >= left && p.x <= right) || (p.x <= left && p.x >= right))
00141                     && ((p.y >= top && p.y <= bottom) || (p.y <= top && p.y >= bottom));
00142         }
00143 
00145         CL_Pointx<Type> get_top_left() const
00146         {
00147                 return CL_Pointx<Type>(left, top);
00148         }
00149 
00151         CL_Pointx<Type> get_top_right() const
00152         {
00153                 return CL_Pointx<Type>(right, top);
00154         }
00155 
00157         CL_Pointx<Type> get_bottom_right() const
00158         {
00159                 return CL_Pointx<Type>(right, bottom);
00160         }
00161 
00163         CL_Pointx<Type> get_bottom_left() const
00164         {
00165                 return CL_Pointx<Type>(left, bottom);
00166         }
00167 
00169         bool is_overlapped(const CL_Rectx<Type> &r) const
00170         {
00171                 return (r.left < right && r.right > left && r.top < bottom && r.bottom > top);
00172         }
00173 
00175         bool is_inside(const CL_Rectx<Type> &r) const
00176         {
00177                 return ((left <= r.left)
00178                         && (top <= r.top)
00179                         && (right >= r.right)
00180                         && (bottom >= r.bottom));
00181         }
00182 
00187         CL_Rectx<Type> get_rot_bounds(const CL_Vec2<Type> &hotspot, const CL_Angle &angle) const;
00188 
00195         CL_Rectx<Type> get_rot_bounds(CL_Origin origin, Type x, Type y, const CL_Angle &angle) const;
00196 
00198         CL_Pointx<Type> get_center() const
00199         {
00200                 return CL_Pointx<Type>( (left + right)/2, ( top + bottom)/2 );
00201         }
00202 
00206 public:
00210         CL_Rectx<Type> &set_top_left(const CL_Vec2<Type>& p)
00211         {
00212                 left = p.x;
00213                 top = p.y;
00214                 return *this;
00215         }
00216 
00220         CL_Rectx<Type> &set_top_right(const CL_Vec2<Type>& p)
00221         {
00222                 right = p.x;
00223                 top = p.y;
00224                 return *this;
00225         }
00226 
00230         CL_Rectx<Type> &set_bottom_right(const CL_Vec2<Type>& p)
00231         {
00232                 right = p.x;
00233                 bottom = p.y;
00234                 return *this;
00235         }
00236 
00240         CL_Rectx<Type> &set_bottom_left(const CL_Vec2<Type>& p)
00241         {
00242                 left = p.x;
00243                 bottom = p.y;
00244                 return *this;
00245         }
00246 
00250         CL_Rectx<Type> &set_width(Type width)
00251         {
00252                 right = left + width;
00253                 return *this;
00254         }
00255 
00259         CL_Rectx<Type> &set_height(Type height)
00260         {
00261                 bottom = top + height;
00262                 return *this;
00263         }
00264 
00268         CL_Rectx<Type> &shrink(const Type &left, const Type &top, const Type &right, const Type &bottom)
00269         {
00270                 this->left += left; this->top += top; this->right -= right; this->bottom -= bottom;
00271                 return *this;
00272         };
00273 
00277         CL_Rectx<Type> &shrink(const Type &left_right, const Type &top_bottom)
00278         {
00279                 this->left += left_right; this->top += top_bottom; this->right -= left_right; this->bottom -= top_bottom;
00280                 return *this;
00281         };
00282 
00286         CL_Rectx<Type> &shrink(const Type &shrink)
00287         {
00288                 this->left += shrink; this->top += shrink; this->right -= shrink; this->bottom -= shrink;
00289                 return *this;
00290         };
00291 
00295         CL_Rectx<Type> &expand(const Type &left, const Type &top, const Type &right, const Type &bottom)
00296         {
00297                 this->left -= left; this->top -= top; this->right += right; this->bottom += bottom;
00298                 return *this;
00299         };
00300 
00304         CL_Rectx<Type> &expand(const Type &left_and_right, const Type &top_and_bottom)
00305         {
00306                 this->left -= left_and_right;
00307                 this->right += left_and_right;
00308                 this->top -= top_and_bottom;
00309                 this->bottom += top_and_bottom;
00310                 return *this;
00311         };
00312 
00316         CL_Rectx<Type> &expand(const Type &expand)
00317         {
00318                 this->left -= expand;
00319                 this->right += expand;
00320                 this->top -= expand;
00321                 this->bottom += expand;
00322                 return *this;
00323         };
00324 
00328         CL_Rectx<Type> &translate(const CL_Vec2<Type> &p)
00329         {
00330                 left += p.x; top += p.y; right += p.x; bottom += p.y;
00331                 return *this;
00332         };
00333 
00337         CL_Rectx<Type> &translate(const CL_Rectx<Type> &p)
00338         {
00339                 left += p.left; top += p.top; right += p.left; bottom += p.top;
00340                 return *this;
00341         };
00342 
00346         CL_Rectx<Type> &translate(Type x, Type y)
00347         {
00348                 left += x; top += y; right += x; bottom += y;
00349                 return *this;
00350         };
00351 
00355         CL_Rectx<Type> &set_size(const CL_Sizex<Type> &size)
00356         {
00357                 right = left + size.width;
00358                 bottom = top + size.height;
00359                 return *this;
00360         }
00361 
00367         CL_Rectx<Type> &overlap(const CL_Rectx<Type> &rect)
00368         {
00369                 CL_Rectx<Type> result;
00370                 result.left   = cl_max(left, rect.left);
00371                 result.right  = cl_min(right, rect.right);
00372                 result.top    = cl_max(top, rect.top);
00373                 result.bottom = cl_min(bottom, rect.bottom);
00374                 *this = result;
00375                 return *this;
00376         }
00377 
00383         CL_Rectx<Type> &bounding_rect(const CL_Rectx<Type> &rect)
00384         {
00385                 CL_Rectx<Type> result;
00386                 result.left   = cl_min(left, rect.left);
00387                 result.right  = cl_max(right, rect.right);
00388                 result.top    = cl_min(top, rect.top);
00389                 result.bottom = cl_max(bottom, rect.bottom);
00390                 *this = result;
00391                 return *this;
00392         }
00393 
00397         CL_Rectx<Type> &normalize()
00398         {
00399                 if (left > right)
00400                 {
00401                         Type temp = right;
00402                         right = left;
00403                         left = temp;
00404                 }
00405 
00406                 if (top > bottom)
00407                 {
00408                         Type temp = bottom;
00409                         bottom = top;
00410                         top = temp;
00411                 }
00412                 return *this;
00413         }
00414 
00421         CL_Rectx<Type> &apply_alignment(CL_Origin origin, Type x, Type y)
00422         {
00423                 CL_Vec2<Type> offset = CL_Vec2<Type>::calc_origin(origin, get_size());
00424                 offset.x -= x;
00425                 offset.y -= y;
00426 
00427                 left += offset.x;
00428                 top += offset.y;
00429                 right += offset.x;
00430                 bottom += offset.y;
00431                 return *this;
00432         }
00433 
00437         CL_Rectx<Type> &clip(const CL_Rectx<Type> &cr)
00438         {
00439                 top = cl_max(top, cr.top);
00440                 left = cl_max(left, cr.left);
00441                 right = cl_min(right, cr.right);
00442                 bottom = cl_min(bottom, cr.bottom);
00443                 top = cl_min(top, bottom);
00444                 left = cl_min(left, right);
00445                 return *this;
00446         }
00448 };
00449 
00450 template<>
00451 inline CL_Rectx<int>::CL_Rectx(const CL_Rectx<float> &rect)
00452 { left = (int) (floor(rect.left + 0.5f)); top = (int) (floor(rect.top + 0.5f)); right = (int) (floor(rect.right + 0.5f)); bottom = (int) (floor(rect.bottom+0.5f)); }
00453 
00454 template<>
00455 inline CL_Rectx<int>::CL_Rectx(const CL_Rectx<double> &rect)
00456 { left = (int) (floor(rect.left + 0.5)); top = (int) (floor(rect.top + 0.5)); right = (int) (floor(rect.right + 0.5)); bottom = (int) (floor(rect.bottom + 0.5)); }
00457 
00458 template<typename Type>
00459 inline CL_Rectx<Type>::CL_Rectx(const CL_Rectx<int> &rect)
00460 { left = (Type) rect.left; top = (Type) rect.top; right = (Type) rect.right; bottom = (Type) rect.bottom; }
00461 
00462 template<typename Type>
00463 inline CL_Rectx<Type>::CL_Rectx(const CL_Rectx<float> &rect)
00464 { left = (Type) rect.left; top = (Type) rect.top; right = (Type) rect.right; bottom = (Type) rect.bottom; }
00465 
00466 template<typename Type>
00467 inline CL_Rectx<Type>::CL_Rectx(const CL_Rectx<double> &rect)
00468 { left = (Type) rect.left; top = (Type) rect.top; right = (Type) rect.right; bottom = (Type) rect.bottom; }
00469 
00473 class CL_Rect : public CL_Rectx<int>
00474 {
00475 public:
00476         CL_Rect() : CL_Rectx<int>() {}
00477         CL_Rect(const CL_Sizex<int> &s) : CL_Rectx<int>(s) {}
00478         CL_Rect(int new_left, int new_top, int new_right, int new_bottom) : CL_Rectx<int>(new_left, new_top, new_right, new_bottom) {}
00479         CL_Rect(const CL_Pointx<int> &p, const CL_Sizex<int> &size) : CL_Rectx<int>(p, size) {}
00480         CL_Rect(const CL_Rectx<int> &rect) : CL_Rectx<int>(rect) {}
00481         CL_Rect(const CL_Rectx<float> &rect) : CL_Rectx<int>(rect) {}
00482         CL_Rect(const CL_Rectx<double> &rect) : CL_Rectx<int>(rect) {}
00483         CL_Rect(int new_left, int new_top, const CL_Sizex<int> &size) : CL_Rectx<int>(new_left, new_top, size) {}
00484 };
00485 
00489 class CL_Rectf : public CL_Rectx<float>
00490 {
00491 public:
00492         CL_Rectf() : CL_Rectx<float>() {}
00493         CL_Rectf(const CL_Sizex<int> &s) : CL_Rectx<float>(s) {}
00494         CL_Rectf(const CL_Sizex<float> &s) : CL_Rectx<float>(s) {}
00495         CL_Rectf(float new_left, float new_top, float new_right, float new_bottom) : CL_Rectx<float>(new_left, new_top, new_right, new_bottom) {}
00496         CL_Rectf(const CL_Pointx<float> &p, const CL_Sizex<float> &size) : CL_Rectx<float>(p, size) {}
00497         CL_Rectf(const CL_Rectx<int> &rect) : CL_Rectx<float>(rect) {}
00498         CL_Rectf(const CL_Rectx<float> &rect) : CL_Rectx<float>(rect) {}
00499         CL_Rectf(const CL_Rectx<double> &rect) : CL_Rectx<float>(rect) {}
00500         CL_Rectf(float new_left, float new_top, const CL_Sizex<float> &size) : CL_Rectx<float>(new_left, new_top, size) {}
00501 };
00502 
00506 class CL_Rectd : public CL_Rectx<double>
00507 {
00508 public:
00509         CL_Rectd() : CL_Rectx<double>() {}
00510         CL_Rectd(const CL_Sizex<int> &s) : CL_Rectx<double>(s) {}
00511         CL_Rectd(const CL_Sizex<float> &s) : CL_Rectx<double>(s) {}
00512         CL_Rectd(const CL_Sizex<double> &s) : CL_Rectx<double>(s) {}
00513         CL_Rectd(double new_left, double new_top, double new_right, double new_bottom) : CL_Rectx<double>(new_left, new_top, new_right, new_bottom) {}
00514         CL_Rectd(const CL_Pointx<double> &p, const CL_Sizex<double> &size) : CL_Rectx<double>(p, size) {}
00515         CL_Rectd(const CL_Rectx<int> &rect) : CL_Rectx<double>(rect) {}
00516         CL_Rectd(const CL_Rectx<float> &rect) : CL_Rectx<double>(rect) {}
00517         CL_Rectd(const CL_Rectx<double> &rect) : CL_Rectx<double>(rect) {}
00518         CL_Rectd(double new_left, double new_top, const CL_Sizex<double> &size) : CL_Rectx<double>(new_left, new_top, size) {}
00519 };
00520 
00521 inline CL_Rect CL_RectPS(int x, int y, int width, int height)
00522 {
00523         return CL_Rect(x, y, x+width, y+height);
00524 }
00525 
00526 inline CL_Rectf CL_RectfPS(float x, float y, float width, float height)
00527 {
00528         return CL_Rectf(x, y, x+width, y+height);
00529 }
00530 
00531 inline CL_Rectd CL_RectdPS(double x, double y, double width, double height)
00532 {
00533         return CL_Rectd(x, y, x+width, y+height);
00534 }
00535