图形学

直线的光栅化算法

导读:计算机图形学介绍了直线生成的三种算法,DDA算法、中点画线法、Bresenham算法的Python语言实现和绘图。编码时被象限问题困扰很久,后来想到参考值可以用abs转化到第一象限,一下解决所有问题。

三种算法的本质都是增量算法。通俗的讲,直线的光栅化就是把矢量图转化成点阵图,要求产生的点阵尽可能真实地渲染出实际直线。

实际上三种算法的思想都差不多,主要考虑的是算法的耗时(主要表现为浮点数,浮点数计算很费事,三种算法在逐渐消除浮点数计算和比较),因为实际应用时,绘制直线操作用的非常多,如果时间消耗太多肯定不行。

DDA算法

DDA算法利用了一条直线的斜率是一个常量这一事实,因此每步增量附加上去,另一个坐标轴上也产生相应增量。得到的点用四舍五入的方法处理,即得到所画直线的点阵表示。

需要注意的是选取的步长为1的增量坐标轴,为了说清,取第一象限,假设斜率 k 大于 1,若此时选择 x 轴作为步进方向,每次步进 1 单位,则 y 轴会步进超过 1 个单位,后果就是画出的 “直线” 根本连不到一起。因此需要分类讨论。

 

中点画线法

思路是把直线与网格的交点、直线跨越的单位网格的中点作差比较,如果直线与网格交点在相应网格中点以上,则选择上面的点绘制,否则选择下面的点绘制。简单的说,就是根据中点,画出离交点最近的像素点。

 

Bresenham算法

此算法的原理是:以第一象限为例,设直线与网格的交点A,离A点最近的上部网格点为Upper,离A点最近的下部网格点为Lower,若 d = Upper-Lower > 0,说明A离下面的像素点近,选择下面的点绘制,否则选择上面的像素点绘制。

为了彻底消灭浮点数计算,下面的代码用到了几次优化过程。

第一次,设变量 d 表示A距离下端最近网格线的垂直距离,d 每次增加 k(设 x 增量1,y 增量就是 k),若 d 大于 0.5 则说明 y 方向要产生增量(因为在中点上方,这里用到了中点画线法的思想),y += 1 且 d -= 1。但出现了与 0.5 的比较,这不是我们想要的。

第二次,用 e 代替 d - 0.5。这样一来 0.5 就变成了 0,消除了浮点数 0.5,但仍存在浮点数 k。

第三次,用 e = 2Δx 代替原来的 e。因为 k = Δy / Δx,这样做直接消除了式中的Δx,浮点数 k 因此被消除了。

最终得到的相关表达式: