2012-09-09 2 views
2

복잡한 함수 플로터에 다음 코드가 있습니다. 복소 함수 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> 

답변

3

나는 약 500 % 그것을 속도를 몇 가지 빠른 최적화를 만들었습니다. 나는 당신이 그것을 더 빠르게 할 수 있다고 생각하지만 조금 더 많은 작업이 필요할 것입니다. imageData의 배열

  • 대신 fillStyle에서는하고 fillRect 할를 사용하여 화소 값을 설정하는 모든 화소 값) 배열 (imageData의) 다음 makeFrame (AS 검으로 조작하고 :

    제가했던 것은 putImageData()를 사용해 모든 픽셀을 동시에 설정합니다.

  • 위의 변경은 complexToRGB()가 문자열 대신 빨강, 녹색 및 파랑 색 값을 가진 배열을 반환하도록 요구했습니다.
  • complexToRGB() 함수에서 if-cases 목록은 if-else 체인으로 변경되었습니다 (실제 조건 이후의 조건은 평가되지 않으므로 빠릅니다).
  • setInterval을 1000fps에서 25로 변경했습니다. 알고리즘이 해당 프레임 속도를 따라갈 수있는 방법이 없기 때문에 더 현실적인 프레임 속도로 설정하는 것이 좋습니다.

Here's the code as a jsFiddle.

다음 단계 : 나는 또한 루프 내부에서) (공식을합니다 (pixToReal 인라인)와 pixToImag 예를 들어, 기능이 가능한 호출 많은 사람을 제거하려고합니다 :

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

을 그리고 다음 코드를 최적화 complexToRGB()에서 해당 함수 호출을 제거하기 위해 해당 함수를 수행하는 것을 고려하십시오.

+0

감사합니다. 나는 프로그래밍에 익숙하지 않으며 이전에 성능 문제에 관해 생각할 필요가 없었습니다. 생각할 좋은 목록. –

+0

방금 ​​f() 함수가 mult()와 add()를 여러 번 호출한다는 것을 알게되었습니다. 좋은 읽을 수있는 코드를 생성하는 동안 많은 함수 호출을 얻습니다. 함수 호출을하지 않으려면 f()를 다시 작성하십시오. 또한, maenu에서 제안한 requestAnimationFrame은 좋은 아이디어입니다. – Strille

+0

나는 궁극적으로 사용자가 여분의 0 (또는 극점)을 추가하고 주변으로 끌 수있게하고 싶다. 그래서 나는 그 기능을 "하드 코딩"하는 것이 어려울 것이라고 생각합니다. 이것은 확실히 저에게 생각할 많은 것을 제공합니다. 함수 호출을 피해야한다는 생각은 새로운 것입니다. –

3

requestAnimationFrame을 사용하고 ImageData을 사용하여 나는 here을 만들었습니다. 꽤 잘 작동합니다, 아마 당신은 스트리의 접근 방식으로 나의 것을 합칠 수 있습니다.