core/vgl/vgl_ellipse_scan_iterator.txx

Go to the documentation of this file.
00001 // This is core/vgl/vgl_ellipse_scan_iterator.txx
00002 #ifndef vgl_ellipse_scan_iterator_txx_
00003 #define vgl_ellipse_scan_iterator_txx_
00004 
00005 #include "vgl_ellipse_scan_iterator.h"
00006 #include <vcl_cmath.h>
00007 
00008 // Helper functions
00009 namespace {
00010   template <class T> inline T my_max( T x, T y ) { return x<y ? y : x; }
00011 }
00012 
00013 template <class T>
00014 vgl_ellipse_scan_iterator<T>::vgl_ellipse_scan_iterator( T xc, T yc, T rx, T ry, T theta )
00015   : xc_( xc ),
00016     yc_( yc ),
00017     rx_( rx*rx ),
00018     ry_( ry*ry ),
00019     theta_( theta ),
00020     y_( 0 ),
00021     min_y_( 0 )
00022 {
00023 }
00024 
00025 template <class T>
00026 vgl_ellipse_scan_iterator<T>::~vgl_ellipse_scan_iterator()
00027 {
00028 }
00029 
00030 template <class T>
00031 void vgl_ellipse_scan_iterator<T>::reset()
00032 {
00033   // The max value.
00034   T y0;
00035   if ( vcl_sin( theta_ ) == 0.0 ) {
00036     y0 = vcl_sqrt(ry_);
00037   } else {
00038     T t = vcl_atan2( vcl_sqrt(ry_) , vcl_sqrt(rx_) * vcl_tan( theta_ ) );
00039     y0 = vcl_sqrt(rx_) * vcl_cos( t ) * vcl_sin( theta_ ) + vcl_sqrt(ry_) * vcl_sin( t ) * vcl_cos( theta_ );
00040   }
00041   if ( y0 < 0 ) y0 = -y0;
00042 
00043   y_ = int( vcl_floor( yc_ + y0 ) ) + 1;
00044   min_y_ = int( vcl_ceil( yc_ - y0 ) );
00045 }
00046 
00047 template <class T>
00048 bool vgl_ellipse_scan_iterator<T>::next()
00049 {
00050   --y_;
00051   if ( y_ < min_y_ ) return false;
00052 
00053   T st = vcl_sin( -theta_ );
00054   T ct = vcl_cos( -theta_ );
00055   T A = rx_ * st * st + ry_ * ct * ct;
00056 
00057   T x0, x1; // the intersection points of the scan line; x0 >= x1
00058 
00059   if ( A > 0 ) {
00060     // not a denegerate horizontal line
00061     //
00062     T B = (rx_ - ry_) * (y_-yc_) * ct*st;
00063 //  T C = - rx_*ry_ + (rx_*ct*ct + ry_*st*st)*(y_-yc_)*(y_-yc_);
00064     T D = rx_*ry_*(rx_*st*st + ry_*ct*ct - (y_-yc_)*(y_-yc_)); // = B*B-A*C
00065     if (D < 0) D=0; // could be slightly < 0 due to rounding errors
00066 
00067     x0 = (-B + vcl_sqrt( D )) / A;
00068     x1 = (-B - vcl_sqrt( D )) / A;
00069   } else {
00070     // "ellipse" is a horizontal line or a point
00071     //
00072     x0 = vcl_sqrt( my_max(rx_,ry_) );
00073     x1 = -x0;
00074   }
00075 
00076   start_x_= int( vcl_ceil( xc_ + x1 - 1e-9 ) ); // avoid problems with rounding
00077   end_x_ = int( vcl_floor( xc_ + x0 + 1e-9 ) ); // by slightly shifting.
00078 
00079   if ( start_x_ > end_x_ ) {
00080     // Could happen with very thin ellipses, near the end points
00081     return next();
00082   } else {
00083     return true;
00084   }
00085 }
00086 
00087 #undef VGL_ELLIPSE_SCAN_ITERATOR_INSTANTIATE
00088 #define VGL_ELLIPSE_SCAN_ITERATOR_INSTANTIATE(T) \
00089 template class vgl_ellipse_scan_iterator<T >
00090 
00091 #endif // vgl_ellipse_scan_iterator_txx_

Generated on Mon Mar 8 05:07:51 2010 for core/vgl by  doxygen 1.5.1