2015-12-13 39 views
0

我一直在試圖用附着在網格上的鼠標繪製一條線。我正在使用Bresenhams線算法。如何修改Bresenham的線路算法以保持秩序?

但是我需要它來保存順序,所以如果用戶正在向左繪圖,它會按順序給我點。

WorldTile是一個充當網格節點的類。

WorldBoard是WorldTiles數組。

private static void Swap<T>(ref T lhs, ref T rhs) 
{ 
    T temp; 
    temp = lhs; 
    lhs = rhs; 
    rhs = temp; 
} 

public static IEnumerable<WorldTile> GetWorldTilesOnLine(int x0, int y0, int x1, int y1) 
{ 


    bool steep = Mathf.Abs(y1 - y0) > Mathf.Abs(x1 - x0); 

    if (steep) 
    { 
     Swap<int>(ref x0, ref y0); // find out how this works 
     Swap<int>(ref x1, ref y1); 
    } 

    if (x0 > x1) 
    { 
     Swap<int>(ref x0, ref x1); 
     Swap<int>(ref y0, ref y1); 
    } 


    int dx = (x1 - x0); 
    int dy = Mathf.Abs(y1 - y0); 
    int error = (dx/2); 
    int ystep = (y0 < y1 ? 1 : -1); 
    int y = y0; 

    for (int x = x0; x <= x1; x++) 
    { 
     yield return worldBoard[(steep ? y : x), (steep ? x : y)]; 
     error = error - dy; 
     if (error < 0) 
     { 
      y += ystep; 
      error += dx; 
     } 
    } 
    yield break; 
} 

這是在我試圖得到它的工作(它陷在while循環偶爾,挺難針點爲什麼)

public static IEnumerable<WorldTile> GetWorldTilesOnLine(int x0, int y0, int x1, int y1) 
{ 
    int dy = (int)(y1-y0); 
    int dx = (int)(x1-x0); 
    int xstep = 1; 
    int ystep = 1; 

    if (dy < 0) {dy = -dy; xstep = -1;} 
    else {ystep = 1;} 
    if (dx < 0) {dx = -dx; ystep = -1;} 
    else {xstep = 1;} 
    dy <<= 1; 
    dx <<= 1; 

    float fraction = 0; 
    //Debug.Log (xstep); 

    if (x0 >= 0 && x0 < worldBoard.GetLength(0) && y0 >= 0 && y0 < worldBoard.GetLength(1)) 
    { 
     yield return worldBoard[x0, y0]; 
    } 

    if (dx > dy) { 
     fraction = dy - (dx >> 1); 

     while (Mathf.Abs(x0 - x1) > 1) { 

      if (fraction >= 0) { 
       y0 += ystep; 
       fraction -= dx; 
      } 
      x0 += xstep; 
      fraction += dy; 
      if (x0 >= 0 && x0 < worldBoard.GetLength(0) && y0 >= 0 && y0 < worldBoard.GetLength(1)) 
      { 
       yield return worldBoard[x0, y0]; 
      } 
     } 
    } 
    else { 
     fraction = dx - (dy >> 1); 

     while (Mathf.Abs(y0 - y1) > 1) { 
      if (fraction >= 0) { 
       x0 += xstep; 
       fraction -= dy; 
      } 
      y0 += ystep; 
      fraction += dx; 
      if (x0 >= 0 && x0 < worldBoard.GetLength(0) && y0 >= 0 && y0 < worldBoard.GetLength(1)) 
      { 
       yield return worldBoard[x0, y0]; 
      } 
     } 
    } 
    yield break; 
} 

感謝

吉姆

版本
+0

修改此算法以在x0大於x1時從右向左繪製看起來非常直觀,但是當您有可用於調試的上下文時,更容易做到這一點。你嘗試過了,失敗了嗎? –

+0

我會將我的失敗嘗試添加到問題 – Jim

+0

您必須在從'right'到'left'時使'for'循環中的邏輯更改爲不使用'x ++',並且在行中更改'ystep'上的符號是_steep_。 –

回答

2

在朋友的大力幫助下,這裏是最終的解決方案。

WorldBoard是WorldTiles數組。

WorldTiles本質上是網格上的節點。

private static void Swap<T>(ref T lhs, ref T rhs) 
{ 
    T temp; 
    temp = lhs; 
    lhs = rhs; 
    rhs = temp; 
} 

public static IEnumerable<WorldTile> GetWorldTilesOnLine(int x0, int y0, int x1, int y1) 
{ 
    bool steep = Mathf.Abs(y1 - y0) > Mathf.Abs(x1 - x0); 

    if (steep) 
    { 
     Swap<int>(ref x0, ref y0); 
     Swap<int>(ref x1, ref y1); 
    } 

    int dx = Mathf.Abs(x1 - x0); 
    int dy = Mathf.Abs(y1 - y0); 
    int error = (dx/2); 
    int ystep = (y0 < y1 ? 1 : -1); 
    int xstep = (x0 < x1 ? 1 : -1); 
    int y = y0; 

    for (int x = x0; x != (x1 + xstep); x += xstep) 
    { 
     yield return worldBoard[(steep ? y : x), (steep ? x : y)]; 
     error = error - dy; 
     if (error < 0) 
     { 
      y += ystep; 
      error += dx; 
     } 
    } 
    yield break; 
}