BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/rational_rotation.h
Go to the documentation of this file.
00001 // Copyright (c) 1999  Utrecht University (The Netherlands),
00002 // ETH Zurich (Switzerland), Freie Universitaet Berlin (Germany),
00003 // INRIA Sophia-Antipolis (France), Martin-Luther-University Halle-Wittenberg
00004 // (Germany), Max-Planck-Institute Saarbruecken (Germany), RISC Linz (Austria),
00005 // and Tel-Aviv University (Israel).  All rights reserved.
00006 //
00007 // This file is part of CGAL (www.cgal.org); you can redistribute it and/or
00008 // modify it under the terms of the GNU Lesser General Public License as
00009 // published by the Free Software Foundation; version 2.1 of the License.
00010 // See the file LICENSE.LGPL distributed with CGAL.
00011 //
00012 // Licensees holding a valid commercial license may use this file in
00013 // accordance with the commercial license agreement provided with the software.
00014 //
00015 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00016 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00017 //
00018 // $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Kernel_23/include/CGAL/rational_rotation.h $
00019 // $Id: rational_rotation.h 35581 2006-12-17 22:28:35Z afabri $
00020 // 
00021 //
00022 // Author(s)     : Stefan Schirra
00023  
00024 
00025 #ifndef CGAL_RATIONAL_ROTATION_H
00026 #define CGAL_RATIONAL_ROTATION_H
00027 
00028 #include <algorithm>
00029 
00030 CGAL_BEGIN_NAMESPACE
00031 
00032 template < class NT >
00033 void
00034 rational_rotation_approximation( const NT &  dirx,     // dir.x()
00035                                  const NT &  diry,     // dir.y()
00036                                        NT &  sin_num,  // return
00037                                        NT &  cos_num,  // return
00038                                        NT &  denom,    // return
00039                                  const NT &  eps_num,  // quality_bound
00040                                  const NT &  eps_den )
00041 {
00042 
00043   const NT& n   = eps_num;
00044   const NT& d   = eps_den;
00045   const NT  NT0 = NT(0)  ;
00046   const NT  NT1 = NT(1)  ;
00047   CGAL_kernel_precondition( (dirx != NT0) ||  (diry != NT0));
00048   CGAL_kernel_precondition( n > NT0 );
00049   CGAL_kernel_precondition( d > NT0 );
00050   NT & sin = sin_num;
00051   NT & cos = cos_num;
00052   NT & den = denom;
00053   NT   dx = CGAL_NTS abs(dirx);
00054   NT   dy = CGAL_NTS abs(diry);
00055   NT   sq_hypotenuse = dx*dx + dy*dy;
00056   NT   common_part;
00057   NT   diff_part;
00058   NT   rhs;
00059   bool lower_ok;
00060   bool upper_ok;
00061 
00062   if (dy > dx)
00063   {
00064      std::swap (dx,dy);
00065   }
00066   // approximate sin = dy / sqrt(sq_hypotenuse)
00067   // if ( dy / sqrt(sq_hypotenuse) < n/d )
00068   if (dy * dy * d * d < sq_hypotenuse * n * n)
00069   {
00070       cos = NT1;
00071       sin = NT0;
00072       den = NT1;
00073   }
00074   else
00075   {
00076       NT  p;
00077       NT  q;
00078       NT  p0 = NT0;
00079       NT  q0 = NT1;
00080       NT  p1 = NT1;
00081       NT  q1 = NT1;
00082 
00083       for(;;)
00084       {
00085           p = p0 + p1;
00086           q = q0 + q1;
00087           sin = NT(2)*p*q;
00088           den = p*p + q*q;
00089 
00090       // sanity check for approximation
00091       //        sin/den < dy/sqrt(hypotenuse) + n/d
00092       //    &&  sin/den > dy/sqrt(hypotenuse) - n/d
00093       // ===    sin/den - n/d  <   dy/sqrt(sq_hypotenuse)
00094       //    &&  sin/den + n/d  >   dy/sqrt(sq_hypotenuse)
00095       // ===    (sin^2 d^2 + n^2 den^2)sq_hypotenuse - 2... < dy^2 d^2 den^2
00096       //    &&  (sin^2 d^2 + n^2 den^2)sq_hypotenuse + 2... > dy^2 d^2 den^2
00097 
00098           common_part = (sin*sin*d*d + n*n*den*den)*sq_hypotenuse;
00099           diff_part   = NT(2)*n*sin*d*den*sq_hypotenuse;
00100           rhs         = dy*dy*d*d*den*den;
00101 
00102           upper_ok    = (common_part - diff_part < rhs);
00103           lower_ok    = (common_part + diff_part > rhs);
00104 
00105           if ( lower_ok && upper_ok )
00106           {
00107              // if ( (p*p)%2 + (q*q)%2 > NT1)
00108              // {
00109              //     sin = p*q;
00110              //     cos = (q*q - p*p)/2;    // exact division
00111              //     den = (p*p + q*q)/2;    // exact division
00112              // }
00113              // else
00114              // {
00115                     cos = q*q - p*p;
00116              // }
00117 
00118              break;
00119           }
00120           else
00121           {
00122               // if ( dy/sqrt(sq_hypotenuse) < sin/den )
00123               if ( dy*dy*den*den < sin*sin*sq_hypotenuse )
00124               {
00125                   p1 = p;
00126                   q1 = q;
00127               }
00128               else
00129               {
00130                   p0 = p;
00131                   q0 = q;
00132               }
00133           }
00134       } // for(;;)
00135   }
00136   dx = dirx;
00137   dy = diry;
00138 
00139   if (CGAL_NTS abs(dy) > CGAL_NTS abs(dx) ) { std::swap (sin,cos); }
00140 
00141   if (dx < NT0) { cos = - cos; }
00142 
00143   if (dy < NT0) { sin = - sin; }
00144 
00145   sin_num = sin;
00146   cos_num = cos;
00147   denom   = den;
00148 }
00149 
00150 
00151 template < class NT >
00152 void
00153 rational_rotation_approximation( const double& angle,
00154                                             NT &  sin_num,  // return
00155                                             NT &  cos_num,  // return
00156                                             NT &  denom,    // return
00157                                       const NT &  eps_num,  // quality_bound
00158                                       const NT &  eps_den )
00159 {
00160 
00161   const NT& n   = eps_num;
00162   const NT& d   = eps_den;
00163   const NT  NT0 = NT(0)  ;
00164   const NT  NT1 = NT(1)  ;
00165   CGAL_kernel_precondition( n > NT0 );
00166   CGAL_kernel_precondition( d > NT0 );
00167   NT& isin = sin_num;
00168   NT& icos = cos_num;
00169   NT& iden = denom;
00170   double dsin = std::sin(angle);
00171   double dcos = std::cos(angle);
00172   double dn = CGAL::to_double(n);
00173   double dd = CGAL::to_double(d);
00174   double eps = dn / dd;
00175   dsin = CGAL_NTS abs( dsin);
00176   dcos = CGAL_NTS abs( dcos);
00177   NT   common_part;
00178   NT   diff_part;
00179   NT   os;
00180   bool lower_ok;
00181   bool upper_ok;
00182   bool swapped = false;
00183 
00184   if (dsin > dcos)
00185   {
00186      swapped = true;
00187      std::swap (dsin,dcos);
00188   }
00189   if ( dsin < eps )
00190   {
00191       icos = NT1;
00192       isin = NT0;
00193       iden = NT1;
00194   }
00195   else
00196   {
00197       NT  p;
00198       NT  q;
00199       NT  p0 = NT0;
00200       NT  q0 = NT1;
00201       NT  p1 = NT1;
00202       NT  q1 = NT1;
00203 
00204       for(;;)
00205       {
00206           p = p0 + p1;
00207           q = q0 + q1;
00208           isin = NT(2)*p*q;
00209           iden = p*p + q*q;
00210 
00211           // XXX sanity check for approximation
00212           //        sin/den < dsin + n/d
00213           //    &&  sin/den > dsin - n/d
00214           //        sin < dsin * den + n/d * den
00215           //    &&  sin > dsin * den - n/d * den
00216           os          = CGAL::to_double(isin);
00217           diff_part   = eps  * CGAL::to_double(iden);
00218           common_part = dsin * CGAL::to_double(iden);
00219 
00220           upper_ok    = (common_part - diff_part < os);
00221           lower_ok    = (os < common_part + diff_part);
00222 
00223           if ( lower_ok && upper_ok )
00224           {
00225              // if ( (p*p)%2 + (q*q)%2 > NT1)
00226              // {
00227              //     isin = p*q;
00228              //     icos = (q*q - p*p)/2;    // exact division
00229              //     iden = (p*p + q*q)/2;    // exact division
00230              // }
00231              // else
00232              // {
00233                     icos = q*q - p*p;
00234              // }
00235 
00236              break;
00237           }
00238           else
00239           {
00240               // XXX if ( dsin < sin/den )
00241               if ( dsin * CGAL::to_double(iden) < CGAL::to_double(isin) )
00242               {
00243                   p1 = p;
00244                   q1 = q;
00245               }
00246               else
00247               {
00248                   p0 = p;
00249                   q0 = q;
00250               }
00251           }
00252       } // for(;;)
00253   }
00254 
00255   if ( swapped ) { std::swap (isin,icos); }
00256 
00257   dsin = std::sin( angle);
00258   dcos = std::cos( angle);
00259   if (dcos < 0.0) { icos = - icos; }
00260   if (dsin < 0.0) { isin = - isin; }
00261 
00262   sin_num = isin;
00263   cos_num = icos;
00264   denom   = iden;
00265 }
00266 
00267 CGAL_END_NAMESPACE
00268 
00269 #endif // CGAL_RATIONAL_ROTATION_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines