研究混沌运动,少不了对分形理论的探讨。分形:通常被定义为“一个粗糙或零碎的几何形状,可以分成数个部分,且每一部分都(至少近似地)是整体缩小后的形状”,即具有自相似的性质。

本篇将从一维过度到三维介绍分形图案的产生,一维类比康托尔集直线三等分的生成,此处比较简单我们不过多讨论,我们重点分析如何通过使用Java语言,实现Sierpinski和Menger sponge分形图案的过程(多图)。

谢尔宾斯基(Sierpinski)三角形

谢尔宾斯基三角形和它本身的一部分完全相似,它是自相似集的经典例子。

构造特点

  1. 取一个三角形边框(常用等边三角形)
  2. 沿三边中点的连线,将它分成四个小三角形
  3. 去掉中间的那一个小三角形
  4. 对其余三个小三角形都重复1~3的操作

代码实现

UI界面鼠标监听器获取鼠标点击处的坐标,再由此坐标和等腰三角的边长关系,得到三角形其余两点坐标:

int x = (int)e.getX();
int y = (int)e.getY();
int length = 120;//设定三角形边长为2*length
int x2 = x+length;//以下为坐标变换
int x3 = x-length;
int y2 = (int)(y-length*Math.sqrt(3));
int y3 = (int)(y-length*Math.sqrt(3));
int count =6;//迭代次数初始值

方法一:

此方法是绘制Sierpinski三角形的典型思路,与构造特点思路对应。

public void triangle_1(int x1,int y1,int x2,int y2,int x3,int y3,int count){//将三角形三顶点坐标存入数组中int m[]={x1,x2,x3};int n[]={y1,y2,y3};//绘制三角形边框g.drawPolygon(m, n, 3);//迭代次数减1,再判断count--;if(count>0){//计算三边中点坐标int x4=(x1+x2)/2;int x5=(x1+x3)/2;int x6=(x2+x3)/2;int y4=(y1+y2)/2;int y5=(y1+y3)/2;int y6=(y2+y3)/2;//迭代到不包括最中间的其余三个小三角形中triangle_1(x1,y1,x4,y4,x5,y5,count);triangle_1(x2,y2,x4,y4,x6,y6,count);triangle_1(x3,y3,x5,y5,x6,y6,count);}}

绘制结果(1)


此结果是迭代6次的效果,三顶点变换方向不同,效果会有区别,但大同小异。

方法二:

与方法一的思路略有不同,我们不排除中间的三角形,而是以它为主,先绘制最中间的实心三角形,再对三边的三个不同方向作迭代,变化过程中只改变三角形边长大小为之前的1/2,并朝此方向作平移,重复上述过程。

public void triangle_2(int length,int x1,int y1,int x2,int y2,int x3,int y3,int l){/*此处代码作用是将三角形三顶点坐标转换,并保存至数组中由于与上述重复,不再赘述*///判断断边长大小决定是否继续递归if(length>4){g.setColor(new Color(length,l/4,length+l/4));g.fillPolygon(m, n, 3);length = length/2;//边长递减一半l = (int) (2*length*Math.sqrt(3));   //小三角形每次变化所要平移的距离System.out.println("X坐标:"+m[0]+"-"+m[1]+"-"+m[2]+" Y坐标:"+n[0]+"-"+n[1]+"-"+n[2]+" 边长="+2*length);g.setColor(new Color(l/4,l/4+length,l/4));g.fillPolygon(m, n, 3);//迭代到不包括最中间的其余三个小三角形中triangle_2(length,x1,y1,x2,y2,x3,y3,l);triangle_2(length,x1+2*length,y1+l,x2+2*length,y2+l,x3+2*length,y3+l,l);triangle_2(length,x1-2*length,y1+l,x2-2*length,y2+l,x3-2*length,y3+l,l);}}

绘制结果(2)


迭代过程中对三角形的填充的颜色做了变化,如果变换背景颜色,与最后迭代时小三角形颜色相近,会产生更好的效果:

同理,Sierpinski矩形地毯的绘制思路与Sierpinski三角形完全一致,不再赘述,只是我们可以多些变化,比如添加倒角效果如下:

可能渐变效果并不好,此处只是分享一种变化的思路,Sierpinski的部分我们就介绍到这里。

门格海绵(Menger sponge)

它是康托尔集和谢尔宾斯基地毯在三维空间的推广

构造特点

  1. 画出一个立方体
  2. 将它等分三层(底层,中层,顶层)即等分27个完全相同的小立方体
  3. 掏空每一面中央的小立方体,包括最内层的小立方体
  4. 对剩余的20个小立方体都重复1~3的操作,并渐变填充每个小立方体的三面,使其更有立体感

过程如图:


代码实现

网上随已有现成源码,但所做封装较多,普遍篇幅较长,本人整理如下的代码量可以缩减到一半以下,可读性大大提高。对比另一种方法:单靠不断叠加for循环的实现过程,此方法避免了代码尾段落全是 } 的尴尬,修改也更便捷,只需设定初始迭代值即可,逻辑更清晰易懂。

 int x = (int)e.getX();int y = (int)e.getY();int count =6;int d=486,dx=243,dy=243; //正方体边长、右、上侧透视深度

由于绘制立方体不会用到被遮挡的顶角,所以只需记录7个顶角坐标。其中P0点是我们认定的小方块起始绘制的首地址。

public void Menger_Sponge(int x,int y,int d,int dx,int dy,int count){//记录单个方块7个顶角的坐标Point p0 = new Point(x,y);Point p1 = new Point(p0.x+d,p0.y);Point p2 = new Point(p1.x,p1.y+d);Point p3 = new Point(p2.x-d,p2.y);Point p4 = new Point(p0.x+dx,p0.y-dy);Point p5 = new Point(p1.x+dx,p1.y-dy);Point p6 = new Point(p2.x+dx,p2.y-dy);count--; //递归次数减1if(count>=0){//递归到底层各小方块的首地址Menger_Sponge(p0.x+2*dx/3,p0.y-2*dy/3+2*d/3,d/3,dx/3,dy/3,count);Menger_Sponge(p0.x+2*dx/3+d/3,p0.y-2*dy/3+2*d/3,d/3,dx/3,dy/3,count);Menger_Sponge(p0.x+2*dx/3+2*d/3,p0.y-2*dy/3+2*d/3,d/3,dx/3,dy/3,count);Menger_Sponge(p0.x+dx/3,p0.y-dy/3+2*d/3,d/3,dx/3,dy/3,count);Menger_Sponge(p0.x+dx/3+2*d/3,p0.y-dy/3+2*d/3,d/3,dx/3,dy/3,count);Menger_Sponge(p0.x,p0.y+2*d/3,d/3,dx/3,dy/3,count);Menger_Sponge(p0.x+d/3,p0.y+2*d/3,d/3,dx/3,dy/3,count);Menger_Sponge(p0.x+2*d/3,p0.y+2*d/3,d/3,dx/3,dy/3,count);//递归到中层各小方块的首地址Menger_Sponge(p0.x+2*dx/3,p0.y-2*dy/3+d/3,d/3,dx/3,dy/3,count);Menger_Sponge(p0.x+2*dx/3+2*d/3,p0.y-2*dy/3+d/3,d/3,dx/3,dy/3,count);Menger_Sponge(p0.x,p0.y+d/3,d/3,dx/3,dy/3,count);Menger_Sponge(p0.x+2*d/3,p0.y+d/3,d/3,dx/3,dy/3,count);//递归到顶层各小方块的首地址Menger_Sponge(p0.x+2*dx/3,p0.y-2*dy/3,d/3,dx/3,dy/3,count);Menger_Sponge(p0.x+2*dx/3+d/3,p0.y-2*dy/3,d/3,dx/3,dy/3,count);Menger_Sponge(p0.x+2*dx/3+2*d/3,p0.y-2*dy/3,d/3,dx/3,dy/3,count);Menger_Sponge(p0.x+dx/3,p0.y-dy/3,d/3,dx/3,dy/3,count);Menger_Sponge(p0.x+dx/3+2*d/3,p0.y-dy/3,d/3,dx/3,dy/3,count);Menger_Sponge(p0.x,p0.y,d/3,dx/3,dy/3,count);Menger_Sponge(p0.x+d/3,p0.y,d/3,dx/3,dy/3,count);Menger_Sponge(p0.x+2*d/3,p0.y,d/3,dx/3,dy/3,count);}else{//填充正面矩形Polygon poly1 = new Polygon();poly1.addPoint(p0.x, p0.y);poly1.addPoint(p1.x, p1.y);poly1.addPoint(p2.x, p2.y);poly1.addPoint(p3.x, p3.y);g.setColor(new Color(150,0,0));g.fillPolygon(poly1);//填充右面矩形Polygon poly2 = new Polygon();poly2.addPoint(p1.x, p1.y);poly2.addPoint(p2.x, p2.y);poly2.addPoint(p6.x, p6.y);poly2.addPoint(p5.x, p5.y);g.setColor(new Color(200,0,0));g.fillPolygon(poly2);//填充上面矩形Polygon poly3 = new Polygon();poly3.addPoint(p0.x, p0.y);poly3.addPoint(p1.x, p1.y);poly3.addPoint(p5.x, p5.y);poly3.addPoint(p4.x, p4.y);g.setColor(new Color(100,0,0));g.fillPolygon(poly3);}}

绘制结果


这是迭代3次产生的结果,需要注意的是,三等分边长可能会出现浮点数,故建议按照3的倍数来设定初始值,以防各小方块分离的情况。

结尾

不论一维的cantor集,还是二维的Sierpinski地毯,又或者三维的Menger sponge绘制,迭代的思路无非都遵循了分形图案的特点:每个局部的形状都是整体图案缩小的效果,局部再分形也同样符合。
所以包括L-树,科赫雪花等分形图案的绘制我们也能如法炮制。

问题

门格海绵的绘制中,时间复杂度大,随着迭代次数增加,耗时明显变多有没有更好的方法可以解决这种问题呢?
例如:立方体的8个顶点我们只需要保存7个,立方体的6个面我们只需要绘制出3个,迭代过程中的小立方体有些是被遮挡不需要绘制的,如果我们能有更好的算法,一次性画出迭代的门格海绵,那么这个问题可以得到很好的解决。

混沌与分形(一):谢尔宾斯基三角形与门格海绵相关推荐

  1. 简单分形(谢尔宾斯基三角形和地毯)

    对于分形,我的理解就是:由小元件组成整体,然后再用另一或相同整体替换元件形成的循环迭代图形. 下面以谢尔平斯基三角形为例,介绍下最简单的分形思路. 第一步,先构造一个正三角形,取正三角形三边中点并连线 ...

  2. 混沌分形之谢尔宾斯基(Sierpinski)

    本文以使用混沌方法生成若干种谢尔宾斯基相关的分形图形. (1)谢尔宾斯基三角形 给三角形的3个顶点,和一个当前点,然后以以下的方式进行迭代处理: a.随机选择三角形的某一个顶点,计算出它与当前点的中点 ...

  3. Python数据结构15:turtle模块制图,画直线,正方形,星星,递归可视化:分形树,谢尔宾斯基三角形

    1. Python中的turtle模块制图 前面已经讲了递归的原理,这里用递归作图来直观的理解递归. 首先了解以下Python中用于作图的内置海龟作图系统turtle module. Python内置 ...

  4. 分形——谢尔宾斯基三角形

    分形--谢尔宾斯基三角形 普通几何学研究的对象,一般都具有整数的维数.比如,零维的点.一维的线.二维的面.三维的立体.乃至四维的时空.在20世纪70年代末80年代初,产生了新兴的分形几何学(fract ...

  5. 小白第一步|Java实现递归分形(以谢尔宾斯基三角形和勾股树为例)

    一个递归分形搞得我心态爆炸 于是 我一定要写个博客祭奠一下!!!!!! 首先回顾一下递归的几个要素: 1.return:往上回溯 2.调用自身:往下挖掘 3.设置条件:防止无限递归 4.递归操作:分析 ...

  6. 分形之谢尔宾斯基(Sierpinski)地毯

    前面讲了谢尔宾斯基三角形,和这一节的将把三角形变为正方形,即谢尔宾斯基地毯,它是由瓦茨瓦夫·谢尔宾斯基于1916年提出的一种分形,是自相似集的一种. 谢尔宾斯基地毯的构造与谢尔宾斯基三角形相似,区别仅 ...

  7. python与分形0009 - 谢尔宾斯基地毯

    分形介绍 分形是一个悖论. 它惊人的简单,却又无限的复杂. 它很新,却又比尘埃更古老. 分形是什么?它们是从哪里来的?我们为什么要在乎? 20世纪非传统的数学家Benoit Mandelbrot在19 ...

  8. 学习Python中turtle模块的基本用法(4:绘制科赫曲线和谢尔宾斯基三角形)

      科赫曲线和谢尔宾斯基三角形是常见的分形图形(详细介绍见参考文献1),本文使用turtle库绘制这两类图形. 科赫曲线   科赫曲线的详细介绍见参考文献2,其中的绘图思路是"画正三角形,并 ...

  9. 数据结构与算法(Python版)二十二:递归可视化(谢尔宾斯基三角形)

    谢尔宾斯基Sierpinski三角形 分形构造, 平面称谢尔宾斯基三角形, 立体称谢尔宾斯基金字塔 谢尔宾斯基三角形:作图思路 根据自相似特性, 谢尔宾斯基三角形是由3个尺寸减半的谢尔宾斯基三角形按照 ...

最新文章

  1. Opera 发布新技术 Opera Unite
  2. ArcGIS JS 学习笔记2 实现仿百度的拖拽画圆
  3. win7发现不了无线网络_Win7笔记本怎么设置wifi热点 Win7笔记本设置wifi热点方法【详解】...
  4. 阶段5 3.微服务项目【学成在线】_day02 CMS前端开发_21-CMS前端页面查询开发-Api调用...
  5. Struts2 标签
  6. react-native 加载图片的几种方式
  7. 3D动态相册实现代码
  8. Java多线程编程-停止线程 暂停线程
  9. 特价酒店预定应用HotelTonight获Battery和Accel 900万投资
  10. everedit选择_文本编辑器软件EverEdit怎么样?EverEdit相关功能介绍
  11. 徐张生:三级分销不是传销,人人店已经占据行业绝对优势
  12. 鹏鹏的Altium Designer快捷方式技巧--SCH
  13. 10大热门的物联网初创公司
  14. 从COVID-19大流行中汲取哪些教训?10种方法帮CIO预防下一次危机
  15. IE浏览器一打开就提示“已停止工作”的解决方案
  16. 通过cmd命令行操作mysql
  17. 数据库建表时,对于字段的数据类型的选择
  18. SQL server数据库实验(三)数据库的嵌套查询和集合查询
  19. 大学计算机基础学生实验报告经验总结,安卓作业实验报告心得体会
  20. 「绩效面谈」精选文章合集

热门文章

  1. 基于Android Studio的安卓课程设计(Keep运动软件)
  2. JavaScript对象与内置对象——对象(一)
  3. Python学习:python数组模块用法
  4. 双代号网络图如何用计算机画,怎么画双代号网络图,双代号网络图的绘制规则和步骤...
  5. Modular Arithmetic
  6. 一个网站做渗透测试对企业的安全性建议
  7. 接口和继承知识点总结
  8. 极简Python语法(9)
  9. tomcat9安装及其简单测试
  10. 搭建风控系统道路上踩过的坑合集