递归的应用 -- 最简单分形图形实现

2016-01-29 12:15 370 1 收藏

递归的应用 -- 最简单分形图形实现,递归的应用 -- 最简单分形图形实现

【 tulaoshi.com - C语言心得技巧 】

递归的应用 -- 最简单分形图形实现


作者:吉林大学 胡卓玮

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com)  

下载本文源代码


图一 例子代码运行结果

    大家在C/C++学习时都会遇到递归,课本上以汗诺塔为例进行讲解,然后大家都希望自己找到一个递归的实例。本文以一个最简单的分形图形来讲解递归的实现过程。
    先来看看绘制这个分形图形的思路。如图二所示,给定两点(p1和p2)确定一条直线,计算这条直线的长度,如果长度小于预先设定的极限值则将这两个点用直线相连,否则,取其1/3处点(点1)、2/3处点(点2),以及中点上方一个点(点3),这个点与第1点、第2点构成的直线与直线p1p2的夹角为60度。判断这五个点按照顺序形成的四条直线的长度是否小于预先设定的极限值,如果小于,则在将相应的两个点相连在屏幕上显示一条直线,否则继续对相应两点形成的直线进行以上判断。


图二 分形图形实现示意图

    这是一个典型的递归问题。我们可以看看如果不使用递归该怎样得到我们需要的结果。首先需要设立一些变量来存储点的坐标,由于不使用递归,我们需要在整个过程的最后,把计算所得并保存起来的点的坐标传递给画线的函数,在不满足递归过程结束的条件下(即直线的长度大于极限值),将需要增加三个点,这时是四条直线,如果下一次仍然达不到结束条件,将会得到的点数为2 + 3 + 4 * 3,直线数为4^2。这样,对于第n次不满足结束条件后获得的点数为:2 + 3 + 3 * 4 + 3 * 4 ^ 2 + …… + 3 * 4 ^ (n - 1),直线数为4 ^ n条。随着n的增大,这不是一个小数目。但如果使用递归实现,情况会大不一样,不需要定义过多的变量,不需要考虑复杂的点的顺序关系。
    来看看我们的程序当中是如何利用递归实现这个简单的分形图形的。整个实现过程封装到类KSQXClass中,为了方便点坐标的存取,定义了KSQXPoint类,参看文件KSQXClass.h和KSQXClass.cpp,大家可以看到类的具体定义和实现。
    整个递归过程用函数Draw来实现。参数含义如下:
CDC* pdc; //设备描述表,绘制分形图形的设备
KSQXPoint p1, KSQXPoint p2; //直线的起点和终点,KSQXPoint以点的x,y坐标作为成员变量
    一开始需要计算直线的长度并判断其长度是否小于极限值:

      ds = (float)sqrt(dx * dx + dy * dy);      if(ds <= m_limit)      {       pdc-MoveTo((int)p1.m_x, (int)p1.m_y);       pdc-LineTo((int)p2.m_x, (int)p2.m_y);       return;      }
其中的极限值m_limit通过成员函数SetLimit设定。

如果ds大于极限值,进行以下工作。
计算点1、点2和点3的坐标。关于点的坐标的计算,这里不进行过多的讲解,读者对照程序代码去理解吧。
    这三个点的坐标得到以后,就可以组成四条直线:p1和1,1和3,3和2,2和p2,分别以这四条直线的起点、终点坐标为参数代入函数Draw中,进行递归调用。
      Draw(pdc, p1, tempp1);      Draw(pdc, tempp1, tempp3);      Draw(pdc, tempp3, tempp2);      Draw(pdc, tempp2, p2);        
一切准备好以后,就可以到程序的主体里去获取我们想要得到的结果了。
      KSQXClass myksqx;      KSQXPoint p1, p2;      p1.m_x = 100;      p1.m_y = 300;      p2.m_x = 400;      p2.m_y = 300;      myksqx.SetLimit(1);      CDC* pdc;       pdc = GetDC();      myksqx.Draw(pdc, p1, p2);      
程序运行结果如本文图一所示。
关于代码和文章中的问题大家可以和作者联系:
通信地址:吉林省长春市西民主大街6号地球探测科学与技术学院2001级硕士研究生 胡卓玮
电子信箱:QiGi@vip.sina.com
欢迎访问作者的主页:forevergis.6to23.com

来源:http://www.tulaoshi.com/n/20160129/1485288.html

延伸阅读
标签: Web开发
如果你有用javascript写过拖动的话,应该知道是有多么麻烦的,不过yui3为大家提供了一个非常方便的方法实现拖动,今天我们先来看看使用yui3实现最简单拖动,首先贴出代码(如果你感兴趣,可以点击这里查看效果):上面我有相应的解释,这些解释都是我的个人理解,可能不完全对,但是这样就可以实现拖动了,如果你有正确的解释,请与我联系,...
标签: Web开发
Asp.Net 2.0 中实现了IButtonControl接口的控件都有一个PostBackUrl属性,可以进行跨页面提交,就是用的POST方法。那么在1.x中费了一番周折的POST提交就很简单了,只要把PostBackUrl设置为提交页,在那提交页用Request.Params[]就能拿到POST的表单参数了。还能用PreviousPage.FindControl去取前一页的控件。这里用Request和PreviousPage去...
标签: Web开发
或多或少都做过树状目录、产品分类之类的二级或三级菜单,如果遇到更多级的分类,就一般使用递归了。在程序中使用递归或多或少会增加一些性能上的开销。 之前我用ASP.net在程序中实现过非递归的无限级分类目录,但考虑到移植性不强,就改成了存储过程,发出来大家共同研究一下,到目前为止,测试过程中还没发现问题,另外,代码方面没...
标签: 折纸
一:首先需要准备一张方形的纸,宽和长的比列就是2:1,从中间进行对折,然后复原,留下折痕。   二:然后像上面一样上下对折,然后还原,只留下折痕。   三:将左右两边的两个正方形如图一样再折出痕迹,然后还原。   四:将...
PPT快速绘制出桨形的风车图形? 直接上图,这个图有多少人可以用PPT制作做出来? 1、新建一个PPT,点击插入形状椭圆。按住Shift拖拽一个正圆形。然后按住Ctrl+shift键水平拖拽复制出另外一个圆。(如下图) 2、继续选中其中一个圆,在垂直方向上进行复制。一样可以利用按住Ctrl键拖拽鼠标的方法。注意四个圆交叉的十字中心位...

经验教程

709

收藏

17
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部