Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

Bresenham's line algorithm is producing discretized line for given two points for purpose of plotting for example.

Like that:

enter image description here

I have to stress that I'm interested in positions, not a plot.

Wikipedia link I've provided includes an algorithm of course. I've just rewritten it thoughtlessly, I don't have time now or special need to work on neat implementation.

But if someone want to improve it (compile e.g.), got it already or know something more, I think this thread may be usefull for future visitors.

Very nice implementation can be found on rossetacode :P, according to that this algorithm should be built in so maybe someone knows how to get it.

Anyway, here's that code:

bresenham[{x1_, y1_}, {x2_, y2_}] := 
 Module[{dx, xi, dy, yi, ai, bi, x, y, d},
     If[x1 < x2, {xi, dx} = {1, x2 - x1};, {xi, dx} = {-1, x1 - x2};];
     If[y1 < y2, {yi, dy} = {1, y2 - y1};, {yi, dy} = {-1, y1 - y2};];
     x = x1; y = y1;
     Sow[{x, y}];
     If[dx > dy,
      (ai = 2 (dy - dx); bi = 2 dy; d = bi - dx;
       While[
        If[d >= 0,
         {x, y, d} += {xi, yi, ai},
         {x, d} += {xi, bi}];
        Sow[{x, y}];
        x != x2])
      ,
      (ai = 2 (dx - dy); bi = 2 dx; d = bi - dy;
       While[
        If[d >= 0,
         {x, y, d} += {xi, yi, ai},
         {y, d} += {yi, bi}];
        Sow[{x, y}];
        y != y2])
      ]] // Reap // Last // First
share|improve this question
    
If your aim is to just draw a line, you can do it in a simpler way with floating point operations. The reason why Bresenham's algorithm is/was important is that it only uses integer operations. Early computers couldn't do floating point operations directly at all. (An Intel 80386 couldn't do floating point operations directly, it required a floating point coprocessor.) Later integer operations were still faster than floating point operations, so it made sense to use this algorithm for good performance. –  Szabolcs Apr 10 at 22:48
    
Of course it's more fun to use the original Bresenham algorithm ;-) –  Szabolcs Apr 10 at 22:52
    
@Szabolcs I hope it's just an intro the the answer you are going to post :) I've used it because I needed it here. I wanted it fast so I just took that :) –  Kuba Apr 10 at 22:53
    
Well, I'm asking about neat/fast implementations or other solutions, it is written, but if it's unclear I can specify. I think it has not sense to cast a close vote without asking... –  Kuba Apr 11 at 8:43
    
@Kuba Can you put that in the form of a question, in the question? You hint at it, but the Q does come right out and ask. (I did not vote to close, btw.) –  Michael E2 Apr 12 at 15:33

1 Answer 1

up vote 3 down vote accepted

Original Bresenham

I guess I can come of with a somewhat shorter implementation without using Reap and Sow. If someone is interested, it follows almost exactly the pseudo-code here

bresenham[p0_, p1_] := Module[{dx, dy, sx, sy, err, newp},
  {dx, dy} = Abs[p1 - p0];
  {sx, sy} = Sign[p1 - p0];
  err = dx - dy;
  newp[{x_, y_}] := 
   With[{e2 = 2 err}, {If[e2 > -dy, err -= dy; x + sx, x], 
     If[e2 < dx, err += dx; y + sy, y]}];
  NestWhileList[newp, p0, # =!= p1 &, 1]
]

To test this I use the setup given by the comment of Kuba under this answer:

p1 = {17, 1}; p2 = {7, 25}; 
Graphics[{EdgeForm[{Thick, RGBColor[203/255, 5/17, 22/255]}], 
  FaceForm[RGBColor[131/255, 148/255, 10/17]], 
  Rectangle /@ (bresenham[p1, p2] - .5), {RGBColor[0, 43/255, 18/85], 
   Thick, Line[{p1, p2}]}}, 
 GridLines -> {Range[150], Range[150]} - .5]

Mathematica graphics

Exercise implementation

What follows was only a fun project I did with my wife. Actually, this is not the original Bresenham algorithm. The task for this weekend-fun was to re-invent the algorithm (the iterative steps and the required correction steps) on the blackboard.

For simplicity this algorithm only makes correction steps in one direction (meaning the points stay always on one half-plane of the line) and therefore, the final points are not as close to the original line as with the real Bresenham algorithm.

Anyway, this is my Mathematica implementation of what my wife had to do in Python:

bresenham[p1 : {x1_, y1_}, p2 : {x2_, y2_}] := 
 Module[{dx, dy, dir, corr, test, side},
  {dx, dy} = p2 - p1;
  dir = If[Abs[dx] > Abs[dy], {Sign[dx], 0}, {0, Sign[dy]}];
  test[{x_, y_}] := dy*x - dx*y + dx*y1 - dy*x1;
  side = Sign[test[p1 + dir]];
  corr = side*{-1, 1}*Reverse[dir];
  NestWhileList[
   Block[{new = # + dir}, If[Sign[test[new]] == side, new += corr];
     new] &, p1, #1 =!= p2 &, 1, 500]]

Here a small dynamic test whether the calculated points do indeed look like a line:

DynamicModule[{p = {{0, 0}, {50, 40}}},
 LocatorPane[Dynamic[p],
  Dynamic@
   Graphics[{Line[bresenham @@ Round[p]], Red, PointSize[Large], 
     Dynamic[Point[p]]}, PlotRange -> {{-200, 200}, {-200, 200}}, 
    ImageSize -> 400, Frame -> True, FrameTicks -> False, 
    GridLines -> True],
  Appearance -> None
  ]
 ]

Mathematica graphics

share|improve this answer
    
@Kuba You are doing nothing wrong. For the Bresenham you need to ensure that you stay on the line and you have to do certain correction steps. It really was only a fun project where we recalculated everything by hand and for simplicity we took correction steps only in one direction. I will point out that this is not the original algorithm. –  halirutan Apr 10 at 22:21
    
Ok, thanks. :-) –  Kuba Apr 10 at 22:30
    
@Kuba OK, for the sake of brevity, I included an implementation of the original algorithm in my answer which satisfies your test-code:-) –  halirutan Apr 10 at 23:19
    
@Kuba For me they are always equal when you switch p1 and p2 in either your or my implementation. Additionally, although the lines are not identical, but they are surely equivalent. –  halirutan Apr 11 at 0:24

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.