如何使用Bresenham创建任意厚度的线?

hor*_*guy 24 algorithm graphics

我目前正在使用Bresenham的算法绘制线条,但它们(当然)厚度为一个像素.我的问题是绘制任意厚度线条的最有效方法是什么?

我使用的语言是C.

Arm*_* J. 21

采取另一个Bresenham循环并使用它来修改矩形方向上原始线的起始和结束位置.问题是有效地找到正确的起点,而不是在绘制下一行时绘制任何像素两次(或跳过一个像素).

可以从Github C代码获得工作和测试的C代码.

这是一个测试页面,包括由此代码创建的一些示例行.黑色像素是算法的起点.

测试页面有不同厚度的bresenham线

  • 如果可以的话,我会更多地回答这个问题,因为它是唯一一个指导读者在C语言中实现干净,有效的实现 - 正如OP所要求的那样. (2认同)

Ski*_*izz 10

我认为最好的方法是绘制一个矩形而不是一条线,因为宽度为一条线的线是一个二维对象.要绘制一组平行线以避免过度绘制(以减少写入带宽)和欠拉(丢失像素)将非常复杂.从起点和终点以及宽度计算矩形的角点并不太难.

因此,在下面的评论之后,执行此操作的过程将是: -

  1. 创建一个长度与所需的线宽相同的矩形,宽度等于所需的宽度,所以(0,0)到(宽度,长度)
  2. 使用2D变换将矩形角坐标旋转并转换为所需位置
  3. 使用硬件加速渲染器(例如OpenGL quad)或使用软件栅格化器对旋转的矩形进行栅格化.它可以使用四边形栅格化器或一对三角形(例如,左上角和右下角)进行渲染.

注意*:如果您正在使用OpenGL,您也可以同时执行步骤2.当然,使用OpenGL确实意味着理解OpenGL(大而复杂),并且这个应用程序可能会在开发的这个后期阶段实现这个棘手的事情.

  • 我没有得到你的解决方案.你能详细说明吗? (2认同)

Mar*_*n B 9

这是一篇论文和Delphi实现的Bresenham算法的修改版本,用于绘制加粗线条.

您可能还想看看Anti-Grain Geometry,这是一个用于2D图形的高质量和高性能软件渲染的库.看看演示页面,了解它可以做什么.


Fab*_*bel 7

为了获得最佳精度,尤其是较粗线条的良好性能,您可以将线条绘制为多边形.一些伪代码:

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)
Run Code Online (Sandbox Code Playgroud)

并且可选地,可以在每个端点处绘制圆圈.


Shu*_*oUk 5

一些简单的使用路线:

  1. 对于任何宽度 n,其中 n 是奇数。对于绘制的任何点 p 还绘制其上方/下方的点为 n/2(如果线条 > 45 度角绘制为边到边代替)。
    • 不是真正适当粗细的适当线条,更像是斜体笔,但速度非常快。
  2. 对于起点 p(x,y),选取点 t0 和 b,使它们以 p 为中心,但相距 n 个像素。为终点做同样的事情导致 t1 b1。从 t0 -> t1, t1->b1, b1 -> t0, b0 -> t1 画线。填充生成的矩形。
    • 这里的技巧是选择点,使它们看起来与路径方向正交。
  3. 为线上的每个点 p 而不是画一个点画一个圆。
    • 无论方向如何,这都具有使端点“干净”的优点。
    • 除了第一个之外,不需要将任何圆圈渲染为实心。
    • 有点慢


x s*_*red 5

创建几乎任意粗细的线的最简单方法是首先进行 bresenham,然后根据需要应用任意数量的膨胀迭代。每个扩张均等地填充线的两侧。

编辑:还值得注意的是,这种方法具有易于推广到 3D 的良好特性,因为 Bresenham 和扩张都很容易推广到 3D。

布雷森汉姆?厚度1:

在此处输入图片说明

扩张掩码:

0 1 0
1 1 1
0 1 0
Run Code Online (Sandbox Code Playgroud)

Bresenham + 1 扩张?厚度 2

在此处输入图片说明

Bresenham + 2 次扩张?厚度 3

在此处输入图片说明

等等。