计算机图形学实验一Word格式.docx

上传人:b****7 文档编号:22687489 上传时间:2023-02-05 格式:DOCX 页数:21 大小:73.49KB
下载 相关 举报
计算机图形学实验一Word格式.docx_第1页
第1页 / 共21页
计算机图形学实验一Word格式.docx_第2页
第2页 / 共21页
计算机图形学实验一Word格式.docx_第3页
第3页 / 共21页
计算机图形学实验一Word格式.docx_第4页
第4页 / 共21页
计算机图形学实验一Word格式.docx_第5页
第5页 / 共21页
点击查看更多>>
下载资源
资源描述

计算机图形学实验一Word格式.docx

《计算机图形学实验一Word格式.docx》由会员分享,可在线阅读,更多相关《计算机图形学实验一Word格式.docx(21页珍藏版)》请在冰豆网上搜索。

计算机图形学实验一Word格式.docx

ID_DDALINE

Bresenham算法生成直线

ID_BRESENHAMLINE

中点算法生成直线

ID_MIDPOINTLINE

4.添加消息处理函数

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

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

菜单项ID

消息

消息处理函数

CONMMAN

OnDdaline

OnMidpointline

OnBresenhamline

5.程序结构代码,在CMyView.cpp文件中相应位置添加如下代码:

//DDA算法生成直线

voidCMyView:

:

OnDdaline()

{

CDC*pDC=GetDC();

//获得设备指针

intxa=100,ya=300,xb=300,yb=200,c=RGB(255,0,0);

//定义直线的两端点,直线颜色

intx,y;

floatdx,dy,k;

dx=(float)(xb-xa),dy=(float)(yb-ya);

k=dy/dx,y=ya;

if(abs(k)<

1)

{

for(x=xa;

x<

=xb;

x++)

{pDC->

SetPixel(x,int(y+0.5),c);

y=y+k;

}

}

if(abs(k)>

=1)

for(y=ya;

y<

=yb;

y++)

SetPixel(int(x+0.5),y,c);

x=x+1/k;

}

ReleaseDC(pDC);

说明:

(1)以上代码理论上通过定义直线的两端点,可得到任意端点之间的一直线,但由于一般屏幕坐标采用右手系坐标,屏幕上只有正的x,y值,屏幕坐标与窗口坐标之间转换知识请参考第3章。

(2)注意上述程序考虑到当k1的情形x每增加1,y最多增加1;

当k>

1时,y每增加1,x相应增加1/k。

在这个算法中,y与k用浮点数表示,而且每一步都要对y进行四舍五入后取整。

//中点算法生成直线

OnMidpointline()

intxa=300,ya=200,xb=450,yb=300,c=RGB(0,255,0);

floata,b,d1,d2,d,x,y;

a=ya-yb,b=xb-xa,d=2*a+b;

d1=2*a,d2=2*(a+b);

x=xa,y=ya;

pDC->

SetPixel(x,y,c);

while(x<

xb)

{if(d<

0){x++,y++,d+=d2;

else{x++,d+=d1;

ReleaseDC(pDC);

(1)其中d是xp,yp的线性函数。

为了提高运算效率,程序中采用增量计算。

具体算法如下:

若当前像素处于d>

0情况,则取正右方像素P1(xp+1,yp),判断下一个像素点的位置,应计算d1=F(xp+2,yp+0.5)=a(xp+2)+b(yp+0.5)=d+a;

,其中增量为a。

若d<

0时,则取右上方像素P2(xp+1,yp+1)。

再判断下一像素,则要计算d2 =F(xp+2,yp+1.5)=a(xp+2)+b(yp+1.5) + c=d+a+b,增量为a+b。

(2)画线从(x0,y0)开始,d的初值d0=F(x0+1,y0+0.5)=F(x0,y0)+a+0.5b,因F(x0,y0)=0,则d0=a+0.5b。

(3)程序中只利用d的符号,d的增量都是整数,只是初始值包含小数,用2d代替d,使程序中仅包含整数的运算。

//Bresenham算法生成直线

voidCMyView:

OnBresenhamline()

intx1=100,y1=200,x2=350,y2=100,c=RGB(0,0,255);

inti,s1,s2,interchange;

floatx,y,deltax,deltay,f,temp;

x=x1;

y=y1;

deltax=abs(x2-x1);

deltay=abs(y2-y1);

if(x2-x1>

=0)s1=1;

elses1=-1;

if(y2-y1>

=0)s2=1;

elses2=-1;

if(deltay>

deltax){

temp=deltax;

deltax=deltay;

deltay=temp;

interchange=1;

elseinterchange=0;

f=2*deltay-deltax;

SetPixel(x,y,c);

for(i=1;

i<

=deltax;

i++){

if(f>

=0){

if(interchange==1)x+=s1;

elsey+=s2;

f=f-2*deltax;

else{

if(interchange==1)y+=s2;

elsex+=s1;

f=f+2*deltay;

(1)以上程序已经考虑到所有象限直线的生成。

(2)Bresenham算法的优点如下:

①不必计算直线的斜率,因此不做除法。

②不用浮点数,只用整数。

③只做整数加减运算和乘2运算,而乘2运算可以用移位操作实现。

④Bresenham算法的运算速度很快。

圆弧生成程序设计的步骤如下:

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

(2)编辑菜单资源。

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

此时建好的菜单如图1-3所示。

图1-3程序主菜单

表1-3菜单资源表

中点画圆

ID_MIDPOINTCIRCLE

Bresenham画圆

ID_BRESENHAMCIRCLE

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

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

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

OnMidpointcircle

OnBresenhamcircle

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

OnMidpointcircle()//中点算法绘制圆,如图1-4所示

图1-4中点算法绘制圆

//TODO:

Addyourcommandhandlercodehere

intxc=300,yc=300,r=50,c=0;

floatd;

x=0;

y=r;

d=1.25-r;

SetPixel((xc+x),(yc+y),c);

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

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

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

SetPixel((xc+y),(yc+x),c);

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

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

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

while(x<

=y)

{if(d<

0)d+=2*x+3;

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

y--;

x++;

OnBresenhamcircle()////Bresenham算法绘制圆,如图1-5所示

intxc=100,yc=100,radius=50,c=0;

图1-5Bresenham算法绘制圆

intx=0,y=radius,p=3-2*radius;

while(x<

y)

pDC->

SetPixel(xc+x,yc+y,c);

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

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

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

SetPixel(xc+y,yc+x,c);

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

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

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)

多边形填充程序设计的步骤如下:

(1)创建应用程序框架,以上述单文档程序框架为基础,创建如图1-17所示应用程序界面。

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

此时建好的菜单如图1-18所示。

图1-17程序界面

表1-7菜单资源表

区域填充

多边形扫描填充

ID_SCANFILL

种子填充

ID_SEEDFILL

图1-18程序主菜单

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

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

OnScanfill

OnSeedfill

(4)添加程序结构代码。

①在“基本图形的生成View.h”适当位置添加以下黑体字部分代码:

typedefstruct//建立边表结构

intnum,ymin,ymax;

floatxmin,xmax,dx;

}Edge;

classCMyView:

publicCView

protected:

//createfromserializationonly

public:

Cpointptset[7];

Edgeedge[7],edge1[7],newedge[1];

②在OnDraw()函数中添加如下黑体字部分代码。

OnDraw(CDC*pDC)//绘制要填充的多边形

CMyDoc*pDoc=GetDocument();

ASSERT_VALID(pDoc);

CPennewpen(PS_SOLID,1,RGB(255,0,0));

CPen*old=pDC->

SelectObject(&

newpen);

TextOut(20,20,"

双击鼠标左键,出现需填充的多边形,点击相关功能菜单实现区域填充"

);

TextOut(20,50,"

进行种子填充,需用鼠标右键,单击多边形内一点,作为开始填充的种子点"

SelectObject(old);

③在菜单项的消息处理函数实体中添加以下黑体字部分代码。

OnScanfill()//扫描线算法进行多边形区域填充,如图1-19所示

CPennewpen(PS_SOLID,1,RGB(0,255,0));

CPen*old=pDC->

intj,k,s=0;

图1-19扫描线算法区域填充

intp[5];

//每根扫描线交点

intpmin,pmax;

for(inti=0;

6;

i++)//建立边表

edge[i].dx=(float)(spt[i+1].x-spt[i].

x)/(spt[i+1].y-spt[i].y);

if(spt[i].y<

=spt[i+1].y){

edge[i].num=i;

edge[i].ymin=spt[i].y;

edge[i].ymax=spt[i+1].y;

edge[i].xmin=(float)spt[i].x;

edge[i].xmax=(float)spt[i+1].x;

pmax=spt[i+1].y;

pmin=spt[i].y;

}

else{

edge[i].ymin=spt[i+1].y;

edge[i].ymax=spt[i].y;

edge[i].xmax=(float)spt[i].x;

edge[i].xmin=(float)spt[i+1].x;

pmax=spt[i].y;

pmin=spt[i+1].y;

}

for(intr=1;

r<

r++)//排序edge(yUpper,xIntersect)

for(intq=0;

q<

6-r;

q++)

{

if(edge[q].ymin<

edge[q+1].ymin)

{

newedge[0]=edge[q];

edge[q]=edge[q+1];

edge[q+1]=newedge[0];

}

for(intscan=pmax-1;

scan>

pmin+1;

scan--)

intb=0;

k=s;

for(j=k;

j<

j++)

{

if((scan>

edge[j].ymin)&

&

(scan<

=edge[j].ymax))//判断与线段相交

if(scan==edge[j].ymax)

{

if(spt[edge[j].num+1].y<

edge[j].ymax)

{

b++;

p[b]=(int)edge[j].xmax;

}

if(spt[edge[j].num-1].y<

b++;

}

}

if((scan>

edge[j].ymax))

b++;

p[b]=(int)(edge[j].xmax+edge[j].dx*(scan-edge[j].

ymax));

}

//pDC->

LineTo(spt[edge[0].num].x,spt[edge[0].num].y);

if(scan<

=edge[j].ymin)//

s=j;

}

if(b>

{

for(intu=1;

u<

b;

u++)

pDC->

MoveTo(p[u]+3,scan);

u++;

LineTo(p[u],scan);

双击,出现需填充的多边形,单击相关功能菜单实现区域填充。

OnSeedfill()//种子算法进行多边形区域填充,如图1-20所示

CWindowDCdc(this);

intfill=RGB(0,255,0);

图1-20种子算法区域填充

intboundary=RGB(255,0,0);

CPointpt=s_point;

intx,y,p0,pmin,pmax;

//求多边形的最大最小值

for(intm=1;

m<

7;

m++)

for(intn=0;

n<

7-m;

n++)

if(spt[n].y<

spt[n+1].y)

p0=spt[n].y;

spt[n]=spt[n+1];

spt[n+1]=p0;

pmax=spt[0].y,pmin=spt[6].y;

x=s_point.x;

y=s_point.y;

for(;

pmax+1;

y++)

intcurrent=dc.GetPixel(x,y);

while((current!

=boundary)&

(current!

=fill))

{

dc.SetPixel(x,y,fill);

x++;

current=dc.GetPixel(x,y);

}

x=s_point.x;

x--;

x--;

x=s_point.x;

y=s_point.y-1;

y>

pmin-2;

y--)

while((current!

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 文学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1