布雷森汉姆线算法与朴素向量加法

Bresenham's Line Algorithm versus Naive Vector Addition

本文关键字:向量 算法 布雷森      更新时间:2023-10-16

给定xlen是 delta-x,ylen 是 delta-y,len是行的长度,为什么是这段代码:

//Bresenham implementation
float x = x0, y = y0;
if (slope < 1) {
    while (x < xlen) {
        paintpt(x, y));
         x += step;
        if (left.y > right.y) 
            y += slope * step;
        else 
            y -= slope * step;
   }
}

比这段代码更有效吗?

//Naive vector addition
int x = x0, y = y0;
float xinc = xlen / len, yinc = ylen / len;
for (float i = 0; i < len; i++) {
   paintpt(x, y);
   x += i * xinc;
   y += i * yinc;
}

(我的意思是,除了初始化,显然。假设你只得到线的长度和方向,并且必须退出斜率之类的,或者其他什么。

布雷森汉姆算法来自60年代,当时计算机可以放入大壁橱。其标志是:

  • 无浮点数学,
  • 没有乘法/除法。

因为在那些日子里,即使是整数除法和乘法也是"昂贵的"。"真正的"布雷森汉姆实现不会除法/乘法,也不会使用浮点数学。您的实现是"错误的"。在这里查看"真正的"一个。

1) x += i * xinc;这是一个四舍五入为整数的浮点乘法。它不能保证您遍历从开始x到最终x的所有整数。这意味着您的生产线可能有孔...

2)你的布雷森汉姆实施是错误的。您不会向x 添加步骤。每次迭代时递增x,并将delta_y添加到错误计数器。当错误计数器大于delta_x时,从错误计数器中递增y减去delta_x

这是对delta_y大于 0 且低于 delta_x 的行的解释。对所有其他情况进行轮换。

3)为了效率:这有点棘手。最老的计算机不能轻易地进行浮点计算。在奔腾之前,通常没有任何x87协处理器,所有浮点计算都是在软件中完成的。这比做简单的整数算术慢 1000 倍。如今,所有计算机都可以执行 SIMD 操作(即它们使用浮点矢量扩展);情况可能不再如此。