实验一DDA画线算法.docx
《实验一DDA画线算法.docx》由会员分享,可在线阅读,更多相关《实验一DDA画线算法.docx(25页珍藏版)》请在冰点文库上搜索。
实验一DDA画线算法
实验一DDA画线算法
一、实验学时:
2
二、实验类型:
验证性实验
三、实验要求和目的
初步了解Tc下画图基本程序结构。
初步了解DDA画线算法的思想和基本方法。
四、实验内容
DDA画线算法画一段直线
1.算法思路
1.算法描述:
设直线方程为:
,
对于直线,其数值微分是
由上式得,y(i+1)=y(i)+m(x(i+1)-x(i)),于是知,使x(i)增1,即x(i+1)=x(i)+1时,y(i+1)=y(i)+m,为画线精确,应使相邻的画出点的坐标值相差最大值为1,这样可以得到画线段的数值微分分析器(DigitalDifferentialAnalyzer,简称DDA),算法如下:
2.C程序代码
#include
#include
#include
voidDDALine(intx1,inty1,intx2,inty2,intcolor)
{
doubledx,dy,e,x,y,i;
dx=x2-x1;
dy=y2-y1;
e=(fabs(dx)>fabs(dy))?
fabs(dx):
fabs(dy);
dx/=e;
dy/=e;
x=x1;
y=y1;
for(i=1;i<=e;i++)
{putpixel((int)(x+0.5),(int)(y+0.5),color);
x+=dx;
y+=dy;
}
}
voidmain()
{intdriver=DETECT;
intgmode;
intx1,y1,x2,y2,color;
printf("pleaseinputx1,y1,y1,y2,color\n");
scanf("%d,%d,%d,%d,%d",&x1,&y1,&x2,&y2,&color);
initgraph(&driver,&gmode,"");
DDALine(x1,y1,x2,y2,color);
getch();
closegraph();
}
实验二Bresenham画线算法
一、实验学时:
2
二、实验类型:
验证性实验
三、实验要求和目的
掌握中点画线算法的思想和基本方法
四、实验内容
用Bresenham画线算法画直线,并完善算法功能,使之适应更广
1.算法思路
假定直线段的斜率0≤m≤1,且x2>x1,
若差为正,即
,下一个象素应取
;若为负,即
,下一个象素应取
。
引入新的判别量pi
其中
,又因为
,所以有
应取
,此时
pi<0,应取
此时
初始值的确定:
2.C程序代码
#include
#include
#include
voidBresenhamLine(intx1,inty1,intx2,inty2,intcolor)
{
intx,y,dx,dy,p;
x=x1;
y=y1;
dx=x2-x1;
dy=y2-y1;
p=2*dy-dx;
for(x=1;x<=x2;x++)
{
putpixel(x,y,color);
if(p>=0)
{y++;
p+=2*(dy-dx);
}
else
{p+=2*dy;
}
}
}
voidmain()
{intdriver=DETECT;
intgmode;
intx1,y1,x2,y2,color;
printf("pleaseinputx1,y1,x2,y2,color");
scanf("%d,%d,%d,%d,%d",&x1,&y1,&x2,&y2,&color);
initgraph(&driver,&gmode,"");
BresenhamLine(x1,y1,x2,y2,color);
getch();
closegraph();
}
实验三中点画圆算法
一、实验学时:
2
二、实验类型:
验证性实验
三、实验要求和目的
掌握中点画圆算法的基本思想
编写中点画圆的基本函数并尽量完善
四、实验内容
中点画圆算法画圆
1.算法描述:
构造函数
对于圆上的点,有F(x,y)=0;对于圆外的点,有F(x,y)>0;对于圆内的点,有F(x,y)<0。
设M的坐标为:
M(xi+1,yi-0.5),构造判别式:
,
当d<0时,下一点取P1;
当d>=0时,下一点取P2。
当d<0时,下一点取P1,再下一个点的判别式:
当d>=0时,下一点取P2,再下一个点的判别式:
判别式的初值:
2.源程序:
#include
#include
#include
voidMidpointCircle(intx0,inty0,intR)
{
intx,y;
doubled;
x=0;
y=R;
d=1.25-R;
while(x{if(d<0)
{d+=x+x+3;
x++;}
else
{d+=(x-y)+(x-y)+5;
x++;
y--;}
putpixel(x0+x,y0+y,RED);
putpixel(x0+y,y0+x,RED);
putpixel(x0+y,y0-x,RED);
putpixel(x0+x,y0-y,RED);
putpixel(x0-x,y0-y,RED);
putpixel(x0-y,y0-x,RED);
putpixel(x0-y,y0+x,RED);
putpixel(x0-x,y0+y,RED);
}
}
main()
{intdriver=DETECT,mode;
initgraph(&driver,&mode,"");
MidpointCircle(200,200,100);
getch();
closegraph();
}
1.
实验四Bresenham画圆算法
一、实验学时:
2
二、实验类型:
验证性实验
三、实验要求和目的
掌握Bresenham画圆算法的基本思想
编写Bresenham算法画圆的基本函数并尽量完善
四、实验内容
Bresenham画圆算法画圆,并改造函数,使之能画整圆。
1.算法思路
先求(0,R)到
之间的四分之一圆弧,然后由对称性求得整个圆。
取
,圆周上y的变化小于1,若第i步是
,那么第i+1步只能是H(Xi+1,Yi)和D(Xi+1,Yi+1)点中的一个,H和D点离圆心距离的平方差
令判别量
当Pi<0时,下一点应选H点,
。
当Pi>=0时,下一点应选D点。
。
2.源程序:
#include
#include
#include
voidBresenhamCirle(intR)
{
intx,y,p;
x=0;
y=R;
p=3-2*R;
for(;x<=y;x++)
{putpixel(x+200,y+100,3);
putpixel(x+200,-y+100,3);
putpixel(y+200,x+100,3);
putpixel(-y+200,x+100,3);
putpixel(-x+200,y+100,3);
putpixel(-x+200,-y+100,3);
putpixel(-y+200,x+100,3);
putpixel(-y+200,-x+100,3);
if(p>=0)
{
p+=4*(x-y)+10;
y--;
}
else
{
p+=4*x+6;
}
}
}
voidmain()
{intdriver=DETECT,gmode;
initgraph(&driver,&gmode,"");
BresenhamCirle(150);
getch();
closegraph();
}
实验五正方形旋转
一、实验学时:
2
二、实验类型:
验证性实验
三、实验要求和目的
掌握图形的旋转变换数学原理
掌握一般图形旋转的基本算法
四、实验内容
画一个正方形,并实现45度旋转,进一步可以使之动起来.
1算法思路
旋转变换:
式中,
是图形以坐标原点为旋转中心的旋转角度。
本程序实现相对于任意一点(x0,y0)作变换,可以先平移到原点,相对于原点作变换后,再平移回去。
相对于任意一点(x0,y0)的旋转变换矩阵如下:
T(-x0,-y0)R(
).T(x0,y0)
=
1.=
2.C程序代码
#include
#include
voidmain()
{
inti,j,s,k;
floatcx;
float
a[4][3]={{400,200,1},{300,200,1},{300,300,1},{400,300,1}};
floatpingyi[3][3]={{1,0,0},{0,1,0},{-125,-125,1}};
floatrpingyi[3][3]={{1,0,0},{0,1,0},{125,125,1}};
floatzhuan[3][3]={{0,0,0},{0,0,0},{0,0,1}};
floataxb[4][3];
floatzaxb[4][3];
floatrp[4][3];
intgdriver=DETECT,gmade;
initgraph(&gdriver,&gmade,"");
line(a[0][0],a[0][1],a[1][0],a[1][1]);
line(a[1][0],a[1][1],a[2][0],a[2][1]);
line(a[2][0],a[2][1],a[3][0],a[3][1]);
line(a[3][0],a[3][1],a[0][0],a[0][1]);
for(i=0;i<4;i++)
{
for(j=0;j<3;j++)
{
s=0;
for(k=0;k<3;k++)
{
s=s+a[i][k]*pingyi[k][j];
}
axb[i][j]=s;
}
}
line(axb[0][0],axb[0][1],axb[1][0],axb[1][1]);
line(axb[1][0],axb[1][1],axb[2][0],axb[2][1]);
line(axb[2][0],axb[2][1],axb[3][0],axb[3][1]);
line(axb[3][0],axb[3][1],axb[0][0],axb[0][1]);
cx=(sqrt
(2))/2.0;
zhuan[0][0]=cx;
zhuan[0][1]=cx;
zhuan[1][0]=-cx;
zhuan[1][1]=cx;
for(i=0;i<4;i++)
{
for(j=0;j<3;j++)
{
s=0;
for(k=0;k<3;k++)
{
s=s+axb[i][k]*zhuan[k][j];
}
zaxb[i][j]=s;
}
}
line(zaxb[0][0],zaxb[0][1],zaxb[1][0],zaxb[1][1]);
line(zaxb[1][0],zaxb[1][1],zaxb[2][0],zaxb[2][1]);
line(zaxb[2][0],zaxb[2][1],zaxb[3][0],zaxb[3][1]);
line(zaxb[3][0],zaxb[3][1],zaxb[0][0],zaxb[0][1]);
for(i=0;i<4;i++)
{
for(j=0;j<3;j++)
{
s=0;
for(k=0;k<3;k++)
{
s=s+zaxb[i][j]*rpingyi[k][j];
}
rp[i][j]=s;
}
}
line(rp[0][0],rp[0][1],rp[1][0],rp[1][1]);
line(rp[1][0],rp[1][1],rp[2][0],rp[2][1]);
line(rp[2][0],rp[2][1],rp[3][0],rp[3][1]);
line(rp[3][0],rp[3][1],rp[0][0],rp[0][1]);
getch();
closegraph();
}
实验六直线段裁剪算法
一、实验学时:
4
二、实验类型:
验证性实验
三、实验要求和目的
掌握直线段裁剪算法的一般思想方法.
四、实验内容
画几条线段,利用裁剪算法实现特定的裁剪,并验证算法的正确性
1算法思路
P52
第一步:
编码。
设直线段的两个端点为P1(x1,y1)和P2(x2,y2),根据编码规则,可以求出P1和P2所在的代码c1和c2;
第二步:
判别。
根据c1和c2的具体值,可以有三种情况:
1)c1=c2=0,这表明两端点全在窗口内,则整个直线也在窗口内,应该保留;
2)c1&&c2!
=0,表明两端点必定同处于某一边界的同一外侧,则整个直线全在窗口外,应该舍弃;
如不属于上面两种请况,表明直线有一部分在窗口内,又可以分为以下三种情况:
(1)一个端点在内,一个端点在外;
(2)两个端点均在外,但直线段中部跨越窗口;
(3)两端点都在外,且直线段也在外。
第三步:
求交。
对不能确定取舍的直线段,求其与窗口边界及其延长线的交点,从而将直线段分割。
求交点时,可以有针对性地与某一确定边界求交。
在交点处把线段分为两段。
把其中一段完全在窗口外,舍弃之。
第四步:
对剩下的线段重复以上各步,可以验证,至多重复到第三遍的判断为止,这时剩下的直线段或者全在窗口内,或者全在窗口外,从而完成了对直线段的裁剪。
2.C程序代码
#include
#include
#definex1150
#definexr180
#defineyt180
#defineyb150
voidCohen_Sutherland(doublex0,doubley0,doublex2,doubley2)
{
intc,c1,c2;
doublex,y;
c1=makecode(x0,y0);
c2=makecode(x2,y2);
while(c1!
==1)
{
if(c1&c2==1)
return;
c=c1;
if(c==0)
c=c2;
if(c&1==1)
{
y=y0+(y2-y0)*(x1-x0)/(x2-x0);
x=x1;
}
else
if(c&2)
{
y=y0+(y2-y0)*(x1-x0)/(x2-x0);
x=xr;
}
else
if(c&4)
{
y=y0+(y2-y0)*(x1-x0)/(x2-x0);
y=yb;
}
else
if(c&8)
{
y=y0+(y2-y0)*(x1-x0)/(x2-x0);
y=yt;
}
if(c==c1)
{
x0=x;
y0=y;
c1=makecode(x,y);
}
else
{
x2=x;
y2=y;
c2=makecode(x,y);
}
}
line(x0,y0,x2,y2);
}
intmakecode(doublex,doubley)
{
intc=0;
if(xc=1;
else
if(x>x1)
c=1;
else
if(x>xr)
c=2;
if(yc=c+4;
else
if(y>yt)
{
c=c+8;
}
returnc;
}
voidmain()
{
intdriver=DETCET;
intmode;
initgraph(&driver,&mode,"");
Cohen_Sutherland(75,75,200,200);
getch();
closegraph();
}
实验七两条线段求交算法
一、实验学时:
2
二、实验类型:
验证性实验
三、实验要求和目的
掌握线段求交的一般思想方法.
实现线段求交算法
四、实验内容
求两条线段的交点,并是函数适应性更广
1.算法思路
1)计算行列式:
若行列式=0,则两线段重合或平行,无交点,算法结束;
2)计算交点参数:
若
,则无交点,算法结束
3)计算交点
2.C程序代码
2.源程序:
#include
#include
voidmain()
{
intxa,ya,xb,yb,xc,yc,xd,yd,x,y,color;
doublet1,t2,deater;
intdriver=DETECT;
intgmode;
initgraph(&driver,&gmode,"");
scanf("%d",&xa);
scanf("%d",&ya);
scanf("%d",&xb);
scanf("%d",&yb);
scanf("%d",&xc);
scanf("%d",&yc);
scanf("%d",&xd);
scanf("%d",&yd);
line(xa,ya,xb,yb);
line(xc,yc,xd,yd);
deater=-(xb-xa)*(yd-yc)+(xd-xc)*(yb-ya);
if(deater==0)
{
printf("zhixianpingxing");
}else
{
t1=((xc-xa)*(yc-yd)-(xc-xd)*(yc-ya))/deater;
t2=((xb-xa)*(yc-ya)-(xc-xa)*(yb-ya))/deater;
if(0{
x=xa+t1*(xb-xa);
y=ya+t1*(yb-ya);
putpixel(x,y,4);
printf("%d,%d",x,y);
}else
{
printf("liangxianbuhuixiangjiao");
}
}
getch();
closegraph();
}
实验八点对简单多边形的包含
一、实验学时:
2
二、实验类型:
验证性实验
三、实验要求和目的
掌握包含判断一般思想方法.
实现点对简单多边形(五边形,自己定义顶点坐标)
四、实验内容
编程实现点对五边形的包含检查算法。
1.算法思路
首先通过给出点的坐标画出五边形,然后:
1)[准备]
=
=
m=-1;i=0;
2)[排除必不相交的情形]若下列条件有一个成立,则到4。
并且
;
并且;
并且
;
3)[计算交点]
,分两种情况:
若y=
,则点P在多边形的边界上,算法结束;
若y<
则m=(-1).m;
4)[结束判断]i=i+1,若i最后,从要判断的点,向下画直线,便于观察点在多边形内部,外部还是在边界上,并且同时输出英文句子,若再边界上则输出pointpisontheedgeofgraph若再内部则输出pointpisontheedgeofgraph,否则输出Pointpisinthegraph。
1.C程序代码
main()
{
intxx[10],yy[10],m,i,x0,y0,n,y;
n=4;
x0=600;
y0=400;
printf("pleaseputthepoints\n");
for(i=0;i{
scanf("%d%d",&xx[i],&yy[i]);
}
m=-1;
for(i=0;i{
if(x0>xx[i]&&x0>=xx[i+1]||x0=yy[i]&&y0>=yy[i+1])
{
y=yy[i]+(x0-xx[i])*(yy[i+1]-yy[i])/(xx[i+1]-xx[i]);
if(y==y0)
printf("itisinthebound\n");
else
{
if(ym=-1*m;
}
}
}
if(m==-1)
{
printf("pisoutoftheduobianxing\n");
}
if(m==1)
{
printf("pisintheduobianxing\n");
}
getch();
}
实验九Bezier曲线
一、实验学时:
4
二、实验类型:
验证性实验
三、实验要求和目的
掌握Bezier曲线的一般性质
实现Bezier曲线的描绘
四、实验内容
实现Bezier曲线的画线算法
1.算法描述:
首先给定四个初始点,由公式可以得到计算n次Bezier曲线上控制点在t时的值P(t),可以归结为两个n-1次Bezier曲线在t时的线性组合。
t每增加一个步长,由递推计算关系可以得到一个对应的P(t)值,依次画出点(t,P(t)),则可以得到曲线
2.源程序:
#include
#include
voidbezier(intdegree,intnpoints,doublecoeff1[],doublecoeff2[])
{
doublet,delt;
inti;
delt=1.0/(double)npoints;
t=0.0;
for(i=0;i<=npoints;i++)
{
decas(degree,coeff1,coeff2,t);
t+=delt;
}
}
decas(intdegree,doublecoeff1[],doublecoeff2[],doublet)
{
intr,i;
double*coeffa,coeffa10,coeffa20;
doublecoeffa1[5],coeffa2[5];
for(i=0;i<=degree;i++)
coeffa1[i]=coeff1[i];
coeffa2[i]