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

Burning Ship Julia

Get Adobe Flash player
by Aquioux 04 Jan 2013
/**
 * Copyright Aquioux ( http://wonderfl.net/user/Aquioux )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/iM75
 */

package {
    //import aquioux.display.colorUtil.CycleRGB;
    //import aquioux.display.fractal.Buttons;
    //import aquioux.display.fractal.Engine;
    //import aquioux.display.fractal.InputBehavior;
    //import aquioux.display.fractal.Sliders;
    //import aquioux.display.fractal.Viewer;
    import com.bit101.components.PushButton;
    import flash.display.Sprite;
    import flash.events.Event;
    [SWF(width = "465", height = "465", frameRate = "60", backgroundColor = "#000000")]
    /**
     * Burning Ship Fractal の描画
     * @see    http://aquioux.net/blog/?p=3207
     * @author YOSHIDA, Akio (Aquioux)
     */
    public class Main extends Sprite {
        // ビューアサイズ
        private const WIDTH:int  = 450;
        private const HEIGHT:int = 450;
        
        // 各連携クラス
        private var calculator_:Julia;                // フラクタル計算クラス
        private var viewer_:Viewer;                    // ビューアクラス
        private var inputBehavior_:InputBehavior;    // ユーザー入力挙動クラス
        private var engine_:Engine;                    // フラクタル描画エンジンクラス
        private var sliders_:Sliders;                // スライダー
        private var complexButtons_:Buttons;        // プリセットパラメータボタン(複素数c)

        // ボタン構築用データ
        // 複素数c
        // 注意点:一番最初の値は、calclator の DEFAULT でなければならない
        private const PRESET_COMPLEX_DATA:Array = [
            ["-0.05 + 0.28i",    Vector.<Number>([-0.05, 0.28])],
            ["-0.324 + 0.13i",    Vector.<Number>([-0.324, 0.13])],
            ["-0.2 + 0.275i",    Vector.<Number>([-0.2, 0.275])],
            ["0.4 - 0.57i",        Vector.<Number>([0.4, -0.57])],
            ["0.46 + 0.19i",    Vector.<Number>([0.46, 0.19])],
            ["-0.78 - 1.1i",    Vector.<Number>([-0.78, -1.1])]
        ];
        // カラーリング
        private const PRESET_COLOR_DATA:Array = [
            ["mono",    Vector.<Number>([0])],
            ["color",    Vector.<Number>([1])]
        ];
        // カラーマップ配列
        private var colorMapList:Vector.<Vector.<uint>>;
        
        
        // コンストラクタ
        public function Main() {
            // カラーマップ生成
            colorMapList = new Vector.<Vector.<uint>>();
            // mono
            var degree:int  = 256;
            var step:Number = 0xFF / degree;
            var colorMap:Vector.<uint> = new Vector.<uint>(degree, true);
            for (var i:int = 0; i < degree; i++) {
                var c:uint = step * i;
                colorMap[i] = c << 16 | c << 8 | c;
            }
            colorMapList.push(colorMap);
            // color
            degree = 90;
            step   = 360 / (degree + 1);
            var start:int = Math.random() * 360 >> 0;
            colorMap = new Vector.<uint>(degree, true);
            for (i = 0; i < degree; i++) colorMap[i] = CycleRGB.getColor(i * step + start);
            colorMapList.push(colorMap);
            colorMapList.fixed = true;

            // フラクタル計算クラス
            calculator_ = new Julia();
            calculator_.colorMap = colorMap;
            
            // ビューアクラス
            viewer_ = new Viewer(WIDTH, HEIGHT);
            viewer_.heightOnceDraw = 5;
            addChild(viewer_);
            
            // ユーザー入力挙動クラス
            inputBehavior_ = new InputBehavior(viewer_);
            
            // フラクタル描画エンジンクラス
            engine_ = new Engine();
            engine_.viewer     = viewer_;
            engine_.controller = inputBehavior_;
            engine_.calculator = calculator_;
            
            // スライダー
            // スライダー構築用データ
            var sliderData:Array = [
                [
                    WIDTH,                                                            // 幅
                    stage.stageHeight - HEIGHT,                                        // 高
                    calculator_.DEFAULT_RECT.x,                                        // 最小値
                    calculator_.DEFAULT_RECT.width + calculator_.DEFAULT_RECT.x,    // 最大値
                    calculator_.DEFAULT_REAL_NUMBER                                    // デフォルト値
                ],    // 実数軸
                [
                    stage.stageWidth - WIDTH,
                    HEIGHT,
                    calculator_.DEFAULT_RECT.y,
                    calculator_.DEFAULT_RECT.height + calculator_.DEFAULT_RECT.y,
                    calculator_.DEFAULT_IMAGINARY_NUMBER
                ]    // 虚数軸
            ];
            sliders_ = new Sliders(sliderData);
            addChild(sliders_);
            sliders_.realAction = realSliderHandler;
            sliders_.imagAction = imagSliderHandler;
            
            // プリセットパラメータボタン
            // ボタンパラメータ
            var buttonWidth:int  = 75;
            var buttonHeight:int = 20;
            // 複素数c
            complexButtons_ = new Buttons(buttonWidth, buttonHeight, WIDTH, PRESET_COMPLEX_DATA);
            addChild(complexButtons_);
            complexButtons_.action = presetComplexButtonsHandler;
            // カラーリング
            var colorButtons:Buttons = new Buttons(buttonWidth, buttonHeight, WIDTH, PRESET_COLOR_DATA);
            colorButtons.y = buttonHeight;
            addChild(colorButtons);
            colorButtons.action = presetColorButtonsHandler;

            // リセットボタン
            // ズーム
            var zoomResetButton:PushButton = new PushButton(this, 0, 0, "ZoomReset", zoomResetButtonHandler);
            zoomResetButton.width  = buttonWidth;
            zoomResetButton.height = buttonHeight;
            zoomResetButton.y      = buttonHeight * 2;
            // 複素数c
            var complexResetButton:PushButton = new PushButton(this, buttonWidth, 0, "ComplexCReset", complexResetButtonHandler);
            complexResetButton.width  = buttonWidth;
            complexResetButton.height = buttonHeight;
            complexResetButton.x      = buttonWidth;
            complexResetButton.y      = buttonHeight * 2;
            
            // 初回の描画
            // 複素数c初期化
            calculator_.resetComplexC();
            // スライダー値更新
            sliders_.setRealValue(calculator_.c.real);
            sliders_.setImagValue(calculator_.c.imag);
            // プリセットパラメータボタンボタン初期選択
            complexButtons_.selectedButton(0);
            colorButtons.selectedButton(1);
            // ズーム初期化
            zoomResetButtonHandler(null);
        }
        
        // スライダーハンドラ
        // 実数軸
        private function realSliderHandler(val:Number):void {
            complexButtons_.releaseSelectedButton()
            calculator_.c.real = val;
            engine_.start();
        }
        // 虚数軸
        private function imagSliderHandler(val:Number):void {
            complexButtons_.releaseSelectedButton()
            calculator_.c.imag = val;
            engine_.start();
        }
        
        // プリセットパラメータボタンハンドラ
        // 複素数c
        private function presetComplexButtonsHandler(values:Vector.<Number>):void {
            calculator_.c.real = values[0];
            calculator_.c.imag = values[1];
            sliders_.setRealValue(calculator_.c.real);
            sliders_.setImagValue(calculator_.c.imag);
            engine_.start();
        }
        // カラーリング
        private function presetColorButtonsHandler(values:Vector.<Number>):void {
            calculator_.colorMap = colorMapList[values[0]];
            engine_.start();
        }

        // リセットボタンハンドラ
        // ズーム
        private function zoomResetButtonHandler(event:Event):void {
            engine_.reset();
            engine_.start();
        }
        // 複素数c
        private function complexResetButtonHandler(event:Event):void {
            complexButtons_.selectedButton(0);
            calculator_.resetComplexC();
            sliders_.setRealValue(calculator_.c.real);
            sliders_.setImagValue(calculator_.c.imag);
            engine_.start();
        }
    }
}

//package {
    //import aquioux.display.fractal.ICalculator;
    //import aquioux.math.Complex;
    import flash.geom.Rectangle;
    /**
     * Burning Ship Fractal 計算クラス
     * base : Julia
     * デフォルト時、(-2.0, -2.0) ~ (2.0, 2.0) の領域を計算する
     * @author YOSHIDA, Akio (Aquioux)
     */
    /*public*/ class Julia implements ICalculator {
        /**
         * 描画範囲
         */
        public function get DEFAULT_RECT():Rectangle { return RECTANGLE; }
        private const RECTANGLE:Rectangle = new Rectangle(START_X, START_Y, (END_X - START_X), (END_Y - START_Y));
        // 個別の開始座標、終了座標
        private const START_X:Number = -2.0;        // 開始X座標値
        private const START_Y:Number = -2.0;        // 開始Y座標値
        private const END_X:Number   =  2.0;        // 終了X座標値
        private const END_Y:Number   =  2.0;        // 終了Y座標値
        
        /**
         * 漸化式の c
         */
        public function get c():Complex { return _c; }
        private var _c:Complex = new Complex(DEFAULT_REAL_NUMBER, DEFAULT_IMAGINARY_NUMBER);
        // 複素数 c デフォルト
        public const DEFAULT_REAL_NUMBER:Number      = -0.05;
        public const DEFAULT_IMAGINARY_NUMBER:Number =  0.28;

        /**
         * 集合に該当する部分の色(一般的には色なし=黒)
         */
        public function set color(value:uint):void { _color = value; }
        private var _color:uint = 0x000000;
        /**
         * 発散部分のカラーリングマップ
         */
        public function set colorMap(value:Vector.<uint>):void {
            _colorMap = value;
            degree_   = value.length;
        }
        private var _colorMap:Vector.<uint>;
        
        // 発散チェックループ回数(_colorMap.length の値)
        private var degree_:int;
        

        /**
         * 複素数 c をデフォルトに戻す
         */
        public function resetComplexC():void {
            _c.real = DEFAULT_REAL_NUMBER;
            _c.imag = DEFAULT_IMAGINARY_NUMBER;
        }
        
        /**
         * 指定座標の計算をおこなう

         * @param    x    X座標値

         * @param    y    Y座標値

         * @return    計算結果

         */

        public function calculate(x:Number, y:Number):uint {

            var r:int = formula(x, y, _c.real, _c.imag);

            return (r >= 0) ? _colorMap[r] : _color;

        }

        /**

         * 漸化式:z ← (|Re[z]| + |Im[z]|i)^2 + c

         * @param    zRl    複素数 z の実数部

         * @param    zIm    複素数 z の虚数部

         * @param    cRl    複素数 c の実数部

         * @param    cIm    複素数 c の虚数部

         * @return    発散評価値

         * @private

         */

        private function formula(zRl:Number, zIm:Number, cRl:Number, cIm:Number):int {

            var i:int = degree_;

            while (i--) {

                // 発散の評価(|z| > 2 = |z|^2 > 4)

                var zRlSqr:Number = zRl * zRl;

                var zImSqr:Number = zIm * zIm;

                if (zRlSqr + zImSqr > 4) break;

                

                // バーニングシップ・フラクタル用前処理

                if (zRl < 0) zRl = -zRl;

                if (zIm < 0) zIm = -zIm;

                

                // 漸化式

                var zNextRl:Number = zRlSqr - zImSqr + cRl;

                zIm = zRl * zIm * 2 + cIm;

                zRl = zNextRl;

            }

            return i;

            // break で脱しなかった(発散しなかった)場合、while を回りきるので i は -1 になる

        }

    }

//}




//package aquioux.display.fractal {

    import flash.geom.Rectangle;

    /**

     * フラクタル計算クラスの interface

     * @author YOSHIDA, Akio (Aquioux)

     */

    /*public*/ interface ICalculator {

        function get DEFAULT_RECT():Rectangle;                // 描画範囲デフォルト値

        function set color(value:uint):void;                // 集合該当する部分の色

        function set colorMap(value:Vector.<uint>):void;    // 発散部分のカラーリングマップ

        function calculate(x:Number, y:Number):uint;        // 計算部

    }

//}



//package aquioux.display.fractal {

    import flash.events.Event;

    import flash.geom.Rectangle;

    /**

     * フラクタル描画エンジンクラス

     * @author YOSHIDA, Akio (Aquioux)

     */

    /*public*/ class Engine {

        /**

         * フラクタル計算クラス

         */

        public function set calculator(value:ICalculator):void { _calculator = value; }

        private var _calculator:ICalculator;

        

        /**

         * ユーザー入力挙動クラス

         */

        public function set controller(value:InputBehavior):void {

            _controller = value;

            _controller.addEventListener(InputBehavior.MOVING,  moveHandler);

            _controller.addEventListener(InputBehavior.ZOOMING, zoomHandler);

            _controller.addEventListener(Event.CHANGE, start);

        }

        private var _controller:InputBehavior;

        

        /**

         * ビューアクラス

         */

        public function set viewer(value:Viewer):void {

            _viewer = value;

            _viewer.addEventListener(Event.CHANGE, draw);

            displayWidth_  = _viewer.width;

            displayHeight_ = _viewer.height;

            dataLen_ = displayWidth_ * _viewer.drawRect.height;

            data_    = new Vector.<uint>(dataLen_, true);

        }

        private var _viewer:Viewer;

        

        /**

         * 描画計算領域を示す Rectangle

         */

        public function set rect(value:Rectangle):void {

            // 引数保持

            _rect = value;

            // 複素平面の走査開始座標を設定する

            startX_ = _rect.x;

            startY_ = _rect.y;

            // 複素平面の走査加算値を計算する

            stepX_ = _rect.width  / (displayWidth_  - 1);

            stepY_ = _rect.height / (displayHeight_ - 1);

        }

        private var _rect:Rectangle;

        



        // ビューア描画用データ

        private var data_:Vector.<uint>;

        // 描画ピクセル数(data_.length)

        private var dataLen_:int;

        

        // ビューアサイズ

        private var displayWidth_:int;        // 幅

        private var displayHeight_:int;        // 高



        // 複素平面の走査計算開始座標

        private var startX_:Number;            // 実数座標

        private var startY_:Number;            // 虚数座標



        // 複素平面の走査計算加算値

        private var stepX_:Number;            // 実数軸

        private var stepY_:Number;            // 虚数軸



        

        /**

         * 描画計算領域のリセット

         */

        public function reset():void {

            rect = _calculator.DEFAULT_RECT;

        }



        /**

         * 描画開始

         * @param    event    イベント

         */

        public function start(event:Event = null):void {

            if (event) {    // _controller の Event.CHANGE からの呼び出し

                var r:Rectangle = _controller.rect.clone();

                r.x = r.x * stepX_ + _rect.x;

                r.y = r.y * stepY_ + _rect.y;

                r.width  *= stepX_;

                r.height *= stepY_;

                rect = r;

            }

            _viewer.start();

        }

        // 描画実行

        private function draw(event:Event):void {

            // 描画部分の計算

            var drawOffset:int = _viewer.drawRect.y;

            for (var i:int = 0; i < dataLen_; i++) {

                var posX:int = i % displayWidth_;

                var posY:int = drawOffset + i / displayWidth_ >> 0;

                data_[i] = _calculator.calculate(posX * stepX_ + startX_, posY * stepY_ + startY_);

            }

            _viewer.draw(data_);

        }





        // 移動

        private function moveHandler(e:Event):void {

            _viewer.move(_controller.rect);

        }

        // 拡大・縮小

        private function zoomHandler(e:Event):void {

            _viewer.zoom(_controller.rect);

        }

    }

//}



//package aquioux.display.fractal {

    import flash.display.DisplayObject;

    import flash.events.Event;

    import flash.events.EventDispatcher;

    import flash.events.KeyboardEvent;

    import flash.events.MouseEvent;

    import flash.geom.Rectangle;

    /**

     * ユーザー入力挙動クラス

     * マウスドラッグ

     *   矩形を描く、マウスボタンを離すとその矩形領域を全体として表示(拡大)

     * cntl ボタン+マウスドラッグ

     *   表示領域の移動(移動)

     * マウスホイール

     *   マウスカーソル位置を中心に拡大(↑)・縮小(↓)

     * @author YOSHIDA, Akio (Aquioux)

     */

    /*public*/ class InputBehavior extends EventDispatcher {

        /**

         * 移動カスタムイベント

         */

        public static const MOVING:String  = "moving";

        /**

         * ズームカスタムイベント

         */

        public static const ZOOMING:String = "zooming";



        /**

         * マウス挙動 Rectangle

         */ 

        public function get rect():Rectangle { return _rect; }

        private var _rect:Rectangle = new Rectangle();





        // 矩形描画、移動に係る変数

        private var startX_:Number;        // ドラッグ開始X座標

        private var startY_:Number;        // ドラッグ開始Y座標

        private var moveX_:Number;        // ドラッグによる移動量(X軸方向)

        private var moveY_:Number;        // ドラッグによる移動量(Y軸方向)

        private var isCtrlDown_:Boolean = false;    // cntl キーダウン

        

        // マウス入力挙動対象

        private var target_:DisplayObject;

        



        /**

         * コンストラクタ

         * @param    target    マウス入力挙動対象

         */

        public function InputBehavior(target:DisplayObject) {

            // マウス入力挙動対象

            target_ = target;

            // マウスイベントハンドラ登録

            target_.addEventListener(MouseEvent.MOUSE_DOWN,  mouseDownHandler);

            target_.addEventListener(MouseEvent.MOUSE_WHEEL, mouseWheelHandler);

            // キーボードイベントハンドラ登録

            target_.stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);

            target_.stage.addEventListener(KeyboardEvent.KEY_UP,   keyUpHandler);

        }





        // マウスイベントハンドラ

        private function mouseDownHandler(event:MouseEvent):void {

            // 起点待避

            startX_ = target_.mouseX;

            startY_ = target_.mouseY;



            // マウスイベントハンドラ登録

            if (isCtrlDown_) {    // 移動

                _rect.width  = target_.width;

                _rect.height = target_.height;

                target_.addEventListener(MouseEvent.MOUSE_MOVE, moving);        // 移動中

                target_.addEventListener(MouseEvent.MOUSE_UP,   moved);            // 移動終了

            } else {            // 拡大

                target_.addEventListener(MouseEvent.MOUSE_MOVE, zooming);        // 拡大中

                target_.addEventListener(MouseEvent.MOUSE_UP,   zoomed);        // 拡大終了

            }

        }



        // マウスイベントハンドラ

        // 移動中

        private function moving(event:MouseEvent):void {

            // 移動量の計算

            moveX_ = startX_ - target_.mouseX;

            moveY_ = startY_ - target_.mouseY;

            // _rect 調整

            _rect.x = moveX_;

            _rect.y = moveY_;

            // イベント送出

            dispatchEvent(new Event(MOVING));

        }

        // 移動終了

        private function moved(event:MouseEvent):void {

            // マウスイベントハンドラ解除

            target_.removeEventListener(MouseEvent.MOUSE_MOVE, moving);

            target_.removeEventListener(MouseEvent.MOUSE_UP,   moved);

            // イベント送出

            update();

        }



        // 拡大中

        private function zooming(event:MouseEvent):void {

            // 移動量の計算

            moveX_ = target_.mouseX - startX_;

            moveY_ = target_.mouseY - startY_;

            // 選択領域を正方形にする

            // 絶対値を求める

            var isMinusWidth:Boolean  = moveX_ < 0 ? true : false;

            var isMinusHeight:Boolean = moveY_ < 0 ? true : false;

            if (isMinusWidth)  moveX_ *= -1;

            if (isMinusHeight) moveY_ *= -1;

            // 幅・高のうち大きい方を正方形の辺とする

            var edge:Number = moveX_ > moveY_ ? moveX_ : moveY_;

            moveX_ = edge;

            moveY_ = edge;

            // _rect 調整

            _rect.x      = startX_;

            _rect.y      = startY_;

            _rect.width  = moveX_;

            _rect.height = moveY_;

            if (isMinusWidth)  _rect.x -= _rect.width;

            if (isMinusHeight) _rect.y -= _rect.height;

            // イベント送出

            dispatchEvent(new Event(ZOOMING));

        }

        // 拡大終了

        private function zoomed(event:MouseEvent):void {

            // マウスイベントハンドラ解除

            target_.removeEventListener(MouseEvent.MOUSE_MOVE, zooming);

            target_.removeEventListener(MouseEvent.MOUSE_UP,   zoomed);

            // イベント送出

            update();

        }



        

        // マウスホイールイベントハンドラ

        private function mouseWheelHandler(event:MouseEvent):void {

            // マウスホイールの移動量をスケールに変換

            var delta:Number = event.delta * 0.5;

            delta = (delta < 0) ? -delta : 1 / delta;

            // _rect を計算

            var nowWidth:Number  = target_.width  * delta;

            var nowHeight:Number = target_.height * delta;

            _rect.x      = target_.mouseX - nowWidth  / 2;

            _rect.y      = target_.mouseY - nowHeight / 2;

            _rect.width  = nowWidth;

            _rect.height = nowHeight;

            // イベント送出

            update();

        }

        

        // イベント送出(マウスアップ時)

        private function update():void {

            dispatchEvent(new Event(Event.CHANGE));

        }

        



        // キーボードイベントハンドラ

        // キーダウン

        private function keyDownHandler(event:KeyboardEvent):void {

            if (event.ctrlKey) isCtrlDown_ = true;

        }

        // キーアップ

        private function keyUpHandler(event:KeyboardEvent):void {

            if (isCtrlDown_) isCtrlDown_ = false;

        }

    }

//}



//package aquioux.display.fractal {

    import flash.display.Bitmap;

    import flash.display.BitmapData;

    import flash.display.BlendMode;

    import flash.display.Graphics;

    import flash.display.Shape;

    import flash.display.Sprite;

    import flash.events.Event;

    import flash.geom.ColorTransform;

    import flash.geom.Point;

    import flash.geom.Rectangle;

    /**

     * ビューア

     * @author YOSHIDA, Akio (Aquioux)

     */

    /*public*/ class Viewer extends Sprite {

        /**

         * 1度の draw で描画する高さ(drawRect.y への加算値)

         */

        public function get heightOnceDraw():int { return _heightOnceDraw; }

        public function set heightOnceDraw(value:int):void {

            _heightOnceDraw  = value;

            _drawRect.height = value;

        }

        private var _heightOnceDraw:int = 1;



        /**

         * キャンバス描画 Rectangle(1度に描画するエリアを示す Rectangle)

         */

        public function get drawRect():Rectangle { return _drawRect; }    // read only

        private var _drawRect:Rectangle;

        

        // キャンバス

        private var canvas_:BitmapData;

        private var canvasRect_:Rectangle;



        // 移動ガイド

        private var moveGuideBm_:Bitmap;

        private var moveGuideBmd_:BitmapData;

        // 移動ガイド表示中か否か

        private var isMove_:Boolean = false;

        

        // ズームガイド

        private var zoomGuideGraphics_:Graphics;

        

        // 描画のために使いまわす Point

        private var destPoint_:Point = new Point();



        // 画面を暗くする効果用

        private const FADE:ColorTransform = new ColorTransform(0.75, 0.75, 0.75);



        

        /**

         * コンストラクタ

         * @param    w    描画幅

         * @param    h    描画高

         */

        public function Viewer(w:int, h:int) {

            // キャンバス生成

            canvas_ = new BitmapData(w, h, false, 0x0);

            addChild(new Bitmap(canvas_));

            canvasRect_ = canvas_.rect;

            

            // キャンバス描画 Rectangle 生成

            _drawRect = new Rectangle(0, 0, w, _heightOnceDraw);



            // 移動ガイド生成

            moveGuideBmd_ = canvas_.clone();

            moveGuideBm_  = new Bitmap(moveGuideBmd_);

            moveGuideBm_.alpha = 0;

            addChild(moveGuideBm_);

            

            // ズームガイド生成

            var zoomGuideShape:Shape = new Shape();

            zoomGuideShape.blendMode = BlendMode.INVERT;

            addChild(zoomGuideShape);

            zoomGuideGraphics_ = zoomGuideShape.graphics;

        }



        /**

         * 移動時の挙動

         * @param    rect    挙動を制御する Rectangle

         */

        public function move(rect:Rectangle):void {

            if (!isMove_) {    // 移動開始時

                // キャンバス全体を暗くする

                canvas_.colorTransform(canvasRect_, FADE);

                // ガイドの生成(キャンバスをそのまま写す)

                destPoint_.x = 0;

                destPoint_.y = 0;

                moveGuideBmd_.copyPixels(canvas_, canvasRect_, destPoint_);

                moveGuideBm_.alpha = 0.5;

                isMove_ = true;

            }

            

            // 移動ガイドの移動

            moveGuideBm_.x = -rect.x;

            moveGuideBm_.y = -rect.y;

        }

        

        /**

         * ズーム時の挙動

         * @param    rect    挙動を制御する Rectangle

         */

        public function zoom(rect:Rectangle):void {

            // ズーム用枠の表示

            zoomGuideGraphics_.clear();

            zoomGuideGraphics_.lineStyle(0, 0x0);

            zoomGuideGraphics_.drawRect(rect.x, rect.y, rect.width, rect.height);

        }

        



        /**

         * 描画開始

         */

        public function start():void {

            if (isMove_) {    // 移動から呼び出されたとき

                // destPoint を更新

                destPoint_.x = moveGuideBm_.x;

                destPoint_.y = moveGuideBm_.y;

                // 移動ガイドをキャンバスに描画

                canvas_.lock();

                canvas_.copyPixels(moveGuideBmd_, canvasRect_, destPoint_);

                canvas_.unlock();

                // 移動ガイドの後処理

                moveGuideBm_.alpha = 0;

                moveGuideBm_.x = 0;

                moveGuideBm_.y = 0;

                isMove_ = false;

            } else {        // ズームから呼び出されたとき

                // ズームガイドに表示された枠を消す

                zoomGuideGraphics_.clear();

                // キャンバスを暗くする

                canvas_.colorTransform(canvasRect_, FADE);

            }

            

            // キャンバス描画 Rectangle の初期化

            _drawRect.y = 0;

            // ENTER_FRAME イベント開始

            addEventListener(Event.ENTER_FRAME, function():void { dispatchEvent(new Event(Event.CHANGE)); } );

        }

        /**

         * 描画実行

         * @param    data    キャンバスを描くための Vector.<uint>

         */

        public function draw(data:Vector.<uint>):void {

            // 指定領域の更新

            canvas_.lock();

            canvas_.setVector(_drawRect, data);

            canvas_.unlock();

            // キャンバス描画 Rectangle の更新

            _drawRect.y += _heightOnceDraw;

            // 終了判定

            if (_drawRect.y >= canvas_.width) removeEventListener(Event.ENTER_FRAME, arguments.callee);

        }

    }

//}



//package aquioux.display.fractal {

    import com.bit101.components.PushButton;

    import flash.display.Sprite;

    import flash.events.Event;

    import flash.utils.Dictionary;

    /**

     * プリセットパラメータボタン

     * @author YOSHIDA, Akio (Aquioux)

     */

    /*public*/ class Buttons extends Sprite {

        /**

         * ボタンアクション(外部で定義する)

         */

        public function set action(value:Function):void { _action = value; }

        private var _action:Function;

        

        // 前回押したボタン

        private var prevButton_:PushButton;

        

        // ボタンの配列

        private var buttonList_:Vector.<PushButton>



        // _action への引数を格納する Dictionary

        private var valueList_:Dictionary;

        

        

        /**

         * コンストラクタ

         * @param    buttonWidth    ひとつのボタンの幅

         * @param    buttonHeight    ひとつのボタンの高さ

         * @param    stageWidth    ボタンを配置する幅

         * @param    data    ボタンが担う値

         */

        public function Buttons(buttonWidth:int, buttonHeight:int, stageWidth:int, data:Array) {

            var numOfButtonRow:int     = stageWidth / buttonWidth >> 0;        // 1行に配置されるボタンの数

            var numOfButtonLastRow:int = data.length % numOfButtonRow;        // 最後の行に配置されるボタンの数

            var numOfButtonCol:int     = data.length / numOfButtonRow >> 0;    // ボタンが配置されるの列の数

            var yLimit:int = (numOfButtonLastRow == 0) ? numOfButtonCol : numOfButtonCol + 1;

            var xLimit:int = numOfButtonRow;

            var idx:int    = 0;

            valueList_  = new Dictionary();

            buttonList_ = new Vector.<PushButton>();

            for (var y:int = 0; y < yLimit; y++) {

                if ((numOfButtonLastRow != 0) && (y == numOfButtonCol)) xLimit = numOfButtonLastRow;

                for (var x:int = 0; x < xLimit; x++) {

                    var b:PushButton = new PushButton(this, buttonWidth * x, buttonHeight * y, data[idx][0], handler);

                    b.width  = buttonWidth;

                    b.height = buttonHeight;

                    valueList_[b]    = data[idx][1];

                    buttonList_[idx] = b;

                    idx++;

                }

            }

        }

        

        /**

         * 指定のボタンを、外部から押した状態にする

         */

        public function selectedButton(idx:int):void {

            if (idx < buttonList_.length) {

                buttonAction(buttonList_[idx]);

            } else {

                throw new Error("指定したインデックス値がボタンの数より大きい値です。");

            }

        }

        /**

         * 現在選択されているボタンを、外部から解除する

         */

        public function releaseSelectedButton():void {

            if (prevButton_) prevButton_.enabled = true;

        }



        // ボタンハンドラ

        private function handler(e:Event):void {

            buttonAction(PushButton(e.target));

        }



        // ボタンを押したときの挙動

        private function buttonAction(target:PushButton):void {

            // 前回押されたボタンを有効にする

            releaseSelectedButton();

            // 今回押されたボタンを無効にする

            target.enabled = false;

            prevButton_ = target;

            // 外部から指定したボタンアクションを実行する

            _action(valueList_[target]);

        }

    }

//}



//package aquioux.display.fractal {

    import com.bit101.components.HSlider;

    import com.bit101.components.Label;

    import com.bit101.components.VSlider;

    import flash.display.BlendMode;

    import flash.display.Sprite;

    import flash.events.MouseEvent;

    /**

     * 複素数c用スライダー

     * @author YOSHIDA, Akio (Aquioux)

     */

    /*public*/ class Sliders extends Sprite {

        /**

         * 実数軸スライダーアクション(外部で定義する)

         */

        public function set realAction(value:Function):void { _realAction = value; }

        private var _realAction:Function;

        /**

         * 虚数軸スライダーアクション(外部で定義する)

         */

        public function set imagAction(value:Function):void { _imagAction = value; }

        private var _imagAction:Function;



        // スライダー

        private var hSlider_:HSlider;        // 横

        private var vSlider_:VSlider;        // 縦

        // ラベル

        private var hLabel_:Label;            // 横スライダー用

        private var vLabel_:Label;            // 縦スライダー用

        

        // マウスダウンフラグ

        private var isMouseDownH_:Boolean;    // 横スライダー用

        private var isMouseDownV_:Boolean;    // 縦スライダー用

        



        /**

         * コンストラクタ

         * @param    values    各種パラメータ

         */

        public function Sliders(values:Array) {

            // 横スライダー(複素数cの実数部)

            hSlider_ = new HSlider(this, 0, values[1][1]);

            hSlider_.width  = values[0][0];

            hSlider_.height = values[0][1];

            hSlider_.tick   = 0.001;

            hSlider_.setSliderParams(values[0][2], values[0][3], values[0][4]);



            // 縦スライダー(複素数cの虚数部)

            vSlider_ = new VSlider(this, values[0][0], 0);

            vSlider_.width  = values[1][0];

            vSlider_.height = values[1][1];

            vSlider_.tick   = 0.001;

            vSlider_.setSliderParams(values[1][2], values[1][3], values[1][4]);



            // マウスハンドラ

            // スライダーに直接ハンドラを設定すると ENTER_FRAME のタイミングで更新がかかり、

            // 処理負荷が大きくなるため、マウスアップ時にスライダハンドラを実行させる

            hSlider_.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHHandler);

            vSlider_.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownVHandler);

            hSlider_.addEventListener(MouseEvent.MOUSE_UP,   mouseUpHHandler);

            vSlider_.addEventListener(MouseEvent.MOUSE_UP,   mouseUpVHandler);

            

            // ラベルパラメータ

            var labelHeight:int = 15;

            var offset:int = 5;

            // 横スライダー用ラベル

            hLabel_ = new Label(this, 0, hSlider_.y - (labelHeight * 2 + offset));

            hLabel_.blendMode = BlendMode.INVERT;

            // 縦スライダー用ラベル

            vLabel_ = new Label(this, 0, hSlider_.y - (labelHeight     + offset));

            vLabel_.blendMode = BlendMode.INVERT;

        }

        

        /**

         * 外部からのスライダー値更新(実数軸)

         * @param    val    更新値

         */

        public function setRealValue(val:Number):void {

            hSlider_.value = val;

            hlabelUpdate(val);

        }

        /**

         * 外部からのスライダー値更新(虚数軸)

         * @param    val    更新値

         */

        public function setImagValue(val:Number):void {

            vSlider_.value = val;

            vlabelUpdate(val);

        }

        

        // スライダーハンドラ

        private function hsliderHandler():void {

            var val:Number = hSlider_.value

            // ラベル更新

            hlabelUpdate(val);

            // 外部から指定したスライダーアクションを実行する

            _realAction(val);

        }

        private function vsliderHandler():void {

            var val:Number = vSlider_.value

            // ラベル更新

            vlabelUpdate(val);

            // 外部から指定したスライダーアクションを実行する

            _imagAction(val);

        }

        

        // ラベル書換

        private function hlabelUpdate(val:Number):void {

            hLabel_.text = "real : " + String(val);

        }

        private function vlabelUpdate(val:Number):void {

            vLabel_.text = "imag : " + String(val);

        }



        // マウスハンドラ

        private function mouseDownHHandler(event:MouseEvent):void {

            isMouseDownH_ = true;

            isMouseDownV_ = false;

        }

        private function mouseDownVHandler(event:MouseEvent):void {

            isMouseDownV_ = true;

            isMouseDownH_ = false;

        }

        private function mouseUpHHandler(event:MouseEvent):void {

            if (isMouseDownH_) hsliderHandler();

            isMouseDownH_ = false;

        }

        private function mouseUpVHandler(event:MouseEvent):void {

            if (isMouseDownV_) vsliderHandler();

            isMouseDownV_ = false;

        }

    }
//}

//package aquioux.math {
    /**
     * 複素数
     * @author Aquioux(Yoshida, Akio)
     */
    /*public*/ final class Complex {
        // 実数部
        public function get real():Number { return _rl; }
        public function set real(value:Number):void { _rl = value; }
        private var _rl:Number;
        // 虚数部
        public function get imag():Number { return _im; }
        public function set imag(value:Number):void { _im = value; }
        private var _im:Number;
        

        // コンストラクタ
        public function Complex(rl:Number = 0, im:Number = 0) {
            _rl = rl;
            _im = im;
        }
        
        // 複製
        public function clone():Complex {
            return new Complex(_rl, _im);
        }
        
        public function toString():String {
            return _rl + " + " + _im + "i";
        }
    }
//}

//package aquioux.display.colorUtil {
    /**
     * コサインカーブで色相環的な RGB を計算
     * @author Aquioux(YOSHIDA, Akio)
     */
    /*public*/ class CycleRGB {
        /**
         * 32bit カラーのためのアルファ値(0~255)
         */
        static public function get alpha():uint { return _alpha; }
        static public function set alpha(value:uint):void {
            _alpha = (value > 0xFF) ? 0xFF : value;
        }
        private static var _alpha:uint = 0xFF;
    
        private static const PI:Number = Math.PI;        // 円周率
        private static const DEGREE120:Number  = PI * 2 / 3;    // 120度(弧度法形式)
        
        /**
         * 角度に応じた RGB を得る
         * @param    angle    HSV のように角度(度数法)を指定
         * @return    色(0xNNNNNN)
         */
        public static function getColor(angle:Number):uint {
            var radian:Number = angle * PI / 180;
            var r:uint = (Math.cos(radian)             + 1) * 0xFF >> 1;
            var g:uint = (Math.cos(radian + DEGREE120) + 1) * 0xFF >> 1;
            var b:uint = (Math.cos(radian - DEGREE120) + 1) * 0xFF >> 1;
            return r << 16 | g << 8 | b;
        }
        
        /**
         * 角度に応じた RGB を得る(32bit カラー)
         * @param    angle    HSV のように角度(度数法)を指定
         * @return    色(0xNNNNNNNN)
         */
        public static function getColor32(angle:Number):uint {
            return _alpha << 24 | getColor(angle);
        }
    }
//}