您的位置:首页 > 编程语言 > Java开发

JAVA第三课——L-system分形的初次接触

2016-07-14 11:32 549 查看
首次接触分形这种东西,觉得特别有趣!为什么呢,首先说一下自己的感想,我们所熟悉的万物其实可以分成两种——有规则和没有规则。有些时候我们看的东西虽然复杂,但是仔细去寻找还是可以发现规律,只要找出它的最小组成单元就可以画出整个物体。但是有时候看似比较简单,但是没有规律可循,额(⊙o⊙)…这就尴尬了,差不多只能手动暴力模拟了吧。那么这次我们讲的分形,简单的就是找规律然后重塑物体。

比如,当我们看到下面这个图形的时候会想到什么呢?


也许会觉得很复杂,不要急,我们再看看下一张图片:


这个是不是就觉得简单点了??不急,我们再看下一张:


这个是不是更简单了???没事,还有更简单的!:


行啦!不能再简单了 !!!!!

细心的同学很快就会发现这几张图片的联系。从最后一张张图片开始,不断的迭代 ——每条边都用本图形代替就会得到第一张图片,也就是说,最后一张图片是第一张图片的最小单元。

那么问题就可以说很好办了。为什么?我们只需要做几件事情就可以了,首先想办法得到最小单元,然后得到迭代的次数,之后最终画出我们想得到的图形。那么也有新的问题,最然我们知道JAVA给我们提供了画图形的方法——画线,画圆等等,我们也可以看出上面的图形就是线条画出来的,但是怎么画呢?????不急,我们先分析一下,最小的单元就是从起点开始向左画一条线段,变向60度,再画一条线段,再变向120度,再画一条线段,再变向60,再画一条线段,这样我们就画出了最简单的图形。但是计算机是很笨的,我们必须指明每一步怎么画才行。那么我们可以利用正则表达式来解决——F-F++F-F。F表示画一条单位长度的线段,-表示以线条的方向为正方向向左偏移60度,+则相反。那么根据这个表达式我们不就可以画出最简单的图形了吗?

那怎么画第二个图形呢?刚才说了,无论多么复杂的图形都是最简单的图形迭代来的,那么我们可以把F-F++F-F中的每个F用F-F++F-F来代替,那么根据新的正则表达式得出的图形就是倒数第二个图形。好了,讲到这里估计大家就都明白了吧,那就赶快去试一下吧!

同样贴出自己的代码:

package L_System;

public class Manager
{
public static void main(String[] args)
{
Manager mag=new Manager();
mag.Draw();
}

public void Draw()
{
String axiom="F-F++F-F";//母串
int count=3;//表示迭代的次数
Curve curve=new Curve(axiom,count);

// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
//
// curve.init();
// curve.draw();
// curve.curve();
curve.paint(curve.getGraphics());
}
}

package L_System;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Curve extends JFrame{
private String axiom;
private String production;
private String sequence;
private Graphics gg;
private int count;
private double ra,rb;
private Point[] points;

public Curve(String axiom,int count)
{
this.axiom=axiom;
this.count=count;
production=axiom;
this.setTitle("L-System");
this.setSize(1000,800);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(3);
this.setVisible(true);
gg = this.getGraphics();
}

public void paint(Graphics g){
//改写重绘方法
super.paint(g);
init();
draw();
}
//	public void curve()
//	{
//		init();
//		draw();
//	}
public void init()
{
//换算角度
ra = 60*Math.PI/180;
rb = 60*Math.PI/180;
if(count==0)
{
sequence=axiom;
return ;
}
sequence=axiom;
//根据迭代次数生成新的正则表达式
for(int i=0;i<count;i++)
{
StringBuffer buf = new StringBuffer();
//			System.out.println(sequence);
for(int j = 0; j < sequence.length(); j++)
{
if(sequence.charAt(j) == 'F')
buf.append(production);
else
buf.append(sequence.charAt(j));
}
sequence = buf.toString();
}
//		System.out.println(sequence);
}

public void draw()
{
int n;
//规定单位F的长度
double len = 10;
//设置方向向量
double dx = 1,dy = 0;
//设置起点坐标
double x0 = 20,y0 = 500;
double min_x,max_x,min_y,max_y;
min_x=max_x=x0;
min_y=max_y=y0;

n = 1;
for(int i = 0; i < sequence.length(); i++)
if(sequence.charAt(i) == 'F')	n++;

points = new Point
;
points[0] = new Point((int)x0,(int)y0);
int num = 1;
for(int i = 0; i < sequence.length(); i++)
{
if(sequence.charAt(i) == 'F')
{
double x1 = x0 + len*dx;
double y1 = y0 + len*dy;
x0 = x1;
y0 = y1;
if(x0 < min_x) min_x = x0;
if(x0 > max_x) max_x = x0;
if(y0 < min_y) min_y = y0;
if(y0 > max_y) max_y = y0;
points[num++] = new Point((int)x0,(int)y0);
}else if(sequence.charAt(i) == '+')
{
//改变方向向量
double _dx = dx*Math.cos(ra)-dy*Math.sin(ra);
double _dy = dx*Math.sin(ra)+dy*Math.cos(ra);
dx = _dx;
dy = _dy;
}else if(sequence.charAt(i) == '-')
{
double _dx = dx*Math.cos(-rb)-dy*Math.sin(-rb);
double _dy = dx*Math.sin(-rb)+dy*Math.cos(-rb);
dx = _dx;
dy = _dy;
}
}

int x1,x2,y1,y2;
x2 = points[0].x;
y2 = points[0].y;
System.out.println(num);
for(int i = 0; i < num; i++)
{
x1 = points[i].x;
y1 = points[i].y;
//			System.out.println(x1+" "+y1);
//			gg.drawLine(x2, y2, x1, y1);
Graphics2D g2d = (Graphics2D) gg;
g2d.setStroke(new BasicStroke(2));
gg.drawLine(x2,y2,x1,y1);
x2 = x1;
y2 = y1;
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: