2010-09-15 82 views
3

我已經在Python中編寫了一個Bresenham算法的實現(跟在Wikipedia article之後),並且除了某些角度的線條以外,它正常工作。所有應該在45度和90度之間或者135度和270度之間延伸的線將沿着y = x線延伸。Bresenham算法的執行失敗,對於某些角度的線條

這裏是我的代碼:

def bresenham(origin, dest): 
    # debug code 
    print origin 
    print dest 
    # end debug code 
    x0 = origin[0]; y0 = origin[1] 
    x1 = dest[0]; y1 = dest[1] 
    steep = abs(y1 - y0) > abs(x1 - x0) 
    backward = x0 > x1 

    if steep: 
     x0, y0 = y0, x0 
     x1, y1 = y1, x1 
    if backward: 
     x0, x1 = x1, x0 
     y0, y1 = y1, y0 

    dx = x1 - x0 
    dy = abs(y1 - y0) 
    error = dx/2 
    y = y0 

    if y0 < y1: ystep = 1 
    else: ystep = -1 

    result = [] 
    #if x0 > x1: xstep = -1 
    #else: xstep = 1 
    # debug code 
    print "x0 = %d" % (x0) 
    print "x1 = %d" % (x1) 
    print "y0 = %d" % (y0) 
    print "y1 = %d" % (y1) 
    for x in range(x0, x1): 
     if steep: result.append((y,x)) 
     else: result.append((x,y)) 
     error -= dy 
     if error < 0: 
      y += ystep 
      error += dx 
    # ensure the line extends from the starting point to the destination 
    # and not vice-versa 
    if backward: result.reverse() 
    print result 
    return result 

任何人看到我搞砸了?


編輯:

我添加了一些印刷的代碼的功能。

(0,0)位於顯示屏的左上角。

我的測試框架非常簡單。這是一個獨立的功能,所以我只是通過兩點吧:

起源=(416,384)
DEST =(440,347)
布氏(原產地,DEST)
(416,384)
(440,347)
X0 = 384
X1 = 347
Y0 = 416個
Y1 = 440
[]

+0

@aaa鯉魚:不。不過謝謝你的回答。 – Max 2010-09-15 00:20:00

+0

除了'如果x0> x1:xstep = -1'是不必要的,我沒有看到你的代碼有什麼問題,所以你的問題可能在其他地方。你需要發佈你的實際結果,以便我們看到發生了什麼。 – Gabe 2010-09-15 00:26:59

+0

@Gabe:'xstep'是必需的,因爲如果沒有它,如果'x0> x1',那麼for循環將立即終止,因爲Python for循環的默認步驟是1.除此之外,你會得到什麼樣的結果想?當它出錯時,它會返回一個點數列表,其中每個點在(1,1)之上或之下。 – Max 2010-09-15 00:45:14

回答

4

我不知道爲什麼你使用的是XSTEP變量。你並不需要使用你正在使用的算法。

@Gabe:需要XSTEP原因無它,如果X0> X1,則for循環將立即終止,作爲一個Python for循環默認的步驟是1

原因你不需要xstep變量是因爲,如果它正在倒退,座標已經被切換(在開始處有條件的if backward:),以便終點現在是起點,反之亦然,這樣我們現在是仍然從左到右。

你只需要這樣:

if backward: return result.reverse() 
else: return result 

result = [] 

for x in range(x0, x1): 
    if steep: result.append((y, x)) 
    else: result.append((x, y)) 
    error -= dy 
    if error < 0: 
     y += ystep 
     error += dx 

return result 

如果你想從開始爲終點座標列表中,那麼你就可以在年底做檢查編輯:問題是backward布爾正在評估它需要之前。如果steep條件執行,那麼值會更改,但是到那時您的條件將有所不同。爲了解決這個問題,而不是使用backward布爾值,使之成爲明確表示:

if x0 > x1: 
    # swapping here 

再說,因爲你最終使用布爾以後,你可能只是之前的有條件定義它:

backward = x0 > x1 

if backward: 
+0

本來我就像你所建議的那樣,但是當我試圖在我的問題中提到的角度做一行時,函數將不會返回任何內容,因爲for循環會立即終止。 「xstep」是一個解決方案。也許這意味着我的實現有其他問題? – Max 2010-09-15 00:48:09

+0

循環不應該失敗,因爲記住,我們交換了座標,使它仍然從左到右(例如x0,x1 = x1,x0)。也許你應該在循環之前打印出x0和x1來驗證。 – 2010-09-15 00:50:40

+0

我做過了,x0的確大於x1。 – Max 2010-09-15 00:53:24

4

問題是你在計算x0 > x1之前換了xy

相反的:

backward = x0 > x1 

if steep: 
    x0, y0 = y0, x0 
    x1, y1 = y1, x1 
if backward: 
    x0, x1 = x1, x0 
    y0, y1 = y1, y0 

你應該有:

if steep: 
    x0, y0 = y0, x0 
    x1, y1 = y1, x1 

backward = x0 > x1 
if backward: 
    x0, x1 = x1, x0 
    y0, y1 = y1, y0 
+0

啊!那樣做了。謝謝。 – Max 2010-09-15 01:15:32

+0

猜測我對於我所做的所有工作都不配得上應有的贊成,因爲我在他之前發佈瞭解決方案;道具Gabe雖然也發現它:) – 2010-09-15 01:17:51

+0

@Blaenk。對不起,你是對的。早一點就知道了。修復,並upvoted啓動。謝謝你的幫助。 :) – Max 2010-09-15 01:38:15