Search code examples
javaalgorithmgraphfractals

Generating fractal Swirl


I need to draw a fractal swirl using the algorithm Iterated Function System.

Targeted Fractal Image

There are coefficients for this fractal:

0.745455 -0.459091  0.406061  0.887121 1.460279 0.691072 0.912675
-0.424242 -0.065152 -0.175758 -0.218182 3.809567 6.741476 0.087325

And here is my code:

import java.awt.Graphics;
import javax.swing.JPanel;

public class Surface extends JPanel {
double a1 = 0.745455;
double b1 = -0.459091;
double d1 = 0.406061;
double e1 = 0.887121;
double c1 = 1.460279;
double f1 = 0.691072;
double p1 = 0.912675;

double a2 = -0.424242;
double b2 = -0.065152;
double d2 = -0.175758;
double e2 = -0.218182;
double c2 = 3.809567;
double f2 = 6.741476;
double p2 = 0.087325;

double x1(double x, double y) {
    return a1 * x + b1 * y + c1;
}

double y1(double x, double y) {
    return d1 * x + e1 * y + f1;
}

double x2(double x, double y) {
    return a2 * x + b2 * y + c2;
}

double y2(double x, double y) {
    return d2 * x + e2 * y + f2;
}

public void paint(Graphics g) {
    drawFractal(g);
}

void drawFractal(Graphics g) {
    double x1 = 300;
    double y1 = 300;
    double x2 = 0;
    double y2 = 0;
    g.fillOval(300 + (int) x1, 300 + (int) y1, 3, 3);
    for (int i = 0; i < 10000; i++) {
        double p = Math.random();
        if (p < 0.91675) {
            x2 = x1(x1, y1);
            y2 = y1(x1, y1);
            g.fillOval(300 + (int) x2, 300 + (int) y2, 3, 3);
            x1 = x2;
            y1 = y2;
        } else {
            x2 = x2(x1, y1);
            y2 = y2(x1, y1);
            g.fillOval(300 + (int) x2, 300 + (int) y2, 3, 3);
            x1 = x2;
            y1 = y2;
        }
    }
}
}

Unfortunately, with this code I get a wrong picture:

Current Fractal Image

It would be great if someone could point out my mistake.


Solution

  • Your generation seems correct (i.e. don't do x1 = x2 +300; y1 = y2 +300;), but your problem is you're way off the scale for the purposes of rendering. This means there are very few points that fall outside very center of the image.

    Your window is [0..600]x[0..600]. Try multiplying x2 and y2 with 50, so that you're rendering the [-6..6]x[-6..6] region instead of the [-300..300]x[-300..300] region of space.

    Note that it should be sufficient to draw single pixels (as lines to itself) instead of 3x3 ovals.

    int xp = 300 + (int) (x2 * scale);
    int yp = 300 + (int) (y2 * scale);
    g.drawLine(xp, yp, xp, yp);
    

    Depending on what gets rendered, you might need to adjust the scale slightly to get the entire image with reasonable bounds. Note the second transformation offsets by -6.7, so a scale of 30 should be about right.

    Also note that by using x1 = x2 +300; y1 = y2 +300; you change the transformations and get a different fractal (at a scale at which you expect).