计算机图形学画多边形(3)

2021-09-24 12:04

若d≥0,则应取P2为下一像素,而且下一像素的判别式为

d=F(x p+2, y p–1.5)= (x p+2)2+(y p–1.5)2–R2=d+2(x p–y p)+5

我们讨论按顺时针方向生成第二个八分圆,则第一个像素是(0, R),判别式d的初始值为

d0=F(1, R–0.5)=1.25–R

1.2.3 圆的Bresenham算法

设圆的半径为r,先考虑圆心在(0, 0),从x=0、y=r开始的顺时针方向的1/8圆周的生成过程。在这种情况下,x每步增加1,从x=0开始,到x=y结束,即有x i+1 = x i + 1;相应的,y i+1则在两种可能中选择:y i+1=y i或者y i+1= y i–1。选择的原则是考察精确值y是靠近y i还是靠近y i–1(见图1-7),计算式为

y2= r2–(x i+1)2

d1 = y i2–y2 = y i2–r2+(x i+1)2

d2 = y2– (y i–1)2 = r2–(x i+1)2–(y i–1)2

令p i=d1–d2,并代入d1、d2,则有

p i = 2(x i+1)2 + y i2+ (y i–1)2–2r2(1.6)

p i称为误差。如果p i<0,则y i+1=y i,否则y i+1=y i–1。

p i的递归式为

p i+1 = p i + 4x i +6+2(y i2+1–y i2)–2(y i+1–y i) (1.7)

p i的初值由式(1.6)代入x i=0,y i=r,得

p1 = 3–2r(1.8)

根据上面的推导,圆周生成算法思想如下:

(1)求误差初值,p1=3–2r,i=1,画点(0, r)。

(2)求下一个光栅位置,其中x i+1=x i+1,如果p i<0则y i+1=y i,否则y i+1=y i–1。

(3)画点(x i+1, y i+1)。

(4)计算下一个误差,如果p i<0则p i+1=p i+4x i+6,否则p i+1=p i+4(x i–y i)+10。

(5)i=i+1,如果x=y则结束,否则返回步骤(2)。

程序设计步骤如下。

(1)创建应用程序框架,以上面建立的单文档程序框架为基础。

(2)编辑菜单资源。

在工作区的ResourceView标签中,单击Menu项左边“+”,然后双击其子项IDR_MAINFRAME,并根据表1-3中的定义添加编辑菜单资源。此时建好的菜单如图1-8

所示。

表1-3 菜单资源表

(3)添加消息处理函数。

利用ClassWizard (建立类向导)为应用程序添加与菜单项相关的消息处理函数,ClassName 栏中选择CMyView ,根据表1-4建立如下的消息映射函数,ClassWizard 会自动完成有关的函数声明。

表1-4 菜单项的消息处理函数

(4)程序结构代码,在CMyView.cpp 文件中的相应位置添加如下代码。

void CMyView::OnMidpointcircle() //中点算法绘制圆,如图1-9所示

{

// TODO: Add your command handler code here

CDC* pDC=GetDC();

int xc=300, yc=300, r=50, c=0;

int x,y;

float d;

x=0; y=r; d=1.25-r;

pDC->SetPixel ((xc+x),(yc+y),c);

pDC->SetPixel ((xc-x),(yc+y),c);

pDC->SetPixel ((xc+x),(yc-y),c);

pDC->SetPixel ((xc-x),(yc-y),c);

pDC->SetPixel ((xc+y),(yc+x),c);

pDC->SetPixel ((xc-y),(yc+x),c);

pDC->SetPixel ((xc+y),(yc-x),c);

pDC->SetPixel ((xc-y),(yc-x),c);

while(x<=y)

{ if(d<0) d+=2*x+3;

else { d+=2*(x-y)+5; y--;}

x++;

pDC->SetPixel ((xc+x),(yc+y),c);

pDC->SetPixel ((xc-x),(yc+y),c); 图1-9 中点算法绘制圆

图1-8 程序主菜单

pDC->SetPixel ((xc+x),(yc-y),c);

pDC->SetPixel ((xc-x),(yc-y),c);

pDC->SetPixel ((xc+y),(yc+x),c);

pDC->SetPixel ((xc-y),(yc+x),c);

pDC->SetPixel ((xc+y),(yc-x),c);

pDC->SetPixel ((xc-y),(yc-x),c);

}

}

void CMyView::OnBresenhamcircle() //// Bresenham算法绘制圆,如图1-10所示{

CDC* pDC=GetDC();

int xc=100, yc=100, radius=50, c=0;

int x=0,y=radius,p=3-2*radius;

while(x<y)

{

pDC->SetPixel(xc+x, yc+y, c);

图1-10 Bresenham算法绘制圆pDC->SetPixel(xc-x, yc+y, c);

pDC->SetPixel(xc+x, yc-y, c);

pDC->SetPixel(xc-x, yc-y, c);

pDC->SetPixel(xc+y, yc+x, c);

pDC->SetPixel(xc-y, yc+x, c);

pDC->SetPixel(xc+y, yc-x, c);

pDC->SetPixel(xc-y, yc-x, c);

if (p<0)

p=p+4*x+6;

else

{

p=p+4*(x-y)+10;

y-=1;

}

x+=1;

}

if(x==y)

pDC->SetPixel(xc+x, yc+y, c);

pDC->SetPixel(xc-x, yc+y, c);

pDC->SetPixel(xc+x, yc-y, c);

pDC->SetPixel(xc-x, yc-y, c);

pDC->SetPixel(xc+y, yc+x, c);

pDC->SetPixel(xc-y, yc+x, c);

pDC->SetPixel(xc+y, yc-x, c);

pDC->SetPixel(xc-y, yc-x, c);

}

1.3 椭圆扫描转换中点算法

下面讨论椭圆的扫描转换中点算法,设椭圆为中心在坐标原点的标准椭圆,其方 程为 F (x , y )=b 2x 2+a 2y 2–a 2b 2=0

(1)对于椭圆上的点,有F (x , y )=0;

(2)对于椭圆外的点,F (x , y )>0;

(3)对于椭圆内的点,F (x , y )<0。

以弧上斜率为–1的点作为分界将第一象限椭圆弧分为上下两部分(如图1-11所示)。 法向量:

22(,)i j 2i 2j F F N x y b x a y x y ??=+=+??

22(1)(0.5)i i b x a y +<- 而在下一个点,不等号改变方向,则说明椭圆弧从上部分转入下部分。 与中点绘制圆算法类似,一个像素确定后,在下面两个候选像素点的中点计算一个判别式的值,再根

据判别式符号确定离椭圆最近的点。先看椭圆弧的上半部分,具体算法如下: 假设横坐标为x p 的像素中与椭圆最近点为(x p , y p ),下一对候选像素的中点应为(x p +1,y p –0.5),判别式为

222222

1(1,0.5)(1)(0.5)p p p p d F x y b x a y a b =+-=++--

10d <,表明中点在椭圆内,应取正右方像素点,判别式变为

222222211(2,0.5)(2)(0.5)(23)p p p p p d F x y b x a y a b d b x '=+-=++--=++

若10d ≥,表明中点在椭圆外,应取右下方像素点,判别式变为

计算机图形学画多边形(3).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:英汉语言对比-1-General Introduction of the Course

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: