计算机图形学报告Word文档下载推荐.docx
《计算机图形学报告Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《计算机图形学报告Word文档下载推荐.docx(28页珍藏版)》请在冰豆网上搜索。
=y1,其他情形可以类推)
1.1.1、待扫描转换生成直线段:
1.1.2、直线的表达形式:
,其中
1.1.3、划分区间:
1.1.4、计算纵坐标:
1.1.5、对计算的纵坐标取整:
2、中点算法扫描转换直线段:
2.1、中点算法简介:
2.1.1、待扫描转换生成直线段:
;
2.1.2、直线的表达形式:
且假定直线段的斜率
2.1.3、直线段的隐式方程:
;
2.1.4、递推计算纵坐标为:
,其中M为
2.1.5、令2.1.4中的
的2倍为判别式,即取判别式为:
并且有递推计算公式如下:
2.1.6、算法的初始条件为
3、Breshenham算法扫描转换直线段:
3.1、Breshenham算法简介:
3.1.1、前序几步与前面两者的思想一样,不同的是在确定下一个点的纵坐标的值的时候,算法不同;
3.1.2、设点Q为斜线段与
直线的交点,
分别为点Q距上下平行线
距离。
可求出
的长度
3.1.3、推得
,且令
3.1.4、则有递推公式
也即:
3.1.5、得到纵坐标的递推求值为:
二、扫描转换圆弧
1、扫描转换生成圆
1.1、算法简介:
1.1.1、利用圆的八对称性;
1.1.2、利用重点算法扫描转换:
1.1.3、取判别数:
,其中
,即圆的隐函数在中点的函数值;
1.1.4、递推求下一个点的纵坐标值:
1.15、给定算法的初始条件如下:
上机实现及源代码:
实验中,在给定两个点之后,根据算法的思想扫描生成一条直线,二两个端点的给定可以通过捕获鼠标信息来获取:
当鼠标左键按下的时候,调用OnLButtonDown()函数来获取直线段的起点,当释放鼠标左键的时候,调用OnLButtonUp()函数来获取直线段的终点。
在扫描转换圆弧中,当鼠标左键按下的时候,调用OnLButtonDown()函数来获取一个点,作为所要画的圆的圆心,当释放左键时,调用OnLButtonUp()函数获取一个点,取两个点之间的的距离作为所要画的圆的半径R,调用switch语句实现不同算法画直线和圆。
voidCAmyGraphView:
:
OnDda()
{
//TODO:
在此添加命令处理程序代码
m_ndrawtype=1;
}
OnMid()
m_ndrawtype=2;
OnBresenham()
m_ndrawtype=3;
voidCAmyGraphView:
OnLButtonDown(UINTnFlags,CPointpoint)
在此添加消息处理程序代码和/或调用默认值
m_start=point;
CView:
OnLButtonDown(nFlags,point);
OnLButtonUp(UINTnFlags,CPointpoint)
m_end=point;
CDC*pDC=GetDC();
CPointP0,P1;
P0=m_start;
P1=m_end;
floatx(P0.x),y(P0.y);
floatdx,dy;
dx=P1.x-P0.x;
dy=P1.y-P0.y;
floatm;
m=dy/dx;
switch(m_ndrawtype)
{
//DDA算法,并且假定x0<
x1
case1:
if(abs(m)<
1)
for(x=P0.x;
x<
=P1.x;
x++)
if(P0.y<
P1.y)
{
pDC->
SetPixel(x,(int)(y+0.5),RGB(255,0,0));
Sleep
(1);
}//0<
=m<
1
else
SetPixel(x,(int)(y-0.5),RGB(255,0,0));
}//-1<
y+=m;
}
if(abs(m)>
=1)
if(P0.y<
for(y=P0.y;
y<
=P1.y;
y++)
x=x+1/m;
pDC->
SetPixel((int)(x+0.5),y,RGB(255,0,0));
Sleep
(1);
else
for(y=P0.y;
y>
y--)
x=x-1/m;
TextOutW(P1.x,P1.y,_T("
DDA算法"
));
ReleaseDC(pDC);
break;
//中点算法生成直线,假定x0<
x1,0<
m<
case2:
intE,NE,d;
d=dx-2*dy;
//初始化判别式d
E=-2*dy;
//取像素E时判别式的增量
NE=2*(dx-dy);
//取像素NE时判别式的增量
SetPixel(x,y,RGB(0,255,0));
while(x<
P1.x)
if(d>
0)
d+=E;
d+=NE;
y++;
}
x++;
中点算法"
//Bresenham算法,假定x0<
case3:
intp,twoDy,twoDyDx,xEND;
p=2*dy-dx;
twoDy=2*dy;
twoDyDx=2*(dy-dx);
SetPixel(x,y,RGB(0,0,255));
P1.x)
if(p<
p+=twoDy;
p+=twoDyDx;
y++;
Bresham算法"
//扫描转换圆
case4:
SetPixel(m_start.x,m_start.y,RGB(255,0,0));
TextOutW(m_start.x,m_start.y,_T("
圆心"
intX(0),Y;
floatD;
intradius;
radius=sqrt(double((P0.x-P1.x)*(P0.x-P1.x)+(P0.y-P1.y)*(P0.y-P1.y)));
//根据鼠标捕获的两个点计算所要绘制的圆的半径,在头文件中定义math.h函数。
Y=radius;
D=5/4-radius;
SetPixel(X+P0.x,Y+P0.y,RGB(255,0,0));
SetPixel(-X+P0.x,Y+P0.y,RGB(255,0,0));
SetPixel(Y+P0.x,X+P0.y,RGB(0,255,0));
SetPixel(Y+P0.x,-X+P0.y,RGB(0,255,0));
SetPixel(-X+P0.x,-Y+P0.y,RGB(0,0,255));
SetPixel(X+P0.x,-Y+P0.y,RGB(0,0,255));
SetPixel(-Y+P0.x,X+P0.y,RGB(0,255,0));
SetPixel(-Y+P0.x,-X+P0.y,RGB(0,255,0));
//绘制八点并将绘制的点平移
while(Y>
X)//八分之一圆弧
if(D<
=0)
D+=2*X+3;
D+=2*(X-Y)+5;
Y--;
X++;
Sleep(15);
(实验一扫描转化直线段)
(实验一中点算法扫描转换圆弧)
第二篇二维填充图元的生成
在第一篇中讨论了一维图元的生成,进而讨论二维图形在计算机中的生成算法,在实际生活中,大多数图形采用定点序列表示多边形,二顶点表示却不能直接用于在光栅系统中显示,所以就需要有从顶点表示转换到点阵表示的算法,这就叫扫描转换多边形。
较为常用的经典扫描转换多边形的算法有住店判断法、扫描线算法、边缘填充法以及递归算法(种子算法),此次试验主要选择递归算法来实现扫描转换多边形。
1、递归算法扫描转换多边形算法的思想简介:
将指定的颜色从种子点扩展到整个区域的过程,区域填充算法要求区域是连通的。
2、上机实现的操作思想:
在扫描填充一个多边形之前,首先需要给定该多边形的顶点表示,本程序的基本想法是,定义一个CPoint类的数组存储多边形顶点,s_point记录种子点,调用OnLButtonDblClk(UINTnFlags,CPointpoint)函数绘制出要填充的多边形。
确定数组中纵坐标最大和最小的点,然后从种子点出发向上向下填充多边形。
算法代码及示例如下:
#defineN12
public:
CPointpset[N],s_point,p0;
voidC区域填充View:
OnDraw(CDC*pDC)
C区域填充Doc*pDoc=GetDocument();
ASSERT_VALID(pDoc);
if(!
pDoc)
return;
TextOut(20,20,_T("
双击鼠标左键,出现需填充的多边形,点击相关功能菜单实现区域填充"
在此处为本机数据添加绘制代码
OnLButtonDblClk(UINTnFlags,CPointpoint)
CPennewpen(PS_SOLID,1,RGB(255,0,0));
CPen*old=pDC->
SelectObject(&
newpen);
pset[0]=CPoint(100,100);
pset[1]=CPoint(200,80);
pset[2]=CPoint(320,100);
pset[3]=CPoint(250,250);
pset[4]=CPoint(100,250);
pset[5]=CPoint(150,200);
pset[6]=CPoint(90,180);
pset[7]=CPoint(150,150);
pset[8]=CPoint(100,100);
Polyline(pset,9);
SelectObject(old);
OnLButtonDblClk(nFlags,point);
OnSeedfill()
intfill=RGB(0,255,0);
intboundary=RGB(255,0,0);
s_point.x=200;
s_point.y=150;
//定义种子点
intx,y,pmin,pmax;
//求多边形的最大最小值
for(intm=1;
9;
m++)
for(intn=0;
n<
9-m;
n++)
if(pset[n].y<
pset[n+1].y)
{
p0=pset[n];
pset[n]=pset[n+1];
pset[n+1]=p0;
}
}//循环得到纵坐标最大和最小的点
pmax=pset[0].y,pmin=pset[8].y;
for(;
pmax+1;
y++)
intcurrent=pDC->
GetPixel(x,y);
while((current!
=boundary)&
&
(current!
=fill))
{
pDC->
SetPixel(x,y,fill);
x++;
current=pDC->
//判断循环是否继续
}
x=s_point.x;
x--;
x--;
x=s_point.x;
x=s_point.x;
y=s_point.y-1;
pmin+1;
y--)
(实验二区域填充—种子扫描线算法)
第三篇二维直线段与多边形裁剪
在第一篇中已经提到,二维图形在现实之前都需要进行两个重要的处理步骤,其一是扫描转换,其二是裁剪。
当二维图形只能在某一可见窗口显示的时候,就需要对其进行裁剪。
现今最要的二位图形的裁剪算法有直线段的裁剪有Cohen-Sutherland算法、Nicholl-Lee-Nicholl算法、中点分割算法以及梁友栋-Barsky算法;
多边形裁剪的算法有Sutherland-Hodgman算法,Weiler-Atherton算法。
本实验将利用Cohen-Sutherland算法上机实现直线段裁剪。
一、直线段裁剪
1、Cohen-Sutherland算法的简介就不做叙述,可以参加文献一第六章。
2、上机实现操作的基本思想:
2.1、首先定义一个数组存储线段的起点和终点坐标,并定义裁剪窗口。
2.2、添加鼠标消息响应函数OnLButtonDblClk()显示要裁剪的线段
2.3、编写“线段裁剪”菜单项,添加事件处理函数来实现直线段裁剪。
3、算法程序源代码及示例如下:
#defineLEFT1
#defineRIGHT2
#defineBOTTOM4
#defineTOP8
#defineXL100
#defineXR300
#defineYT100
#defineYB250
#defineN11
public:
CPointpset[N];
voidCCohenSutherland算法View:
CCohenSutherland算法Doc*pDoc=GetDocument();
Rectangle(CRect(XL,YT,XR,YB));
//剪切窗口
pset[0]=CPoint(200,140);
pset[1]=CPoint(200,200);
pset[2]=CPoint(10,225);
pset[3]=CPoint(350,225);
pset[4]=CPoint(280,170);
pset[5]=CPoint(150,10);
pset[6]=CPoint(200,50);
pset[7]=CPoint(120,150);
pset[8]=CPoint(310,100);
pset[9]=CPoint(350,280);
双击鼠标左键,出现要剪切的线段"
OnLinecut()
CPennewpen(PS_SOLID,1,RGB(0,0,255));
floatx,y;
inti;
intcode1,code2;
RedrawWindow();
//求两端点所在区号code
for(i=0;
i<
N;
i++,i++)
intc=0;
if(pset[i].x<
XL)c=c|LEFT;
//按位或"
|"
即做和运算
elseif(pset[i].x>
XR)c=c|RIGHT;
if(pset[i].y>
YB)c=c|BOTTOM;
elseif(pset[i].y<
YT)c=c|TOP;
code1=c;
c=0;
if(pset[i+1].x<
elseif(pset[i+1].x>
XR)c=c|RIGHT;
if(pset[i+1].y>
elseif(pset[i+1].y<
code2=c;
//线段与区域的相交情况
if(code1!
=0&
code2!
(code1&
code2)==0)//按位与"
"
非"
0"
时一定位于裁剪窗口外的某一侧,p2p3线段
{
if((LEFT&
code1)!
=0)//线段与左边界相交
x=XL;
y=(float)pset[i].y+(pset[i+1].y-pset[i].y)*(XL-pset[i].x)/(pset[i+1].x-pset[i].x);
elseif((RIGHT&
=0)//线段与右边界相交
x=XR;
y=(float)pset[i].y+(pset[i+1].y-pset[i].y)*(XR-pset[i].x)/(pset[i+1].x-pset[i].x);
elseif((BOTTOM&
=0)//线段与下边界相交
y=YB;
x=(float)pset[i].x+(pset[i+1].x-pset[i].x)*(YB-pset[i].y)/(pset[i+1].y-pset[i