圆的生成

这里仅讨论圆心位于坐标原点的圆的扫描转换算法,对于圆心不在原点的圆,可先用平移变换,将它的圆心平移到原点,然后进行扫描转换,最后再平移到原来的位置。

  有几种较容易的方法可以得到圆的扫描转换,但是效率都不高。例如:直角坐标法和极坐标法:

  1、直角坐标法

  圆的直角坐标方程为 x2+y2=R2
  若取x作为自变量,解出y,得到

(2-17)

  我们可以先扫描转换四分之一的圆周。让自变量x从0到R以单位步长增加,在每一步时可解出y,然后调用画点函数即可逐点画出圆。但这样做,由于有乘方和平方根运算,并且都是浮点运算,算法效率不高。而且当x接近R值时(圆心在原点),在圆周上的点(R,0)附近,由于圆的斜率趋于无穷大,使得圆周上有较大的间隙。

  2、极坐标法

  假设圆周上一点P(x,y)处的半径与x轴的夹角为θ,则圆的极坐标方程为

 x=Rcosθ
y=Rsinθ
(2-18)

  利用下面将要介绍的圆周上点的对称性,那么自变量θ的取值范围就是(0,45°)。这个方法涉及三角函数计算和乘法运算,计算量较大。因此,也不是一种有效的方法。

一、 圆的八分对称性

圆心位于原点的圆有四条对称轴x=0、y=0、x=y和x=-y,见下图。从而若已知圆弧上一点P(x,y),就可以得到其关于四条对称轴的七个对称点,这种性质称为八分对称性。因此只要能画出八分之一的圆弧,就可以利用对称性的原理得到整个圆弧。下面的函数CirclePoints()用来显示P(x,y)及其七个对称点。    

  void CirclePoints(x,y,color)
  int x,y,color;
   {
    putpixel(x,y,color);
    putpixel(x,-y,color);
    putpixel(-x,y,color);
    putpixel(-x,-y,color);
    putpixel(y,x,color);
    putpixel(y,-x,color);
    putpixel(-y,x,color);
    putpixel(-y,-x,color);
   }

圆的八分对称性

注意:

  当圆心不在原点时,只须在putpixel()函数中加上平移量x0、y0(圆心坐标)即可。

例如:

  当 x0=300,y0=200时,则:

        …
  putpixel(x0+x,y0+y,color);
  putpixel(x0+x,y0-y,color);
  putpixel(x0-x,y0+y,color);
  putpixel(x0-x,y0-y,color);
  putpixel(x0+y,y0+x,color);
  putpixel(x0+y,y0-x,color);
  putpixel(x0-y,y0+x,color);
  putpixel(x0-y,y0-x,color);
        …

二、中点算法生成圆

中点画圆算法在一个方向上取单位间隔,在另一个方向的取值由两种可能取值的中点离圆的远近而定。实际处理中,用决策变量的符号来确定象素点的选择,因此算法效率较高。

  (一)、中点画圆算法描述

  设要显示圆的圆心在原点(0,0),半径为R,起点在(0,R)处,终点在()处,顺时针生成八分之一圆,利用对称性扫描转换全部圆。

  为了应用中点画圆法,我们定义一个圆函数

F(x,y)=x2+y2-R2(2-19)

  任何点(x,y)的相对位置可由圆函数的符号来检测:

F(x,y)<0 点(x,y)位于数学圆内
=0 点(x,y)位于数学圆上
>0 点(x,y)位于数学圆外
(2-20)

  如下图所示,图中有两条圆弧AB,假定当前取点为Pi(xi,yi),如果顺时针生成圆,那么下一点只能取正右方的点E(xi+1,yi)或右下方的点SE(xi+1,yi-1)两者之一。

中点画线算法

  假设MESE的中点,即 ,则:

  1、当 F(M) <0时, M在圆内(圆弧 A),这说明点E距离圆更近,应取点 E作为下一象素点;
  2、当 F(M) >0时, M在圆外(圆弧 B),表明 SE点离圆更近,应取 SE点;
  3、当 F(M) =0时,在 E点SE点之中随便取一个即可,我们约定取 SE点

  (二)、中点画圆算法思想

  因此,我们用中点M的圆函数作为决策变量di,同时用增量法来迭代计算下一个中点M的决策变量di+1

(2-21)

  下面分两种情况来讨论在迭代计算中决策变量di+1的推导。

  1、见图(a),若di<0,则选择E点,接着下一个中点就是,这时新的决策变量为:

(2-22)

(a)(di<0) 中点画线算法


  式(2-22)减去(2-21)得:

di+1=di+2xi+3(2-23)

  2、见图(b),若di≥0,则选择SE点,接着下一个中点就是 ,这时新的决策变量为:

(2-24)

(b)(di≥0) 中点画线算法

  式(2-24)减去(2-21)得:

di+1=di+2(xi-yi)+5(2-25)

  我们利用递推迭代计算这八分之一圆弧上的每个点,每次迭代需要两步处理:
   (1)用前一次迭代算出的决策变量的符号来决定本次选择的点。
   (2)对本次选择的点,重新递推计算得出新的决策变量的值。

  剩下的问题是计算初始决策变量d0,如下图所示。对于初始点(0,R),顺时针生成八分之一圆,下一个中点M的坐标是 ,所以:

(2-26)

生成圆的初始条件和圆的生成方向

  (三)、中点画圆算法实现

  1、输入:圆半径r、圆心(x0,y0);
  2、确定初值:x=0,y=r、d=5/4-r;
  3、While(x<=y)
   {
    ·利用八分对称性,用规定的颜色color画八个象素点(x,y);
    · 若d≥0
      {
       y=y-1;
       d=d+2(x-y)+5);
      }
     否则
       d=d+2x+3;
    ·x=x+1;
   }

s

  (四)、中点画圆算法完善

  在上述算法中,使用了浮点数来表示决策变量d。为了简化算法,摆脱浮点数,在算法中全部使用整数,我们使用e=d-1/4代替d。显然,初值d=5/4-r对应于e=1-r。决策变量d<0对应于e<-1/4。算法中其它与d有关的式子可把d直接换成e。又由于e的初值为整数,且在运算过程中的迭代值也是整数,故e始终是整数,所以e<-1/4等价于e<0。因此,可以写出完全用整数实现的中点画圆算法。
  要求:写出用整数实现的中点画圆算法程序,并上机调试,观看运行结果。

  (五)、中点画圆算法程序

void MidpointCircle(int x0,int y0,int r,int color)
{
 int x,y;
 float d;
 x=0;
 y=r;
 d=5.0/4-r;

 while(x<=y)
 {
  putdot(x0,y0,x,y,color);
  if(d<0)
  d+=x*2.0+3;
  else
  {
   d+=2.0*(x-y)+5;
   y--;
  } 
  x++;
 }
}

putdot(x0,y0,x,y,color)
{
 putpixel(x0+x,y0+y,color);
 putpixel(x0+x,y0-y,color);
 putpixel(x0-x,y0+y,color);
 putpixel(x0-x,y0-y,color);
 putpixel(x0+y,y0+x,color);
 putpixel(x0+y,y0-x,color);
 putpixel(x0-y,y0+x,color);
 putpixel(x0-y,y0-x,color);
}


 

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值