如何“放大”Mandelbrot集合的一部分?

5
我创建了一个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]

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

我很怀念你使用线程来加速代码的方式,因为Python字节码在线程上无法同时执行,这是由于GIL所致。 - nosklo
2个回答

15

这行代码:

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

这一部分定义了正在呈现的坐标空间的区域,因此您只需要更改这一行。第一个坐标对是区域的左上角,第二个坐标对是右下角。

从图像中获取新的坐标应该很简单。您有两个坐标系:一个大小为100x100像素,原点位于(0,0)的“图像”系统和由“box”定义的“复数”平面坐标系。对于X:

X_complex=X_complex_origin+(X_image/X_image_width)*X_complex_width

谢谢,伙计!我怎么把这些转换成X和Y的值呢?有可能吗? - Lobe
盒子包含两个x,y对:box=((x,y),(x,y)) 这回答了你的问题吗? - Ian Hopkinson
啊,对不起,我误解了。我的意思是,如果我有完整渲染图像的尺寸(比如100x100),我该如何将100x100图像的某个部分的x和y值转换为一个“缩放”的x和y值呢?我怀疑这是不可能的 - 谢谢你的回答! - Lobe
这应该相当简单。你有两个坐标系,一个是100x100像素大小的“图像”系统,原点在(0,0)处。另一个是由“box”定义的“复杂”平面坐标系。对于X: X_complex=X_complex_origin+(X_image/X_image_width)*X_complex_width 也许我应该编辑我的答案! - Ian Hopkinson
谢谢!你能否更新一下你的答案,以防我需要回来查看而忘记了评论! - Lobe
计算曼德博集合让我想起了我遥远的计算机过去的美好回忆! - Ian Hopkinson

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和其他相关变量)

如果您好奇,曼德布罗特集合背后的数学并不复杂(只是复杂的数学)。 所有它所做的就是取一个特定的坐标,将其视为一个复数,然后重复平方并加上原始数字。对于某些数字来说,这样做会导致结果发散,随着您重复这个过程而不断增长,趋向于无穷大。对于其他数字,它将始终保持在某个水平以下(例如,显然(0.0,0.0)在此过程中永远不会变得更大)。曼德布罗特集合(黑色区域)是那些不发散的坐标。已经证明,如果任何数字超过5的平方根,它将发散-您的代码只是使用2.0作为其对sqrt(5)(〜2.236)的近似值,但这不会产生太多明显的差异。

通常,发散的区域会用它们超过此值所需的过程的迭代次数(您代码中的“尝试”变量)进行绘制,这就是产生彩色区域的原因。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接