Main Page | File List

Canvas.cpp

00001 #include "Canvas.h"
00002 #include "color.h"
00003 #include "xmath.h"
00004 #include <iostream>
00005 #include <fstream>
00006 #include <vector>
00007 
00008 
00009 using namespace std;
00010 
00011 namespace columbia
00012 {
00013 
00014   void Canvas :: init() 
00015   { 
00016     int N = hReso*vReso;
00017 
00018     delete [] data; 
00019     data = new RGB [N]; 
00020     memset(data, 0, sizeof(RGB) * N);
00021   }
00022 
00023 
00024   void Canvas :: WritePPM(const char *_filename) const
00025   {
00026     Canvas* This =  (Canvas*)this;
00027     
00028     if(!_filename) 
00029       _filename = filename.c_str();
00030 
00031     ofstream file;
00032     file.open (_filename, ios::out | ios::binary);
00033     
00034     if(file) 
00035     {
00036       file << "P6\n";   // color rawbits format
00037       file << hReso << " " << vReso << endl << 100 << endl;
00038   
00039       unsigned char r, g, b;
00040       for (int row = 0; row < vReso; row++) 
00041         for (int col = 0; col < hReso; col++) 
00042         {
00043           r = (unsigned char) (100.0*(*This)[vReso-row-1][col][0]);  
00044           g = (unsigned char) (100.0*(*This)[vReso-row-1][col][1]);  
00045           b = (unsigned char) (100.0*(*This)[vReso-row-1][col][2]);  
00046 
00047           if(r>100.0 || g>100.0 || b>100.0)  throw "RGB color overflow\n"; 
00048 
00049           file << r << g << b;
00050         }
00051 
00052       file << endl;
00053       file.close();
00054     }
00055     else 
00056       cerr << "Can't open output file " << _filename << endl;
00057   }
00058 
00059 
00060   void Canvas :: scanLineSegment(int x1, int y1, RGB const& col1, int x2, int y2, RGB const& col2, multimap<int, int>* output)
00061   {
00062     assert( x2-x1 >= 1 && x2-x1 >= y2-y1 && y2-y1 >= 0);
00063 
00064     for(int x = x1; x != x2; ++x)
00065     {
00066       double t = ( double(x-x1) ) / (x2 - x1);
00067       int y = round( interpolate(t, double(y1), double(y2)) );
00068 
00069       int X = x, Y = y;
00070 
00071       if(swap_xy)
00072       {
00073         swap(X,Y);
00074       }
00075       if(flip_y) Y = -Y-1;   // minus 1 is necessary because the pixel is specified by its lower left corner (x, y) pair.
00076       
00077       if(output) 
00078         output->insert(make_pair(Y, X));
00079       else
00080         (*this)[Y + vReso/2][X + hReso/2] = interpolate(t, col1, col2);
00081     }
00082   }
00083   
00084 
00085   void Canvas :: ScanLineSegment(int x1, int y1, RGB const& col1, int x2, int y2, RGB const& col2, multimap<int,int>* output)
00086   {
00087     if(x1==x2 && y1==y2) return;
00088     
00089     if(x1 > x2)                                       // always scan convert from left to right.
00090     {
00091       swap(x1, x2), swap(y1, y2); 
00092       swap( ((RGB&)col1),  ((RGB&)col2) );
00093     }
00094     if( (flip_y = y1 > y2) )                          // always scan convert from down to up.
00095     {
00096       y1 = -y1, y2 = -y2;
00097     }
00098     if( (swap_xy = y2-y1 > x2-x1) )                   // and always scan convert a line with <= 45 deg to x-axis.
00099     {
00100       swap(x1, y1), swap(x2, y2);
00101     }
00102     scanLineSegment(x1, y1, col1, x2, y2, col2, output);
00103   }
00104 
00105 
00106   void Canvas :: SolidTriangle(int x1, int y1, RGB const& col1, int x2, int y2, RGB const& col2, int x3, int y3, RGB const& col3)
00107   {
00108     multimap<int, int> scanned_pnts;     // the key is y value of the scanned point.
00109 
00110     ScanLineSegment(x1,y1,White, x2,y2,White, &scanned_pnts);
00111     ScanLineSegment(x1,y1,White, x3,y3,White, &scanned_pnts);
00112     ScanLineSegment(x3,y3,White, x2,y2,White, &scanned_pnts);
00113 
00114     int cur_yval = vReso / 2;           // initialize to an invalid value.
00115     vector<int> xvals;                  // put x_vals of all points with the same y value here.
00116     
00117     for (multimap<int, int>::iterator it = scanned_pnts.begin(); it != scanned_pnts.end(); ++it)
00118     {
00119       int y = it->first;
00120       if(y != cur_yval) 
00121       {
00122         if(xvals.size())
00123         {
00124           int xleft = *( min_element( xvals.begin(), xvals.end() ) );
00125           int xright = *( max_element( xvals.begin(), xvals.end() ) );
00126           ScanLineSegment(xleft, cur_yval, White, xright, cur_yval, White);
00127           xvals.clear();
00128         }
00129         cur_yval = y;
00130       }
00131       xvals.push_back(it->second);
00132     }
00133   }
00134   
00135 }

Generated on Thu Jul 8 10:41:20 2004 by doxygen 1.3.6