当前位置:文档之家› 计算机图形学实验--完整版-带结果--vc++实现

计算机图形学实验--完整版-带结果--vc++实现

计算机图形学实验报告信息学院计算机专业20081060183 周建明综括:利用计算机编程语言绘制图形,主要实现以下内容:(1)、中点算法生成任意斜率直线,并设置线型线宽。

(2)、中点算法生成圆(3)、中点算法生成椭圆(4)、扫描算法实现任意多边形填充(5)、Cohen_Sutherland裁剪(6)、自由曲线与曲面的绘制(7)、二维图形变换(8)、三视图变换实验一、直线的生成一、实验内容根据提供的程序框架,修改部分代码,完成画一条直线的功能(中点画线法或者Bresenham画线法任选一),只要求实现在第一象限内的直线。

二、算法原理介绍双击直线生成.dsw打开给定的程序,或者先启动VC++,文件(file)→打开工作空间(open workspace)。

打开直线生成view.cpp,按注释改写下列函数:1.void CMyView::OnDdaline() (此为DDA生成直线)2.void CMyView::OnBresenhamline()(此为Bresenham画直线)3.void CMYView::OnMidPointLine()(此为中点画线法)三、程序源代码1.DDA生成直线画法程序:float x,y,dx,dy,k;dx=(float)(xb-xa);dy=(float)(yb-ya);k=dy/dx;x=xa;y=ya;if(abs(k)<1){for (x=xa;x<=xb;x++){pdc->SetPixel(x, int(y+0.5),COLOR);y=y+k;}}if(abs(k)>=1){for(y=ya;y<=yb;y++){pdc->SetPixel(int(x+0.5),y,COLOR);x=x+1/k;}}//DDA画直线结束}2.Bresenham画直线源程序:float b,d,xi,yi;int i;float k;k=(yb-ya)/(xb-xa);b=(ya*xb-yb*xa)/(xb-xa);if(k>0&&k<=1)for(i=0;i<abs(xb-xa);i++){ d=ya+0.5-k*(xa+1)-b;if(d>=0){ xi=xa+1;yi=ya;xa++;ya=ya+0.5;}if(d<0){ xi=xa+1;yi=ya+1;xa++;ya=ya+1.5;}pdc->SetPixel(xi,yi,COLOR);}//BresenHam画直线结束}3.中点画线法源程序:float b,d,xi,yi;int i;float k;k=(yb-ya)/(xb-xa);b=(ya*xb-yb*xa)/(xb-xa);if(k>0&&k<=1)for(i=0;i<abs(xb-xa);i++){ d=ya+0.5-k*(xa+1)-b;if(d>=0){ xi=xa+1;yi=ya;xa++;ya=ya+0.5;}if(d<0){ xi=xa+1;yi=ya+1;xa++;ya=ya+1.5;}pdc->SetPixel(xi,yi,COLOR); }//BresenHam画直线结束}四、实验结果1、DDA生成直线2、Bresenham画直线3、中点画线法实验二、bresenham画圆一、实验内容根据提供的程序框架,修改部分代码,用Bresenham画法画一段圆弧或者画圆。

二、算法原理介绍双击experiment.dsw打开,或者先启动VC++,文件(file)→打开工作空间(open workspace)。

打开直线生成view.cpp,按注释改写下列函数:void CMyView::OnBresenhamCircle()三、程序源代码bresenham画圆源程序void Bresenhan_circle();int x,y=180,color=1,xcenter,ycenter;x=0;int d=3-2*180;while(x<y){if(d<0){d=d+4*x+6;x=x+1;}else{d=d+4*(x-y)+10;x=x+1;y=y-1;}pdc->SetPixel(0+x,0+y,COLOR);pdc->SetPixel(0+x,0-y,COLOR);pdc->SetPixel(0-x,0+y,COLOR);pdc->SetPixel(0-x,0-y,COLOR);pdc->SetPixel(0+y,0+x,COLOR);pdc->SetPixel(0+y,0-x,COLOR);pdc->SetPixel(0-y,0+x,COLOR);pdc->SetPixel(0-y,0-x,COLOR);}四、实验结果实验三、二维图形的几何变换一、实验内容以一条直线段为例,完成目标的平移、绕任一点旋转。

(缩放等其它变换选做)二、实验步骤和方法1、打开二维变换.dsw2、改写二维变换view.cpp里的void CMyView::Onrecycle()函数(需要改写的地方我已经做了说明)。

3、生成直线的函数采用VC里的函数。

4、函数的主要任务是计算出变换后的坐标。

三、程序源代码1.目标的平移的源程序xa1=xa+dx;ya1=ya+dy;xb1=xb+dx;yb1=yb+dy;2.绕任意点旋转的源程序xa1=cos(angle/57.1)*xa-sin(angle/57.1)*ya+x-x*cos(angle/57.1)+y*sin(angle/57.1);y a1=sin(angle/57.1)*xa+cos(angle/57.1)*ya+y-y*cos(angle/57.1)-x*sin(angle/57.1); xb1=cos(angle/57.1)*xb-sin(angle/57.1)*yb+x-x*cos(angle/57.1)+y*sin(angle/57.1);y b1=sin(angle/57.1)*xb+cos(angle/57.1)*yb+y-y*cos(angle/57.1)-x*sin(angle/57.1);四、实验结果1、目标的平移的源程序2、绕任意点旋转的源程序实验四、用扫描线算法实现多边形填充:(1)算法思想:用水平扫描线从上到下扫描由点线段构成的多段定义的多边形。

每根扫描线与多边形各边产生一系列交点,将这些交点按照x坐标进行排序,将排序后的交点成对取出,作为两个端点,用所需填充的色彩画水平直线。

多边形被扫描完毕,则填充结束。

实现步骤:(1)建立边的分类表ET;(2)将扫描线纵坐标y的初值为ET中非空元素的最小序号;(3)置活化边表AEL为空;(4)执行下列步骤直至ET和AEL都为空;A、如果ET中的第y类非空,则将其中的所有边取出并插入AEL中,在插入过程忠进行排序;B、对AEL中的边两两配对,将每对边中x坐标按规则取整,获得有效的填充区段,再填充;C、将当前扫描线纵坐标y值递增1,即y=1;D、将AEL中满足y=ymax边删去;E、对AEL中剩下的每一条边的x递增deltax,即x=x+deltax;(2)程序实现typedef struct{int y_top;float x_int;int delta_y;float x_change_per_scan; }EACH_ENTRY;EACH_ENTRY sides[MAX_POINT];int x[MAX_POINT],y[MAX_POINT];int side_count,first_s,last_s,scan,bottomscan,x_int_count;void fill_area(int count){sort_on_bigger_y(count); first_s=1; last_s=1;for(scan=sides[1].y_top;scan>=bottomscan;scan--){ update_first_and_last(count,scan);process_x_intersections(first_s,last_s);draw_lines(scan,x_int_count,first_s);update_sides_list(); } }sort_on_bigger_y(int n){ int k,x1,y1;int tem;side_count=0; y1=y[n];x1=x[n]; bottomscan=y[n];for(k=1;k<n+1;k++){ if(y1!=y[k]){ side_count++; if(k!=n) tem=y[k+1];else tem=y[1];put_in_sides_list(side_count,x1,y1,x[k],y[k],tem);}else { setcolor(13); line(x1,y1,x[k],y[k]); }if(y[k]<bottomscan) bottomscan=y[k];y1=y[k];x1=x[k]; }}put_in_sides_list(int entry,int x1,int y1,int x2,int y2,int next_y) { int maxy; float x2_temp,x_change_temp;x_change_temp=(float)(x2-x1)/(float)(y2-y1);x2_temp=x2; if((y2>y1)&&(y2<next_y)){ y2--; x2_temp-=x_change_temp; }else { if((y2<y1)&&(y2>next_y)){ y2++; x2_temp+=x_change_temp; } }maxy=(y1>y2)? y1:y2;while((entry>1)&&(maxy>sides[entry-1].y_top)){ sides[entry]=sides[entry-1];entry--; }sides[entry].y_top=maxy;sides[entry].delta_y=abs(y2-y1)+1;if(y1>y2) sides[entry].x_int=x1;else sides[entry].x_int=x2_temp;sides[entry].x_change_per_scan=x_change_temp;}update_first_and_last(int count,int scan){while((sides[last_s+1].y_top>=scan)&&(last_s<count))last_s++; while(sides[first_s].delta_y==0)first_s++; }process_x_intersections(int first_s,int last_s){ int k; x_int_count=0;for(k=first_s;k<last_s+1;k++){ if(sides[k].delta_y>0){ x_int_count++;sort_on_x(k,first_s);}}}sort_on_x(int entry,int first_s){ while((entry>first_s)&&(sides[entry].x_int<sides[entry-1].x_int)) { swap(&sides[entry],&sides[entry-1]); entry--;}}swap(EACH_ENTRY *x,EACH_ENTRY *y){ int i_temp;float f_temp;i_temp=x->y_top;x->y_top=y->y_top;y->y_top=i_temp;f_temp=x->x_int;x->x_int=y->x_int;y->x_int=f_temp;i_temp=x->delta_y;x->delta_y=y->delta_y;y->delta_y=i_temp;f_temp=x->x_change_per_scan;x->x_change_per_scan=y->x_change_per_scan;y->x_change_per_scan=f_temp;}draw_lines(int scan,int x_int_count,int index){int k,x,x1,x2; for(k=1;k<(int)(x_int_count/2+1.5);k++) { while(sides[index].delta_y==0)index++; x1=(int)(sides[index].x_int+0.5);index++;while(sides[index].delta_y==0)index++;x2=(int)(sides[index].x_int+0.5);setcolor(13);line(x1,scan,x2,scan); index++;}}update_sides_list() {int k;int temp;for(k=first_s;k<last_s+1;k++){ if(sides[k].delta_y>0){ sides[k].delta_y--;sides[k].x_int-=sides[k].x_change_per_scan;}}}实验五用Cohen-Sutherland裁剪算法实现直线段裁剪:5.1编码算法:5.1.1算法思想:本算法分为三个步骤:判断线段两端是否都在窗口内,如果是,线段完全可见;否则判断线段是否显然不可见,如果是,裁剪结束。

相关主题