分形的原理,是利用某一算法,迭代(一般用循环或者递归)获得新的图形来形成分形图形的。
在分形的学习中,掌握了递归这一个处理算法的工具,那么对于递归,我的看法是对一个或者一组数据进行相同而多次重复操作时使用的,它必须具备一个出口,不然会变成死递归,然后还可能需要对每一步递归进行一些变量的变化,一般通过递归方法的参数的传递来实现。
那么除了递归还可以用循环来实现,感觉关于分形,涉及到数学公式的迭代用循环比较好,而根据图形的规律来画出整个图形的话则用递归比较好。
下面用我画毕达哥拉斯曲线的过程来谈下我的经验。
画分形主要是算法问题,所以大部分代码集中在鼠标监听器,实现根据按下的点的坐标来做递归的第一层,然后根据点击的次数来增加递归的次数,使得树生长起来。
这是UI界面:
public class Pythagoras {
private Graphics g;
public static void main(String[] args) {
Pythagoras rc = new Pythagoras();
rc.show();
}
public void show() {
//初始化窗口
JFrame jf = new JFrame();
jf.setSize(1100, 800);
jf.setDefaultCloseOperation(3);
jf.setLocationRelativeTo(null);
jf.setVisible(true);
//获得画布
g = jf.getGraphics();
MyMouseListener ml = new MyMouseListener(g);
jf.addMouseListener(ml);
}
}
然后是鼠标监听器,开始以为挺简单的,就只在监听器里面加了个画图的方法,但是发现没把方法封装起来,感觉还是很乱,就比如在计算图形的顶点的时候用到了三角函数来计算,但是需要获得某两边的夹角,由于JFrame里面的坐标和我们熟悉的xy坐标有一点不一样,y的方向是往下的,所以在进行角的数值判断的时候BUG很多,一直调不好,导致递归出来的图形奇形怪状。
然后我就把分析角度,从而获得角度的环节封装在了一个getAngle方法里面,然后在这里方法里面很全面地分析了各种情况产生出来的角度。然后用起来也很方便,也便利了其他递归图形,比如科赫曲线,也用到了这个方法。
public class MyMouseListener extends MouseAdapter {
private int x1,y1;
private Graphics g;
private int count=1;
private double angle=Math.PI/6;
public MyMouseListener(Graphics g){
this.g = g;
}
public void mousePressed(MouseEvent e) {
x1 = e.getX();
y1 = e.getY();
/* for(int i=0;i<1000;i++){
g.clearRect(0, 0, 1100, 800);
angle = angle + Math.PI/3600;
draw(x1,y1,x1+100,y1,15,angle);
try {
Thread.sleep(10);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}*/
g.clearRect(0, 0, 1100, 800);
draw(x1,y1,x1+100,y1,count,angle);
count++;
}
public void draw(double x1,double y1,double x2,double y2, int n,double angle){
//退出递归的条件
if(n<=0)
return;
g.setColor(new Color(139, 0, 255));
double L = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
double a = getAngle(x1,y1,x2,y2);
double x3 = x1 + Math.cos(a - Math.PI/2)*L;
double y3 = y1 + Math.sin(a - Math.PI/2)*L;
double x4 = x1 + Math.cos(a - Math.PI/4)*L*Math.sqrt(2);
double y4 = y1 + Math.sin(a - Math.PI/4)*L*Math.sqrt(2);
g.drawLine((int)x1, (int)y1, (int)x2, (int)y2);
g.drawLine((int)x2, (int)y2, (int)x4, (int)y4);
g.drawLine((int)x4, (int)y4, (int)x3, (int)y3);
g.drawLine((int)x3, (int)y3, (int)x1, (int)y1);
a = getAngle(x3, y3, x4, y4);
double sanx = x3 + Math.cos(a - angle)*L*Math.cos(angle);
double sany = y3 + Math.sin(a - angle)*L*Math.cos(angle);
g.drawLine((int)x3, (int)y3, (int)sanx, (int)sany);
g.drawLine((int)sanx, (int)sany, (int)x4, (int)y4);
draw(x3,y3,sanx,sany,n-1,angle);
draw(sanx,sany,x4,y4,n-1,angle);
}
public double getAngle(double x1,double y1,double x2,double y2){
//定义逆时针为负角度
double a=0.0;
if(x1 == x2){//说明两点在同一竖线
if(y1 > y2)
a = Math.PI*3/2;
else if(y1 < y2)
a = Math.PI/2;
}else{
double temp_angle = Math.atan((y2 - y1)/(x2 - x1));
if(x2 > x1){//说明x2在左边
a = temp_angle;
}else if(x2 < x1){//说明x2在右边
a = temp_angle + Math.PI;
}
}
return a;
}
}
上面的注释段是想通过改变三角形的角度从而使得树生长的方向改变,然后用循环来做出左右摇摆的感觉,但是好像用法太简单,导致在摆的过程中一直闪,期待学到新知识解决这个问题!
分享到:
相关推荐
自写MFC实现分形云层,计算机图形学上机可能会用得到
python代码,可以实现画数学图形中的分形之雪花,很漂亮,很实用
c++画分形之Julia集
分形的一些论文,欢迎下载。 同时也有几种分形构成的方法。
分形技术,分形程序,分形动画,分形。。。。。。
该程序应用于一维数据的多重分形分析,是matlab代码
分形曲线分形几何学之二-windfern.m 分形曲线 分形几何学之一: https://www.ilovematlab.cn/thread-88859-1-1.html 程序: lyapunovfractal2.m 结果: 1.gif ...
matlab代码实现分形维数计算
分形之城..md
分形几何的matlab代码的一个小栗子。上课的一个作业。
分形曲线分形几何学之二-newtongallery[1].zip 分形曲线 分形几何学之一: https://www.ilovematlab.cn/thread-88859-1-1.html 程序: lyapunovfractal2.m 结果: 1....
本人收集的分形的资料和源码 包含分形屏保的代码 分形图生成的代码 和几本分形方面的书籍。
分形图形制作软件分形图形制作软件分形图形制作软件分形图形制作软件vvv
包含m文件,数据示范格式等,用来计算数列多重分形维数
openGL实现分形树的源代码,openGL实现分形树的源代码
讲解分形图形学中关于随机分形的一些详细内容,其中也有图形实例讲解
分形插值的matlab程序-分形插值曲面的MATLAB程序.pdf 传统的插值方法, 在相邻的两个信息点之间只能插出直线或者光滑...多重分形的特征, 因此在进行分形插值模拟的过程中, 还需考虑插值领域的确定与压缩比的选择[4]
matlab代码实现分形维数计算
c++画分形之Mandelbrot集