5

しばらくの間、私はフラクタル、その背後にある数学、およびフラクタルが生成できるビジュアルに興味を持っていました。

数式を絵を描くコードにマッピングする方法がわかりません。
マンデルブロ集合のこの式を考えるPc(z) = z * z + c
と、次のコードとどのように比較されますか。

$outer_adder = ($MaxIm - $MinIm) / $Lines;
$inner_adder = ($MaxRe - $MinRe) / $Cols;
for($Im = $MinIm; $Im <= $MaxIm; $Im += $outer_adder)
{
  $x=0;
  for($Re = $MinRe; $Re <= $MaxRe; $Re += $inner_adder)
  {
    $zr = $Re;
    $zi = $Im;
    for($n = 0; $n < $MaxIter; ++$n)
    {
      $a = $zr * $zr;
      $b = $zi * $zi;
      if($a + $b > 2) break;
      $zi = 2 * $zr * $zi + $Im;
      $zr = $a - $b + $Re;
    }
    $n = ($n >= $MaxIter ? $MaxIter - 1 : $n);
    ImageFilledRectangle($img, $x, $y, $x, $y, $c[$n]);
    ++$x;
  }
  ++$y;
}

コードは完全ではなく、簡潔にするために主要な反復部分を示しているだけです。

だから問題は、数学がコードとどのように比較されるかを誰かが私に説明できるかということです。

編集:明確にするために、私は数学を説明する数十のリソースとコードを示す数十のリソースを見つけましたが、2つを組み合わせた良い説明をどこにも見つけることができません。

4

1 に答える 1

18

免責事項。以前はフラクタルについて何も知りませんでしたが、常に知りたいと思っていたので、ウィキペディアの記事を読んで、ここで見つけたものを書くことにしました。彼らが言うように、あなたが何かを理解したいのなら、それを他の誰かに説明してみてください。;)

さて、複素数を操作します。複素数は実際には(実)数のペアであるため、私たちphpプログラマーにとっては、2要素の配列とします。

    /// Construct a complex number from two reals
    function cpl($re, $im) {
        return array($re, $im);
    }

次に、複素数の算術演算を行う方法をphpに指示する必要があります。加算、乗算、およびmod( "norm")演算子が必要です。(詳細については、 http://mathworld.wolfram.com/topics/ComplexNumbers.htmlを参照してください)。

    /// Add two complex numbers.
    function cadd($p, $q) {
        return cpl(
            $p[0] + $q[0],
            $p[1] + $q[1]);
    }

    /// Multiply two complex numbers.
    function cmul($p, $q) {
        return cpl(
            $p[0] * $q[0] - $p[1] * $q[1],
            $p[0] * $q[1] + $p[1] * $q[0]);
    }

    /// Return the norm of the complex number.
    function cmod($p) {
        return sqrt($p[0] * $p[0] + $p[1] * $p[1]);
    }

ここで、指定された(複雑な)点$cがマンデルブロ集合に属している場合にtrueを返す関数を記述します。

すべての点が半径2の円の内側にある場合、その点cはセットに属します。z = z^2 + c

  • 複素数z=(0、0)から始めます。
  • 各ステップで、z = z * z+cを計算します。
  • > 2の場合modulus of z、つまり、円の外にある場合、ポイントは設定されていません
  • それ以外の場合は、手順を繰り返します。

それが際限なくループするのを防ぐために、反復の最大数を制限してください。

    function is_in_mandelbrot_set($c, $iterations) {
        $z = cpl(0, 0);
        do {
            if(cmod($z) >= 2)
                return false;
            $z = cadd(cmul($z, $z), $c);
        } while($iterations--);
        return true;
    }

残りは数学とは何の関係もなく、非常に明白です

    function mandelbrot($img, $w, $h) {
        $color = imagecolorallocate($img, 0xFF, 0, 0);
        $zoom = 50;
        $iters = 30;

        for($x = 0; $x < $w; $x++) {
            for($y = 0; $y < $h; $y++) {

                // scale our integer points 
                // to be small real numbers around 0

                $px = ($x - $w / 2) / $zoom;
                $py = ($y - $h / 2) / $zoom;

                $c = cpl($px, $py);

                if(is_in_mandelbrot_set($c, $iters))
                    imagesetpixel($img, $x, $y, $color);
            }
        }

        return $img;
    }

    $w = 200;
    $h = 200;

    header("Content-type: image/png");
    imagepng(
        mandelbrot(
            imagecreatetruecolor($w, $h), $w, $h));

結果

代替テキスト

もちろん、このコードは極端に効果がありません。その唯一の目的は、数学の概念を理解することです。

于 2010-09-16T12:57:39.993 に答える