如何编写分形图?

时间:2009-01-08 21:07:22

标签: theory fractals

我对编程分形没有任何经验。当然,我已经看过着名的Mandelbrot图像等。

你能为我提供简单的分形算法吗?

编程语言并不重要,但我最熟悉的是actionscript,C#,Java。

我知道如果我谷歌分形,我会得到很多(复杂的)信息,但我想从一个简单的算法开始并使用它。

也欢迎改进基本算法的建议,比如如何用那些可爱的颜色制作它们。

13 个答案:

答案 0 :(得分:53)

对Mandelbrot进行编程非常简单 我的快速脏代码如下(不保证没有错误,但是一个好的大纲)。

这是大纲: Mandelbrot集完全位于复杂网格内,半径为2。

因此,首先扫描该矩形区域中的每个点。 每个点代表一个复数(x + yi)。 迭代这个复数:

[new value] = [old-value]^2 + [original-value]同时跟踪两件事情:

1。)迭代次数

2。)[新值]与原点的距离。

如果达到最大迭代次数,则表示已完成。 如果与原点的距离大于2,那么就完成了。

完成后,根据您完成的迭代次数为原始像素着色。 然后转到下一个像素。

    public void MBrot()
    {
        float epsilon = 0.0001; // The step size across the X and Y axis
        float x;
        float y;
        int maxIterations = 10; // increasing this will give you a more detailed fractal
        int maxColors = 256; // Change as appropriate for your display.

        Complex Z;
        Complex C;
        int iterations;
        for(x=-2; x<=2; x+= epsilon)
        {
            for(y=-2; y<=2; y+= epsilon)
            {
                iterations = 0;
                C = new Complex(x, y);
                Z = new Complex(0,0);
                while(Complex.Abs(Z) < 2 && iterations < maxIterations)
                {
                    Z = Z*Z + C;
                    iterations++;
                }
                Screen.Plot(x,y, iterations % maxColors); // depending on the number of iterations, color a pixel.
            }
        }
    }

遗漏的一些细节是:

1。)准确了解复数的平方是什么以及如何计算它。

2。)弄清楚如何将(-2,2)矩形区域转换为屏幕坐标。

答案 1 :(得分:26)

你应该从Mandelbrot set开始,并了解它到底是什么。

背后的想法相对简单。您从复杂变量

的函数开始
  

f(z)= z 2 + C

其中z是复杂的变量,C是复杂的常量。现在你从z = 0开始迭代它,即你计算z 1 = f(0),z 2 = f(z 1 ) ,z 3 = f(z 2 ),依此类推。序列z 1 ,z 2 ,z 3 ,......的那些常数C的集合有界,即它没有进入无限,是Mandelbrot集合(维基百科页面图中的黑色集合)。

在实践中,要画出Mandelbrot套装,你应该:

  • 在复杂平面中选择一个矩形(例如,从点-2-2i到点2 + 2i)。
  • 使用合适的矩形网格点(例如,400x400点)覆盖矩形,该网格将映射到显示器上的像素。
  • 对于每个点/像素,让C为该点,计算相应的迭代序列z 1 的20个项,z 2 ,z 3 ,...并检查它是否“无限”。在实践中,您可以在迭代时检查20个术语之一的绝对值是否大于2(如果其中一个术语确实存在,则后续术语保证无限制)。如果有一些z_k,则序列“变为无穷大”;否则,你可以认为它是有界的。
  • 如果对应于某个点C的序列是有界的,则将图片上的相应像素绘制成黑色(因为它属于Mandelbrot集)。否则,请用另一种颜色绘制。如果你想获得乐趣并制作漂亮的情节,可以根据abs(20日)的大小以不同颜色绘制它。

关于分形的惊人事实是我们如何从容易且明显无害的要求中获得极其复杂的集合(特别是Mandelbrot集合的前沿)。

享受!

答案 2 :(得分:8)

有一本名为Chaos and Fractals的好书,在每一章末尾都有简单的示例代码,用于实现某些分形或其他示例。很久以前,当我阅读那本书时,我将每个示例程序(在某些基本方言中)转换为在网页上运行的Java小程序。小程序位于:http://hewgill.com/chaos-and-fractals/

其中一个示例是简单的Mandelbrot实现。

答案 3 :(得分:6)

要学习的另一个优秀分形是Sierpinski Triangle Fractal。

基本上,绘制三角形的三个角(等边是优选的,但任何三角形都可以工作),然后在其中一个角上开始一个点P.随意将P移动到三个角中的任意一个,并在那里画一个点。再次将P移向任意一个角落,画出并重复。

您认为随机运动会产生随机结果,但事实并非如此。

参考:http://en.wikipedia.org/wiki/Sierpinski_triangle

答案 4 :(得分:6)

Sierpinski三角形和Koch曲线是特殊类型的火焰分形。火焰分形是一种非常通用的迭代函数系统,因为它使用非线性函数。

IFS的算法:es如下:

Start with a random point.

重复以下几次(至少100万,取决于最终图像大小):

Apply one of N predefined transformations (matrix transformations or similar) to the point. An example would be that multiply each coordinate with 0.5. Plot the new point on the screen.

如果该点位于屏幕之外,请在屏幕内随机选择一个新点。

如果你想要漂亮的颜色,让颜色取决于最后使用的变换。

答案 5 :(得分:5)

我会从简单的事情开始,比如Koch Snowflake。这是一个简单的过程,一条线并对其进行转换,然后递归地重复该过程,直到它看起来很整洁。

超级简单的东西,比如取2个点(一条线)并添加第三个点(制作一个角),然后重复创建的每个新部分。

fractal(p0, p1){
    Pmid = midpoint(p0,p1) + moved some distance perpendicular to p0 or p1;
    fractal(p0,Pmid);
    fractal(Pmid, p1);
}

答案 6 :(得分:4)

我认为您可能不会将分形看作算法或编程的东西。分形是一个概念!这是一个详细模式重复的数学概念。

因此,您可以使用不同的方法以多种方式创建分形,如下图所示。

enter image description here

选择一种方法,然后研究如何实施它。这四个示例是使用Marvin Framework实现的。源代码可用here

答案 7 :(得分:3)

mandelbrot集是通过重复计算函数直到它溢出(某个已定义的限制),然后检查溢出所花费的时间来生成的。

伪代码:

MAX_COUNT = 64 // if we haven't escaped to infinity after 64 iterations, 
               // then we're inside the mandelbrot set!!!

foreach (x-pixel)
  foreach (y-pixel)
    calculate x,y as mathematical coordinates from your pixel coordinates
    value = (x, y)
    count = 0
    while value.absolutevalue < 1 billion and count < MAX_COUNT
        value = value * value + (x, y)
        count = count + 1

    // the following should really be one statement, but I split it for clarity
    if count == MAX_COUNT 
        pixel_at (x-pixel, y-pixel) = BLACK
    else 
        pixel_at (x-pixel, y-pixel) = colors[count] // some color map. 

注意:

值是一个复数。将一个复数(a + b i)平方给出(a a-b * b + 2 * a b i)。您必须使用复杂类型,或在循环中包含该计算。

答案 8 :(得分:3)

这是一个简单易懂的Java代码,用于mandelbrot和其他分形示例

http://code.google.com/p/gaima/wiki/VLFImages

只需下载BuildFractal.jar以在Java中测试它并使用命令运行:

java -Xmx1500M -jar BuildFractal.jar 1000 1000默认MANDELBROT

源代码也可以免费下载/浏览/编辑/扩展。

答案 9 :(得分:2)

嗯,简单和图形吸引力并不是真正相辅相成。如果您对编程分形很认真,我建议您阅读迭代函数系统以及在渲染它们时所取得的进展。

http://flam3.com/flame_draves.pdf

答案 10 :(得分:1)

上面的人正在为sierpinski和Koch使用发现中点,我更推荐复制形状,缩放它们,然后翻译它们以实现“分形”效果。 用于sierpinski的Java中的伪代码看起来像这样:

public ShapeObject transform(ShapeObject originalCurve)
    {
        Make a copy of the original curve
        Scale x and y to half of the original
        make a copy of the copied shape, and translate it to the right so it touches the first copied shape
        make a third shape that is a copy of the first copy, and translate it halfway between the first and second shape,and translate it up
        Group the 3 new shapes into one
        return the new shape
    }

答案 11 :(得分:1)

有时我会将分形作为乐趣和挑战来编程。你可以找到它们here。代码是使用P5.js库在Javascript中编写的,可以直接从HTML源代码中读取。

对于那些我看过算法非常简单的人,只需找到核心元素然后反复重复。我用递归函数来做,但可以用不同的方式完成。

答案 12 :(得分:0)

这里是a codepen that I wrote,用于使用纯Javascript和HTML的Mandelbrot分形。

希望很容易理解代码。

最复杂的部分是缩放和平移坐标系。制作彩虹调色板也很复杂。

function mandel(x,y) {
  var a=0; var b=0;
  for (i = 0; i<250; ++i) {
    // Complex z = z^2 + c
    var t = a*a - b*b;
    b = 2*a*b;
    a = t;
    a = a + x;
    b = b + y;
    var m = a*a + b*b;
    if (m > 10)  return i;
  }
  return 250;
}

enter image description here