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 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