计算机图形学常用算法及代码大全
MFC实现计算机图形学算法

MFC实现计算机图形学算法⽬录1.直线算法1.1 DDAvoid ChuituView::OnDDA(){// TODO: 在此添加命令处理程序代码dlg_line dlg;dlg.DoModal();CDC* pDC = GetDC();CRect rect;GetClientRect(&rect);//重定义坐标轴Axis(pDC, rect);pDC->TextOut(450, 18, _T("DDA画线法成功了!"));//在屏幕(450,18)的位置显⽰⼀个⽩⾊底⾊的⿊字:DDA画线法成功了!double dx, dy, e, x, y;dx = dlg.x2 - dlg.x1;dy = dlg.y2 - dlg.y1;e = (fabs(dx) > fabs(dy) ? fabs(dx) : fabs(dy));dx /= e;dy /= e;x = dlg.x1;y = dlg.y1;for (int i = 1; i <= e; ++i) {pDC->SetPixel(int(x + 0.5), int(y + 0.5), RGB(255, 0, 0));x += dx;y += dy;}}1.2 中点法void ChuituView::OnMidpointline(){// TODO: 在此添加命令处理程序代码dlg_line dlg;dlg.DoModal();float x, y, xa, xb, ya, yb;xa = dlg.x1, ya = dlg.y1;xb = dlg.x2; yb = dlg.y2;float d, k;CDC* pDC = GetDC();CRect rect;GetClientRect(&rect);//重定义坐标轴Axis(pDC, rect);pDC->TextOut(450, 18, _T("中点画线法成功了!"));k = (yb - ya) / (xb - xa);y = ya, x = xa;d = 0.5 - k;for (x = xa; x <= xb; x++){if (d < 0){y = y + 1; d = d + 1 - k;}else{y = y; d = d - k;}pDC->SetPixel(x, y, RGB(0, 0, 255));}}1.3Bresenham法void ChuituView::OnBresenhamline_1(int x0, int y0, int x1, int y1){// TODO: 在此处添加实现代码.CDC* pDC = GetDC();pDC->TextOut(450, 70, _T("请⽤⿏标划线!"));// TODO: 在此添加命令处理程序代码int color = 255;int x, y, e;int dx = x1 - x0;//x偏移量int dy = y1 - y0;//y偏移量int ux = dx > 0 ? 1 : -1;//x伸展⽅向int uy = dy > 0 ? 1 : -1;//y伸展⽅向int dx2 = abs(dx << 1);//x偏移量乘2int dy2 = abs(dy << 1);//y偏移量乘2if (abs(dx) > abs(dy))//以x为增量⽅向计算{int e = -dx; //e = -0.5 * 2 * dx,把e ⽤2 * dx* e替换int x = x0;//起点x坐标int y = y0;//起点y坐标while (x != x1 + ux){//printf("%d,%d\n", x, y);pDC->SetPixel(x, y, color);e = e + dy2;//来⾃ 2*e*dx= 2*e*dx + 2dy (原来是 e = e + k)if (e > 0)//e是整数且⼤于0时表⽰要取右上的点(否则是右下的点) {if (y != y1){y += uy;}e = e - dx2;//2*e*dx = 2*e*dx - 2*dx (原来是 e = e -1)}x += ux;}}else{//以y为增量⽅向计算int e = -dy; //e = -0.5 * 2 * dy,把e ⽤2 * dy* e替换int x = x0;//起点x坐标int y = y0;//起点y坐标while (y != y1 + uy){//printf("%d,%d\n", x, y);pDC->SetPixel(x, y, color);e = e + dx2;//来⾃ 2*e*dy= 2*e*dy + 2dy (原来是 e = e + k)if (e > 0)//e是整数且⼤于0时表⽰要取右上的点(否则是右下的点) {if (x != x1){x += ux;}e = e - dy2;//2*e*dy = 2*e*dy - 2*dy (原来是 e = e -1)}y += uy;}}}void ChuituView::OnBresenhamline(){CDC* pDC = GetDC();state = 1;pDC->TextOut(450, 70, _T("请⽤⿏标划线!"));}2.圆2.1中点法void ChuituView::OnMidpointcircle(){// TODO: 在此添加命令处理程序代码dlg_circle dlg;dlg.DoModal();CDC* pDC = GetDC();CRect rect;GetClientRect(&rect);//重定义坐标轴Axis(pDC, rect);int r = dlg.circle_r;int x0 =dlg.circle_x, y0 = dlg.circle_y;double d;int x = 0;int y = r;d = 1 - r;int color = 255;//pDC->SetPixel(x, y, color);while (x < y){pDC->SetPixel(x + x0, y + y0, color);pDC->SetPixel(-x + x0, y + y0, color);pDC->SetPixel(-x + x0, -y + y0, color);pDC->SetPixel(x + x0, -y + y0, color);pDC->SetPixel(y + x0, x + y0, color);pDC->SetPixel(-y + x0, x + y0, color);pDC->SetPixel(-y + x0, -x + y0, color);pDC->SetPixel(y + x0, -x + y0, color);if (d < 0){d += 2 * x;++x;}else{d += 2 * (x - y) + 5;++x;--y;}//pDC->SetPixel(x, y, 255);}}1.2 Bresenham法void ChuituView::Bresenhamcircle_1(int x0, int y0, int r){// TODO: 在此处添加实现代码.CDC *pDC = GetDC();int color = 255;int x = 0;int y = r;int d = 1 - r;while (x <= y){pDC->SetPixel(x + x0, y + y0, color);pDC->SetPixel(-x + x0, y + y0, color);pDC->SetPixel(-x + x0, -y + y0, color);pDC->SetPixel(x + x0, -y + y0, color);pDC->SetPixel(y + x0, x + y0, color);pDC->SetPixel(-y + x0, x + y0, color);pDC->SetPixel(-y + x0, -x + y0, color);pDC->SetPixel(y + x0, -x + y0, color);if (d < 0)d += 2 * x + 3;else{d += 2 * (x - y) + 5;y--;}x++;}}void ChuituView::OnBresenhamcircle(){// TODO: 在此添加命令处理程序代码CDC *pDC = GetDC();pDC->TextOut(450, 70, _T("请⽤⿏标划线以确定远点坐标和半径!"));state = 2;}3.椭圆(Bresenhame)void ChuituView::OnBresenhamellipse(){// TODO: 在此添加命令处理程序代码CRect rect;GetClientRect(&rect);CDC* pDC = GetDC();//重定义坐标轴Axis(pDC, rect);pDC->TextOut(400, 70, _T("这是⼀个长半轴为200,短半轴100的椭圆!"));int a = 200, b = 100, color = 255, x, y;float d1;float d2 = 0;x = 0; y = b;d1 = b * b + a * a*(-b + 0.25);pDC->SetPixel(x, y, color);pDC->SetPixel(-x, -y, color);pDC->SetPixel(-x, y, color);pDC->SetPixel(x, -y, color);while (b*b*(x + 1) < a*a*(y - 0.5)){if (d1 <= 0){d1 += b * b*(2 * x + 3);x++;}else{d1 += b * b*(2 * x + 3) + a * a*(-2 * y + 2);x++;y--;}pDC->SetPixel(x, y, color);pDC->SetPixel(-x, -y, color);pDC->SetPixel(-x, y, color);pDC->SetPixel(x, -y, color);}d2 += b * b*(x + 0.5)*(x + 0.5) + a * a*(y - 1)*(y - 1) - a * a*b*b;while (y > 0){if (d2 <= 0){d2 += b * b*(2 * x + 2) + a * a*(-2 * y + 3);x++;y--;}else{d2 += a * a*(-2 * y + 3);y--;}pDC->SetPixel(x, y, color);pDC->SetPixel(-x, -y, color);pDC->SetPixel(-x, y, color);pDC->SetPixel(x, -y, color);}}4.直线扫描//直线扫描void ChuituView::OnPolygonscan(){// TODO: 在此添加命令处理程序代码CDC* pDC = GetDC();const int POINTNUM = 6;typedef struct XET{float x;float dx, ymax;XET* next;}AET, NET;struct point{float x;float y;}polypoint[POINTNUM] = { 250, 50, 550, 150, 550, 400, 250, 250, 100, 350, 100, 100 };int MaxY = 0;int i;for (i = 0; i < POINTNUM; i++)if (polypoint[i].y > MaxY)MaxY = polypoint[i].y;AET *pAET = new AET;pAET->next = NULL;NET *pNET[1024];for (i = 0; i <= MaxY; i++){pNET[i] = new NET;pNET[i]->next = NULL;}for (i = 0; i <= MaxY; i++){for (int j = 0; j < POINTNUM; j++)if (polypoint[j].y == i){if (polypoint[(j - 1 + POINTNUM) % POINTNUM].y > polypoint[j].y){NET *p = new NET;p->x = polypoint[j].x;p->ymax = polypoint[(j - 1 + POINTNUM) % POINTNUM].y;p->dx = (polypoint[(j - 1 + POINTNUM) % POINTNUM].x - polypoint[j].x) / (polypoint[(j - 1 + POINTNUM) % POINTNUM].y - polypoint[j].y);p->next = pNET[i]->next;pNET[i]->next = p;}if (polypoint[(j + 1 + POINTNUM) % POINTNUM].y > polypoint[j].y){NET *p = new NET;p->x = polypoint[j].x;p->ymax = polypoint[(j + 1 + POINTNUM) % POINTNUM].y;p->dx = (polypoint[(j + 1 + POINTNUM) % POINTNUM].x - polypoint[j].x) / (polypoint[(j + 1 + POINTNUM) % POINTNUM].y - polypoint[j].y);p->next = pNET[i]->next;pNET[i]->next = p;}}}for (i = 0; i <= MaxY; i++){NET *p = pAET->next;while (p){p->x = p->x + p->dx;p = p->next;}AET *tq = pAET;p = pAET->next;tq->next = NULL;while (p){while (tq->next && p->x >= tq->next->x)tq = tq->next;NET *s = p->next;p->next = tq->next;tq->next = p;p = s;tq = pAET;}AET *q = pAET;p = q->next;while (p){if (p->ymax == i){q->next = p->next;delete p;p = q->next;}else{q = q->next;p = q->next;}}p = pNET[i]->next;q = pAET;while (p){while (q->next && p->x >= q->next->x)q = q->next;NET *s = p->next;p->next = q->next;q->next = p;p = s;q = pAET;}p = pAET->next;while (p && p->next){for (float j = p->x; j <= p->next->x; j++)pDC->SetPixel(static_cast<int>(j), i, RGB(255, 0, 0));p = p->next->next;//考虑端点情况}}}5.种⼦填充5.1 四领域//四领域void ChuituView::OnPolygonfloodfill4(){// TODO: 在此添加命令处理程序代码CClientDC dc1(this);for (int i = 0; i <= 60; i++){dc1.SetPixel(0, i, 200);}for (int i = 0; i <= 60; i++)dc1.SetPixel(i, 0, 200);for (int i = 0; i <= 60; i++)dc1.SetPixel(i, 60, 200);for (int i = 0; i <= 60; i++)dc1.SetPixel(60, i, 200);FloodFill4(20, 20, 200, 100);}void ChuituView::FloodFill4(int x, int y, int oldColor, int newColor){CClientDC dc(this);int color;color = dc.GetPixel(x, y);if ((color != oldColor) && color != newColor){dc.SetPixel(x, y, newColor);FloodFill4(x, y + 1, oldColor, newColor);FloodFill4(x, y - 1, oldColor, newColor);FloodFill4(x - 1, y, oldColor, newColor);FloodFill4(x + 1, y, oldColor, newColor);}}5.1⼋领域//⼋领域void ChuituView::OnPolygonfloodfill8(){// TODO: 在此添加命令处理程序代码CClientDC dc1(this);for (int i = 0; i <= 50; i++){dc1.SetPixel(0, i, 200);}for (int i = 0; i <= 50; i++)dc1.SetPixel(i, 0, 200);for (int i = 0; i <= 50; i++)dc1.SetPixel(i, 50, 200);for (int i = 0; i <= 50; i++)dc1.SetPixel(50, i, 200);FloodFill8(6, 6, 200, 250);}void ChuituView::FloodFill8(int x, int y, int oldColor, int newColor){CClientDC dc(this);int color;color = dc.GetPixel(x, y);if ((color != oldColor) && color != newColor){dc.SetPixel(x, y, newColor);FloodFill8(x, y + 1, oldColor, newColor);FloodFill8(x, y - 1, oldColor, newColor);FloodFill8(x - 1, y, oldColor, newColor);FloodFill8(x + 1, y, oldColor, newColor);FloodFill8(x + 1, y + 1, oldColor, newColor);FloodFill8(x - 1, y - 1, oldColor, newColor);FloodFill8(x + 1, y - 1, oldColor, newColor);FloodFill8(x - 1, y + 1, oldColor, newColor);}}6.⼆维⼏何变换-五种基本变换6.1 平移//平移void ChuituView::Onpingyi2(){// TODO: 在此添加命令处理程序代码CClientDC dc(this);CRect rect;GetClientRect(&rect);//返回的是设备坐标,⽽SetViewportOrg需要的也是设备坐标,故此处不⽤转换 dc.SetViewportOrg(rect.Width() / 2, rect.Height() / 2);int Tx = 100, Ty = 200;//x平移100,y平移200int a[4][2] = { 0, 0, 100, 0, 100, 100, 0, 0 };//确定三⾓形的形状dc.TextOut(100, 0, (CString)"原图形");for (int i = 0; i < 3; i++){dc.MoveTo(a[i][0], a[i][1]);dc.LineTo(a[i + 1][0], a[i + 1][1]);}CPen pen;pen.CreatePen(PS_SOLID, 1, RGB(0, 0, 255));dc.SelectObject(&pen);dc.TextOut(100 + Tx, Ty, (CString)"平移后图形");for (int i = 0; i < 3; i++){dc.MoveTo(a[i][0] + Tx, a[i][1] + Ty);dc.LineTo(a[i + 1][0] + Tx, a[i + 1][1] + Ty);}}6.2旋转//旋转void ChuituView::Onxuanzhaun2(){// TODO: 在此添加命令处理程序代码CClientDC dc(this);CRect rect;GetClientRect(&rect);//返回的是设备坐标,⽽SetViewportOrg需要的也是设备坐标,故此处不⽤转换 dc.SetViewportOrg(rect.Width() / 2, rect.Height() / 2);float o = 3.1415926 / 2; //旋转90度float c = cos(o);float s = sin(o);int Tx = 300;int a[4][2] = { 0, 0, 100, 0, 100, 100, 0, 0 };//确定三⾓形的形状dc.TextOut(100, 0, (CString)"原图形");for (int i = 0; i < 3; i++){dc.MoveTo(a[i][0], a[i][1]);dc.LineTo(a[i + 1][0], a[i + 1][1]);}CPen pen;pen.CreatePen(PS_SOLID, 1, RGB(0, 0, 255));dc.SelectObject(&pen);dc.TextOut(100 * c + Tx, 0, (CString)"旋转后图形");for (int i = 0; i < 3; i++){dc.MoveTo(a[i][0] * c - a[i][1] * s + Tx, a[i][0] * s + a[i][0] * c);dc.LineTo(a[i + 1][0] * c - a[i + 1][1] * s + Tx, a[i + 1][0] * s + a[i + 1][0] * c);}}6.3错切//错切void ChuituView::Oncuoqie2(){// TODO: 在此添加命令处理程序代码CClientDC dc(this);CRect rect;GetClientRect(&rect);//返回的是设备坐标,⽽SetViewportOrg需要的也是设备坐标,故此处不⽤转换 dc.SetViewportOrg(rect.Width() / 2, rect.Height() / 2);int b = 2, c = 2;int Tx = 300;int a[4][2] = { 0, 0, 100, 0, 100, 100, 0, 0 };//确定三⾓形的形状dc.TextOut(100, 0, (CString)"原图形");for (int i = 0; i < 3; i++){dc.MoveTo(a[i][0], a[i][1]);dc.LineTo(a[i + 1][0], a[i + 1][1]);}CPen pen;pen.CreatePen(PS_SOLID, 1, RGB(0, 0, 255));dc.SelectObject(&pen);dc.TextOut(100 + Tx, 0, (CString)"错切后图形");for (int i = 0; i < 3; i++){dc.MoveTo(a[i][0] + c * a[i][1] + Tx, b * a[i][0] + a[i][1]);dc.LineTo(a[i + 1][0] + c * a[i + 1][1] + Tx, b * a[i + 1][0] + a[i + 1][1]);}}6.4⽐例//⽐例void ChuituView::Onbili2(){// TODO: 在此添加命令处理程序代码CClientDC dc(this);CRect rect;GetClientRect(&rect);//返回的是设备坐标,⽽SetViewportOrg需要的也是设备坐标,故此处不⽤转换 dc.SetViewportOrg(rect.Width() / 2, rect.Height() / 2);int Tx = 300;int Sx = 3, Sy = 4; //放⼤缩⼩⽐例int a[4][2] = { 0, 0, 100, 0, 100, 100, 0, 0 };//确定三⾓形的形状dc.TextOut(100, 0, (CString)"原图形");for (int i = 0; i < 3; i++){dc.MoveTo(a[i][0], a[i][1]);dc.LineTo(a[i + 1][0], a[i + 1][1]);}CPen pen;pen.CreatePen(PS_SOLID, 1, RGB(0, 0, 255));dc.SelectObject(&pen);dc.TextOut(100 + Tx, 0, (CString)"⽐例变换后图形");for (int i = 0; i < 3; i++){dc.MoveTo(a[i][0] * Sx + Tx, a[i][1] * Sy);dc.LineTo(a[i + 1][0] * Sx + Tx, a[i + 1][1] * Sy);}}6.5对称//对称void ChuituView::Onduichen2(){// TODO: 在此添加命令处理程序代码CClientDC dc(this);CRect rect;GetClientRect(&rect);//返回的是设备坐标,⽽SetViewportOrg需要的也是设备坐标,故此处不⽤转换 dc.SetViewportOrg(rect.Width() / 2, rect.Height() / 2);int a[4][2] = { 0, 0, 100, 0, 100, 100, 0, 0 };//确定三⾓形的形状dc.TextOut(100, 0, (CString)"原图形");for (int i = 0; i < 3; i++){dc.MoveTo(a[i][0], a[i][1]);dc.LineTo(a[i + 1][0], a[i + 1][1]);}CPen pen;pen.CreatePen(PS_SOLID, 1, RGB(0, 0, 255));dc.SelectObject(&pen);dc.TextOut(-100, -0, (CString)"对称后图形");for (int i = 0; i < 3; i++){dc.MoveTo(-a[i][0], -a[i][1]);dc.LineTo(-a[i + 1][0], -a[i + 1][1]);}}7.裁剪7.1直线cohen-sutherland法//直线cohen-sutherland法unsigned int ChuituView::EnCode(CPoint point){#define D0 1 //0001#define D1 2 //0010#define D2 4 //0100#define D3 8 //1000// TODO: 在此处添加实现代码.int C1 = 0;if (point.x < wxl)C1 = C1 | D0;if (point.x > wxr)C1 = C1 | D1;if (point.y < wyb)C1 = C1 | D2;if (point.y > wyt)C1 = C1 | D3;return C1;}void ChuituView::Oncs_line(){// TODO: 在此添加命令处理程序代码CDC* pDC = GetDC();ChuituDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);if (!pDoc)return;// wxl为左侧裁剪边,wxr为右侧裁剪边,wyb为下侧裁剪边,wyt为上裁剪边。
计算机图形学编程

1:角度DDA法绘制椭圆的程序:V oid line DDA(int x1,int y1,int x2,int y2,int color) x=x0+acost;y=y0+bsint { if{abs(x2-x1)>=abs(y2-y1);dm=abs(x2-x1)}Else { dm=abs(y2-y1)}float dx=(float)(x2-x1)/dm;float x=(float)(x1+0.5);float y=(float)(y1+0.5);for (int i=0;i<dm;i++)Setpixel(int x,int y,int color)x+=dx;y+=dy;}}2:绘制抛物线的程序:Par (int xs,int ys,int xm,int ym,int xe,int ye){double d,d1,ax,bx,by;int n,i;ax=(xe-2*xm+xs)*2.0;ay=(ye-2*ym+ys)*2.0;bx=xe-xs-ax;by=ye-ys-ay;n=sqrt(ax*ax+ay*ay);d=1.0/n;d1=d;for(i=0;i<=n;i++){ lineto((ax*d1+bx*d1+xs),(ay*d1*d1+by*d1+ys);d1+=d;}Lineto(xe,ye);}3:绘制三次Hermite曲线的程序:(给出四个点P0,P1,P2,P3,要在P1和P2之间绘一条Hermite曲线,用向量P0P1作为P1处的切线向量,用P2P3作为P2处的切线矢量)V oid HermiteCurve(Point po,Point p1,Point p2,Point p3,int count){Point r1,r2; //切线矢量r1=p1-p0; //调用重载r2=p3-p2;double t=0.0; dt=1.0/count;moveto(p1.x,p1.y);//设置起点for(int i=0;i<count+1;i++){double tt=t*t; double ttt=t*t*t;Double F1,F2,F3,F4; //调和函数F1=2*ttt-3*tt+1; F2=-2*ttt+3*tt; F3=ttt-2*tt+t; F4=ttt-tt;double x=p1.x*F1+p2.x*F2+r1.x*F3+r2.x*F4;double x=p1.y*F1+p2.y*F2+r1.y*F3+r2.y*F4;Lineto(x,y);t+=dt;}}4:绘制三次Bezier曲线和三次B样条曲线的程序(以四个点P0,P1,P2,P3作为控制多边形)V oid BezierCurve(Point p0,Pint p1,Point p2,Point p3,int count){double t=0.0; dt=1.0/count;moveto(p1.x, p1.y);//设置起点for(int i=0; i<count+1;i++){ double F1,F2,F3,F4,x,y;//调和函数double u=1.0-t;F1=u*u*u; F2=3*t*u*u; F3=3*t*t*u; F4=t*t*t;x=p0.x*F1+p1.x+F2+p2.x*F3+p3.x*F4;y=po.y*F1+p1.y*F2+p2.y*F3+p3.y*F4;Lineto(x,y);t+=dt;}}Void B_SpLine((Point p0,Pint p1,Point p2,Point p3,int count){double t=0.0;dt=1.0/count;For (int i=0;i<count+1;i++){ double tt=t*t; double ttt=tt*t;Double F1,F2,F3,F4;//调和函数F1=-ttt+3*tt-3*t+1; F2=3*ttt-6*tt+4;F3=-3*ttt+3*tt+3*t+1; F4=ttt;x=p0.x*F1+p1.x*F2+p2.x*F3+p3.x*F4;y=p0.y*F1+p1.y*F2+p2.y*F3+p3.y*F4;x/=6.0; y/=6.0;if(i==0) moveto(x,y);else lineto(x,y);t+=dt;}}5:写出光线跟踪算法(Ray-Tracing算法)的伪代码Color TraceRay(start,direction,depth)Vector start,directionInt depth{if (depth>MAX_DEPTH)color=黑色;else{ 光线与物体求交,找出离start最近的交点;If(无交点)color=背景色;Else{ local——color=用局部光照模型计算出交点处的光强;计算反射方向:R=1+2Ncosθ;Reflected_color=TraceRay(交点,反射方向R,depth+1);计算折射方向: T= (1/η)I-(cosθ2-(1/η)cosθ1)N;Transmitted_color=TraceRay(交点,折射方向,depth+1);Color=combine(local_color,Reflected_color,Kr,transmitted_color,KT)}}Return(color);}6:借助栈数据结构,写出漫水法区域填充的程序。
计算机图形学常用算法及代码大全

2。
1。
1 生成直线的DDA算法数值微分法即DDA法(Digital Differential Analyzer),是一种基于直线的微分方程来生成直线的方法.一、直线DDA算法描述:设(x1,y1)和(x2,y2)分别为所求直线的起点和终点坐标,由直线的微分方程得= m =直线的斜率(2-1)可通过计算由x方向的增量△x引起y的改变来生成直线:x i+1=x i+△x (2-2)y i+1=y i+△y=y i+△x·m (2-3) 也可通过计算由y方向的增量△y引起x的改变来生成直线:y i+1=y i+△y (2-4)x i+1=x i+△x=x i+△y/m (2-5) 式(2-2)至(2-5)是递推的.二、直线DDA算法思想:选定x2-x1和y2-y1中较大者作为步进方向(假设x2-x1较大),取该方向上的增量为一个象素单位(△x=1),然后利用式(2-1)计算另一个方向的增量(△y=△x·m=m)。
通过递推公式(2-2)至(2-5),把每次计算出的(x i+1,y i+1)经取整后送到显示器输出,则得到扫描转换后的直线。
之所以取x2-x1和y2-y1中较大者作为步进方向,是考虑沿着线段分布的象素应均匀,这在下图中可看出。
另外,算法实现中还应注意直线的生成方向,以决定Δx及Δy是取正值还是负值。
三、直线DDA算法实现:1、已知直线的两端点坐标:(x1,y1),(x2,y2)2、已知画线的颜色:color3、计算两个方向的变化量:dx=x2-x1dy=y2-y14、求出两个方向最大变化量的绝对值:steps=max(|dx|,|dy|)5、计算两个方向的增量(考虑了生成方向):xin=dx/stepsyin=dy/steps6、设置初始象素坐标:x=x1,y=y17、用循环实现直线的绘制:for(i=1;i〈=steps;i++){putpixel(x,y,color);/*在(x,y)处,以color色画点*/x=x+xin;y=y+yin;}五、直线DDA算法特点:该算法简单,实现容易,但由于在循环中涉及实型数的运算,因此生成直线的速度较慢。
C语言之图形学算法

C语言之图形学算法图形学算法是计算机图形学领域中的重要内容,它涉及到图形的创建、显示和处理等方面。
在C语言中,有一些常用的图形学算法可以帮助我们实现各种各样的图形效果。
本文将介绍一些常见的C语言图形学算法,包括直线绘制算法、圆绘制算法和多边形填充算法等。
一、直线绘制算法直线是图形学中最基础的图形之一,其绘制算法也是最简单的。
在C语言中,常用的直线绘制算法有DDA算法和Bresenham算法。
1. DDA算法DDA(Digital Differential Analyzer)算法是一种直线绘制算法,其基本思想是通过计算直线的斜率和每个像素点之间的差值来实现直线的绘制。
下面是DDA算法的伪代码:```dx = x2 - x1dy = y2 - y1step = max(abs(dx), abs(dy))x_increment = dx / stepy_increment = dy / stepx = x1y = y1plot(x, y)for i in range(step):x = x + x_incrementy = y + y_incrementplot(round(x), round(y))```2. Bresenham算法Bresenham算法是一种更加高效的直线绘制算法,它通过利用整数运算和误差累积的方式来实现直线的绘制。
下面是Bresenham算法的伪代码:```dx = abs(x2 - x1)dy = abs(y2 - y1)if dx > dy:step = dxelse:step = dyx_increment = dx / stepy_increment = dy / stepy = y1plot(x, y)for i in range(step):if dx > dy:x = x + x_incrementelse:y = y + y_incrementplot(round(x), round(y))```二、圆绘制算法圆是一种常见的图形,在计算机图形学中,圆的绘制算法也是一个重要的问题。
计算机图形学代码

四、实验结果抓图与分析1、目标的平移的源程序2、绕任意点旋转的源程序实验一、直线的生成一、实验内容根据提供的程序框架,修改部分代码,完成画一条直线的功能(中点画线法或者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画法画一段圆弧或者画圆。
计算机图形学DDA算法程序代码

计算机图形学DDA算法程序代码// Experiment_Frame_OneView.cpp : implementation of the CExperiment_Frame_OneView class //#include "stdafx.h"#include "Experiment_Frame_One.h"#include "Experiment_Frame_OneDoc.h"#include "Experiment_Frame_OneView.h"#include "SettingDlg.h"#include "InputDialog.h"#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif/////////////////////////////////////////////////////////////////// //////////// CExperiment_Frame_OneViewIMPLEMENT_DYNCREATE(CExperiment_Frame_OneView, CView)BEGIN_MESSAGE_MAP(CExperiment_Frame_OneView, CView)//{{AFX_MSG_MAP(CExperiment_Frame_OneView)ON_COMMAND(IDM_SETTING, OnSetting)ON_COMMAND(IDM_INPUT, OnInput)//}}AFX_MSG_MAP// Standard printing commandsON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_PREVIEW,CView::OnFilePrintPreview)END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////// //////////// CExperiment_Frame_OneView construction/destructionCExperiment_Frame_OneView::CExperiment_Frame_OneVie w(){// TODO: add construction code herem_bGridOn = true;m_iMarginSize = 20;m_iPointSize = 20;m_iActive_Algorithm = 0;m_PointColor = RGB(255, 0, 0);X0 = Y0 = 0;X1 = Y1 = 10;}CExperiment_Frame_OneView::~CExperiment_Frame_OneVi ew(){}BOOLCExperiment_Frame_OneView::PreCreateWindow(CREA TESTRUCT& cs) {// TODO: Modify the Window class or styles here by modifying// the CREATESTRUCT csreturn CView::PreCreateWindow(cs);}/////////////////////////////////////////////////////////////////////////////// CExperiment_Frame_OneView drawingvoid CExperiment_Frame_OneView::OnDraw(CDC* pDC){CExperiment_Frame_OneDoc* pDoc = GetDocument();ASSERT_V ALID(pDoc);// TODO: add draw code for native data hereif( this->m_bGridOn ){this->DrawGrid(pDC);}switch( this->m_iActive_Algorithm) {case 0: //DDADDA(X0,Y0,X1,Y1);break;case 1: //Mid_BresenhamMid_Bresenham(X0,Y0,X1,Y1);break;default:break;}CView::OnDraw(pDC);}/////////////////////////////////////////////////////////////////// //////////// CExperiment_Frame_OneView printingBOOLCExperiment_Frame_OneView::OnPreparePrinting(CPrintInfo* pInfo){// default preparationreturn DoPreparePrinting(pInfo);}void CExperiment_Frame_OneView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) {// TODO: add extra initialization before printing}void CExperiment_Frame_OneView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) {// TODO: add cleanup after printing}/////////////////////////////////////////////////////////////////// //////////// CExperiment_Frame_OneView diagnostics#ifdef _DEBUGvoid CExperiment_Frame_OneView::AssertV alid() const{CView::AssertValid();}void CExperiment_Frame_OneView::Dump(CDumpContext& dc) const{CView::Dump(dc);}CExperiment_Frame_OneDoc*CExperiment_Frame_OneView::GetDocument() // non-debug version is inline{ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CExperi ment_Frame_OneDoc)));return (CExperiment_Frame_OneDoc*)m_pDocument;}#endif //_DEBUG/////////////////////////////////////////////////////////////////// //////////// CExperiment_Frame_OneView message handlersvoid CExperiment_Frame_OneView::DrawGrid(CDC *pDC){CRect ClientRect;GetClientRect( &ClientRect );CPen *pNewPen = new CPen;pNewPen->CreatePen(PS_DOT, 1, RGB(256,0,0));CPen *pOldPen = pDC->SelectObject(pNewPen);int x0 = ClientRect.left + m_iMarginSize;int x1 = x0 + (ClientRect.right -ClientRect.left - 2*m_iMarginSize)/m_iPointSize * m_iPointSize;int y0 = ClientRect.bottom - m_iMarginSize;int y1 = y0 - (ClientRect.bottom - ClientRect.top - 2*m_iMarginSize)/m_iPointSize * m_iPointSize;int x, y;//Draw horizontal linesfor ( y = y0; y >= y1; y -= m_iPointSize){pDC->MoveTo(x0, y);pDC->LineT o(x1, y);}//Draw vertical linesfor ( x = x0; x <= x1; x += m_iPointSize){pDC->MoveTo(x, y0);pDC->LineT o(x, y1);}pDC->SelectObject(pOldPen);pNewPen->DeleteObject();return;}void CExperiment_Frame_OneView::DrawPixel(int X, int Y) {CDC *pDC= GetDC();CBrush *pNewBrush = new CBrush;pNewBrush->CreateSolidBrush(m_PointColor);CBrush *pOldBrush = pDC->SelectObject(pNewBrush); CPen *pNewPen = new CPen;pNewPen->CreatePen(PS_NULL, 1, RGB(0,0,0));CPen *pOldPen = pDC->SelectObject(pNewPen); CRect ClientRect;GetClientRect( &ClientRect );int x0 = ClientRect.left + m_iMarginSize;int y0 = ClientRect.bottom - m_iMarginSize;CRect Point;Point.left = x0 + X*m_iPointSize;Point.right = Point.left + m_iPointSize;Point.bottom = y0 - Y*m_iPointSize;Point.top = Point.bottom - m_iPointSize;pDC->Rectangle(&Point);pDC->SelectObject(pOldBrush);pNewBrush->DeleteObject();pDC->SelectObject(pOldPen);pOldPen->DeleteObject();}void CExperiment_Frame_OneView::OnSetting(){CSettingDlg SettingDialog(m_iPointSize,m_PointColor,m_iActive_Algorithm,m_bGridOn);if ( SettingDialog.DoModal() == IDOK ){this->m_bGridOn = SettingDialog.m_bGridOn;this->m_PointColor = SettingDialog.m_Point_Color;this->m_iPointSize = SettingDialog.m_Point_Size;this->m_iActive_Algorithm = SettingDialog.m_iActive_Algorithm;this->Invalidate();}}void CExperiment_Frame_OneView::OnInput(){CInputDialog InputDialog(X0, Y0, X1, Y1);if ( InputDialog.DoModal() == IDOK){X0 = InputDialog.m_X0;X1 = InputDialog.m_X1;Y0 = InputDialog.m_Y0;Y1 = InputDialog.m_Y1;Invalidate();}}//-------------------------算法实现------------------------------////绘制像素的函数DrawPixel(x, y);void CExperiment_Frame_OneView::DDA(int X0, int Y0, int X1, int Y1){int dx,dy,epsl,k;float x,y,xIncre,yIncre;dx=X1-X0; dy=Y1-Y0;x=X0; y=Y0;if(abs(dx)>abs(dy)) epsl=abs(dx);else epsl=abs(dy);xIncre=(float)dx/(float)epsl;yIncre=(float)dy/(float)epsl;for(k=0;k<=epsl;k++){DrawPixel (int(x+0.5),(int)(y+0.5));x+=xIncre;y+=yIncre;}}void CExperiment_Frame_OneView::Mid_Bresenham(int X0, int Y0, int X1, int Y1) {int dx,dy,d,UpIncre,DownIncre,x,y;if(X0>X1){x=X1;X1=X0;X0=x;y=Y1;Y1=Y0;Y0=y;}x=X0;y=Y0;dx=X1-X0; dy=Y1-Y0;d=dx-2*dy; UpIncre=2*dx-2*dy; DownIncre=-2*dy; while(x<=X1){DrawPixel(x,y);x++;if(d<0){y++;d+=UpIncre;}else d+=DownIncre; }}。
计算机图形学 算法总结

外侧的不算交点。
Байду номын сангаас
五、 消隐
画家算法 对场景中的多边形按深度进行排序,形成深度优先级表, 按从远倒近的顺序 显示多边形 不能处理循环遮挡,计算量大。 Z 缓冲器算法 { for(v=0;v<vmax;v++) for(u<0;u<umax;u++) { 置 Z 缓冲器的第(u,v)单元的深度值为-1 置帧缓冲器的第(u,v)单元的颜色值为背景色 } for(每一个多边形) for(多边形投影区域内的每一个像素) { 计算多边形在当前像素(u,v)处的深度值,记为 d; if(d>Z 缓冲器的(u,v)单元的值) { 置 Z 缓冲器的第(u,v)单元的深度值为 d; 置帧缓冲器的第(u,v)单元的颜色值为当前多边形颜色值; } } 扫描线 Z 缓冲器算法
加权区域采样方法 改进非加权区域采样方法:相交面积相同,像素亮度可能不同 求出相交区域 A’,然后用 计算相交区域对像素的亮度贡献值,这个计
算结果乘以最大亮度值就是该像素的亮度。W(x,y)是高斯分布函数。 离散算法: 分割像素成 n 个子像素,每个子像素面积为 1/n,用 计算每个子像素
对原像素的亮度贡献权值, 记录在加权表中。然后求所有中心落在直线段里的子 像素的集合。最后针对上述集合计算亮度贡献权值的代数和作为亮度值。
扫描转换多边形 逐点判断法、扫描线算法、边缘填充法 逐点判断法: 射线法:从每个象素点发射线,交点个数偶数的在外,反之在内。避免射线 通过顶点。 累积角度法: 记录从该象素到多边形每个顶点的有向角 (逆时针旋转为正) , 若代数和为 0 则在外,若为正负 2pi 的在内。 编码方法:从 X 轴起逆时针把各象限编码,确认各顶点所在象限的编码, 然后两顶点相减计算各边的编码,用 4 处理使编码绝对值不大于 2,最后求各边 编码代数和。代数和为 0 的在外,为正负 4 的在内。特殊情况:(1)点在边上.预 处理解决 (2)代数和为正负 2(取中点再编码,递归) 扫描线算法 求扫描线与多边形各边的交点 对所得交点从小到大排序 两两配对,填充每个区段 原则:与扫描线的交点向多边形内取整。交点落在象素点上时,仅落在左边上的 属于多边形。交点为多边形顶点时,每个边被认为下闭上开(p74)。 数据结构和算法流程 P76 特点:算法效率比逐点填充法高很多 缺点:对各种表的维持和排序开销太大,适合软件实现而不是硬件实现。
计算机图形学 自行车 旋转平移 等代码

glutAddMenuEntry("实体正四面体",2);
glutAddMenuEntry("线框正八面体",3);
glutAddMenuEntry("实体正八面体",4);
int nGlutCurveMenu = glutCreateMenu(ProcessMenu); //创建GLUT曲面绘制菜单
setbkcolor(6);
/*画前轮*/
circle(x/2,y/2,30);
for(k=0;k<=360;k+=30){
line( x/2,y/2,x/2+30*cos((x/2+k)*0.01745),y/2+30*sin((x/2+k)*0.01745));}
/*画后轮*/
circle(x/2+100,y/2,30);
registerbgidriver(EGAVGA_driver);/*注册BGI驱动后可以不需要.BGI文件的支持运行*/
initgraph(&gd, &gm, "");
}
int main(void)
{ void *w1,*w2;
int i,k;
int x=500,y=300;
initgr(); /* BGI初始化*/
circle(x/2+20,y/2-90,4);
line(x/2+70,y/2-60,x/2+90,y/2-60);
w1=malloc(imagesize(x/2-130,y/2-90,x/2+130,y/2+30));
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
2.1.1 生成直线的DDA算法数值微分法即DDA法(Digital Differential Analyzer),是一种基于直线的微分方程来生成直线的方法。
一、直线DDA算法描述:设(x1,y1)和(x2,y2)分别为所求直线的起点和终点坐标,由直线的微分方程得= m =直线的斜率(2-1) 可通过计算由x方向的增量△x引起y的改变来生成直线:x i+1=x i+△x (2-2)y i+1=y i+△y=y i+△x·m (2-3) 也可通过计算由y方向的增量△y引起x的改变来生成直线:y i+1=y i+△y (2-4)x i+1=x i+△x=x i+△y/m (2-5) 式(2-2)至(2-5)是递推的。
二、直线DDA算法思想:选定x2-x1和y2-y1中较大者作为步进方向(假设x2-x1较大),取该方向上的增量为一个象素单位(△x=1),然后利用式(2-1)计算另一个方向的增量(△y=△x·m=m)。
通过递推公式(2-2)至(2-5),把每次计算出的(x i+1,y i+1)经取整后送到显示器输出,则得到扫描转换后的直线。
之所以取x2-x1和y2-y1中较大者作为步进方向,是考虑沿着线段分布的象素应均匀,这在下图中可看出。
另外,算法实现中还应注意直线的生成方向,以决定Δx及Δy是取正值还是负值。
三、直线DDA算法实现:1、已知直线的两端点坐标:(x1,y1),(x2,y2)2、已知画线的颜色:color3、计算两个方向的变化量:dx=x2-x1dy=y2-y14、求出两个方向最大变化量的绝对值:steps=max(|dx|,|dy|)5、计算两个方向的增量(考虑了生成方向):xin=dx/stepsyin=dy/steps6、设置初始象素坐标:x=x1,y=y17、用循环实现直线的绘制:for(i=1;i<=steps;i++){ putpixel(x,y,color);/*在(x,y)处,以color色画点*/x=x+xin;y=y+yin;}五、直线DDA算法特点:该算法简单,实现容易,但由于在循环中涉及实型数的运算,因此生成直线的速度较慢。
//@brief 浮点数转整数的宏实现代码#define FloatToInteger(fNum)((fNum>0)?static_cast<int>(fNum+0.5):static_cast<int>(fNum-0.5))/*!* @brief DDA画线函数** @param pDC [in]窗口DC* @param BeginPt [in]直线起点* @param EndPt [in]直线终点* @param LineCor [in]直线颜色* @return 无*/void CDrawMsg::DDA_DrawLine(CDC *pDC,CPoint &BeginPt,CPoint &EndPt,COLORREF LineCor){l ong YDis = (EndPt.y - BeginPt.y);l ong XDis = (EndPt.x-BeginPt.x);l ong MaxStep = max(abs(XDis),abs(YDis)); // 步进的步数f loat fXUnitLen = 1.0f; // X方向的单位步进f loat fYUnitLen = 1.0f; // Y方向的单位步进f YUnitLen = static_cast<float>(YDis)/static_cast<float>(MaxStep);f XUnitLen = static_cast<float>(XDis)/static_cast<float>(MaxStep);// 设置起点像素颜色p DC->SetPixel(BeginPt.x,BeginPt.y,LineCor);f loat x = static_cast<float>(BeginPt.x);f loat y = static_cast<float>(BeginPt.y);// 循环步进f or (long i = 1;i<=MaxStep;i++){x = x + fXUnitLen;y = y + fYUnitLen;pDC->SetPixel(FloatToInteger(x),FloatToInteger(y),LineCor);}}2.1.2 生成直线的B resenham算法从上面介绍的DDA算法可以看到,由于在循环中涉及实型数据的加减运算,因此直线的生成速度较慢。
在生成直线的算法中,B resenham算法是最有效的算法之一。
B resenham算法是一种基于误差判别式来生成直线的方法。
一、直线Bresenham算法描述:它也是采用递推步进的办法,令每次最大变化方向的坐标步进一个象素,同时另一个方向的坐标依据误差判别式的符号来决定是否也要步进一个象素。
我们首先讨论m=△y/△x,当0≤m≤1且x1<x2时的B resenham算法。
从DDA直线算法可知这些条件成立时,公式(2-2)、(2-3)可写成:x i+1=x i+1 (2-6)y i+1=y i+m(2-7)有两种B resenham算法思想,它们各自从不同角度介绍了B resenham算法思想,得出的误差判别式都是一样的。
二、直线B resenham算法思想之一:由于显示直线的象素点只能取整数值坐标,可以假设直线上第i个象素点坐标为(x i,y i),它是直线上点(x i,y i)的最佳近似,并且x i=x i(假设m<1),如下图所示。
那么,直线上下一个象素点的可能位置是(x i+1,y i)或(x i+1,y i+1)。
由图中可以知道,在x=x i+1处,直线上点的y值是y=m(x i+1)+b,该点离象素点(x i+1,y i)和象素点(x i+1,y i+1)的距离分别是d1和d2:d1=y-y i=m(x i+1)+b-y i(2-8)d2=(y i+1)-y=(y i+1)-m(x i+1)-b (2-9) 这两个距离差是d1-d2=2m(x i+1)-2y i+2b-1 (2-10)我们来分析公式(2-10):(1)当此值为正时,d1>d2,说明直线上理论点离(x i+1,y i+1)象素较近,下一个象素点应取(x i+1,y i+1)。
(2)当此值为负时,d1<d2,说明直线上理论点离(x i+1,y i)象素较近,则下一个象素点应取(x i+1,y i)。
(3)当此值为零时,说明直线上理论点离上、下两个象素点的距离相等,取哪个点都行,假设算法规定这种情况下取(x i+1,y i+1)作为下一个象素点。
因此只要利用(d1-d2)的符号就可以决定下一个象素点的选择。
为此,我们进一步定义一个新的判别式:p i=△x×(d1-d2)=2△y·x i-2△x·y i+c (2-11)式(2-11)中的△x=(x2-x1)>0,因此p i与(d1-d2)有相同的符号;这里△y=y2-y1,m=△y/△x;c=2△y+△x(2b-1)。
下面对式(2-11)作进一步处理,以便得出误差判别递推公式并消除常数c 。
将式(2-11)中的下标i 改写成i+1,得到:p i+1=2△y ·x i +1-2△x ·y i +1+c(2-12)将式(2-12)减去(2-11),并利用x i +1=x i +1,可得:p i+1= p i +2△y-2△x ·(y i +1-y i )(2-13)再假设直线的初始端点恰好是其象素点的坐标,即满足:y 1=m x 1+b(2-14)由式(2-11)和式(2-14)得到p 1的初始值:p 1=2△y-△x(2-15)这样,我们可利用误差判别变量,得到如下算法表示:初始 p 1=2△y-△x (2-16)当p i ≥0时: y i+1=y i +1, x i+1=x i +1, p i+1=p i +2(△y-△x) 否则: y i+1=y i , x i+1=x i +1,p i+1=p i +2△y从式(2-16)可以看出,第i+1步的判别变量p i+1仅与第i 步的判别变量p i 、直线的两个端点坐标分量差△x 和△y 有关,运算中只含有整数相加和乘2运算,而乘2可利用算术左移一位来完成,因此这个算法速度快并易于硬件实现。
三、直线B resenham 算法思想之二:由于象素坐标的整数性,数学点(x i ,y i )与所取象素点(x i ,y ir )间会引起误差(εi ),当x i 列上已用象素坐标(x i ,y ir )表示直线上的点(x i ,y i ),下一直线点B (x i+1,y i+1),是取象素点C (x i+1,y ir ),还是D (x i +1,y (i+1)r )呢?设A 为CD 边的中点,正确的选择:若B 点在A 点上方,选择D 点; 否则,选C 点。
用误差式描述为:ε(x i+1)=BC-AC=(y i+1-y ir)-0.5 (2-8')求递推公式:ε(x i+2)=(y i+2-y(i+1)r)-0.5 = y i+1+m-y(i+1)r-0.5 (2-9')当ε(x i+1)≥0时,选D点,y(i+1)r = y ir+1ε(x i+2)= y i+1+m-y ir-1-0.5=ε(x i+1)+m-1 (2-10')当ε(x i+1)﹤0时,选C点,y(i+1)r = y irε(x i+2)= y i+1+m-y ir-0.5=ε(x i+1)+m(2-11')初始时:ε(x s+1)=BC-AC=m-0.5 (2-12')为了运算中不含实型数,同时不影响不等式的判断,将方程两边同乘一正整数。
令方程两边同乘2·Δx,即d=2·Δx·ε,则:初始时:d = 2·Δy-Δx (2-13')递推式:当d≥0时:{ d=d+2·(Δy-Δx);y++;x++;(2-14')}否则:{ d=d+2·Δy;x++;}实现代码void Bresenhamline (int x0,int y0,int x1, int y1,int color){int x, y, dx, dy;float k, e;dx = x1-x0, dy = y1- y0, k=dy/dx;e=-0.5, x=x0, y=y0;for (i=0; i<=dx; i++){ drawpixel (x, y, color);x=x+1,e=e+k;if (e>=0){ y++, e=e-1;}}}或者将e扩大2dx倍;void Bresenhamline (int x0,int y0,int x1, int y1,int color){int x, y, dx, dy;float k, e;dx = x1-x0, dy = y1- y0, k=dy/dx;e=-dx, x=x0, y=y0;for (i=0; i<=dx; i++){ drawpixel (x, y, color);x=x+1,e=e+2dy;if (e>=0){ y++, e=e-2dx;}}}四、直线B resenham算法实现:条件:0≤m≤1且x1<x21、输入线段的两个端点坐标和画线颜色:x1,y1,x2,y2,color;2、设置象素坐标初值:x=x1,y=y1;3、设置初始误差判别值:p=2·Δy-Δx;4、分别计算:Δx=x2-x1、Δy=y2-y1;5、循环实现直线的生成:for(x=x1;x<=x2;x++){ putpixel(x,y,color) ;if(p>=0){ y=y+1;p=p+2·(Δy-Δx);}else{ p=p+2·Δy;}}五、直线B resenham算法完善:现在我们修正(2-16)公式,以适应对任何方向及任何斜率线段的绘制。