Mandelbrot集可视化项目:max_iter滑块仅支持低于默认值迭代,修改初始值后显示异常求助
解决Mandelbrot滑块迭代次数显示异常的问题
我明白你的问题了——当你把初始max_iter设为100后,滑块调到30时的显示效果和预期的30次迭代结果不符,但调到100时却正常。这是因为图像的颜色范围(color limits)没有随着迭代次数的更新而同步调整。
问题根源分析
初始绘制时,Matplotlib会根据第一次生成的M数组(此时max_iter=100)自动设置图像的颜色范围为[0, 100]。当你拖动滑块到30时,虽然redraw()函数重新计算了30次迭代的M数组(最大值为30),但图像仍然沿用原来的[0, 100]颜色范围。这就导致新的M值被压缩到颜色谱的前30%,视觉上和直接用30次迭代生成的图像(颜色范围为[0,30])差异巨大。而当滑块回到100时,M的最大值和初始颜色范围匹配,所以显示正常。
修正方案
只需要在redraw()函数中,更新完图像数据后,同步更新颜色范围即可。我们可以用img.set_clim()手动设置范围,或者调用img.autoscale()让Matplotlib自动适配新的M数组范围。
另外,为了避免重复代码,我们可以把初始绘制的逻辑也交给redraw()函数,这样就不需要单独写初始的迭代循环了。
修正后的完整代码如下:
import numpy as np import matplotlib.pyplot as plt from matplotlib.widgets import RadioButtons, Slider fig, ax = plt.subplots() plt.subplots_adjust(left=0.3) # Rozmiary i obszar width, height = 1500, 1500 x_min, x_max = -2, 0.5 y_min, y_max = -1.25, 1.25 # Siatka x = np.linspace(x_min, x_max, width) y = np.linspace(y_min, y_max, height) X, Y = np.meshgrid(x, y) C = X + 1j * Y # Ustawienie slidera dla iteracji axiter = plt.axes([0.25,0.05,0.65,0.03], facecolor="#777777") iter_slider = Slider(axiter, "Ilość iteracji", 1, 100, valinit=30, track_color="#777777") # Wyświetlenie fraktalu - inicjalizujemy puste dane najpierw img = ax.imshow(np.zeros(C.shape), extent=(x_min, x_max, y_min, y_max), cmap='twilight', origin='lower') ax.axis('equal') ax.axis('off') ax.set_title('Fraktal Mandelbrota', pad=10) # RadioButtons do zmiany cmap rax = plt.axes([0.05, 0.4, 0.15, 0.15]) radio = RadioButtons(rax, ('twilight', 'Spectral', 'inferno', 'pink', 'viridis', 'berlin')) rax.set_title('Wybór mapy kolorów', pad=10) def redraw(): max_iter = int(iter_slider.val) Z = np.zeros(C.shape, dtype=complex) M = np.zeros(C.shape, dtype=int) for k in range(max_iter): mask = np.abs(Z) <= 2.0 Z[mask] = Z[mask]**2 + C[mask] M[mask] = k + 1 img.set_data(M) # Dodajemy aktualizację zakresu kolorów img.set_clim(vmin=M.min(), vmax=M.max()) # Lub użyj img.autoscale() aby automatycznie dopasować zakres img.set_cmap(radio.value_selected) fig.canvas.draw_idle() def update(label): redraw() def update_iter(val): redraw() radio.on_clicked(update) iter_slider.on_changed(update_iter) # Wywołujemy redraw raz na początku aby wygenerować początkowy fraktal redraw() plt.show()
额外优化说明
- 移除了冗余的初始
max_iter变量,直接使用滑块的初始值valinit=30来生成初始图像。 - 初始图像用空数组初始化,然后通过
redraw()生成正确的初始帧,避免了重复的迭代代码。 - 添加了
img.set_clim()来确保每次迭代次数变化时,颜色范围都能适配新的M数组,保证视觉效果和迭代次数匹配。
这样修改后,无论你拖动滑块到任何值,显示效果都会和直接用该迭代次数生成的Mandelbrot集一致。
内容的提问来源于stack exchange,提问作者Helewapo
相关产品推荐
相关产品推荐

