Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 603
Johannes Hoff Avatar asked Sep 11 '12 11:09

Johannes Hoff


1 Answers

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)
like image 147
Nico Schertler Avatar answered Sep 26 '22 17:09

Nico Schertler