1 /* === S Y N F I G ========================================================= */ 2 /*! \file rect.h 3 ** \brief Rectangle Class 4 ** 5 ** $Id$ 6 ** 7 ** \legal 8 ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley 9 ** Copyright (c) 2007, 2008 Chris Moore 10 ** 11 ** This package is free software; you can redistribute it and/or 12 ** modify it under the terms of the GNU General Public License as 13 ** published by the Free Software Foundation; either version 2 of 14 ** the License, or (at your option) any later version. 15 ** 16 ** This package is distributed in the hope that it will be useful, 17 ** but WITHOUT ANY WARRANTY; without even the implied warranty of 18 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 ** General Public License for more details. 20 ** \endlegal 21 */ 22 /* ========================================================================= */ 23 24 /* === S T A R T =========================================================== */ 25 26 #ifndef __SYNFIG_RECT_H 27 #define __SYNFIG_RECT_H 28 29 /* === H E A D E R S ======================================================= */ 30 31 #include <ETL/rect> 32 #include "real.h" 33 #include "vector.h" 34 #include <limits> 35 #include <cmath> 36 37 /* === M A C R O S ========================================================= */ 38 39 /* === T Y P E D E F S ===================================================== */ 40 41 /* === C L A S S E S & S T R U C T S ======================================= */ 42 43 namespace synfig { 44 45 class RectInt : public etl::rect<int> 46 { 47 public: 48 typedef etl::rect<int> baserect; 49 50 using baserect::set_point; 51 using baserect::expand; 52 using baserect::set; 53 zero()54 static RectInt zero() 55 { 56 return RectInt( 57 0, 58 0, 59 0, 60 0 61 ); 62 } 63 RectInt()64 RectInt(): baserect(0, 0, 0, 0) { } 65 RectInt(const PointInt & x)66 RectInt(const PointInt& x) { set_point(x); } 67 RectInt(const PointInt & min,const PointInt & max)68 RectInt(const PointInt& min, const PointInt& max) { set_point(min); expand(max); } 69 RectInt(const value_type & x1,const value_type & y1)70 RectInt(const value_type &x1,const value_type &y1) { set_point(x1,y1); } 71 RectInt(const value_type & x1,const value_type & y1,const value_type & x2,const value_type & y2)72 RectInt(const value_type &x1,const value_type &y1, 73 const value_type &x2,const value_type &y2) 74 { 75 set_point(x1,y1); 76 expand(x2,y2); 77 } 78 set_point(const PointInt & max)79 void set_point(const PointInt& max) { set_point(max[0],max[1]); } 80 expand(const PointInt & max)81 RectInt& expand(const PointInt& max) { expand(max[0],max[1]); return *this; } 82 expand(const int & r)83 RectInt& expand(const int& r) { minx-=r; miny-=r; maxx+=r; maxy+=r; return *this; } 84 expand_x(const int & r)85 RectInt& expand_x(const int& r) { minx-=r; maxx+=r; return *this; } 86 expand_y(const int & r)87 RectInt& expand_y(const int& r) { miny-=r; maxy+=r; return *this; } 88 set(const PointInt & min,const PointInt & max)89 RectInt& set(const PointInt& min,const PointInt& max) { set(min[0],min[1],max[0],max[1]); return *this; } 90 get_min()91 PointInt get_min()const { return PointInt(minx,miny); } get_max()92 PointInt get_max()const { return PointInt(maxx,maxy); } get_size()93 VectorInt get_size()const { return get_max() - get_min(); } get_width()94 value_type get_width()const { return maxx - minx; } get_height()95 value_type get_height()const { return maxy - miny; } 96 is_inside(const PointInt & x)97 bool is_inside(const PointInt& x) { return x[0]>=minx && x[0]<maxx && x[1]>=miny && x[1]<maxy; } 98 area()99 int area()const 100 { 101 return (maxx-minx)*(maxy-miny); 102 } 103 104 // Operators 105 106 RectInt& operator+=(const VectorInt& rhs) 107 { 108 minx+=rhs[0]; miny+=rhs[1]; 109 maxx+=rhs[0]; maxy+=rhs[1]; 110 return *this; 111 } 112 113 RectInt& operator-=(const VectorInt& rhs) 114 { 115 minx-=rhs[0]; miny-=rhs[1]; 116 maxx-=rhs[0]; maxy-=rhs[1]; 117 return *this; 118 } 119 120 RectInt& operator*=(const int& rhs) 121 { 122 minx*=rhs; miny*=rhs; 123 maxx*=rhs; maxy*=rhs; 124 return *this; 125 } 126 127 RectInt& operator/=(int rhs) 128 { 129 minx/=rhs; miny/=rhs; 130 maxx/=rhs; maxy/=rhs; 131 return *this; 132 } 133 134 RectInt& operator&=(const RectInt& rhs) 135 { 136 if(rhs.valid() && valid()) 137 etl::set_intersect(*this,*this,rhs); 138 else 139 *this=zero(); 140 return *this; 141 } 142 143 RectInt& operator|=(const RectInt& rhs) 144 { 145 if(rhs.valid()>0 && valid()>0) 146 etl::set_union(*this,*this,rhs); 147 else 148 { 149 if(area()<rhs.area()) 150 *this=rhs; 151 } 152 return *this; 153 } 154 155 RectInt operator+(const VectorInt& rhs)const { return RectInt(*this)+=rhs; } 156 157 RectInt operator-(const VectorInt& rhs)const { return RectInt(*this)-=rhs; } 158 159 RectInt operator*(const int& rhs)const { return RectInt(*this)*=rhs; } 160 161 RectInt operator/(const int& rhs)const { return RectInt(*this)/=rhs; } 162 163 RectInt operator&(const RectInt& rhs)const { return RectInt(*this)&=rhs; } 164 165 RectInt operator|(const RectInt& rhs)const { return RectInt(*this)|=rhs; } 166 167 bool operator&&(const RectInt& rhs)const { return valid() && rhs.valid() && etl::intersect(*this, rhs); } 168 169 bool operator==(const RectInt &rhs)const { return get_min() == rhs.get_min() && get_max() == rhs.get_max(); } 170 171 bool operator!=(const RectInt &rhs)const { return get_min() != rhs.get_min() || get_max() != rhs.get_max(); } 172 contains(const RectInt & x)173 bool contains(const RectInt &x)const { return etl::contains(*this, x); } 174 is_valid()175 bool is_valid()const { return valid(); } 176 177 template<typename List> merge(List & list)178 static void merge(List &list) 179 { etl::rects_merge(list); } 180 181 template<typename List> list_add(List & list)182 void list_add(List &list) 183 { etl::rects_add(list, *this); merge(list); } 184 185 template<typename List> list_subtract(List & list)186 void list_subtract(List &list) 187 { etl::rects_subtract(list, *this); merge(list); } 188 multiply_coords(const VectorInt & rhs)189 RectInt multiply_coords(const VectorInt &rhs) const 190 { return RectInt(minx*rhs[0], miny*rhs[1], maxx*rhs[0], maxy*rhs[1]); } divide_coords(const VectorInt & rhs)191 RectInt divide_coords(const VectorInt &rhs) const 192 { return RectInt(minx/rhs[0], miny/rhs[1], maxx/rhs[0], maxy/rhs[1]); } 193 }; // END of class RectInt 194 195 196 class Rect : public etl::rect<Real> 197 { 198 public: 199 typedef etl::rect<Real> baserect; 200 201 using baserect::set_point; 202 using baserect::expand; 203 using baserect::set; 204 205 static Rect full_plane(); 206 207 static Rect horizontal_strip(const value_type &y1, const value_type &y2); 208 static Rect vertical_strip(const value_type &x1, const value_type &x2); 209 zero()210 static Rect zero() 211 { 212 return Rect( 213 0, 214 0, 215 0, 216 0 217 ); 218 } 219 infinite()220 static Rect infinite() 221 { 222 return Rect( 223 -INFINITY, 224 -INFINITY, 225 INFINITY, 226 INFINITY 227 ); 228 } 229 Rect()230 Rect(): baserect(0, 0, 0, 0) { } 231 Rect(const Point & x)232 Rect(const Point& x) { set_point(x); } 233 Rect(const Point & min,const Point & max)234 Rect(const Point& min, const Point& max) { set_point(min); expand(max); } 235 Rect(const value_type & x1,const value_type & y1)236 Rect(const value_type &x1,const value_type &y1) { set_point(x1,y1); } 237 Rect(const value_type & x1,const value_type & y1,const value_type & x2,const value_type & y2)238 Rect(const value_type &x1,const value_type &y1, 239 const value_type &x2,const value_type &y2) 240 { 241 set_point(x1,y1); 242 expand(x2,y2); 243 } 244 set_point(const Point & max)245 void set_point(const Point& max) { set_point(max[0],max[1]); } 246 expand(const Point & max)247 Rect& expand(const Point& max) { expand(max[0],max[1]); return *this; } 248 expand(const Real & r)249 Rect& expand(const Real& r) { minx-=r; miny-=r; maxx+=r; maxy+=r; return *this; } 250 expand_x(const Real & r)251 Rect& expand_x(const Real& r) { minx-=r; maxx+=r; return *this; } 252 expand_y(const Real & r)253 Rect& expand_y(const Real& r) { miny-=r; maxy+=r; return *this; } 254 set(const Point & min,const Point & max)255 Rect& set(const Point& min,const Point& max) { set(min[0],min[1],max[0],max[1]); return *this; } 256 get_min()257 Point get_min()const { return Point(minx,miny); } get_max()258 Point get_max()const { return Point(maxx,maxy); } get_size()259 Vector get_size()const { return get_max() - get_min(); } get_width()260 value_type get_width()const { return maxx - minx; } get_height()261 value_type get_height()const { return maxy - miny; } 262 is_inside(const Point & x)263 bool is_inside(const Point& x) 264 { 265 return approximate_less_or_equal(minx, x[0]) 266 && approximate_less_or_equal(x[0], maxx) 267 && approximate_less_or_equal(miny, x[1]) 268 && approximate_less_or_equal(x[1], maxy); 269 } 270 area()271 Real area()const 272 { 273 return (maxx-minx)*(maxy-miny); 274 } 275 276 // Operators 277 278 Rect& operator+=(const Vector& rhs) 279 { 280 minx+=rhs[0]; miny+=rhs[1]; 281 maxx+=rhs[0]; maxy+=rhs[1]; 282 return *this; 283 } 284 285 Rect& operator-=(const Vector& rhs) 286 { 287 minx-=rhs[0]; miny-=rhs[1]; 288 maxx-=rhs[0]; maxy-=rhs[1]; 289 return *this; 290 } 291 292 Rect& operator*=(const Real& rhs) 293 { 294 minx*=rhs; miny*=rhs; 295 maxx*=rhs; maxy*=rhs; 296 return *this; 297 } 298 299 Rect& operator/=(Real rhs) 300 { 301 rhs=1.0/rhs; // Avoid doing several divisions 302 minx*=rhs; miny*=rhs; 303 maxx*=rhs; maxy*=rhs; 304 return *this; 305 } 306 307 Rect& operator&=(const Rect& rhs) 308 { 309 if ( rhs.valid() && valid() 310 && rhs.area()>0.00000001 && area()>0.00000001 ) 311 etl::set_intersect(*this,*this,rhs); 312 else 313 *this=zero(); 314 return *this; 315 } 316 317 Rect& operator|=(const Rect& rhs) 318 { 319 if ( rhs.valid() && valid() 320 && rhs.area()>0.00000001 && area()>0.00000001 ) 321 etl::set_union(*this,*this,rhs); 322 else 323 { 324 if(area()<rhs.area()) 325 *this=rhs; 326 } 327 return *this; 328 } 329 330 Rect operator+(const Vector& rhs)const { return Rect(*this)+=rhs; } 331 332 Rect operator-(const Vector& rhs)const { return Rect(*this)-=rhs; } 333 334 Rect operator*(const Real& rhs)const { return Rect(*this)*=rhs; } 335 336 Rect operator/(const Real& rhs)const { return Rect(*this)/=rhs; } 337 338 Rect operator&(const Rect& rhs)const { return Rect(*this)&=rhs; } 339 340 Rect operator|(const Rect& rhs)const { return Rect(*this)|=rhs; } 341 342 bool operator&&(const Rect& rhs)const { return valid() && rhs.valid() && etl::intersect(*this, rhs); } 343 344 bool operator==(const Rect &rhs)const { return get_min() == rhs.get_min() && get_max() == rhs.get_max(); } 345 346 bool operator!=(const Rect &rhs)const { return get_min() != rhs.get_min() || get_max() != rhs.get_max(); } 347 contains(const Rect & x)348 bool contains(const Rect &x)const { return etl::contains(*this, x, approximate_less<Real>); } 349 valid()350 bool valid()const { return etl::rect<value_type>::valid(approximate_less<Real>); } is_valid()351 bool is_valid()const { return valid(); } is_nan_or_inf()352 bool is_nan_or_inf()const 353 { 354 return std::isnan(minx) 355 || std::isnan(miny) 356 || std::isinf(maxx) 357 || std::isinf(maxy); 358 } 359 360 template<typename List> merge(List & list)361 static void merge(List &list) 362 { etl::rects_merge(list, approximate_less<Real>); } 363 364 template<typename List> list_add(List & list)365 void list_add(List &list) 366 { etl::rects_add(list, *this, approximate_less<Real>); merge(list); } 367 368 template<typename List> list_subtract(List & list)369 void list_subtract(List &list) 370 { etl::rects_subtract(list, *this, approximate_less<Real>); merge(list); } 371 multiply_coords(const Vector & rhs)372 Rect multiply_coords(const Vector &rhs) const 373 { return Rect(minx*rhs[0], miny*rhs[1], maxx*rhs[0], maxy*rhs[1]); } divide_coords(const Vector & rhs)374 Rect divide_coords(const Vector &rhs) const 375 { return Rect(minx/rhs[0], miny/rhs[1], maxx/rhs[0], maxy/rhs[1]); } 376 }; // END of class Rect 377 378 }; // END of namespace synfig 379 380 /* === E N D =============================================================== */ 381 382 #endif 383