计算机图形学作业报告_第1页
计算机图形学作业报告_第2页
计算机图形学作业报告_第3页
计算机图形学作业报告_第4页
计算机图形学作业报告_第5页
已阅读5页,还剩19页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

计算机图形学第一次实验报告班级:1302学号:09211162姓名:鱼朝伟2012年4月20日实验目的:设计和实现一个图形函数库,具有绘制直线段、任意圆弧、椭圆弧、多边形区域的阴影填充和颜色填充等功能。(仅调用画点函数)二.实验接口:WindowsAPI:setpixel(hdc,x,y,color)。实验内容:DDA算法画直线;Bresenham算法画直线;Bresenham算法画圆弧;正负法算法画圆弧;多边形逼近法画圆弧;画椭圆弧;多边形区域的阴影填充;多边形区域的颜色填充。实验步骤:1.DDA算法画直线:算法描述:voidCTETEView::DrawLine1(CPointstart,CPointend){ intx1=start.x,y1=start.y; intx2=end.x,y2=end.y; inti; floatdx,dy,length,x=float(x1),y=float(y1); CClientDCdc(this); //计算直线长度 if(fabs(x2-x1)>=fabs(y2-y1)) length=float(fabs(x2-x1)); else length=float(fabs(y2-y1)); //计算x轴和y轴增量 dx=(x2-x1)/length; dy=(y2-y1)/length; //画直线 for(i=0;i<=length;i++) { dc.SetPixel(int(x+0.5),int(y+0.5),m_clr); x+=dx; y+=dy; }}实验结果:bresenham算法画直线:算法描述:voidCTETEView::DrawLine2(intx1,inty1,intx2,inty2){ CClientDCdc(this); inti; intdx,dy,e,x,y; intdeltay,deltax; dx=abs(x2-x1); dy=abs(y2-y1); if(dx>=dy){ e=2*dy-dx; if(x1>x2){ swap(x1,x2); swap(y1,y2); } x=x1; y=y1; if(y1>y2)deltay=-1; elsedeltay=1; for(i=0;i<=dx;i++){ dc.SetPixel(x,y,m_clr); x++; if(e>=0){ //y++; y+=deltay; e-=2*dx; } e+=2*dy; } }else{ e=2*dx-dy; if(y1>y2){ swap(x1,x2); swap(y1,y2); } x=x1; y=y1; if(x1>x2)deltax=-1; elsedeltax=1; for(i=0;i<=dy;i++){ dc.SetPixel(x,y,m_clr); y++; if(e>=0){ //y++; x+=deltax; e-=2*dy; } e+=2*dx; } }}实验结果:bresenham算法画圆弧:算法描述:voidCTETEView::DrawCircle1(intx0,inty0,intradius){ intx=0,y=radius,d=3-2*radius; while(x<=y){CirclePoints(x0,y0,x,y);//画圆弧上的八个对称点 if(d<0)d+=4*x+6; else{ d+=4*(x-y)+10; y--; } x++; }}voidCTETEView::CirclePoints(intx0,inty0,intx,inty){ CClientDCdc(this); dc.SetPixel(x0+x,y0+y,m_clr); dc.SetPixel(x0+y,y0+x,m_clr); dc.SetPixel(x0-x,y0+y,m_clr); dc.SetPixel(x0+y,y0-x,m_clr); dc.SetPixel(x0+x,y0-y,m_clr); dc.SetPixel(x0-y,y0-x,m_clr); dc.SetPixel(x0-x,y0-y,m_clr); dc.SetPixel(x0-y,y0+x,m_clr);}实验结果:正负法画圆弧:算法描述:voidCTETEView::CirclePoints(intx0,inty0,intx,inty){ CClientDCdc(this); dc.SetPixel(x0+x,y0+y,m_clr); dc.SetPixel(x0+y,y0+x,m_clr); dc.SetPixel(x0-x,y0+y,m_clr); dc.SetPixel(x0+y,y0-x,m_clr); dc.SetPixel(x0+x,y0-y,m_clr); dc.SetPixel(x0-y,y0-x,m_clr); dc.SetPixel(x0-x,y0-y,m_clr); dc.SetPixel(x0-y,y0+x,m_clr);}voidCTETEView::DrawCircle2(intx0,inty0,intradius){ intx=0,y=radius,f=0; while(y>0){ CirclePoints(x0,y0,x,y); if(f>0){ f=f-2*y+1; y--; }else{ f+=2*x+1; x++; } }// if(y==0)CirclePoints(x0,y0,x,y);}实验结果:多边形逼近法画圆弧;算法描述:voidCTETEView::DrawCircle3(intx0,inty0,intradius){ doublex=float(radius),y=float(0); doubledx=sin(PI/24),dy=cos(PI/24); doubletemp1,temp2; inti; for(i=0;i<=48;i++){ temp1=x; temp2=y; x=temp1*dy-temp2*dx; y=temp1*dx+temp2*dy; DrawLine2(int(temp1+0.5+x0),int(temp2+0.5+y0), int(x+0.5+x0),int(y+0.5+y0)); }}实验结果:画椭圆弧:算法描述:voidCTETEView::DrawEllipase(intx0,inty0,inta,intb){ intaa=a*a,bb=b*b;intx=0,y=b;intd=(int)(bb+aa*(0.25-b)+0.5);intdx=0,dy=2*aa*y; CClientDCdc(this);//画对称的四个点dc.SetPixel(x0+x,y0+y,m_clr); dc.SetPixel(x0+x,y0-y,m_clr); dc.SetPixel(x0-x,y0+y,m_clr); dc.SetPixel(x0-x,y0-y,m_clr);//画椭圆的上部分while(dx<dy) {x++;dx+=2*bb;if(d<0) //取右方像素d+=bb+dx;else //取右下方像素 {dy-=2*aa;d+=bb+dx-dy;y--;}//画对称的四个点dc.SetPixel(x0+x,y0+y,m_clr); dc.SetPixel(x0+x,y0-y,m_clr); dc.SetPixel(x0-x,y0+y,m_clr); dc.SetPixel(x0-x,y0-y,m_clr);}d=(int)(bb*(x+0.5)*(x+0.5)+aa*(y-1)*(y-1)-aa*bb+0.5);//画椭圆的下部分while(y>0) {y--;dy-=2*aa;if(d>0) //取下方像素d+=aa-dy;else //取右下方像素 {dx+=2*bb;d+=aa-dy+dx;x++;}//画对称的四个点dc.SetPixel(x0+x,y0+y,m_clr); dc.SetPixel(x0+x,y0-y,m_clr); dc.SetPixel(x0-x,y0+y,m_clr); dc.SetPixel(x0-x,y0-y,m_clr);}}实验结果:多边形的阴影填充:算法描述:voidCTETEView::DrawPolygon(CPointpoint){ //画外环 if(CountPoint<m_nOut) { CountPoint++; P1[CountPoint-1]=point; DrawLine1(P1[CountPoint-2],point); } if(CountPoint==m_nOut) {//画最后一条边 DrawLine1(P1[0],point); if(m_nInner==0){ CountPoint=0; P1[9].x=m_nOut; P2[9].x=m_nInner; return; } } if((CountPoint>m_nOut)&&(CountPoint-m_nOut<m_nInner)) { CountPoint++; P2[CountPoint-m_nOut-1]=point; DrawLine1(P2[CountPoint-m_nOut-2],point); } if((CountPoint-m_nOut)==m_nInner) //画最后一条边 { DrawLine1(P2[0],point); CountPoint=0; P1[9].x=m_nOut; P2[9].x=m_nInner; } }voidCTETEView::OnShade(){ //TODO:Addyourcommandhandlercodehere m_nDrawType=8; CATTRatr; atr.m_nAngle=m_nAngle; atr.m_nDistance=m_nDistance; if(IDOK==atr.DoModal()) { m_nAngle=atr.m_nAngle; m_nDistance=atr.m_nDistance; if(P1[9].x==-1) MessageBox("图形不是多边形或多边形没有画完,不能进行阴影填充!","警告",MB_OK|MB_ICONWARNING); }}voidCTETEView::DrawShade(){ floata=m_nAngle*PI/180; floatk=-tan(a); //阴影线斜率 //floatdb=m_nDistance/abs(cos(a)); Calculate_B(k); //计算多边形棱边和棱边两顶点按阴影线斜率引线得到的截距 swap(m_nclr,m_clr); intBmin=B[0][0],Bmax=B[0][1]; for(inti=1;i<P1[9].x+P2[9].x;i++) { if(B[i][0]<Bmin) Bmin=B[i][0]; if(B[i][1]>Bmax) Bmax=B[i][1]; } intdeltab=int(m_nDistance/(fabs(cos(a))));//阴影线截距增量 intb=Bmin+deltab; //第一条阴影线的截距 //画阴影线部分 for(;b<Bmax;b+=deltab) //对每条阴影线 { // InitD(); //初始化存放阴影线与各棱边的交点的数组 intCountCross=0; //交点个数 for(inti=0;i<P1[9].x+P2[9].x;i++) { if(IsCross(i,b)) { intxp,yp,xq,yq,xl,yl; xp=Edge[i].xp,yp=Edge[i].yp; xq=Edge[i].xq,yq=Edge[i].yq; //计算交点并存入D数组 xl=int((xp*yq-yp*xq+b*(xq-xp))/((yq-yp)-k*(xq-xp))); yl=int(k*xl+b); D[CountCross][0]=xl; D[CountCross][1]=yl; CountCross++; } } if(CountCross>1) SortCross(CountCross); //把所有交点按x递增是顺序进行排序for(intj=1;j<CountCross;j+=2) { intx1,x2,y1,y2; x1=D[j-1][0]; y1=D[j-1][1]; x2=D[j][0]; y2=D[j][1]; DrawLine2(x1,y1,x2,y2); //生成阴影线段 } } swap(m_nclr,m_clr);}voidCTETEView::Calculate_B(floatk){ intx,y,b1,b2,i; //处理外环棱边 for(i=0;i<P1[9].x-1;i++) { Edge[i].xp=x=P1[i].x; Edge[i].yp=y=P1[i].y; b1=int(y-k*x); Edge[i].xq=x=P1[i+1].x; Edge[i].yq=y=P1[i+1].y; b2=int(y-k*x); if(b1<=b2) //把较小的放在第一个存储单元,较大的放在第二个存储单元 { B[i][0]=b1; B[i][1]=b2; } else { B[i][0]=b2; B[i][1]=b1; } } Edge[i].xp=x=P1[i].x; Edge[i].yp=y=P1[i].y; b1=int(y-k*x); Edge[i].xq=x=P1[0].x; Edge[i].yq=y=P1[0].y; b2=int(y-k*x); if(b1<=b2) { B[i][0]=b1; B[i][1]=b2; } else { B[i][0]=b2; B[i][1]=b1; } //处理内孔棱边 if(P2[9].x!=-1) { for(i=0;i<P2[9].x-1;i++) { Edge[i+P1[9].x].xp=x=P2[i].x; Edge[i+P1[9].x].yp=y=P2[i].y; b1=int(y-k*x); Edge[i+P1[9].x].xq=x=P2[i+1].x; Edge[i+P1[9].x].yq=y=P2[i+1].y; b2=int(y-k*x); if(b1<=b2) { B[i+P1[9].x][0]=b1; B[i+P1[9].x][1]=b2; } else { B[i+P1[9].x][0]=b2; B[i+P1[9].x][1]=b1; } } Edge[i+P1[9].x].xp=x=P2[i].x; Edge[i+P1[9].x].yp=y=P2[i].y; b1=int(y-k*x); Edge[i+P1[9].x].xq=x=P2[0].x; Edge[i+P1[9].x].yq=y=P2[0].y; b2=int(y-k*x); if(b1<=b2) { B[i+P1[9].x][0]=b1; B[i+P1[9].x][1]=b2; } else { B[i+P1[9].x][0]=b2; B[i+P1[9].x][1]=b1; } }}voidCTETEView::SortCross(intCountCross){ intpass,i,temp; //冒泡排序 for(pass=1;pass<CountCross;pass++) { for(i=0;i<=CountCross-pass-1;i++) { if(D[i][0]>D[i+1][0]) { temp=D[i][0]; D[i][0]=D[i+1][0]; D[i+1][0]=temp; temp=D[i][1]; D[i][1]=D[i+1][1]; D[i+1][1]=temp; } } }}BOOLCTETEView::IsCross(inti,intbj){ intmin=B[i][0]; intmax=B[i][1]; if((min<=bj)&&(bj<max)) //相交 returnTRUE; else //不相交 returnFALSE;}实验结果:多边形的颜色填充:算法描述:voidCTETEView::ColorFill(CPointv,COLORREFcolor){ inti,j,Bmax=-0x7fffffff,Bmin=0x7fffffff,Brange; intvsize=v.size(); for(i=0;i<=vsize-1;i++) { if(v[i].y>Bmax) Bmax=v[i].y; if(v[i].y<Bmin) Bmin=v[i].y; } Brange=Bmax-Bmin; EDGE**ET=newEDGE*[Brange]; EDGE*AEL=NULL; EDGE*AELItr=NULL; EDGE*prevAELItr=NULL; CPointdrawPoint; for(i=0;i<=Brange-1;i++) ET[i]=NULL; for(i=0;i<=vsize-1;i++) if(v[i].y!=v[(i+1)%vsize].y)//排除水平边 InsertEdgeToET(v,ET,Bmin,v[i],v[(i+1)%vsize]); for(i=0;i<=Brange-1;i++) { //把ET[i]接在AEL上,保持按X升序,x相同时按dtx升序 if(AEL==NULL) AEL=ET[i]; elseif(ET[i]==NULL) AEL=AEL; else MergeSortList(&ET[i],&AEL); //将AEL中x域两两配对,连水平线 AELItr=AEL; while(AELItr!=NULL&&AELItr->next!=NULL) { drawPoint.y=i+Bmin; for(j=AELItr->x;j<=AELItr->next->x;j++) { drawPoint.x=j; pDC->SetPixel(drawPoint,color); } AELItr=AELItr->next->next; } //扫描AEL,ymax为当前水平线截距的边删除 //其余边执行:x+=dtx AELItr=AEL; prevAELItr=AELItr; if(AELItr!=NULL)//AEL链不为空 { if(AELItr->next==NULL)//AEL链长为1 { if(AELItr->ymax==i)//此边该被删除 { deleteAELItr; AELItr=NULL; AEL=NULL; } else//此边不该被删除 AELItr->x+=AELItr->dtx; } else//AEL链长>=2 { while(AELItr!=NULL) { if(AELItr->ymax==i+Bmin)//要删除该节点 { if(AELItr==AEL)//当前要删除的是头节点 { prevAELItr=AELItr->next; AEL=prevAELItr; deleteAELItr; AELItr=prevAELItr; } else//要删除的不是头结点 { prevAELItr->next=AELItr->next; deleteAELItr; AELItr=prevAELItr->next; } } else//不用删除 { AELItr->x+=AELItr->dtx; prevAELItr=AELItr; AELItr=AELItr->next; } } } } }}//将边插入边表ET中//包含非极值奇点预处理voidCTETEView::InsertEdgeToET(CPointv,EDGE**ET,intBmin,CPointp1,CPointp2){ if(p1.y>p2.y) { CPointptmp=p1; p1=p2; p2=ptmp; } //以上保证p1为下端点p2为上端点 intkind; if(GetIntersectNum(v,p1.y)==2) kind=p1.y+1-Bmin; else kind=p1.y-Bmin; //以上为非极值奇点预处理 EDGE*tmp=newEDGE; tmp->ymax=p2.y; tmp->x=p1.x; tmp->dtx=(p2.x-p1.x)/double(p2.y-p1.y); tmp->next=NULL; EDGE*itr=ET[kind],*prev=itr; if(prev==NULL)//待插入的原链表为空 ET[kind]=tmp; else//待插入的原链表非空 { if(prev->x>tmp->x||prev->x==tmp->x&&prev->dtx>tmp->dtx)//要插入在链表头 { ET[kind]=tmp; tmp->next=prev; } else//不插入在链表头 { itr=itr->next; while(itr!=NULL&&(itr->x<tmp->x||itr->x==tmp->x&&itr->dtx<tmp->dtx))//保持链表升序 { prev=itr; itr=itr->next; } prev->next=tmp;

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论