Forked from: aont's Double Pendulum Leap Frog diff:54 forked from: Double Pendulum Symplectic Euler makc3d forked:3favorite:8lines:150license : MIT License modified : 2010-03-11 07:53:21 Embed Tweet // forked from aont's Double Pendulum package { import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.Sprite; import flash.events.MouseEvent; import flash.events.TimerEvent; import flash.geom.ColorTransform; import flash.geom.Matrix; import flash.geom.Point; import flash.utils.Timer; [SWF(backgroundColor=0)] public class DoublePendulum extends Sprite { private var line_1:Sprite; private var line_2:Sprite; private var circle:Sprite; private var circleCoords:Array = []; private var line_ratio:Number; private var length_1:Number = 0.5; private var length_2:Number = 0.25; private var radius:Number = 2; private var mass_1:Number = 0.05; private var mass_2:Number = 0.01; private var color_1:Number = 0x7f0000; private var color_2:Number = 0xff0000; private var color_3:Number = 0xff7f00; private var theta:Number = 0; private var phi:Number = 0; private var d_theta:Number = 0; private var d_phi:Number = 0; private var center:Number; private var center_y:Number; private var dt:Number = 1.0/60; private var g:Number = 9.8; private var myTimer:Timer; private var gamma1:Number = 0; private var gamma2:Number = 0; private var friction:Number = 1 - 1e-3; private var bd:BitmapData; private var ct:ColorTransform; public function DoublePendulum() { this.parent.addEventListener(MouseEvent.CLICK, MouseClick); this.center = 230; this.line_ratio = center / (this.length_1+this.length_2); line_1 = CreateLine(this.length_1*line_ratio,color_1) line_2 = CreateLine(this.length_2*line_ratio,color_2); this.line_1.x = center; this.line_1.y = center; bd = new BitmapData (465, 465, true, 0); addChild (new Bitmap (bd)); ct = new ColorTransform; ct.color = color_3; ct.alphaMultiplier = friction; circle = new Sprite; circle.graphics.beginFill (0xffffff); circle.graphics.drawCircle (0, 0, radius); addChild (circle); this.ReDraw(); this.myTimer = new Timer(this.dt * 1000,0); this.myTimer.addEventListener(TimerEvent.TIMER,Tick); this.myTimer.start(); } private function MouseClick(event:MouseEvent):void { theta = Math.atan2(center-event.localY,event.localX-center) + Math.PI /2; d_theta = 0; //d_phi = 0; this.ReDraw(); } private function ReDraw():void { this.line_1.rotation = 90 - this.theta * 180 / Math.PI; this.line_2.rotation = 90 - this.phi * 180 / Math.PI; this.line_2.x = center + this.length_1*line_ratio * Math.sin(this.theta) ; this.line_2.y = center + this.length_1 * line_ratio * Math.cos(this.theta) ; circle.x = line_2.x + length_2*line_ratio * Math.sin (phi); circle.y = line_2.y + length_2 * line_ratio * Math.cos (phi); if (circleCoords.length == 4) circleCoords.shift (); while (circleCoords.length != 4) circleCoords.push (new Point (circle.x, circle.y)); var m:Matrix = new Matrix, n:Number = 40 / radius; for (var i:int = 1; i < n + 1; i++) { var p:Point = spline (circleCoords [0], circleCoords [1], circleCoords [2], circleCoords [3], i / n); m.tx = p.x; m.ty = p.y; bd.draw (circle, m); } bd.colorTransform (bd.rect, ct); } private function CreateLine(length:Number,color:uint):Sprite { var line:Sprite = new Sprite(); with(line.graphics) { lineStyle(1, color); moveTo(0,0); lineTo(length,0); } this.addChild(line); return line; } private function Advance():void { //var theta_new:Number //var phi_new:Number; d_theta += dt* ( -(mass_1+mass_2)*g*Math.sin(theta)/length_1 +mass_2*g*Math.cos(theta-phi)*Math.sin(phi)/length_1 -mass_2*Math.pow(d_theta,2)*Math.sin(2*(theta-phi))/2 -mass_2*Math.sin(theta-phi)*Math.pow(d_phi,2)*length_2/length_1 ) / (mass_1 + mass_2 * Math.pow(Math.sin(theta-phi),2)) -gamma1 * d_theta ; d_phi += dt* ( (mass_1+mass_2)*g*Math.cos(theta)*Math.sin(theta-phi)/length_2 +(mass_1+mass_2)*Math.sin(theta-phi)*Math.pow(d_theta,2)*length_1/length_2 +mass_2*Math.pow(d_phi,2)*Math.sin(2*(theta-phi))/2 ) / (mass_1 + mass_2 * Math.pow(Math.sin(theta-phi),2)) -gamma2 * d_phi ; d_theta *= friction; d_phi *= friction; theta = ModRadian(theta + d_theta * dt); phi = ModRadian(phi + d_phi * dt); } private function ModRadian(rad:Number):Number { while(rad > Math.PI) { rad -= 2*Math.PI; } while(rad <= -Math.PI) { rad += 2*Math.PI; } return rad; } private function Tick(event:TimerEvent):void { this.Advance(); this.ReDraw(); } /* * Calculates 2D cubic Catmull-Rom spline. * @see http://www.mvps.org/directx/articles/catmull/ */ private function spline (p0:Point, p1:Point, p2:Point, p3:Point, t:Number):Point { return new Point ( 0.5 * (( 2*p1.x) + t * (( -p0.x +p2.x) + t * ((2*p0.x -5*p1.x +4*p2.x -p3.x) + t * ( -p0.x +3*p1.x -3*p2.x +p3.x)))), 0.5 * (( 2*p1.y) + t * (( -p0.y +p2.y) + t * ((2*p0.y -5*p1.y +4*p2.y -p3.y) + t * ( -p0.y +3*p1.y -3*p2.y +p3.y)))) ); } } } Code Fullscreen Preview Fullscreen bradsedito cygnusx code_in_a lexanderc nanlow cjcat2266 clockmaker narutohyper Math.pow Math.sin Math.PI Point Math.cos rotation shift graphics TimerEvent start Math.atan2 Timer TimerEvent.TIMER length addEventListener push addChild Array uint Sprite sort new page view favorite forked pv83 forked from: forked from: Doub.. Dokin forked:0 favorite:1lines:150 (diff:1) pv191 forked from: forked from: Doub.. yotsu42keisuke forked:0 favorite:0lines:150 (diff:1) pv1295 Double Pendulum in QuickBox2D makc3d forked:5 favorite:4lines:77 (diff:129)