实验报告
实验课程:
学生姓名:
学 号:
专业班级:
2014年12月28日
目 录
实验二 几何变换
实验三 二维基本图形生成的算法实现.
实验四 二维填充图的生成算法
实验五 曲线的生成算法实现
实验二
1.实验名称: 图形绘制
2.实验目的:
(1) 掌握二维图形基本的几何变换原理及变换矩阵;
(2) 掌握矩阵运算的程序设计。
3说明图形设计思想或程序流程图
(1) 掌握二维图形的齐次坐标表示方法;
(2)实现二维图形的基本变换,如进行平移变换等。
算法描述:
二维图形齐次坐标变换矩阵一般表达式:
这3×3 矩阵中各元素功能一共可分成四块,即
(4)程序结果分析
#include #include double x1,y1,x2,y2,x3,y3,x4,y4; void pingyi(double d,double c) { double a1,b1,a2,b2; a1=x1+d; b1=y1+c; a2=x2+d; b2=y2+c; rectangle(a1,b1,a2,b2); } void suofang(double s) { double a1,b1,a2,b2; a1=(double)x1*s; b1=(double)y1*s; a2=(double)x2*s; b2=(double)y2*s; rectangle(a1,b1,a2,b2); } void xuanzhuan(double b) { double a1,b1,a2,b2; a1=x1*cos(b)-y1*sin(b); b1=y1*cos(b)+x1*sin(b); a2=x2*cos(b)-y2*sin(b); b2=y2*cos(b)+x2*sin(b); rectangle(a1,b1,a2,b2); } void cuoqie(double b,double d) { double a1,b1,a2,b2,a3,b3,a4,b4; a1=x1+b*y1; a3=x3+b*y3; b1=d*x1+y1; b3=d*x3+y3; a2=x2+b*y2; a4=x4+b*x4; b2=d*x2+y2; b4=d*x4+y4; line(a1,b1,a3,b3); line(a3,b3,a2,b2); line(a2,b2,a4,b4); line(a4,b4,a1,b1); } void duichenpoint() { double a1,b1,a2,b2; a1=-x1;b1=-y1;a2=-x2;b2=-y2; rectangle(a1,b1,a2,b2); } void duichenx() { double a1,b1,a2,b2; a1=x1;b1=-y1;a2=x2;b2=-y2; rectangle(a1,b1,a2,b2); } void duicheny() { double a1,b1,a2,b2; a1=-x1;b1=y1;a2=-x2;b2=y2; rectangle(a1,b1,a2,b2); } void duichenxy() { double a1,b1,a2,b2; a1=y1;b1=x1;a2=y1;b2=x2; rectangle(a1,b1,a2,b2); } void duichenyx() { double a1,b1,a2,b2; a1=-y1;b1=-x1;a2=-y2;b2=-x2; rectangle(a1,b1,a2,b2); } main() { int gdriver,gmode; int select=100; double c,d,e; gdriver=DETECT; gmode=0; initgraph(&gdriver,&gmode,"d:\\\c20h\\\\bgi"); x1=50;y1=50;x2=100;y2=100; x3=x2;y3=y1;x4=x1;y4=y2; printf("please input a rectangle's two point:(x1,y1,x2,y2)"); scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); rectangle(x1,y1,x2,y2); getch(); printf("1----pingyi\\n"); printf("2----suofang"); printf("3----xuanzhuan"); printf("4----cuoqie"); printf("5----guanyu yuandian duichen\\n"); printf("6----guanyu x duichen \\n"); printf("7----guanyu y duichen \\n"); printf("8----guanyu y=x duichen \\n"); printf("9----guanyu y=-x duichen \\n"); printf("would you want to select what:(0 is exit system!) \\n"); while(select!=0) { scanf("%d",&select); if(select==1) { printf("what's distance to pingyi?"); printf("x: "); scanf("%lf",&d); printf("y: "); scanf("%lf",&c); pingyi(d,c); } else if(select==2) { printf("what's size of rectangle you want?"); scanf("%lf",&e); suofang(e); } else if(select==3) { printf("xuanzhaun's size?"); scanf("%lf",&e); xuanzhuan(e); } else if(select==4) { printf("cuoqie's size?"); scanf("%lf%lf",&c,&d); cuoqie(c,d); } else if(select==5) duichenpoint(); else if(select==6) duichenx(); else if(select==7) duicheny(); else if(select==8) duichenxy(); else if(select==9) duichenyx(); else printf("error please again! or input 0 to exit!\\n"); } closegraph(); system("pause"); } 输入一个矩形,输入想要进行的操作,得到操作之后的结果。图形转换,错切那个地方的程序有错误,其他的函数接口都写得很好。 实验三 1.实验名称 二维基本图形生成的算法实现 2.实验目的 (1) 掌握直线的两种生成算法; (2)掌握二维图形显示原理。 3.说明图形设计思想或程序流程图 (1)对各种生成算法进行效率及效果的分析和比较; (2)实现直线的生成; (3)学有余力的同学可在对现有算法理解的基础上,能自行设计二维图形的生成算法并编程实现。 算法描述: 1. 数值微分法(Digital Differential Analyzer,DDA)生成直线 (1) 算法思想:基于直线的微分方程来生成直线。 已知过端点P0 (x0, y0), P1(x1, y1)的直线段L:y=kx+b 直线斜率为 (2)数学描述 ①k ≤1 时,在x的增量方向上走步,走步的方向决定于x的符号。 xi+1=xi+ x , 计算yi+1= kxi+1+ b = kxi + b + kx = yi + kx 当x =1; yi+1 = yi+ k 即:当x每递增1,y递增k(即直线斜率); 在这种情况下,x每增加1,y最多增加1。 ②当 k 1时,在y的增量方向上走步,走步的方向决定于y的符号。 yi+1 = yi + 1 计算 xi = yi/k - b/k xi+1 = yi+1/k - b/k = (yi+1)/k - b/k = yi/k-b/k + 1/k = xi + 1/k 2. Bresenham算法生成直线 (1)算法思想 比较从理想直线到位于直线上方的像素的距离d2和相邻的位于直线下方的像素的距离d1,然后根据距离误差项的符号确定与理想直线最近的象素。 (2) 数学描述 1. 判别函数 设直线起点P0(x0,y0),终点P1(x1,y1),令e0=2y - x作为判别函数,根据e0的正负,可以确定走向: ① e0<0,Y 方向不走步 ② e0>=0,Y方向走一步 (2) 递推公式 对于第i +1步(i=0,l,2,……,n) 如果ei ≥ 0,则Y方向走一步: Xi+l= Xi+1 Yi+1 =Yi+1 ei+1= ei + 2y - 2x 如果ei<0,则Y方向不走步: Xi+l= Xi+1 Yi+1 =Yi ei+1= ei+ 2y (4)程序结果分析 #include #include double x,y; double a[50];b[50]; void run(double k,int d) { int i; if(abs(k)<=1) { for(i=2;i<=10;i++) { a[i]=a[i-1]+d; b[i]=b[i-1]+k*d; putpixel(a[i],b[i],1); getch(); } } else { for(i=2;i<=10;i++) { a[i]=a[i-1]+1/k; b[i]=b[i-1]+1; putpixel(a[i],b[i],1); getch(); } } } main() { int gdriver,gmode; gdriver=DETECT; gmode=0; initgraph(&gdriver,&gmode,"d:\\\c20h\\\\bgi"); x=50;y=50; putpixel(x,y,1); getch(); a[1]=x; b[1]=y; run(2,2); run(0.5,50); system("pause"); } 运用数值微分法得到一条直线,给定距离,斜率生成直线,这个实验简单,用了第一个算法,但是第二个算法更为精确。 实验四 1.实验名称 二维填充图的生成算法 2.实验目的 编程实现任一多边形的填充。 3.说明图形填充的思想或程序流程图 (1)算法思想 用水平扫描线从上到下扫描由点线段构成的多段构成的多边形。每根扫描线与多边形各边产生一系列交点,将这些交点按横坐标从小到大排序,将交点两两配对,并填充每一区段。多边形被扫描完毕后,填充也就完成。 (2)算法步骤: 为每一条扫描线建立新边表NET;将扫描线纵坐标y的初值置为NET中非空元素的最小序号;置活性边表AET为空; 执行下列步骤直至NET和AET都为空; 如果NET中的第y类非空,则将其中的所有边取出并插入AET中,在插入过程中进行排序; 对AET中的边两两配对,将每对边中x坐标按规则取整,获得有效的填充区段,再填充; 将当前扫描线纵坐标y值递增1,即y=1; 将AET中满足y=ymax边删去; E、 对AET中剩下的每一条边的x递增deltax,即x=x+deltax (3)程序结果分析 #include #include #include #include void draw(int x1,int y1,int x2,int y2,int delta) {int nx1,ny1,nx2,ny2; nx1=x1,ny1=y2-delta,nx2=x1+delta,ny2=y2; while((ny1>=y1)&&(nx2<=x2)) {line(nx1,ny1,nx2,ny2); getch(); ny1-=delta; nx2+=delta; } if(nx2>x2) {ny2-=nx2-x2; nx2=x2; while(ny1>y1) {line(nx1,ny1,nx2,ny2); getch(); ny1-=delta; ny2-=delta; } nx1+=y1-ny1; ny1=y1; while(nx1 getch(); nx1+=delta; ny2-=delta; } } else {nx1+=y1-ny1; ny1=y1; while(nx2 getch(); nx2+=delta; nx1+=delta; } ny2-=nx2-x2; nx2=x2; while(ny2>y1) {line(nx1,ny1,nx2,ny2); getch(); ny2-=delta; nx1+=delta; } } } int main(void) {int x1,y1,y2,x2,delta; int driver=DETECT,mode; printf("Please input lefttop(x1,y1) and rightbottom(x2,y2) of rectangle and delta:\\n"); scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&delta); initgraph (&driver,&mode,"d:\\\c20h\\\\bgi"); /*这里*/rectangle(x1,y1,x2,y2); getch(); draw(x1,y1,x2,y2,delta); gotoxy(1,1); printf("Press any key to exit!"); getch(); closegraph(); return 0; } 利用活性边表,对图形进行填充,网上有这种算法的模板,稍加修改就可以形成图形,做这个实验的时候,增加了一点知识,getch()是和C语言中的getchar()是一个意思,都是吸收字符用的,但在这个软件中按理来说就是C语言编程工具,但是用getchar()却不可以,软件之间还是有点差别吧。 实验五 1.实验名称 曲线的生成算法实现 2.实验目的 (1) 掌握B样条曲线、Bezier曲线的定义; (2) 能编程实现N 次B样条曲线、Bezier曲线的绘制与显示。 3.说明图形设计思想或程序流程图 贝塞尔曲线的参数向量表达式 通常,n+1个顶点定义一个n次多项式。 其中 称为伯恩斯坦(Bernstain)基函数。 4.程序结果分析 #include struct point { double x; double y; }coeff[50],coeffa[50]; struct point decas(int degree,double t) { int r,i; double t1; t1=1.0-t; for(i=1;i<=degree+1;i++) { coeffa[i]=coeff[i]; } for(r=2;r<=degree;r++) { for(i=1;i<=degree+1;i++) { coeffa[i].x=t1*coeffa[i].x+t*coeffa[i+1].x; coeffa[i].y=t1*coeffa[i].y+t*coeffa[i+1].y; } } return (coeffa[1]); } main() { int gdriver,gmode; struct point p; int i; gdriver=DETECT; gmode=1; initgraph(&gdriver,&gmode,"d:\\\c20h\\\\bgi"); coeff[1].x=50;coeff[1].y=50; coeff[2].x=60;coeff[2].y=60; coeff[3].x=70;coeff[3].y=75; coeff[4].x=30;coeff[4].y=50; moveto(coeff[1].x,coeff[1].y); getch(); for(i=1;i<=3;i++) { lineto(coeff[i+1].x,coeff[i+1].y); getch(); } for(i=1;i<=4-2;i++) { p=decas(3,0.2); lineto(p.x,p.y); getch(); } closegraph(); system("pause"); } 用到贝塞尔曲线生成算法,生成一条曲线,开始编程的时候,没有考虑到该算法的本质,贝塞尔算法是四点决定一个曲线段。我以为是所有点进行遍历。从这次论文中我收获到很多。经过了一阶段计算机图形学的学习,对于图形学中基本图形的生成算法有了一定的了解。深度研究图形学,需要高深的数学知识且每一个细化的方向需要的知识也不一样。图形学是计算机科学与技术学科的活跃前沿学科,被广泛的应用到生物学、物理学、化学、天文学、地球物理学、材料科学等领域。我深深感到这门学科涉及的领域之广是惊人的,可以说博大精深。在这个计算机的时代什么都要用到计算机技术,图形也是我们生活中重要的部分。所以我们得好好学好图形学。