(迁移至博客园 原文)
直线的光栅画法
今天看GOLang的书,里面有个程序示例用到了图形学里面的中点圆画法和直线的光栅画法。专业选修课老师讲过这俩种算法,但是睡过去了 T_T 。中点圆画法和直线光栅画法的基本思想是一致的(增量,增量修正,中点判断,判别式去乘法去除法去浮点运算,迭代,圆还使用了对称性),闲着无事推一下简单的直线光栅画法。
场景
屏幕上的每一个图像都是由一个个微小的像素点构成,这些像素点构成了像素阵列,作图就是给这个阵列上的像素点设置颜色的过程。
像素点之间是有间隔的,但是很小,被肉眼忽略。一条直线y=kx+b
是连续的,我们无法在阵列上严格的画出他,只能选取直线轨迹附近的像素点近似地表现出来。
问题
如果通过解直线方程去确定每一个x
对应的y
然后画点,虽然简单准确,但无疑是低效的,首先每一个点都要根据x
去求y
,而且避免不了乘法和浮点运算。
解
设P1(x1,y1),P2(x2,y2)
是直线的俩个端点(x2>x1
),并且我们在斜率0<=k<=1
的情况下讨论(其他情况可以通过平移对称等变换映射过去)。
dx=x2-x1
dy=y2-y1
k=dy/dx
若当前已画点为(x0,y0)
,则下一个点有俩个待选点Pa(x0+1,y0)
和Pb(x0+1,y0+1)
:
if y0+k>y0+0.5
则选择Pb
,否则选择Pa
.其中y0+k
表示按直线方程来计算下一个点y
值的精确值,y0+0.5
表示俩个待选点的中点的y
值。这个判断等价于:
Note:选择中点y值来作判断其实是一个间接的判断,严格的讲应是判断这俩个待选点到直线的垂直距离的大小,但是作图之后你会发现和这种判断方式是等价的,因为构成了俩个相似的直角三角形。
Dj=y0+k-y0-0.5
if Dj>0{
chose Pb
}else{
chose Pa
}
令Dg=2*Dj*dx
,则Dg=2*dy-dx
,那么原判断等价于