[计算机图形学经典算法] 直线段和圆弧在屏幕上的绘制 (附matlab代码)

刚学习了计算机图形学这门课程,为奠定根基的算法所倾倒,特此记录一二。

直线—中点 Bresenham 算法

DDA算法在效率上较低的原因是需要计算 k,并以之作为累加项。一个直观的改进方式,是在整个运算过程中将涉及到的数值乘以 dx (或dy),转化为整型进行运算。

中点 Bresenham 算法采用一种不同的观点来解决这一问题-判别式。我们先考虑一般的直线方程,在图形学中我们一般给出的已知条件是两个端点:
这里写图片描述

此判别方程的意义,在于直线上的所有点均使 F(x,y)=0。

现在,我们考虑离散的情形,在|k| < 1时,为判断如下图所示的与P相邻的像素点Pd和Pu中的哪一个归属于直线,我们取两者的中点M作为判决依据。将其坐标代入判别式
(1) F(M) < 0, 取上方点 Pu
(2) F(M) > 0, 取下方点 Pd

这里写图片描述

因此,若(Xi, Yi)为直线上的点,在判定下一个点(Xi+1,Yi+1)并在(Xi+1,Yi+1)和(Xi+1,Yi)中进行选择时,可以根据中点坐标(Xi+1,Yi+0.5)代入判别式进行判定。
F(Xi,Yi) = a Yi + b Xi + c = 0
F(Xi+1,Yi+0.5) = a Yi + 0.5a + b Xi + b +c
= 0.5a + b
(1) F(M) = 0.5a + b < 0, 取上方点 Pu (Xi+1,Yi+1)
(2) F(M) = 0.5a + b > 0, 取下方点 Pd (Xi+1,Yi)

两个问题:

(1) F(Xi,Yi)=0 不一定总能满足,如何解决?
(2) 尽管 a, b, c 均为整数(?),仍有一个0.5为小数。
问题(2)容易解决,仅需在计算过程中乘2即可;
问题(1)则较为麻烦。我们知道在起始点时,F(Xi,Yi)=0 总是成立的,在后续计算中我们将偏差 F(Xi,Yi)=di 累计表达为 F(Xi,Yi)-di=0,再累积起来通过一个变量来考虑的。然而,因为前面的推导基于 +1(x方向) 和 +0.5(y方向),所以对该变量要进行调整。具体通过递推完成。

递推式

因为不能保证各像素点处的F(Xi,Yi)=0,因此只能从起始点处考虑 F(X0,Y0)=0,然后依次考虑F(X0+1,Y0+0.5), F(X0+2,Y0+?),… 此处我们可以看出,必须要分两种情况。
当 F(X0+1,Y0+0.5) < 0,选择(Xi+1,Yi+1)时,再判断的下一个中点应为(Xi+2,Yi+1.5);
当 F(X0+1,Y0+0.5) > 0,选择(Xi+1,Yi)时,再判断的下一个中点应为(Xi+2,Yi+0.5);
注意每一步只有两种可能,所以这个模式是重复出现的,换句话说可用迭代的方式实现两个中点间的递推关系。

累积误差项的递推(di+1 < 0)
这里写图片描述
累积误差项的递推关系,反映了相邻中点间的递推关系。

补充细节:

这里写图片描述

算法整体描述:

  • 计算初始值△x、△y、d=△x-2△y、x=x0、y=y0。
  • 绘制点(x,y)。判断d的符号。若d<0,则(x,y)更新为(x+1,y+1),d更新为d+2△x-2△y;否则(x,y)更新为(x+1,y), d更新为d-2△y。
    (这种递推关系类似数学归纳法,相邻中点间构建关系)
  • 当直线没有画完时,重复上一步骤,否则结束。

例题:

这里写图片描述

matlab代码

% P,Q为直线段端点,pixs_line为计算出的像素点
function pixs_line = bresenham_line(P,Q)

% 判断斜率 k 是否绝对值小于1
% 如果斜率大于1, X,Y坐标互换
if abs(Q(2
  • 0
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值