vgl_ellipse_scan_iterator.hxx
Go to the documentation of this file.
1 // This is core/vgl/vgl_ellipse_scan_iterator.hxx
2 #ifndef vgl_ellipse_scan_iterator_hxx_
3 #define vgl_ellipse_scan_iterator_hxx_
4 
5 #include <cmath>
7 #ifdef _MSC_VER
8 # include <vcl_msvc_warnings.h>
9 #endif
10 
11 // Helper functions
12 namespace {
13  template <class T> inline T my_max( T x, T y ) { return x<y ? y : x; }
14 }
15 
16 template <class T>
18  : xc_( xc ),
19  yc_( yc ),
20  rx_( rx*rx ),
21  ry_( ry*ry ),
22  theta_( theta ),
23  y_( 0 ),
24  min_y_( 0 )
25 {
26 }
27 
28 template <class T>
30 
31 template <class T>
33 {
34  // The max value.
35  T y0;
36  if ( std::sin( theta_ ) == 0.0 ) {
37  y0 = std::sqrt(ry_);
38  }
39  else {
40  T t = std::atan2( std::sqrt(ry_) , std::sqrt(rx_) * std::tan( theta_ ) );
41  y0 = std::sqrt(rx_) * std::cos( t ) * std::sin( theta_ ) + std::sqrt(ry_) * std::sin( t ) * std::cos( theta_ );
42  }
43  if ( y0 < 0 ) y0 = -y0;
44 
45  y_ = int( std::floor( yc_ + y0 ) ) + 1;
46  min_y_ = int( std::ceil( yc_ - y0 ) );
47 }
48 
49 template <class T>
51 {
52  --y_;
53  if ( y_ < min_y_ ) return false;
54 
55  T st = std::sin( -theta_ );
56  T ct = std::cos( -theta_ );
57  T A = rx_ * st * st + ry_ * ct * ct;
58 
59  T x0, x1; // the intersection points of the scan line; x0 >= x1
60 
61  if ( A > 0 ) {
62  // not a degenerate horizontal line
63  //
64  T B = (rx_ - ry_) * (y_-yc_) * ct*st;
65 // T C = - rx_*ry_ + (rx_*ct*ct + ry_*st*st)*(y_-yc_)*(y_-yc_);
66  T D = rx_*ry_*(rx_*st*st + ry_*ct*ct - (y_-yc_)*(y_-yc_)); // = B*B-A*C
67  if (D < 0) D=0; // could be slightly < 0 due to rounding errors
68 
69  x0 = (-B + std::sqrt( D )) / A;
70  x1 = (-B - std::sqrt( D )) / A;
71  }
72  else {
73  // "ellipse" is a horizontal line or a point
74  //
75  x0 = std::sqrt( my_max(rx_,ry_) );
76  x1 = -x0;
77  }
78 
79  start_x_= int( std::ceil( xc_ + x1 - 1e-9 ) ); // avoid problems with rounding
80  end_x_ = int( std::floor( xc_ + x0 + 1e-9 ) ); // by slightly shifting.
81 
82  if ( start_x_ > end_x_ ) {
83  // Could happen with very thin ellipses, near the end points
84  return next();
85  }
86  else {
87  return true;
88  }
89 }
90 
91 #undef VGL_ELLIPSE_SCAN_ITERATOR_INSTANTIATE
92 #define VGL_ELLIPSE_SCAN_ITERATOR_INSTANTIATE(T) \
93 template class vgl_ellipse_scan_iterator<T >
94 
95 #endif // vgl_ellipse_scan_iterator_hxx_
vgl_ellipse_scan_iterator(T xc, T yc, T rx, T ry, T theta)
Constructor.
~vgl_ellipse_scan_iterator() override
Destructor.
void reset() override
Resets the scan iterator to before the first scan line.
bool next() override
Tries to moves to the next scan line.