分形解释

发布于 2024-09-24 07:38:42 字数 869 浏览 4 评论 0原文

一段时间以来,我对分形、它们背后的数学以及它们可以产生的视觉效果很感兴趣。

我只是无法真正弄清楚如何将数学公式映射到绘制图片的一段代码。
给定曼德尔布罗集合的公式: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;
}

代码不完整,为了简洁起见,仅显示了主要迭代部分。

所以问题是:有人可以向我解释一下数学与代码的比较吗?

编辑:需要明确的是,我找到了数十种解释数学的资源,以及数十种显示代码的资源,但我找不到将两者结合在一起的良好解释。

For a while now I've been interested in fractals, the math behind them and the visuals they can produce.

I just can't really figure out how to map the mathematical formula to a piece of code that draws the picture.
Given this formula for the mandelbrot set: Pc(z) = z * z + c
How does that compare to the following code:

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

Code is not complete, just showing the main iteration part for brevity.

So the question is: could someone explain to me how the math compares to the code?

Edit: To be clear, I've found dozens of resources explaining the math, and dozens of resources showing code, but nowhere can I find a good explanation of the two combined.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

泡沫很甜 2024-10-01 07:38:42

免责声明。我以前对分形一无所知,但一直想知道,所以我阅读了 wikipedia 文章< /a> 并决定写下我在这里找到的内容。
正如他们所说,如果你想理解某件事,请尝试向别人解释它。 ;)

好的,我们要对复数进行运算。复数实际上是一对(实数)数字,因此,对于我们 PHP 程序员来说,让它成为一个双元素数组。

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

现在我们需要告诉 php 如何对我们的复数进行算术运算。我们需要加法、乘法和 mod(“范数”)运算符。 (请参阅 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 属于 mandelbrot 集合,则返回 true

如果所有点 z = z^2 + c<,则点 c 属于该集合/code> 位于半径为 2 的圆内。

  • 我们从复数 z = (0, 0) 开始。
  • 在每一步中,我们计算 z = z * z + c。
  • 如果z的模> 2 - 也就是说,我们超出了圆圈 - 该点不在集合中,
  • 否则重复该步骤。

为了防止无限循环,请限制最大迭代次数。

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

结果

alt text

当然,这段代码效率低到了极点。它的唯一目的是理解数学概念。

Disclaimer. I didn't know anything about fractals before, but always wanted to know, so I've read the wikipedia article and decided to write what I've found here.
As they say, if you want to understand something, try explaining it to someone else. ;)

Okay, we're going to operate on complex numbers. A complex number is actually a pair of (real) numbers, so, for us php programmers, let it be a two-elements array.

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

Now we need to tell php how to do arithmetics on our complex numbers. We'll need addition, multiplication and the mod ("norm") operator. (see http://mathworld.wolfram.com/topics/ComplexNumbers.html for more details).

    /// 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]);
    }

Now we write a function that returns true if the given (complex) point $c belongs to the mandelbrot set

A point c belongs to the set if all points z = z^2 + c lie inside the circle with the radius 2.

  • We start with the complex number z = (0, 0).
  • On each step we calculate z = z * z + c.
  • If modulus of z > 2 - that is, we're out of the circle - the point is NOT in set
  • Otherwise repeat the step.

To prevent that from looping endlessly, limit the max number of iterations.

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

The rest has nothing to do with math and is quite obvious

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

Result

alt text

Of course, this code is ineffective to the extreme. Its only purpose is to understand the math concept.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文