javascript - 加速我的复杂函数绘图仪(canvas+javascript)

标签 javascript performance canvas complex-numbers

我有以下复杂函数绘图仪的代码。它创建复数函数 f(z) = z*(z+5)(z-v) 的相图,其中 v 是鼠标指向的位置。如您所见,速度相当慢。有什么方法可以加快速度并获得流畅的动画吗?只要为我指明正确的方向就会很有帮助。

<html>
<head>
<script type="text/javascript" src="jquery-1.8.1.js"></script>
<script type="application/javascript">
function draw() {
var canvas = document.getElementById("canvas");
var ctx;// = canvas.getContext("2d");

//The following functions convert pixel Xs and Ys to real and imaginary 
//parts of a complex    number, and back again
var pixToReal = function(n){return n/15.0-10.0};
var pixToImag = function(n){return  - n/15.0+10}
var realToPix = function(x){return Math.round((x+10.0)*15)}
var imagToPix = function(y){return Math.round((-y+10.0)*15)}

//Storing the complex number a+bi as [a,b], the following functions add, 
//multiply, and  find the modulus of the complex number
var add = function(z1,z2){return [z1[0]+z2[0],z1[1] + z2[1]]}
var mult = function(z1,z2){return [z1[0]*z2[0]-z1[1]*z2[1],z1[0]*z2[1]+z1[1]*z2[0]]}
var modulus = function(z){
    if (z[1]>0){return Math.atan2(z[1],z[0])}
    else {return Math.atan2(z[1],z[0])+2*Math.PI}
    };

//Takes a complex number and returns the RGB value of the corresponding 
//point on the color wheel.
var complexToRGB = function(z){
var theta = modulus(z)%(2*Math.PI)
var Hp = (theta/(2*Math.PI))*6
var X = Math.abs(Math.round((1 - Math.abs(Hp%2 -1))*255))
var C =  "rgb(0,0,0)"
if (Hp>=0 && Hp<1){
    C = "rgb("+255+","+X+",0)"
    };
if (1<=Hp && Hp<2){
    C = "rgb("+X+","+255+",0)"}
if (2<=Hp && Hp<3){
    C = "rgb("+0+","+255+","+X+")"}
if (3<=Hp && Hp<4){
    C = "rgb("+0+","+X+","+255+")"}
if (4<=Hp && Hp<5){
    C = "rgb("+X+","+0+","+255+")"}
if (5<=Hp && Hp<6){
    C = "rgb("+255+","+0+","+X+")"}
return  C

}

//a complex number
var v = [0,4] 

//the function f(z) = z*(z+5)*(z+v)
var f = function(z){return mult(add(mult(z,z),mult([5,5],z)),add(z,v))}

//makes v the opposite complex number your mouse is pointing at, 
//i.e. your mouse points at a root of f
function onMouseMove(evt) {
v = [-pixToReal(evt.pageX), -pixToImag(evt.pageY)];
}

$(document).mousemove(onMouseMove);

makeFrame = function(){
 ctx.clearRect(0,0,300,300);
 for (var n =0;n<300;n++){
     for (var m=0;m<300;m++){
        var x = pixToReal(n)
        var y = pixToImag(m)
        var z = [x,y]
        var w = f(z) 
        ctx.fillStyle = complexToRGB(w)
        ctx.fillRect(n,m,1,1)
        }
       }
   }

 function animate() {
 ctx = canvas.getContext("2d");
 return setInterval(makeFrame, 1);
 }

 animate();

}
 </script>
</head>
<body onload="draw()">
  <canvas id="canvas" width="300" height="300"></canvas>
</body>

最佳答案

我做了一些快速优化,速度提高了约 500%。我认为你可以进一步加快速度,但这需要更多的工作。

我所做的是:

  • 不是使用 fillStyle 和 fillRect 设置像素值,而是以数组 (imageData) 的形式检索所有像素值,然后 makeFrame() 操作 imageData 数组,然后使用 putImageData() 一次设置所有像素。
  • 上述更改要求 ComplexToRGB() 使用红色、绿色和蓝色颜色值重新调整数组,而不是字符串。
  • 在complexToRGB()函数中,if-cases列表已更改为if-else链(速度更快,因为不会评估真实条件后的条件)。
  • 将 setInterval 从 1000 fps 更改为 25。算法无法跟上该帧速率,因此最好将其设置为更实际的帧速率。

Here's the code as a jsFiddle .

后续步骤:我还会尝试删除尽可能多的函数调用,例如在内部 for 循环中内联 pixToReal() 和 pixToImag() 公式:

for (var m = 0; m < 300; m++) {
   var x = n / 15.0 - 10.0;
   var y = -m / 15.0 + 10;

然后优化complexToRGB()中的代码,并考虑对该函数执行相同的操作以删除该函数调用。

关于javascript - 加速我的复杂函数绘图仪(canvas+javascript),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12342016/

相关文章:

javascript - HTML5 Canvas : Rotate cropped image within bounds on single canvas

javascript - DukTape 在 GLUT 窗口上显示 JavaScript Canvas

javascript - 复制两个数组和控制台输出

javascript - 从事件发射器创建生成器

JavaScript 用于字符串中的部分匹配

ruby-on-rails - unicorn 中每个 worker 的最大请求数

jquery - 从一个 CDN 或多个 CDNS 加载文件

javascript - 如何从curl命令转换为ajax请求

sql - 有没有办法识别或检测 Hive 表中的数据倾斜?

javascript - 如何使用旋转矩阵旋转形状?