在做完画图板之后,就被胡哥忽悠着去做神马分形的东东,不过自己也确实被分形所展示的自然界的图形美所吸引。大家自己百度“分形”之后就会看到许多有趣而又神奇的图片,那些图片都是符合分形美的!分形美是一种异于对称美的自然的另一杰作 !
那么什么是分形呢?说的简单点就是“部分与整体以某种形式相似的形,称为分形。”这个定义虽然在真正的分形几何学的定义中也不是很确切,但是我觉得很形象。
大家现在来看一个简单的分形实例。
一.不可旋转的科赫曲线
在这个实例中我们看到,每条线段在一次分形变换中都被分为了四条线段并且中间的是一个没有底
的正三角形,在经过四次以上变换之后我们发现它变成了一种类似于雪花的形状,怎么样是不是还蛮神
奇的勒!
那么我们怎么用代码实现这个东东呢?其实只需要我们有一点从画图板中学到的界面知识以及初中
几何知识就可以了!
但是还存在一个问题不知道你有没有想过,怎么存储这个图形中的信息呢?这是个问题,因为图形
中的点和边都是以指数级增长的,我们以队列亦或是树存储信息也好,都不可能一直那么分形下去,都
会出现内存溢出的现象,问题就在于如何尽可能做更多次的分形!这就要抓住分形的本质--自相似性!
我们发现每次分形的最小微元和整体都是相似的,这就启发我们用递归去做,因为每次做的和上次做的
都是同一件事,这样就可以省去一些不必要的重复存储信息的操作。
请看代码实例:
//递归的深度;
private int depth=1;
//重写重绘的方法;
@Override
public void paint(Graphics g) {
// TODO Auto-generated method stub
super.paint(g);
KehePaint(150,500,650,500,this.depth);
}
/**
* 绘制科赫曲线的方法
* @param x1
* @param y1
* @param x2
* @param y2
*/
public void KehePaint(double x1,double y1,double x2,double y2,int depth){
if(depth<=1){//直接画直线;
g.drawLine((int)x1,(int)y1,(int)x2,(int)y2);
}else{
//找三等份点;
double x3=(2*x1+x2)/3;
double y3=(2*y1+y2)/3;
double x4=(x1+2*x2)/3;
double y4=(y1+2*y2)/3;
//找突出的点;
double x5=0,y5=0;
double k=(y4-y3)*(x4-x3);//判断倾斜角
//另一种发方法得到第三个点的坐标----还要做一下斜率的判断
if(y3==y4){
x5=(x3+x4)/2;
y5=y3-(x4-x3)*Math.sqrt(3)/2;
}else if(k<0){//右上斜
y5=y4;
x5=x3-(x4-x3);
}else if(k>0){//右下斜
y5=y3;
x5=x4+(x4-x3);
}if(x3==x4){//如果出现两个点重合的情况
x5=x3;
y5=y3;
}
//递归调用;
KehePaint(x1,y1,x3,y3,depth-1);
KehePaint(x3,y3,x5,y5,depth-1);
KehePaint(x5,y5,x4,y4,depth-1);
KehePaint(x4,y4,x2,y2,depth-1);
}
}
//绘制图形的方法;
@Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
if(e.getButton()==1&&this.depth<12){//如果是左击
this.depth++;
this.repaint();
}else if(e.getButton()==3&&this.depth>1){//如果是右击;
this.depth--;
this.repaint();
}
}
这种操作至少已经尝试过的两种数据结构多操作那么几次!呵呵~~
二.可旋转的科赫曲线
那么如果在科赫曲线的基础上加一个角度的变换,就是每次的没有底的正三角形不变,其余的每条
边相对于上一条边的角度不是60多而是0~360之间的任意角我们又如何做呢?这就需要我们在对科赫曲线
做分析。
我们每次用重复的四条线段代替一条线段用一下公式代替F+F--F+F,这里F代表前进,+代表左旋
60°角,-代表右旋60°角。那么科赫曲线的构造是不是可以等效于一下描述:
我们发现这也是一个递归的过程,但是对于可以旋转的科赫曲线我并没有采取向以上那种递归的方法,因为一旦旋转起来每个点都是不确定的值,所以我们可以换个角度思考,抓住每次变换最重要的部分就是角度!只要能获取这些角度值,再加上一个长度就可确定点了。当然在实际操作中比较头痛的问题还是怎么让我们画出来的图形适合于我们的界面,让图形恰当的显示在界面中还是比较麻烦的,我们可以采取先假定一个长度的形式先确定所画点的最值,然后根据最值对于起点和边的长度做调整,最后在画图形。
呵呵,看看小可一些代码,在算法的处理上还是比较愚笨的,请多指教啦!Y(^_^)Y
一.如何获取角
/**
* 计算角度队列的方法;
*/
public void CulAngleList(){
for(int i=0;i<this.depth;i++){
if(angleList.size()==0){//如果是空队列就直接加入三个角度;
addAngle();
//复制队列;
angleList.addAll(tmpAngleList);
//清空临时队列;
tmpAngleList.clear();
}else{
for(int j=0;j<angleList.size();j++){
addAngle();
tmpAngleList.add(angleList.get(j));
}
//添加最后的三个角度--一开始并没有考虑;
addAngle();
//清空原队列;
angleList.clear();
//复制队列;
angleList.addAll(tmpAngleList);
//清空临时队列;
tmpAngleList.clear();
}
}
}
public void addAngle(){
//新建三个Integer对象;
Integer angle1=new Integer(angle);
Integer angle2=new Integer(-120);
Integer angle3=new Integer(angle);
tmpAngleList.add(angle1);
tmpAngleList.add(angle2);
tmpAngleList.add(angle3);
}
这里我用来两个角度的队列,一个是角度队列一个是临时的队列,总的感觉还是觉得比较麻烦的,不怎么好。
二.如何确定每一点。
/**
* 计算点队列的方法;
*/
public void CulPointList(){
//将上次的点队列清空
pointList.clear();
//确定起点;
p1.x=this.startX;
p1.y=this.startY;
pointList.add(p1);
//确定第二点的坐标;
p2.x=p1.x+(int)this.length;
p2.y=p1.y;
pointList.add(p2);
//遍历角队列求点
for(int i=0;i<angleList.size();i++){
//得到角度;
double angle=((double)angleList.get(i)/180)*Math.PI;
//得到两点;
Point.Double p1=pointList.get(i);
Point.Double p2=pointList.get(i+1);
//得到坐标的double值;
//第一个点
double x1=p1.getX();
double y1=p1.getY();
//第二个点;
double x2=p2.getX();
double y2=p2.getY();
////计算直线的斜率;
double atan=0;
//确定直线p1--p2的角度;
if(x1<x2){
atan=Math.atan((y2-y1)/(x2-x1));
}else if(x1>x2){
atan=Math.atan((y2-y1)/(x2-x1))+Math.PI;
}else if(x1==x2&&y1<y2){
atan=Math.PI/2;
}else if(x1==x2&&y1>y2){
atan=-Math.PI/2;
}
//确定第三个点;
double x3=x2+this.length*(Math.cos(atan-angle));
double y3=y2+this.length*(Math.sin(atan-angle));
Point.Double p3=new Point.Double(x3,y3);
//判断坐标;
this.maxX=Math.max(x3, maxX);
this.minX=Math.min(x3, minX);
this.maxY=Math.max(y3, maxY);
this.minY=Math.min(y3, minY);
//加入队列;
pointList.add(p3);
}
}
三.对于初始位置和长度的调整
/**
* 依据得到的点队列的最值改变长度和初始位置;
*/
public void StateChanged(){
double lengthX=maxX-minX;
double lengthY=maxY-minY;
//横向采用缩放,纵向采取收缩;
//权衡两个方向取得适合的长度;
double k=0;//缩放的比例;
if(lengthX>lengthY){
k=size/lengthX;
this.length=k*length;
}else{
k=size/lengthY;
this.length=k*length;
}
/*************************************确定起点********************************************************/
//一另外一种方法计算调整之后的起点坐标;
//计算点的坐标得出最值;
maxX=startX+length;
minX=startX;
maxY=startY;
minY=startY;
CulPointList();
double x1=minX;
double y1=minY;
lengthX=maxX-minX;
lengthY=maxY-minY;
double x2=(size-lengthX)/2;
double y2=(size-lengthY)/2;
//调整起点;
this.startX=startX-(int)(x1-x2)+10;
this.startY=startY-(int)(y1-y2)+10;
/******************************************************************************************************************/
//还必须确定一下最值--哎在做一次
maxX=startX+length;
minX=startX;
maxY=startY;
minY=startY;
}
真的比较繁琐,有些东东我总是感觉自己老是在重复的做,⊙﹏⊙‖∣
呵呵,展示一下最后的效果图!Y(^_^)YY(^_^)Y
当然我们的分形几何学中的内容还远不止这些东东,还有神马谢冰司机三角形,pascal三角形,
Julia集的东东,形状也千奇百怪,树形分形,草形分析,.......总之分形构造出了很多美妙的图片!
如果我们深入研究就会发现这个世界真奇妙,我们知道的见到的都太少! 引用一下某人的名言啦“任重
道远~~~”!
后记
总的来说有这么几点感想。1.对于程序员来说算法才是王道。但是算法这么个东东又是要我们自
己去不断的尝试才可以领悟的。2.BUG这个东东真的很恶心,在计算点的时候我不小心将一个弧度制的角
和一个角度值的角相加然后自己又用变量来表示就没有发现,其实在打印角度结果的时候一开始就差那
么一点,这就需要我们去细心思考,思考那些微小的差别!3.对于系统不同的api我们需要取舍利用,比
如一开我用的是POint类来表示点,但是后来发现即使是一开始的60°最后的线段也总是不水平,这就启
发我换一个我不怎么熟悉的Point2D.Double类,哎~~~及结果真是柳暗花明啊!Y(^_^)Y,一直感觉自己
的思路没有问题可就是没有个结果,结果我们换了一个api类就搞定啦!4.这次做的几个分形的程序收获
还是蛮多的,在做树形分形的时候自己自学了二叉树,顺便学会了二叉树的排序方法嘿嘿,发现原来树
这种原来在我看来很神秘,很复杂的数据结构也不过如此吗!
- 大小: 23.7 KB
- 大小: 12.5 KB
- 大小: 63.7 KB
- 大小: 25 KB
分享到:
相关推荐
NULL 博文链接:https://luliangy.iteye.com/blog/1266548
用户可以通过控制一个虚拟的“海龟”在屏幕上移动并绘制线条,就像小时候玩的纸笔游戏一样。turtle模块的基本操作包括前进、后退、左转、右转等,非常适合初学者学习和探索图形绘制。 在创建分形树的过程中,我们...
**偶然玩分形 Java 测试** 在编程世界中,分形是一种引人入胜的数学概念,它体现了自相似性和无限复杂性。本项目聚焦于使用 Java 语言来实现分形图像的绘制,通过源码解析,我们可以深入理解分形的生成原理以及 ...
大家一起来玩分形,本程序为基于图片的分形程序,让分形创作变为一种游戏! <br>简单来说程序有两大特色: <br> 一、引入SQFormula复数计算引擎 <br> 利用该引擎,本程序实现了迭代公式、终止条件公式和...
6. **交互性增强**:增加用户控制迭代次数的输入框,允许用户自定义查看不同迭代级别的科赫格子,增加程序的可玩性和学习性。 7. **保存和加载**:提供保存和加载功能,用户可以保存当前的分形状态,或者加载之前...
《玩乱:在JavaScript中探索分形与奇怪吸引子》 在编程的世界里,JavaScript以其灵活性和广泛的应用性,成为了创建交互式Web内容的首选语言。本项目“playing-with-chaos-master”引领我们深入一个迷人的话题——...
Create React App入门该项目是通过。可用脚本在项目目录中,可以运行:npm start 在开发模式下运行应用程序。 打开在浏览器中查看。 如果进行编辑,页面将重新加载。 您还将在控制台中看到任何棉绒错误。...
7. **用户交互**:为了使程序更具可玩性和教育价值,可以添加用户界面,让用户可以自定义参数,如迭代次数、形状大小等,实时观察分形云的变化。 通过以上步骤,我们可以用MATLAB实现一个自定义的分形云生成器。在...
《网络游戏中的数字岩心与孔隙网络模型重构:基于随机分形理论》 在网络游戏的开发中,模拟真实的...通过这种方法,开发者能够创建出更加丰富、真实的地下世界,提高游戏的可玩性和沉浸感,为玩家带来独特的游戏体验。
《cpp-MarbleMarcher》是基于C++编程语言开发的一款创新性的视频游戏演示,它巧妙地结合了分形物理引擎和完全程序渲染技术,为玩家带来了极具艺术感和独特玩法的游戏体验。这款游戏不仅展示了C++在游戏开发领域的...
早期大一时候写的分形绘图程序,当时仅仅觉得分形好玩,写着玩玩。。代码比较烂,仅供参考学习。。。 主要功能 利用逃逸迭代法绘制Mandelbrot、Julia、Newton集 支持无限局部放大 支持颜色、常数因子等参数设置 支持...
《分形:TWEWY随机化器》是一款基于Python编程语言开发的工具,主要用于游戏《The World Ends with You(译名:与你同行/世界末日)》的玩家社区中,提供游戏元素的随机化功能,从而为玩家带来全新的挑战和游戏体验...
ascii.hs使用它来以ASCII形式呈现分形,并且在ghci中玩起来很酷。 graphical.hs和julia_param-*.hs使用图形库分别放大到一个Julia集和动画Julia开始参数。 使用-threaded -fllvm编译,例如ghc --make -O2 -...
这是一个使用菱形平方算法生成分形景观的小型 MATLAB 函数。 该算法实际上很老了,但我是在 Paul Martz 的“生成随机分形地形”页面上学到的( http://www.gameprogrammer.com/fractal.html )他还给出了一... 玩得开心
Mandelbrot 和 Julia 集的绘图仪。 缩放启用高达双精度。 可作为独立应用程序、matlab 应用程序或函数使用。 该功能是最稳定的,具有更多的自由度,但这些应用程序对于只想玩分形的人来说效果很好。
此外,学习如何将VB程序与外部数据源(如文本文件或数据库)集成,可以实现动态生成不同分形图案,提升程序的互动性和可玩性。 总之,这个VB分形图程序提供了一个很好的学习平台,让我们能够亲手探索分形的美丽世界...
游戏玩法 按开始按钮开始游戏。 要开始战斗,请按“战斗”按钮。 游戏每秒钟都会将您的统计数据与敌人的统计数据进行比较,并显示结果。 如果您的健康状况为0-您将会输掉。 如果敌人的生命值变为0,您将获胜并移至下...
第3课概率模拟算法 第4课排序算法可视化 第5课走迷宫 第6课随机迷宫生成 第7课自己做一个扫雷游戏 第8课益智游戏自动生成解- Move the Box 第9课分形图的绘制:计算机生成艺术 ...Java深度实战玩转算法源码.zip
在网络游戏领域,3D游戏随机地图的生成方法是游戏设计中的一个重要组成部分,它极大地增加了游戏的可玩性和重玩价值。这种技术广泛应用于各种类型的3D游戏中,如角色扮演游戏(RPG)、动作冒险游戏、策略游戏等。...
- 随机化策略:通过随机数生成器确保每次运行jdgen都能得到不同的地牢布局,增加游戏的可玩性。 3. **用户界面与交互** - 对于jdgen,可能包含一个图形用户界面(GUI),用户可以通过点击按钮或输入参数来控制...