Bresenham 线算法所有情况

Posted

技术标签:

【中文标题】Bresenham 线算法所有情况【英文标题】:Bresenham's line algorithm all cases 【发布时间】:2017-08-10 09:29:26 【问题描述】:

我创建了一个函数,它接收 2D std::vector,向量中的 2 个点,并在向量中“绘制”一条线。但是,它并没有涵盖所有情况(八分圆)。我所说的线是指以直线相互连接的点。该向量将被写入.ppm 文件,因此它在图像中显示为一条线。

我使用这个链接实现了这个功能:https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm

看这里:https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm#All_cases 我试图弄清楚如何更改我的函数,以便它为 2D 矢量中的任何 2 个坐标“绘制”一条线,但我有点困惑。我不明白为什么有一个函数可以应用于输入和输出。以及在哪个坐标上应用哪个。另外,我不知道如何确定 2 个坐标的线在哪个八分圆内。

2D 向量将被写入.ppm 文件,如下所示:

255 255 255  255 255 255  255 255 255
255 255 255  0 0 0  255 255 255
255 255 255  255 255 255  255 255 255

此图像将是中心的一个黑点。

#include <vector>
#include <tuple>
#include <utility>

using pixel  = std::tuple<unsigned, unsigned, unsigned>; // rgb pixel
using row_t  = std::vector<pixel>; // row in a 2D vector
using grid_t = std::vector<row_t>; // the grid made up of rows
// x, y coordinate - access is like grid[y][x] since grid is made of rows
using coord  = std::pair<long long, long long>;

// Bresenham's line algorithm
// 2 points to draw a line between
void draw(grid_t& grid, const coord& c1, const coord& c2)

    long long dxc2.first - c1.first,
              dyc2.second - c1.second,
              D 2 * dy - dx,
              y c1.second;
    // is the if/else needed?
    if (c1.first <= c2.first)
        for (long long xc1.first; x <= c2.first; ++x)
        
            grid[y][x] = pixel0, 0, 0;
            if (D > 0)
            
                ++y;
                D -= 2 * dx;
            
            D += 2 * dy;
        
    else
        for (long long xc1.first; x >= c2.first; --x)
        
            grid[y][x] = pixel0, 0, 0;
            if (D > 0)
            
                ++y;
                D -= 2 * dx;
            
            D += 2 * dy;
        

任何帮助使此功能适用于所有情况(以及如何使其更好)并帮助我了解如何将不胜感激。

【问题讨论】:

“在向量中画一条线”是什么意思? @tobi303 他有一个向量向量(也就是一个二维数组),这个二维数组的每个元素代表一个像素。 @tobi303 一条由一系列点组成的线,尽可能笔直地连接在一条线上。我将编辑问题。 【参考方案1】:

输入函数对坐标进行变换,使变换后坐标始终位于第一个八分圆中。应用算法(仅适用于第一个八分圆)后,您必须再次将它们转换回原始八分圆。

使用了这个技巧,因为每个八分圆的算法需要不同。不是为所有不同的情况编写代码,而是应用转换以使算法本身保持简单。

但是,我也不完全了解如何正确应用该转换。***的文章对此并不十分清楚。在他们的示例中,它们有 (0, 1), (6, 4) 位于两个不同的八分圆中,但在下一节中他们说它仅适用于第一个八分圆。

【讨论】:

感谢您的澄清。看完文章有点懵。现在我只需要弄清楚如何确定由 2 个坐标点创建的线所在的八分圆。 为什么在应用算法后需要转换坐标?坐标已经被绘制(绘制)。 @cppxor2arr 您必须在绘制之前对其进行转换,或者将转换应用于我猜的整个图像。可以这样想:你只知道如何添加正数。如果我想让你把 -3 加到 -5 我会让你把 3 和 5 相加,你告诉我答案是 8 然后我仍然需要应用逆变换得到 -8 那么,有两种方法:1. 在运行算法之前转换 2 个坐标,然后在绘制点时运行它。通过遍历 2D 向量的元素来变换整个图像,变换每个当前坐标,并交换当前坐标和变换后的当前坐标的元素。 2. 在运行算法之前转换 2 个坐标。在运行算法时存储要绘制的坐标。转换存储的坐标并绘制它们。有错误吗? @cppxor2arr 我也不确定细节。我会在家里试试(但不是在工作时间;)。这是一个很好的问题,因为如果你做错了什么,你会立即看到哪里出了问题

以上是关于Bresenham 线算法所有情况的主要内容,如果未能解决你的问题,请参考以下文章

Bresenham画线算法

用C++如何实现bresenham画线算法?计算机图形学上面有个drawpixel的函数。不知道怎么用。

Bresenham 线算法错误

Bresenham&039;s线算法

Bresenham画线算法详解及其OpenGL编程实现

用Bresenham线算法绘制线条