我试图严格遵循公式,但是总的来说我只是一个圆圈。我非常了解这是在mandelbrot坐标系中。
for(x=-50;x<50;x++){
for(y=-50;y<50;y++){
// Canvas pixel coordinates to -2,2
var x2 = x * 0.04;
var y2 = y * 0.04;
var i = 0;
var z = 0;
var c = Math.sqrt( x2*x2 + y2*y2 );
while(true) {
if( i > 20 || z > 4.0 ) {
break;
}
z = z*z + c;
i = i + 1;
}
}
}
jsFiddle:
https://jsfiddle.net/d4fj1n63/
最佳答案
您需要执行复杂的算术运算。
var x3 = 0, y3 = 0, k = 0;
while (x3*x3 + y3*y3 < 16 && k++ < 20) {
var tmp = x3*x3 - y3*y3 + x2;
y3 = 2*x3*y3 + y2;
x3 = tmp;
}
公式为zk + 1 = zk2 + c,其中z0 = 0或等效地z1 = c
其中c是当前位置,即c =
x2
+i⋅y2
。我有z =
x3
+i⋅y3
所以z2 =(x3
+i⋅y3
)2 = x3
2 +2⋅i⋅x3
⋅y3
+i2⋅ 2。当i2 = -1时,它简化为z2 =(
y3
2 − x3
2)+i⋅(2⋅y3
⋅x3
),向它们添加y3
即c
和。有关实时演示,请参见https://jsfiddle.net/d5avqq5w/。
您的原始代码在
x2
步骤中丢弃了角度信息,因为在此点之后未使用y2
和z = Math.sqrt( x2*x2 + y2*y2 )
。因此,所得颜色必须与角度无关,即由同心圆组成。The page you gave as a reference处理复数的绝对值。但是Mandelbrot公式的迭代步骤应按原样对复数进行运算,而不是对复数的任何绝对值进行运算,因此在此处遵循该公式是不合适的。
有一个有效的绝对值应用,即在确定是否终止循环(即检测散度)时。 The other page you referenced只是写关于
zn的模量(长度)超过给定值。
而不明确地给出阈值。我使用的阈值为4,但是通过测试z长度的平方是否超过16来避免平方根。这就是代码中
x2
的来源。通常使用2作为阈值(即平方测试为4),但是我觉得使用4会更接近于您拥有的代码,即更适合于强调比较绝对值和比较其平方之间的区别。 。使用4而不是2可能会导致我们稍后检测到差异,从而在循环退出时导致计数器变量的值稍高。请注意,Wikipedia也有一些伪代码,您可能已将其用作起点,并在本文的其余部分中说明了代码中的实值算术如何与复值算术相关。
关于javascript - 我得到了圈子而不是曼德布罗特,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37653369/