这一篇关于分形图像,当然只是入门。

分形通常被定义为“一个粗糙或零碎的几何形状,可以分成数个部分,且每一部分都(至少近似地)是整体缩小后的形状”,即具有自相似的性质。分形有几种类型,可以分别依据表现出的精确自相似性、半自相似性和统计自相似性来定义。虽然分形是一个数学构造,它们同样可以在自然界中被找到,这使得它们被划入艺术作品的范畴。

之前有做过一个镂垫的程序,今天要做的是康托集,谢尔宾斯基地毯和Koch雪花。

源码下载

一维康托集

康托尔集是由不断去掉线段的中间三分之一而得出。首先从区间[0, 1]中去掉中间的三分之一(1/3, 2/3),留下两条线段:[0, 1/3] ∪ [2/3, 1]。然后,把这两条线段的中间三分之一都去掉,留下四条线段:[0, 1/9] ∪ [2/9, 1/3] ∪ [2/3, 7/9] ∪ [8/9, 1]。把这个过程一直进行下去。

看程序实现:

void cantuo1(GLfloat *a, GLfloat *b)
{glBegin(GL_LINES);glVertex3fv(a);glVertex3fv(b);glEnd();
}void divide_cantuo1(GLfloat *a, GLfloat *b, int m)
{cantuo1(a,b);GLfloat mid[2][3];if(m>0){/* compute 1/3points */mid[0][0]=a[0]+(b[0]-a[0])/3.0;mid[0][1]=(a[1]+b[1])/2.0+0.5;mid[0][2]=(a[2]+b[2])/2.0;mid[1][0]=b[0]-(b[0]-a[0])/3.0;mid[1][1]=(a[1]+b[1])/2.0+0.5;mid[1][2]=(a[2]+b[2])/2.0;a[1]+=0.5;b[1]+=0.5;/* create 2 part  by subdivision */divide_cantuo1(mid[1],b, m-1);divide_cantuo1(a,mid[0], m-1);}
}

divide_cantuo1中,首先将ab直线绘制出来,然后计算出1/3和2/3处的点坐标(y方向要移动0.5个单位),然后在分别绘制起点到1/3处和2/3处到终点的曲线。

cantuo1就是画线函数。

渲染出来看一下:

void renderGL()
{GLfloat a[2][3]={{-3.0, 0.0, 0.0},{3.0, 0, 0}};// Clear the color and depth buffers.glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );// We don't want to modify the projection matrix. */glMatrixMode( GL_MODELVIEW );glLoadIdentity( );// Move down the z-axis.glTranslatef( 0.0, -2.0, -5.0 );glClear(GL_COLOR_BUFFER_BIT);  /* clear the window */glLineWidth(4.0);divide_cantuo1(a[0],a[1],5);SDL_GL_SwapBuffers( );
}

最后的效果是这样:

谢尔宾斯基地毯

谢尔宾斯基地毯的构造与谢尔宾斯基三角形相似,区别仅在于谢尔宾斯基地毯是以正方形而非等边三角形为基础的。将一个实心正方形划分为的9个小正方形,去掉中间的小正方形,再对余下的小正方形重复这一操作便能得到谢尔宾斯基地毯。

看代码:

void cantuo2(GLfloat *a, GLfloat *b,GLfloat *c,GLfloat *d )
{static int i=0;glBegin(GL_QUADS);glColor3fv(colors[i++%4]);glVertex3fv(a);glVertex3fv(b);glVertex3fv(c);glVertex3fv(d);glEnd();
}void divide_cantuo2(GLfloat *a, GLfloat *b,GLfloat *c,GLfloat *d,int m)
{GLfloat mid[12][3];if(m>0){// compute 12 pointsmid[0][0]=a[0]+(b[0]-a[0])/3.0;mid[0][1]=a[1]+(b[1]-a[1])/3.0;mid[0][2]=0.0;mid[1][0]=a[0]+2.0*(b[0]-a[0])/3.0;mid[1][1]=a[1]+2.0*(b[1]-a[1])/3.0;mid[1][2]=0.0;mid[2][0]=d[0]+1.0*(a[0]-d[0])/3.0;mid[2][1]=d[1]+2.0*(a[1]-d[1])/3.0;mid[2][2]=0.0;mid[3][0]=a[0]+(b[0]-a[0])/3.0;mid[3][1]=d[1]+2.0*(a[1]-d[1])/3.0;mid[3][2]=0.0;mid[4][0]=a[0]+2.0*(b[0]-a[0])/3.0;mid[4][1]=d[1]+2.0*(a[1]-d[1])/3.0;mid[4][2]=0.0;mid[5][0]=c[0]+2.0*(b[0]-c[0])/3.0;mid[5][1]=c[1]+2.0*(a[1]-d[1])/3.0;mid[5][2]=0.0;mid[6][0]=d[0]+(a[0]-d[0])/3.0;mid[6][1]=d[1]+(a[1]-d[1])/3.0;mid[6][2]=0.0;mid[7][0]=a[0]+(b[0]-a[0])/3.0;mid[7][1]=d[1]+(a[1]-d[1])/3.0;mid[7][2]=0.0;mid[8][0]=a[0]+2.0*(b[0]-a[0])/3.0;mid[8][1]=d[1]+(a[1]-d[1])/3.0;mid[8][2]=0.0;mid[9][0]=c[0]+2.0*(b[0]-c[0])/3.0;mid[9][1]=d[1]+(a[1]-d[1])/3.0;mid[9][2]=0.0;mid[10][0]=a[0]+(b[0]-a[0])/3.0;mid[10][1]=d[1]+(c[1]-d[1])/3.0;mid[10][2]=0.0;mid[11][0]=a[0]+2.0*(b[0]-a[0])/3.0;mid[11][1]=d[1]+2.0*(c[1]-d[1])/3.0;mid[11][2]=0.0;/* create 9 part  by subdivision */divide_cantuo2(a,mid[0],mid[3],mid[2], m-1);divide_cantuo2(mid[0],mid[1],mid[4],mid[3],m-1);divide_cantuo2(mid[1],b,mid[5],mid[4],m-1);divide_cantuo2(mid[2],mid[3],mid[7],mid[6],m-1);//divide_cantuo2(mid[3],mid[4],mid[8],mid[7],m-1);divide_cantuo2(mid[4],mid[5],mid[9],mid[8],m-1);divide_cantuo2(mid[6],mid[7],mid[10],d,m-1);divide_cantuo2(mid[7],mid[8],mid[11],mid[10],m-1);divide_cantuo2(mid[8],mid[9],c,mid[11],m-1);printf("m:%d\n",m);}elsecantuo2(a,b,c,d);
}

这次divide_cantuo2函数需要找的是12个点,建议在纸上面画一下。

cantuo2就是画矩形。

渲染一下:

void renderGL()
{GLfloat a[4][3]={{-3.0, 3.0, 0.0},{3.0, 3.0, 0},{3.0, -3.0, 0.0},{-3.0, -3.0, 0}};// Clear the color and depth buffers.glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );// We don't want to modify the projection matrix. */glMatrixMode( GL_MODELVIEW );glLoadIdentity( );// Move down the z-axis.glTranslatef( 0.0, 0.0, -6.0 );glClear(GL_COLOR_BUFFER_BIT);  /* clear the window */divide_cantuo2(a[0],a[1],a[2],a[3],2);SDL_GL_SwapBuffers( );
}

当然,可以改变迭代次数和绘制的颜色。

Koch雪花

给定线段AB,科赫曲线可以由以下步骤生成:
将线段分成三等份(AC,CD,DB)
以CD为底,向外(内外随意)画一个等边三角形DMC
将线段CD移去
分别对AC,CM,MD,DB重复1~3。
科赫雪花是以等边三角形三边生成的科赫曲线组成的。。每条科赫曲线的长度是无限大,它是连续而无处可微的曲线。

代码实现:

void Koch(GLfloat *a, GLfloat *b)
{static int i=0;glBegin(GL_LINES);glColor3fv(colors[i++%4]);glVertex3fv(a);glVertex3fv(b);glEnd();
}void divideKoch(GLfloat *a, GLfloat *b,int m)
{float length= sqrt(pow(a[0] - b[0],2) + pow(a[1] - b[1],2))/3;printf("length:%f\n",length);GLfloat mid[3][3];if(m>0){// compute 3 pointsmid[0][0]=a[0]+(b[0]-a[0])/3.0;mid[0][1]=a[1]+(b[1]-a[1])/3.0;mid[0][2]=0.0;mid[1][0]=b[0]-(b[0]-a[0])/3.0;mid[1][1]=b[1]-(b[1]-a[1])/3.0;mid[1][2]=0.0;double alpha = 0.0;if (b[1]>= a[1]){alpha = atan((double) (b[1]-a[1]) / (b[0]-a[0]));if (b[0]>a[0]){mid[2][0] = mid[0][0] + length * cos(alpha + PI / 3);mid[2][1] = mid[0][1] + length  * sin(alpha + PI / 3);}else{mid[2][0] = mid[0][0] - length * cos(alpha + PI / 3);mid[2][1] = mid[0][1] - length * sin(alpha + PI / 3);}}else{alpha = atan((double) (a[1] - b[1]) / (b[0] - a[0]) );if (b[0]>a[0]){mid[2][0] = mid[1][0] - length * cos(alpha + PI / 3);mid[2][1] = mid[1][1] + length * sin(alpha + PI / 3);}else{mid[2][0] = mid[1][0] + length * cos(alpha + PI / 3);mid[2][1] = mid[1][1] - length * sin(alpha + PI / 3);}}/* create 9 part  by subdivision */divideKoch(a,mid[0], m-1);divideKoch(mid[0],mid[2],m-1);divideKoch(mid[2],mid[1],m-1);divideKoch(mid[1],b,m-1);printf("m:%d\n",m);}elseKoch(a,b);
}

divideKoch只是对一条直线进行分形。思路就是找到线的1/3,2/3处点的坐标,还有中间生成的等边三角形的一个顶点,然后对生成的每一条边都进行迭代。

渲染一个雪花:

void renderGL()
{//Define a triangle in spaceGLfloat a[3][3]={{-3.0, 0.0, 0.0},{3.0, 0.0, 0},{0.0, 5.196, 0.0}};// Clear the color and depth buffers.glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );// We don't want to modify the projection matrix. */glMatrixMode( GL_MODELVIEW );glLoadIdentity( );// Move down the z-axis.glTranslatef( 0.0, -2.0, -9.0 );glClear(GL_COLOR_BUFFER_BIT);  /* clear the window *///Koch(a[0],a[1]);divideKoch(a[1],a[0],6);divideKoch(a[2],a[1],6);divideKoch(a[0],a[2],6);SDL_GL_SwapBuffers( );
}

结果:

关于分形,这里只是一个很小很小的开始,还有很多的分形图像比如门格海绵,分形地形,分形云彩等等。可以参考:http://zh.wikipedia.org/wiki/%E5%88%86%E5%BD%A2

OpenGL进阶(七)-康托尔集 谢尔宾斯基地毯 Koch雪花相关推荐

  1. 陈斌老师《数据结构与算法Python版》第五周作业——ASCII谢尔宾斯基地毯

    陈斌老师<数据结构与算法Python版>第五周作业--ASCII谢尔宾斯基地毯 题目 思路 程序如下 总结 题目 谢尔宾斯基地毯是形如上图的正方形分形图案,每个地毯可分为等大小的9份,其中 ...

  2. Java学习日记:UI篇(6)--谢尔宾斯基地毯图

    Java学习日记:UI篇(6)–谢尔宾斯基地毯图 引言:谢尔宾斯基地毯是数学家谢尔宾斯基提出的一个分形图形,谢尔宾斯基地毯和谢尔宾斯基三角形基本类似,不同之处在于谢尔宾斯基地毯采用的是正方形进行分形构 ...

  3. python数据结构与算法40题_Python数据结构与算法40:递归编程练习题3:ASCII谢尔宾斯基地毯...

    注:本文如涉及到代码,均经过Python 3.7实际运行检验,保证其严谨性. 本文阅读时间约为7分钟. 递归编程练习题3:ASCII谢尔宾斯基地毯 谢尔宾斯基地毯 谢尔宾斯基地毯是形如上图的正方形分形 ...

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

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

  5. Java面向对象编程:利用递归思想绘制“谢尔宾斯基地毯”和“谢尔宾斯基三角形”

    1.递归:在方法中调用本方法. 2.递归调用会无限循环下去,因此方法体中必须有结束方法的条件.返回值为void时通常写为: if (条件) {return; } 下面使用递归绘制"谢尔宾斯基 ...

  6. 画完三角形再画谢尔宾斯基地毯

    照样废话不说,看代码看注释 import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import jav ...

  7. 按钮动作监听器和鼠标监听器的同时实现,在画图板上画出三角形,射线,曲笔,谢尔宾斯基三角形,谢尔宾斯基地毯Random类的实现,数组的实现,Thread.sleep的实现

    按钮动作监听器和鼠标监听器的实现 实例化 实现 监听器的类 DrawListener dl = new DrawListener();// 在界面上添加鼠标监听器对象(鼠标监听器的对象可以是界面和按钮 ...

  8. 谢尔宾斯基地毯的讲解

    谢尔宾斯基地毯是数学家谢尔宾斯基提出的一个分形图形,谢尔宾斯基地毯和谢尔宾斯基三角形基本类似,不同之处在于谢尔宾斯基地毯采用的是正方形进行分形构造,而谢尔宾斯基三角形采用的等边三角形进行分形构造.谢尔 ...

  9. Python实验舱谢尔宾斯基地毯绘制教程

    谢尔宾斯基地毯,和谢尔宾斯基三角形相似,下图就是谢尔宾斯基地毯 一,起始代码 p.width(3) p.speed(10) import turtle n=int(input()) base=int( ...

最新文章

  1. 设计模式之四-Factory模式
  2. 11月国内网站统计:淘宝得益于双11流量直逼腾讯
  3. Mac电脑设置adb环境变量
  4. [css] 说说你对字母“X“在CSS中有什么作用?
  5. DEBUG命令的应用
  6. JavaScript 删除Cookie
  7. java poi设置单元格格式为数值_java中导出excel设置单元格的样式为数字格式怎样设置?...
  8. 2018年面试题大全
  9. [ExtJs6]随记--去除extjs trial水印
  10. php ubb类,一个用PHP实现的UBB类!-PHP教程,PHP应用
  11. 多伦多大学计算机硕士读几年,多伦多大学计算机硕士申请条件
  12. visual studio使用时光标变粗
  13. 从反人工智能到反无人机,谁在左右科技的进步?
  14. Scala基础知识(个人总结)
  15. Hadoop基本命令(记一次Hadoop课后实验)
  16. 让你眼前一亮——智慧之眼(Python代码实现)
  17. STM32F4的LED点灯
  18. 操作系统---存储管理
  19. 俄罗斯品牌VOXTEL 520手机硬启动方法(恢复出厂)
  20. Linux中的古老缩略语

热门文章

  1. 《银河护卫队》系列终章IMAX中国首周末劲收3840万票房,全球斩获约2500万美元...
  2. 高级性能测试课程介绍
  3. 教你如何做大学英语四级翻译题!!!英语四级翻译必备分类词汇和练习题以及模板
  4. java 反射 工厂模式_Java反射机制demo(七)—反射机制与工厂模式
  5. 库存管理系统(java)
  6. RISC-V架构解析
  7. python谷歌翻译库googletrans使用 避坑!
  8. C# 限制TextBox控件内输入值的范围
  9. 名编辑电子杂志大师教程 | 名编辑制作电子杂志时只能添加PDF的页面吗?
  10. VScode CMake 编写 Boost Asio 程序----记录4