计算机图形学
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

3.2 圆与椭圆图形

3.2.1 简单方程产生圆弧

用圆的参数方程,直接计算离散点值。圆的参数方程为

x=x0+rcosθ y=y0+rsinθ

式中,x0y0为圆的圆心坐标,r为圆的半径。

对以上方程进行离散化:

xi=x0+rcosθi

yi=y0+rsinθi

这里关键的问题是θi+1与θi的关系,即θi+1=θi+d中的d如何确定。如果使用画点生成圆,则d与圆的半径r相关,r越大,圆的周长就长,圆周上的像素点就多,对于固定范围内的θ,d就越小。根据圆周长公式,取d=1/(2πr)。因此离散化后圆的参数取值如下:

θ0=0,θi+1=θi+1/(2πr)i=0, 1, 2,…,直到θi=2π时结束,直到θi=2π时结束

其VC主要程序代码为:

CDC∗pDC=GetDC();
d=0.5/r/3.14;
for(t=0;t<6.283;t=t+d)
{    x=x0+r∗cos(t);
     y=y0+r∗sin(t);
     pDC->SetPixel (x,y,RGB(0,0,0));
}

此方法算法简单,但算法效率不高,有小数及函数运算,不易硬件实现。

3.2.2 中点画圆算法

1.八分法画圆

为了方便,我们只考虑中心在原点、半径为整数R的八分圆,圆的其他部分可通过一系列的简单反射变换得到,如图3-12所示。设已知一个圆心在原点的圆上一点(xy),根据对称性可得另外7个八分圆上的对应点(yx),(y,-x),(x,-y),(-x,-y),(-y,-x),(-yx),(-xy)。

对于中心不在原点的圆,可先对中心在原点的圆进行扫描转换,最后把所得的像素坐标加上圆的中心坐标即得所求像素坐标。

2.中点画圆算法基本原理

考虑如图3-13所示的八分圆的生成。讨论从(0,R)到()顺时针圆弧的像素序列生成。假定与圆弧最近的Pxy)像素已确定,那么下一个像素只能是正右方的P1x+1,y)或右下方的P2x+1,y-1)两者之一,如图3-14所示。

图3-12 圆的对称性

图3-13 八分圆示意图

图3-14 当前像素与下一像素的候选者

3.中点画圆算法的基本判别式

构造一个误差判别函数:F(x,y)=x2+y2-R2

对于圆上的点,Fxy)=0;对于圆外的点,Fxy)>0;对于圆内的点,Fxy)<0。

MPlP2的中点,M=(xi+1,yi-0.5)。当FM)<0时,M在圆内,P1离圆弧更近,应取P1作为下一像素。当FM)>0时,P2离圆弧更近,应取P2。当FM)=0时,在PlP2之中随便取一个即可,约定取P2

与中点画线算法一样,构造判别式为

di=F(M)=F(xi+1,yi-0.5)=(xi+1)2+(yi-0.5)2-R2

4.中点画圆算法的递推公式

di<0,应取P1为下一像素,而且下一个像素的判别式为

di+1=F(xi+2,yi-0.5)=(xi+2)2+(yi-0.5)2-R2=di+2xi+3

di≥0,则P2是下一像素,而且下一像素的判别式为

di+1=F(xi+2,yi-1.5)=(xi+2)2+(yi-1.5)2-R2=di+2xi+2yi+5

由于第1个像素是(0,R),判别式di的初始值为:

d0=F(1,R-0.5)=1+(R-0.5)2-R2=1.25-R

根据上述分析,可写出中点画圆算法的递推公式如下:

d0=1.25-R,x0=0,y0=R

di<0:di+1=di+2xi+3,xi+1=xi+1

di≥0:di+1=di+2xi-2yi+5,xi+1=xi+1,yi+1=yi-1(i=0,1,2,…,直到xy为止)

5.消除小数运算

在上述算法中,d使用了浮点数表示。为了摆脱浮点数,在算法中全部使用整数,使用e0=d0-0.25代替d0

初始化运算d0=1.25-R对应于e0=1-R

判别式di<0对应于ei<-0.25,又由于e的初值为整数,且在运算过程中的增量也是整数,故e始终是整数,所以ei<-0.25等价于ei<0。

其他与d有关的式子可把d直接换成e。因此,可以写出完全用整数实现的中点画圆算法。算法中e仍用d来表示。

d0=1-R,x0=0,y0=R

di<0:di+1=di+2xi+3,xi+1=xi+1

di≥0:di+1=di+2xi-2yi+5,xi+1=xi+1,yi+1=yi-1(i=0,1,2,…,直到xy为止)

6.程序设计

中点画圆算法画圆弧的VC主要程序代码如下:

CDC.pDC=GetDC();
d=1-r; x=0; y=r; // r为圆的半径
while(y>=x)
{ pDC->SetPixel (x+x0,y+y0,RGB(0,0,0)); //(x0,y0)为圆心坐标
    pDC->SetPixel (-x+x0,y+y0,RGB(0,0,0));
    pDC->SetPixel (-x+x0,-y+y0,RGB(0,0,0));
    pDC->SetPixel (x+x0,-y+y0,RGB(0,0,0));
    pDC->SetPixel (y+x0,x+y0,RGB(0,0,0));
    pDC->SetPixel (-y+x0,x+y0,RGB(0,0,0));
    pDC->SetPixel (-y+x0,-x+y0,RGB(0,0,0));
    pDC->SetPixel (y+x0,-x+y0,RGB(0,0,0));
    x=x+1;
    if(d<0)
    d=d+2.x+3;
    else
      d=d+2.(x-y)+5, y--;
}

x0=100,y0=100,r=80,该程序的运行效果如图3-15所示。

图3-15 中点法绘制圆弧效果示意图

3.2.3 Bresenham画圆算法

Bresenham画圆算法的基本思想是寻找最接近于实际圆周上的点。与中点画圆算法相似,考虑圆心在原点,半径为R的八分圆,取(0,R)为起点,按顺时针方向生成圆。如图3-16所示,对于Pi的下一点Pi+1只有两种可能,即Sxi+1,yi)和Txi+1,yi-1)。

1.基本判别式

根据圆的公式:x2+y2=R2

误差公式:

D(S)=(xi+1)2+(yi)2-R2

D(T)=(xi+1)2+(yi=1)2-R2

图3-16 Bresenham画圆算法判别式推导示意图

当|DS)|≥|DT)|,则T更接近于圆周,选择T

当|DS)|<|DT)|,则S更接近于圆周,选择S

di=|D(S)|-|D(T)|,则di≥0,取Tdi<0,取S

由于判别式的di计算较复杂,因此要进行简化。

2.简化判别式

ST像素中,与理想圆弧最近者为所求像素。理想圆弧与这两个候选点之间的关系有以下几种情况:

情况CS在圆外,所以DS)>0;T在圆内,所以DT)<0。因此判别式可简化为di=D(S)+D(T)。

下面分析一下其他情况是否可用此判别式。

情况ABST都在圆内或圆上,即DS) ≤ 0,DT)<0,所以判别式di=D(S)+D(T)<0,取S。从图3-16中可以看出S更接近圆周,选择S是对的。

情况DEST都在圆外或圆上,即DS)>0,DT)≥0,所以判别式di=DS)+DT)>0,取T。从图3-16中可以看出T更接近圆周,选择T是对的。

综上所述,只要计算出di=D(S)+D(T)的符号,便可确定是选S还是选T作为下一点。

3.判别式的递推公式

x0=0,y0=R

d0=D(S)+D(T)=(12+R2-R2)+[12+(R-1)2-R2]=3-2R

Pi为(xiyi),则

di=[(xi+1)2+yi2-R2]+[(xi+1)2+(yi-1)2-R2]

di<0,取S作为下一点,则

di+1=[(xi+2)2+(yi)2-R2]+[(xi+2)2+(yi-1)2-R2]

di+1=di+4xi+6

di≥0,则取T作为下一点,则

di+1=[(xi+2)2+(yi-1)2-R2]+[(xi+2)2+(yi-2)2-R2]

di+1=di+4(xi-yi)+10

即Bresenham画圆算法的递归式为

d0=3-2R(x0=0,y0=R)

di<0时,

di+1=di+4(xi-yi)+6,xi+1=xi+1

di≥0时,di+1=di+4(xi-yi)+10,xi+1=xi+1,yi+1=yi-1 (i=0,1,2,…,直到yx为止),直到yx为止)

4.程序设计

Bresenham画圆算法绘制八分圆的VC主要代码如下:

3.2.4 椭圆算法

中点画圆算法可以推广到一般二次曲线的生成。下面讨论如何利用这种方法,对图3-17所示的标准椭圆进行扫描转换。

1.椭圆的特征

圆心在原点的椭圆方程为:

F(x,y)=b2x2+a2y2-a2b2=0

对于椭圆上的点,Fxy)=0

对于椭圆外的点,Fxy)>0

对于椭圆内的点,Fxy)<0

由于椭圆的对称性,所以只需讨论第1象限椭圆弧的生成。在处理这段椭圆弧时,要把它分为两部分:上部分和下部分。以圆弧上斜率为1的点(即法矢量两个分量相等的点)作为分界来讨论,如图3-18所示。

椭圆上某一点(xy)处的法矢量为:

式中,ij分别为沿x轴和y轴方向的单位矢量。由图3-18知,在上部分,法矢量的y分量更大;而在下部分,法矢量的x分量更大。因此,若在当前中点,法矢量(2b2xp+1),2a2yp-0.5))的y分量比x分量大,即

b2xp+1)<a2yp-0.5)

而在下一个中点,不等号改变方向,则说明椭圆弧从上部分转入下部分。

图3-17 中心在原点的标准椭圆

图3-18 第1象限的椭圆弧

2.绘制椭圆的中点算法

绘制椭圆的中点算法与中点画圆算法类似,当确定一个像素之后,接着可在两个候选像素的中点计算一个判别式的值,并根据判别式符号确定两个候选像素哪个离椭圆更近。

(1) 上部分的算法判别式。先看椭圆弧的上部分,如图3-19所示,当前与椭圆弧最接近者是Pixiyi),下一对候选像素的中点是Mxi+1,yi-0.5)。

判别式为

di=F(xi+1,yi-0.5)=b2(xi+1)2+a2(yi-0.5)2-a2b2

di<0,中点在椭圆内,则应取正右方像素,且判别式递推公式为

di≥0,中点在椭圆之外,则应取右下方像素,且判别式递推公式为

(2) 判别式的初始值。由于弧的起点为(0,b),因此,第1个中点是(1,b-0.5),对应的判别式是

(3) 下部分的算法判别式。如图3-20所示,在下部分,当与椭圆弧最接近的像素是Pixiyi)时,那么下一对候选像素应为正下方和右下方两个像素,中点是Mxi+0.5,yi-1)。所以当判别式di=Fxi

时,取右下方像素,下一点的判别式为

di≥0取正下方像素,下一点的判别式为

图3-19 上部分的中点示意图

图3-20 下部分的中点示意图

(4) 第1象限椭圆弧中点算法。

x0=0,y0=bd0=b2+a2(0.25-b

当2b2xi+1)<2a2yi-0.5)时,

当2b2xi+1)>2a2yi-0.5)时,

(5) 程序设计(略)。

程序的运行效果如图3-21所示。

3.圆弧线宽的处理

为了生成具有宽度的圆弧,可采用与直线情形类似的方法。

当采用线刷子时,在经过曲线斜率为±1的点时,必须把线刷子在水平与垂直方向之间切换。由于线刷子总是放置成水平或垂直的,所以在曲线接近水平与垂直的地方,线条更粗一些,而在斜率接近±1的点附近,线条更细一些,如图3-22所示。

图3-21 中点法绘制椭圆效果示意图

当采用正方形刷子时,无须移动刷子方向。只需顺着单像素宽的轨迹,把正方形中心对准轨迹上的像素,把方形内的像素全部用线条颜色填充。用正方形刷子绘制的曲线条,在接近水平与垂直的部分最细,而在斜率为±1的点附近最粗,这恰与线刷子画线的情形相反,如图3-23所示。

图3-22 用线刷子绘制的圆弧

图3-23 用正方形刷子绘制的圆弧