计算机图形学实验报告直线的生成程序设计:实验目的:掌握直线段的生成算法, 并用C/WIN-TC/VC++实现算法, 包括中点法生成直线, 微分数值法生成直线段等。
实验内容:用不同的方法生成斜率不同的直线段, 比较各种方法的效果。
/////////////////////////////////////////////////////////////////////////////// CLineView drawingvoid DDALine(int x1,int y1,int x2,int y2,int color,CDC*pDC)//数值微分法{int x;int k,y=y1;k=1.0*(y2-y1)/(x2-x1);for(x=x1;x<=x2;x++){pDC->SetPixel(x,(int)(y+0.5),color);y=y+k;}}void MPLine(int x1,int y1,int x2,int y2,int color,CDC*pDC)//中点画线法{int x,y,a,b,d,d1,d2;a=y1-y2; b=x2-x1;y=y1;d=2*a+b; d1=2*a; d2=2*(a+b);pDC->SetPixel(x,y,color);for(x=x1;x<=x2;x++){if(d<0) { y++; d+=d2;}else {d+=d1;}pDC->SetPixel(x,y,color);}}void BHLine(int x1,int y1,int x2,int y2,int color,CDC*pDC)//Bresenham画线法{int x,y,dx,dy,dk;dx=abs(x2-x1);dy=abs(y2-y1);dk=2*dy-dx;y=y1;for(x=x1;x<=x2;x++){pDC->SetPixel(x,y,color);dk=dk+2*dy;if(dk>=0){ y++; dk=dk-2*dx;}}}void CLineView::OnDraw(CDC* pDC){CLineDoc* pDoc = GetDocument();ASSERT_V ALID(pDoc);DDALine(100,100,200,70,255,pDC);//数值微分法pDC->TextOut(200,70,"数值微分画线");MPLine(100,120,200,140,255,pDC);//中点画线法pDC->TextOut(200,140,"中点画线");BHLine(100,140,200,190,255,pDC);//Bresenham画线法pDC->TextOut(200,190,"Bresenham画线法");// TODO: add draw code for native data here}运行结果:2.圆的生成程序设计:实验目的:掌握用C/WIN-TC/VC++实现算法, 圆的生成算法实验内容: 用中点画圆法、Bresenham画圆法/////////////////////////////////////////////////////////////////////////////// CCircleView drawingvoid WholeCircle(int xc,int yc,int x,int y,int color,CDC*pDC){pDC->SetPixel(xc+x,yc+y,color);pDC->SetPixel(xc-x,yc+y,color);pDC->SetPixel(xc+x,yc-y,color);pDC->SetPixel(xc-x,yc-y,color);pDC->SetPixel(xc+y,yc+x,color);pDC->SetPixel(xc-y,yc+x,color);pDC->SetPixel(xc+y,yc-x,color);pDC->SetPixel(xc-y,yc-x,color);}void MidCircle(int xc,int yc,int r,int color,CDC*pDC )//中点画圆法{int x,y,d;x=0;y=r;d=1-r;WholeCircle(xc,yc,x,y,color,pDC);while(x<=y){if(d<0){ d+=2*x+3;x++;}else{ d+=2*(x-y)+5;x++; y--;}WholeCircle(xc,yc,x,y,color,pDC);}WholeCircle(xc,yc,x,y,color,pDC);}void BresenhamCircle(int xc,int yc,int r,int color,CDC*pDC)//Bresenham画圆法{ int x,y,d;x=0; y=r;d=3-2*r;while(x<y){WholeCircle(xc,yc,x,y,color,pDC);if(d<0)d=d+4*x+6;else{d=d+4*(x-y)+10;y--;}x++;}if(x==y) WholeCircle(xc,yc,x,y,color,pDC);}void CCircleView::OnDraw(CDC* pDC){CCircleDoc* pDoc = GetDocument();ASSERT_V ALID(pDoc);MidCircle(100,100,70,255,pDC);//中点画圆法pDC->TextOut(175,100,"中点画圆法");BresenhamCircle(100,250, 80, 255,pDC);//Bresenham画圆法pDC->TextOut(185,250,"Bresenham画圆法");// TODO: add draw code for native data here}运行结果:3.椭圆的生成程序设计:实验目的:掌握用C/WIN-TC/VC++实现算法, 椭圆的生成算法实验内容: 实现椭圆的算法// CMPEllipseView drawingvoid WholeEllipse(int xc,int yc,int x,int y,int color,CDC*pDC) {pDC->SetPixel(xc+x,yc+y,color);pDC->SetPixel(xc+x,yc-y,color);pDC->SetPixel(xc-x,yc+y,color);pDC->SetPixel(xc-x,yc-y,color);}void MidEllipse(int xc,int yc,int a,int b,int color,CDC*pDC) {int aa=a*a, bb=b*b;int twoaa=2*aa, twobb=2*bb;int x=0, y=b;int dx=0, dy=twoaa*y;int d=(int)(bb+aa*(-b+0.25)+0.5);WholeEllipse(xc,yc,x,y,color,pDC);while(dx<dy){x++; dx+=twobb;if(d<0)d+=bb+dx;else{ y--;dy-=twoaa;d+=bb+dx-dy;}WholeEllipse(xc,yc,x,y,color,pDC);}d=(int)(bb*(x+0.5)*(x+0.5)+aa*(y-1)*(y-1)-aa*bb+0.5);while(y>0){y--; dy-=twoaa;if(d>0)d+=aa-dy;else{ x++;dx+=twobb; d+=aa-dy+dx; }WholeEllipse(xc,yc,x,y,color,pDC);}}void CMPEllipseView::OnDraw(CDC* pDC){CMPEllipseDoc* pDoc = GetDocument();ASSERT_V ALID(pDoc);MidEllipse(200,100,100,50,255, pDC);pDC->TextOut(305,100,"中点画椭圆法");// TODO: add draw code for native data here }运行结果:4.有序边表填充算法程序设计实验目的:掌握用C/WIN-TC/VC++实现算法, 有序边生成算法实验内容: 实现有序边填充算法代码如下:#define WINDOW_HEIGHT 480#define NULL 0typedef struct tEdge /* 有序便表和活化边表的结构 */ {int ymax;float x,dx;struct tEdge *next;} Edge;typedef struct point{int x,y;} tPOINT;void InsertEdge(Edge *list,Edge *edge){Edge *p,*q = list;p = q->next;while(p){if (edge->x < p->x){p = NULL;}else{q = p;p = p->next;}}edge->next = q->next;q->next = edge;}int yNext(int k,int cnt,tPOINT *pts){int j;if ((k+1)>(cnt-1)){j = 0;}else{j = k+1;}while(pts[k].y == pts[j].y){ if ((j+1) > (cnt-1)){ j = 0;}else{ j++;}}return pts[j].y;}void MakeEdgeRec(tPOINT lower,tPOINT upper,int yComp,Edge *edge,Edge *edges[]) /* 生成有序边表的一条边 */{edge->dx = (float)(upper.x - lower.x)/(upper.y - lower.y);edge->x = lower.x;if (upper.y < yComp){edge->ymax = upper.y - 1;}else{edge->ymax = upper.y;}InsertEdge(edges[lower.y],edge);}void BuildEdgeList(int cnt,tPOINT *pts,Edge *edges[]){ Edge *edge;tPOINT v1,v2;int i,yPrev = pts[cnt-2].y;v1.x = pts[cnt-1].x;v1.y = pts[cnt-1].y;for (i = 0;i < cnt;i++){v2 = pts[i];if (v1.y != v2.y){edge = (Edge *)malloc(sizeof(Edge)); /* C语言中的malloc */if (v1.y < v2.y){MakeEdgeRec(v1,v2,yNext(i,cnt,pts),edge,edges);}else{MakeEdgeRec(v2,v1,yPrev,edge,edges);}yPrev = v1.y;v1 = v2;}}}void BuildActiveList(int scan,Edge *active,Edge *edges[]){Edge *p,*q;p = edges[scan]->next;while (p){q = p->next;InsertEdge(active,p);p = q;}}void FillScan(int scan,Edge *active,int color,CDC *pDC){int i;Edge *p1,*p2;p1 = active->next;while(p1){p2 = p1->next;for (i = p1->x;i < p2->x;i++){pDC->SetPixel((int)i,scan,color);}p1 = p2->next;}}void DeletAfter(Edge *q){Edge *p = q->next;q->next = p->next;free(p);}void UpdateActiveList(int scan,Edge *active){Edge *q = active,*p = active->next;while(p){if (scan >= p->ymax){p = p->next;DeletAfter(q);}else{p->x = p->x + p->dx;q = p;p = p->next;}}}void ResortActiveList(Edge *active){Edge *q,*p = active->next;active->next = NULL;while(p){q = p->next;InsertEdge(active,p);p = q;}}void ScanFill(int cnt,tPOINT *pts,int color,CDC *pDC) {Edge *edges[WINDOW_HEIGHT],*active;int i,scan,scanmax = 0,scanmin = WINDOW_HEIGHT;for (i = 0;i < cnt-1;i++){if (scanmax < pts[i].y){scanmax = pts[i].y;}if (scanmin > pts[i].y){scanmin = pts[i].y;}}for (scan = scanmin;scan <= scanmax;scan++){edges[scan] = (Edge *)malloc(sizeof(Edge));edges[scan]->next = NULL;}BuildEdgeList(cnt,pts,edges);active = (Edge *)malloc(sizeof(Edge));active->next = NULL;for (scan = scanmin;scan <= scanmax;scan++){BuildActiveList(scan,active,edges);if (active->next){FillScan(scan,active,color,pDC);UpdateActiveList(scan,active);ResortActiveList(active);}}}CFillView::CFillView(){// TODO: add construction code here}CFillView::~CFillView(){}BOOL CFillView::PreCreateWindow(CREATESTRUCT& cs){// TODO: Modify the Window class or styles here by modifying// the CREATESTRUCT csreturn CView::PreCreateWindow(cs);}///////////////////////////////////////////////////////////////////////////// // CFillView drawingvoid CFillView::OnDraw(CDC* pDC){CFillDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);// TODO: add draw code for native data heretPOINT points[3]={{100,80},{300,100},{300,260}};tPOINT *p = points;int color = RGB(255,2,0);ScanFill(3,p,color,pDC);}运行结果:8.Cohen-SutherLand编码裁剪算法程序设计#define LEFT 1#define RIGHT 2#define BOTTOM 4#define TOP 8typedef struct point { int x,y;} POINT1;void Encode (int x,int y,int *code,int XL,int XR,int YB,int YT,CDC *pDC) {int c=0;if(x<XL) c=c|LEFT;else if(x>XR) c=c|RIGHT;if (y<YB) c=c|BOTTOM;else if (y>YT) c=c|TOP;(*code)=c;}void C_S_Line(POINT p1,POINT p2,int XL,int XR,int YB,int YT,CDC *pDC) {int x1,x2,y1,y2,x,y;int code1,code2,code;x1=p1.x;x2=p2.x;y1=p1.y;y2=p2.y;Encode(x1,y1,&code1,XL,XR,YB,YT,pDC);Encode(x2,y2,&code2,XL,XR,YB,YT,pDC);while(code1!=0 || code2!=0){if ((code1 & code2) !=0) return;code=code1;if (code1==0) code=code2;if ((LEFT & code) !=0){x=XL;y=y1+(y2-y1)*(XL-x1)/(x2-x1);}else if((RIGHT & code)!=0){x=XR;y=y1+(y2-y1)*(XR-x1)/(x2-x1);}else if((BOTTOM & code) != 0){y=YB;x=x1+(x2-x1)*(YB-y1)/(y2-y1);}else if((TOP & code)!=0){y=YT;x=x1+(x2-x1)*(YT-y1)/(y2-y1);}if(code==code1){x1=x; y1=y;Encode(x,y,&code1,XL,XR,YB,YT,pDC);}else{x2=x; y2=y;Encode(x,y,&code2,XL,XR,YB,YT,pDC);}}p1.x=x1;p1.y=y1;p2.x=x2;p2.y=y2;pDC->MoveTo(p1.x,p1.y);pDC->LineTo(p2.x,p2.y);}void CCohenView::OnDraw(CDC* pDC){CCohenDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);POINT p1,p2,p3,p4,p5,p6,p7,p8;p1.x=35;p1.y=160;p2.x=245;p2.y=121;p3.x=120;p3.y=60;p4.x=200;p4.y=300;p5.x=169;p5.y=45;p6.x=150;p6.y=200;p7.x=120;p7.y=200;p8.x=220;p8.y=130;pDC->LineTo(120,100);pDC->LineTo(210,100);pDC->LineTo(220,180);pDC->LineTo(120,170);pDC->LineTo(110,100);C_S_Line(p1,p2,100,200,90,170,pDC); C_S_Line(p3,p4,100,200,90,170,pDC); }运行结果:6.基于链队列的种子填充算法程序设计程序代码:#define NULL 0typedef struct point{ int x,y;}POINT1;typedef struct QNode{POINT Data;struct QNode *Next;}QNode,*QPtr;typedef struct{QPtr Front;QPtr Rear;}LinkQueue;LinkQueue q;void CreateQueue(){q.Front=q.Rear=(QPtr)malloc(sizeof(QNode));q.Rear->Next=NULL;}POINT Dequeue(){QNode *p;POINT x;p=q.Front;x=q.Front->Data;q.Front=q.Front->Next;free(p);return x;}void Enqueue(POINT x){QNode *p=(QPtr)malloc(sizeof(QNode));q.Rear->Next=p;q.Rear->Data=x;q.Rear=p;}int Empty(){if( q.Front==q.Rear)return 1;else return 0;}void QueueSeedFill(int seedx, int seedy, int fcolor, int bcolor,CDC *pDC) {int color;POINT pt,p,p1,p2,p3,p4;pDC->SetPixel(seedx,seedy,fcolor);p.x=seedx;p.y=seedy;Enqueue(p);while(!Empty()){pt=Dequeue();color=pDC->GetPixel(pt.x,pt.y-1);if(color!=bcolor && color!=fcolor){pDC->SetPixel(pt.x,pt.y-1,fcolor);p1.x=pt.x;p1.y=pt.y-1;Enqueue(p1);}color= pDC->GetPixel(pt.x,pt.y+1);if(color!=bcolor && color!=fcolor){pDC->SetPixel(pt.x,pt.y+1,fcolor);p2.x=pt.x;p2.y=pt.y+1;Enqueue(p2);}color=pDC->GetPixel(pt.x-1,pt.y);if(color!=bcolor && color!=fcolor){pDC->SetPixel(pt.x-1,pt.y,fcolor);p3.x=pt.x-1;p3.y=pt.y;Enqueue(p3);}color=pDC->GetPixel(pt.x+1,pt.y);if(color!=bcolor && color!=fcolor){pDC->SetPixel(pt.x+1,pt.y,fcolor);p4.x=pt.x+1;p4.y=pt.y;Enqueue(p4);}}}void EdgeMark(int x1,int y1,int x2,int y2,int color,CDC *pDC){int i,length;float dx,dy,x=x1,y=y1;if (abs(x2-x1)>=abs (y2-y1))length=abs(x2-x1);elselength=abs(y2-y1);dx=(float)(x2-x1)/length;dy=(float)(y2-y1)/length;pDC->SetPixel((int)(x+0.5),(int)(y+0.5),color);for(i=1;i<=length;i++){x=x+dx;y=y+dy;pDC->SetPixel((int)(x+0.5),(int)(y+0.5),color);}}void QSeedFill(int cnt,POINT *pts,int seedx,int seedy,int fcolor,int bcolor,CDC *pDC){POINT v1,v2;int i;for(i=0;i<cnt-1;i++){v1=pts[i]; v2=pts[i+1];EdgeMark(v1.x,v1.y,v2.x,v2.y,bcolor,pDC);}QueueSeedFill(seedx,seedy,fcolor,bcolor,pDC); }void CQseedFillView::OnDraw(CDC* pDC){CQseedFillDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);POINT pts[7];pts[0].x=40;pts[0].y=12;pts[1].x=75;pts[1].y=45;pts[2].x=110;pts[2].y=20;pts[3].x=130;pts[3].y=70;pts[4].x=80;pts[4].y=110;pts[5].x=25;pts[5].y=60;pts[6].x=40;pts[6].y=15;QSeedFill(8,pts,70,80,2,4,pDC);}运行结果:13.Bezier曲线绘制程序设计程序代码如下:// CBezierView drawingtypedef struct point {int x,y;}POINT1;void Parabola(POINT *p,int n,CDC *pDC){int x,y,i,j,k=10;double t1,t2,t3,t,a,b,c,d;p[n].x=p[n-1].x;p[n].y=p[n-1].y;t=0.5/k;pDC->MoveTo(p[1].x,p[1].y);for(i=1;i<n-1;i++){for(j=1;j<k;j++){t1=j*t;t2=t1*t1;t3=t2*t1;a=4.0*t2-t1-4.0*t3; b=1.0-10.0*t2+12.0*t3;c=t1+8.0*t2-12.0*t3; d=4.0*t3-2.0*t2;x=(int)(a*p[i-1].x+b*p[i].x+c*p[i+1].x+d*p[i+2].x);y=(int)(a*p[i-1].y+b*p[i].y+c*p[i+1].y+d*p[i+2].y);pDC->LineTo(x,y);}pDC->LineTo(p[i+1].x,p[i+1].y);}}double powi(double v,int k){int i;double temp=1.0;if(k==0 || v==0)return 1;else{for(i=1;i<=k;i++)temp=temp*v;}return temp;}long fac(int m){int i;long temp=1;if(m==0)return 1;else{for(i=2;i<=m;i++)temp=temp*i;}return temp;}void Bezier(POINT *p,int n,CDC *pDC){int x,y,i,j,k=100;double t,t1,u,v;double temp,temp1,temp2,bi;t=1.0/k;pDC->MoveTo(p[0].x,p[0].y);for(j=1;j<k;j++){t1=j*t;u=t1;v=1-u;x=0;y=0;for(i=0;i<=n;i++){temp=(double)fac(n)/fac(i)/fac(n-i);temp1=powi(u,i);temp2=powi(v,n-i);bi=temp*temp1*temp2;x=x+bi*p[i].x;y=y+bi*p[i].y;}pDC->LineTo(x,y);}pDC->LineTo(p[n].x,p[n].y);}void BSpLine(POINT *p, int n,CDC *pDC){int x,y,i,j,k=1000;double t,t1,t2,t3,a,b,c,d;t=1.0/k;p[n].x=2*p[n-1].x-p[n-2].x;p[n].y=2*p[n-1].y-p[n-2].y;pDC->MoveTo(p[1].x,p[1].y);for(i=1;i<n-1;i++){for(j=1;j<=k;j++){t1=j*t;t2=t1*t1;t3=t2*t1;a=(3*t2-t3-3*t1+1)/6;b=(3*t3-6*t2+4)/6;c=(3*t2-3*t3+3*t1+1)/6;d=t3/6;x=(int)(a*p[i-1].x+b*p[i].x+c*p[i+1].x+d*p[i+2].x);y=(int)(a*p[i-1].y+b*p[i].y+c*p[i+1].y+d*p[i+2].y);pDC->LineTo(x,y);}}}void CardinalSpLine(POINT *p,int n,float tension,CDC *pDC) {int x,y,i,j,k=1000;double t,t1,t2,t3,a,b,c,d,s;t=1.0/k;s=(1.0-tension)/2.0;p[n].x=2*p[n-1].x-p[n-2].x;p[n].y=2*p[n-1].y-p[n-2].y;pDC->MoveTo(p[1].x,p[1].y);for(i=1;i<n-1;i++){for(j=1;j<=k;j++){t1=j*t;t2=t1*t1;t3=t2*t1;a=-s*t3+2*s*t2-s*t1;b=(2-s)*t3+(s-3)*t2+1;c=(s-2)*t3+(3-2*s)*t2+s*t1;d=s*t3-s*t2;x=(int)(a*p[i-1].x+b*p[i].x+c*p[i+1].x+d*p[i+2].x);y=(int)(a*p[i-1].y+b*p[i].y+c*p[i+1].y+d*p[i+2].y);pDC->LineTo(x,y);}}}void CBezierView::OnDraw(CDC* pDC){CBezierDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);int n=5;POINT ps[4];ps[0].x=60;ps[0].y=200;ps[1].x=50;ps[1].y=200;ps[2].x=160;ps[2].y=60;ps[3].x=200;ps[3].y=200;ps[4].x=350;ps[4].y=60;pDC->MoveTo(ps[0].x,ps[0].y);pDC->LineTo(ps[1].x,ps[1].y);pDC->LineTo(ps[2].x,ps[2].y);pDC->LineTo(ps[3].x,ps[3].y);Parabola(ps,n,pDC);CardinalSpLine(ps,n,0.5,pDC);Bezier(ps,n-1,pDC);BSpLine(ps,n,pDC);}。