Search code examples
javaswingrecursionfractals

Draw fractal with recursion algorithm


I write below code for draw a fractal tree like photo. But I have problem in second recursion method. (for middle branch length control ).How I can improve and correct It?

My Code:

import java.awt.BasicStroke;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.JFrame;

public class FractalTree1 extends Canvas {

// fields for drawing
private final JFrame frame;
private final int WINDOW_WIDTH = 1280;
private final int WINDOW_HEIGHT = 720;

public FractalTree1() {
    frame = new JFrame("Fractal Tree");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
    frame.setLocationRelativeTo(null);
    frame.setResizable(true);
    Component add = frame.add(this);
    frame.setVisible(true);
}

public static void main(String[] args) {
    FractalTree1 ft = new FractalTree1();
    ft.setVisible(true);
    ft.setBackground(Color.black);
}

@Override
public void paint(Graphics g) {
    g.setColor(Color.green);
    drawFractalTree(g, WINDOW_WIDTH / 2, WINDOW_HEIGHT - 75, -90, 2, true);
}

public void drawFractalTree(Graphics g, int x1, int y1, double angle, int depth, boolean value) {
    if (depth == 0) {
    } else {
        int x2, y2;
        if (value) {
            x2 = x1 + (int) (Math.cos(Math.toRadians(angle)) * depth * 100.0);
            y2 = y1 + (int) (Math.sin(Math.toRadians(angle)) * depth * 100.0);
        } else {
            x2 = (int) ((x1 + (int) (Math.cos(Math.toRadians(angle)) * depth * 100.0)) * 0.3);
            y2 = (int) (y1 + (int) (Math.sin(Math.toRadians(angle)) * depth * 100.0) * 0.3);
        }

        Graphics2D g2d = (Graphics2D) g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        g2d.setStroke(new BasicStroke(0.5f * depth));
        g2d.drawLine(x1, y1, x2, y2);

        drawFractalTree(g, x2, y2, angle + 10, depth - 1, true);
        drawFractalTree(g, x2, y2, angle - 35, depth - 1, false);
        drawFractalTree(g, x2, y2, angle - 70, depth - 1, true);
    }
}

}

My Target Photo: my target photo

I Updated Code :

import java.awt.BasicStroke;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.JFrame;

public class FractalTree1 extends Canvas {

// fields for drawing
private final JFrame frame;
private final int WINDOW_WIDTH = 1280;
private final int WINDOW_HEIGHT = 720;

public FractalTree1() {
    frame = new JFrame("Fractal Tree");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
    frame.setLocationRelativeTo(null);
    frame.setResizable(true);
    Component add = frame.add(this);
    frame.setVisible(true);
}

public static void main(String[] args) {
    FractalTree1 ft = new FractalTree1();
    ft.setVisible(true);
    ft.setBackground(Color.black);
}

@Override
public void paint(Graphics g) {
    g.setColor(Color.green);
    drawFractalTree((Graphics2D) g, WINDOW_WIDTH / 2, WINDOW_HEIGHT - 75, -90, 3,100, 1.0);
}

public void drawFractalTree(Graphics2D g, int x1, int y1, double angle, int depth, double size, double factor) {
if (depth > 0) {
    int x2 = x1 + (int) (Math.cos(Math.toRadians(angle)) * depth * size * factor);
    int y2 = y1 + (int) (Math.sin(Math.toRadians(angle)) * depth * size * factor);

    g.setStroke(new BasicStroke(0.5f * depth));
    g.drawLine(x1, y1, x2, y2);

    drawFractalTree(g, x2, y2, angle + 10, depth - 1, size, 1.0);
    drawFractalTree(g, x2, y2, angle - 35, depth - 1, size, 0.3);
    drawFractalTree(g, x2, y2, angle - 70, depth - 1, size, 1.0);
} }}

I show my new result in this Photo Link: new

But second branch length is worng.how I can correct It like my first photo(target link)


Solution

  • The calculation in your else case is wrong:

    • you are missing some parens in the y2 = ... line
    • you apply the factor 0.3 to the endpoint of the branch, not to it's length

    Try this:

    } else {
        x2 = x1 + (int) (Math.cos(Math.toRadians(angle)) * depth * 100.0 * 0.3);
        y2 = y1 + (int) (Math.sin(Math.toRadians(angle)) * depth * 100.0 * 0.3);
    }
    

    This my need a bit more fine-tuning of the different size and angle parameters, though.

    Also, you can simplify your method a bit by providing a few more parameters and moving the antialias settings out of the method:

    public void drawFractalTree(Graphics2D g, int x1, int y1, double angle, int depth, double size, double factor) {
        if (depth > 0) {
            int x2 = x1 + (int) (Math.cos(Math.toRadians(angle)) * depth * size * factor);
            int y2 = y1 + (int) (Math.sin(Math.toRadians(angle)) * depth * size * factor);
    
            g.setStroke(new BasicStroke(0.5f * depth));
            g.drawLine(x1, y1, x2, y2);
    
            drawFractalTree(g, x2, y2, angle + 10, depth - 1, size, 1.0);
            drawFractalTree(g, x2, y2, angle - 35, depth - 1, size, 0.3);
            drawFractalTree(g, x2, y2, angle - 70, depth - 1, size, 1.0);
        }
    }