java實現三角形分形山脈

本文實例為大傢分享瞭java實現三角形分形山脈的具體代碼,供大傢參考,具體內容如下

三角形分形山脈原理

原型圖

如圖,這是三角形分形山脈的一個原型圖。首先我們讓x1、x2、x3三個點組成的三角形的各條邊的中點mid1、mid2、mid3可以在大三角形內部畫一個三角形,這時就會有四個小三角形,那麼我們對這四個小三角形做同樣的操作,如此就可以畫出雛形瞭。接下來我們隻需要對內部每個需要連線三角形的y坐標做相關操作就可以瞭。

效果圖

山脈分形之前的問題

重寫equals與hasCode方法

重寫的原因

就像下面這張圖所展示的效果一樣,其中出現瞭一個三角形分形兩邊的情況,導致下面這張圖沒有上面的圖看上去更有山脈的感覺。

出現這種情況是因為其中一條邊的中點向兩邊波動時,它的兩個頂點不同方向連線後留下的大片空白區域導致的(見上圖)。所以我們要想辦法記錄這條邊的中點,使它們隻記錄它的一個中點,這樣我們就能解決大片空白區域的問題瞭。

equals與hasCode

這裡我們用到瞭hashMap,那麼就牽涉到hashMap存儲的問題。如圖,hashMap在存儲對象數據時會通過它的hasCode與哈希函數計算該對象的存儲位置,如果這個位置沒有存儲數據,則直接存儲這個對象;如果存在有對象,我們則需要比較他們的hasCode來比較他們是否是同一個對象,如果是true已經存在這個對象的情況下,那麼我們就不操作,如果是false還沒有存入這個對象,我們則在這個存儲位置的後面將這個對象鏈接進來就好瞭。綜上,我們要自己建立一個數據類型來記錄這條邊的兩個點的x、y坐標及波動後中點的y坐標,所以我們要重寫equals與hasCode方法。

三角形山脈代碼

import java.awt.Color;
import java.awt.Graphics;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

import javax.swing.JFrame;

public class Recursive extends JFrame{

    private int[] xLabel;
    private int[] yLabel;
    Map<Object, Integer> map = new HashMap<>();
    Integer shiftY = 100;

    public void drawTri(Graphics g, int x1, int y1, int x2, int y2, int x3, int y3,
                        int deep, double range) {

        xLabel = new int[] {x1, x2, x3};
        yLabel = new int[] {y1, y2, y3};

        int shiftY1 = 0;
        int shiftY2 = 0;
        int shiftY3 = 0;

        if(deep-- < 0) {

            Color color = new Color(43, 43, 41, 233);

            g.setColor(color);

            g.drawPolygon(xLabel, yLabel, 3);

            return;

        }

        range *= 0.62;

        int midX1 = (x1 + x2) / 2;
        int midX2 = (x2 + x3) / 2;
        int midX3 = (x3 + x1) / 2;

        int midY1 = (y1 + y2) / 2;
        int midY2 = (y2 + y3) / 2;
        int midY3 = (y3 + y1) / 2;

        //其中每個點相對應
        if(verify(x2, y2, x1, y1)){
            shiftY1 = shiftY;
        } else{
            shiftY1 = shift(midY1,range);
        }
        if (verify(x3, y3, x2, y2)) {
            shiftY2 = shiftY;
        } else {
            shiftY2 = shift(midY2,range);
        }
        if(verify(x1, y1, x3, y3)) {
            shiftY3 = shiftY;
        } else{
            shiftY3 = shift(midY3,range);
        }

            //邊對象對應,震蕩點
            //存入邊對象
        map.put(new LineObject(x1, y1, x2, y2), shiftY1);
        map.put(new LineObject(x2, y2, x3, y3), shiftY2);
        map.put(new LineObject(x3, y3, x1, y1), shiftY3);

        drawTri(g, x1, y1, midX1, shiftY1, midX3, shiftY3, deep, range);  //頂
        drawTri(g, midX1, shiftY1, x2, y2, midX2, shiftY2, deep, range);   //左
        drawTri(g, midX3, shiftY3, midX2, shiftY2, x3, y3, deep, range);  //右
        drawTri(g, midX2, shiftY2, midX3, shiftY3, midX1, shiftY1, deep, range); //中

    }

    public int shift(int y, double range) {
        return y += (Math.random() * 2 - 1) * range;
    }

    public boolean verify(int x1, int y1, int x2, int y2) {

        LineObject lineObject = new LineObject(x1, y1, x2, y2);

        if(map.containsKey(lineObject)){
            shiftY = map.get(lineObject);
            return true;
        }
        return false;
    }
    public void UI() {
        this.setTitle("test");
        this.setDefaultCloseOperation(this.EXIT_ON_CLOSE);
        this.setSize(1000,1000);
        this.setLocationRelativeTo(null);
        this.setVisible(true);
        
        Graphics g=this.getGraphics();
        RecursiveListener rl=new RecursiveListener();
        this.addMouseListener(rl);
        rl.g=g;
    }

}

class LineObject {
    int x1;
    int y1;
    int x2;
    int y2;

    public LineObject(int x1, int y1, int x2, int y2) {
        this.x1 = x1;
        this.x2 = x2;
        this.y1 = y1;
        this.y2 = y2;

    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        LineObject that = (LineObject) o;
        return x1 == that.x1 &&
                y1 == that.y1 &&
                x2 == that.x2 &&
                y2 == that.y2;
    }

    @Override
    public int hashCode() {
        return Objects.hash(x1, y1, x2, y2);
    }

}

三角形山脈監聽器

import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

public class TriangleListener implements MouseListener {

    int x1, x2, x3, y1, y2, y3;
    int count = 0;
    Graphics g;

    @Override
    public void mouseClicked(MouseEvent e) {
        // TODO Auto-generated method stub
        g.drawOval(e.getX() - 4, e.getY() - 4, 8, 8);
        if (count == 0) {
            x1 = e.getX();
            y1 = e.getY();
            count++;
        } else if (count == 1) {
            x2 = e.getX();
            y2 = e.getY();
            count++;
            g.drawLine(x1, y1, x2, y2);
        } else {
            x3 = e.getX();
            y3 = e.getY();
            g.drawLine(x1, y1, x3, y3);
            g.drawLine(x2, y2, x3, y3);
            count = 0;
            Triangle triangle = new Triangle();
            triangle.recursion(x1, y1, x2, y2, x3, y3, g, 9, 800);
        }

    }

    @Override
    public void mousePressed(MouseEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mouseReleased(MouseEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mouseEntered(MouseEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mouseExited(MouseEvent e) {
        // TODO Auto-generated method stub

    }

}

以上就是本文的全部內容,希望對大傢的學習有所幫助,也希望大傢多多支持WalkonNet。

推薦閱讀: