views:

177

answers:

2

I'm trying to build my first fractal (Pythagoras Tree):

alt text

in Java using Graphics2D. Here's what I have now :

import java.awt.*;
import java.awt.geom.*; 
import javax.swing.*;
import java.util.Scanner;

public class Main {

public static void main(String[] args) {

    int i=0;
    Scanner scanner = new Scanner(System.in);

    System.out.println("Give amount of steps: ");
    i = scanner.nextInt();

    new Pitagoras(i);
    }
}

class Pitagoras extends JFrame {

private int powt, counter;

public Pitagoras(int i) {
    super("Pythagoras Tree.");
    setSize(1000, 1000);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setVisible(true);
    powt = i;
}

private void paintIt(Graphics2D g) {

    double p1=450, p2=800, size=200;

    for (int i = 0; i < powt; i++) {
        if (i == 0) {
            g.drawRect((int)p1, (int)p2, (int)size, (int)size);
            counter++;
        }
        else{
            if( i%2 == 0){
                //here I must draw two squares
            }
            else{
                //here I must draw right triangle
            }
        }
    }
}

@Override
public void paint(Graphics graph) {

    Graphics2D g = (Graphics2D)graph;
    paintIt(g);

}

So basically I set number of steps, and then draw first square (p1, p2 and size). Then if step is odd I need to build right triangle on the top of square. If step is even I need to build two squares on free sides of the triangle. What method should I choose now for drawing both triangle and squares ? I was thinking about drawing triangle with simple lines transforming them with AffineTransform but I'm not sure if it's doable and it doesn't solve drawing squares.

+4  A: 

You do not have to draw triangles, only squares (the edges of the squares are the triangle) in this tree.

You can make things a lot easier looking into recursion (these types of fractals are standard examples for recursion):

In Pseudo-Code

drawSquare(coordinates) {
    // Check break condition (e.g. if square is very small)
    // Calculate coordinates{1|2} of squares on top of this square -> Pythagoras
    drawSquare(coordinates1)
    drawSquare(coordinates2)
}

And since I often programmed fractals, a hint: Draw the fractal itself in a BufferedImage and only paint the image in the paint-method. The paint-Method gets called possibly several times per second, so it must be faaaaast.

Also do not directly draw in a JFrame but use a Canvas (if you want to use awt) or a JPanel (if you use swing).

Searles
the problem with recursion is that at some depth in the fractal you're going to run out of stack space. So while elegant, it's probably impractical here.
Stefan Monov
Well, in this case you would run out of space no matter which data structure you use.
Searles
good point, I'm stupid.
Stefan Monov
+1  A: 

My final solution :

import java.awt.*;
import java.util.Scanner;
import javax.swing.*;

public class Main extends JFrame {;

    public Main(int n) {
        setSize(900, 900);
        setTitle("Pythagoras tree");
        add(new Draw(n));
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.print("Give amount of steps: ");
        new Main(sc.nextInt());
    }
}

class Draw extends JComponent {
    private int height = 800;
    private int width = 800;
    private int steps;

    public Draw(int n) {
        steps = n;

        Dimension d = new Dimension(width, height);
        setMinimumSize(d);
        setPreferredSize(d);
        setMaximumSize(d);
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(Color.white);
        g.fillRect(0, 0, width, height);
        g.setColor(Color.black);

        int x1, x2, x3, y1, y2, y3;
        int base = width/7;

        x1 = (width/2)-(base/2);
        x2 = (width/2)+(base/2);
        x3 = width/2;
        y1 = (height-(height/15))-base;
        y2 = height-(height/15);
        y3 = (height-(height/15))-(base+(base/2));

        g.drawPolygon(new int[]{x1, x1, x2, x2, x1}, new int[]{y1, y2, y2, y1, y1}, 5);

        int n1 = steps;
        if(--n1 > 0){
            g.drawPolygon(new int[] {x1, x3, x2}, new int[] {y1, y3, y1}, 3);
            paintMore(n1, g, x1, x3, x2, y1, y3, y1);
            paintMore(n1, g, x2, x3, x1, y1, y3, y1);
        }
    }

    public void paintMore(int n1, Graphics g, double x1_1, double x2_1, double x3_1, double y1_1, double y2_1, double y3_1){
        int x1, x2, x3, y1, y2, y3;

        x1 = (int)(x1_1 + (x2_1-x3_1));
        x2 = (int)(x2_1 + (x2_1-x3_1));
        x3 = (int)(((x2_1 + (x2_1-x3_1)) + ((x2_1-x3_1)/2)) + ((x1_1-x2_1)/2));
        y1 = (int)(y1_1 + (y2_1-y3_1));
        y2 = (int)(y2_1 + (y2_1-y3_1));
        y3 = (int)(((y1_1 + (y2_1-y3_1)) + ((y2_1-y1_1)/2)) + ((y2_1-y3_1)/2));

        g.setColor(Color.green);
        g.drawPolygon(new int[] {x1, x2, (int)x2_1, x1}, new int[] {y1, y2, (int)y2_1, y1}, 4);
        g.drawLine((int)x1, (int)y1, (int)x1_1, (int)y1_1);
        g.drawLine((int)x2_1, (int)y2_1, (int)x2, (int)y2);
        g.drawLine((int)x1, (int)y1, (int)x2, (int)y2);

        if(--n1 > 0){
            g.drawLine((int)x1, (int)y1, (int)x3, (int)y3);
            g.drawLine((int)x2, (int)y2, (int)x3, (int)y3);
            paintMore(n1, g, x1, x3, x2, y1, y3, y2);
            paintMore(n1, g, x2, x3, x1, y2, y3, y1);
        }
    }
}
owca