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

ltiBox.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 .......: ltiBox.h
00027  * authors ....: Pablo Alvarado
00028  * organization: LTI, RWTH Aachen
00029  * creation ...: 01.11.2002
00030  * revisions ..: $Id: ltiBox.h,v 1.2 2006/02/07 18:06:50 ltilib Exp $
00031  */
00032 
00033 #ifndef LTI_BOX_H
00034 #define LTI_BOX_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 ltiBox.h
00044  *
00045  * This file contains the definitions of the box and tbox 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 box's side and the
00053    * inverse transformation.
00054    * 
00055    * For integer types it assumes the box lies on a discrete grid with
00056    * grid elements of size 1x1x1, which means that the size of a side
00057    * defined by 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 box lies on a real valued 2D space.
00061    */
00062   template <class T>
00063   class boxSide {
00064   public:
00065     /**
00066      * return the size of a box'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 boxSide<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 boxSide<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    * Class to describe a 3D box aligned with the coordinate system.  It is
00120    * specified through two points with the minimum and maximum coordinates.
00121    *
00122    * @ingroup gGeomData
00123    */
00124   template <class T,class S=boxSide<T> >
00125   class tbox {
00126   public:
00127     /**
00128      * default constructor
00129      */
00130     tbox()
00131       : min(tpoint3D<T>(0,0,0)),max(tpoint3D<T>(0,0,0)) {
00132     };
00133 
00134     /**
00135      * constructor
00136      */
00137     tbox(const tpoint3D<T>& p1,const tpoint3D<T>& p2)
00138       : min(p1), max(p2) {
00139     };
00140 
00141     /**
00142      * constructor
00143      */
00144     tbox(const T& x1,const T& y1,const T& z1,
00145          const T& x2,const T& y2,const T& z2)
00146       : min(tpoint3D<T>(x1,y1,z1)),max(tpoint3D<T>(x2,y2,z2)) {
00147     };
00148 
00149     /**
00150      * construct a cube with the given side size.
00151      *
00152      * If the size is even and T is an integer type, the box
00153      * will be created from -|_size/2_| to size + |_size/2_| in both
00154      * coordinates x and y.
00155      */
00156     tbox(const T& size) {
00157       T low,high;
00158       S::invSize(size,low,high);
00159       min.set(low,low,low);
00160       max.set(high,high,high);
00161     };
00162 
00163     /**
00164      * copy constructor
00165      */
00166     tbox(const tbox<T>& other)
00167       : min(other.min),max(other.max) {
00168     };
00169 
00170     /**
00171      * @name Dimensions and location
00172      */
00173     //@{
00174 
00175     /**
00176      * resize tbox<T> with new dimensions, but keep its center
00177      */
00178     void resize(const tpoint3D<T>& dim) {
00179       tpoint3D<T> cen = getCenter();
00180       S::invSize(dim.x,min.x,max.x);
00181       S::invSize(dim.y,min.y,max.y);
00182       S::invSize(dim.z,min.z,max.z);
00183       min.add(cen);
00184       max.add(cen);
00185     };
00186 
00187     /**
00188      * resize tbox<T> with new dimensions, but keep its center
00189      */
00190     void resize(const T& x, const T& y, const T& z) {
00191       tpoint3D<T> cen = getCenter();
00192 
00193       S::invSize(x,min.x,max.x);
00194       S::invSize(y,min.y,max.y);
00195       S::invSize(z,min.z,max.z);
00196 
00197       min.add(cen);
00198       max.add(cen);
00199     };
00200 
00201     /**
00202      * Get dimensions of tbox<T>.  If one coordinate of the two
00203      * points coincide and the box contains fixed point typed
00204      * points, the returned dimension is one.  For floating point
00205      * types this case will return 0.
00206      *
00207      * \warning Note that the result of this method depends on the type T
00208      *
00209      * For integer types it will be assumed that the box lies on
00210      * a discrete grid with grid elements of size 1x1, and that is not
00211      * the box itself what is described but the number of grid
00212      * elements.  This means that the size of a side defined by two
00213      * scalar values x1 and x2 (x2>x1) is x2-x1+1.  This is useful for 
00214      * example when dealing with rectangular regions of images.
00215      *
00216      * For floating point values the size is just x2-x1, because of
00217      * the assumtion that the box lies on a real valued 2D space.
00218      */
00219     tpoint3D<T> getDimensions() const {
00220       return tpoint3D<T>(S::size(min.x,max.x),
00221                          S::size(min.y,max.y),
00222                          S::size(min.z,max.z));
00223     };
00224 
00225     /**
00226      * Get the volume of this box. This value is always positive,
00227      * regardless of the position of the minimum and maximum
00228      * corners. A box whose corners coincide has an area of 1 for
00229      * fixed point types or 0 for floating point ones.
00230      *
00231      * \warning Note that the result of this method depends on the type T
00232      *
00233      * For integer types it will be assumed that the box lies on
00234      * a discrete grid with grid elements of size 1x1, and that is not
00235      * the box itself what is described but the index of grid
00236      * elements.  This means that the size of a side defined by two
00237      * scalar values x1 and x2 (x2>x1) is x2-x1+1.  This is useful for 
00238      * example when dealing with rectangular regions of images.
00239      *
00240      * For floating point values the size is just x2-x1, because of
00241      * the assumtion that the box lies on a real valued 2D space.
00242      */
00243     T getVolume() const {
00244       return abs(S::size(min.x,max.x)*
00245                  S::size(min.y,max.y)*
00246                  S::size(min.z,max.z));
00247     };
00248 
00249     /**
00250      * Get center of tbox<T>
00251      */
00252     tpoint3D<T> getCenter() const {
00253       return tpoint3D<T>((max.x+min.x)/2,(max.y+min.y)/2,(max.z+min.z)/2);
00254     };
00255 
00256     /**
00257      * Set the center of this box.
00258      */
00259     void setCenter(tpoint3D<T> center) {
00260       tpoint3D<T> dim(abs(max.x-min.x),abs(max.y-min.y),abs(max.z-min.z));
00261       min.set(center.x - dim.x/2,center.y - dim.y/2,center.z - dim.z/2);
00262       max.set(min.x + dim.x, min.y + dim.y, min.z + dim.z);
00263     }
00264 
00265     /**
00266      * Ensure consistency of minimum and maximum corners.  A tbox<T>
00267      * is called "consistent" if the minimum tpoint3D<T> has lower
00268      * coordinate-values than the maximum tpoint3D<T>.
00269      */
00270     void ensureConsistency() {
00271       tbox<T> t(*this);
00272 
00273       if (t.min.x > t.max.x) {
00274         min.x = t.max.x;
00275         max.x = t.min.x;
00276       }
00277 
00278       if (t.min.y > t.max.y) {
00279         min.y = t.max.y;
00280         max.y = t.min.y;
00281       }
00282 
00283       if (t.min.z > t.max.z) {
00284         min.z = t.max.z;
00285         max.z = t.min.z;
00286       }
00287     };
00288 
00289     /**
00290      * Check for consistent tbox<T>.
00291      * @return True if minimum and maximum corners are correct
00292      */
00293     bool isConsistent() const {
00294       return !( (min.x > max.x) || (min.y > max.y) || (min.z > max.z) );
00295     };
00296 
00297     /**
00298      * Shift tbox<T> by delta
00299      */
00300     void shift(const tpoint3D<T>& delta) {
00301       min.add(delta);
00302       max.add(delta);
00303     };
00304     //@}
00305 
00306     /**
00307      * @name Simple operations
00308      */
00309     //@{
00310 
00311     /**
00312      * Check if tpoint3D<T> p is inside the tbox<T>. (border included!)
00313      */
00314     bool isInside(const tpoint3D<T>& p) const {
00315       return ( (p.x>=min.x) && (p.x<=max.x) &&
00316                (p.y>=min.y) && (p.y<=max.y) &&
00317                (p.z>=min.z) && (p.z<=max.z) );
00318     };
00319 
00320     /**
00321      * Check if the given coordinates are inside the tbox<T>. 
00322      * (border included!)
00323      */
00324     bool isInside(const T& x, const T& y, const T& z) const {
00325       return ( (x>=min.x) && (x<=max.x) &&
00326                (y>=min.y) && (y<=max.y) &&
00327                (z>=min.z) && (z<=max.z) );
00328     };
00329 
00330     //@}
00331 
00332 
00333     /**
00334      * @name Duplication
00335      */
00336     //@{
00337 
00338     /**
00339      * copy member
00340      */
00341     tbox<T>& copy(const tbox<T>& other) {
00342       min.copy(other.min);
00343       max.copy(other.max);
00344       return (*this);
00345     };
00346 
00347     /**
00348      * cast from a box of another type
00349      */
00350     template <class U,class SU>
00351     tbox<T>& castFrom(const tbox<U,SU>& other) {
00352 
00353       min.castFrom(other.min);
00354       max.castFrom(other.max);
00355 
00356       return (*this);
00357     };
00358 
00359     /**
00360      * alias for copy
00361      */
00362     tbox<T>& operator=(const tbox<T>& other) {
00363       return (copy(other));
00364     };
00365 
00366     //@}
00367 
00368     /**
00369      * @name Comparison
00370      */
00371     //@{
00372 
00373     /**
00374      * test for equality
00375      */
00376     bool operator==(const tbox<T>& other) const {
00377       return ( (other.min == min) &&
00378                (other.max == max) );
00379     };
00380 
00381     /**
00382      * test for inequality
00383      */
00384     bool operator!=(const tbox<T>& other) const {
00385       return ( (other.min != min) ||
00386                (other.max != max) );
00387     };
00388 
00389     //@}
00390 
00391     /**
00392      * @name Geometrical combination
00393      */
00394     //@{
00395 
00396     /**
00397      * Intersection of this tbox with tRect
00398      *
00399      * (the largest box which is contained both inside this
00400      * box and inside tRect).
00401      *
00402      * The result will be left in this instance. If the boxs do
00403      * not intersect, the resul will be inconsistent, so you should
00404      * call isConsistent() to check for this case unless you know for
00405      * sure that it cannot occur.
00406      *
00407      * @return a reference to this (modified) instance.
00408      */
00409     tbox<T>& intersect(const tbox<T>& tRect) {
00410       if (tRect.min.x > min.x) {
00411         min.x = tRect.min.x;
00412       }
00413       if (tRect.min.y > min.y) {
00414         min.y = tRect.min.y;
00415       }
00416       if (tRect.min.z > min.z) {
00417         min.z = tRect.min.z;
00418       }
00419 
00420       if (tRect.max.x < max.x) {
00421         max.x = tRect.max.x;
00422       }
00423       if (tRect.max.y < max.y) {
00424         max.y = tRect.max.y;
00425       }
00426       if (tRect.max.z < max.z) {
00427         max.z = tRect.max.z;
00428       }
00429       return (*this);
00430     };
00431 
00432 
00433     /**
00434      * Check whether this box overlaps with the given box.
00435      */
00436     bool overlaps(const tbox<T>& tRect) const {
00437       tbox<T> rect(*this);
00438       rect.intersect(tRect);
00439       return rect.isConsistent();
00440     };
00441 
00442     /**
00443      * tbox = intersection of tbox with tRect.
00444      * (alias for intersect)
00445      */
00446     tbox<T>& operator&=(const tbox<T>& tRect) {
00447       return intersect(tRect);
00448     };
00449 
00450     /**
00451      * new tbox = intersection of tbox with tRect
00452      */
00453     tbox<T> operator&(const tbox<T>& tRect) {
00454       tbox<T> tempRect(*this);
00455       return tempRect.intersect(tRect);
00456     };
00457     
00458     /**
00459      * Union of this tbox with tRect
00460      * (the smallest box containing both this tbox and tRect)
00461      * The result will be left in this instance.
00462      * @return a reference to this (modified) instance.
00463      */
00464     tbox<T>& join(const tbox<T>& tRect) {
00465       if (tRect.min.x < min.x) {
00466         min.x = tRect.min.x;
00467       }
00468       if (tRect.min.y < min.y) {
00469         min.y = tRect.min.y;
00470       }
00471       if (tRect.min.z < min.z) {
00472         min.z = tRect.min.z;
00473       }
00474 
00475       if (tRect.max.x > max.x) {
00476         max.x = tRect.max.x;
00477       }
00478       if (tRect.max.y > max.y) {
00479         max.y = tRect.max.y;
00480       }
00481       if (tRect.max.z > max.z) {
00482         max.z = tRect.max.z;
00483       }
00484       return (*this);
00485     };
00486 
00487     /**
00488      * tbox = union of this tbox with tRect
00489      * (alias for join)
00490      */
00491     tbox<T>& operator|=(const tbox<T>& tRect) {
00492       return join(tRect);
00493     };
00494 
00495     /**
00496      * new tbox = union of this tbox  with tRect
00497      */
00498     tbox<T> operator|(const tbox<T>& tRect) {
00499       tbox<T> tempRect(*this);
00500       return tempRect.join(tRect);
00501     };
00502 
00503     //@}
00504 
00505     /**
00506      * minimum tpoint3D<T>
00507      */
00508     tpoint3D<T> min;
00509 
00510     /**
00511      * maximum tpoint3D<T>
00512      */
00513     tpoint3D<T> max;
00514 
00515   };
00516 
00517   /**
00518    * A box with integer coordinates
00519    */
00520   typedef tbox<int> box;
00521 
00522   /**
00523    * read the box from the given ioHandler.  The complete flag indicates
00524    * if the enclosing begin and end should be also be readed
00525    *
00526    * @ingroup gStorable
00527    */
00528   template<class T,class S>
00529   bool read(ioHandler& handler,tbox<T,S>& p,const bool complete=true) {
00530     bool b;
00531 
00532     if (complete) {
00533       handler.readBegin();
00534     }
00535 
00536     read(handler,p.min);
00537     handler.readDataSeparator();
00538     b = read(handler,p.max);
00539 
00540     if (complete) {
00541       b = handler.readEnd();
00542     }
00543 
00544     return b;
00545   };
00546 
00547   /**
00548    * write the box in the given ioHandler.  The complete flag indicates
00549    * if the enclosing begin and end should be also be written or not
00550    *
00551    * @ingroup gStorable
00552    */
00553   template <class T,class S>
00554   bool write(ioHandler& handler,const tbox<T,S>& p,
00555              const bool complete=true) {
00556     bool b;
00557 
00558     if (complete) {
00559       handler.writeBegin();
00560     }
00561     write(handler,p.min);
00562     handler.writeDataSeparator();
00563     b = write(handler,p.max);
00564 
00565     if (complete) {
00566       b = handler.writeEnd();
00567     }
00568 
00569     return b;
00570   };
00571 }
00572 
00573 namespace std {
00574 
00575   //inline ostream& operator<<(ostream& s,const lti::point& p);
00576   template <class T,class S>
00577   inline ostream& operator<<(ostream& s,const lti::tbox<T,S>& p) {
00578     s << "(" << p.min << ","
00579       << p.max << ")";
00580     return s;
00581   };
00582 
00583   //inline ostream& operator>>(istream& s,const lti::point& p);
00584   template <class T,class S>
00585   inline istream& operator>>(istream& s,lti::tbox<T,S>& p) {
00586     char c;
00587     lti::tpoint3D<T> min,max;
00588     s >> c
00589       >> min >> c
00590       >> max >> c;
00591     p.min = min;
00592     p.max = max;
00593 
00594     return s;
00595   };
00596 }
00597 
00598 #endif

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