9

アルゴリズムIteratedFunctionSystemを使用してフラクタルスワールを描画する必要があります

ターゲットフラクタル画像

このフラクタルには次の係数があります。

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

そしてここに私のコードがあります:

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;
        }
    }
}
}

残念ながら、このコードでは間違った画像が表示されます。

現在のフラクタル画像

誰かが私の間違いを指摘できたら素晴らしいと思います。

4

3 に答える 3

14

あなたの世代は正しいように見えますが(つまり、そうではありませんx1 = x2 +300; y1 = y2 +300;)、問題は、レンダリングの目的でスケールから大きく外れていることです。これは、画像の中心から外れる点がほとんどないことを意味します。

あなたのウィンドウは[0..600]x[0..600]です。空間の領域ではなく領域をレンダリングするように、50を掛けてみてx2ください。y2[-6..6]x[-6..6][-300..300]x[-300..300]

3x3の楕円ではなく、(それ自体への線として)単一のピクセルを描画するだけで十分であることに注意してください。

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

レンダリングされる内容によっては、画像全体を適切な範囲で取得するために、スケールをわずかに調整する必要がある場合があります。2番目の変換オフセットが-6.7。であることに注意してください。したがって、30のスケールはほぼ正しいはずです。

また、を使用x1 = x2 +300; y1 = y2 +300;することにより、変換を変更し、(期待するスケールで)異なるフラクタルを取得することに注意してください。

于 2012-12-23T13:54:50.483 に答える
4

これは素晴らしいことです。指数関数的なランタイムが必要だと思っていたのは間違っていました。フラクタルは私の想像よりも次元的に見えました!

ありがとう@JanDvorak!

以下も機能し(私の座標ではxcenter=300、、はグローバル描画パラメータです)、より高速に機能します。ycenter=100radius=50

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;
        }

    }

そして絵はより良いです

ここに画像の説明を入力してください

于 2012-12-23T14:18:31.237 に答える
1

以下は私の間違った答えです

しかし、それはフラクタルが直感よりも大きいことを示しているので、私はそれを維持します。

アルゴリズムは線形であるのに対し、アルゴリズムはツリーのよう(再帰的)である必要があると思います。ポイントのチェーンを1つ描画し、次々に変換します。つまり、スパイラルのようなチェーンができます。原則としてフラクタル画像を生成することはできません。

私はあなたの写真を手に入れました

あなたには2つの間違いがあります:

1)反復と描画シフトの両方に300を渡します。これはマイナーです。

2)アルゴリズムは線形です。線形アルゴリズムでは、木のような絵を描くことはできません。ランダムな値を使用する場合は、アルゴリズムを複数回実行する必要があります。1つのチェーンは、画像のランダムな部分を1つだけ描画します。

次の再帰的アルゴリズムであなたの写真を撮りました。動作は遅くなりますが、改善する必要があります。

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






    }

それを実行するために私は使用しました

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

パラメータは

    int xcenter = 300;
    int ycenter = 100;

    int radius = 50;

写真は次のとおりです。

ここに画像の説明を入力してください

于 2012-12-23T13:35:27.747 に答える