圆的Bresenham算法的opengL实现

来源:互联网 发布:如皋 java培训学校 编辑:程序博客网 时间:2024/04/26 03:05

源代码实现如下:

// Bresenham_circile.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include<stdlib.h>#include <GL/glut.h>/* initialization: */void myinit(void){ /* attributes */      glClearColor(1.0, 1.0, 1.0, 0.0); /* white background */      glColor3f(1.0, 0.0, 0.0); /* draw in red *//* set up viewing: *//* 500 x 500 window with origin lower left */      glMatrixMode(GL_PROJECTION);      glLoadIdentity();      gluOrtho2D(0.0, 500.0, 0.0, 500.0);      glMatrixMode(GL_MODELVIEW);}void  plot_circle_points(int xc,int yc,int x,int y){      glBegin(GL_POINTS);      glVertex3f(xc+x,yc+y,0);       glVertex3f(xc-x,yc+y,0);      glVertex3f(xc+x,yc-y,0);      glVertex3f(xc-x,yc-y,0);      glVertex3f(xc+y,yc+x,0);      glVertex3f(xc-y,yc+x,0);      glVertex3f(xc+y,yc-x,0);      glVertex3f(xc-y,yc-x,0);      glEnd();     }void drawcircle(int xc,int yc,int radius){     int x,y,p;     x=0;     y=radius;     p=3-2*radius;     glClear(GL_COLOR_BUFFER_BIT);     glBegin(GL_POINTS);     while(x<y)     {          plot_circle_points(xc,yc,x,y);          if(p<0)                 p=p+4*x+6;          else          {                 p=p+4*(x-y)+10;                 y-=1;                           }          x+=1;               }          if(x==y)          plot_circle_points(xc,yc,x,y);}/* the display callback: */void display( void ){    glClear(GL_COLOR_BUFFER_BIT);  /*clear the window */    /*----------------------------------------*/    /*  viewport stuff                        */    /*----------------------------------------*/    /* set up a viewport in the screen window */    /* args to glViewport are left, bottom, width, height */    glViewport(0, 0, 500, 500);    /* NB: default viewport has same coords as in myinit, */    /* so this could be omitted: */      drawcircle(200,200,100);    /* and flush that buffer to the screen */    glFlush();  }int main(int argc, char** argv){/* Standard GLUT initialization */    glutInit(&argc,argv);    glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); /* default, not needed */    glutInitWindowSize(500,500); /* 500 x 500 pixel window */    glutInitWindowPosition(0,0); /* place window top left on display */    glutCreateWindow("Bresenham  circile"); /* window title */    glutDisplayFunc(display); /* display callback invoked when window opened */     myinit(); /* set attributes */    glutMainLoop(); /* enter event loop */}

 

 

 

 设要显示圆的圆心在原点(0,0),半径为R,初始点的坐标为(0,R),顺时针生成八分之一圆,令:F(x,y)=x2+y2-R2

  则圆的方程为:

F(x,y)=0(2-27)

当点(x,y)在圆内时,则F(x,y)<0;
当点(x,y)在圆外时,则F(x,y)>0;
当点(x,y)在圆上时,则F(x,y)=0;

现以下图的AB弧为例,来说明正负画圆法(顺时针生成圆)。

  假设当前点为Pi(xi,yi),取下一个点Pi+1(xi+1,yi+1)的原则是:
  1、当F(xi,yi)≤0时:取xi+1= xi+1,yi+1= yi。即向走一步,从圆内走向圆外。对应图(a)中的从PiPi+1
  2、当F(xi,yi)>0时:取xi+1= xi,yi+1= yi-1。即向走一步,从圆外走向圆内。对应图(b)中的从PiPi+1

  由于向圆内或向圆外走取决于F(xi,yi)的正负,因此称为正负法。

  下面分两种情况求出F(xi,yi)的递推公式:
  (1) 当F(xi,yi)≤0时,向右走,取xi+1=xi+1,yi+1=yi,则

F(xi+1,yi+1)
=F(xi+1,yi)
=(xi+1)2+yi2-R2
=(xi2+yi2-R2)+2xi+1
= F(xi,yi)+2xi+1
(2-28)

  (2) 当F(xi,yi)>0时,向下走,取xi+1=xi,yi+1=yi-1,则

F(xi+1,yi+1)
=F(xi,yi-1)
=xi2+(yi-1)2-R2
=(xi2+yi2-R2)-2yi+1
= F(xi,yi)-2yi+1
(2-29)

  初始时,x=0,y=R,故

F(0,R)=(02+R2)-R2=0(2-30)

  公式(2-28)、(2-29)和(2-30)就构成正负画圆算法的核心。

  给象素坐标(x,y)及F赋初始值后,进入循环画点;

  画点后,根据F的符号进行F值的递推和下一个点的获取,直到x>y为止。

  同前面介绍的一样,利用圆的八分对称性,循环一次,画八个点。

注意:初值不同、圆的生成方向不同时,当前点和下一个点的获取原则是不同的,见下图。

  例如,初始点(R,0),逆时针生成圆,从图(b)可知:

  若当前点Pi在圆内,则下一点Pi+1(xi,yi+1),即向走一步;
  若当前点Pi在圆外,则下一点Pi+1(xi-1,yi),即向走一步;

(a) 顺时针生成圆        (b) 逆时针生成圆

 


// 顺时针生成圆
void PNARC(int x0,int y0,int r,int color)
{
 int x=0,y=r,f=0;
 while(x<=y)
 {
  putdot(x0,y0,x,y,color);
  if(f<=0)
  {
   f=f+2*x+1;
   x++;
  }
  else
  {
   f=f-2*y+1;
   y--;
  }
 }