문제

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.

도움이 되었습니까?

해결책

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).

다른 팁

This is great, I was wrong thinking that exponential runtime required! The fractals appeared more dimensional than my imagination!

Thanks @Jan Dvorak!

The following also works (in my coordinates, xcenter=300, ycenter=100 and radius=50 are global drawing parameters) and works faster:

void drawFractal2(Graphics g) {

        double x1 = 0;
        double y1 = 0;
        double x2 = 0;
        double y2 = 0;
        double p;

        g.fillOval(xcenter + (int) (x1 * radius), ycenter + (int) (y1 * radius), 3, 3);

        for(int i=0; i<100000; ++i) {
            p = Math.random();

            if (p < p1) {
                x2 = x1(x1, y1);
                y2 = y1(x1, y1);

            }
            else {
                x2 = x2(x1, y1);
                y2 = y2(x1, y1);

            }

            g.fillOval(xcenter + (int) (x2 * radius), ycenter + (int) (y2 * radius), 3, 3);
            x1 = x2;
            y1 = y2;
        }

    }

and the picture is better

enter image description here

BELOW IS MY INCORRECT ANSWER

But it show how fractals are bigger than the intuition, so I keep it.

I guess your algorithm should be tree-like (recursive) while your one is linear. You are just drawing one chain of points, transforming it one after one. So you get some spiral-like chain. It can't generate any fractal picture in principle.

I GOT YOUR PICTURE

You have 2 mistakes:

1) you pass 300 both into iteration and as drawing shift. This is minor.

2) You algorithm is linear. Linear algorithm can't draw tree-like picture. If you use random values, you should run algorithm multiple times. One chain draws only one random portion of the picture.

I got your picture with following recursive algorithm. It works slow but you are to improve it.

  void drawFractal(Graphics g, double x1, double y1, int depth) {

        double x2 = 0;
        double y2 = 0;

        if( depth > 20 ) {
            return;
        }

        g.fillOval(xcenter + (int) (x1 * radius), ycenter + (int) (y1 * radius), 3, 3);

        x2 = x1(x1, y1);
        y2 = y1(x1, y1);
        drawFractal(g, x2, y2, depth+1);



        x2 = x2(x1, y1);
        y2 = y2(x1, y1);
        drawFractal(g, x2, y2, depth+1);






    }

to run it I used

    public void paint(Graphics g) {
        //drawFractal(g);
        drawFractal(g, 0, 0, 0);
    }

parameters are

    int xcenter = 300;
    int ycenter = 100;

    int radius = 50;

the picture is follows:

enter image description here

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top