Andrew Yenalavitch Homework 1 CSE 420 - Fall 2014 1.) ( 20 points ) In the class, we have discussed how to draw a line given by y = m x + b using Besenham's algorithm with m 1. Extend the algorithm to include the case m > 1. Implement the algorithm for all the cases of m 1 and m > 1. Test your program by drawing the following lines a.) from ( 20, 20 ) to ( 300, 60 ) b.) from ( 20, 20 ) to ( 60, 300 ) c.) from ( 20, 20 ) to ( 300, -60 ) d.) from ( 20, 20 ) to ( -300, 60 ) I used a series of if statements to swap values before plotting depending on the slope and direction of the input. Here is the output for: a) (20,20) to (300,60)
b) (20,20) to (60,300) c) (20,20) to (300, -60)
d) (20,20) to (-300,60) Source code: #include <GL/glut.h> #include <stdio.h> #include <math.h> void init(void) glclearcolor(1.0,1.0,1.0,0.0); glmatrixmode(gl_projection); gluortho2d(-500.0,500.0,-500.0,500.0); void setpixel(glint x,glint y) glbegin(gl_points); glvertex2i(x,y); void line() int x0 = 20, y0 = 20, xn = -300, yn = 60, x, y; int dx, dy, //deltas pk, //decision parameter k; //looping variable glclear(gl_color_buffer_bit); glcolor3f( 0, 0, 0); setpixel(x0, y0); //plot first point
// difference between starting and ending points dx = xn - x0; dy = yn - y0; double m = dy/dx; x = x0; y = y0; pk = 2 * dy - dx; if ( m < 0 ) dy = -dy; for ( k = 0; k < dx+1; ++k ) if ( pk < 0 ) pk = pk + 2 * dy; else pk = pk + 2*dy - 2*dx; --y; ++x; setpixel( x, y ); if ( m > 1 ) dx = yn - y0; dy = xn - x0; x = y0; y = x0; for ( k = 0; k < dx-1; ++k ) if ( pk < 0 ) pk = pk + 2 * dy; else pk = pk + 2*dy - 2*dx; ++y; ++x; setpixel( y, x ); if ( (m <= 1 && m >= 0) && (xn > 0)) for ( k = 0; k < dx-1; ++k ) if ( pk < 0 ) pk = pk + 2 * dy; else pk = pk + 2*dy - 2*dx; ++y; ++x;
setpixel( x, y ); if ( (m <= 1 && m >= 0) && (xn < 0) ) dx = -dx; pk = 2 * dy - dx; for ( k = 0; k > -dx+1; --k ) if ( pk < 0 ) pk = pk + 2 * dy; else pk = pk + 2*dy - 2*dx; ++y; --x; setpixel( x, y ); glflush(); int main(int argc,char **argv) glutinit(&argc,argv); glutinitdisplaymode(glut_single GLUT_RGB); glutinitwindowposition(0,0); glutinitwindowsize(500,500); glutcreatewindow("blinemod"); init(); glutdisplayfunc( line ); glutmainloop(); return 0; 2.) ( 10 points ) Use OpenGL to draw a dot plot of the function f(x) = e - x sin ( 2πx ), where it is known that as x varies from x low to x high, f(x) takes on values between from y low to y high. Find the appropriate scaling and translation factors so that the dots will lie properly in a screen window with width W pixels and height H pixels. I used OpenGL to create a modified version of the plots program. It scales the function to fill the window based on inputs xlow and xhigh. Here are screenshots of 3 different combinations of xlow and xhigh.
xlow = 0 and xhigh = 4 xlow = -4 and xhigh = 4 xlow = 0 and xhigh = 10 Source code: #include <GL/glut.h> #include <stdio.h> #include <math.h> using namespace std; const int screenwidth = 640; const int screenheight = 480; // width of the screen window in pixels // height of the screen window in pixels
void init(void) glclearcolor(1.0,1.0,1.0,0.0); // the background color is white glcolor3f(0.0f, 0.0f, 0.0f); // the drawing color is black glpointsize(2.0); // a 'dot' is 2 by 2 pixels glmatrixmode(gl_projection); glloadidentity(); gluortho2d(0.0, screenwidth, 0.0, screenheight); double f ( double x ) double y = exp(-abs(x)) * sin(2 * 3.14159265 * x); return y; void mysine(void) glclear(gl_color_buffer_bit); double A, B, C, D, x, y, xlow, xhigh; int sx, sy; xlow = 0; xhigh = 10; A = screenwidth / (xhigh - xlow); B = A * abs(xlow); C = -screenheight / 2; D = screenheight / 2; glbegin(gl_points); for(x = xlow; x < xhigh ; x += 0.001) y = f(x); sx = (int) ( A * x + B ); sy = (int) ( C * y + D ); glvertex2i(sx, sy); glflush(); // send all output to display int main(int argc,char **argv) glutinit(&argc,argv); glutinitdisplaymode(glut_single GLUT_RGB); glutinitwindowposition(0,0); glutinitwindowsize(500,500); glutcreatewindow("mysine"); init(); glutdisplayfunc( mysine ); glutmainloop(); return 0;
3.) ( 10 points )Use SDL and the Surface class supplied in the web site to draw a line passing through the center of the screen. Animate the rotation of the line about the center for several rounds. ( Note that a user at any instance only sees a single line on the screen. ) I used SDL_Delay() and surf.clearscreen() to clear lines in set intervals, simulating a spinning line. Source code: // spinline.cpp #include <SDL/SDL.h> #include <stdlib.h>
#include <stdio.h> #include "draw.h" #include "surface.h" //draw a spinning line void spinline ( Surface &surf, int x, int y ) surf.moveto( x - 200, y ); surf.lineto( x + 200, y ); SDL_Delay ( 1000 ); surf.clearscreen(); surf.moveto( x - 175, y - 100); surf.lineto( x + 175, y + 100); SDL_Delay ( 1000 ); surf.clearscreen(); surf.moveto( x - 100, y - 175 ); surf.lineto( x + 100, y + 175 ); SDL_Delay ( 1000 ); surf.clearscreen(); surf.moveto( x, y - 200); surf.lineto( x, y + 200); SDL_Delay ( 1000 ); surf.clearscreen(); surf.moveto( x + 100, y - 175 ); surf.lineto( x - 100, y + 175 ); SDL_Delay ( 1000 ); surf.clearscreen(); surf.moveto( x + 175, y - 100 ); surf.lineto( x - 175, y + 100); SDL_Delay ( 1000 ); surf.clearscreen(); surf.moveto( x + 200, y ); surf.lineto( x - 200, y ); SDL_Delay ( 1000 ); surf.clearscreen();
int main() const int VWIDTH = 640; const int VHEIGHT = 480; const Point center ( VWIDTH/2, VHEIGHT/2 ); //center of screen Surface surf( VWIDTH, VHEIGHT, (char *) "Spinning Line" ); surf.setbackgroundcolor ( 0xff, 0xff, 0xff ); //set background to white surf.setcolor ( 0, 0, 0 ); spinline ( surf, center.x, center.y ); return 1; //using black drawing color 4.) Use turtle graphics or/and other means to reproduce any five of the following images ( extra credit for extra reproduction ). The images on the homework page are really low resolution, which makes it hard see some shapes, but I feel I made all 5 correctly. Image 1) I did some research into the recursive Dragon curve algorithm and created this using turtle graphics via the Canvas class: Source code: #include "canvas.h" Canvas cvs ( 500, 500, "Dragon" ); void dragon( int n )
if (n == 0) cvs.forward(.2,1); else dragon (n-1); cvs.turn(-90); for (int i = n - 2; i >= 0; i--) dragon(i); cvs.turn(90); cvs.forward(.2,1); void display(void) cvs.clearscreen(); cvs.setbackgroundcolor(0, 0, 0); cvs.setcolor(1.0, 0.5, 0); cvs.moveto(-2.0, 0.0); cvs.turnto ( 90.0 ); dragon ( 10 ); Image 2) I created the seven hexagon/six triangle image using OpenGl: Source code: #include <GL/glut.h> //initialization void init( void ) glclearcolor( 1.0, 1.0, 1.0, 0.0 ); //get white background color glcolor3f( 0.0f, 1.0f, 0.0f ); //set drawing color glpointsize( 4.0 ); //a dot is 4x4 glmatrixmode( GL_PROJECTION ); glloadidentity(); //replace current matrix with identity matrix gluortho2d( 0.0, 500.0, 0.0, 500.0 );
void display( void ) int x=200, y=200; glclear( GL_COLOR_BUFFER_BIT ); // clear screen glpolygonmode( GL_FRONT, GL_FILL ); //Here are the 7 hexagons // Middle hexagon glcolor3f ( 0.0, 0.0, 1.0 ); // Blue glbegin( GL_POLYGON ); glvertex2i( x + 50, y + 100 ); glvertex2i( x, y + 75 ); glvertex2i( x, y + 25); glvertex2i( x + 50, y ); glvertex2i( x + 100, y + 25); glvertex2i( x + 100, y + 75); // Top middle hexagon glcolor3f ( 1.0, 1.0, 0.0 ); // Yellow glbegin( GL_POLYGON ); glvertex2i( x + 50, y + 200 ); glvertex2i( x, y + 175 ); glvertex2i( x, y + 125); glvertex2i( x + 50, y + 100); glvertex2i( x + 100, y + 125); glvertex2i( x + 100, y + 175); // Bottom middle hexagon glcolor3f ( 1.0, 0.0, 0.0 ); // Red glbegin( GL_POLYGON ); glvertex2i( x + 50, y ); glvertex2i( x, y - 25 ); glvertex2i( x, y - 75); glvertex2i( x + 50, y - 100); glvertex2i( x + 100, y - 75); glvertex2i( x + 100, y - 25); // Upper right hexagon glcolor3f ( 1.0, 0.0, 0.0 ); // Red glbegin( GL_POLYGON ); glvertex2i( x + 100, y + 125); glvertex2i( x + 100, y + 75); glvertex2i( x + 150, y + 50);
glvertex2i( x + 150, y + 150); glvertex2i( x + 200, y + 75); glvertex2i( x + 200, y + 125); // Lower right hexagon glcolor3f ( 1.0, 1.0, 0.0 ); glbegin( GL_POLYGON ); glvertex2i( x + 100, y + 25); glvertex2i( x + 100, y - 25); glvertex2i( x + 150, y - 50); glvertex2i( x + 200, y - 25); glvertex2i( x + 200, y + 25); glvertex2i( x + 150, y + 50); // Yellow // Upper left hexagon glcolor3f ( 1.0, 0.0, 0.0 ); // Red glbegin( GL_POLYGON ); glvertex2i( x, y + 125); glvertex2i( x, y + 75); glvertex2i( x - 50, y + 50); glvertex2i( x - 100, y + 75); glvertex2i( x - 100, y + 125); glvertex2i( x - 50, y + 150); // Lower left hexagon glcolor3f ( 1.0, 1.0, 0.0 ); glbegin( GL_POLYGON ); glvertex2i( x, y + 25); glvertex2i( x, y - 25); glvertex2i( x - 50, y - 50); glvertex2i( x - 100, y - 25); glvertex2i( x - 100, y + 25); glvertex2i( x - 50, y + 50); // Yellow // Here are the six green triangles glcolor3f ( 0.0, 1.0, 0.0 ); glbegin( GL_TRIANGLES ); glvertex2i( x, y + 25); glvertex2i( x, y - 25); glvertex2i( x + 50, y); // Green glbegin( GL_TRIANGLES ); glvertex2i( x, y + 25); glvertex2i( x, y + 75); glvertex2i( x - 50, y + 50);
glbegin( GL_TRIANGLES ); glvertex2i( x, y + 125); glvertex2i( x, y + 75); glvertex2i( x + 50, y + 100); glbegin( GL_TRIANGLES ); glvertex2i( x + 50, y + 100); glvertex2i( x + 100, y + 75); glvertex2i( x + 100, y + 125); glbegin( GL_TRIANGLES ); glvertex2i( x + 100, y + 75); glvertex2i( x + 100, y + 25); glvertex2i( x + 150, y + 50); glbegin( GL_TRIANGLES ); glvertex2i( x + 100, y + 25); glvertex2i( x + 100, y - 25); glvertex2i( x + 50, y); glflush(); //send all output to screen Image 3) I created the trispiral configuration using the Canvas class. There are 3 spirals and each spiral has sides that increase in length with every turn: #include "canvas.h" Canvas cvs ( 500, 500, "trispiral" );
//draw a trispiral pattern void drawtrispiral ( float sidelength ) for (int i = 0; i < 3; i++) // Number of spirals cvs.forward( sidelength *.5, 1 ); cvs.turn(300); for (int j = 1; j < 10; j++) cvs.forward( sidelength * j, 1 ); cvs.turn(300); void display(void) cvs.clearscreen(); cvs.setbackgroundcolor(1, 1, 1); cvs.setcolor(0, 0, 0); cvs.moveto(0, 0); cvs.turnto ( 90 ); drawtrispiral(.5 ); Image 4)For this image I created the 5 figures using the Surface class Source code: #include <SDL/SDL.h> #include <stdlib.h> #include <stdio.h> #include "draw.h" #include "surface.h" //draw a star pattern void draw_star( Surface &surf, int L )
for ( int i = 0; i < 5; ++i ) surf.forward( L, 1 ); surf.turn( 144 ); //draw a wheel void draw_wheel ( Surface &surf, int n, int radius, float rotangle, Point wcenter) if ( n < 5 ) return; //bad number of sides int cx = surf.getcp().x; int cy = surf.getcp().y; Point pointarray[n]; double angle = rotangle * 3.14159265 / 180; //initial angle double angleinc = 2 * 3.14159265 / n; //angle increment surf.moveto ( ( int) (radius * cos( angle ) + cx), ( int ) ( radius * sin ( angle ) + cy ) ); for ( int k = 0; k < n; k++ ) //repeat n times angle += angleinc; Point temp (( int) (radius * cos( angle ) + cx), ( int ) ( radius * sin ( angle ) + cy ) ); surf.lineto ( temp ); pointarray[k] = temp; for (int i = 0; i < n; i++) surf.moveto (wcenter); surf.lineto (pointarray[i]); //draw an n-sided regular polygon void draw_polygon ( Surface &surf, int n, int radius, float rotangle ) if ( n < 3 ) return; //bad number of sides int cx = surf.getcp().x; int cy = surf.getcp().y; double angle = rotangle * 3.14159265 / 180; //initial angle double angleinc = 2 * 3.14159265 / n; //angle increment surf.moveto ( ( int) (radius * cos( angle ) + cx), ( int ) ( radius * sin ( angle ) + cy ) ); for ( int k = 0; k < n; k++ ) //repeat n times angle += angleinc; surf.lineto ( ( int) (radius * cos( angle ) + cx), ( int ) ( radius * sin ( angle ) + cy ) ); //draw_polygon //draw rosette with N-sided polygon void rosette (Surface &surf, int N, int radius )
if ( N < 3 ) return; Point pt[n+1]; int cx = surf.getcp().x; int cy = surf.getcp().y; double angle = 0; //initial angle double angleinc = 2 * 3.14159265 / N; //angle increment pt[0] = Point ( ( int) (radius * cos( angle ) + cx), ( int ) ( radius * sin ( angle ) + cy ) ); for ( int k = 1; k < N; k++ ) //repeat n times angle += angleinc; pt[k] = Point ( ( int) (radius * cos( angle ) + cx), ( int ) ( radius * sin ( angle ) + cy ) ); for ( int i = 0; i < N - 1; i++ ) for ( int j = i + 1; j < N; j++ ) surf.moveto ( pt[i] ); //connect all vertices //rosette int main() surf.lineto ( pt[j] ); #ifndef ARM const int VWIDTH = 640; const int VHEIGHT = 480; #else const int VWIDTH = 320; const int VHEIGHT = 240; #endif const Point center ( VWIDTH/2, VHEIGHT/2 ); //center of screen Surface surf( VWIDTH, VHEIGHT, (char *) "Draw_demo" ); surf.clearscreen(); SDL_Delay ( 1000 ); //clear screen //dealy one second, just for demo surf.setbackgroundcolor ( 0xff, 0xff, 0xff ); //set background to white surf.setcolor ( 0, 0, 0 ); //black //draw a star surf.moveto ( center.x - 100, center.y - 70 ); surf.turnto ( 0 ); draw_star ( surf, 100 ); //draw nested stars Point p1 ( center.x + 100, center.y - 60 ); surf.moveto ( p1 );
surf.turnto ( 0 ); for (int i = 99; i > 0; i-=33) int x = p1.x + 16; int y = p1.y - 5; p1.set(x,y); surf.moveto ( p1 ); draw_star ( surf, i ); //draw an pentagon surf.moveto ( center.x - 220, center.y - 70 ); draw_polygon ( surf, 5, 60, 55 ); //draw a wheel Point wcenter ( center.x - 200, center.y + 100 ); surf.moveto ( wcenter ); draw_wheel ( surf, 15, 100, 0, wcenter ); //draw an 20-sided rosette surf.setcolor ( 0, 0, 0 ); surf.moveto ( center.x + 90, center.y + 100 ); rosette ( surf, 20, 100 ); SDL_Delay ( 5000 ); return 1; Image 5) For this image I used the Surface class as in the above image: Source code: #include <SDL/SDL.h> #include <stdlib.h> #include <stdio.h> #include "draw.h" #include "surface.h"
void draw_frect( Surface surf, int L) int temp = L; for ( int i = 0; i < L; ++i ) surf.forward( temp, 1 ); surf.turn( 90 ); --temp; void draw_rect( Surface surf, int W, int H) surf.forward( W, 1 ); surf.turn( 90 ); surf.forward( H, 1 ); surf.turn( 90 ); surf.forward( W, 1 ); surf.turn( 90 ); surf.forward( H, 1 ); surf.turn( 90 ); void draw_arc ( Surface &surf, int n, int radius, float rotangle ) if ( n < 3 ) return; //bad number of sides int cx = surf.getcp().x; int cy = surf.getcp().y; double angle = rotangle * 3.14159265 / 180; //initial angle double angleinc = 2 * 3.14159265 / n; //angle increment surf.moveto ( ( int) (radius * cos( angle ) + cx), ( int ) ( radius * sin ( angle ) + cy ) ); for ( int k = 0; k < 2 * n / 3; k++ ) //repeat n times angle += angleinc; surf.lineto ( ( int) (radius * cos( angle ) + cx), ( int ) ( radius * sin ( angle ) + cy ) ); //draw rosette with N-sided polygon void rosette (Surface &surf, int N, int radius ) if ( N < 3 ) return; Point pt[n+1]; int cx = surf.getcp().x; int cy = surf.getcp().y; double angle = 0; //initial angle double angleinc = 2 * 3.14159265 / N; //angle increment pt[0] = Point ( ( int) (radius * cos( angle ) + cx), ( int ) ( radius * sin ( angle ) + cy ) ); for ( int k = 1; k < N; k++ ) //repeat n times
angle += angleinc; pt[k] = Point ( ( int) (radius * cos( angle ) + cx), ( int ) ( radius * sin ( angle ) + cy ) ); for ( int i = 0; i < N - 1; i++ ) for ( int j = i + 1; j < N; j++ ) surf.moveto ( pt[i] ); //connect all vertices //rosette int main() surf.lineto ( pt[j] ); #ifndef ARM const int VWIDTH = 640; const int VHEIGHT = 480; #else const int VWIDTH = 320; const int VHEIGHT = 240; #endif const Point center ( VWIDTH/2, VHEIGHT/2 ); //center of screen Surface surf( VWIDTH, VHEIGHT, (char *) "Draw_demo" ); surf.clearscreen(); SDL_Delay ( 1000 ); //clear screen //dealy one second, just for demo surf.setbackgroundcolor ( 0xff, 0xff, 0xff ); //set background to white //draw a 17-sided rosette surf.setcolor ( 0xff, 0, 0 ); surf.moveto ( center.x + 90, center.y ); rosette ( surf, 17, 100 ); //draw an arc (2/3 of a circle) surf.setcolor ( 0, 0, 0 ); surf.moveto ( center.x + 40, center.y ); draw_arc ( surf, 40, 230, -85 ); //red //black //draw filled rectangle surf.setcolor ( 0, 0xff, 0 ); //green surf.moveto ( center.x - 270, center.y + 90 ); surf.turnto(0); draw_frect ( surf, 170 ); //draw an empty square (overwrites lines of rectangle that overlap) surf.setcolor ( 0, 0xff, 0 ); //green surf.moveto ( center.x - 250, center.y - 60 );
draw_rect ( surf, 65, 75 ); SDL_Delay ( 3000 ); return 1; Evaluation: This was one of the most time-consuming homework assignments I've ever done. I feel 5 images is too large a number. Having said that, I feel I successfully completed all parts of the homework assignment and am giving myself 60 points.