我正在尝试使用OpenGL可视化Mandelbrot设置,并且在光滑着色时发现了非常奇怪的行为。
我们假设,对于当前的复数值C
,当n
被证明超过2时,算法在Z
次迭代后已经转义。
我按照这样编程着色部分:
if(n==maxIterations){
color=0.0; //0.0 is black in OpenGL when put to each channel of RGB
//Points in M-brot set are colored black.
} else {
color = (n + 1 - log(log(abs(Z)))/log(2.0) )/maxIterations;
//continuous coloring algorithm, color is between 0.0 and 1.0
//Points outside M-brot set are colored depending of their absolute value,
//from brightest near the edge of set to darkest far away from set.
}
glColor3f(color ,color ,color );
//OpenGL-command for making RGB-color from three channel values.
问题是,这只是效果不好。一些平滑是显而易见的,但它并不完美。
但是当我添加两个额外的迭代时(只是发现这个没有解释的地方)
Z=Z*Z+C;
n++;
在“else”分支中,在计算颜色之前,图片出来绝对,优雅流畅。
为什么会这样?为什么在检查要设置的点之后,我们是否需要在着色部分中进行额外的迭代?
答案 0 :(得分:3)
我实际上并不确定,但我猜测它与数字(log(log(n))
)的日志日志有点相关的事实有关对于“小”数字n
不稳定的事情,其中“小”在这种情况下意味着接近2.如果你的Z
刚刚逃脱,它接近2.如果你继续迭代,你得到(快速)从2开始越来越远,log(log(abs(Z)))
稳定,从而为您提供更可预测的价值......然后,它会为您提供更平滑的价值。
示例数据,任意选择:
n Z.real Z.imag |Z| status color
-- ----------------- ----------------- ----------- ------- -----
0 -0.74 -0.2 0.766551 bounded [nonsensical]
1 -0.2324 0.096 0.251447 bounded [nonsensical]
2 -0.69520624 -0.2446208 0.736988 bounded [nonsensical]
3 -0.31652761966 0.14012381319 0.346157 bounded [nonsensical]
4 -0.65944494902 -0.28870611409 0.719874 bounded [nonsensical]
5 -0.38848357953 0.18077157738 0.428483 bounded [nonsensical]
6 -0.62175887162 -0.34045357891 0.708867 bounded [nonsensical]
7 -0.46932454495 0.22336006613 0.519765 bounded [nonsensical]
8 -0.56962419064 -0.40965672279 0.701634 bounded [nonsensical]
9 -0.58334691196 0.26670075833 0.641423 bounded [nonsensical]
10 -0.4708356748 -0.51115812757 0.69496 bounded [nonsensical]
11 -0.77959639873 0.28134296385 0.828809 bounded [nonsensical]
12 -0.2113833184 -0.63866792284 0.67274 bounded [nonsensical]
13 -1.1032138084 0.070007489775 1.10543 bounded 0.173185134517425
14 0.47217965836 -0.35446645882 0.590424 bounded [nonsensical]
15 -0.64269284066 -0.53474370285 0.836065 bounded [nonsensical]
16 -0.6128967403 0.48735189882 0.783042 bounded [nonsensical]
17 -0.60186945901 -0.79739278033 0.999041 bounded [nonsensical]
18 -1.0135884004 0.75985272263 1.26678 bounded 0.210802091344997
19 -0.29001471459 -1.7403558114 1.76435 bounded 0.208165835763602
20 -3.6847298156 0.80945758785 3.77259 ESCAPED 0.205910029166315
21 12.182012228 -6.1652650168 13.6533 ESCAPED 0.206137522227716
22 109.65092918 -150.41066764 186.136 ESCAPED 0.20614160700086
23 -10600.782669 -32985.538932 34647.1 ESCAPED 0.20614159039676
24 -975669186.18 699345058.7 1.20042e+09 ESCAPED 0.206141590396481
25 4.6284684972e+17 -1.3646588486e+18 1.44101e+18 ESCAPED 0.206141590396481
26 -1.6480665667e+36 -1.263256098e+36 2.07652e+36 ESCAPED 0.206141590396481
注意颜色值在[20,22]中的n处仍然波动多少,在n = 23时变得稳定,并且从n = 24开始一致。请注意,Z值在半径为2的圆圈外面有一个边界,它限制了Mandelbrot集。
我实际上没有做足够的数学运算来确定这实际上是一个可靠的解释,但那是我的猜测。
答案 1 :(得分:3)
由于我刚刚制作了相同的程序,而且作为优秀的数学家,我会解释原因,希望这一点很清楚。
如果说在k次迭代后,带有种子C的序列已经转义。
由于函数it self被定义为Limit,因为迭代变为无穷大,所以得到接近k的东西并不是那么好。这就是原因。
正如我们所知,在2之后,序列变为无穷大,让我们考虑一些迭代T,其中z变得足够大。考虑到它C将是非常小的,因为通常你看2轴的[-2,2]和[-1.5,1.5]中的集合。所以在T + 1迭代中,z将是~~ z ^ 2,并且在这种情况下很容易检查| z | T + 1将是~~ | z | ^ 2的前一个。
对于第K次迭代,我们的函数是log(| z |)/ 2 ^ k。在我们看的情况下 很容易看出,在T + 1迭代中它将是~~ http://www.equationsheet.com/latexrender/pictures/e8ab9446e81684037708209bf8f3a297.gif 这是T迭代的功能。
换句话说是| z |变得比种子C“显着”大,功能变得越来越稳定。你不想使用接近逃避迭代k的迭代,因为实际上Z将接近2,并且因为它依赖于C,它可能与它相比并不是非常小,因此你不会接近极限。 / p>
As | C |实际上在第一次逃避迭代时接近2,你将远离极限。另一方面,如果您选择在| Z |> 100之后进行转义绑定,或者只需要多次迭代,您将获得更加稳定。
希望对这个问题感兴趣的人能够很好地回答他。
答案 2 :(得分:2)
现在似乎“额外的迭代”想法没有令人信服的公式,如果不计算它只是有用的事实。
在维基百科的一篇旧版本的Mandelbrot文章中,有关于连续着色的文章:
其次,建议少数 进行额外的迭代以便z 可以成长如果你停止迭代为 一旦z逃脱,就有了 平滑的可能性 算法不起作用。
总比没有好。