LTI-Lib latest version v1.9 - last update 10 Apr 2010

ltiRectangle.h

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2002, 2003, 2004, 2005, 2006
00003  * Lehrstuhl fuer Technische Informatik, RWTH-Aachen, Germany
00004  *
00005  * This file is part of the LTI-Computer Vision Library (LTI-Lib)
00006  *
00007  * The LTI-Lib is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public License (LGPL)
00009  * as published by the Free Software Foundation; either version 2.1 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * The LTI-Lib is distributed in the hope that it will be
00013  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
00014  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with the LTI-Lib; see the file LICENSE.  If
00019  * not, write to the Free Software Foundation, Inc., 59 Temple Place -
00020  * Suite 330, Boston, MA 02111-1307, USA.
00021  */
00022 
00023 
00024 /*----------------------------------------------------------------
00025  * project ....: LTI Digital Image/Signal Processing Library
00026  * file .......: ltiRectangle.h
00027  * authors ....: Pablo Alvarado
00028  * organization: LTI, RWTH Aachen
00029  * creation ...: 01.11.2002
00030  * revisions ..: $Id: ltiRectangle.h,v 1.8 2006/02/07 18:10:26 ltilib Exp $
00031  */
00032 
00033 #ifndef LTI_RECTANGLE_H
00034 #define LTI_RECTANGLE_H
00035 
00036 #include <iostream>
00037 #include "ltiIoHandler.h"
00038 #include "ltiConfig.h"
00039 #include "ltiPoint.h"
00040 #include "ltiMath.h"
00041 
00042 /**
00043  * @file ltiRectangle.h
00044  *
00045  * This file contains the definitions of the rectangle and trectangle types
00046  * used in the LTI-Lib to describe rectangular areas through two points.
00047  */
00048 
00049 namespace lti {
00050 
00051   /**
00052    * Policy class to compute the size of a rectangle's side and the
00053    * inverse transformation.
00054    * 
00055    * For integer types it assumes the rectangle lies on a discrete grid with
00056    * grid elements of size 1x1, which means that the size of a side defined by
00057    * two scalar values x1 and x2 (x2>x1) is x2-x1+1.
00058    *
00059    * For floating point values the size is just x2-x1, because of the assumtion
00060    * that the rectangle lies on a real valued 2D space.
00061    */
00062   template <class T>
00063   class rectSide {
00064   public:
00065     /**
00066      * return the size of a rectangle's side which is aligned with one
00067      * of the two coordinates, assuming that the delimiting coordinates are
00068      * x1 and x2.
00069      *
00070      * For example:
00071      * - if T is int, x1=0 and x2=2, then size returns 3
00072      * - if T is float, x1=0 and x2=2 then size returns 2
00073      */
00074     static inline T size(const T x1,const T x2) {
00075       return (x2-x1+static_cast<T>(1));
00076     }
00077 
00078     /**
00079      * For a given side size, compute two coordinates which generates it.
00080      *
00081      * For example:
00082      * - if T is int and sz is 3, the returned values would be
00083      *   x1=-1 and x2=1.
00084      * - if T is float and sz = 3, the returned values would be
00085      *   x1=-1.5 and x2=1.5
00086      */
00087     static inline void invSize(const T sz,T& x1,T& x2) {
00088       x1=(static_cast<T>(1)-sz)/2;
00089       x2=x1+sz-1;
00090     }
00091   };
00092   
00093   // specialization for float and double
00094   template <>
00095   class rectSide<float> {
00096   public:
00097     static inline float size(const float x1,const float x2) {
00098       return (x2-x1);
00099     }
00100     static inline void invSize(const float sz,float& x1,float& x2) {
00101       x1=-sz/2.0f;
00102       x2=x1+sz;
00103     }
00104   };
00105 
00106   template <>
00107   class rectSide<double> {
00108   public:
00109     static inline double size(const double& x1,const double& x2) {
00110       return (x2-x1);
00111     }
00112     static inline void invSize(const double sz,double& x1,double& x2) {
00113       x1=-sz/2.0;
00114       x2=x1+sz;
00115     }
00116   };
00117 
00118   /**
00119    * Rectangle representation class.
00120    *
00121    * A rectangle is described by a pair of points: the upper-left and
00122    * bottom-right corners.
00123    *
00124    * A consistent rectangle will have the x and y coordinates of its upper-
00125    * left corner smaller than the ones of its bottom-right corner (note
00126    * the use of a left coordinate system, as usual with imaging systems).
00127    *
00128    * You can always check if a rectangle is consistent with the method 
00129    * \c isConsistent() or even force its consistency with
00130    * \c ensureConsistency().
00131    *
00132    * This is a template class, where the first template parameter \c T 
00133    * denotes the type used for the two points, which will be of type
00134    * <code>tpoint<T></code>.  For example, the type trectangle<int> (which
00135    * has the alias rectangle) contains to points (tpoint<int>) as corner 
00136    * representation.
00137    * The second template parameter is optional and allows the trectangle 
00138    * to behave correctly in a discrete integer grid or in a continuous real
00139    * grid (please see the lti::rectSide policy for more information).
00140    *
00141    * @ingroup gGeomData
00142    */
00143   template <class T,class S=rectSide<T> >
00144   class trectangle {
00145   public:
00146     /**
00147      * default constructor
00148      * The two points \a ul and \a br will be initialized with (0,0)
00149      */
00150     trectangle()
00151       : ul(tpoint<T>(0,0)),br(tpoint<T>(0,0)) {
00152     };
00153 
00154     /**
00155      * constructor
00156      */
00157     trectangle(const tpoint<T>& p1,const tpoint<T>& p2)
00158       : ul(p1), br(p2) {
00159     };
00160 
00161     /**
00162      * constructor
00163      */
00164     trectangle(const T& x1,const T& y1,
00165                const T& x2,const T& y2)
00166       : ul(tpoint<T>(x1,y1)),br(tpoint<T>(x2,y2)) {
00167     };
00168 
00169     /**
00170      * construct a square with the given side size.
00171      *
00172      * If the size is even and T is an integer type, the rectangle
00173      * will be created from -|_size/2_| to size + |_size/2_| in both
00174      * coordinates x and y.
00175      */
00176     trectangle(const T& size) {
00177       T low,high;
00178       S::invSize(size,low,high);
00179       ul.set(low,low);
00180       br.set(high,high);
00181     };
00182 
00183     /**
00184      * copy constructor
00185      */
00186     trectangle(const trectangle<T>& other)
00187       : ul(other.ul),br(other.br) {
00188     };
00189 
00190     /**
00191      * @name Location and Dimensions
00192      */
00193     //@{
00194 
00195     /**
00196      * resize trectangle<T> with new dimensions, but keep its center
00197      */
00198     void resize(const tpoint<T>& dim) {
00199       tpoint<T> cen = getCenter();
00200       S::invSize(dim.x,ul.x,br.x);
00201       S::invSize(dim.y,ul.y,br.y);
00202       ul.add(cen);
00203       br.add(cen);
00204     };
00205 
00206     /**
00207      * resize trectangle<T> with new dimensions, but keep its center
00208      */
00209     void resize(const T& x, const T& y) {
00210       tpoint<T> cen = getCenter();
00211       S::invSize(x,ul.x,br.x);
00212       S::invSize(y,ul.y,br.y);
00213       ul.add(cen);
00214       br.add(cen);
00215     };
00216 
00217     /**
00218      * Get dimensions of trectangle<T>.  If one coordinate of the two
00219      * points coincide and the rectangle contains fixed point typed
00220      * points, the returned dimension is one.  For floating point
00221      * types this case will return 0.
00222      *
00223      * \warning Note that the result of this method depends on the type T
00224      *
00225      * For integer types it will be assumed that the rectangle lies on
00226      * a discrete grid with grid elements of size 1x1, and that is not
00227      * the rectangle itself what is described but the number of grid
00228      * elements.  This means that the size of a side defined by two
00229      * scalar values x1 and x2 (x2>x1) is x2-x1+1.  This is useful for 
00230      * example when dealing with rectangular regions of images.
00231      *
00232      * For floating point values the size is just x2-x1, because of
00233      * the assumtion that the rectangle lies on a real valued 2D space.
00234      */
00235     tpoint<T> getDimensions() const {
00236       return tpoint<T>(S::size(ul.x,br.x),
00237                        S::size(ul.y,br.y));
00238     };
00239 
00240     /**
00241      * Get the area of this rectangle. This value is always
00242      * positive, regardless of the position of the upper left and
00243      * bottom right corner. A rectangle whose corners coincide
00244      * has an area of 1 for fixed point types or 0 for floating point ones.
00245      *
00246      * \warning Note that the result of this method depends on the type T
00247      *
00248      * For integer types it will be assumed that the rectangle lies on
00249      * a discrete grid with grid elements of size 1x1, and that is not
00250      * the rectangle itself what is described but the index of grid
00251      * elements.  This means that the size of a side defined by two
00252      * scalar values x1 and x2 (x2>x1) is x2-x1+1.  This is useful for 
00253      * example when dealing with rectangular regions of images.
00254      *
00255      * For floating point values the size is just x2-x1, because of
00256      * the assumtion that the rectangle lies on a real valued 2D space.
00257      */
00258     T getArea() const {
00259       return abs(S::size(ul.x,br.x)*
00260                  S::size(ul.y,br.y));
00261     };
00262 
00263     /**
00264      * Get center of trectangle<T>
00265      */
00266     tpoint<T> getCenter() const {
00267       return tpoint<T>((br.x+ul.x)/2,(br.y+ul.y)/2);
00268     };
00269 
00270     /**
00271      * Set the center of this rectangle.
00272      */
00273     void setCenter(tpoint<T> center) {
00274       tpoint<T> dim(abs(br.x-ul.x),abs(br.y-ul.y));
00275       ul.set(center.x - dim.x/2,center.y - dim.y/2);
00276       br.set(ul.x + dim.x,ul.y + dim.y);
00277     }
00278 
00279     /**
00280      * Ensure consistency of upper-left and bottom-right corners.
00281      * A trectangle<T> is called "consistent" if the upper-left
00282      * tpoint<T> has lower coordinate-values than the bottom-right
00283      * tpoint<T>.
00284      */
00285     void ensureConsistency() {
00286       trectangle<T> t(*this);
00287 
00288       if (t.ul.x > t.br.x) {
00289         ul.x = t.br.x;
00290         br.x = t.ul.x;
00291       }
00292 
00293       if (t.ul.y > t.br.y) {
00294         ul.y = t.br.y;
00295         br.y = t.ul.y;
00296       }
00297     };
00298 
00299     /**
00300      * Check for consistent trectangle<T>.
00301      * @return True if upper-left corner and bottom-right are correct
00302      */
00303     bool isConsistent() const {
00304       return !((ul.x > br.x) || (ul.y > br.y));
00305     };
00306 
00307     /**
00308      * Shift trectangle<T> by delta
00309      */
00310     void shift(const tpoint<T>& delta) {
00311       ul.add(delta);
00312       br.add(delta);
00313     };
00314 
00315     //@}
00316 
00317     /**
00318      * @name Simple operations
00319      */
00320     //@{
00321 
00322     /**
00323      * Check if tpoint<T> p is inside the trectangle<T>. (border included!)
00324      */
00325     bool isInside(const tpoint<T>& p) const {
00326       return ((p.x>=ul.x) && (p.x<=br.x) &&
00327               (p.y>=ul.y) && (p.y<=br.y));
00328     };
00329 
00330     /**
00331      * Check if the given coordinates are inside the trectangle<T>. 
00332      * (border included!)
00333      */
00334     bool isInside(const T& x, const T& y) const {
00335       return ((x>=ul.x) && (x<=br.x) &&
00336               (y>=ul.y) && (y<=br.y));
00337     };
00338 
00339     //@}
00340 
00341 
00342     /**
00343      * @name Duplication
00344      */
00345     //@{
00346 
00347     /**
00348      * copy member
00349      */
00350     trectangle<T>& copy(const trectangle<T>& other) {
00351       ul.copy(other.ul);
00352       br.copy(other.br);
00353       return (*this);
00354     };
00355 
00356     /**
00357      * cast from a rectangle of another type
00358      */
00359     template <class U,class SU>
00360     trectangle<T>& castFrom(const trectangle<U,SU>& other) {
00361       ul.x = static_cast<T>(other.ul.x);
00362       ul.y = static_cast<T>(other.ul.y);
00363       br.x = static_cast<T>(other.br.x);
00364       br.y = static_cast<T>(other.br.y);
00365 
00366       return (*this);
00367     };
00368 
00369     /**
00370      * alias for copy
00371      */
00372     trectangle<T>& operator=(const trectangle<T>& other) {
00373       return (copy(other));
00374     };
00375 
00376     //@}
00377 
00378     /**
00379      * @name Comparison
00380      */
00381     //@{
00382 
00383     /**
00384      * test for equality
00385      */
00386     bool operator==(const trectangle<T>& other) const {
00387       return ((other.ul == ul) &&
00388               (other.br == br));
00389     };
00390 
00391     /**
00392      * test for inequality
00393      */
00394     bool operator!=(const trectangle<T>& other) const {
00395       return ((other.ul != ul) ||
00396               (other.br != br));
00397     };
00398 
00399     //@}
00400 
00401     /**
00402      * @name Geometrical combination
00403      */
00404     //@{
00405 
00406     /**
00407      * Intersection of this trectangle with tRect
00408      * \deprecated Please use intersect instead
00409      */
00410     trectangle<T>& intersectRect(const trectangle<T>& tRect) {
00411       return intersect(tRect);
00412     };
00413 
00414     /**
00415      * Intersection of this trectangle with tRect
00416      *
00417      * (the largest rectangle which is contained both inside this
00418      * rectangle and inside tRect).
00419      *
00420      * The result will be left in this instance. If the rectangles do
00421      * not intersect, the resul will be inconsistent, so you should
00422      * call isConsistent() to check for this case unless you know for
00423      * sure that it cannot occur.
00424      *
00425      * @return a reference to this (modified) instance.
00426      */
00427     trectangle<T>& intersect(const trectangle<T>& tRect) {
00428       if (tRect.ul.x > ul.x) {
00429         ul.x = tRect.ul.x;
00430       }
00431       if (tRect.ul.y > ul.y) {
00432         ul.y = tRect.ul.y;
00433       }
00434       if (tRect.br.x < br.x) {
00435         br.x = tRect.br.x;
00436       }
00437       if (tRect.br.y < br.y) {
00438         br.y = tRect.br.y;
00439       }
00440       return (*this);
00441     };
00442 
00443 
00444     /**
00445      * Check whether this rectangle overlaps with the given rectangle.
00446      */
00447     bool overlaps(const trectangle<T>& tRect) const {
00448       trectangle<T> rect(*this);
00449       rect.intersect(tRect);
00450       return rect.isConsistent();
00451     };
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 trectangle<T>& tRect, const tpoint<T>& dist) const {
00458       const tpoint<T> br1 ( tRect.br + dist );
00459       const tpoint<T> ul1 ( tRect.ul - dist );
00460       
00461       if ( br.x >= ul1.x ) {
00462   if ( br.x <= br1.x ) {
00463     if ( br.y >= ul1.y ) {
00464       if ( br.y <= br1.y ) {
00465         return true;
00466         
00467       } else if ( ul.y <= br1.y ) {
00468         return true;
00469         
00470       } else {
00471         return false;
00472       }
00473       
00474     } else {
00475       return false;
00476     }
00477     
00478   } else if ( ul.x <= br1.x ) {
00479     if ( ul.y >= ul1.y ) {
00480       if ( ul.y <= br1.y ) {
00481         return true;
00482         
00483       } else {
00484         return false;
00485       }
00486       
00487     } else if ( br.y >= ul1.y ) {
00488       if ( ul.y <= br1.y ) {
00489         return true;
00490         
00491       } else {
00492         return false;
00493       }
00494       
00495     } else {
00496       return false;
00497     }
00498   }
00499       }
00500       
00501       return false;
00502     };
00503 
00504 
00505     /**
00506      * trectangle = intersection of trectangle with tRect.
00507      * (alias for intersect)
00508      */
00509     trectangle<T>& operator&=(const trectangle<T>& tRect) {
00510       return intersect(tRect);
00511     };
00512 
00513     /**
00514      * new trectangle = intersection of trectangle with tRect
00515      */
00516     trectangle<T> operator&(const trectangle<T>& tRect) {
00517       trectangle<T> tempRect(*this);
00518       return tempRect.intersect(tRect);
00519     };
00520     
00521     /**
00522      * Union of this trectangle with tRect
00523      * \deprecated please use join instead.
00524      */
00525     trectangle<T>& unionRect(const trectangle<T>& tRect) {
00526       return join(tRect);
00527     }
00528 
00529     /**
00530      * Union of this trectangle with tRect
00531      * (the smallest rectangle containing both this trectangle and tRect)
00532      * The result will be left in this instance.
00533      * @return a reference to this (modified) instance.
00534      */
00535     trectangle<T>& join(const trectangle<T>& tRect) {
00536       if (tRect.ul.x < ul.x) {
00537         ul.x = tRect.ul.x;
00538       }
00539       if (tRect.ul.y < ul.y) {
00540         ul.y = tRect.ul.y;
00541       }
00542       if (tRect.br.x > br.x) {
00543         br.x = tRect.br.x;
00544       }
00545       if (tRect.br.y > br.y) {
00546         br.y = tRect.br.y;
00547       }
00548       return (*this);
00549     };
00550 
00551     /**
00552      * trectangle = union of this trectangle with tRect
00553      * (alias for join)
00554      */
00555     trectangle<T>& operator|=(const trectangle<T>& tRect) {
00556       return join(tRect);
00557     };
00558 
00559     /**
00560      * new trectangle = union of this trectangle  with tRect
00561      */
00562     trectangle<T> operator|(const trectangle<T>& tRect) {
00563       trectangle<T> tempRect(*this);
00564       return tempRect.join(tRect);
00565     };
00566 
00567     //@}
00568 
00569 
00570     /**
00571      * upper-left tpoint<T>
00572      */
00573     tpoint<T> ul;
00574 
00575     /**
00576      * bottom-right tpoint<T>
00577      */
00578     tpoint<T> br;
00579 
00580   };
00581 
00582   /**
00583    * A rectangle with integer coordinates
00584    *
00585    * \deprecated  Please use irectangle instead.
00586    */
00587   typedef trectangle<int> rectangle;
00588 
00589   /**
00590    * A rectangle with integer coordinates
00591    *
00592    * \deprecated  Please use irectangle instead.
00593    */
00594   typedef trectangle<int> irectangle;
00595 
00596   /**
00597    * A rectangle with float coordinates
00598    *
00599    * \deprecated  Please use irectangle instead.
00600    */
00601   typedef trectangle<float> frectangle;
00602 
00603   /**
00604    * A rectangle with double coordinates
00605    *
00606    * \deprecated  Please use irectangle instead.
00607    */
00608   typedef trectangle<double> drectangle;
00609 
00610   /**
00611    * read the vector from the given ioHandler.  The complete flag indicates
00612    * if the enclosing begin and end should be also be readed
00613    *
00614    * @ingroup gStorable
00615    */
00616   template<class T,class S>
00617   bool read(ioHandler& handler,trectangle<T,S>& p,const bool complete=true) {
00618     bool b;
00619 
00620     if (complete) {
00621       handler.readBegin();
00622     }
00623 
00624     read(handler,p.ul);
00625     handler.readDataSeparator();
00626     b = read(handler,p.br);
00627 
00628     if (complete) {
00629       b = handler.readEnd();
00630     }
00631 
00632     return b;
00633   };
00634 
00635   /**
00636    * write the vector in the given ioHandler.  The complete flag indicates
00637    * if the enclosing begin and end should be also be written or not
00638    *
00639    * @ingroup gStorable
00640    */
00641   template <class T,class S>
00642   bool write(ioHandler& handler,const trectangle<T,S>& p,
00643              const bool complete=true) {
00644     bool b;
00645 
00646     if (complete) {
00647       handler.writeBegin();
00648     }
00649     write(handler,p.ul);
00650     handler.writeDataSeparator();
00651     b = write(handler,p.br);
00652 
00653     if (complete) {
00654       b = handler.writeEnd();
00655     }
00656 
00657     return b;
00658   };
00659 }
00660 
00661 namespace std {
00662 
00663   //inline ostream& operator<<(ostream& s,const lti::point& p);
00664   template <class T,class S>
00665   inline ostream& operator<<(ostream& s,const lti::trectangle<T,S>& p) {
00666     s << "(" << p.ul << ","
00667       << p.br << ")";
00668     return s;
00669   };
00670 
00671   //inline ostream& operator>>(istream& s,const lti::point& p);
00672   template <class T,class S>
00673   inline istream& operator>>(istream& s,lti::trectangle<T,S>& p) {
00674     char c;
00675     lti::tpoint<T> ul,br;
00676     s >> c
00677       >> ul >> c
00678       >> br >> c;
00679     p.ul = ul;
00680     p.br = br;
00681 
00682     return s;
00683   };
00684 }
00685 
00686 #endif

Generated on Sat Apr 10 15:26:03 2010 for LTI-Lib by Doxygen 1.6.1