题
我没有任何分形编程经验。当然,我看过著名的曼德尔布罗图像等。
你能为我提供简单的分形算法吗?
编程语言其实并不重要,但我最熟悉的是actionscript、C#、Java。
我知道如果我用谷歌搜索分形,我会得到很多(复杂的)信息,但我想从一个简单的算法开始并使用它。
也欢迎提出改进基本算法的建议,例如如何使它们具有可爱的颜色等。
解决方案
对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)矩形区域转换为屏幕坐标。
其他提示
你确实应该从 曼德尔布罗特集, ,并了解它到底是什么。
其背后的想法相对简单。您从复杂变量的函数开始
f(z) = z2 + C
其中 z 是复数 多变的 C 是一个复数 持续的. 。现在从 z = 0 开始迭代,即你计算z1 = f(0), z2 = f(z1), z3 = f(z2) 等等。这些常数 C 的集合,其中序列 z1, z2, z3, ...是 有界的, , IE。它不会趋于无穷大,是曼德尔布罗特集(维基百科页面上图中的黑色集合)。
在实践中,要绘制 Mandelbrot 集,您应该:
- 在复平面中选择一个矩形(例如,从点 -2-2i 到点 2+2i)。
- 用合适的矩形点网格(例如 400x400 点)覆盖矩形,这些点将映射到显示器上的像素。
- 对于每个点/像素,令 C 为该点,计算相应迭代序列 z 的 20 项1, z2, z3, ...并检查它是否“趋向无穷大”。实际上,您可以在迭代时检查 20 项中一项的绝对值是否大于 2(如果其中一项大于 2,则保证后续项无界)。如果某个 z_k 这样做,则序列“趋向无穷大”;否则,您可以将其视为有界。
- 如果某个点C对应的序列是有界的,则将图片上对应的像素画成黑色(因为它属于Mandelbrot集)。否则,用另一种颜色绘制它。如果您想获得乐趣并生成漂亮的图,请根据 abs(第 20 项)的大小用不同的颜色绘制它。
关于分形的令人震惊的事实是我们如何获得一个极其复杂的集合(特别是, 边境 曼德尔布罗特集)来自简单且明显无害的要求。
享受!
如果复杂数字让您头痛,可以使用L系统制定各种各样的分形。这需要几层交互,但每一层都很有趣。
首先你需要一只乌龟。前进,后退,左,右,上笔,下笔。即使没有驱动它的L系统,使用乌龟几何体的龟图形也有很多有趣的形状。搜索“LOGO图形”或“龟图形”。完整的 LOGO 系统实际上是 Lisp 编程环境使用不明显的剑桥波兰语语法。但是你不必走近那么远,就可以使用乌龟概念获得一些漂亮的照片。
然后你需要一个层来执行L系统。 L系统与邮政系统和 Semi-Thue系统,和virii一样,它们跨越了图灵完整性的边界。概念是字符串重写。它可以实现为宏扩展或带有额外控件的过程集来绑定递归。如果使用宏扩展(如下例所示),您仍然需要一个过程设置来将符号映射到turtle命令,以及迭代遍历字符串或数组以运行编码的乌龟程序的过程。对于有界递归过程集(例如),您将乌龟命令嵌入到过程中,并且为每个过程添加递归级别检查或将其分解为处理函数。
以下是使用宏扩展和非常简略的海龟命令集的后记中的毕达哥拉斯树的示例。有关python和mathematica中的一些示例,请参阅我的代码高尔夫挑战。
有一本名为 Chaos and Fractals 的好书,其中包含简单的示例代码在每一章的最后,实现一些分形或其他例子。很久以前,当我阅读那本书时,我将每个示例程序(在某些基本方言中)转换为在网页上运行的Java小程序。小程序在这里: http://hewgill.com/chaos-and-fractals/
其中一个示例是简单的Mandelbrot实现。
要学习的另一个优秀分形是Sierpinski Triangle Fractal。
基本上,绘制三角形的三个角(等边是优选的,但任何三角形都可以工作),然后在其中一个角上开始一个点P.随意将P移动到三个角中的任意一个,并在那里画一个点。再次将P移向任意一个角落,画出并重复。
您认为随机运动会产生随机结果,但事实并非如此。
Sierpinski三角形和Koch曲线是特殊类型的火焰分形。火焰分形是一种非常通用的迭代函数系统,因为它使用非线性函数。
IFS的算法:es如下:
以随机点开头。
重复以下几次(至少100万,取决于最终图像大小):
<代码> 将N个预定义变换(矩阵变换或类似变换)中的一个应用于该点。一个例子是将每个坐标乘以0.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);
}
我认为您可能不会将分形视为算法或编程。分形是一个概念!这是一个详细模式重复的数学概念。
因此,您可以使用不同的方法以多种方式创建分形,如下图所示。
选择一种方法,然后研究如何实施它。这四个示例是使用 Marvin Framework 实现的。源代码可用此处
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)。您必须使用复杂类型,或在循环中包含该计算。
这是一个简单易懂的Java代码,用于mandelbrot和其他分形示例
http://code.google.com/p/gaima/wiki/VLFImages
只需下载BuildFractal.jar以在Java中测试它并使用命令运行:
java -Xmx1500M -jar BuildFractal.jar 1000 1000默认MANDELBROT
源代码也可以免费下载/浏览/编辑/扩展。
嗯,简单和图形吸引力并不是真正相辅相成。如果您对编程分形很认真,我建议您阅读迭代函数系统以及在渲染它们时所取得的进展。
上面的人正在使用发现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
}
有时我会将分形作为乐趣和挑战来编程。您可以在此处找到它们。代码是使用P5.js库在Javascript中编写的,可以直接从HTML源代码中读取。
对于那些我看过算法非常简单的人,只需找到核心元素然后反复重复。我用递归函数来做,但可以用不同的方式完成。