`
lazyee
  • 浏览: 15124 次
社区版块
存档分类
最新评论

简单分形(谢尔宾斯基三角形和地毯)

    博客分类:
  • java
阅读更多

对于分形,我的理解就是:由小元件组成整体,然后再用另一或相同整体替换元件形成的循环迭代图形。
下面以谢尔平斯基三角形为例,介绍下最简单的分形思路。
第一步,先构造一个正三角形,取正三角形三边中点并连线,形成一个内置倒三角形,然后把周围3个三角形又分别作为一个基元重复上述操作,多迭代几次就成了第三个图的样子。
      
界面初始代码如下:

import java.awt.Graphics;
import javax.swing.JFrame;
//谢尔宾斯基三角形
public class DrawPanel extends JFrame{

	/**
	 * 程序的入口主函数
	 */
	public static void main(String[] args) {
		//实例化DrawPanel类
		DrawPanel dp = new DrawPanel();
		//调用初始化界面的方法
		dp.initUI();
		
	}

	private void initUI() {
		// 设置界面基础属性
		this.setName("分形");
		this.setSize(500, 500);
		this.setDefaultCloseOperation(3);
		this.setLocationRelativeTo(null);
		this.setVisible(true);
		Graphics g = this.getGraphics();
		MListener ml = new MListener(g);
		this.addMouseListener(ml);
	}
}

实现画谢尔宾斯基的鼠标监听器类:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Random;

//谢尔宾斯基三角形
public class MListener implements MouseListener {
	int x1, y1, x2, y2, x3, y3, length;
	int count = 6;	//控制递归次数
	int c1,c2,c3;
	Graphics g;
	/**
	 * 覆写构造方法,传递画布
	 * @param g	传递的画布
	 */
	public MListener(Graphics g) {
		this.g = g;
	}

	/**
	 * 按下鼠标,求出第三个顶点坐标,画出初始三角形,并调用draw方法
	 */
	public void mousePressed(MouseEvent e) {
		g.clearRect(0, 0,1024, 1024);
		// 单击鼠标时,获得三点坐标,并完成递归调用
		System.out.println("单击");
		// 实例化一个随机数对象
		Random rd = new Random();
		
		//随机确定第一个顶点坐标和边长
		x1 = rd.nextInt(500);
		y1 = rd.nextInt(500);
		length=rd.nextInt(600);
		
		//确定颜色变量
		c1=rd.nextInt(256);
		c2=rd.nextInt(256);
		c3=rd.nextInt(256);
		
		// 计算第二、三个点坐标
		x2 = x1 + length;
		y2 = y1;
		
		x3 = (x1 + x2) / 2;
		y3 = (int) (y1 - length * Math.sqrt(3.0) / 2);
		
		//设置颜色
		g.setColor(new Color(c1,c2,c3));
		//画三角形三边
		g.drawLine(x1, y1, x2, y2);
		g.drawLine(x1, y1, x3, y3);
		g.drawLine(x3, y3, x2, y2);
		//将三个顶点传入draw方法
		this.draw(count, x1, y1, x2, y2, x3, y3);

	}

	/**
	 * 递归在三角形中画三角形的方法,取三边中点连线画出新三角形,又把周围三个三角形作为迭代变量
	 * @param count	递归次数控制变量
	 * @param x1
	 * @param y1
	 * @param x2
	 * @param y2
	 * @param x3
	 * @param y3	进行递归的三角形三个顶点的纵横坐标
	 */
	public void draw(int count, int x1, int y1, int x2, int y2, int x3, int y3) {
		int x4, y4, x5, y5, x6, y6;
		if (count > 0) {
			count--;
			x4 = (x1 + x2) / 2;
			y4 = (y1 + y2) / 2;
			x5 = (x1 + x3) / 2;
			y5 = (y1 + y3) / 2;
			x6 = (x3 + x2) / 2;
			y6 = (y3 + y2) / 2;
			g.drawLine(x4, y4, x5, y5);
			g.drawLine(x4, y4, x6, y6);
			g.drawLine(x6, y6, x5, y5);
			this.draw(count, x1, y1, x4, y4, x5, y5);
			this.draw(count, x4, y4, x2, y2, x6, y6);
			this.draw(count, x5, y5, x6, y6, x3, y3);
		} else
			return;
	}

	public void mouseClicked(MouseEvent e) {
		
	}

	public void mouseReleased(MouseEvent e) {

	}

	public void mouseEntered(MouseEvent e) {

	}

	public void mouseExited(MouseEvent e) {

	}
}

在此基础上还可以进行扩展:
扩展一:初始三角形可以是由随机的三个点连接而成的。只需将三个顶点的坐标设成随机数就好。
扩展二:谢尔宾斯基地毯与谢尔宾斯基三角形类似,先在大正方形中心画一个小正方形,再画中心正方形旁边八个正方形的中心正方形,如下图所示:


修改鼠标监听器类代码:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Random;
//谢尔宾斯基地毯
public class MListener implements MouseListener{
	int x1,y1,length;
	int count =6;//递归控制变量
	int c1,c2,c3;
	Graphics g;
	/**
	 * 覆写构造方法,传递画布
	 * @param g	传递的画布
	 */
	public MListener(Graphics g){
		this.g=g;
	}
	/**
	 * 按下鼠标,获得随机左上顶点坐标和最外层正方形边长,并调用draw方法
	 */
	public void mousePressed(MouseEvent e) {
		g.clearRect(0, 0, 1000, 1000);
		//单击鼠标时,获得三点坐标,并完成递归调用
		System.out.println("单击");
		//实例化一个随机数对象
		Random rd = new Random();
		x1=rd.nextInt(500);
		y1=rd.nextInt(500);
		length=rd.nextInt(600);
		
		c1=rd.nextInt(256);
		c2=rd.nextInt(256);
		c3=rd.nextInt(256);
		this.draw(count, x1, y1, length);
	}
	
	/**
	 * 每次迭代要实现的过程,画正中间的实心正方形,取周边8个正方形的顶点,进行迭代
	 * @param count	控制迭代次数
	 * @param x1	迭代单位正方形的左上顶点横坐标 
	 * @param y1	迭代单位正方形的左上顶点纵坐标 
	 * @param length正方形边长
	 */
	public void draw(int count,int x1,int y1,int length){
		int x2,y2,x3,y3,length2;
		int x4,y4,x5,y5,x6,y6;
		int x7,y7,x8,y8,x9,y9;
	
		if(count>0){
			count--;	
			//画中间实心正方形
			length2=length/3;
			x2=x1+length2;
			y2=y1+length2;
			
			g.setColor(new Color(c1,c2,c3));
			g.fillRect(x2, y2, length2, length2);
			
			//获得要迭代的其余八个正方形的起点坐标
			x3=x1+length2;
			y3=y1;
			
			x4=x1+2*length2;
			y4=y1;
			
			x5=x1;
			y5=y1+length2;
			
			x6=x1+2*length2;
			y6=y1+length2;
			
			x7=x1;
			y7=y1+2*length2;
			
			x8=x1+length2;
			y8=y1+2*length2;
			
			x9=x1+2*length2;
			y9=y1+2*length2;
			//对周边的八个正方形进行迭代操作
			this.draw(count, x1, y1, length2);
			this.draw(count, x3, y3, length2);
			this.draw(count, x4, y4, length2);
			this.draw(count, x5, y5, length2);
			this.draw(count, x6, y6, length2);
			this.draw(count, x7, y7, length2);
			this.draw(count, x8, y8, length2);
			this.draw(count, x9, y9, length2);
		} else return;
	}

	public void mouseClicked(MouseEvent e) {

	}

	public void mouseReleased(MouseEvent e) {
		
	}

	public void mouseEntered(MouseEvent e) {
		
	}

	public void mouseExited(MouseEvent e) {
		
	}

}

同谢尔宾斯基三角形类似,地毯也可以是长方形的。增加代表长和宽的参数即可。

 

  • 大小: 3.3 KB
  • 大小: 3.9 KB
  • 大小: 5.3 KB
  • 大小: 2.3 KB
  • 大小: 3.2 KB
  • 大小: 6.7 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics