last update 20 Sep 2009 |
00001 /* 00002 * Copyright (C) 1998-2004 00003 * Lehrstuhl fuer Technische Informatik, RWTH-Aachen, Germany 00004 * 00005 * 00006 * This file is part of the Computer Vision and Robotics Library (CVR-Lib) 00007 * 00008 * The CVR-Lib is free software; you can redistribute it and/or 00009 * modify it under the terms of the BSD License. 00010 * 00011 * All rights reserved. 00012 * 00013 * Redistribution and use in source and binary forms, with or without 00014 * modification, are permitted provided that the following conditions are met: 00015 * 00016 * 1. Redistributions of source code must retain the above copyright notice, 00017 * this list of conditions and the following disclaimer. 00018 * 00019 * 2. Redistributions in binary form must reproduce the above copyright notice, 00020 * this list of conditions and the following disclaimer in the documentation 00021 * and/or other materials provided with the distribution. 00022 * 00023 * 3. Neither the name of the authors nor the names of its contributors may be 00024 * used to endorse or promote products derived from this software without 00025 * specific prior written permission. 00026 * 00027 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00028 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00029 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00030 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00031 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00032 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00033 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00034 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00035 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00036 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00037 * POSSIBILITY OF SUCH DAMAGE. 00038 */ 00039 00040 00041 00042 /** 00043 * \file cvrRectangle.h 00044 * Contains template class for aligned rectangles, which are described 00045 * through two points. 00046 * \author Pablo Alvarado 00047 * \date 01.11.2002 00048 * 00049 * $Id: cvrRectangle.h,v 1.9 2007/10/22 00:47:18 alvarado Exp $ 00050 */ 00051 00052 #ifndef _CVR_RECTANGLE_H 00053 #define _CVR_RECTANGLE_H 00054 00055 #include "cvrIoHandler.h" 00056 #include "cvrPoint.h" 00057 #include "cvrTypeInfo.h" 00058 00059 #include <iostream> 00060 00061 namespace cvr { 00062 00063 /** 00064 * Policy class to compute the size of a rectangle's side and the 00065 * inverse transformation. 00066 * 00067 * For integer types it assumes the rectangle lies on a discrete grid with 00068 * grid elements of size 1x1, which means that the size of a side defined by 00069 * two scalar values x1 and x2 (x2>x1) is x2-x1+1. 00070 * 00071 * For floating point values the size is just x2-x1, because of the 00072 * assumption that the rectangle lies on a real valued 2D space. 00073 * 00074 * The template parameter T represents the type used for the coordinates, and 00075 * is usually int or float. 00076 */ 00077 template <typename T> 00078 class rectangleSide { 00079 public: 00080 /** 00081 * Return the size of a rectangle's side which is aligned with one 00082 * of the two coordinates, assuming that the delimiting coordinates are 00083 * x1 and x2. 00084 * 00085 * For example: 00086 * - if T is int, x1=0 and x2=2, then returns 3 00087 * - if T is float, x1=0 and x2=2 then returns 2 00088 */ 00089 static inline T size(const T x1,const T x2); 00090 00091 /** 00092 * For a given side size, compute two coordinates which generates it. 00093 * 00094 * For example: 00095 * - if T is int and sz is 3, the returned values would be 00096 * x1=-1 and x2=1. 00097 * - if T is float and sz = 3, the returned values would be 00098 * x1=-1.5 and x2=1.5 00099 */ 00100 static inline void invSize(const T sz,T& x1,T& x2); 00101 }; 00102 00103 // specialization for float 00104 template <> 00105 class rectangleSide<float> { 00106 public: 00107 static inline float size(const float x1,const float x2); 00108 static inline void invSize(const float sz,float& x1,float& x2); 00109 }; 00110 00111 // specialization for double 00112 template <> 00113 class rectangleSide<double> { 00114 public: 00115 static inline double size(const double x1,const double x2); 00116 static inline void invSize(const double sz,double& x1,double& x2); 00117 }; 00118 00119 /** 00120 * Rectangle representation class. 00121 * 00122 * A rectangle is described by a pair of points: the upper-left and 00123 * bottom-right corners. 00124 * 00125 * A consistent rectangle will have the x and y coordinates of its upper- 00126 * left corner smaller than the ones of its bottom-right corner (note 00127 * the use of a left coordinate system, as usual with imaging systems). 00128 * 00129 * You can always check if a rectangle is consistent with the method 00130 * \c isConsistent() or even force its consistency with 00131 * \c ensureConsistency(). 00132 * 00133 * This is a template class, where the first template parameter \c T 00134 * denotes the type used for the two points, which will be of type 00135 * \c point<T>. For example, the type rectangle<int> (which 00136 * has the alias irectangle) contains to ipoints (point<int>) as corner 00137 * representation. You can access the type T through the public type 00138 * \c value_type. 00139 * 00140 * The second template parameter S is optional and allows the rectangle to 00141 * behave correctly in a discrete integer grid or in a continuous real grid 00142 * (please see the cvr::rectangleSide policy for more information). 00143 * 00144 * @ingroup gGeomData 00145 */ 00146 template <typename T,class S=rectangleSide<T> > 00147 class rectangle { 00148 public: 00149 /** 00150 * Type used in each coordinate of the two internal points 00151 */ 00152 typedef T value_type; 00153 00154 /** 00155 * Type used for the side policy 00156 */ 00157 typedef S side_type; 00158 00159 /** 00160 * \name The two corners of the rectangle 00161 */ 00162 //@{ 00163 /** 00164 * Upper-left point<T> 00165 */ 00166 point<T> ul; 00167 00168 /** 00169 * Bottom-right point<T> 00170 */ 00171 point<T> br; 00172 //@} 00173 00174 /** 00175 * Default constructor 00176 * 00177 * The two points \a ul and \a br will be initialized with (0,0) 00178 */ 00179 rectangle(); 00180 00181 /** 00182 * Constructor with two points 00183 * 00184 * @param ul upper left corner 00185 * @param br bottom right corner 00186 */ 00187 rectangle(const point<T>& ul,const point<T>& br); 00188 00189 /** 00190 * Construct a rectangle via separate coordinates 00191 * 00192 * @param left left side coordinate 00193 * @param top top side coordinate 00194 * @param right right side coordinate 00195 * @param bottom bottom side coordinate 00196 */ 00197 rectangle(const T& left,const T& top, 00198 const T& right,const T& bottom); 00199 00200 /** 00201 * Construct a square with the given side size. 00202 * 00203 * If the size is even and T is an integer type, the rectangle 00204 * will be created from -|_size/2_| to size + |_size/2_| in both 00205 * coordinates x and y. 00206 */ 00207 rectangle(const T& size); 00208 00209 /** 00210 * Copy constructor 00211 */ 00212 template<typename U,class US> 00213 rectangle(const rectangle<U,US>& other); 00214 00215 00216 /** 00217 * Set the corners via separate coordinates 00218 * 00219 * You must ensure that the data is consistent, i.e. left < right and 00220 * top < bottom. See setConsistent(). 00221 * 00222 * @param left left side coordinate 00223 * @param top top side coordinate 00224 * @param right right side coordinate 00225 * @param bottom bottom side coordinate 00226 * @return true when successful, false otherwise 00227 */ 00228 inline bool set(const T& left, const T& top, 00229 const T& right, const T& bottom); 00230 00231 00232 /** 00233 * Set the corners via two points 00234 * 00235 * You must ensure that the data is consistent, i.e. ul.x < br.x and 00236 * ul.y < br.y. See setConsistent(). 00237 * 00238 * @param ul upper left corner 00239 * @param br bottom right corner 00240 * @return true upon success, false otherwise 00241 */ 00242 inline bool set(const point<T>& ul, const point<T>& br); 00243 00244 /** 00245 * Set the corners via separate coordinates. 00246 * 00247 * This method ensures consistency of the resulting rectangle, no matter if 00248 * the given data implies negative sides. 00249 * 00250 * @param left left side coordinate 00251 * @param top top side coordinate 00252 * @param right right side coordinate 00253 * @param bottom bottom side coordinate 00254 * @return true when successful, false otherwise 00255 */ 00256 inline bool setConsistent(const T& left, const T& top, 00257 const T& right, const T& bottom); 00258 00259 00260 /** 00261 * Set the corners via two points 00262 * 00263 * This method ensures consistency of the resulting rectangle, no matter if 00264 * the given data implies negative sides. 00265 * 00266 * @param ul upper left corner 00267 * @param br bottom right corner 00268 * @return true upon success, false otherwise 00269 */ 00270 inline bool setConsistent(const point<T>& ul, const point<T>& br); 00271 00272 00273 /** 00274 * @name Location and Dimensions 00275 */ 00276 //@{ 00277 00278 /** 00279 * Resize rectangle<T,S> with new dimensions, but keep its center 00280 */ 00281 void resize(const point<T>& dim); 00282 00283 /** 00284 * Resize rectangle<T,S> with new dimensions, but keep its center 00285 */ 00286 void resize(const T& x, const T& y); 00287 00288 /** 00289 * Get dimensions of rectangle<T,S>. If one coordinate of the two 00290 * points coincide and the rectangle contains fixed point typed 00291 * points, the returned dimension is one. For floating point 00292 * types this case will return 0. 00293 * 00294 * \warning Note that the result of this method depends on the type T 00295 * 00296 * For integer types it will be assumed that the rectangle lies on 00297 * a discrete grid with grid elements of size 1x1, and that is not 00298 * the rectangle itself what is described but the number of grid 00299 * elements. This means that the size of a side defined by two 00300 * scalar values x1 and x2 (x2>x1) is x2-x1+1. This is useful for 00301 * example when dealing with rectangular regions of images. 00302 * 00303 * For floating point values the size is just x2-x1, because of 00304 * the assumtion that the rectangle lies on a real valued 2D space. 00305 */ 00306 inline point<T> getDimensions() const; 00307 00308 /** 00309 * Get the area of this rectangle. This value is always 00310 * positive, regardless of the position of the upper left and 00311 * bottom right corner. A rectangle whose corners coincide 00312 * has an area of 1 for fixed point types or 0 for floating point ones. 00313 * 00314 * \warning Note that the result of this method depends on the type T 00315 * 00316 * For integer types it will be assumed that the rectangle lies on 00317 * a discrete grid with grid elements of size 1x1, and that is not 00318 * the rectangle itself what is described but the index of grid 00319 * elements. This means that the size of a side defined by two 00320 * scalar values x1 and x2 (x2>x1) is x2-x1+1. This is useful for 00321 * example when dealing with rectangular regions of images. 00322 * 00323 * For floating point values the size is just x2-x1, because of 00324 * the assumtion that the rectangle lies on a real valued 2D space. 00325 */ 00326 inline typename typeInfo<T>::square_accumulation_type getArea() const; 00327 00328 /** 00329 * Get center of rectangle<T,S> 00330 */ 00331 inline point<T> getCenter() const; 00332 00333 /** 00334 * Set the center of this rectangle. 00335 */ 00336 void setCenter(point<T> center); 00337 00338 /** 00339 * Ensure consistency of upper-left and bottom-right corners. 00340 * A rectangle<T,S> is called "consistent" if the upper-left 00341 * point<T> has lower coordinate-values than the bottom-right 00342 * point<T>. 00343 */ 00344 void ensureConsistency(); 00345 00346 /** 00347 * Check for consistent rectangle<T,S>. 00348 * @return True if upper-left corner and bottom-right are correct 00349 */ 00350 inline bool isConsistent() const; 00351 00352 /** 00353 * Shift rectangle<T,S> by delta 00354 * 00355 * @param delta The shift amount to be added to both corners 00356 */ 00357 inline void shift(const point<T>& delta); 00358 00359 /** 00360 * Shift the other rectangle<T,S> by delta and leave the result here 00361 * 00362 * @param other The reference rectangle 00363 * @param delta The shift amount to be added to both corners of the 00364 * reference rectangle 00365 */ 00366 inline void shift(const rectangle<T,S>& other, 00367 const point<T>& delta); 00368 //@} 00369 00370 /** 00371 * @name Simple operations 00372 */ 00373 //@{ 00374 00375 /** 00376 * Check if point<T> p is inside this rectangle. (border inclusive!) 00377 */ 00378 inline bool contains(const point<T>& p) const; 00379 00380 /** 00381 * Check if the given coordinates are inside this rectangle. 00382 * (border included!) 00383 */ 00384 inline bool contains(const T& x, const T& y) const; 00385 00386 //@} 00387 00388 /** 00389 * @name Duplication 00390 */ 00391 //@{ 00392 00393 /** 00394 * Copy member 00395 */ 00396 rectangle<T,S>& copy(const rectangle<T,S>& other); 00397 00398 /** 00399 * Cast from a rectangle of another type 00400 */ 00401 template <class U,class SU> 00402 rectangle<T,S>& castFrom(const rectangle<U,SU>& other); 00403 00404 /** 00405 * Alias for copy 00406 */ 00407 inline rectangle<T,S>& operator=(const rectangle<T,S>& other); 00408 00409 //@} 00410 00411 /** 00412 * @name Comparison 00413 */ 00414 //@{ 00415 00416 /** 00417 * Test for equality 00418 */ 00419 inline bool operator==(const rectangle<T,S>& other) const; 00420 00421 /** 00422 * Test for inequality 00423 */ 00424 inline bool operator!=(const rectangle<T,S>& other) const; 00425 00426 //@} 00427 00428 /** 00429 * @name Geometrical combination 00430 */ 00431 //@{ 00432 00433 /** 00434 * Intersection of this rectangle with tRect 00435 * 00436 * (the largest rectangle which is contained both inside this 00437 * rectangle and inside tRect). 00438 * 00439 * The result will be left in this instance. If the rectangles do 00440 * not intersect, the resul will be inconsistent, so you should 00441 * call isConsistent() to check for this case unless you know for 00442 * sure that it cannot occur. 00443 * 00444 * @return A reference to this (modified) instance. 00445 */ 00446 rectangle<T,S>& intersect(const rectangle<T,S>& tRect); 00447 00448 /** 00449 * Check whether this rectangle overlaps with the given rectangle. 00450 */ 00451 bool overlaps(const rectangle<T,S>& tRect) const; 00452 00453 /** 00454 * Check whether this rectangle is close to the given rectangle, i.e. 00455 * if the two rectangles overlap if one is extended by the given distance. 00456 */ 00457 bool isClose(const rectangle<T,S>& tRect, const point<T>& dist) const; 00458 00459 /** 00460 * This rectangle is set to the intersection of himself with tRect. 00461 * (alias for intersect) 00462 */ 00463 inline rectangle<T,S>& operator&=(const rectangle<T,S>& tRect); 00464 00465 /** 00466 * New rectangle equals the intersection of this rectangle with tRect 00467 */ 00468 inline rectangle<T,S> operator&(const rectangle<T,S>& tRect); 00469 00470 /** 00471 * Union-rectangle of this rectangle with tRect. 00472 * 00473 * This is the smallest rectangle containing both this rectangle and 00474 * tRect. The result will be left in this instance. 00475 * 00476 * @return A reference to this (modified) instance. 00477 */ 00478 rectangle<T,S>& join(const rectangle<T,S>& tRect); 00479 00480 /** 00481 * This rectangle is set to the union-rectangle of this rectangle with 00482 * tRect (alias for join()). 00483 */ 00484 inline rectangle<T,S>& operator|=(const rectangle<T,S>& tRect); 00485 00486 /** 00487 * Generates a new rectangle equal to the smallest rectangle that 00488 * contains the union of this rectangle with tRect 00489 */ 00490 rectangle<T,S> operator|(const rectangle<T,S>& tRect); 00491 //@} 00492 }; 00493 00494 /** 00495 * A rectangle with integer coordinates 00496 */ 00497 typedef rectangle<int> irectangle; 00498 00499 /** 00500 * A rectangle with float coordinates 00501 */ 00502 typedef rectangle<float> frectangle; 00503 00504 /** 00505 * A rectangle with double coordinates 00506 */ 00507 typedef rectangle<double> drectangle; 00508 00509 /** 00510 * Read the vector from the given ioHandler. The complete flag indicates 00511 * if the enclosing begin and end should be also read. 00512 * 00513 * @ingroup gStorable 00514 */ 00515 template<typename T,class S> 00516 bool read(ioHandler& handler,rectangle<T,S>& p,const bool complete=true); 00517 00518 /** 00519 * Write the vector in the given ioHandler. The complete flag indicates 00520 * if the enclosing begin and end should be also written. 00521 * 00522 * @ingroup gStorable 00523 */ 00524 template <typename T,class S> 00525 bool write(ioHandler& handler,const rectangle<T,S>& p, 00526 const bool complete=true); 00527 } 00528 00529 namespace std { 00530 00531 template <typename T,class S> 00532 inline ostream& operator<<(ostream& s,const cvr::rectangle<T,S>& p); 00533 00534 template <typename T,class S> 00535 inline istream& operator>>(istream& s,cvr::rectangle<T,S>& p); 00536 } 00537 00538 #include "cvrRectangle_inline.h" 00539 #include "cvrRectangle_template.h" 00540 00541 #endif 00542