Bresenham画线算法
void line(int ax, int ay, int bx, int by, TGAImage &framebuffer, TGAColor color)
{
// 更陡峭时使用y遍历
bool steep = std::abs(ay - by) > std::abs(ax - bx);
if (steep)
{
// 交换x轴和y轴
std::swap(ax, ay);
std::swap(bx, by);
}
// 保证 bx >= ax, 遍历从 ax 到 bx
if (ax > bx)
{
std::swap(ax, bx);
std::swap(ay, by);
}
int y = ay;
int ierror = 0.;
//通过x去遍历,保证足够的采样点,使线段连续
for (int x = ax; x <= bx; x++)
{
if (steep)
framebuffer.set(y, x, color);
else
framebuffer.set(x, y, color);
//将float计算优化为int计算,提升性能
ierror += 2 * std::abs(by - ay);
y += (by > ay ? 1 : -1) * (ierror >= bx - ax);
ierror -= 2 * (bx - ax) * (ierror >= bx - ax);
}
}
作者的思路是以线段的参数方程入手,如有两个点(ax,ay)和(bx,by),那么该线段上任意一点P = Pa + t * (Pb – Pa),其中t的值为0到1。
现在我们使x从ax到bx逐一像素遍历(需保证ax <=bx),带入上述方程可得x = ax + t * (bx – ax),变换一下得到t = (x – ax) / (bx – ax),以此可以得到当前x对应的y坐标,y = ay + (x – ax) / (bx – ax) * (by – ay)。
但是这种直接计算的方法需要用到浮点数计算,有一定的性能消耗,且浮点数的取整可能会导致线段不连续。
因此通过int运算代替float预算,用int型变量ierror去累计误差值,优化算法的性能并避免线段的离散。
评论(0)
暂无评论