Main Page | File List

Canvas.h

Go to the documentation of this file.
00001 /**
00002  *\file         Canvas.h
00003  *
00004  *\brief        The Canvas class is a discrete simulation of the real life canvas. 
00005  *
00006  *              The canvas is cutted into grid structure, with <b><var>vReso</var></b> grids along
00007  *              vertical (<b><var>Row</var></b>) direction and <b><var>hReso</var></b> horizontal grids along 
00008  *              horizontal(<b><var>Col</var></b>) direction. Each rectangular grid is called a pixel, or picture
00009  *              element, and is specified by its lower-left <b><var>(row, col)</var></b> position. 
00010  *              The coordinate system has the lower-left corner of the canvas as its origin, 
00011  *              with <b><var>Row</var></b> going up and <b><var>Col</var></b> going right. The lower-left corner 
00012  *              pixel has a coordinate of <b><var>(0,0)</var></b>, and the upper-right one of <b><var>
00013  *              (hReso - 1, vReso - 1)</var></b>. 
00014  *
00015  *              A <b><var>(x, y)</var></b> pair means <b><var>col = x+hReso/2, and row = y+vReso/2</var></b>.
00016  *
00017  *              To each piexel <b><var>(row, col)</var></b> on the Canvas, a RGB color value is associated,
00018  *              which can be accessed via index operator [<b><var>row</var></b>][<b><var>col</var></b>].
00019  *
00020  *              WritePPM() writes the Canvas to an image file of PPM format.
00021  *
00022  * <H4>11 Jul 2004:</H4> Point structure and perspectiveProjection(Point const&) added. Now the Canvas is actually a virutal camera
00023  *              in the simplest setting: the Canvas plane is centered at z=0 with x-size of hReso, and y-size of vReso, 
00024  *              Eye at eye_at (>0) and looking along positive z direction.  eye_at defaults to hReso / 2.
00025  *
00026  *              Now the triangle primitives are updated so the given points are in 3D space. The other primitives are
00027  *              not updated though, and actually can be deleted from Canvas class, since for 3D graphics, everything 
00028  *              is usually tesselated by triangles.
00029  *
00030  *\author       Xianming Chen
00031  *
00032  */
00033 
00034 
00035 #ifndef _CANVAS_H_
00036 #define _CANVAS_H_
00037 
00038 #include "RGB.h"
00039 #include "xmath.h"
00040 #include "Point.h"
00041 
00042 #include <string>
00043 #include <cassert>
00044 #include <map>
00045 
00046 using namespace std;
00047 
00048 namespace columbia
00049 {
00050   
00051   class Canvas
00052   { 
00053   public:
00054       explicit Canvas(int resoH = 512, int resoV = 512) : hReso(resoH), vReso(resoV), filename("tmp.ppm"), data(0)  { init(); }
00055       ~Canvas()                                  { delete [] data; }
00056       void Clear(RGB const&);
00057       
00058       RGB* operator[] (int r)                    { assert(r>=0 && r<vReso); return data + r*hReso; }
00059       RGB& Pixel(int row, int col);              //! Use this instead of the [] operator if both row and col number checking is needed.
00060       
00061       /**
00062        * Scan-convert a line segment given two end points. The scan conversion stop right before the second end point.
00063        * If output = 0, Draw a line segment between two end points, (x1,y1) and (x2,y2).  Each pixel color is interpolated from two end colors.
00064        * Else only return scanned result to output.
00065        */
00066       void ScanLineSegment(int x1, int y1, RGB const& color1, int x2, int y2, RGB const& color2, multimap<int, pair<int, RGB> >* output=0);  
00067 
00068       void WireTriangle(Point const& P1, RGB const& col1, Point const& P2, RGB const& col2, Point const& P3, RGB const& col3);
00069       void SolidTriangle(Point const& P1, RGB const& col1, Point const& P2, RGB const& col2, Point const& P3, RGB const& col3);
00070       
00071       void WritePPM(const char* = 0) const;
00072 
00073       int hReso, vReso;                          //! Resolutions (pixel #)at horizontal and vertical directions.
00074       std::string filename;                      //! write as PPM image file name.
00075 
00076 
00077       //! For 3D graphics, we can get rid of these methods-- everything should be triangles.
00078       void WireCircle(int center_x, int center_y, int radius, int reso, RGB const& col);
00079       void SolidCircle(int center_x, int center_y, int radius, RGB const& col);
00080       void SolidRectangle(int minx, int miny, int maxx, int maxy, RGB const& col);
00081 
00082   private:
00083       RGB* data;
00084       bool swap_xy, flip_y;                      // swap x&y if abs(slope) > 1.0, flip y if y<0.
00085 
00086       void init();
00087 
00088       void scanLineSegment(int x1, int y1, RGB const& col1, int x2, int y2, RGB const& col2, multimap<int, pair<int, RGB> >* output); 
00089       void writePixel(int X, int Y, RGB const& col, multimap<int, pair<int, RGB> >* output); 
00090 
00091       double eye_at;
00092       Point perspectiveProjection(Point const&); 
00093   };
00094   
00095   inline void Canvas :: writePixel(int X, int Y, RGB const& col, multimap<int, pair<int, RGB> >* output)
00096   {
00097     if(swap_xy) swap(X,Y);
00098     if(flip_y)  Y = -Y; 
00099 
00100     if(output) output->insert(make_pair(Y, make_pair(X, col)));
00101 
00102     else if( (X >= -hReso/2 && X <= hReso/2) &&
00103              (Y >= -vReso/2 && Y <= vReso/2) )
00104     {
00105       Pixel(Y + vReso/2, X + hReso/2) = col;
00106     }
00107   }
00108   
00109 
00110   inline RGB& Canvas :: Pixel(int row, int col)
00111   {
00112     if(row >= vReso) throw "row number overflow\n";
00113     if(row < 0)      throw "row number underflow\n";
00114     if(col >= hReso) throw "col number overrflow\n";
00115     if(col < 0)      throw "col number underflow\n";
00116     return *(data + row * hReso + col);
00117   }
00118   
00119 
00120   /* Geometry: Canvas at z=0. eye at eye_at(>0).
00121                     |
00122                     |  *
00123      eye<-----------|----------
00124                     |
00125                     |
00126   */
00127   inline Point Canvas :: perspectiveProjection(Point const& P)
00128   {
00129     double scale = eye_at / (eye_at - P.z);
00130     return Point(P.x * scale, P.y * scale, P.z);
00131   }
00132 
00133 
00134 }
00135 
00136 #endif

Generated on Wed Jul 14 19:41:01 2004 by doxygen 1.3.6