Java中的分形幾何:把遞歸用到極致
"一尺之錘、日取其半、萬世不竭"這和分形幾何的思想極為相似。
無論從美學(xué)的觀點還是從科學(xué)的觀點,許多人在第一次見到分形時都有新的感受。----曼德勃羅
在外形看來分形藝術(shù)似乎是魔術(shù)。但不會有任何數(shù)學(xué)家疏于了解他的結(jié)構(gòu)和意義。
分形是自然界的幾何學(xué)。我們看到了一些以前沒有看到過得東西,它讓我們用另一種眼光去看世界。
蜿蜒曲折的海岸線、起伏不定的山脈、粗糙不堪的斷層、變換無常的浮云、九曲回腸的河流、縱橫交錯的血管、令人眼花繚亂的繁星,他們都那么的極不規(guī)則、極不光滑。粗略的說這些對象都是分形。分形幾何據(jù)有自相似性、自仿射性。分形幾何與歐式幾何有著明顯的區(qū)別:首先它是無規(guī)則的(不光滑的)、他是無限的、可以從局部看出整體、看上去復(fù)雜但結(jié)構(gòu)相當(dāng)簡單、他的維數(shù)一般為分?jǐn)?shù)。
想了解分形幾何可以去baidu百科找http://baike.baidu.com/view/44498.htm
下面我就以遞歸的思想,采用java語言畫一樹葉。
截圖看一下:
程序代碼:
- import java.awt.*;
- import java.awt.event.*;
- import java.util.Random;
- import javax.swing.*;
- /**
- *
- * @author http://javaflex.iteye.com/
- *
- */
- public class GraphicsTest extends JFrame implements ActionListener {
- public static final double PI = Math.PI / 180;
- JPanel panel;
- JPanel pnlCtl;
- JButton button;
- JButton button2;
- Graphics2D g2;
- public GraphicsTest(String string) {
- super(string);
- }
- public void init() {
- panel = new JPanel();
- pnlCtl = new JPanel();
- button = new JButton("分形樹");
- button2 = new JButton("清除");
- this.add(panel, BorderLayout.CENTER);
- button.addActionListener(this);
- button2.addActionListener(this);
- pnlCtl.add(button);
- pnlCtl.add(button2);
- this.add(pnlCtl, BorderLayout.NORTH);
- setSize(800, 600);
- this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- this.setVisible(true);
- Dimension winSize = Toolkit.getDefaultToolkit().getScreenSize();
- this.setLocation((winSize.width - this.getWidth()) / 2,
- (winSize.height - this.getHeight()) / 2);
- g2 = (Graphics2D) panel.getGraphics();
- }
- public static void main(String[] args) throws ClassNotFoundException,
- InstantiationException, IllegalAccessException,
- UnsupportedLookAndFeelException {
- UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
- GraphicsTest testPanel = new GraphicsTest("分形樹:QQ:三2824七676");
- testPanel.init();
- }
- @Override
- public void actionPerformed(ActionEvent e) {
- if ("分形樹".equals(e.getActionCommand())) {
- drawLeaf(g2, 400, 500, 100, 210+random.nextInt(100));
- } else if ("清除".equals(e.getActionCommand())) {
- panel.getGraphics().clearRect(0, 0, 800, 800);
- }
- }
- Random random=new Random();
- public void drawLeaf(Graphics g, double x, double y, double L, double a) {
- //random=new Random();
- //可以方面速度畫以了解其算法
- // try {
- // Thread.sleep(1000);
- // } catch (InterruptedException e) {
- // // TODO Auto-generated catch block
- // e.printStackTrace();
- // }
- int red = random.nextInt(127);
- int green = random.nextInt(127);
- int blue = random.nextInt(127);
- //隨機顏色
- g.setColor(new Color(red, green, blue));
- double x1, x2, x1L, x2L, x2R, x1R, y1, y2, y1L, y2L, y2R, y1R;
- float deflection = 50-random.nextInt(20);//側(cè)干主干的夾角
- float intersection = random.nextInt(40)-20;//主干偏轉(zhuǎn)角度
- float depth = 2+random.nextInt(2);//限制遞歸深度
- float ratio = 3f;//主干側(cè)干長度比(可調(diào)整使其更茂密或稀疏)
- float ratio2 = 1.2f;//上級主干與本級主干長度比(可調(diào)整使其變高低)
- if (L > depth) {
- x2=x+L*Math.cos(a*PI);
- y2=y+L*Math.sin(a*PI);
- x2R=x2+L/ratio*Math.cos((a+deflection)*PI);
- y2R=y2+L/ratio*Math.sin((a+deflection)*PI);
- x2L=x2+L/ratio*Math.cos((a-deflection)*PI);
- y2L=y2+L/ratio*Math.sin((a-deflection)*PI);
- x1=x+L/ratio*Math.cos(a*PI);
- y1=y+L/ratio*Math.sin(a*PI);
- x1L=x1+L/ratio*Math.cos((a-deflection)*PI);
- y1L=y1+L/ratio*Math.sin((a-deflection)*PI);
- x1R=x1+L/ratio*Math.cos((a+deflection)*PI);
- y1R=y1+L/ratio*Math.sin((a+deflection)*PI);
- g.drawLine((int)x,(int)y,(int)x2,(int)y2);
- g.drawLine((int)x2,(int)y2,(int)x2R,(int)y2R);
- g.drawLine((int)x2,(int)y2,(int)x2L,(int)y2L);
- g.drawLine((int)x1,(int)y1,(int)x1L,(int)y1L); g.drawLine((int)x1,(int)y1,(int)x1R,(int)y1R);
- drawLeaf(g,x2,y2,L/ratio2,a+intersection);
- drawLeaf(g,x2R,y2R,L/ratio,a+deflection);
- drawLeaf(g,x2L,y2L,L/ratio,a-deflection);
- drawLeaf(g,x1L,y1L,L/ratio,a-deflection);
- drawLeaf(g,x1R,y1R,L/ratio,a+deflection);
- }
- }
- }
希望對大家有所幫助,特別是對分形幾何感興趣的朋友,希望可以進(jìn)一步交流。
原文鏈接:http://javaflex.iteye.com/blog/1266365
【編輯推薦】