ReSCue - Retrieval System for Curves
Main Page   Class Hierarchy   Compound List   File List   Compound Members  

angle.h

00001 #ifndef INCLUDE_UNITCIRCLEANGLE
00002 #define INCLUDE_UNITCIRCLEANGLE
00003 
00004 #include "rescuenumerics.h"
00005 #include <math.h>
00006 
00007 namespace rescue
00008 {
00009 
00024 template<class arithmetic>
00025 class unit_circle_angle
00026 {
00027 //private:
00028 public:
00029     arithmetic s;
00030     arithmetic c;
00031     enum {regular,two_pi} type;
00032 
00033 public:
00034 
00035     unit_circle_angle<arithmetic>() 
00036     {
00037         s = 0.0;
00038         c = 1.0;
00039         type = regular;
00040     }
00041 
00042     unit_circle_angle<arithmetic>(const unit_circle_angle<arithmetic>& uca) 
00043     {
00044         s = uca.s;
00045         c = uca.c;
00046         type = uca.type;
00047     }
00048 
00049     unit_circle_angle<arithmetic>(bool angle_two_pi) 
00050     {
00051         s = 0.0;
00052         c = 1.0;
00053         if (angle_two_pi)
00054             type = two_pi;
00055         else
00056             type = regular;
00057     }
00058 
00059     arithmetic sin() const
00060     {
00061         return s;
00062     }
00063 
00064     arithmetic cos() const
00065     {
00066         return c;
00067     }
00068 
00070     void bisect()
00071     {
00072         arithmetic s_new = sqrt((1-c)/2.0);
00073         arithmetic c_new = sqrt((1+c)/2.0); 
00074         int q = quadrant();
00075         switch (q) {
00076             case 0:
00077                 s = s_new;
00078                 c = c_new;
00079                 break;
00080             case 1:
00081                 s = s_new;
00082                 c = c_new;
00083                 break;
00084             case 2:
00085                 s = s_new;
00086                 c = -c_new;
00087                 break;
00088             case 3:
00089                 s = s_new;
00090                 c = -c_new;
00091                 break;
00092         }
00093 
00094         
00095     }
00096 
00097     inline bool operator==(const unit_circle_angle<arithmetic>& B) const
00098     {
00099         return (type==B.type &&  s==B.s && c==B.c);
00100     }
00101         
00102     inline unit_circle_angle<arithmetic>& operator=(const unit_circle_angle<arithmetic>& uca)
00103     {
00104         type = uca.type;
00105         c = uca.c;
00106         s = uca.s;
00107         return *this;
00108     }
00109         
00113     inline int quadrant() const
00114     {
00115         if (type==two_pi)
00116             return 3;
00117         // How nice: sign() is numerically exact and supported by LEDA/real !
00118         // Not so nice: for double there is no sign()-function by default.
00119         // That's why it is implemented in rescuenumerics.h / .cpp .
00120         if (sign(s)==0)
00121             if (sign(c)>=0)
00122                 return 0;
00123             else
00124                 return 2;
00125         else if (sign(s)>0)
00126             if (sign(c)==1)
00127                 return 0;
00128             else
00129                 return 1;
00130         else // sign(s)<0
00131             if (sign(c)<0)
00132                 return 2;
00133             else
00134                 return 3;
00135     }
00136 
00137 
00138     inline unit_circle_angle<arithmetic>& operator-=(const unit_circle_angle<arithmetic>& B)
00139     {
00140 
00141         // by definition, the resulting interval is regular
00142         type = regular;
00143 
00144         // use addition theorems for sin and cos:
00145         // cos(a-b) = cos(a)cos(b) + sin(a)sin(b)
00146         // sin(a-b) = sin(a)cos(b) - cos(a)sin(b)
00147         arithmetic c2 = c*B.c + s*B.s;
00148         arithmetic s2 = s*B.c - c*B.s;
00149         c = c2;
00150         s = s2;
00151         return *this;
00152         
00153     }
00154 
00155     inline unit_circle_angle<arithmetic>& operator+=(const unit_circle_angle<arithmetic>& B)
00156     {
00157         
00158         // by definition, the resulting interval is regular
00159         type = regular;        
00160 
00161         // use subtraction theorems for sin and cos:
00162         // cos(a+b) = cos(a)cos(b) - sin(a)sin(b)
00163         // sin(a+b) = sin(a)cos(b) + cos(a)sin(b)
00164         arithmetic c2 = c*B.c - s*B.s;
00165         arithmetic s2 = s*B.c + c*B.s;
00166         c = c2;
00167         s = s2;
00168         return *this;
00169 
00170     }
00171 
00172     inline unit_circle_angle<arithmetic> operator+(const unit_circle_angle<arithmetic>& B) const
00173     {
00174         unit_circle_angle<arithmetic> A;
00175         A = *this;
00176         A += B;
00177         return A;
00178     }
00179     
00180     inline unit_circle_angle<arithmetic> operator-(const unit_circle_angle<arithmetic>& B) const
00181     {
00182         unit_circle_angle<arithmetic> A;
00183         A = *this;
00184         A -= B;
00185         return A;
00186     }
00187     
00188     inline unit_circle_angle<arithmetic>(const arithmetic& sin1, const arithmetic& cos1)
00189     {
00190         type = regular;
00191         /*if (s>1.0)
00192         {
00193             s=1.0;
00194             c=0.0;
00195             return;
00196         }
00197         if (s<-1.0)
00198         {
00199             s=-1.0;
00200             c=0.0;
00201             return;
00202         }
00203         if (c>1.0)
00204         {
00205             s=0.0;
00206             c=1.0;
00207             return;
00208         }
00209         if (c<-1.0)
00210         {
00211             s=0.0;
00212             c=-1.0;
00213             return;
00214         }*/
00215         s = sin1;
00216         c = cos1;
00217     }
00218 
00219     inline bool operator<(const unit_circle_angle<arithmetic>& A) const
00220     {
00221         int q = quadrant();
00222         int qa = A.quadrant();
00223         if (q<qa)
00224             return true;
00225         if (q>qa)
00226             return false;
00227         
00228         // q==qa
00229         switch(q)
00230         {
00231         case 0:
00232             return s<A.s;
00233         case 1:
00234             return s>A.s;
00235         case 2:
00236             return s>A.s;
00237         case 3:
00238             return s<A.s;
00239 
00240         }
00241         return false;
00242     }
00243 
00244     inline bool operator<=(const unit_circle_angle<arithmetic>& A) const
00245     {
00246         return (*this)<A || (*this)==A;
00247     }
00248 
00249     inline bool between(const unit_circle_angle<arithmetic>& lower, const unit_circle_angle<arithmetic>& upper) const
00250     {
00251         if (lower<upper)
00252             // circular arc between lower und upper does not cover angle 0
00253             return lower<*this && *this<upper;
00254         else
00255             // circular arc between lower und upper covers angle 0
00256             return lower<*this || *this<upper;
00257     }
00258 
00263 #ifndef RESCUE__IGNORE_RAD
00264     double rad() const
00265     {
00266         double x = atan(s/c);
00267         int q = quadrant();
00268         switch(q)
00269         {
00270             case 0:
00271                 return x;
00272             case 1:
00273                 return x+PI;
00274             case 2:
00275                 return x+PI;
00276             case 3:
00277                 return x+2.0*PI;
00278         }       
00279         return x;
00280     }
00281 #endif
00282 
00283 };
00284 
00285 }
00286 
00287 #endif
ReSCue - Retrieval System for Curves
Universität Bonn, Institut für Informatik III, 2001