📜  计算机图形学布雷森汉姆圆算法

📅  最后修改于: 2020-12-20 09:33:22             🧑  作者: Mango

布雷森汉姆的循环算法:

使用Bresenham算法对圆进行扫描转换的工作方式如下:点从90°到45°生成,将仅沿+ x&-y方向移动,如图所示:

真实圆的最佳近似将由栅格中与真实圆的距离最小的那些像素描述。我们想从中产生点

90°至45°。假定最后的经扫描转换的像素是P 1 ,如图2所示。通过执行以下两个操作之一,可以找到最接近真实圆的每个新点。

  • 在x方向上移动一个单位或
  • 在x方向上移动一个单位,在y方向上移动一个负数。

令D(S i )是从原点到真圆平方的距离减去到点P 3平方的距离。 D(T i )是从原点到真圆平方的距离减去到点P 2平方的距离。因此,出现以下表达式。

D(S i )=(x i-1 +1) 2 + y i-1 2 -r 2
D(T i )=(x i-1 +1) 2 +(y i-1 -1) 2 -r 2

由于D(S i )将始终为+ ve&D(T i )将始终为-ve,因此可以将决策变量d定义如下:

d i = D(S i )+ D(T i )

因此,
d i =(x i-1 +1) 2 + y i-1 2 -r 2 +(x i-1 +1) 2 +(y i-1 -1) 2 -r 2

根据这个方程,我们可以将d i的初始值驱动为

如果假定圆以原点为中心,则第一步x = 0&y = r。

因此,
d i =(0 + 1) 2 + r 2 -r 2 +(0 + 1) 2 +(r-1) 2 -r 2
= 1 + 1 + r 2 -2r + 1-r 2
= 3-2r

此后,如果d_i <0,则仅x递增。

x i + 1 = x i + 1 d i + 1 = d i + 4x i +6

&如果d≥0,则X和Y被递增
x i + 1 = x i + 1 y i + 1 = y i + 1
d i + 1 = d i + 4(x i -y i )+10

布雷森汉姆的循环算法:

步骤1:开始算法

步骤2:声明p,q,x,y,r,d变量
p,q是圆心的坐标
r是圆的半径

步骤3:输入r的值

步骤4:计算d = 3-2r

步骤5:初始化x = 0
&nbsy = r

步骤6:检查整个圆是否已扫描转换
如果x> = y
停止

第7步:使用八向对称性概念绘制八个点。中心位于(p,q)。当前有效像素为(x,y)。
像素(x + p,y + q)
putpixel(y + p,x + q)
像素(-y + p,x + q)
像素(-x + p,y + q)
像素(-x + p,-y + q)
putpixel(-y + p,-x + q)
putpixel(y + p,-x + q)
putpixel(x + p,-yq)

步骤8:找到下一个要扫描像素的位置
如果d <0
然后d = d + 4x + 6
增量x = x + 1
如果d≥0
然后d = d + 4(x-y)+ 10
增量x = x + 1
递减y = y-1

步骤9:前往步骤6

步骤10:停止算法

示例:使用Bresenham算法绘制6个圆点。圆弧半径为10个单位时。圆的中心为(50,50)。

解:令r = 10(给出)

步骤1:取得起点(0,10)
d = 3-2r
d = 3-2 * 10 = -17
d <0 d = d + 4x + 6
= -17 + 4(0)+ 6
= -11

步骤2:绘制(1,10)
d = d + 4x + 6(∵d <0)
= -11 + 4(1)+ 6
= -1

步骤3:绘制(2,10)
d = d + 4x + 6(∵d <0)
= -1 + 4 x 2 + 6
= 13

步骤4:绘制(3,9)d> 0,因此x = x + 1,y = y-1
d = d + 4(xy)+ 10(∵d> 0)
= 13 + 4(3-9)+ 10
= 13 + 4(-6)+ 10
= 23-24 = -1

步骤5:绘制(4,9)
d = -1 + 4x + 6
= -1 + 4(4)+ 6
= 21

步骤6:绘制(5,8)
d = d + 4(xy)+ 10(∵d> 0)
= 21 + 4(5-8)+ 10
= 21-12 + 10 = 19

所以P 1 (0,0)⟹(50,50)
P 2 (1,10)⟹(51,60)
P 3 (2,10)⟹(52,60)
P 4 (3,9)⟹(53,59)
P 5 (4,9)⟹(54,59)
P 6 (5,8)⟹(55,58)

使用Bresenham的圆图绘制算法绘制圆的程序:

#include 
#include 
#include 
#include 
#include 

    void    EightWaySymmetricPlot(int xc,int yc,int x,int y)
   {
    putpixel(x+xc,y+yc,RED);
    putpixel(x+xc,-y+yc,YELLOW);
    putpixel(-x+xc,-y+yc,GREEN);
    putpixel(-x+xc,y+yc,YELLOW);
    putpixel(y+xc,x+yc,12);
    putpixel(y+xc,-x+yc,14);
    putpixel(-y+xc,-x+yc,15);
    putpixel(-y+xc,x+yc,6);
   }

    void BresenhamCircle(int xc,int yc,int r)
   {
    int x=0,y=r,d=3-(2*r);
    EightWaySymmetricPlot(xc,yc,x,y);

    while(x<=y)
     {
      if(d<=0)
             {
        d=d+(4*x)+6;
      }
     else
      {
        d=d+(4*x)-(4*y)+10;
        y=y-1;
      }
       x=x+1;
       EightWaySymmetricPlot(xc,yc,x,y);
      }
    }

    int  main(void)
   {
    /* request auto detection */
    int xc,yc,r,gdriver = DETECT, gmode, errorcode;
    /* initialize graphics and local variables */
     initgraph(&gdriver, &gmode, "C:\\TURBOC3\\BGI");

     /* read result of initialization */
     errorcode = graphresult();

      if (errorcode != grOk)  /* an error occurred */
     {
        printf("Graphics error: %s\n", grapherrormsg(errorcode));
        printf("Press any key to halt:");
        getch();
        exit(1); /* terminate with an error code */
     }
       printf("Enter the values of xc and yc :");
       scanf("%d%d",&xc,&yc);
       printf("Enter the value of radius  :");
       scanf("%d",&r);
       BresenhamCircle(xc,yc,r);

     getch();
     closegraph();
     return 0;
    }

输出: