您的位置:首页 > 其它

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

2015-11-25 21:58 519 查看
我们将平面划分成十个部分,从第一象限的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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: