Search code examples
algorithmgraphicsgraphics2d

Linear interpolation along a "Bresenham line"


I'm using linear interpolation for animating an object between two 2d coordinates on the screen. This is pretty close to what I want, but because of rounding, I get a jagged motion. In ASCII art:

ooo
  ooo
    ooo
      oo

Notice how it walks in a Manhattan grid, instead of taking 45 degree turns. What I'd like is linear interpolation along the line which Bresenham's algorithm would have created:

oo
  oo
    oo
      oo

For each x there is only one corresponding y. (And swap x/y for a line that is steep)

So why don't I just use Bresenham's algorithm? I certainly could, but that algorithm is iterative, and I'd like to know just one coordinate along the line.

I am going to try solving this by linearly interpolating the x coordinate, round it to the pixel grid, and then finding the corresponding y. (Again, swap x/y for steep lines). No matter how that solution pans out, though, I'd be interested in other suggestion and maybe previous experience.


Solution

  • Bresenham's algorithm for lines was introduced to draw a complete line a bit faster than usual approaches. It has two major advantages:

    • It works on integer variables
    • It works iteratively, which is fast, when drawing the complete line

    The first advantage is not a great deal, if you calculate only some coordinates. The second advantage turns out as a disadvantage when calculating only some coordinates. So after all, there is no need to use Bresenham's algorithm.

    Instead, you can use a different algorithm, which results in the same line. For example the DDA (digital differential analyzer). This is basically, the same approach you mentioned.

    First step: Calculate the slope.

    m = (y_end - y_start) / (x_end - x_start)
    

    Second step: Calculate the iteration step, which is simply:

    i = x - x_start
    

    Third step: Calculate the coresponding y-value:

    y = y_start + i * m
      = y_start + (x - x_start) * (y_end - y_start) / (x_end - x_start)