投稿    登录
  博主录制的Python3爬虫视频教程已发布!详情请戳Python3爬虫视频教程!希望大家支持!非常感谢!

OpenGL绘图实例二之直线和圆弧的绘制

C/C++ 崔庆才 5053浏览 2评论

综述

在上一篇文章我们介绍了利用类库来完成一个机器人绘制的过程,这里我们一起来看一下怎样直接利用直线和圆弧生成算法来进行图形的绘制。

P.S. 本篇文章针对《计算机图形学》张彩明 版来探讨学习。关于书中的详细算法不会再赘述。

P.P.S. 本篇文章算法扩展思路及代码实现为博主原创内容,如存在纰漏和错误,希望大家指正。

直线生成算法

1.DDA算法

DDA算法是最基本的一种直线生成算法了,代码实现简单,不过缺点是计算量比较大,画一个点要两次加法,两次取整运算。另外,DDA算法还包括了除法运算。不仅算法复杂,而且硬件实现上有一定的难度。优点就是程序简单易懂,在这里实现如下

解释一下这里的gl_Point方法,这个方法并不是直接调用类库的方法,而是我们自己来实现的画点的方法。

用来画点的话,我们必须要在glBegin方法传入GL_POINTS参数,然后利用类库中画点的方法来绘制点。

2.正负法

在教材中只讨论了斜率在0-1之间的情况,代码的实现也是仅仅只有0-1一种情况,对于斜率大于1,斜率在-1和0之间以及斜率小于-1的情况没有加以讨论。

如果我们直接拿来教材中的代码来用,我们会发现只能绘制出0-1斜率的直线,对于其他的情况,均绘制错误。

所以我们需要分四种情况来讨论,直线方程 F(x,y)=ax+by+c=0,其中 a=ys-ye,b=xe-xs

设直线的斜率为k,讨论分类如下

(1)k∈[0,1)

此时有 a<0,b>0

d=F(M)=F(x+1,y+0.5)=a(x+1)+b(y+0.5)+c

当d>=0时,Q在M点下方,取右下方的点,d1=F(x+2,y+0.5)=a(x+2)+b(y+0.5)+c=d+a

当d<0时,Q在M点上方,取右上方的点,d2=F(x+2,y+1.5)=a(x+2)+b(y+1.5)+c=d+a+b

此时d的初始值 d0=F(xs+1,ys+0.5)=a+0.5b

(2)k∈[1,+∞]

此时有 a<0,b>0

d=F(M)=F(x+0.5,y+1)=a(x+0.5)+b(y+1)+c

当d>=0时,Q在M点右侧,取右上方的点,d1=F(x+1.5,y+2)=a(x+1.5)+b(y+2)+c=a+b+d

当d<0时,Q在M点左侧,取左上方的点,d2=F(x+0.5,y+2)=b+d

此时d的初始值 d0=F(xs+0.5,ys+1)=0.5a+b

(3)k∈[-1,0)

此时有 a>0,b>0

d=F(M)=F(x+1,y-0.5)=a(x+1)+b(y-0.5)+c

当d>=0时,Q在M点下方,取右下方的点,d1=F(x+2,y-1.5)=a(x+2)+b(y-1.5)+c=a-b+d

当d<0时,Q在M点上方,取右上方的点,d2=F(x+2,y-0.5)=a(x+2)+b(y-0.5)+c=a+d

此时d的初始值 d0=F(xs+1,ys-0.5)=a-0.5b

(4)k∈[-∞,-1)

此时有 a>0,b>0

d=F(M)=F(x+0.5,y-1)=a(x+0.5)+b(y-1)+c

当d>=0时,Q在M点左方,取左下方的点,d1=F(x+0.5,y-2)=a(x+0.5)+b(y-2)+c=d-b

当d<0时,Q在M点右方,取右下方的点,d2=F(x+1.5,y-2)=a(x+1.5)+b(y-2)+c=a-b+d

此时d的初始值 d0=F(xs+0.5,ys-1)=0.5a-b

注意:上面的a和b的符号,是在默认起点在终点的左侧来看待的

所以,如果我们传入参数时,第二个点在第一个点的左侧时,我们可能就不会得到正确的结果。所以当我们发现第二个点不在第一个点右侧时,就需要把二者的横纵坐标交换。

代码实现如下,此实现仅供参考,未经优化。

在一开始我们用到了swap方法,是用来交换两个数字的,实现如下

以上便是正负法的实现,代码仅供参考。

3.Bresenham算法

在教材中,同样是只针对斜率在0-1之间讨论。对于教材中的程序,我们也只能绘制斜率为0-1的直线,所以我们需要对另外三种情况进行扩充。

分类讨论如下

(1)k∈[0,1)

即教材中的讲解方法

(2)k∈[1,+∞]

需要把x和y互换即可

(3)k∈[-1,0)

x不变,y换为-y

(4)k∈[-∞,-1)

x换为-y,y换为x

程序实现如下

以上便是Bresenham算法,经测试通过。

圆弧生成算法

 1.正负法

教材中只讨论了圆弧在第一象限的情况,不过有趣的是,圆是具有对称性的,在绘制圆形时,我们如果把x换为-x,就可以绘制第二象限的图形,把y换为-y,就可以绘制第四象限的图形,代码也不需要改动很多。只需要在gl_Point上面下功夫即可。

另外,教材中圆弧生成算法中没有指定圆的中心点的坐标,我们可以把它当做参数来传递进来,然后传入gl_Point绘图函数即可,相当方便。

注:此方法不需要再繁琐地分类讨论。

在这里给出博主写出的两种方法,一种是如上所介绍的思路,利用对称性,另一种是分类讨论的思想。

(1)利用对称性实现

 (2)分类讨论思想

在上面的代码中,我们传入了centerX和centerY以及area参数。其中centerX和centerY是圆弧中心点的坐标,area是所在的象限,传入的参数需要是1,2,3,4中的一个数字,如果传入其他数字则不会绘制出任何图形。

注:此方法只能一次性绘制一个四分之一圆弧,局限性比较大,如果要融入弧度,改动量比较大。

2.Bresenham算法

和上面方法类似,我们的实现同样非常简单,即使教材中只讨论了八分之一圆,我们可以利用对称的思想来实现画圆。另外我们添加了圆弧中心点坐标已经所在的区块。

从(π/4,π/2)这个区块开始,编号为1,角度为45°,顺时针旋转(0,π/4)的编号为2,以此类推,参数变量为area

代码实现如下

此段代码亲测可用,仅供参考。

终极目标

上一节我们实现了用类库的方法和sin,cos方法来定位坐标绘制机器人,在这一节我们就利用上述的直线和圆弧生成算法,对上一篇中的机器人进行绘制。

在这里只贴出最核心的部分,那就是绘画的函数了,只是简单地传入坐标点然后调用刚才实现的一些方法,比较繁琐,但是比较简单,核心代码如下

其他的部分不再赘述,都十分基础。

运行结果

直接贴图如下

QQ截图20150413005949

嘿嘿,我们直接用生成算法绘制的图形是不是更好看一些呢?

总结

本节介绍了各种直线生成算法和圆弧生成算法,以及利用该算法重新绘制机器人,希望对大家有帮助!

转载请注明:静觅 » OpenGL绘图实例二之直线和圆弧的绘制

喜欢 (11)or分享 (0)

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请狠狠点击下面的

想结交更多的朋友吗?

来进击的Coder瞧瞧吧

进击的Coder

QQ群号 99350970 立即加入

进击的Coder灌水太多?

这里是纯粹的技术领地

激进的Coder

QQ群号 627725766 立即加入

想找人聊天解闷?想要学习干货?

微信公众号进击的Coder为你打造

进击的Coder

微信公众号 扫一扫关注