图形算法:直线算法
标签(空格分隔): 算法
版本:3
作者:陈小默
声明:禁止商用,禁止转载
场景中的直线由其两端点的坐标位置来定义。要在光栅监视器中显示一条线段,图形系统必须先将两端点投影到整数屏幕坐标,并确定离两端点间的直线路径最近的像素位置。接下来才是将颜色填充到相应的像素坐标。1
前言
文章最后的演示代码使用的是C++语言,函数库使用的是以GLUT为基础的自定义封装库。本章内容将介绍生成直线的直线方程算法
、DDA算法
以及重要的Bresenham算法
。
一、算法导论
以下仅仅展示算法的计算过程,具体实施请参考示例程序部分。
1.1直线方程算法
对于绘制直线来说,使用直线方程无疑是一种最直接的算法。在二维笛卡尔坐标系中,直线方程为:
其中m代表直线的斜率,b为直线的截距,对于任意两个端点 (x0,y0) 和 (x1,y1) :
由于屏幕上的点在其坐标系中以整数表示,当斜率 1>|m| 时,我们可以以 x 轴增量
同样,对于斜率 |m|>1 的线段,我们需要通过以 y 轴增量
通过使用直线方程绘制的点,其优点是算法简单且精确,但是其在绘制每一个点的过程中都需要计算一次乘法和加法,显而易见,由于乘法的存在,导致运算时间大幅度增加。接下来介绍的DDA算法将弥补直线方程的乘法缺陷。
1.2 DDA算法
从上可知,在绘制大量点的过程中,我们要尽可能的减少每一个点的计算时间。在计算机中加法运算是最简单的运算之一了。我们可以利用直线的微分特性将每一步的乘法运算替换为加法运算。数字微分分析法(Digital Differential Analyzer,DDA)是一种线段扫描转换算法,基于式 (1.4) 或 (1.5) 来计算 δx 或 δy 。
对于斜率 |m|≤1 的线段来说,我们仍以单位 x
于是,我们便将乘法运算合理的转换为了加法运算。但是需要注意的是,在屏幕设备中的坐标均是整数,所以我们在绘制时的y需要取整。
对于具有大于1的正斜率线段,则需要交换 x 和
此时,每一个计算出的 x 要沿着
该算法只需要计算出一个 step 值( m 或者
1.3 Bresenham算法
接下来我们介绍由布莱森汉姆(Bresenham)提出的精确且高效的光栅线生成算法,该算法仅仅使用整数增量计算,除此之外,该算法还能应用于圆或者其他曲线。
我们将分别介绍四种斜率( m>1 、 0<m<1 、 −1<m<0 和 m<−1 )的计算过程(以下示例均为从左至右画线)。
1.3.1 斜率大于1
首先,在斜率大于1的情况下,沿路径像素以单位 y 间隔取样。假设线段以
在取样位置 yk+1 我们使用 dleft 和 dright 来标识两个像素位置( xk 与 xk+1 )与数学位置的水平偏移量。根据式 (1.1) 可得在像素列 yk+1 处的 x 坐标计算值为
所以
且
为了确定两个像素中哪一个更接近真实路径,需要计算两个像素偏移的差值。
设线段终点位置为 (x1,y1) ,可得
设决策参数 pk=Δy(dleft−dright)
其中
在第 k+1 步,决策参数可以由式 (1.13) 计算得出
将上述等式减去式 (1.13) 可得决策值的增量 δpk+1