计算机图形学DDA画线法+中点画线法+Bresenham画线法
Posted sufferingStriver
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了计算机图形学DDA画线法+中点画线法+Bresenham画线法相关的知识,希望对你有一定的参考价值。
#include <cstdio> #include <cstring> #include <conio.h> #include <graphics.h> void line1(){ line(100, 100, 200, 400); line(100, 400, 200, 100); line(0, 200, 300, 300); line(0, 300, 300, 200); } void lineDDA(int x0, int y0, int x1, int y1, int color){ int x; float dy, dx, y, m; dx = x1 - x0; dy = y1 - y0; m = dy / dx; y = y0; for (x = x0; x <= x1; x++){ putpixel(x, (int)(y + 0.5), color); y += m; } } void lineDDA(){ lineDDA(100, 100, 200, 400, RED); lineDDA(100, 400, 200, 100, RED); lineDDA(0, 200, 300, 300, RED); lineDDA(0, 300, 300, 200, RED); } void lineMidPoint(int x0, int y0, int x1, int y1, int color){ int x = x0, y = y0; int a = y0 - y1, b = x1 - x0; int cx = (b >= 0 ? 1 : (b = -b, -1)); int cy = (a <= 0 ? 1 : (a = -a, -1)); putpixel(x, y, color); int d, d1, d2; if (-a <= b) // 斜率绝对值 <= 1 { d = 2 * a + b; d1 = 2 * a; d2 = 2 * (a + b); while (x != x1) { if (d < 0) y += cy, d += d2; else d += d1; x += cx; putpixel(x, y, color); } } else // 斜率绝对值 > 1 { d = 2 * b + a; d1 = 2 * b; d2 = 2 * (a + b); while (y != y1) { if (d < 0) d += d1; else x += cx, d += d2; y += cy; putpixel(x, y, color); } } } void lineMidPoint(){ lineMidPoint(100, 100, 200, 400, GREEN); lineMidPoint(100, 400, 200, 100, GREEN); lineMidPoint(0, 200, 300, 300, GREEN); lineMidPoint(0, 300, 300, 200, GREEN); } void lineBresenham(int x0, int y0, int x1, int y1, int color) { int dx = x1 - x0; int dy = y1 - y0; int ux = dx >0 ? 1 : -1;//x伸展方向 int uy = dy >0 ? 1 : -1;//y伸展方向 int dx2 = dx << 1;//x偏移量乘2 int dy2 = dy << 1;//y偏移量乘2 if (abs(dx)>abs(dy)) {//以x为增量方向计算 int e = -dx; //e = -0.5 * 2 * dx,把e 用2 * dx* e替换 int x = x0; int y = y0;//起点y坐标 for (x = x0; x < x1; x += ux) { putpixel(x, y, color); e = e + dy2;//来自 2*e*dx= 2*e*dx + 2dy (原来是 e = e + k) if (e > 0)//e是整数且大于0时表示要取右上的点(否则是右下的点) { y += uy; e = e - dx2;//2*e*dx = 2*e*dx - 2*dx (原来是 e = e -1) } } } else {//以y为增量方向计算 int e = -dy; //e = -0.5 * 2 * dy,把e 用2 * dy* e替换 int x = x0; int y = y0; for (y = y0; y < y1; y += uy) { putpixel(x, y, color); e = e + dx2;//来自 2*e*dy= 2*e*dy + 2dy (原来是 e = e + k) if (e > 0)//e是整数且大于0时表示要取右上的点(否则是右下的点) { x += ux; e = e - dy2;//2*e*dy = 2*e*dy - 2*dy (原来是 e = e -1) } } } } void lineBresenham1(int x0, int y0, int x1, int y1, long color) { int dx = abs(x1 - x0); int dy = abs(y1 - y0); int x = x0; int y = y0; int stepX = 1; int stepY = 1; if (x0 > x1) //从右向左画 stepX = -1; if (y0 > y1) stepY = -1; if (dx > dy) //沿着最长的那个轴前进 { int e = dy * 2 - dx; for (int i = 0; i <= dx; i++) { putpixel(x, y, color); x += stepX; e += dy; if (e >= 0) { y += stepY; e -= dx; } } } else { int e = 2 * dx - dy; for (int i = 0; i <= dy; i++) { putpixel(x, y, color); y += stepY; e += dx; if (e >= 0) { x += stepX; e -= dy; } } } } void lineBresenham(){ lineBresenham1(100, 100, 200, 400, YELLOW); lineBresenham1(100, 400, 200, 100, YELLOW); lineBresenham1(0, 200, 300, 300, YELLOW); lineBresenham1(0, 300, 300, 200, YELLOW); } void showWord(int code){ outtextxy(200, 30, "单击右键退出"); switch (code){ case 1://原画 outtextxy(200, 10, "easyX系统画线算法"); break; case 2://DDA算法 outtextxy(200, 10, "DDA算法"); break; case 3://中点画线算法 outtextxy(200, 10, "中点画线算法"); break; case 4://Bresenham算法 outtextxy(200, 10, "Bresenham算法"); break; default: line1(); break; } } void drawLine(int code){ switch (code){ case 1://原画 line1(); break; case 2://DDA算法 lineDDA(); break; case 3://中点画线算法 lineMidPoint(); break; case 4://Bresenham算法 lineBresenham(); break; default: line1(); break; } } void drawLine(int x0,int y0,int x1,int y1,int code){ showWord(code); switch (code){ case 1://原画 line(x0,y0,x1,y1); break; case 2://DDA算法 lineDDA(x0, y0, x1, y1,WHITE); break; case 3://中点画线算法 lineMidPoint(x0, y0, x1, y1, WHITE); break; case 4://Bresenham算法 lineBresenham1(x0, y0, x1, y1, WHITE); break; default: line1(); break; } } void showWORDXY(int x, int y, int showX, int showY,int flag){ char dintX[5] = { 0 }; char dintY[5] = { 0 }; _itoa_s(showX, dintX, 10);//把整数showX转成字符串dintX _itoa_s(showY, dintY, 10);//把整数showY转成字符串dintY char str1[100] = "第一个点的坐标:(";//此时数组没有定义长度 元素的个数应该为strlen +1 因为字符串末尾有 ‘\0‘结束 char str2[100] = "第二个点的坐标:("; if (flag == 1){ // _countof(dintX)能够获取到数组中元素的个数 含‘\0’ strcat_s(str1, strlen(str1) + strlen(dintX)+1, dintX); strcat_s(str1, strlen(str1) + strlen(",")+1, ","); strcat_s(str1, strlen(str1) + strlen(dintY)+1, dintY); strcat_s(str1, strlen(str1) + strlen(")")+1, ")"); outtextxy(x, y, str1); } else if (flag == 2){ strcat_s(str2, strlen(str2) + strlen(dintX)+1, dintX); strcat_s(str2, strlen(str2) + strlen(",")+1, ","); strcat_s(str2, strlen(str2) + strlen(dintY)+1, dintY); strcat_s(str2, strlen(str2) + strlen(")")+1, ")"); outtextxy(x, y, str2); } } //调用easyX void easyX(int code){ initgraph(640, 480); //初始化 showWord(code); MOUSEMSG m; // 定义鼠标消息 int n=0;//读取两个点 int exit = false; int x0=0, y0=0,x1=0,y1=0; while (n<2 && !exit) { m = GetMouseMsg(); switch (m.uMsg) { case WM_RBUTTONDOWN: outtextxy(200, 300, "再次点击键退出"); exit = true; break; // 按鼠标右键退出程序 } while (m.uMsg != WM_LBUTTONDOWN){ m = GetMouseMsg(); switch (m.uMsg) { case WM_RBUTTONDOWN: outtextxy(200, 300, "再次点击键退出"); exit = true; break; // 按鼠标右键退出程序 } } while (m.uMsg != WM_LBUTTONUP){ m = GetMouseMsg(); cleardevice(); showWord(code); if (n == 0){ showWORDXY(200, 430, x0, y0,1); x0 = m.x; y0 = m.y; } else{ showWORDXY(200, 430, x0, y0, 1); showWORDXY(200, 450, x1, y1, 2); x1 = m.x; y1 = m.y; } } n++; if (n == 2){ //画线 drawLine(x0, y0, x1, y1, code); //重置 n = 0; } } //_getch(); //等待用户操作 closegraph(); //关闭图形 } int main(){ int n = 1; printf("请选择画线算法画线:\n"); printf("1.easyX系统画线函数.\n"); printf("2.DDA画线算法函数.\n"); printf("3.中点画线算法函数.\n"); printf("4.Bresenham画线算法函数.\n"); printf("0.退出.\n"); while (n != 0){ scanf_s("%d", &n); if (n == 0){ exit(0); } easyX(n); } return 0; }
效果图:
以上是关于计算机图形学DDA画线法+中点画线法+Bresenham画线法的主要内容,如果未能解决你的问题,请参考以下文章
用C++如何实现bresenham画线算法?计算机图形学上面有个drawpixel的函数。不知道怎么用。