计算机图形学几个算法的关键C++代码
jopen
12年前
一、中点画线算法:
//中点画线算法 void CMidPointLineView::MyMidLine(int x0, int y0, int x1, int y1) { CClientDC dc(this); int a=0; int b=0; int d1=0; int d2=0; int d=0; int x=0; int y=0; a=y0-y1; b=x1-x0; d=2*a+b; d1=2*a; d2=2*a+2*b; x=x0; y=y0; dc.SetPixel(x,y,RGB(255,0,0)); while(x<x1) { if(d<0) { x++; y++; d += d2; } else { x++; d += d1; } dc.SetPixel(x,y,RGB(255,0,0)); } }效果图如下:
二、中点画圆算法:
//画1/8圆弧 void CMidPointCircleView::MyMidCircle(int x0,int y0, int r) { CClientDC dc(this); int x=0; int y=r; float d=1.25-r; CirclePoint(x0,y0,x,y); while(x<=y) { if(d<0) { d+=2*x+3; } else { d+=2*(x-y)+5; y--; } x++; CirclePoint(x0,y0,x,y); } }效果图如下:
三、多边形裁剪算法:
//直线窗口裁剪 int CPolygonCutView::DrawLine(float x1, float y1, float x2, float y2) { CDC *pDC=GetDC(); int code1,code2,code; float x,y; CPen redpen(PS_SOLID,1,RGB(255,0,0));//创建画实线、线宽为2的红色画笔 CPen *old=pDC->SelectObject(&redpen); encode(x1,y1,code1); encode(x2,y2,code2); while(code1!=0||code2!=0) { if(code1&code2) return 1;//线段在窗口外,返回 code=code1; if(code1==0)code=code2; if(l&code) { x=left; y=y1+(y2-y1)*(left-x1)/(x2-x1); } else if(r&code) { x=right; y=y1+(y2-y1)*(right-x1)/(x2-x1); } else if(b&code) { y=bottom; x=x1+(x2-x1)*(bottom-y1)/(y2-y1); } else if(t&code) { y=top; x=x1+(x2-x1)*(top-y1)/(y2-y1); } if(code==code1) { x1=x;y1=y;encode(x,y,code1); } else { x2=x;y2=y;encode(x,y,code2); } } pDC->MoveTo(x1,y1); pDC->LineTo(x2,y2); ReleaseDC(pDC); return 1; }
效果图如下:
四、多边形区域填充算法:
//扫描线填充算法 void CFieldFillView::ScanlineSeedfill(CDC *pDC, int x, int y, COLORREF boundaryvalue, COLORREF newvalue) { int x0,xl,xr,y0,xid; int flag,xnextspan; stack<CPoint> s;//堆栈 CPoint p; s.push(CPoint(x,y));//第一个种子入栈 while (!s.empty())//堆栈不为空 { p = s.top(); s.pop();//取栈顶元素并弹栈 pDC->SetPixel(p.x,p.y,newvalue);//绘制像素点为指定颜色 x = p.x;y = p.y; x0 =x + 1; while (pDC->GetPixel(x0,y) != boundaryvalue)//填充右方元素 { pDC->SetPixel(x0,y,newvalue); x0++; } xr = x0 -1;//最右边像素 x0 = x -1; while (pDC->GetPixel(x0,y) != boundaryvalue)//填充左方像素 { pDC->SetPixel(x0,y,newvalue); x0--; } xl = x0 + 1;//最左边像素 //检查上一条和下一条扫描线,若存在边界且未填充的像素 //则选取代表各连续区间的种子像素入栈 y0 = y; for (int i=1;i>=-1;i-=2) { x0 = xr; y = y0 + i;//获得上一行和下一行 while (x0 >= xl) { flag = 0; while ((pDC->GetPixel(x0,y) != boundaryvalue) && (pDC->GetPixel(x0,y) != newvalue) && (x0 > xl)) { if (flag == 0) { flag = 1; xid = x0; } x0--; } if (flag == 1) { s.push(CPoint(xid,y));//新种子入栈 flag = 0; } xnextspan = x0; while ((pDC->GetPixel(x0,y) == boundaryvalue) || (pDC->GetPixel(x0,y) == newvalue) && (x0 >= xl)) x0--; if (xnextspan == x0) x0--; } } } }
效果图如下:
五、Bezier曲线生成算法:
//画Bezier曲线 void CBezierView::OnBezier() { CDC*pDC=GetDC(); RedrawWindow(); CPen redpen(PS_SOLID,2,RGB(255,0,0));//创建画笔 CPen *old=pDC->SelectObject(&redpen); float x0=50,y0=80,x1=150,y1=250,x2=400,y2=130,x3=300,y3=70; float x,y,dt,t,n=30.0; int i ; dt=1/n; for(i=0;i<=n;i++) { t=i*dt; x=x0*(1-t)*(1-t)*(1-t)+x1*3*t*(1-t)*(1-t)+x2*3*t*t*(1-t)+x3*t*t*t; y=y0*(1-t)*(1-t)*(1-t)+y1*3*t*(1-t)*(1-t)+y2*3*t*t*(1-t)+y3*t*t*t; if(i==0)pDC->MoveTo(x,y); pDC->LineTo(x,y); } pDC->MoveTo(x0,y0); pDC->LineTo(x1,y1); pDC->LineTo(x2,y2); pDC->LineTo(x3,y3); pDC->SelectObject(old); ReleaseDC(pDC); }
效果图如下:
工程文件下载地址:http://www.kuaipan.cn/file/id_8128290032206914.htm