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 绘图。

实测效果

  • 7
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Bresenham 算法是一种离散化的画线算法,采用了整数运算,具有高效、简单的特点。该算法的实现步骤如下: 1. 根据起点和终点坐标计算出直线斜率 k 2. 根据斜率 k 的正负情况和起点和终点的位置关系确定每次画线的方向(上下或左右) 3. 根据斜率 k 的绝对值大小判断每次画线的步长(1 或 -1) 4. 根据起点和终点的位置关系确定起始点,并按照每次画线的步长和方向不断画线直到到达终点 以下是 C 语言实现 Bresenham 算法的代码示例: ``` #include<stdio.h> #include<graphics.h> void BresenhamLine(int x1, int y1, int x2, int y2) { int dx = x2 - x1; int dy = y2 - y1; int x = x1; int y = y1; int stepx = dx > 0 ? 1 : -1; int stepy = dy > 0 ? 1 : -1; dx = abs(dx); dy = abs(dy); putpixel(x, y, WHITE); if (dx > dy) { int p = 2 * dy - dx; for (int i = 0; i < dx; i++) { if (p < 0) { p += 2 * dy; } else { p += 2 * (dy - dx); y += stepy; } x += stepx; putpixel(x, y, WHITE); } } else { int p = 2 * dx - dy; for (int i = 0; i < dy; i++) { if (p < 0) { p += 2 * dx; } else { p += 2 * (dx - dy); x += stepx; } y += stepy; putpixel(x, y, WHITE); } } } int main() { int gd = DETECT, gm; initgraph(&gd, &gm, ""); BresenhamLine(0, 0, 100, 100); getch(); closegraph(); return 0; } ``` 该代码同样使用了图形库 `graphics.h`,并调用 `putpixel` 函数来绘制像素点。需要注意的是,在 Windows 环境下需要使用 `BGI` 图形库来支持绘图操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不会画板子的物联网工程师

如果文章还不错,欢迎点赞收藏~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值