如何编程分形?


77

我没有分形编程的经验。当然,我已经看过著名的Mandelbrot图片等等。

您能为我提供一些简单的分形算法吗?

编程语言并不重要,但是我最熟悉动作脚本,C#和Java。

我知道,如果我使用Google分形进行搜索,会得到很多(复杂的)信息,但是我想从一个简单的算法开始并进行研究。

也欢迎提出对基本算法进行改进的建议,例如如何将它们制成可爱的颜色等等。


6
基于此问题的答案,我在github上使用canvas元素在javascript中使用了动画的mandelbrot创建了要点。gist.github.com/1853604
Sander Versluys

Answers:


58

对Mandelbrot进行编程很容易。
我的快速n脏代码在下面(不保证没有错误,但是轮廓不错)。

轮廓如下: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)矩形区域转换为屏幕坐标。


28

您确实应该从Mandelbrot集开始,并了解它的真正含义。

其背后的想法相对简单。您从复杂变量的功能开始

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集(在Wikipedia页面上图中的黑色集)。

在实践中,要绘制曼德布罗集,您应该:

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

分形的惊人事实是,我们如何从简单且显然无害的需求中获得极其复杂的集合(尤其是Mandelbrot集的边界)。

请享用!


10

如果复数使您头疼,则可以使用L系统来创建各种各样的分形。这需要几层相互作用,但是每一层本身都很有趣。

首先,你需要一只乌龟。前进,后退,左,右,上笔,下笔。即使没有L系统驱动,使用乌龟几何图形也可以用乌龟图形制作许多有趣的形状。搜索“ LOGO图形”或“ Turtle图形”。完整的LOGO系统实际上是使用未括号化的Cambridge Polish语法的Lisp编程环境。但是,使用乌龟概念,您不必走得太远就能得到一些漂亮的照片。

然后,您需要一个层来执行L系统。L系统与Post系统Semi-Thue系统相关,并且像virii一样,它们跨越图灵完备性边界。这个概念是字符串重写。可以将其实现为宏扩展或带有额外控件以限制递归的过程集。如果使用宏扩展(如下面的示例所示),您仍然需要一个过程来设置将符号映射到turtle命令的过程,以及一个遍历字符串或数组以运行编码的turtle程序的过程。对于有界递归过程集(例如),您将turtle命令嵌入到过程中,然后向每个过程添加递归级别检查,或者将其分解为处理函数。

这是使用宏扩展和一组非常简短的turtle命令在后记中的毕达哥拉斯树的示例。有关python和mathematica中的一些示例,请参阅我的代码golf Challenge

ps l系统毕达哥拉斯树luser-droog


该图像是使用此处描述的技术创建的,该技术将一小段代码与一个小插图结合在一起。
luser droog

8

有一本很棒的书,叫做《混沌与分形》,在每章的末尾都有简单的示例代码,实现了一些分形或其他示例。很久以前,当我读这本书时,我将每个示例程序(以某种基本的方言)转换为可在网页上运行的Java小程序。小程序在这里:http : //hewgill.com/chaos-and-fractals/

示例之一是简单的Mandelbrot实现。


6

另一个要学习的出色分形是Sierpinski三角分形。

基本上,绘制一个三角形的三个角(首选等边的,但是任何三角形都可以),然后在这些角之一处开始一个点P。将P随机移动到三个角中的任意一个,并在那里画一个点。再次将P移到任意随机角的一半处,绘制并重复。

您可能会认为随机运动会产生随机结果,但实际上不会。

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


2
这实际上是IFS的基础,可以视为您描述的方法的概括。
Algorias

6

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

IFS的算法如下:

Start with a random point.

重复以下多次(至少一百万,具体取决于最终图像大小):

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

我将从简单的东西开始,例如科赫雪花。这是一个简单的过程,先进行一行转换,然后递归地重复该过程,直到看起来整洁。

超级简单的操作,例如获得2点(一条线)并添加一个3rd点(形成一个角),然后在创建的每个新部分上重复。

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

5

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

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

在此处输入图片说明

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


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-b * b + 2 * a b i)。您将必须使用复杂的类型,或者将该计算包括在循环中。


1
您确定value.absolutevalue <10亿吗???一旦value.absolutevalue超过2,它将“转义”并变为无穷大。因此,您只需要测试多达2个,而不需要测试10亿个。
abelenky

3

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

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

只需下载BuildFractal.jar即可在Java中对其进行测试并使用以下命令运行:

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

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



1

上面的人都在寻找sierpinski和Koch的中点,我更建议复制形状,缩放形状,然后翻译它们以实现“分形”效果。Java中用于sierpinski的伪代码如下所示:

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
    }

1

有时,我为了娱乐和挑战而编写分形。你可以在这里找到他们。该代码使用P5.js库以Javascript编写,可以直接从HTML源代码中读取。

对于那些我已经看到的算法,它们非常简单,只需找到核心元素,然后一遍又一遍地重复即可。我使用递归函数来完成此操作,但是可以通过其他方式完成。


1

这是使用普通的javascript和HTML为Mandelbrot分形编写的codepen

希望很容易理解代码。

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

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

在此处输入图片说明

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.