Bersenham Circle Algorithm demonstrated using Win32 SetPixel

NicAx64 2 Tallied Votes 493 Views Share

circle.h

//
// circle.h
//  defines the functions to draw circle.
//

#ifndef CIRCLE_H
#define CIRCLE_H

#include <windows.h>

typedef struct tagCircle
{
  int x;
  int y;
  int radius;
} Circle;


/* set the window handle */
void SetWindowHandle(HWND);

/* set pixel 
  @parms int x xposition
  @parms int y yposition
  @parms Color color of the pixel.
  @returns void
*/
void Circle_SetPixel(int,int,COLORREF&);


/* circle dawing function
   
   @parms int x x position of the circle to be drawn
   @parms int y center y position.
   @parms int radius radius of the circle.

 */
void DrawCircle(int,int,int);

#endif // END CIRCLE_H

circle.cpp

#include <windows.h>
#include "circle.h"

/* set window handle */
static HWND sHwnd;
void SetWindowHandle(HWND hwnd)
{
  sHwnd=hwnd; 
}

static COLORREF sDefaultColor=RGB(255,0,0);

/* SetPixel */
void Circle_SetPixel(int x,int y,COLORREF& color=sDefaultColor)
{
  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;
  // NEVERREACH //
}

#define PLOT_ALL_EIGHT(x,y,x1,y1)  { Circle_SetPixel(x+x1,y+y1);Circle_SetPixel(y+x1,x+y1);\
                                    Circle_SetPixel(-x+x1,y+y1);Circle_SetPixel(-y+x1,x+y1);\
                                    Circle_SetPixel(-x+x1,-y+y1);Circle_SetPixel(-y+x1,-x+y1);\
                                    Circle_SetPixel(x+x1,-y+y1);Circle_SetPixel(y+x1,-x+y1);}


/* DrawCircle */
void DrawCircle(int x,int y,int radius)
{
  int yk =radius;
  int xk=0;
  double pk=5.0/4-radius;   // you may wonder why I used the double floating point arithmetic here.
                            // the answer is in modern computing architecture encourages the use of floating 
                            // point math.

  while(yk>=xk)
  {
    PLOT_ALL_EIGHT(xk,yk,x,y)
    if(pk>=0)
    {
      pk+=2*xk -2*yk +5;
      xk=xk+1;
      yk=yk-1;
    }else
    {
      pk+=2*xk+3;
      xk=xk+1;
      yk=yk;
    }    
  }  
}

main.cpp

//
// main.cpp
//   The file that consists the WinMain and the WndProc. 
//   
//
#include <windows.h>
#include "circle.h"


/* forward declarations */
LRESULT CALLBACK WndProc(HWND,UINT,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.lpszMenuName  = NULL ;
     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,"Circle Algorithm",
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;
}



/* Window Procedure WndProc */
LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
  switch(message)
  {
    
    case WM_PAINT:
       SetWindowHandle(hwnd);
       DrawCircle(100,100,100);
       return 0;    
    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);
}

compile.bat

echo off
g++ -c -o main.o main.cpp -g
g++ -c -o circle.o circle.cpp -g
REM linking........
g++ -o circle_algorithm.exe main.o circle.o -mwindows -g
echo on

please note that you need mingw installed and your paths have been setten inorder to use compile.bat directly. Otherwise modify the compile.bat to compile it using microsoft C++ compiler cl.exe.


--Happy Coding--