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

畑政義写像

畑政義写像 HATA map
@see http://aquioux.net/blog/?p=232
@author YOSHIDA, Akio (Aquioux)
/**
 * Copyright Aquioux ( http://wonderfl.net/user/Aquioux )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/a2ii
 */

package {
    import flash.display.Bitmap;
    import flash.display.Sprite;
    import flash.events.Event;
    [SWF(width = "465", height = "465", frameRate = "10", backgroundColor = "#000000")]
    /**
     * 畑政義写像 HATA map
     * @see http://aquioux.net/blog/?p=232
     * @author YOSHIDA, Akio (Aquioux)
     */
    public class Main extends Sprite {
        
        private var model_:HataMap;    // 畑政義写像エンジン
        private var viewer_:Viewer;    // ビューア

        /**
         * コンストラクタ
         */ 
        public function Main() {
            setup();
            addEventListener(Event.ENTER_FRAME, update);
        }
        
        // 初期化
        private function setup():void {
            var sw:Number = stage.stageWidth;
            var sh:Number = stage.stageHeight;
            
            // 写像クラス(Model)
            model_ = new HataMap();
            model_.setup(sw, sh);

            // ビューア
            viewer_ = new Viewer();
            viewer_.setup(sw, sh);
            addChild(viewer_);
            
            // スライダー
            var sliders:PSliders = new PSliders();
            sliders.setup(model_, viewer_);
            addChild(sliders);
            // ボタン
            var buttons:PButtons = new PButtons();
            buttons.setup(sliders);
            buttons.y = stage.stageHeight - buttons.height;
            addChild(buttons);
            
            model_.update();
        }
        
        // ループ
        private function update(e:Event):void {
            viewer_.update(model_.data);
        }
    }
}


//package {
    /**
     * 畑政義写像エンジン
     * @author YOSHIDA, Akio (Aquioux)
     */
    /*public*/ class HataMap {

        public function get data():Vector.<Number> { return _data; }
        private var _data:Vector.<Number>;        // 描画座標

        public function get a():Complex { return _a; }
        public function set a(value:Complex):void { _a = value; }
        private var _a:Complex = new Complex(0.0,   0.0);

        public function get b():Complex { return _b; }
        public function set b(value:Complex):void { _b = value; }
        private var _b:Complex = new Complex(1.0, 1.0);
        
        public function get c():Complex { return _c; }
        public function set c(value:Complex):void { _c = value; }
        private var _c:Complex = new Complex(0.0,   0.0);
        
        public function get d():Complex { return _d; }
        public function set d(value:Complex):void { _d = value; }
        private var _d:Complex = new Complex(1.0,  -1.0);
        
        private const GENERATION:int = 11;        // 再帰世代
        
        private var sw_:Number;                // ステージ幅
        private var sh_:Number;                // ステージ高
        
        private var maxWidth_:int;            // 表示幅の最大値
        private var maxHeight_:int;            // 表示高の最大値
        private var numOfCoordinate_:int;    // プロットする座標の数(プロットする点の数 * 2)
        
        private var minX_:Number = 0.0;        // プロットする点のX座標の最小値
        private var minY_:Number = 0.0;        // プロットする点のX座標の最大値
        private var maxX_:Number = 0.0;        // プロットする点のY座標の最小値
        private var maxY_:Number = 0.0;        // プロットする点のY座標の最大値
        private var scale_:Number = 1.0;    // 表示スケール

        
        /**
         * コンストラクタ
         */ 
        public function HataMap() {
            _a.r = Math.random() * 2 - 1;
            _a.i = Math.random() * 2 - 1;
            _b.r = Math.random() * 2 - 1;
            _b.i = Math.random() * 2 - 1;
            _c.r = Math.random() * 2 - 1;
            _c.i = Math.random() * 2 - 1;
            _d.r = Math.random() * 2 - 1;
            _d.i = Math.random() * 2 - 1;
        }
        
        /**
         * 初期化
         * @param    sw    ステージ幅
         * @param    sh    ステージ高
         */
        public function setup(sw:Number, sh:Number):void {
            // ステージサイズ
            this.sw_ = sw;
            this.sh_ = sh;
            
            // 描画領域
            maxWidth_  = (int(sw / 100) - 0.5) * 100;
            maxHeight_ = (int(sh / 100) - 0.5) * 100;
            
            //プロットする座標の数
            var len:uint = GENERATION + 1;
            numOfCoordinate_ = 0;
            for (var i:int = 0; i < len; i++) {
                numOfCoordinate_ += Math.pow(2, i);
            }
            numOfCoordinate_ *= 2;
        }
        
        /**
         * ループ
         */
        public function update():void {
            // hataMap, plot 共に使用される各変数の初期化
            _data = new Vector.<Number>();
            minX_ = 0.0;
            minY_ = 0.0;
            maxX_ = 0.0;
            maxY_ = 0.0;

            // 写像実行
            mapping(Complex.COMPLEX_0, 0);

            // 写像処理の再帰が完了してからプロット実行
            plot(minX_, minY_, maxX_ - minX_, maxY_ - minY_);
        }
        
        // 写像処理
        private function mapping(z1:Complex, generation:int):void {
            // プロット座標として待避
            _data.push(z1.r, z1.i);
            // 座標の最大値と最小値を待避
            if (minX_ > z1.r) minX_ = z1.r;
            if (minY_ > z1.i) minY_ = z1.i;
            if (maxX_ < z1.r) maxX_ = z1.r;
            if (maxY_ < z1.i) maxY_ = z1.i;
            
            // ループの終了判定
            if (generation < GENERATION) {
                // 再帰
                var z2:Complex = new Complex(z1.r,     -z1.i);    // z~
                var z3:Complex = new Complex(z1.r - 1,  z1.i);    // z  - 1
                var z4:Complex = new Complex(z2.r - 1,  z2.i);    // z~ - 1
                
                var zF1:Complex = Complex.add(
                    Complex.multiply(_a, z1),
                    Complex.multiply(_b, z2)
                );
                var zF2:Complex = Complex.add(
                    Complex.multiply(_c, z3),
                    Complex.multiply(_d, z4)
                );
                zF2 = Complex.add(zF2, Complex.COMPLEX_1);
                
                var next:int = generation + 1;
                mapping(zF1, next);    // f1(z) で再帰
                mapping(zF2, next);    // F2(z) で再帰
            }
        }
        
        // プロット
        private function plot(offsetX:Number, offsetY:Number, w:Number, h:Number):void {
            scale_ = Math.min(maxWidth_ / w, maxHeight_ / h);    // スケールの計算
            var offsetX2:Number = (sw_ - w * scale_) / 2;        // プロット開始X座標のオフセットを計算
            var offsetY2:Number = (sh_ - h * scale_) / 2;        // プロット開始Y座標のオフセットを計算
            var len:uint = numOfCoordinate_;
            for (var i:int = 0; i < len; i += 2) {
                var posX:Number = _data[i]     - offsetX;
                var posY:Number = _data[i + 1] - offsetY;
                _data[i]     = posX * scale_ + offsetX2;
                _data[i + 1] = posY * scale_ + offsetY2;
            }
        }
    }
//}


//package {
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.filters.BitmapFilterQuality;
    import flash.filters.BlurFilter;
    import flash.geom.ColorTransform;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    import frocessing.color.ColorHSV;
    /**
     * BitmapData 書き込みおよび表示
     * @author YOSHIDA, Akio (Aquioux)
     */
    /*public*/ class Viewer extends Bitmap {
        /*
         * ColorTransform によるフェードアウトのための定義
         */
        public function set fade(value:ColorTransform):void { _fade = value; }
        private var _fade:ColorTransform = new ColorTransform(1, 1, 1, 0.9);

        /*
         * Blur filter によるフェードアウトのための定義
         */
        public function set blur(value:BlurFilter):void { _blur = value; }
        private var _blur:BlurFilter = new BlurFilter(4, 4, BitmapFilterQuality.LOW);
        private const ZERO_POINT:Point = new Point(0, 0);

        // ColorTransform, Blur 共用
        private var rect:Rectangle;
        
        // バッファ
        private var bufferBmd_:BitmapData;
        
        // 描画色調整用
        private var hsv:ColorHSV;
        
        
        /**
         * コンストラクタ
         */ 
        public function Viewer() {
        }
        
        /**
         * 初期化
         * @param    sw    ステージ幅
         * @param    sh    ステージ高
         */
        public function setup(sw:Number, sh:Number):void {
            bufferBmd_ = new BitmapData(sw, sh, true, 0xFF000000);
            bitmapData = bufferBmd_.clone();
            rect = new Rectangle(0, 0, sw, sh);
            hsv  = new ColorHSV();
        }
        
        /**
         * ループ
         * @param    data    描画座標データ
         */
        public function update(data:Vector.<Number>):void {
            // bufferBmd_ の更新
            bufferBmd_.lock();
            bufferBmd_.fillRect(bufferBmd_.rect, 0x00000000);
            var len:uint = data.length;
            hsv.h += 1;
            for (var i:int = 0; i < len; i += 2) {
                bufferBmd_.setPixel32(data[i], data[i + 1], hsv.value32);
            }
            bufferBmd_.unlock();
            
            // bitmapData の更新
            bitmapData.colorTransform(rect, _fade);
            bitmapData.applyFilter(bitmapData, rect, ZERO_POINT, _blur);
            bitmapData.draw(bufferBmd_);
        }
    }
//}


/*package {*/
    import flash.display.Sprite;
    /**
     * スライダー集合
     * @author Aquioux
     */
    /*public*/ class PSliders extends Sprite {
        
        private var pSliders:Array;

        /**
         * コンストラクタ
         */ 
        public function PSliders() {
        }
        
        /**
         * 初期化
         * @param    hatamap    写像クラス(Model)
         * @param    viewer    ビューア
         */
        public function setup(model:HataMap, viewer:Viewer):void {
            var values:Array = [
                ["a:", model.a],
                ["b:", model.b],
                ["c:", model.c],
                ["d:", model.d]
            ];
            
            pSliders = [];
            for (var i:int = 0; i < 4; i++) {
                var pSlider:PSlider = new PSlider();
                pSlider.model = model;
                pSlider.viewer = viewer;
                pSlider.setup(values[i][0], values[i][1]);
                addChild(pSlider);
                pSlider.y = 15 * i;
                pSliders.push(pSlider);
            }
        }
        
        // ボタンから呼び出される
        public function update(val:Array):void {
            for (var i:int = 0; i < 4; i++) {
                var pSlider:PSlider = pSliders[i];
                pSlider.outerUpdate(val[i]);
            }
        }
    }
//}


//package {
    import caurina.transitions.Tweener;
    import com.bit101.components.HSlider;
    import com.bit101.components.Label;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.geom.ColorTransform;
    /**
     * 個別スライダー
     * @author YOSHIDA, Akio (Aquioux)
     */
    /*public*/ class PSlider extends Sprite {
        
        public function set model(value:HataMap):void { model_ = value; }
        private var model_:HataMap;        // 写像クラス(Model)への参照
        
        public function set viewer(value:Viewer):void { viewer_ = value; }
        private var viewer_:Viewer;        // ビューアへの参照
        
        private var z_:Complex;            // 対象の複素数への参照

        private var label0_:Label;        // 変数名
        private var label1_:Label;        // 実数部の値
        private var label2_:Label;        // 虚数部の値
        private var slider1_:HSlider;    // 実数部を操作する
        private var slider2_:HSlider;    // 虚数部操作する

        private const RATE:int = 10000;
        

        /**
         * コンストラクタ
         */ 
        public function PSlider() {
        }

        /**
         * 初期化
         * @param    text    どの変数かを表示するためのテキスト
         * @param    target    対象の複素数
         */
        public function setup(text:String, z:Complex):void {
            z_ = z;
            
            label0_  = new Label(this,     0, 0, text);        // どの変数かを表示する
            label1_  = new Label(this,    20, 0, String(z.r)); // 実数部の値を表示する
            slider1_ = new HSlider(this,  70, 5, handler1);    // 実数部の値を変更する
            label2_  = new Label(this,   180, 0, String(z.i)); // 虚数部の値を表示する
            slider2_ = new HSlider(this, 230, 5, handler2);    // 虚数部の値を変更する
            
            slider1_.setSliderParams( -RATE, RATE, z_.r * RATE);
            slider2_.setSliderParams( -RATE, RATE, z_.i * RATE);
            
            var colorTransform:ColorTransform = new ColorTransform(0, 0, 0, 1, 255, 255, 255, 0);
            label0_.transform.colorTransform = colorTransform;
            label1_.transform.colorTransform = colorTransform;
            label2_.transform.colorTransform = colorTransform;
            
            slider1_.alpha = 0.5;
            slider2_.alpha = 0.5;
        }
        // 実数部に関わるハンドラ
        private function handler1(e:Event):void {
            var value:Number = e.target.value / RATE;
            label1_.text = String(value);
            z_.r = value;
            innerUpdate();
        }
        // 虚数部に関わるハンドラ
        private function handler2(e:Event):void {
            var value:Number = e.target.value / RATE;
            label2_.text = String(value) + " i";
            z_.i = value;
            innerUpdate();
        }
        
        // 内部由来の更新
        private function innerUpdate():void{
            model_.update();
            viewer_.update(model_.data);
        }
        // 外部由来の更新
        public function outerUpdate(z:Complex):void {
            var r:Number = z.r;
            var i:Number = z.i;
            Tweener.addTween(z_,
                {
                    "r":r,
                    "i":i,
                    time:2.5,
                    transition:"easeNone",
                    onUpdate:outerUpdate2
                }
            );
        }
        private function outerUpdate2():void {
            var r:Number = z_.r;
            var i:Number = z_.i;
            label1_.text = String(r);
            label2_.text = String(i) + " i";
            slider1_.value = r * RATE;
            slider2_.value = i * RATE;
            innerUpdate();
        }
    }
//}


//package {
    import com.bit101.components.PushButton;
    import flash.display.Sprite;
    import flash.events.MouseEvent;
    
    /**
     * プリセットボタン集合
     * @author Aquioux
     */
    /*public*/ class PButtons extends Sprite {
        // スライダーへの参照
        private var sliders_:PSliders;

        // 各ボタンの値
        private const VALUES:Array = [
            ["Koch",        Complex.COMPLEX_0,                new Complex(0.5, -0.25),    Complex.COMPLEX_0,            new Complex(0.5, 0.25)    ],
            ["Levy C",        Complex.COMPLEX_0,                new Complex(-0.5, 0.5),        Complex.COMPLEX_0,            new Complex(-0.5, -0.5)    ],
            ["Leaf",        new Complex(0.7, 0.2),            Complex.COMPLEX_0,            Complex.COMPLEX_0,            new Complex(2 / 3, 0.0)    ],
            ["Branch",        Complex.COMPLEX_0,                new Complex(0.5, 0.3),        Complex.COMPLEX_0,            new Complex(2 / 3, 0.0)    ],
            ["Wave",        new Complex(0.55, -0.45),        Complex.COMPLEX_0,            new Complex(0.6, 0.2),        Complex.COMPLEX_0        ],
            ["Cloud",        new Complex(2/3, -0.5),            Complex.COMPLEX_0,            new Complex(-0.2, 0.5),        Complex.COMPLEX_0        ],
            ["Shine",        new Complex(1.0, -1.0),            Complex.COMPLEX_0,            new Complex(-1.0, -1.0),    new Complex(-1.0, 1.0)    ],
            ["Cross",        new Complex(0.0, Math.SQRT1_2),    Complex.COMPLEX_0,            new Complex(0.5, 0.0),        Complex.COMPLEX_0        ],
            ["Pole",        new Complex(0.25, -0.25),        new Complex(-0.2, -0.3),    Complex.COMPLEX_0,            new Complex(-0.8, 0.0)    ],
            ["Triangle",    Complex.COMPLEX_0,                new Complex(0.5, -0.5),        Complex.COMPLEX_0,            new Complex(0.5, 0.5)    ],
            ["Saw",            Complex.COMPLEX_0,                new Complex(0.0, -0.5),        new Complex(0.8, 0.0),        Complex.COMPLEX_0        ],
            ["Grid",        Complex.COMPLEX_0,                new Complex(0.0, 0.5),        Complex.COMPLEX_0,            new Complex(0.0, -0.5)    ],
            ["Thunder",        new Complex(-0.5, -0.2),        Complex.COMPLEX_0,            Complex.COMPLEX_0,            new Complex(0.0, 2 / 3)    ],
            ["Diamond",        new Complex(0.0, 0.75),            new Complex(0.25, 0.0),        new Complex(0.0, 0.75),        new Complex(0.25, 0.0)    ],
            ["RadioActive",    Complex.COMPLEX_0,                new Complex(0.5, 1.0),        Complex.COMPLEX_0,            new Complex(0.5, -1.0)    ],
            ["Frost",        new Complex(0.25, 0.5),            Complex.COMPLEX_0,            Complex.COMPLEX_0,            new Complex(0.75, 0.0)    ],
            ["Burr",        new Complex(-0.5, 0.35),        new Complex(0.5, -0.45),    new Complex(0.0, 0.225),    new Complex(Math.SQRT1_2, -0.35)    ],
            ["WindMill",    Complex.COMPLEX_0,                new Complex(-1.0, -1.0),    Complex.COMPLEX_0,            new Complex(-1.0, 1.0)    ]
        ];

        
        /**
         * コンストラクタ
         */ 
        public function PButtons() {
        }
        
        /**
         * 初期化
         * @param    sliders    スライダー集合
         */
        public function setup(sliders:PSliders):void {
            sliders_ = sliders;
            
            var w:int = 52;
            var h:int = 20;
            var pButtons:Array = [];
            for (var yCnt:int = 0; yCnt < 2; yCnt++) {
                for (var xCnt:int = 0; xCnt < 9; xCnt++) {
                    var pButton:PButton = new PButton();
                    var cnt:int = yCnt * 9 + xCnt;
                    pButton.setup(VALUES[cnt][0], VALUES[cnt][1], VALUES[cnt][2], VALUES[cnt][3], VALUES[cnt][4]);
                    pButton.addEventListener(MouseEvent.CLICK, clickHandler);
                    pButton.width  = w;
                    pButton.height = h;
                    addChild(pButton);
                    pButton.x = w * xCnt - 1;
                    pButton.y = h * yCnt;
                    pButtons.push(pButton);
                }
            }
        }
        
        // 各ボタンのイベントハンドラ
        private function clickHandler(e:MouseEvent):void {
            var pButton:PButton = PButton(e.target);
            sliders_.update([pButton.a, pButton.b, pButton.c, pButton.d]);
        }
    }
//}


//package {
    import com.bit101.components.PushButton;
    /**
     * 個別プリセットボタン
     * @author YOSHIDA, Akio (Aquioux)
     */
    /*public*/ class PButton extends PushButton {
        
        public function set sliders(value:PSliders):void { sliders_ = value; }
        private var sliders_:PSliders;    // スライダーへの参照
        
        public function get a():Complex { return _a; }
        private var _a:Complex;
        
        public function get b():Complex { return _b; }
        private var _b:Complex;
        
        public function get c():Complex { return _c; }
        private var _c:Complex;
        
        public function get d():Complex { return _d; }
        private var _d:Complex;
        

        /**
         * コンストラクタ
         */ 
        public function PButton() {
        }
        
        /**
         * 初期化
         * @param    label    ボタンのラベル
         * @param    a    複素数 a
         * @param    b    複素数 b
         * @param    c    複素数 c
         * @param    d    複素数 d
         */
        public function setup(label:String, a:Complex, b:Complex, c:Complex, d:Complex):void {
            this.label = label;
            _a = a;
            _b = b;
            _c = c;
            _d = d;
        }
    }
//}


//package {
    /**
     * 複素数クラス
     * @author YOSHIDA, Akio (Aquioux)
     */
    /*public*/ class Complex {
        /*
         * 実数部 real number
         */
        public function get r():Number { return _r; }
        public function set r(value:Number):void { _r = value; }
        private var _r:Number;
        
        /*
         * 虚数部 imaginary number
         */
        public function get i():Number { return _i; }
        public function set i(value:Number):void { _i = value; }
        private var _i:Number;
        
        /*
         * コンストラクタ
         * @param    r    実数部値
         * @param    i    虚数部値
         */
        public function Complex(r:Number = 0.0, i:Number = 0.0) {
            _r = r;
            _i = i;
        }
        

        // public な定数
        /*
         * 実数 0
         */
        public static const COMPLEX_0:Complex = new Complex(0.0, 0.0);
        /*
         * 実数 1
         */
        public static const COMPLEX_1:Complex = new Complex(1.0, 0.0);
        /*
         * 純虚数 i
         */
        public static const COMPLEX_i:Complex = new Complex(0.0, 1.0);
        
        
        // public な関数
        /*
         * 2項加算(ハミルトンの定義)
         */
        static public function add(z0:Complex, z1:Complex):Complex {
            return new Complex(z0.r + z1.r, z0.i + z1.i);
        }
        /*
         * 2項乗算(ハミルトンの定義)
         */
        static public function multiply(z0:Complex, z1:Complex):Complex {
            return new Complex((z0.r * z1.r) - (z0.i * z1.i), (z0.r * z1.i) + (z0.i * z1.r));
        }
    }
//}