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

首次接触分形这种东西,觉得特别有趣!为什么呢,首先说一下自己的感想,我们所熟悉的万物其实可以分成两种——有规则和没有规则。有些时候我们看的东西虽然复杂,但是仔细去寻找还是可以发现规律,只要找出它的最小组成单元就可以画出整个物体。但是有时候看似比较简单,但是没有规律可循,额(⊙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[n];
		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;
		}
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值