You are on page 1of 9

2.3.

1 Midpoint Circle Algorithm

Figure: Midpoint circle algorithm The midpoint circle algorithm of Bresenham [Bre77] and [BGP83] is analogously to that of straight lines and goes as follows:

and in the next step:

One can speed up things be calculating the linear increments recursively.

Mid-Point Circle Algorithm More Information #include<stdio.h> #include<conio.h> #include<graphics.h> void main() { int gd=DETECT,gm; int x,y,r;

void Drawcircle(int,int,int); printf("Enter the Mid points and Radious:"); scanf("%d%d%d",&x,&y,&r); initgraph(&gd,&gm,""); Drawcircle(x,y,r); getch(); closegraph(); } void Drawcircle(int x1,int y1,int r) { int x=0,y=r,p=1-r; void cliplot(int,int,int,int); cliplot(x1,y1,x,y); while(x<y) { x++; if(p<0) p+=2*x+1; else { y--; p+=2*(x-y)+1; } cliplot(x1,y1,x,y); } } void cliplot(int xctr,int yctr,int x,int y) { putpixel(xctr +x,yctr +y,1); putpixel(xctr -x,yctr +y,1); putpixel(xctr +x,yctr -y,1); putpixel(xctr -x,yctr -y,1); putpixel(xctr +y,yctr +x,1); putpixel(xctr -y,yctr +x,1); putpixel(xctr +y,yctr -x,1); putpixel(xctr -y,yctr -x,1); getch(); }

Terrain Tutorial

The Circles Algorithm


This algorithm is similar to the fault algorithm in the sense that some points are displaced upwards. The main differences reside in the way how the points are select and how the points are displaced. In the fault algorithm a line divided the terrain in two parts, points in one part where displaced upwards, whereas points in the other part where displaced downwards. In here a circle with a random center, and a user defined radius is computed. Points inside the circle are displaced upwards, whereas the remaining points will keep their height. The points inside the circle are displaced according to a cosine function as shown in the next figure

The next image shows a single iteration.

As you can see the algorithm is very simple. The first step is to find a random point which will be the center of the circle. Afterwards the points inside the circle are displaced using the following pseudocode.

for each terrain point (tx,tz) do pd = distance from circle center * 2 / terrainCircleSize if fabs(pd) <= 1.0 height(tx,tz) += disp/2 + cos(pd*3.14)*disp/2;

where terrainCircleSize defines the circle size and disp defines the maximum height variation. As in the fault algorithm, the value of disp can be decreased as the number of iterations increases. As usual there are endless variations to this algorithm, for instance try replacing the cosine with other functions. As an example, in the implementation provided, for each circle the height can be decreased or increased according to a random value, i.e. some iterations increase the height of the points inside the circle, whereas others will produce the symmetrical effect. The following image is a screen shot of a terrain rendered with this algorithm after 1000 iterations.

(Midpoint Circle Algorithm) Below is the circle routine that appears on page 102 of Hearn and Baker (modified slightly to work on my MAC).
void circleMidpoint(int xCenter, int yCenter, int radius){ int x = 0; int y = radius; int p = 1 - radius; void circlePlotPoints(int xCenter, int yCenter, int x, int y); /* Plot first set of points */ circlePlotPoints(xCenter, yCenter, x, y); while (x < y) {

x++; if (p < 0) p += 2*x + 1; else { y--; p += 2 * (x-y) + 1; } circlePlotPoints(xCenter, yCenter, x, y); } } void circlePlotPoints(int xCenter, int yCenter, int x, int y){ // SetColorPixel(x, y, r, g, b); sets the pixel (x, y) to rgb (r, g, b) SetColorPixel(xCenter + x, yCenter + y, 0, 0, 0); SetColorPixel(xCenter - x, yCenter + y, 0, 0, 0); SetColorPixel(xCenter + x, yCenter - y, 0, 0, 0); SetColorPixel(xCenter - x, yCenter - y, 0, 0, 0); SetColorPixel(xCenter + y, yCenter + x, 0, 0, 0); SetColorPixel(xCenter - y, yCenter + x, 0, 0, 0); SetColorPixel(xCenter + y, yCenter - x, 0, 0, 0); SetColorPixel(xCenter - y, yCenter - x, 0, 0, 0); }

Assume that you have a function:


void HLine(int x1, int x2, int y);

that efficiently draws the horizontal line from (x1, y) to (x2, y). For each of the shapes on below, show the changes you would make, to the circle code, to generate the shape shown. USE HLine.

Drawing Circle Explained


13 October 2007, 05:57 AM

Before

anything

else

examine

the

circles

below.

What

is

the

characteristic?

They are obviously round, which we describe a shape that is highly symmetrical and unchanging. The fact that a circle is symmetrical makes it very fitting for optimization. We can take advantage of this symmetry to implement fast circle plotter by calculating only the points in the first octant and copying those points to all other remaining octants. This is like cloning the first octant to produce the remaining seven while maintaining symmetry. The picture above-right can help to visualize this idea further. Examine each octant and we can immediately tell that they are all similar to each other. Finding the first octant is actually similar to finding all of the others. Because of this, the article will concentrate on the method of determining only the pixels in the first octant and replicating and mirroring it to get a full circle. We will begin with a make it work first kind of implementation. A slow, crunchy, unoptimized code that work just fine, all in the name of simplicty and understanding. But first let us revise the good ol circle function we can find in our text book:

For practical reason we will assume both x0 and y0 as zero to make our circle centered at location (0,0) and of course to make it simpler and easier to implement. Now arrange the equation further to get,

a function of x because we know r (radius) will always be constant. Let us now look at the unoptimized implementation of above equation. The following image after the code shows an actual plotting of nine circles with increasing radius, plotted using the code.
public void circle(int x,int y,int radius,int color) { int i = 0, j = radius ; while (i<=j) { putpixel(x+i,y-j,color) ; putpixel(x+j,y-i,color) ; putpixel(x+i,y+j,color) ; putpixel(x+j,y+i,color) ; putpixel(x-i,y-j,color) ; putpixel(x-j,y-i,color) ; putpixel(x-i,y+j,color) ; putpixel(x-j,y+i,color) ; i++ ; j = (int)(Math.sqrt(radius*radius - i*i) + 0.5) ;

} }

As we can see from the code there are eight instances of putpixel suggesting each calculated point is plotted eight times at different locations. The observant reader may notice that weird +0.5, wondering what the hell is it for? The extra addition is to avoid early rounding of variable j which causes a somewhat pointy version of the plotted circle, if not ugly. Actually it is just a matter of preference, try removing that +0.5 and see for yourself - who knows we might just have different definition for the word ugly circle. While the above implementation will work just fine, the presence of that expensive sqrt just made it tasteless. So the next thing we will do is to see how this costly calculation can be avoided by the use of discriminant equation. To explain this, lets get back to the drawing board and rearrange the circle equation,

Here the f(x,y) is a concept very useful in graphics programming called the discriminant function. It is used to partition or categorize f(x,y) based on the parameter x and y into, in our case, location of that point. If f(x,y) equals to zero, it means the point (x,y) is located on the right circle trajectory, a perfect pixel plot. If f(x,y) is below zero, the point (x,y) is inside the circle, while f(x,y) greater than zero would mean the point (x,y) is outside the circle. That may be a bit difficult to follow, but hopefully the diagram below will help give a better picture.

To draw our circle, we will be using x as the incrementing variable and y will be guessed for every x.

The initial value for x will be zero, and y equals to radius, satisfying the condition f(0,r) = 0. Now the term guessing y for every x goes like this, keep incrementing x until f(x,y) suggest that the point (x,y) is starting to move outside the circle. If a point is outside the circle, f(x,y) > 0, we can bring it back inside by decreasing y by one.

The equation above shows that if we increase x by one, the next discriminant will be equal to the previous discriminant + 2x + 1. We can use this equation to find the new discriminant for every x for unchanging y. If y changes, as in condition f(x,y) > 0, update the discriminant with,

Now there is still one more thing to consider, remember that +0.5 mentioned earlier? If we want to take that into consideration f(x,y) must not start at f(0,r)=0, but at f(1,r-0.5),

Once we have determined how to calculate f(x,y), f(x+1,y), f(x+1,y-1), and f(1,r-0.5) for all x, we can start implementing a fully optimized circle function. Notice that operator shift right >>, and shift left << are used to represent division and multiplication respectively. Here is the full implementation of a circle function,
public void circle(int x,int y,int radius,int color) { int discriminant = (5 - radius<<2)>>2 ; int i = 0, j = radius ; while (i<=j) { putpixel(x+i,y-j,color) ; putpixel(x+j,y-i,color) ; putpixel(x+i,y+j,color) ; putpixel(x+j,y+i,color) ; putpixel(x-i,y-j,color) ; putpixel(x-j,y-i,color) ; putpixel(x-i,y+j,color) ; putpixel(x-j,y+i,color) ; i++ ;

if (discriminant<0) { discriminant += (i<<1) + 1 ; } else { j-- ; discriminant += (1 + i - j)<<1 ; } } }

[edit] should be (1 + i - j)<<1 not 1+ (i - j)<<1

Midpoint Algorithm (Circular Arc)

Description This applet demonstrates the working of the midpoint algorithm in drawing a circular arc where the slope of the tangent is less than 1. The pixels in this region are represeted by circular regions. Select any blue-colored pixel on the left hand side of the window by clicking on it. The selected point defines the radius of the arc. A circular arc from this point is drawn using the midpoint algorithm. The candidate pixels at each stage are shown in yellow color.

Code (Midpoint Algorithm: Arc)

void arc(double rad){ int x2=(int)(rad*0.7071); int p=(int)(1.25-rad); int y=(int)rad; for (int x=0; x <=x2; x++) { setPixel(x, y); if(p > 0) { y--; p+ = 2*(x-y)+5; } else p+ = 2*x+3; } }
Computer Graphics

You might also like