【计算机图形学】-直线和圆弧绘制算法实现 (code included)

1. 问题描述:

理解基本图形元素光栅化的基本原理,实现直线绘制的中点画线算法、Bresenham算法、圆弧生成的中点画圆算法。掌握OpenGL画线及设置线的属性(颜色、线宽、线型)方法。


2. 算法描述:

1) 中心画线算法:

下面展示一些 伪代码

void MidPLine(int x0,int y0,int x1,int y1,void (*setPixel)(int x,int y))
{
		a⬅abs(y0 - y1); b⬅abs(x0 - x1); d⬅a + b / 2; 
		if(y0 > y1)  
		{	
			x⬅x0; y⬅y0;
			setPixel(x, y);
			while (x < x1) {
				if (d < 0) {
					x++; y++;
					d⬅d + a + b;  // 取直线上方的像素点
				}
				else {
					x++;
					d += a;         // 取直线下方的像素点
				}
			if (abs(斜率) >= 1) setPixel(y, x);
			else setPixel(x, y);
		}
		else {		
			// 与上一种情况类似
		}
}

2) Bresenham算法:

下面展示一些 伪代码

void BresLine(int x0, int y0, int x1, int y1, void (*setPixel)(int x, int y)) {
	SetPixel(x0, y0);		// 绘出起始点(x0,y0)
	dx⬅abs(x0 - x1);	// 表示两点x轴方向上的差值
	dy⬅abs(y0 - y1);	// 表示两点y轴方向上的差值
	// 当(x0,y0)(x1,y1)表示同一个点时,退出函数。
	if (dx < dy){	// 下面将斜率变换至0≤丨k丨≤1区间
		flag = 1;	// 此情况下丨k丨>=1,以x1,x2表示y轴的点;y1,y2表示x轴的点,以y轴为计长方向
		swap_value(&x0, &y0);	
		swap_value(&x1, &y1);
		swap_value(&dx, &dy);
	}
	int tx⬅ (x1 - x0) > 0 ? 1 : -1;	// tx表示直线相对于起点在x轴的方向
	int ty⬅ (y1 - y0) > 0 ? 1 : -1;	// ty表示直线相对于起点在y轴的方向
	int curx = x0;
	int cury = y0;
	int dS⬅2 * dy;			// 用于表示迭代式中的项
	int dT⬅2 * (dy - dx);		// 用于表示迭代式中的项
	int d⬅dS - dx;			// 用于表示迭代式中的项
	while (curx != x1){
		if (d < 0)				// 取直线下方的像素点
			d += dS;
		else{					// 取直线上方的像素点
			cury += ty; 
			d += dT;
		}
		if(flag)
			SetPixel(cury, curx);
		else
			SetPixel(curx, cury);
		curx += tx;
	}
}

3) 中心画圆算法:

下面展示一些 伪代码

void MidPoint_Circle(int x0,int y0,int x1,int y1,void (*setPixel)(int x,int y))
{
	r⬅sqrt((1.0 * x1 - x0) * (1.0 * x1 - x0) + (1.0 * y1 - y0) * (1.0 * y1 - y0));	// 计算半径
	x⬅0; y⬅r; d⬅1 - r;	// 是公式中 1.25-r 取整后的结果
	Cirpot(x0, y0, x, y, SetPixel);	// 进行8路对称
	while (x < y)
	{
		if (d < 0)
			d += 2 * x + 3;		// 表明当前中点在圆内,下一个点亮的像素点选取圆外的像素点
		else {
			d += 2 * (x - y) + 5;	// 表明当前中点在圆外,下一个点亮的像素点选取圆内的像素点
			y--;
		}
		x++;
		Cirpot(x0, y0, x, y, SetPixel);
	}
}


测试结果:

1) 使用中点画线算法(任意斜率均可以画出,函数名:MidPLine)完成画线:

实际运行结果:
在这里插入图片描述

2) 使用Bresenham算法(任意斜率均可以画出,函数名:BresLine)完成画线:

实际运行结果:
在这里插入图片描述

3) 使用中点画圆算法(函数名:MidPoint_Circle)完成画圆:

实际运行结果:
在这里插入图片描述

4) 用OpenGL画直线方法(函数名:OpenGLLine)完成画线:

实际运行结果:
在这里插入图片描述


分析与评论:

1) 中点画线算法:

本算法以起点到终点的计长方向距离 = max{|x1-x0|,|y1-y0|} 来进行扫描画线,时间复杂度为O(max{|x1-x0|,|y1-y0|})。

2) Bresenham算法:

Bresenham算法与中点画线算法一样,扫描的像素点是以起点到终点的计长方向距离 = max{|x1-x0|,|y1-y0|},所以时间复杂度也为O(max{|x1-x0|,|y1-y0|})。

3) 中点画圆算法:

以起点(x0,y0)为圆心,线段两端的距离为半径画圆。在画圆的过程中以x轴的计长方向上的值来扫描像素点,所以总的时间复杂度是O(|x结束-x起始|)。但是由于本算法中有一步将”1.25-r”取整为”1-r”将导致出现误差,如果用双精度存不取整将更精确。

4) 用OpenGL画直线方法完成画线:

相比于中间画线算法和Bresenham算法,这种算法是封装好的函数,对于初学者来说很友好,只需修改对应参数即可,可操控性强。

附录: Source Code(in C)

链接: 直线和圆弧绘制算法实现.rar

(代码仅供参考)

没有币的同学来Gitee吧!记得留下Star噢~
Jack-lllll 的Gitee仓库

  • 2
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值