レスラー方程式は以下で定義される連続力学系です。
ここでドット記号は時間 t での微分を表すこととします。
連続時間ではシミュレーションできないので時間を0.02ずつ増やしてシミュレーションしました。また、パラメータは
としました。
以下シミュレーションに用いたコードになります。
<html> <body> <script type="text/javascript" src="rossler.js"></script> </body> </html>
const A = 0.2; const B = 0.2; const C = 5.7; const D = 0.02; // x軸まわりの回転 function rotate_x(x,y,z,theta){ return [x,y*Math.cos(theta)-z*Math.sin(theta),y*Math.sin(theta)+z*Math.cos(theta)]; } // y軸まわりの回転 function rotate_y(x,y,z,theta){ return [x*Math.cos(theta)+z*Math.sin(theta),y,-x*Math.sin(theta)+z*Math.cos(theta)]; } // z軸まわりの回転 function rotate_z(x,y,z,theta){ return [x*Math.cos(theta)-y*Math.sin(theta),x*Math.sin(theta)+y*Math.cos(theta),z]; } const WIDTH = 400; const HEIGHT = 400; const E = 20; const X_MAX = E; const X_MIN = -E; const Y_MAX = E; const Y_MIN = -E; const Z_MAX = E; const Z_MIN = -E; const canvas = document.createElement('canvas'); canvas.width = WIDTH; canvas.height = HEIGHT; const context = canvas.getContext('2d'); document.body.appendChild(canvas); class Point{ constructor(x, y, z, color){ this.x = x; this.y = y; this.z = z; this.color = color; } update(){ this.prev_x = this.x; this.prev_y = this.y; this.prev_z = this.z; let dx = -this.y-this.z; let dy = this.x + A*this.y; let dz = B + this.z*(this.x-C); this.x += D * dx; this.y += D * dy; this.z += D * dz; } render(context){ context.beginPath(); context.strokeStyle = this.color; let [x0,y0,z0] = rotate_z(this.prev_x, this.prev_y, this.prev_z,Math.PI); [x0,y0,z0] = rotate_x(x0,y0,z0,Math.PI/4); let [x1,y1,z1] = rotate_z(this.x, this.y, this.z,Math.PI); [x1,y1,z1] = rotate_x(x1,y1,z1,Math.PI/4); context.moveTo(WIDTH*(x0-X_MIN)/(X_MAX-X_MIN), HEIGHT*(y0-Y_MIN)/(Y_MAX-Y_MIN)); context.lineTo(WIDTH*(x1-X_MIN)/(X_MAX-X_MIN), HEIGHT*(y1-Y_MIN)/(Y_MAX-Y_MIN)); context.stroke(); } } const objects = []; let count = 0; let colors = ["blue","green","red","purple","yellow"]; for(let i=0;i<3;i++){ objects.push(new Point(1+0.01*i,1+0.01*i,1+0.01*i,colors[i])); } function loop(timestamp) { objects.forEach((obj) => obj.update()); objects.forEach((obj) => obj.render(context)); window.requestAnimationFrame((ts) => loop(ts)); count++; context.fillStyle = "white"; context.fillRect(0,0,60,40); context.fillStyle = "black"; context.fillText("t : " + (D*count).toFixed(2), 10, 10); } window.requestAnimationFrame((ts) => loop(ts));