Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

ixlib_drawing_functions.hh

Go to the documentation of this file.
00001 // ----------------------------------------------------------------------------
00002 //  Description      : Generic drawing functions
00003 // ----------------------------------------------------------------------------
00004 //  (c) Copyright 2000 by iXiONmedia, all rights reserved.
00005 // ----------------------------------------------------------------------------
00006 
00007 
00008 
00009 
00010 #ifndef IXLIB_DRAWING_FUNCTIONS
00011 #define IXLIB_DRAWING_FUNCTIONS
00012 
00013 
00014 
00015 
00016 #include <ixlib_polygon.hh>
00017 
00018 
00019 
00020 
00021 namespace ixion {
00034   namespace drawing_functions {
00042     template<class Target>
00043     void drawLine(Target &target,int x1,int y1,int x2,int y2);
00044     
00045     template<class Target>
00046     void drawBox(Target &target,int x1,int y1,int x2,int y2);
00047     template<class Target>
00048     void fillBox(Target &target,int x1,int y1,int x2,int y2);
00049     
00050     template<class Target>
00051     void drawCircle(Target &target,int x,int y,int r);
00052     template<class Target>
00053     void fillCircle(Target &target,int x,int y,int r);
00054 
00055     template<class Target>
00056     void drawEllipse(Target &target,int x,int y,int r_x,int r_y);
00057     template<class Target>
00058     void fillEllipse(Target &target,int x,int y,int r_x,int r_y);
00059     
00060     template<class Target,class T>
00061     void drawPolygon(Target &target,polygon<T> const &poly);
00062     template<class Target,class T>
00063     void fillPolygon(Target &target,polygon<T> const &poly);
00064     }
00065   }
00066 
00067 
00068 
00069 
00070 
00071 template<class Target>
00072 void ixion::drawing_functions::drawLine(Target &target,int x1,int y1,int x2,int y2) {
00073   int dx = abs(x2-x1);
00074   int dy = abs(y2-y1);
00075   int npixel;
00076   int dinc1;
00077   int dinc2;
00078   int xinc1;
00079   int xinc2;
00080   int yinc1;
00081   int yinc2;
00082   int x;
00083   int y;
00084   int d;
00085 
00086   if (dx >= dy) {
00087     npixel = dx;
00088     d = (2*dy)-dx;
00089     dinc1 = dy << 1;
00090     dinc2 = (dy-dx) << 1;
00091     xinc1 = 1;
00092     xinc2 = 1;
00093     yinc1 = 0;
00094     yinc2 = 1;
00095     }
00096   else {
00097     npixel = dy;
00098     d = (2*dx)-dy;
00099     dinc1 = dx << 1;
00100     dinc2 = (dx-dy) << 1;
00101     xinc1 = 0;
00102     xinc2 = 1;
00103     yinc1 = 1;
00104     yinc2 = 1;
00105     }
00106 
00107   if (x1>x2) {
00108     xinc1 = -xinc1;
00109     xinc2 = -xinc2;
00110     }
00111   if (y1>y2) {
00112     yinc1 = -yinc1;
00113     yinc2 = -yinc2;
00114     }
00115 
00116   x = x1;
00117   y = y1;
00118   for (int i=0; i < npixel; i++) { 
00119     target.setPixel(x,y);
00120     if (d<0) {
00121       d += dinc1;
00122       x += xinc1;
00123       y += yinc1;
00124       }
00125     else {
00126       d += dinc2;
00127       x += xinc2;
00128       y += yinc2;
00129       }
00130     }
00131   }
00132 
00133 
00134 
00135 
00136 template<class Target>
00137 void ixion::drawing_functions::drawBox(Target &target,int x1,int y1,int x2,int y2) {
00138   target.drawHLine(x1,y1,x2);
00139   target.drawVLine(x1,y1+1,y2);
00140   target.drawHLine(x1,y2,x2);
00141   target.drawVLine(x2-1,y1+1,y2);
00142   }
00143 
00144 
00145 
00146 
00147 template<class Target>
00148 void ixion::drawing_functions::fillBox(Target &target,int x1,int y1,int x2,int y2) {
00149   for (int y = y1;y < y2;y++)
00150     target.drawHLine(x1,y,x2);
00151   }
00152 
00153 
00154 
00155 
00156 // The following notation is used throughout the circle drawing code:
00157 //  81
00158 // 7  2
00159 // 6  3
00160 //  54
00161     
00162 
00163 
00164 
00165 template<class Target>
00166 void ixion::drawing_functions::drawCircle(Target &target,int x,int y,int r) {
00167   int counter = r;
00168   int xcount = 0;
00169   int ycount = r;
00170 
00171   target.setPixel(x + xcount,y - ycount); // 1
00172   target.setPixel(x - xcount,y + ycount); // 5
00173   target.setPixel(x - ycount,y - xcount); // 7
00174   target.setPixel(x + ycount,y + xcount); // 3
00175   
00176   counter -= xcount + xcount + 1;
00177   xcount++;
00178 
00179   while(xcount < ycount) {
00180     if (counter < 0) {
00181       ycount--;
00182       counter += ycount + ycount;
00183       }
00184     
00185     target.setPixel(x + xcount,y - ycount); // 1
00186     target.setPixel(x - xcount,y - ycount); // 8
00187     target.setPixel(x + xcount,y + ycount); // 4
00188     target.setPixel(x - xcount,y + ycount); // 5
00189     target.setPixel(x + ycount,y - xcount); // 2
00190     target.setPixel(x - ycount,y - xcount); // 7
00191     target.setPixel(x + ycount,y + xcount); // 3
00192     target.setPixel(x - ycount,y + xcount); // 6
00193 
00194     counter -= xcount + xcount + 1;
00195     xcount++;
00196     }
00197   }
00198 
00199 
00200 
00201 
00202 template<class Target>
00203 void ixion::drawing_functions::fillCircle(Target &target,int x,int y,int r) {
00204   int counter = r;
00205   int xcount = 0;
00206   int ycount = r;
00207   bool ycount_changed = true;
00208 
00209   target.drawHLine(x - ycount,y - xcount,x + ycount); // 7 --> 2
00210   counter -= xcount + xcount + 1;
00211   xcount++;
00212 
00213   while(xcount < ycount) {
00214     if (counter < 0) {
00215       ycount--;
00216       ycount_changed = true;
00217       
00218       counter += ycount + ycount;
00219       }
00220 
00221     if (ycount_changed) {
00222       target.drawHLine(x - xcount,y - ycount,x + xcount); // 8 --> 1
00223       target.drawHLine(x - xcount,y + ycount,x + xcount); // 5 --> 4
00224       ycount_changed = false;
00225       }
00226     target.drawHLine(x - ycount,y - xcount,x + ycount); // 7 --> 2
00227     target.drawHLine(x - ycount,y + xcount,x + ycount); // 6 --> 3
00228     counter -= xcount + xcount + 1;
00229     xcount++;
00230     }
00231   }
00232 
00233 
00234 
00235 
00236 template<class Target>
00237 void ixion::drawing_functions::drawEllipse(Target &target,int x,int y,int r_x,int r_y) {
00238   int const fix_digits = 10;
00239 
00240   if (r_x > r_y) {
00241     int counter = r_x;
00242     int xcount = 0;
00243     int ycount = r_x;
00244     int factor = (r_y << fix_digits) / r_x;
00245   
00246     target.setPixel(x + r_x,y); // S
00247     target.setPixel(x - r_x,y); // N
00248     target.setPixel(x,y - r_y); // W
00249     target.setPixel(x,y + r_y); // E
00250     
00251     int lastline_ycount = ycount;
00252     int last_xcount_scaled = (xcount * factor) >> fix_digits;
00253     counter -= xcount + xcount + 1;
00254     xcount++;
00255     
00256     while(xcount < ycount) {
00257       if (counter < 0) {
00258         ycount--;
00259         counter += ycount + ycount;
00260         }
00261       
00262       int ycount_scaled = (ycount * factor) >> fix_digits;
00263       
00264       target.setPixel(x + xcount,y - ycount_scaled); // 1
00265       target.setPixel(x - xcount,y - ycount_scaled); // 8
00266       target.setPixel(x + xcount,y + ycount_scaled); // 4
00267       target.setPixel(x - xcount,y + ycount_scaled); // 5
00268 
00269       int xcount_scaled = (xcount * factor) >> fix_digits;
00270       
00271       if (xcount_scaled != last_xcount_scaled) {
00272         if (lastline_ycount == ycount) {
00273           target.setPixel(x + ycount,y + xcount_scaled);
00274           target.setPixel(x - ycount,y + xcount_scaled);
00275           target.setPixel(x + ycount,y - xcount_scaled);
00276           target.setPixel(x - ycount,y - xcount_scaled);
00277           }
00278         else {
00279           target.drawHLine(x + ycount,y + xcount_scaled,x + lastline_ycount);
00280           target.drawHLine(x - lastline_ycount + 1,y + xcount_scaled,x - ycount + 1); 
00281           target.drawHLine(x + ycount,y - xcount_scaled,x + lastline_ycount);
00282           target.drawHLine(x - lastline_ycount + 1,y - xcount_scaled,x - ycount + 1); 
00283           }
00284 
00285         last_xcount_scaled = xcount_scaled;
00286         lastline_ycount = ycount;
00287         }
00288       
00289       counter -= xcount + xcount + 1;
00290       xcount++;
00291       }
00292     }
00293   else {
00294     int counter = r_y;
00295     int xcount = 0;
00296     int ycount = r_y;
00297     int factor = (r_x << fix_digits) / r_y;
00298   
00299     target.setPixel(x + r_x,y); // S
00300     target.setPixel(x - r_x,y); // N
00301     target.setPixel(x,y - r_y); // W
00302     target.setPixel(x,y + r_y); // E
00303     
00304     int lastline_ycount = ycount;
00305     int last_xcount_scaled = (xcount * factor) >> fix_digits;
00306     counter -= xcount + xcount + 1;
00307     xcount++;
00308     
00309     while(xcount < ycount) {
00310       if (counter < 0) {
00311         ycount--;
00312         counter += ycount + ycount;
00313         }
00314       
00315       int ycount_scaled = (ycount * factor) >> fix_digits;
00316       
00317       target.setPixel(x + ycount_scaled,y - xcount);
00318       target.setPixel(x - ycount_scaled,y - xcount);
00319       target.setPixel(x + ycount_scaled,y + xcount);
00320       target.setPixel(x - ycount_scaled,y + xcount);
00321 
00322       int xcount_scaled = (xcount * factor) >> fix_digits;
00323       
00324       if (xcount_scaled != last_xcount_scaled) {
00325         if (lastline_ycount == ycount) {
00326           target.setPixel(x + xcount_scaled,y + ycount);
00327           target.setPixel(x + xcount_scaled,y - ycount);
00328           target.setPixel(x - xcount_scaled,y + ycount);
00329           target.setPixel(x - xcount_scaled,y - ycount);
00330           }
00331         else {
00332           target.drawVLine(x + xcount_scaled,y + ycount,y + lastline_ycount);
00333           target.drawVLine(x + xcount_scaled,y - lastline_ycount + 1,y - ycount + 1);
00334           target.drawVLine(x - xcount_scaled,y + ycount,y + lastline_ycount);
00335           target.drawVLine(x - xcount_scaled,y - lastline_ycount + 1,y - ycount + 1);
00336           }
00337 
00338         last_xcount_scaled = xcount_scaled;
00339         lastline_ycount = ycount;
00340         }
00341       
00342       counter -= xcount + xcount + 1;
00343       xcount++;
00344       }
00345     }
00346   }
00347 
00348 
00349 
00350 
00351 template<class Target>
00352 void ixion::drawing_functions::fillEllipse(Target &target,int x,int y,int r_x,int r_y) {
00353   int const fix_digits = 10;
00354   if (r_x > r_y) {
00355     int counter = r_x;
00356     int xcount = 0;
00357     int ycount = r_x;
00358     int factor = (r_y << fix_digits) / r_x;
00359     
00360     int last_scaled_xcount = (xcount * factor) >> fix_digits;
00361     int last_scaled_ycount = (ycount * factor) >> fix_digits;
00362   
00363     target.drawHLine(x - r_x,y,x + r_x + 1);
00364     
00365     counter -= xcount + xcount + 1;
00366     xcount ++;
00367     
00368     while(xcount < ycount) {
00369       if (counter < 0) {
00370         ycount --;
00371         counter += ycount + ycount;
00372         }
00373   
00374       int scaled_xcount = (xcount * factor) >> fix_digits;
00375       int scaled_ycount = (ycount * factor) >> fix_digits;
00376 
00377       if (scaled_xcount != scaled_ycount && last_scaled_ycount != scaled_ycount) {
00378         target.drawHLine(x - xcount,y - scaled_ycount,x + xcount+1); // 8 --> 1
00379         target.drawHLine(x - xcount,y + scaled_ycount,x + xcount+1); // 5 --> 4
00380         last_scaled_ycount = scaled_ycount;
00381         }
00382       if (last_scaled_xcount != scaled_xcount) {
00383         target.drawHLine(x - ycount,y - scaled_xcount,x + ycount+1); // 7 --> 2
00384         target.drawHLine(x - ycount,y + scaled_xcount,x + ycount+1); // 6 --> 3
00385         last_scaled_xcount = scaled_xcount;
00386         }
00387   
00388       counter -= xcount + xcount + 1;
00389       xcount ++;
00390       }
00391     }
00392   else {
00393     int counter = r_y;
00394     int xcount = 0;
00395     int ycount = r_y;
00396     int factor = (r_x << fix_digits) / r_y;
00397     
00398     int last_scaled_xcount = (xcount * factor) >> fix_digits;
00399     int last_scaled_ycount = (ycount * factor) >> fix_digits;
00400   
00401     target.drawVLine(x,y - r_y,y + r_y + 1);
00402     
00403     counter -= xcount + xcount + 1;
00404     xcount ++;
00405     
00406     while(xcount < ycount) {
00407       if (counter < 0) {
00408         ycount --;
00409         counter += ycount + ycount;
00410         }
00411   
00412       int scaled_xcount = (xcount * factor) >> fix_digits;
00413       int scaled_ycount = (ycount * factor) >> fix_digits;
00414 
00415       if (scaled_xcount != scaled_ycount && last_scaled_ycount != scaled_ycount) {
00416         target.drawVLine(x + scaled_ycount,y - xcount,y + xcount + 1); // 2 --> 3
00417         target.drawVLine(x - scaled_ycount,y - xcount,y + xcount + 1); // 7 --> 6
00418         last_scaled_ycount = scaled_ycount;
00419         }
00420       if (last_scaled_xcount != scaled_xcount) {
00421         target.drawVLine(x + scaled_xcount,y - ycount,y + ycount + 1); // 1 --> 4
00422         target.drawVLine(x - scaled_xcount,y - ycount,y + ycount + 1); // 8 --> 5
00423         last_scaled_xcount = scaled_xcount;
00424         }
00425   
00426       counter -= xcount + xcount + 1;
00427       xcount ++;
00428       }
00429     }
00430   }
00431 
00432 
00433 
00434 
00435 template<class Target,class T>
00436 void ixion::drawing_functions::drawPolygon(Target &target,polygon<T> const &poly) {
00437   FOREACH_CONST(first_seg,poly,polygon<T>) {
00438     if ((*first_seg)->size() <= 1) continue;
00439     if ((*first_seg)->size() == 2) {
00440       drawLine(target,(*first_seg)->front()[0],(*first_seg)->front()[1],
00441         (*first_seg)->back()[0],(*first_seg)->back()[1]);
00442       target.setPixel((*first_seg)->back()[0],(*first_seg)->back()[1]);
00443       }
00444 
00445     // at least a triangle
00446     polygon_segment<T>::const_iterator 
00447       next = (*first_seg)->begin(),
00448       last = (*first_seg)->end(),
00449       previous = last-1;
00450     while (next != last) {
00451       drawLine(target,(*previous)[0],(*previous)[1],
00452         (*next)[0],(*next)[1]);
00453       previous = next;
00454       next++;
00455       }
00456     }
00457   }
00458 
00459 
00460 
00461 
00462 namespace {
00463   template<class Target>
00464   class hline_routine {
00465       Target &Tgt;
00466     public:
00467       hline_routine(Target &tgt)
00468         : Tgt(tgt) {
00469         }
00470       void operator()(int x1,int y,int x2) const {
00471         Tgt.drawHLine(x1,y,x2);
00472         }
00473     };
00474   }
00475   
00476 
00477 
00478 
00479 template<class Target,class T>
00480 void ixion::drawing_functions::fillPolygon(Target &target,polygon<T> const &poly) {
00481   hline_routine<Target> hlr(target);
00482   poly.drawScanlines(hlr);
00483   }
00484 
00485 
00486 
00487 
00488 #endif

Generated on Wed Oct 31 17:12:23 2001 for ixlib by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001