C语言画直线~Bresenham方法

前言

由于项目上遇到了棘手的问题,给定坐标需要实现C绘制直线的驱动函数,绘制直线一般都是显示屏的底层函数,本想着找个显示屏的驱动看下drawline源码,但仔细想一想会不会底层用的是汇编尼,于是便放弃了这种想法。通过百度学习到这是计算机图形学方面的,寻找到了解决办法就是自己用C实现,网上有三种方法:

  1. 数值微分DDA(Digital Differential Analyzer)算法
  2. 中点画线算法
  3. Bresenham算法

这三种方法的优缺点知乎——《不调用画图 API,用C 或 C++ 如何实现画一条线?》上面说的很清楚,还有腾讯的游戏开发、计算机图形学方面的高级工程师也有在知乎讲到《用 C 语言画直线》,我是采用了最后一种方法。

一. 代码

// 来自知乎
char pic[50][50] = {0};

void show_pic(){
	for(int i=49;i>=0;--i){
		for(int j=0;j<50;j++){
			if(pic[i][j]==1) printf("x ");
			else printf("o ");
		}
		printf("\n");
	}
}
void drawline_old(int x0,int y0,int x1,int y1){
	int dx = abs(x0-x1);
	int dy = abs(y0-y1);
	printf("dx: %d,dy: %d \n",dx,dy);

	int y = y0,e = -2*dx;
	for(int x=x0; x<=x1;++x){
		pic[y][x] = 1;
		e += 2*dy;
		if(e > 0) ++y;
		if(e >= dx) e -= 2*dx;
	}
}
// 使用 Bresenham 算法画任意斜率的直线(包括起始点,不包括终止点)
void Line_Bresenham(int x1, int y1, int x2, int y2){
	int x = x1;
	int y = y1;
	int dx = abs(x2 - x1);
	int dy = abs(y2 - y1);
	int s1 = x2 > x1 ? 1 : -1;
	int s2 = y2 > y1 ? 1 : -1;

	char interchange = 0;	// 默认不互换 dx、dy
	if (dy > dx)				// 当斜率大于 1 时,dx、dy 互换
	{
		int temp = dx;
		dx = dy;
		dy = temp;
		interchange = 1;
	}

	int p = 2 * dy - dx;
	for(int i = 0; i < dx; i++)
	{
		pic[y][x] = 1;
		if (p >= 0)
		{
			if (!interchange)		// 当斜率 < 1 时,选取上下象素点
				y += s2;
			else					// 当斜率 > 1 时,选取左右象素点
				x += s1;
			p -= 2 * dx;
		}
		if (!interchange)
			x += s1;				// 当斜率 < 1 时,选取 x 为步长
		else
			y += s2;				// 当斜率 > 1 时,选取 y 为步长
		p += 2 * dy;
	}
}

int main(void) {
	//drawline_old(2,2,50,10);
	Line_Bresenham(2,2,50,10);
	show_pic();
	return EXIT_SUCCESS;
}

二. 实测效果

实际测试了两个函数,easyx给出的方法可靠考虑的比较全面,可以拿过来移植。最近工作收获挺多的,也不知道未来会深入到哪一个方向,先记下来,图形学还是蛮好玩的。最后推荐一下EasyX ,看他文章虽然比较老了,但是都是精华。

EasyX Library for C++ 是针对 VC 的一套绘图库,接口简单易用,用起来很像 TC 的 graphics.h 绘图。

C语言画直线~Bresenham方法_第1张图片

你可能感兴趣的:(#,C/C++,编程语言,C语言,画直线,Bresenham,EasyX)