Bresenham's line algorithm

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


Willing to draw lines on the frame-buffer (/dev/fb0) of a Raspberry Pi, I ended up reformulating the Bresenham's line algorithm in a functional way. Let's say the frame-buffer is 16 columns by 9 rows fb0=Array[{#1, #2} &, {9, 16}]. Given two input points {p1,p2} belonging to the grid fb0, the bresenhamn function finds the points of fb0 that are the nearest to the intersections between the Line[{p1,p2}] and all the the grid-lines.

fb0 = Array[{#1,#2}&,{9,16}];

gridLines = Line@{First@#,Last@#}&/@Join[#,Transpose@#]&@fb0;

bresenham = Function[{p1,p2},(RegionIntersection[#,Line@{p1,p2}]&/@gridLines)~DeleteCases~EmptyRegion[_]~Level~{3}//DeleteDuplicates//First/@Nearest[Join@@fb0]@#&]

In this example p1={2,3}; p2={8,15};

SparseArray@Append[#->1&/@bresenham[{2,3},{8,15}],Last@Last@fb0->0]//MatrixPlot[#,Mesh->All]&

enter image description here