|
|
|
|
| dlower | = | y - yk |
| = | m ( xk + 1 ) + b - yk |
| dupper | = | ( yk + 1 ) - y |
| = | yk + 1 - m ( xk + 1 ) - b |
| dlower - dupper | = | 2m ( xk + 1 ) - 2 yk + 2b - 1 |
Let m = ( yn - y0 ) / ( xn - x0 ) = Δy / Δx
Define the decision parameter as
| pk | = | Δx ( dlower - dupper ) |
| = | 2Δy.xk - 2Δx.yk + c ----- ( 1 ) |
Therefore,
In ( 2 ) , yk+1 - yk is either 0 or 1, depending on the sign of pk. From ( 1 ), as Δx >0, if the pixel at yk is closer to the line path than at yk + 1 (i.e. dlower < dupper ), pk is negative and we choose the next pixel to be the lower pixel; otherwise we choose the upper pixel.
|
Brensenham's Line Drawing algorithm for |m| < 1
|
|
//bline.cpp : Bresenham Line algorithm, works only for |m| < 1
#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(0.0,400.0,0.0,400.0);
}
void setPixel(GLint x,GLint y)
{
glBegin(GL_POINTS);
glVertex2i(x,y);
glEnd();
}
void line()
{
int x0 = 50, y0=50, xn = 300, yn = 150, x, y;
int dx, dy, //deltas
pk, //decision parameter
k; //looping variable
glClear(GL_COLOR_BUFFER_BIT);
glColor3f( 1 ,0, 0);
setPixel(x0, y0); //plot first point
// difference between starting and ending points
dx = xn - x0;
dy = yn - y0;
pk = 2 * dy - dx;
x = x0; y = y0;
for ( k = 0; k < dx-1; ++k ) {
if ( pk < 0 ) {
pk = pk + 2 * dy; //calculate next pk
//next pixel: (x+1, y )
} else {
//next pixel: (x+1, y+1)
pk = pk + 2*dy - 2*dx; //calculate next pk
++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("Bresenham Line");
init();
glutDisplayFunc( line );
glutMainLoop();
return 0;
}
|
| E1(k) | = | [yk2 - y2] | = | yk2 + ( xk + 1 )2 - r2 |
| E2(k) | = | y2 - (yk - 1)2 | = | r2 - ( xk + 1 )2 - (yk - 1)2 |
| dk | = | ( E1(k) - E2(k) ) / 2 | = | yk2 + xk2 + 2xk - yk + c |
| dk+1 | = | yk2 + (xk + 1)2 + 2( xk + 1 ) - yk + c |
| = | yk2 + xk 2 + 2xk + 1 + 2xk + 2 - yk + c | |
| = | dk + 2xk + 3 |
| dk+1 | = | (yk - 1) 2 + (xk + 1)2 + 2( xk + 1 ) - yk + c |
| = | yk2 - 2yk + 1 + xk2 + 2xk + 1 + 2xk + 2 - yk + c | |
| = | dk + 2 (xk - yk) + 5 |
//bcircle.cpp : Bresenham Circle algorithm
#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(0.0,200.0,0.0,200.0);
}
void setPixel(GLint x,GLint y)
{
glBegin(GL_POINTS);
glVertex2i(x,y);
glEnd();
}
void Circle(){
int xCenter=100,yCenter=100,r=50;
int x=0,y=r;
int d = 3/2 - r; // = 1 - r
glClear(GL_COLOR_BUFFER_BIT);
glColor3f( 1 ,0, 0);
while(x<=y){
setPixel(xCenter+x,yCenter+y);
setPixel(xCenter+y,yCenter+x); //find other points by symmetry
setPixel(xCenter-x,yCenter+y);
setPixel(xCenter+y,yCenter-x);
setPixel(xCenter-x,yCenter-y);
setPixel(xCenter-y,yCenter-x);
setPixel(xCenter+x,yCenter-y);
setPixel(xCenter-y,yCenter+x);
if (d<0)
d += (2*x)+3;
else {
d += (2*(x-y))+5;
y -= 1;
}
x++;
}
glFlush();
}
int main(int argc,char **argv){
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowPosition(0,0);
glutInitWindowSize(500,500);
glutCreateWindow("Bresenham Circle");
init();
glutDisplayFunc(Circle);
glutMainLoop();
return 0;
}
|
/*
draws a line from current point to new point using Bresenham algorithm
surf is the SDL_Surface of the class
*/
void Surface:: lineTo( int x1, int y1 )
{
Uint16 *buffer;
int drawpos;
int xspan, yspan;
int xinc, yinc, x0, y0;
int sum;
int i;
/* If we need to lock this surface before drawing pixels, do so. */
if (SDL_MUSTLOCK( surf )) {
if (SDL_LockSurface(surf) < 0) {
printf("Error locking surface: %s\n", SDL_GetError());
abort();
}
}
/* Get the surface's data pointer. */
buffer = (Uint16 *)surf->pixels;
x0 = CP.x; y0 = CP.y;
//here's the Brensenham's algorithm, it draws from ( x0, y0 ) to ( x1, y1 )
/* Calculate the x and y spans of the line. */
xspan = x1-x0+1;
yspan = y1-y0+1;
/* Figure out the correct increment for the major axis.
Account for negative spans (x1 < x0, for instance). */
if (xspan < 0) {
xinc = -1;
xspan = -xspan;
} else xinc = 1;
if (yspan < 0) {
yinc = -surf->pitch/2;
yspan = -yspan;
} else yinc = surf->pitch/2;
i = 0;
sum = 0;
/* This is our current offset into the buffer. We use this
variable so that we don't have to calculate the offset at
each step; we simply increment this by the correct amount.
Instead of adding 1 to the x coordinate, we add one to drawpos.
Instead of adding 1 to the y coordinate, we add the surface's
pitch (scanline width) to drawpos. */
drawpos = surf->pitch/2 * y0 + x0;
/* Our loop will be different depending on the
major axis. */
if (xspan < yspan) {
/* Loop through each pixel along the major axis. */
for (i = 0; i < yspan; i++) {
/* Draw the pixel. */
buffer[drawpos] = color;
/* Update the incremental division. */
sum += xspan;
/* If we've reached the dividend, advance
and reset. */
if (sum >= yspan) {
drawpos += xinc;
sum -= yspan;
}
/* Increment the drawing position. */
drawpos += yinc;
}
} else {
/* See comments above. This code is equivalent. */
for (i = 0; i < xspan; i++) {
buffer[drawpos] = color;
sum += yspan;
if (sum >= xspan) {
drawpos += yinc;
sum -= xspan;
}
drawpos += xinc;
}
}
CP.set ( x1, y1 ); //set new CP position
/* Unlock the surface. */
SDL_UnlockSurface(surf);
}
|
Suppose we wish to learn the behavior of some mathematical functions f(x) as x varies. For example, how does
for ( double x = 0; x < 4.0; x += 0.005 ) surf.lineTo ( (int) x, (int) f(x) ); |
![]() |
sx sy 1 |
![]() |
= | ![]() |
a 0 c 0 b d 0 0 1 |
![]() |
![]() |
x y 1 |
![]() |
double f ( double x )
{
double y = exp ( -fabs ( x ) ) * cos ( 2 * 3.1415926 * x );
return y;
}
|
int sx, sy;
double x, y, a, b, c, d;
a = VWIDTH / 4.0;
c = 0;
b = -VHEIGHT / 2.0;
d = VHEIGHT / 2.0;
x = 0.0; //initial position
y = f ( 0.0 );
sx = (int) ( a * x + c );
sy = (int) ( b * y + d );
surf.moveTo ( sx, sy );
for ( x = 0; x < 4.0; x += 0.005 ) {
y = f ( x );
sx = (int) ( a * x + c );
sy = (int) ( b * y + d );
surf.lineTo ( sx, sy );
}
|
|
Turtle graphics is a style of computer drawing based on preserved state (position and orientation) and a small number of operations against that state (forward, turn, pen up & down).
The state was called the turtle and programs taught the turtle how to draw.
Easy for kids to pick up.
to draw-a-box forward 10 turn 90 forward 10 turn 90 forward 10 turn 90 forward 10 turn 90 to draw-a-window draw-a-box turn 90 draw-a-box turn 90 draw-a-box turn 90 draw-a-box turn 90 |
![]() |
![]() |
![]() |
A coding example: drawing a hook
|
|
Class exercise: