CVR-Lib last update 20 Sep 2009

cvrArctanLUT.h

Go to the documentation of this file.
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   cvrArctanLUT.h
00044  *         Contains the arctan lookup table.
00045  * \author Pablo Alvarado
00046  * \date   01.06.2003
00047  *
00048  * revisions ..: $Id: cvrArctanLUT.h,v 1.4 2006/09/22 11:28:38 doerfler Exp $
00049  */
00050 
00051 #ifndef _CVR_ARCTAN_LUT_H_
00052 #define _CVR_ARCTAN_LUT_H_
00053 
00054 #include "cvrObject.h"
00055 #include "cvrRound.h"
00056 #include "cvrMath.h"
00057 #include "cvrAssert.h"
00058 
00059 
00060 namespace cvr {
00061   /**
00062    * Following class provides a mono-state object that contains a 1MB Look-up
00063    * Table to accelerate the computation of the arc-tangens.
00064    *
00065    * The provided functionality is similar to std::atan2(y,x) which computes
00066    * arctan(y/x) returning also the right angle quadrant.
00067    *
00068    * This method is used in time critical operations.  It is not appropriate
00069    * if you need exact computations of the arctan.  For that you can use the
00070    * standard method std::atan2, which is of course much more time expensive.
00071    *
00072    * As a mono-state class, only one instance of the LUT will be created.
00073    *
00074    * To use it, just create an instance and use the operator() as if you were
00075    * using std::atan2:
00076    *
00077    * \code
00078    * cvr::arctanLUT myatan2;
00079    *
00080    * float angle = myatan2(20,10);
00081    * \endcode
00082    *
00083    * The returned angle will be always possitive 0 <= angle < 2*Pi (in radians)
00084    *
00085    * @ingroup gMath
00086    */
00087   class arctanLUT : public object {
00088   public:
00089     /**
00090      * Construct the class
00091      * Here, the LUT will be build just once (if not already done).
00092      * The first time you construct this class, it will take about 0.15 seconds
00093      * to build the LUT.
00094      */
00095     arctanLUT();
00096 
00097     /**
00098      * Compute the arctan(dx/dy).
00099      *
00100      * It is a little bit slower than the other atan2() method, as it needs
00101      * to scale the input values into the range -255 and 255.  If you need
00102      * a extremely efficient computation, try the other atan2() method.
00103      *
00104      * @param dy y component.
00105      * @param dx x component.
00106      * @return arctan(dy/dx) in radians (always possitive between 0 and 2*Pi)
00107      */
00108     inline float operator() (const float dy,const float dx) const;
00109 
00110     /**
00111      * Compute the arctan(dx/dy).
00112      *
00113      * It is a little bit slower than the other atan2() method, as it needs
00114      * to scale the input values into the range -255 and 255.  If you need
00115      * a extremely efficient computation, try the other atan2() method.
00116      *
00117      * @param dy y component.
00118      * @param dx x component.
00119      * @return arctan(dy/dx) in radians (always possitive between 0 and 2*Pi)
00120      */
00121     inline float operator() (const double& dy,const double& dx) const;
00122 
00123 
00124     /**
00125      * Compute the arctan(dx/dy).
00126      *
00127      * This is the fastest method, but the value range of the input variables
00128      * is restricted.
00129      *
00130      * @param dy y component must be between -255 and 255
00131      * @param dx x component must be between -255 and 255
00132      * @return arctan(dy/dx) in radians (always possitive between 0 and 2*Pi)
00133      */
00134     inline float operator() (const int dy,const int dx) const;
00135 
00136     /**
00137      * Returns the name of this class
00138      */
00139     virtual const std::string& name() const;
00140 
00141     /**
00142      * Returns a pointer to a clone of the parameters.
00143      */
00144     virtual arctanLUT* clone() const;
00145 
00146     /**
00147      * Returns a pointer to a clone of the parameters.
00148      */
00149     virtual arctanLUT* newInstance() const;
00150 
00151   protected:
00152     /**
00153      * Construct a atan2 LUT.  It will assume that the difference values
00154      * of the gradients will be always between -255 and 255.  The 1MB Memory
00155      * required should not be a problem in modern PCs anymore!.
00156      */
00157     static void constructArcTanLUT();
00158 
00159     /**
00160      * Type required to create the LUT as a const structure
00161      */
00162     typedef const float* cfloatptr_;
00163 
00164     /**
00165      * The arctanLUT with floats.  After calling constructArcTanLUT() the
00166      * valid index range for both dimensions will be between -255 and 255.
00167      * The  arctanLUT[dy][dx] is equivalent to atan2(dy,dx) (but much faster).
00168      * The entries will always be between 0 and 2*Pi.
00169      */
00170     static const cfloatptr_* atanLUT_;
00171   };
00172 
00173   // implementation of inline methods
00174   inline float arctanLUT::operator() (const double& dy,
00175               const double& dx) const {
00176     return this->operator()(static_cast<float>(dy),static_cast<float>(dx));
00177   }
00178 
00179   inline float arctanLUT::operator() (const float dy,const float dx) const {
00180     if (dy < 0.0f) {
00181       if (dx < 0.0f) {
00182         if (dx<dy) {
00183           return atanLUT_[iround(-255.0f*dy/dx)][-255];
00184         } else {
00185           return atanLUT_[-255][iround(-255.0f*dx/dy)];
00186         }
00187       } else {
00188         // dy < 0 and dx >= 0
00189         if (dx > -dy) {
00190           return atanLUT_[iround(dy*255.0f/dx)][255];
00191         } else {
00192           return atanLUT_[-255][iround(-255.0f*dx/dy)];
00193         }
00194       }
00195     } else {
00196       if (dx < 0.0f) {
00197         // dy >= 0 and dx < 0
00198         if (-dx > dy) {
00199           return atanLUT_[iround(-dy*255.0f/dx)][-255];
00200         } else {
00201           return atanLUT_[255][iround(dx*255.0f/dy)];
00202         }
00203       } else {
00204         // dy >= 0 and dx >= 0
00205         if (dx>dy) {
00206           return atanLUT_[iround(dy*255.0f/dx)][255];
00207         } else if (dx<dy) {
00208           return atanLUT_[255][iround(dx*255.0f/dy)];
00209         } else if (!closeToZero(dx)) {
00210           return atanLUT_[255][255];
00211         }
00212       }
00213     }
00214     return atanLUT_[0][0];
00215   }
00216 
00217   inline float arctanLUT::operator() (const int dy,const int dx) const {
00218     // check in debug modus that range is ok
00219     assert((dy>-256) && (dy<256) && (dx>-256) && (dx<256));
00220 
00221     // just return the value
00222     return atanLUT_[dy][dx];
00223   }
00224 
00225 
00226 }
00227 
00228 #endif

Generated on Sun Sep 20 22:07:58 2009 for CVR-Lib by Doxygen 1.5.8