10
2018
10

Bresenham算法

Bresenham算法是计算机图形学领域使用最广泛的直线扫描转换方法。

Bresenham算法不止可以用来画直线,还可以用来画圆,画椭圆,等等,其他曲线。

Bresenham算法画直线的原理,可以参考:

https://blog.csdn.net/qq_26093511/article/details/73695096

这个写的比较清楚,有详细的推导过程,还有代码:https://wenku.baidu.com/view/eb1faabab84ae45c3b358cd8.html

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://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




« 上一篇下一篇 »

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。