core/vgl/vgl_triangle_scan_iterator.txx
Go to the documentation of this file.
00001 // This is core/vgl/vgl_triangle_scan_iterator.txx
00002 #ifndef vgl_triangle_scan_iterator_txx_
00003 #define vgl_triangle_scan_iterator_txx_
00004 //:
00005 // \file
00006 // \author fsm
00007 
00008 #include "vgl_triangle_scan_iterator.h"
00009 
00010 #include <vcl_cmath.h>
00011 #include <vcl_iostream.h>
00012 
00013 template <class T>
00014 static inline
00015 void min_n_max(T a, T b, T c, T *min, T *max)
00016 {
00017   if (a < b) {
00018     if (a < c) {
00019       *min = a;
00020       if (b < c)  // a b c
00021   *max = c;
00022       else        // a c b
00023   *max = b;
00024     }
00025     else {        // c a b
00026       *min = c;
00027       *max = b;
00028     }
00029   }
00030   else {
00031     if (b < c) {
00032       *min = b;
00033       if (a < c) // b a c
00034   *max = c;
00035       else       // b c a
00036   *max = a;
00037     }
00038     else {       // c b a
00039       *min = c;
00040       *max = a;
00041     }
00042   }
00043   // that was fun. now do some work.
00044 }
00045 
00046 #if use_polygon_scan_iterator
00047 #include <vgl/vgl_polygon_scan_iterator.h>
00048 template <class T>
00049 struct vgl_triangle_scan_iterator<T>::data_t : public vgl_polygon_scan_iterator<T>
00050 {
00051   typedef vgl_polygon_scan_iterator<T> base;
00052   data_t(vgl_polygon<T> const &p) : base(p) {}
00053 };
00054 
00055 template <class T>
00056 vgl_triangle_scan_iterator<T>::~vgl_triangle_scan_iterator()
00057 {
00058   if (data)
00059     delete data;
00060   data = 0;
00061 }
00062 #else
00063 // w(a, b, c) = det [ a b c ]
00064 //                  [ 1 1 1 ]
00065 //# define w(a, b, c) ( b.x*c.y - b.x*a.y - a.x*c.y - c.x*b.y + c.x*a.y + a.x*b.y )
00066 #endif
00067 
00068 template <class T>
00069 void vgl_triangle_scan_iterator<T>::reset()
00070 {
00071 #if use_polygon_scan_iterator
00072   if (data)
00073     delete data;
00074   T x[3] = { a.x, b.x, c.x };
00075   T y[3] = { a.y, b.y, c.y };
00076   vgl_polygon<T> p(x, y, 3);
00077   data = new data_t(p);
00078   data->reset();
00079 #else
00080   T min, max;
00081 
00082   min_n_max(a.x, b.x, c.x, &min, &max);
00083   x0 = (int) vcl_ceil (min);
00084   x1 = (int) vcl_floor(max);
00085 #ifdef DEBUG
00086   vcl_cerr << "x0 x1 = " << x0 << ' ' << x1 << '\n';
00087 #endif
00088 
00089   min_n_max(a.y, b.y, c.y, &min, &max);
00090   y0 = (int) vcl_ceil (min);
00091   y1 = (int) vcl_floor(max);
00092 #ifdef DEBUG
00093   vcl_cerr << "y0 y1 = " << y0 << ' ' << y1 << '\n';
00094 #endif
00095 
00096   scany_ = y0 - 1;
00097 
00098   // compute centroid
00099   g.x = vcl_floor((a.x + b.x + c.x)/3);
00100   g.y = vcl_floor((a.y + b.y + c.y)/3);
00101 #ifdef DEBUG
00102   vcl_cerr << "g = " << g.x << ' ' << g.y << '\n';
00103 #endif
00104 
00105   //
00106   pt ag = { a.x - g.x, a.y - g.y };
00107   pt bg = { b.x - g.x, b.y - g.y };
00108   pt cg = { c.x - g.x, c.y - g.y };
00109 
00110   data[0][0] = bg.y - cg.y; data[0][1] = cg.x - bg.x; data[0][2] = bg.x * cg.y - bg.y * cg.x;
00111   data[1][0] = cg.y - ag.y; data[1][1] = ag.x - cg.x; data[1][2] = cg.x * ag.y - cg.y * ag.x;
00112   data[2][0] = ag.y - bg.y; data[2][1] = bg.x - ag.x; data[2][2] = ag.x * bg.y - ag.y * bg.x;
00113 
00114   T tmp = ( bg.x*cg.y - bg.x*ag.y - ag.x*cg.y - cg.x*bg.y + cg.x*ag.y + ag.x*bg.y );
00115   if (tmp < 0)
00116     tmp = -1;
00117   else
00118     tmp = +1;
00119   for (int i=0; i<3; ++i) {
00120     T f = tmp; // / sqrt(data[i][0]*data[i][0] + data[i][1]*data[i][1]);
00121     for (int j=0; j<3; ++j)
00122       data[i][j] *= f;
00123   }
00124 #if 0
00125   vcl_cerr << "data:\n";
00126   for (int i=0; i<3; ++i) {
00127     for (int j=0; j<3; ++j)
00128       vcl_cerr << ' ' << data[i][j];
00129     vcl_cerr << vcl_endl;
00130   }
00131   vcl_cerr << vcl_endl;
00132 #endif
00133 #endif // use_polygon_scan_iterator
00134 }
00135 
00136 template <class T>
00137 bool vgl_triangle_scan_iterator<T>::next()
00138 {
00139 #if use_polygon_scan_iterator
00140   if (data->next()) {
00141     scany_ = data->scany();
00142     startx_ = data->startx();
00143     endx_ = data->endx();
00144     return true;
00145   }
00146   else
00147     return false;
00148 #else
00149   if (++scany_ > y1)
00150     return false;
00151 
00152   T minx = x0 - g.x;
00153   T maxx = x1 - g.x;
00154 
00155 #ifdef DEBUG
00156   vcl_cerr << "minx maxx = " << minx << ' ' << maxx << '\n';
00157 #endif
00158   for (int i=0; i<3; ++i) {
00159     T a_ = data[i][0];
00160     T b_ = data[i][1] * (scany_ - g.y) + data[i][2];
00161     // ax + b >= 0
00162     if (a_ == 0) {
00163       // bif bif
00164     }
00165     else {
00166       T x = -b_/a_;
00167       if (a_ > 0) {
00168         if (x > minx)
00169           minx = x;
00170       }
00171       else {
00172         if (x < maxx)
00173           maxx = x;
00174       }
00175     }
00176 #ifdef DEBUG
00177     vcl_cerr << "minx maxx = " << minx << ' ' << maxx << '\n';
00178 #endif
00179   }
00180 
00181   startx_ = (int) vcl_ceil (minx + g.x);
00182   endx_   = (int) vcl_floor(maxx + g.x);
00183 
00184   // can not use (scany_ == y0) || (startx_ <= endx_)
00185   // for early scan termination because some triangles may have
00186   // (startx_ > endx_) for more than the first scan line
00187 
00188 
00189   return true;
00190 #endif
00191 }
00192 
00193 #undef VGL_TRIANGLE_SCAN_ITERATOR_INSTANTIATE
00194 #define VGL_TRIANGLE_SCAN_ITERATOR_INSTANTIATE(T) \
00195 template class vgl_triangle_scan_iterator<T >
00196 
00197 #endif // vgl_triangle_scan_iterator_txx_