抗锯齿 Bresenham 的线没有按预期工作
Anti-aliasing Bresenham's line not working as expected
我正在尝试使用这篇文章实现具有抗锯齿功能的 bresenham 线条图:
http://members.chello.at/~easyfilter/bresenham.html
函数如下:
void ColoringScene::drawLineAA(int x0, int y0, int x1, int y1, int r, int g, int b, int a)
{
float dx = abs(x1-x0), sx = x0<x1 ? 1 : -1;
float dy = abs(y1-y0), sy = y0<y1 ? 1 : -1;
float err = dx-dy, e2, x2; /* error value e_xy */
float ed = dx+dy == 0 ? 1 : sqrt((float)dx*dx+(float)dy*dy);
for (;;){ /* pixel loop */
setPixel(x0, y0, r, g, b, a*abs(err-dx+dy)/ed);
e2 = err; x2 = x0;
if (2*e2 >= -dx) { /* x step */
if (x0 == x1) break;
if (e2+dy < ed) setPixel(x0, y0 + sy, r, g, b, a*(e2+dy)/ed);
err -= dy; x0 += sx;
}
if (2*e2 <= dy) { /* y step */
if (y0 == y1) break;
if (dx-e2 < ed) setPixel(x2 + sx, y0, r, g, b, a*(dx-e2)/ed);
err += dx; y0 += sy;
}
}
}
不知道它是否改变了什么,但我将所有 int 都更改为 float。只是为了确定除法是否适用于浮点数。不管怎样,整数结果是一样的。
现在,示例调用:
drawLineAA(10, 10, 50, 400, 255, 0, 0, 255);
drawLineAA(100, 10, 500, 40, 255, 0, 0, 255);
结果:
如果我像这样将 y0 + sy 更改为 y0 - sy:
if (e2+dy < ed) setPixel(x0, y0 - sy, r, g, b, a*(e2+dy)/ed);
输出变成这样:
如果我像这样将 x2 + sx 更改为 x2 - sx:
if (dx-e2 < ed) setPixel(x2 - sx, y0, r, g, b, a*(dx-e2)/ed);
现在的输出是:
所以最后的配置都是负数,它给出:
差不多好了,但出现了一些漏洞。所以还是错了。我无法弄清楚,为什么它没有正确绘制。当我尝试没有抗锯齿的普通 bresenham 时,它没有任何问题。
同样重要的是,在我的例子中,我使用 cocos2d-x 纹理,所以 y 被翻转了。这就是为什么我有这个方法:
void ColoringScene::setPixel(int x, int y, int r, int g, int b, int a){
if(x < 0 || x >= img->getWidth() || y < 0 || y >= img->getHeight()) return;
int index = (x + (img->getHeight() - y - 1) * img->getWidth()) * 4;
data[index] = r;
data[index + 1] = g;
data[index + 2] = b;
data[index + 3] = a;
}
也许是因为这个问题。我该如何解决这个问题?
此致
这个算法似乎不正确。
x0==x1
或 y0==y1
是致命错误。
dx==dy
是致命错误。
- 当
dx+dy=0
时设置 ed=1
完全是任意的。
2*e2==dy
和 2*e2==-dx
导致每步绘制三个像素。
建议:将dx=dy、dx=-dy、dx=0、dy=0视为特殊情况,为每个八分圆制作单独的情况,如果不需要则不要使用浮点数。
我正在尝试使用这篇文章实现具有抗锯齿功能的 bresenham 线条图: http://members.chello.at/~easyfilter/bresenham.html
函数如下:
void ColoringScene::drawLineAA(int x0, int y0, int x1, int y1, int r, int g, int b, int a)
{
float dx = abs(x1-x0), sx = x0<x1 ? 1 : -1;
float dy = abs(y1-y0), sy = y0<y1 ? 1 : -1;
float err = dx-dy, e2, x2; /* error value e_xy */
float ed = dx+dy == 0 ? 1 : sqrt((float)dx*dx+(float)dy*dy);
for (;;){ /* pixel loop */
setPixel(x0, y0, r, g, b, a*abs(err-dx+dy)/ed);
e2 = err; x2 = x0;
if (2*e2 >= -dx) { /* x step */
if (x0 == x1) break;
if (e2+dy < ed) setPixel(x0, y0 + sy, r, g, b, a*(e2+dy)/ed);
err -= dy; x0 += sx;
}
if (2*e2 <= dy) { /* y step */
if (y0 == y1) break;
if (dx-e2 < ed) setPixel(x2 + sx, y0, r, g, b, a*(dx-e2)/ed);
err += dx; y0 += sy;
}
}
}
不知道它是否改变了什么,但我将所有 int 都更改为 float。只是为了确定除法是否适用于浮点数。不管怎样,整数结果是一样的。
现在,示例调用:
drawLineAA(10, 10, 50, 400, 255, 0, 0, 255);
drawLineAA(100, 10, 500, 40, 255, 0, 0, 255);
结果:
如果我像这样将 y0 + sy 更改为 y0 - sy:
if (e2+dy < ed) setPixel(x0, y0 - sy, r, g, b, a*(e2+dy)/ed);
输出变成这样:
如果我像这样将 x2 + sx 更改为 x2 - sx:
if (dx-e2 < ed) setPixel(x2 - sx, y0, r, g, b, a*(dx-e2)/ed);
现在的输出是:
所以最后的配置都是负数,它给出:
差不多好了,但出现了一些漏洞。所以还是错了。我无法弄清楚,为什么它没有正确绘制。当我尝试没有抗锯齿的普通 bresenham 时,它没有任何问题。
同样重要的是,在我的例子中,我使用 cocos2d-x 纹理,所以 y 被翻转了。这就是为什么我有这个方法:
void ColoringScene::setPixel(int x, int y, int r, int g, int b, int a){
if(x < 0 || x >= img->getWidth() || y < 0 || y >= img->getHeight()) return;
int index = (x + (img->getHeight() - y - 1) * img->getWidth()) * 4;
data[index] = r;
data[index + 1] = g;
data[index + 2] = b;
data[index + 3] = a;
}
也许是因为这个问题。我该如何解决这个问题?
此致
这个算法似乎不正确。
x0==x1
或y0==y1
是致命错误。dx==dy
是致命错误。- 当
dx+dy=0
时设置ed=1
完全是任意的。 2*e2==dy
和2*e2==-dx
导致每步绘制三个像素。
建议:将dx=dy、dx=-dy、dx=0、dy=0视为特殊情况,为每个八分圆制作单独的情况,如果不需要则不要使用浮点数。