how do I create a line of arbitrary thickness using Bresenham?

后端 未结 12 689
不知归路
不知归路 2020-12-01 03:31

I am currently using Bresenham\'s algorithm to draw lines but they are (of course) one pixel in thickness. My question is what is the most efficient way to draw lines of arb

相关标签:
12条回答
  • 2020-12-01 04:31

    I think the best way is to draw a rectangle rather than a line since a line with width is a two dimensional object. Tring to draw a set of parallel lines to avoid overdraw (to reduce write bandwidth) and underdraw (missing pixels) would be quite complex. It's not too hard to calculate the corner points of the rectangle from the start and end point and the width.

    So, following a comment below, the process to do this would be:-

    1. Create a rectangle the same length as the required line and width equal to the desired width, so (0,0) to (width,length)
    2. Rotate and translate the rectangles corner coordinates to the desired position using a 2D transformation
    3. Rasterise the rotated rectangle, either using a hardware accelerated renderer (an OpenGL quad for example*) or use a software rasteriser. It can be rendered using a quad rasteriser or as a pair of triangles (top left and bottom right for example).

    Note *: If you're using OpenGL you can also do Step 2 at the same time. Of course, using OpenGL does mean understanding OpenGL (big and complex) and this application may make that a tricky thing to implement at such a late stage in development.

    0 讨论(0)
  • 2020-12-01 04:31

    For my embedded thermal printer application, using Bresenham's algorithm, the line was way too thin. I don't have GL or anything fancy. I ended up simply decrementing the Y value and drawing more lines under the first one. Each number of thickness added another line. Very quick to implement and made for the desired results printing from monochrome bitmap to the thermal.

    0 讨论(0)
  • 2020-12-01 04:32

    Some simple routes to use:

    1. for any width n where n is odd. for any point p plotted also plot the points above/below it for n/2 (if the line is > 45 degree angle draw side to side instead).
      • not really a proper line of the right thickness, more like an italic pen, but very fast.
    2. for start point p(x,y) pick the points t0 and b such that they are centred on p but n pixels apart. for the end point do the same resulting in t1 b1. Draw lines from t0 -> t1, t1->b1, b1 -> t0, b0 -> t1. Fill in the resulting rectangle.
      • The trick here is picking the points such that they appear orthogonal to the path direction.
    3. for each point p on the line instead of drawing a point draw a circle.
      • This has the advantage of making the end points 'clean' no matter what the orientation.
      • there should be no need to render any circles in solid except for the first.
      • somewhat slow
    0 讨论(0)
  • 2020-12-01 04:33

    I was facing the same problem some time ago. Based on this paper, I created a Matlab reference implementation, which I would like to share on GitHub.

    0 讨论(0)
  • 2020-12-01 04:38

    For best accuracy, and also good performance for thicker lines especially, you can draw the line as a polygon. Some pseudo code:

    draw_line(x1,y1,x2,y2,thickness)
      Point p[4];
      angle = atan2(y2-y1,x2-x1);
      p[0].x = x1 + thickness*cos(angle+PI/2);
      p[0].y = y1 + thickness*sin(angle+PI/2);
      p[1].x = x1 + thickness*cos(angle-PI/2);
      p[1].y = y1 + thickness*sin(angle-PI/2);
      p[2].x = x2 + thickness*cos(angle-PI/2);
      p[2].y = y2 + thickness*sin(angle-PI/2);
      p[3].x = x2 + thickness*cos(angle+PI/2);
      p[3].y = y2 + thickness*sin(angle+PI/2);
      draw_polygon(p,4)
    

    And optionally a circle could be drawn at each end point.

    0 讨论(0)
  • 2020-12-01 04:38

    The easiest way to create a line of almost arbitrary thickness would be to first do a bresenham, then apply as many dilation iterations as you wish. Each dilation pads both sides of your line equally.

    EDIT: It is also worth noting that this method has the nice feature of being easily generalizable to 3D, because both Bresenham and dilation are easily generalizable to 3D.

    Bresenham → thickness 1:

    Dilation mask:

    0 1 0
    1 1 1
    0 1 0
    

    Bresenham + 1 dilation → thickness 2

    Bresenham + 2 dilations → thickness 3

    etc.

    0 讨论(0)
提交回复
热议问题