直线生成算法——Bresenham画线法

我们将平面划分成十个部分,从第一象限的x轴开始做逆时针旋转,每隔45度角为一部分,由此类推到第八部分。Y轴正向为第九部分,负向为第十部分。

当直线的斜率k∈[0,1],Bresenham画线算法的基本原理是通过各行各列像素中心构造一张虚拟网格线,按直线从起点到终点的顺序计算直线与各垂直网格线的交点,然后确定该列像素中与此交点最近的像素。如果在x方向增加一个单位长度,在y方向是否增加一个单位根据计算的误差项d来决定。d为所画直线与网格垂直线的交点到本网格水平底线的距离。

当d>=1时,将其减去1,使其保持在一个单位之内,因此误差项d的界定为0.5.判断条件为:d>=0.5取右上方像素,反之取正右方像素。

同理于斜率在[1,+∞]和负数的情况,当斜率的绝对值大于1时,如果在y轴方向增加一个单位长度,在x方向是否增加一个单位根据计算的误差项d来决定。

程序实现时,依旧划分为8+2个共10个区域,但是这次引入对换方法实现,由于8个区域内存在4对4的斜率相同的情况,即,八个两两中心对称的区域斜率相同,只是始末点不同。同时因为直线的无向性,所以我们以y轴为届,x轴正向的情况通过公式导出,x轴负向的通过其中心对称区域的点互换数值实现直线画图。同时依旧使用if和switch语句实现。


OnBresenhamline()
{
	*pDC = GetDC();
	tempx = 0;
<span style="white-space:pre">	</span>tempy = 0;
	if (x0 > x1)
	{
		tempx = x0;
		x0 = x1;
		x1 = tempx;

		tempy = y0;
		y0 = y1;
		y1 = tempy;
	}

	dx = x1 - x0;
	dy = y1 - y0;
	ex = -dx;
	ey = -dy;

	x = x0;
	y = y0;
	state = 0;
	Dx = abs(dx);
	Dy = abs(dy);


	//状态分析
	if (dx > 0)
	{
		if (dy < 0)
		{
			if (Dx >= Dy)
				state = 1;
			else
				state = 2;
		}
		else
		{
			if (Dx >= Dy)
				state = 8;
			else
				state = 7;
		}
	}
	else if (dx < 0)
	{
		if (dy < 0)
		{
			if (Dx <= Dy)
				state = 3;
			else
				state = 4;
		}
		else
		{
			if (Dx <= Dy)
				state = 6;
			else
				state = 5;
		}
	}
	else if (dy < 0)
		state = 9;
	else
		state = 10;

	switch (state)
	{
	case 1: case 5:
		for (i = 0; i <= dx; i++)
		{
			pDC->SetPixel(x, y, color);
			x++;
			ex += (-2) * dy;
			if (ex >= 0)
			{
				y--;
				ex = ex - 2 * dx;
			}
		}
		break;
	case 2: case 6:
		for (i = 0; i <= (-dy); i++)
		{
			pDC->SetPixel(x, y, color);
			y--;
			ey += 2 * dx;
			if (ey >= 0)
			{
				x++;
				ey = ey + 2 * dy;
			}
		}
		break;
	case 3: case 7:
		for (i = 0; i <= dy; i++)
		{
			pDC->SetPixel(x, y, color);
			y++;
			ey += 2 * dx;
			if (ey >= 0)
			{
				x++;
				ey = ey - 2 * dy;
			}
		}
		break;
	case 4: case 8:
		for (i = 0; i <= dx; i++)
		{
			pDC->SetPixel(x, y, color);
			x++;
			ex += 2 * dy;
			if (ex >= 0)
			{
				y++;
				ex = ex - 2 * dx;
			}
		}
		break;
	case 9:
		while (y >= y1)
		{
			y--;
			pDC->SetPixel(x, y, color);
		}
		break;
	case 10:
		while (y <= y1)
		{
			y++;
			pDC->SetPixel(x, y, color);
		}
		break;
	default:
		break;
	}
	ReleaseDC(pDC);
}


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值