-1

I have been trying to create a Bresenhams line algorithm that preserves order so that the user is able to draw on a grid at runtime.

It works 'for the most part, however, it seems to get stuck in a while loop and crashes my program occasionally. I believe this is when the mouse is moving quite fast.

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) { // This seems to be where the crash occurs

            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) { // This seems to be where the crash occurs

            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;
}

This method is called while the user has the mouse button down using this

IEnumerator Draw()
{
    startPos =  WorldGridUtilities.getNearestWorldTileArrayValue(getMousePosition());
    worldTilesToAdd = new List<WorldTile>();
    Debug.Log (worldTilesToAdd.Count);
    while (true)
    {       
        worldTilesToAdd.Clear();
        nextPos = WorldGridUtilities.getNearestWorldTileArrayValue(getMousePosition());

        if (nextPos != startPos)
        {

            foreach (WorldTile wt in WorldGridUtilities.GetWorldTilesOnLine((int)startPos.x,(int)startPos.y, (int)nextPos.x, (int)nextPos.y))
            {
                worldTilesToAdd.Add (wt);

            startPos = nextPos;
        }

        foreach (WorldTile wt in worldTilesToAdd)
        {
            //Debug.Log ("coordinates added to list used by vectorline: " + wt.gridCoordinates);
            vectorLine.points3.Add(wt.gridCoordinates);
            vectorLine.Draw3D();
        }


        yield return new WaitForEndOfFrame();
    }
}
Jim
  • 761
  • 3
  • 10
  • 32

1 Answers1

1

There's something strange in xstep ystep. if dy > 0 and dx < 0 then xstep = 1 and ystep = 1. So x1 < x0 because dx < 0 but you keep increasing x0 with xstep =1. Which means infinite loop. Likely something gets overloaded and sometimes you get an error.

Sorin
  • 11,863
  • 22
  • 26