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

ltiArctanLUT.h

00001 /*
00002  * Copyright (C) 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-Lib: Image Processing and Computer Vision Library
00026  * file .......: ltiArctanLUT.h
00027  * authors ....: Pablo Alvarado
00028  * organization: LTI, RWTH Aachen
00029  * creation ...: 01.06.2003
00030  * revisions ..: $Id: ltiArctanLUT.h,v 1.4 2006/02/08 12:11:42 ltilib Exp $
00031  */
00032 
00033 #ifndef _LTI_ARCTAN_LUT_H_
00034 #define _LTI_ARCTAN_LUT_H_
00035 
00036 #include "ltiObject.h"
00037 #include "ltiMath.h"
00038 #include "ltiAssert.h"
00039 
00040 
00041 namespace lti {
00042   /**
00043    * Following class provides a mono-state object that contains a 1MB Look-up
00044    * Table to accelerate the computation of the arc-tangens.
00045    *
00046    * The provided functionality is similar to std::atan2(y,x) which computes
00047    * arctan(y/x) returning also the right angle quadrant.
00048    *
00049    * This method is used in time critical operations.  It is not appropriate
00050    * if you need exact computations of the arctan.  For that you can use the
00051    * standard method std::atan2, which is of course much more time expensive.
00052    *
00053    * As a mono-state class, only one instance of the LUT will be created.
00054    *
00055    * To use it, just create an instance and use the operator() as if you were
00056    * using std::atan2:
00057    *
00058    * \code
00059    * lti::arctanLUT myatan2;
00060    *
00061    * float angle = myatan2(20,10);
00062    * \endcode
00063    *
00064    * The returned angle will be always possitive 0 <= angle < 2*Pi (in radians)
00065    */
00066   class arctanLUT : public object {
00067   public:
00068     /**
00069      * Construct the class
00070      * Here, the LUT will be build just once (if not already done). 
00071      * The first time you construct this class, it will take about 0.15 seconds
00072      * to build the LUT.
00073      */
00074     arctanLUT();
00075 
00076     /**
00077      * Compute the arctan(dx/dy).
00078      *
00079      * It is a little bit slower than the other atan2() method, as it needs
00080      * to scale the input values into the range -255 and 255.  If you need
00081      * a extremely efficient computation, try the other atan2() method.
00082      *
00083      * @param dy y component.
00084      * @param dx x component.
00085      * @return arctan(dy/dx) in radians (always possitive between 0 and 2*Pi)
00086      */
00087     inline float operator() (const float dy,const float dx) const;
00088 
00089     /**
00090      * Compute the arctan(dx/dy).
00091      *
00092      * It is a little bit slower than the other atan2() method, as it needs
00093      * to scale the input values into the range -255 and 255.  If you need
00094      * a extremely efficient computation, try the other atan2() method.
00095      *
00096      * @param dy y component.
00097      * @param dx x component.
00098      * @return arctan(dy/dx) in radians (always possitive between 0 and 2*Pi)
00099      */
00100     inline float operator() (const double& dy,const double& dx) const;
00101 
00102 
00103     /**
00104      * Compute the arctan(dx/dy).
00105      *
00106      * This is the fastest method, but the value range of the input variables
00107      * is restricted.
00108      *
00109      * @param dy y component must be between -255 and 255
00110      * @param dx x component must be between -255 and 255
00111      * @return arctan(dy/dx) in radians (always possitive between 0 and 2*Pi)
00112      */
00113     inline float operator() (const int dy,const int dx) const;
00114 
00115   protected:
00116     /**
00117      * construct a atan2 LUT.  It will assume that the difference values
00118      * of the gradients will be always between -255 and 255.  The 1MB Memory
00119      * required should not be a problem in modern PCs anymore!.
00120      */
00121     static void constructArcTanLUT();
00122 
00123     /**
00124      * Type required to create the LUT as a const structure
00125      */
00126     typedef const float* cfloatptr;
00127     
00128     /**
00129      * the arctanLUT with floats.  After calling constructArcTanLUT() the
00130      * valid index range for both dimensions will be between -255 and 255.
00131      * The  arctanLUT[dy][dx] is equivalent to atan2(dy,dx) (but much faster).
00132      * The entries will always be between 0 and 2*Pi.
00133      */
00134     static const cfloatptr* atanLUT;
00135   };
00136 
00137   // implementation of inline methods
00138   inline float arctanLUT::operator() (const double& dy,const double& dx) const {
00139     return this->operator()(static_cast<float>(dy),static_cast<float>(dx));
00140   }
00141 
00142   inline float arctanLUT::operator() (const float dy,const float dx) const {
00143     if (dy < 0.0f) {
00144       if (dx < 0.0f) {
00145         if (dx<dy) {
00146           return atanLUT[iround(-255.0f*dy/dx)][-255];
00147         } else {
00148           return atanLUT[-255][iround(-255.0f*dx/dy)];
00149         }
00150       } else {
00151         // dy < 0 and dx >= 0
00152         if (dx > -dy) {
00153           return atanLUT[iround(dy*255.0f/dx)][255];
00154         } else {
00155           return atanLUT[-255][iround(-255.0f*dx/dy)];
00156         }
00157       }
00158     } else {
00159       if (dx < 0.0f) {
00160         // dy >= 0 and dx < 0
00161         if (-dx > dy) {
00162           return atanLUT[iround(-dy*255.0f/dx)][-255];
00163         } else {
00164           return atanLUT[255][iround(dx*255.0f/dy)];
00165         }
00166       } else {
00167         // dy >= 0 and dx >= 0
00168         if (dx>dy) {
00169           return atanLUT[iround(dy*255.0f/dx)][255];
00170         } else if (dx<dy) {
00171           return atanLUT[255][iround(dx*255.0f/dy)];          
00172         } else if (dx != 0.0f) {
00173           return atanLUT[255][255];
00174         }
00175       } 
00176     }
00177     return atanLUT[0][0];    
00178   }
00179 
00180   inline float arctanLUT::operator() (const int dy,const int dx) const {
00181     // check in debug modus that range is ok
00182     assert((dy>-256) && (dy<256) && (dx>-256) && (dx<256));
00183     
00184     // just return the value
00185     return atanLUT[dy][dx];
00186   };
00187 
00188 
00189 }
00190 
00191 #endif

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