Php 不带对角线运动的Bresenham线
是否有一种改进的Bresenham算法,其中从一个像素到下一个像素的步长不允许是对角的、水平的或垂直的?或者任何其他算法都可以做到这一点?PHP优先Php 不带对角线运动的Bresenham线,php,algorithm,line,bresenham,Php,Algorithm,Line,Bresenham,是否有一种改进的Bresenham算法,其中从一个像素到下一个像素的步长不允许是对角的、水平的或垂直的?或者任何其他算法都可以做到这一点?PHP优先 Right: 0 0 0 1 0 0 1 1 0 1 1 0 1 1 0 0 Wrong: 0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 0 应该是一个很小的修改——假设你在象限I——即向上和向右。不是做对角线,而是做向上。。。然后右转 而不是: for x from x0 to x1 plot(x,
Right:
0 0 0 1
0 0 1 1
0 1 1 0
1 1 0 0
Wrong:
0 0 0 1
0 0 1 0
0 1 0 0
1 0 0 0
应该是一个很小的修改——假设你在象限I——即向上和向右。不是做对角线,而是做向上。。。然后右转 而不是:
for x from x0 to x1
plot(x,y)
error := error + deltaerr
if error ≥ 0.5 then
y := y + 1
error := error - 1.0
大概是这样的:
for x from x0 to x1
plot(x,y)
error := error + deltaerr
if error ≥ 0.5 then
y := y + 1
plot(x,y)
error := error - 1.0
应该是一个很小的修改——假设你在象限I——即向上和向右。不是做对角线,而是做向上。。。然后右转 而不是:
for x from x0 to x1
plot(x,y)
error := error + deltaerr
if error ≥ 0.5 then
y := y + 1
error := error - 1.0
大概是这样的:
for x from x0 to x1
plot(x,y)
error := error + deltaerr
if error ≥ 0.5 then
y := y + 1
plot(x,y)
error := error - 1.0
詹姆斯的回答很酷,但正如他评论的那样,这有点偏离了底线。对原始Bresenham的另一个简单修改是绘制一条不带对角线的直线,该直线更接近真实直线 这是原始Bresenham算法的实现:
public void line(int x0, int y0, int x1, int y1, int value) {
int xDist = Math.abs(x1 - x0);
int yDist = -Math.abs(y1 - y0);
int xStep = (x0 < x1 ? +1 : -1);
int yStep = (y0 < y1 ? +1 : -1);
int error = xDist + yDist;
plot(x0, y0, value);
while (x0 != x1 || y0 != y1) {
if (2*error > yDist) {
// horizontal step
error += yDist;
x0 += xStep;
}
if (2*error < xDist) {
// vertical step
error += xDist;
y0 += yStep;
}
plot(x0, y0, value);
}
}
修改只是执行水平或垂直步骤,而不是同时执行两个步骤,这取决于错误指示器是否更接近水平或垂直步骤:
public void lineNoDiag(int x0, int y0, int x1, int y1, int value) {
int xDist = Math.abs(x1 - x0);
int yDist = -Math.abs(y1 - y0);
int xStep = (x0 < x1 ? +1 : -1);
int yStep = (y0 < y1 ? +1 : -1);
int error = xDist + yDist;
plot(x0, y0, value);
while (x0 != x1 || y0 != y1) {
if (2*error - yDist > xDist - 2*error) {
// horizontal step
error += yDist;
x0 += xStep;
} else {
// vertical step
error += xDist;
y0 += yStep;
}
plot(x0, y0, value);
}
}
这样可以有效地选择使误差最小化的步长,从而使直线更接近实际直线
代码是用Java编写的,但是应该可以轻松地移植到PHP。我还没有完全测试过它,但是它应该和原来的Bresenham一样好用。这甚至可能快一点。詹姆斯的回答很酷,但正如他所评论的,这有点偏离了底线。对原始Bresenham的另一个简单修改是绘制一条不带对角线的直线,该直线更接近真实直线 这是原始Bresenham算法的实现:
public void line(int x0, int y0, int x1, int y1, int value) {
int xDist = Math.abs(x1 - x0);
int yDist = -Math.abs(y1 - y0);
int xStep = (x0 < x1 ? +1 : -1);
int yStep = (y0 < y1 ? +1 : -1);
int error = xDist + yDist;
plot(x0, y0, value);
while (x0 != x1 || y0 != y1) {
if (2*error > yDist) {
// horizontal step
error += yDist;
x0 += xStep;
}
if (2*error < xDist) {
// vertical step
error += xDist;
y0 += yStep;
}
plot(x0, y0, value);
}
}
修改只是执行水平或垂直步骤,而不是同时执行两个步骤,这取决于错误指示器是否更接近水平或垂直步骤:
public void lineNoDiag(int x0, int y0, int x1, int y1, int value) {
int xDist = Math.abs(x1 - x0);
int yDist = -Math.abs(y1 - y0);
int xStep = (x0 < x1 ? +1 : -1);
int yStep = (y0 < y1 ? +1 : -1);
int error = xDist + yDist;
plot(x0, y0, value);
while (x0 != x1 || y0 != y1) {
if (2*error - yDist > xDist - 2*error) {
// horizontal step
error += yDist;
x0 += xStep;
} else {
// vertical step
error += xDist;
y0 += yStep;
}
plot(x0, y0, value);
}
}
这样可以有效地选择使误差最小化的步长,从而使直线更接近实际直线
代码是用Java编写的,但是应该可以轻松地移植到PHP。我还没有完全测试过它,但是它应该和原来的Bresenham一样好用。甚至可能快一点。我发现弗兰兹D的答案产生的线条在接近水平或垂直时与原始线条不匹配。虽然下面的函数并不完美,但我发现它可以产生更好的结果
Function BresenhamLineNew : Void( x0 : Int, y0 : Int, x1 : Int, y1 : Int )
Local dx : Int = Abs( x1 - x0 )
Local dy : Int = Abs( y1 - y0 )
Local sx : Int = -1
Local sy : Int = -1
If x0 < x1 Then sx = 1
If y0 < y1 Then sy = 1
Local err : Int = dx - dy
Local e2 : Int
While True
DrawRect x0, y0, 1, 1
If x0 = x1 And y0 = y1 Then Exit
e2 = 2 * err
If dy > dx
If e2 > -dy
err = err - dy
x0 = x0 + sx
Elseif e2 < dx
err = err + dx
y0 = y0 + sy
Endif
Else
If e2 < dx
err = err + dx
y0 = y0 + sy
Elseif e2 > -dy
err = err - dy
x0 = x0 + sx
Endif
Endif
Wend
End Function
我发现Franz D的答案产生的线条在接近水平或垂直方向时与原始线条不匹配。虽然下面的函数并不完美,但我发现它可以产生更好的结果
Function BresenhamLineNew : Void( x0 : Int, y0 : Int, x1 : Int, y1 : Int )
Local dx : Int = Abs( x1 - x0 )
Local dy : Int = Abs( y1 - y0 )
Local sx : Int = -1
Local sy : Int = -1
If x0 < x1 Then sx = 1
If y0 < y1 Then sy = 1
Local err : Int = dx - dy
Local e2 : Int
While True
DrawRect x0, y0, 1, 1
If x0 = x1 And y0 = y1 Then Exit
e2 = 2 * err
If dy > dx
If e2 > -dy
err = err - dy
x0 = x0 + sx
Elseif e2 < dx
err = err + dx
y0 = y0 + sy
Endif
Else
If e2 < dx
err = err + dx
y0 = y0 + sy
Elseif e2 > -dy
err = err - dy
x0 = x0 + sx
Endif
Endif
Wend
End Function
事实上,这会使你的思路有点歪。视在中心的平均值比预期的高出半个像素。如果这很重要,你可能不得不修改错误计算。实际上,这会使你的线有点歪斜。视在中心的平均值比预期的高出半个像素。如果这很重要,您可能必须修改错误计算。