forked from: [教材] 連成振り子
// forked from knd's [教材] 連成振り子
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.Point;
public class CoupledOscillator extends Sprite
{
//紐の長さ
private const L1:Number = 150.0;
private const L2:Number = 120.0;
//玉の質量・半径
private const M1:Number = 10.0;
private const M2:Number = 50.0;
private const R1:Number = 5*Math.pow(M1,1.0/3.0);
private const R2:Number = 5*Math.pow(M2,1.0/3.0);
//玉の位置
private const P1:Point = new Point();
private const P2:Point = new Point();
//重力加速度
private const G0:Number = 20.0;
//1フレームあたりの時間
private const dt:Number = 0.03;
//鉛直方向を0として、初期状態の紐の角度
private var ang1:Number = 60.0 / 180.0 * Math.PI;
private var ang2:Number = -45.0 / 180.0 * Math.PI;
//初期状態の振り子の角速度
private var omg1:Number = 0.0;
private var omg2:Number = 0.0;
//振り子の支点
private var x0:Number = stage.stageWidth * 0.5;
public function CoupledOscillator() {
redraw();
addEventListener(Event.ENTER_FRAME, loop);
}
private function redraw():void {
P1.x = x0 + L1 * Math.sin(ang1);
P1.y = L1 * Math.cos(ang1);
P2.x = P1.x + L2 * Math.sin(ang2);
P2.y = P1.y + L2 * Math.cos(ang2);
graphics.clear();
graphics.lineStyle(2)
graphics.moveTo(x0, 0);
graphics.lineTo(P1.x, P1.y);
graphics.lineTo(P2.x, P2.y);
graphics.beginFill(0xff8000);
graphics.drawCircle(P1.x, P1.y, R1);
graphics.drawCircle(P2.x, P2.y, R2);
graphics.endFill();
}
private function loop(e:Event):void {
//振り子の角加速度
var dda1:Number;
var dda2:Number;
//紐にはたらく張力
var T1:Number;
var T2:Number;
var omg1Tmp:Number;
var omg2Tmp:Number;
//2次RK法の計算を入れたつもりなんだけど、
//減衰項が無いのに振動が減衰する。なんでだろう。
dda2 = -G0 * Math.sin(ang2) / L2 * dt ;
T2 = M2 * G0 * Math.cos(ang2);
T1 = M1 * G0 * Math.cos(ang1) + T2 * Math.cos(ang1 - ang2);
dda1 = ( -G0 * Math.sin(ang1) - T2 / M1 * Math.sin(ang1 - ang2)) / L1 * dt;
omg1Tmp = omg1 + dda1;
omg2Tmp = omg2 + dda2;
dda2 = 0.5 * (dda2 -G0 * Math.sin(ang2 + omg2Tmp) / L2 * dt);
T2 = M2 * G0 * Math.cos(ang2 + omg2Tmp);
T1 = M1 * G0 * Math.cos(ang1 + omg1Tmp) + T2 * Math.cos(ang1 + omg1Tmp - ang2 - omg2Tmp);
dda1 = 0.5 * (dda1 + (-G0 * Math.sin(ang1 + omg1Tmp) - T2 / M1 * Math.sin(ang1 + omg1Tmp - ang2 - omg2Tmp)) / L1 * dt);
omg1 += dda1;
omg2 += dda2;
ang1 += omg1;
ang2 += omg2;
redraw();
}
}
}