In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

forked from: 非線形離散力学系の不変集合

-------
2010年3月31日水曜日
非線形離散力学系の不変集合
少しずつプロットされていきますので気長に見てください
--------
以下は、数学的内容の解説 --- 
平面の自己同相写像
new X = f(X) + αY
new Y = βX
... ただし
(1)	α, β は定数で, αβ = 1 となるもの. 今回は α = β = -1
(2)	f(X) は任意の可微分函数だけど,  ここでは f(X) = 4X(1-X)
...
の, 不動点での挙動 (不動点の微小近傍の軌道) を図示

赤い図形は原点の微小近傍がこの写像の反復で引き伸ばされてできる図形 (不安定多様体)
青い図形は同じく原点の微小近傍が逆写像の反復で引き伸ばされてできる図形 (安定多様体)
いずれも(究極的には)一本の線が複雑に折りたたまれた形状になります
--------
Get Adobe Flash player
by matacat 02 Apr 2010
    Embed
/**
 * Copyright matacat ( http://wonderfl.net/user/matacat )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/5Jz0
 */

// forked from tenasaku's 非線形離散力学系の不変集合
/* -------
	2010年3月31日水曜日
	非線形離散力学系の不変集合
	少しずつプロットされていきますので気長に見てください
	--------
	以下は、数学的内容の解説 --- 
	平面の自己同相写像
		new X = f(X) + αY
		new Y = βX
		... ただし
			(1)	α, β は定数で, αβ = 1 となるもの. 今回は α = β = -1
			(2)	f(X) は任意の可微分函数だけど,  ここでは f(X) = 4X(1-X)
		...
	の, 不動点での挙動 (不動点の微小近傍の軌道) を図示

	赤い図形は原点の微小近傍がこの写像の反復で引き伸ばされてできる図形 (不安定多様体)
	青い図形は同じく原点の微小近傍が逆写像の反復で引き伸ばされてできる図形 (安定多様体)
	いずれも(究極的には)一本の線が複雑に折りたたまれた形状になります
	-------- */
package
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.filters.GlowFilter;
	import flash.geom.Point;
	import flash.text.TextField;
	import flash.text.TextFormat;
	
	[SWF(width=465, height=465, frameRate=24)]
	
	public class Main extends Sprite
	{
		private function F(u:Number):Number { return 4 * u * (1 - u); }
		private static const ALPHA:Number = -1;
		private static const BETA:Number  = 1 / ALPHA;
		
		
		// 微調整用
		private static const EPSILON:Number = 2.0e-02;
		private static const FROM:Number    = -75;
		private static const TO:Number      = 55;
		private static const TOTAL:Number   = 100 / (TO - FROM);
		private static const DELTA:Number   = Math.pow(2, -10);
		private static const COUNTMAX:int   = 8;
		private static const ACCEL:int      = 200;
		private var seed:Number;
		
		
		// プロット用
		private const P0:Number    = 140;
		private const Q0:Number    = 240;
		private const Pu:Number    = 150;
		private const Qv:Number    = -Pu;
		private const R:BitmapData = new BitmapData(2, 2, false, 0xFF6060);
		private const B:BitmapData = new BitmapData(2, 2, false, 0x6060FF);
		private const A:BitmapData = new BitmapData(2, 2, true, 0x08 << 24);
		private const C:Point      = new Point();
		private const O:Point      = new Point();
		
		
		// 表示用・その他
		private var redScreen:BitmapData;
		private var blueScreen:BitmapData;
		private var rsaf:Function;
		private var bsaf:Function;
		private var rf:GlowFilter;
		private var bf:GlowFilter;
		private var redCache:BitmapData;
		private var blueCache:BitmapData;
		private var rccp:Function;
		private var bccp:Function;
		private var progress:TextField;
		
		
		public function Main()
		{
			Wonderfl.capture_delay(30);
			
			stage.align     = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE;
			
			graphics.beginFill(0);
			graphics.drawRect(0, 0, 465, 465);
			
			addChild( new Bitmap( redScreen  = new BitmapData(465, 465, true, 0) ) );
			addChild( new Bitmap( blueScreen = new BitmapData(465, 465, true, 0) ) ).blendMode = "add";
			
			rsaf = redScreen.applyFilter;
			bsaf = blueScreen.applyFilter;
			rf   = new GlowFilter(0xE04060, 1, 32, 32, 3, 2);
			bf   = new GlowFilter(0x6040E0, 1, 32, 32, 3, 2);
			
			redCache  = redScreen.clone();
			blueCache = blueScreen.clone();
			rccp = redCache.copyPixels;
			bccp = blueCache.copyPixels;
			
			addChild( progress  = new TextField() );
			progress.defaultTextFormat = new TextFormat(null, null, 0xC0FFC0);
			progress.autoSize          = "right";
			progress.selectable        = false;
			progress.text              = "000.0%";
			progress.x                 = 465 - progress.width;
			
			seed = FROM;
			
			stage.addEventListener(Event.ENTER_FRAME, atEveryFrame);
		}
		
		private function atEveryFrame(e:Event):void
		{
			var p0:Number, q0:Number; // 順方向へ移動する点
			var p1:Number, q1:Number; // 逆方向へ移動する点
			
			for (var j:int = 0; j < ACCEL; j++) {
				
				p0 = p1 = seed * EPSILON; // 初期値(X座標)
				q0 = q1 = seed * EPSILON; // 初期値(Y座標)
				
				for (var i:int = 0 ; i < COUNTMAX ; ++i ) {
					
					var p2:Number = F(p0) + ALPHA * q0;          // 順方向(X座標)
					var q2:Number = BETA * p0;                   // 順方向(Y座標)
					var p3:Number = q1 / BETA;                   // 逆方向(X座標)
					var q3:Number = (p1 - F(q1 / BETA)) / ALPHA; // 逆方向(Y座標)
					
					plot(p2, q2, true);  // 不安定多様体を赤でプロット
					plot(p3, q3, false); // 安定多様体を青でプロット
					
					p0 = p2, q0 = q2;
					p1 = p3, q1 = q3;
				}
				
				if (seed < TO) seed += DELTA;
				else {
					stage.removeEventListener(Event.ENTER_FRAME, atEveryFrame);
					break;
				}
			}
			
			rsaf(redCache, redCache.rect, O, rf);
			bsaf(blueCache, blueCache.rect, O, bf);
			
			progress.text = ((seed - FROM) * TOTAL).toFixed(1) + "%";
		}
		
		private function plot(u:Number, v:Number, mode:Boolean):void
		{
			var P:int = P0 + Pu * u >> 0;
			var Q:int = Q0 + Qv * v >> 0;
			if ((P >= 0) && (Q >= 0) && (P < 465) && (Q < 465)) {
				C.x = P;
				C.y = Q;
				if (mode) rccp(R, R.rect, C, A, O, true);
				else      bccp(B, B.rect, C, A, O, true);
			}
		}
	} // end of class Main
} // end of package