Bresenham算法是计算机图形学领域使用最广泛的直线扫描转换方法。
Bresenham算法不止可以用来画直线,还可以用来画圆,画椭圆,等等,其他曲线。
Bresenham算法画直线的原理,可以参考:
https://blog.csdn.net/qq_26093511/article/details/73695096
这个写的比较清楚,有详细的推导过程,还有代码:https://wenku.baidu.com/view/eb1faabab84ae45c3b358cd8.html
实现可以看一下:
https://zhuanlan.zhihu.com/p/30553006
太神奇了,我没看懂。
代码:
#include <stdio.h> #include <stdlib.h> #include <math.h> #include <string.h> #include "svpng.inc" #define PI 3.14159265359f #define W 512 #define H 512 unsigned char img[W * H * 3]; // https://zhuanlan.zhihu.com/p/30553006 // https://zh.wikipedia.org/wiki/%E5%B8%83%E9%9B%B7%E6%A3%AE%E6%BC%A2%E5%A7%86%E7%9B%B4%E7%B7%9A%E6%BC%94%E7%AE%97%E6%B3%95 // https://blog.csdn.net/qq_26093511/article/details/73695096 void setPixel(int x, int y){ unsigned char* p = img + (y * W + x) * 3; p[0] = p[1] = p[2] = 0; } void bresenham(int x0, int y0, int x1, int y1){ int dx = abs(x1 - x0); int sx = x0 < x1 ? 1 : -1; int dy = abs(y1 - y0); int sy = y0 < y1 ? 1 : -1; int err = (dx > dy ? dx : -dy) / 2; setPixel(x0, y0); while(x0 != x1 || y0 != y1){ setPixel(x0, y0); int e2 = err; if(e2 > -dx){ err -= dy; x0 += sx; } if(e2 < dy){ err += dx; y0 += sy; } } } int main(){ memset(img, 255, sizeof(img)); float cx = W * 0.5f - 0.5f; float cy = H * 0.5f - 0.5f; for(int j = 0; j < 5; j ++){ float r1 = fminf(W, H) * (j + 0.5f) * 0.085f; float r2 = fminf(W, H) * (j + 1.5f) * 0.085f; float t = j * PI / 64.0f; for(int i = 1; i <= 64; i++){ float ct = cosf(t); float st = sinf(t); bresenham((int)(cx + r1 * ct), (int)(cy - r1 * st), (int)(cx + r2 * ct), (int)(cy - r2 * st)); t += 2.0f * PI / 64.0f; } } svpng(fopen("line_bresenham.png", "wb"), W, H, img, 0); return 0; }
Bresenham算法画圆
https://www.cnblogs.com/gamesky/archive/2012/09/03/2668932.html
代码:
#include <stdio.h> #include <stdlib.h> #include <math.h> #include <string.h> #include "svpng.inc" #define PI 3.14159265359f #define W 512 #define H 512 unsigned char img[W * H * 3]; void setPixel(int x, int y){ if(x >= 0 && x < W && y >=0 && y < H){ unsigned char* p = img + (y * W + x) * 3; p[0] = p[1] = p[2] = 0; } } // https://www.cnblogs.com/gamesky/archive/2012/09/03/2668932.html void bresenhamCircle(int x0, int y0, int r){ int x = 0; int y = r; int d = 1 - r; while(y > x){ setPixel(x0 + x, y0 + y); setPixel(x0 - x, y0 + y); setPixel(x0 - x, y0 - y); setPixel(x0 + x, y0 - y); setPixel(x0 + y, y0 + x); setPixel(x0 - y, y0 + x); setPixel(x0 - y, y0 - x); setPixel(x0 + y, y0 - x); if(d < 0){ d = d + 2 * x + 3; } else { d = d + 2 * (x - y) + 5; y--; } x++; } } int main(){ memset(img, 255, sizeof(img)); for(int i = 0; i < 36; i++){ bresenhamCircle(256, 256, 10 * i); } svpng(fopen("circle_bresenham.png", "wb"), W, H, img, 0); return 0; }
Bresenham算法画椭圆
https://www.cnblogs.com/yym2013/category/707569.html
https://blog.csdn.net/orbit/article/details/7496008
代码:
#include <stdio.h> #include <stdlib.h> #include <math.h> #include <string.h> #include "svpng.inc" #define PI 3.14159265359f #define W 512 #define H 512 unsigned char img[W * H * 3]; // https://www.cnblogs.com/yym2013/category/707569.html // https://blog.csdn.net/orbit/article/details/7496008 void setPixel(int x, int y){ if(x >= 0 && x < W && y >=0 && y < H){ unsigned char* p = img + (y * W + x) * 3; p[0] = p[1] = p[2] = 0; } } void bresenhamEllipse(int x0, int y0, int a, int b){ int sqa = a * a; int sqb = b * b; int x = 0; int y = b; int d = 2 * sqb - 2 * b * sqa + sqa; int px = (int)round((double)sqa / sqrt((double)(sqa+sqb))); while(x <= px){ setPixel(x0 + x, y0 + y); setPixel(x0 - x, y0 + y); setPixel(x0 - x, y0 - y); setPixel(x0 + x, y0 - y); if(d < 0){ d = d + 2 * sqb * (2 * x + 3); } else { d = d + 2 * sqb * (2 * x + 3) - 4 * sqa * (y - 1); y--; } x++; } d = sqb * (x * x + x) + sqa * (y * y - y) - sqa * sqb; while(y >= 0){ setPixel(x0 + x, y0 + y); setPixel(x0 - x, y0 + y); setPixel(x0 - x, y0 - y); setPixel(x0 + x, y0 - y); y--; if(d < 0){ x++; d = d - 2 * sqa * y - sqa + 2 * sqb * x + 2 * sqb; } else { d = d - 2 * sqa * y - sqa; } } } int main(){ memset(img, 255, sizeof(img)); for(int i = 0; i < 51; i++){ bresenhamEllipse(256, 256, 10 * i, 7 * i); } svpng(fopen("ellipse_bresenham.png", "wb"), W, H, img, 0); return 0; }
保存png图片,用到了svpng.inc,从这里下载: http://github.com/miloyip/svpng
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。