## Monday, January 23, 2012

### Drawing a Circle with Mid – Point Circle Algorithm in C/C++

As in the previous line drawing algorithm, we sample at unit intervals and determine the closest pixel position to the specified circle path at each step. For a given radius r and screen center position (xc, yc), we can first set up our algorithm to calculate pixel positions around a circle path centered at the coordinate origin (0, 0). Then each calculated  position (x, y) is moved to its proper screen position by adding xc to x and yc to y. Along the circle section from x = 0 to x = y in the first quadrant, the slope of the curve varies from 0 to –1.  Therefore, we can take unit steps in the positive x direction over this octant and use a decision parameter to determine which of the two possible y positions is closer to the circle path at each step. Position in the other seven octants are then obtained by symmetry.

The following section implements Mid – Point Cicle  Algorithm in C/C++. The source code is complied using gcc Compiler and Code::Blocks IDE. To print a pixel, SetPixel() function of windows.h is used.
Note: to run this code in your machine with Code::blocks IDE, add a link library libgdi32.a (it is usually inside MinGW\lib )  in linker setting.
Souce Code
#include <windows.h>
#include <cmath>
#define ROUND(a) ((int) (a + 0.5))
/* set window handle */
static HWND sHwnd;
static COLORREF redColor=RGB(255,0,0);
static COLORREF blueColor=RGB(0,0,255);
static COLORREF greenColor=RGB(0,255,0);

void SetWindowHandle(HWND hwnd){
sHwnd=hwnd;
}

/* SetPixel */
void setPixel(int x,int y,COLORREF& color=redColor){
if(sHwnd==NULL){
MessageBox(NULL,"sHwnd was not initialized !","Error",MB_OK|MB_ICONERROR);
exit(0);
}
HDC hdc=GetDC(sHwnd);
SetPixel(hdc,x,y,color);
ReleaseDC(sHwnd,hdc);
return;
}

void circlePoints(int xCenter, int yCenter, int x, int y){
setPixel(xCenter + x, yCenter + y);
setPixel(xCenter - x, yCenter + y);
setPixel(xCenter + x, yCenter - y);
setPixel(xCenter - x, yCenter - y);
setPixel(xCenter + y, yCenter + x);
setPixel(xCenter - y, yCenter + x);
setPixel(xCenter + y, yCenter - x);
setPixel(xCenter - y, yCenter - x);

}
void drawCircle(int xCenter, int yCenter, int radius){
int x = 0;
int p = 1 - radius;
circlePoints(xCenter, yCenter, x, y);
while(x < y){
x++;
if (p < 0){
p += 2 * x + 1;
}else{
y--;
p += 2 * (x - y) + 1;
}
circlePoints(xCenter, yCenter, x, y);
}
}
/* Window Procedure WndProc */
LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam){
switch(message){
case WM_PAINT:
SetWindowHandle(hwnd);
drawCircle(200, 200, 100);
break;
case WM_CLOSE: // FAIL THROUGH to call DefWindowProc
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
break; // FAIL to call DefWindowProc //
}
return DefWindowProc(hwnd,message,wParam,lParam);
}

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int iCmdShow){
static TCHAR szAppName[] = TEXT("Circle");
WNDCLASS wndclass;
wndclass.style         = CS_HREDRAW|CS_VREDRAW ;
wndclass.lpfnWndProc   = WndProc ;
wndclass.cbClsExtra    = 0 ;
wndclass.cbWndExtra    = 0 ;
wndclass.hInstance     = hInstance ;
wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszClassName = szAppName ;

// Register the window //
if(!RegisterClass(&wndclass)){
MessageBox(NULL,"Registering the class failled","Error",MB_OK|MB_ICONERROR);
exit(0);
}

// CreateWindow //
HWND hwnd=CreateWindow(szAppName,"Mid Point Circle Drawing - Programming Techniques",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL);
if(!hwnd){
MessageBox(NULL,"Window Creation Failed!","Error",MB_OK);
exit(0);
}
// ShowWindow and UpdateWindow //
ShowWindow(hwnd,iCmdShow);
UpdateWindow(hwnd);

// Message Loop //
MSG msg;
while(GetMessage(&msg,NULL,0,0)){
TranslateMessage(&msg);
DispatchMessage(&msg);
}

/* return no error to the operating system */
return 0;
}


Output