如何'放大'Mandelbrot集的一部分?

时间:2009-02-07 18:22:48

标签: python math mandelbrot

我创建了一个Python文件来生成Mandelbrot集图像。原始数学代码不是我的,所以我不理解它 - 我只是对其进行了大量修改,使其速度提高了约250倍(线程规则!)。

无论如何,我想知道如何修改代码的数学部分以使其呈现一个特定的位。这是数学部分:

for y in xrange(size[1]):
        coords = (uleft[0] + (x/size[0]) * (xwidth),uleft[1] - (y/size[1]) * (ywidth))
        z = complex(coords[0],coords[1])
        o = complex(0,0)
        dotcolor = 0  # default, convergent
        for trials in xrange(n):
            if abs(o) <= 2.0:
                o = o**2 + z
            else:
                dotcolor = trials
                break  # diverged
        im.putpixel((x,y),dotcolor)

尺寸定义:

size1 = 500
size2 = 500
n=64
box=((-2,1.25),(0.5,-1.25))
plus = size[1]+size[0]
uleft = box[0]
lright = box[1]
xwidth = lright[0] - uleft[0]
ywidth = uleft[1] - lright[1]

我需要修改什么才能使其呈现集合的某个部分?

2 个答案:

答案 0 :(得分:14)

该行:

box=((-2,1.25),(0.5,-1.25))

是定义正在渲染的坐标空间区域的位,因此您只需要更改此行。第一个坐标对是区域的左上角,第二个是右下角。

从图像中获取新坐标应该非常简单。你有两个坐标系,你的“图像”系统大小为100x100像素,原点为(0,0)。而你的“复杂”平面坐标系由“盒子”定义。对于X:

X_complex=X_complex_origin+(X_image/X_image_width)*X_complex_width

答案 1 :(得分:4)

了解如何执行此操作的关键是了解coords =行正在做什么:

coords = (uleft[0] + (x/size[0]) * (xwidth),uleft[1] - (y/size[1]) * (ywidth))

实际上,您循环的xy值对应于屏幕上像素的坐标,正在被转换到正在查看的复平面上的对应点。这意味着(0,0)屏幕坐标将转换为查看(-2,1.25)的左上区域,(1,0)将相同,但移动距离的1/500(假设500像素) -20.5 x坐标之间的宽度窗口。

这正是该行正在做的事情 - 我将仅使用更多说明性变量名称扩展X坐标位来表示:

mandel_x = mandel_start_x + (screen_x / screen_width) * mandel_width

mandel_变量指的是复平面上的坐标,screen_变量指的是被绘制像素的屏幕坐标。)

如果你想让屏幕的一个区域放大,你想要完全相同:取左上和右下区域的屏幕坐标,将它们转换为复平面坐标,并使那些新的uleft和lright变量。即放大由屏幕坐标(x1,y1)...(x2,y2)分隔的框,使用:

new_uleft = (uleft[0] + (x1/size[0]) * (xwidth), uleft[1] - (y1/size[1]) * (ywidth))
new_lright = (uleft[0] + (x2/size[0]) * (xwidth), uleft[1] - (y2/size[1]) * (ywidth))

(显然你需要根据新坐标重新计算大小,xwidth,ywidth和其他因变量)

如果你很好奇,mandelbrot集背后的数学并不复杂(只是复杂)。 它所做的只是采用一个特定的坐标,将其视为一个复数,然后反复对其进行平方并将原始数字添加到其中。

对于某些数字,这样做会导致结果发散,在重复此过程时不断向无穷大方向发展。对于其他人来说,它总是会保持在一定水平以下(例如,显然(0.0,0.0)在这个过程中永远不会变得更大.mandelbrot集合(黑色区域)是那些没有发散的坐标。已经证明,如果任何数字都高于5的平方根,它会发散 - 你的代码只是使用2.0作为sqrt(5)(〜2.236)的近似值,但这不会太明显差异。

通常,发散的区域会与过程的迭代次数一起绘制,超过此值(代码中的trials变量),这将产生彩色区域。