如何将Bresenham的画线算法与裁剪一起使用? [英] How to use Bresenham's line drawing algorithm with clipping?

查看:90
本文介绍了如何将Bresenham的画线算法与裁剪一起使用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 Bresenham画线算法绘制线时,该行可能不在要写入的位图的范围内-剪切结果将很有用,以便它们适合要写入的图像的轴对齐范围内.

When drawing a line with Bresenham line drawing algorithm, where the line may not be within the bounds of the bitmap being written to - it would be useful to clip the results so they fit within the axis aligned bounds of the image being written to.

虽然可以先将线剪裁到矩形,然后再画线.这是不理想的,因为它常常使(假设使用int坐标)线的倾斜度稍有不同.

While its possible to first clip the line to the rectangle, then draw the line. This isn't ideal since it often gives a slightly different slant to the line (assuming int coords are being used).

由于这是原始操作,是否存在在保持相同形状的同时剪切线的方法?

Since this is such a primitive operation, are there established methods for clipping the line while maintaining the same shape?

如果有帮助,请这是该算法的参考实现-它使用int坐标,这样可以避免在绘制直线时进行int/float转换.

In case it helps, here is a reference implementation of the algorithm - it uses int coords, which avoids int/float conversion while drawing the line.

我花了一些时间研究这个问题:

I spent some time looking into this:

推荐答案

让我们重新构造问题,以便我们了解布雷森汉姆算法的真正工作原理...

Let's reframe the problem so we can see how Bresenham's algorithm really works...

让我们说您正在画一条从(x0,y0)(x1,y1)的基本上是水平的线(该方法对于大多数是垂直的,但是轴已切换):

Lets say you are drawing a mostly horizontal line (the method is the same for mostly vertical, but with the axes switched) from (x0,y0) to (x1,y1):

整行可以用 x (所有整数)描述为 y 的函数:

The full line can be described as a function of y in terms of x (all integers):

y = y0 + round( (x-x0) * (y1-y0) / (x1-x0) )

这精确地描述了绘制整条线时要绘制的每个像素,并且当连续裁剪线时,它 still 精确地描述了要绘制的每个像素-您只需将其应用于较小的 x 值的范围.

This describes precisely each pixel you will paint when drawing the full line, and when you clip the line consistently, it still describes precisely each pixel you will paint -- you just apply it to a smaller range of x values.

我们可以使用所有整数数学,通过分别计算除数和余数来评估此函数.对于 x1> = x0 y1> = y0 (否则请进行常规转换):

We can evaluate this function using all integer math, by calculating the divisor and remainder separately. For x1 >= x0 and y1 >= y0 (do the normal transformations otherwise):

let dx = (x1-x0);
let dy = (y1-y0);
let remlimit = (dx+1)/2; //round up

rem = (x-x0) * dy % dx;
y = y0 + (x-x0) * dy / dx;
if (rem >= remlimit)
{
    rem-=dx;
    y+=1;
}

布雷森纳姆(Bresenham)算法是在更新 x 时递增地更新此公式结果的一种快速方法.

Bresenham's algorithm is a just a fast way to update the result of this formula incrementally as you update x.

在这里,我们可以利用增量更新来绘制从x = xs到x = xe的同一行的一部分:

Here's how we can make use of incremental updates to draw the portion of the very same line from x=xs to x=xe:

let dx = (x1-x0);
let dy = (y1-y0);
let remlimit = (dx+1)/2; //round up

x=xs;
rem = (x-x0) * dy % dx;
y = y0 + (x-x0) * dy / dx;
if (rem >= remlimit)
{
    rem-=dx;
    y+=1;
}
paint(x,y);
while(x < xe)
{
    x+=1;
    rem+=dy;
    if (rem >= remlimit)
    {
        rem-=dx;
        y+=1;
    }
    paint(x,y);
}

如果要对0进行余数比较,则可以在开始时将其偏移:

If you want do to your remainder comparisons against 0, you can just offset it at the beginning:

let dx = (x1-x0);
let dy = (y1-y0);
let remlimit = (dx+1)/2; //round up

x=xs;
rem = ( (x-x0) * dy % dx ) - remlimit;
y = y0 + (x-x0) * dy / dx;
if (rem >= 0)
{
    rem-=dx;
    y+=1;
}
paint(x,y);
while(x < xe)
{
    x+=1;
    rem+=dy;
    if (rem >= 0)
    {
        rem-=dx;
        y+=1;
    }
    paint(x,y);
}

这篇关于如何将Bresenham的画线算法与裁剪一起使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆