mandelbrot 集在大约 2^47 缩放时变得模糊
mandelbrot set gets blurry at around 2^47 zoom
所以我创建了一个简单的 mandelbrot 缩放代码,可以在您单击的位置放大 (lmb) 或缩小 (rmb)。每次单击放大曲线时,渲染的部分都会减半。
问题是无论 maxiter 和 additer 计数有多大,分形似乎总是在 2^47 缩放值左右变得模糊。
Here is what it looks like at 2^49 zoom.
下面是我的代码。谁能告诉我为什么它变得模糊以及我该如何解决这个问题?
import numpy as np
from numba import jit
from matplotlib import pyplot as plt
from matplotlib import colors
from datetime import datetime
width, height, resolution = 8, 8, 100
maxiter = 50 #starting maxiter
additer = 50 #value to add to maxiter upon zoom
xmin, xmax = -2, 1
ymin, ymax = -1.5, 1.5
zoom = 1
color = 'terrain' #https://matplotlib.org/3.1.0/tutorials/colors/colormaps.html
#--------------------------------------------------------------------------------------------------#
@jit
def mandel(c, maxiter):
z = c
for n in range(maxiter):
if (z.real*z.real + z.imag*z.imag)>4: #if z diverges
return n
z = (z * z) + c
return 0
@jit
def mandelbrot(xmin, xmax, ymin, ymax, maxiter):
re = np.linspace(xmin, xmax, width*resolution)
im = np.linspace(ymin, ymax, height*resolution)
answer = np.empty((width*resolution, height*resolution))
for y in range(height*resolution):
for x in range(width*resolution):
answer[x,y] = mandel(re[x] + 1j*im[y], maxiter) #iteration count at (re, im)
return answer
def onclick(event):
global zoom, xmax, xmin, ymax, ymin, maxiter
if event.button == 1:
zoom *= 2
maxiter += additer
elif event.button == 3:
zoom/=2
if maxiter > additer:
maxiter -= additer
#get the re,im coordinate position of mouse
posx = xmin + (xmax-xmin)*event.xdata/(width*resolution)
posy = ymin + (ymax-ymin)*event.ydata/(height*resolution)
print(posx, posy, "iter:", maxiter, "zoom:", zoom)
#change max and min so the coordinate is at the center
xmin = posx - (1.5/zoom)
xmax = posx + (1.5/zoom)
ymin = posy - (1.5/zoom)
ymax = posy + (1.5/zoom)
#recalculate and display
answer = mandelbrot(xmin, xmax, ymin, ymax, maxiter)
plt.imshow(answer.T, cmap=color)
plt.draw()
#for benchmarking
'''a = datetime.now()
mandelbrot(xmin, xmax, ymin, ymax, zoom)
print(datetime.now() - a)'''
answer = mandelbrot(xmin, xmax, ymin, ymax, maxiter)
plt.connect('button_press_event', onclick)
plt.imshow(answer.T, cmap=color)
plt.axis('off')
plt.tight_layout()
plt.show()
低于 2^-47 的图像宽度以及您想要缩放的大部分区域,2 个相邻像素之间的差异(考虑 1000 像素宽度)将在标准双精度下产生 0。
要更深入,您需要使用 multi-precision 算术包(十进制,gmpy2)计算至少一个点(参考轨道)。对于剩余的像素,为了使计算时间保持在可接受的范围内,您通常可以仅迭代增量 - 有一些超出此问题范围的警告。
有关使用 python / numpy 实现的示例,您可以查看类似 fractalshades 的包。文档的图库部分包含 Mandelbrot 和 Burning Ship 的 deep-zooms 到 10^-2000 的示例:
https://gbillotey.github.io/Fractalshades/examples/index.html
免责声明:我是 fractalshades 的作者。
所以我创建了一个简单的 mandelbrot 缩放代码,可以在您单击的位置放大 (lmb) 或缩小 (rmb)。每次单击放大曲线时,渲染的部分都会减半。
问题是无论 maxiter 和 additer 计数有多大,分形似乎总是在 2^47 缩放值左右变得模糊。 Here is what it looks like at 2^49 zoom.
下面是我的代码。谁能告诉我为什么它变得模糊以及我该如何解决这个问题?
import numpy as np
from numba import jit
from matplotlib import pyplot as plt
from matplotlib import colors
from datetime import datetime
width, height, resolution = 8, 8, 100
maxiter = 50 #starting maxiter
additer = 50 #value to add to maxiter upon zoom
xmin, xmax = -2, 1
ymin, ymax = -1.5, 1.5
zoom = 1
color = 'terrain' #https://matplotlib.org/3.1.0/tutorials/colors/colormaps.html
#--------------------------------------------------------------------------------------------------#
@jit
def mandel(c, maxiter):
z = c
for n in range(maxiter):
if (z.real*z.real + z.imag*z.imag)>4: #if z diverges
return n
z = (z * z) + c
return 0
@jit
def mandelbrot(xmin, xmax, ymin, ymax, maxiter):
re = np.linspace(xmin, xmax, width*resolution)
im = np.linspace(ymin, ymax, height*resolution)
answer = np.empty((width*resolution, height*resolution))
for y in range(height*resolution):
for x in range(width*resolution):
answer[x,y] = mandel(re[x] + 1j*im[y], maxiter) #iteration count at (re, im)
return answer
def onclick(event):
global zoom, xmax, xmin, ymax, ymin, maxiter
if event.button == 1:
zoom *= 2
maxiter += additer
elif event.button == 3:
zoom/=2
if maxiter > additer:
maxiter -= additer
#get the re,im coordinate position of mouse
posx = xmin + (xmax-xmin)*event.xdata/(width*resolution)
posy = ymin + (ymax-ymin)*event.ydata/(height*resolution)
print(posx, posy, "iter:", maxiter, "zoom:", zoom)
#change max and min so the coordinate is at the center
xmin = posx - (1.5/zoom)
xmax = posx + (1.5/zoom)
ymin = posy - (1.5/zoom)
ymax = posy + (1.5/zoom)
#recalculate and display
answer = mandelbrot(xmin, xmax, ymin, ymax, maxiter)
plt.imshow(answer.T, cmap=color)
plt.draw()
#for benchmarking
'''a = datetime.now()
mandelbrot(xmin, xmax, ymin, ymax, zoom)
print(datetime.now() - a)'''
answer = mandelbrot(xmin, xmax, ymin, ymax, maxiter)
plt.connect('button_press_event', onclick)
plt.imshow(answer.T, cmap=color)
plt.axis('off')
plt.tight_layout()
plt.show()
低于 2^-47 的图像宽度以及您想要缩放的大部分区域,2 个相邻像素之间的差异(考虑 1000 像素宽度)将在标准双精度下产生 0。
要更深入,您需要使用 multi-precision 算术包(十进制,gmpy2)计算至少一个点(参考轨道)。对于剩余的像素,为了使计算时间保持在可接受的范围内,您通常可以仅迭代增量 - 有一些超出此问题范围的警告。
有关使用 python / numpy 实现的示例,您可以查看类似 fractalshades 的包。文档的图库部分包含 Mandelbrot 和 Burning Ship 的 deep-zooms 到 10^-2000 的示例: https://gbillotey.github.io/Fractalshades/examples/index.html
免责声明:我是 fractalshades 的作者。