实现Mandelbrot集的平滑着色

时间:2019-05-07 12:10:53

标签: javascript colors fractals mandelbrot

重新创建我的Mandelbrot集颜色的方法我很难用JavaScript实现它。我目前使用常见的“转义时间”算法:

 for(px = 0; px < a; px+=scale){
   for(py = 0; py < b; py+=scale){
    x0 = panX + px/zm;
    y0 = panY + py/zm;

    var x = 0;
    var y = 0;

    var i = 0;
     var xtemp;

     var xSquare = x*x;
     var ySquare = y*y;

    while (x*x + y*y <= 4  &&  i < maxI) {
      xtemp = x*x - y*y + x0
      y = 2*x*y + y0
      x = xtemp
          i += 1;
    }

    //coloring
    var shade = pallete.colourAt(i);
    c.fillStyle = "#"+shade;
    c.fillRect(px,py,scale, scale);
    }
 }

这里是full code.的一部分,我想在Wikipedia上找到此伪代码。

  

对于屏幕上的每个像素(Px,Py),请执行以下操作:{x0 =缩放的x坐标   像素的像素数(缩放为位于Mandelbrot X缩放比例(-2.5,1)内)y0 =   像素的缩放y坐标(缩放为位于Mandelbrot Y缩放比例中   (-1,1))x = 0.0 y = 0.0迭代= 0 max_iteration = 1000 // //   选择N = 2 ^ 8作为合理的救援半径。而(x x + y y <=   (1 << 16)AND迭代 x-y y + x0 y =   2 * x y + y0 x = xtemp迭代=迭代+ 1} //用于避免   集合内的点的浮点问题。如果(迭代<   max_iteration){//使用日志删除内部术语的sqrt   简化规则。 log_zn = log(x x + y * y)/ 2 nu = log(log_zn /   log(2))/ log(2)//重新排列电位函数。 //除法   用log(2)代替log(N = 1 << 8)// log_zn //因为我们想要   整个调色板的范围从//中心到半径2,不是我们的   救援半径。迭代=迭代+ 1-nu} color1 =   调色板[floor(iteration)] color2 =调色板[floor(iteration)+ 1] //   迭代%1 =迭代的小数部分。颜色=    linear_interpolate(color1,color2,迭代%1)图(Px,Py,颜色)   }

对此:

for(px = 0; px < a; px+=scale){
  for(py = 0; py < b; py+=scale){
    //zoom factors
    x0 = panX + px/zm;
    y0 = panY + py/zm;

    var x = 0;
    var y = 0;

    var i = 0;
    var xtemp;

    var xSquare = x*x;
    var ySquare = y*y;

    while (x*x + y*y <= 4  &&  i < maxI) {
      /*ticks++
      xtemp = x*x - y*y + x0
      y = 2*x*y + y0
      x = xtemp
      i = i + 1*/

      y = x*y;
      y += y;
      y += y0;

      x = xSquare - ySquare + x0;
      xSquare = Math.pow(x,2);
      ySquare = Math.pow(y,2);
      i += 1;
    }


    if ( i < maxI ) {

    log_zn = Math.log( x*x + y*y ) / 2
    nu = Math.log( log_zn / Math.log(2) ) / Math.log(2)



    i += 1 - nu
    }
    color1 = palette.colourAt(Math.floor(i))
    color2 = palette.colourAt(Math.floor(i) + 1)

    /*****************
    I dont know how to implement this.....
    color = linear_interpolate(color1, color2, iteration % 1)
    *****************/

    c.fillStyle = color
    c.fillRect(px,py,scale, scale);
    }
}

但是我不知道如何实现这部分伪代码:

color1 = palette[floor(iteration)]
color2 = palette[floor(iteration) + 1]
 // iteration % 1 = fractional part of iteration.
color = linear_interpolate(color1, color2, iteration % 1)
plot(Px, Py, color)

有人可以帮助我理解并给出实现此方法的方法吗?

1 个答案:

答案 0 :(得分:2)

linear_interpolate函数应该根据线性函数y = mx + b计算两种颜色之间的颜色。 要将线性函数应用于颜色,y是输出颜色,m是两种颜色之间的差,b是起始颜色,x是0到1之间的值。 当x为0时,此功能输出起始颜色。 x为1时,此功能输出结束色。

要执行此计算,我们需要使用三个数字形式的颜色。如果需要使用十六进制字符串,则必须将其拆分,并将每个两个字符解析为16位数字。我将使用已经是数字形式的调色板,因为它更容易。

这是我的三种调色板。我不建议您使用这些颜色,仅用于演示:

let palette = [{r:255,g:0,b:0},{r:0,g:255,b:0},{r:0,g:0,b:0}]

第一个函数进行迭代,该整数可能不是整数,并且可能大于1。它占用了迭代的底限,将其转换为数组索引必须为整数。然后,将迭代的余数除以1,得到0到1之间的数字。

function interpolation(iteration) {
    let color1 = palette[Math.floor(iteration)];
    let color2 = palette[Math.floor(iteration) + 1];
    return linear_interpolate(color1, color2, iteration % 1);
}

现在,我们需要创建线性插值函数,该函数必须将线性函数应用于每个颜色通道,并使用floor将它们转换为整数。我在rgb()中返回了css颜色,但是您可以将其转换为十六进制。

function linear_interpolate(color1, color2, ratio) {
    let r = Math.floor((color2.r - color1.r) * ratio + color1.r);
    let g = Math.floor((color2.g - color1.g) * ratio + color1.g);
    let b = Math.floor((color2.b - color1.b) * ratio + color1.b);
    return 'rgb(' + r + ',' + g + ',' + b + ')';
}

以下是代码阴影矩形:https://jsfiddle.net/q7kLszud/