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

Glynn Fractal(z^1.75+c)

/**
 * Copyright Aquioux ( http://wonderfl.net/user/Aquioux )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/lMkd
 */

package {
    //import aquioux.display.colorUtil.CycleRGB;
    //import aquioux.display.fractal.*;
    import com.bit101.components.HSlider;
    import com.bit101.components.Label;
    import com.bit101.components.PushButton;
    import com.bit101.components.VSlider;
    import flash.display.BlendMode;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    [SWF(width = "465", height = "465", frameRate = "60", backgroundColor = "#000000")]
    /**
     *  の描画
     * @see    http://aquioux.net/blog/?p=3107
     * @see    http://wonderfl.net/c/8Btj
     * @author Aquioux(Yoshida, Akio)
     */
    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 hslider_:HSlider;                // 横スライダー
        private var vslider_:VSlider;                // 縦スライダー
        private var hlabel_:Label;                    // 横スライダーのラベル
        private var vlabel_:Label;                    // 縦スライダーのラベル
        private var complexButtons_:Buttons;        // プリセットパラメータボタン(複素数c)
        private var colorButtons_:Buttons;            // プリセットパラメータボタン(カラーリング)
        
        // マウスダウンフラグ
        private var isMouseDownH_:Boolean;
        private var isMouseDownV_:Boolean;

        // ボタンのラベルとプロパティ値のペア(複素数c)
        private const COMPLEX_DATA:Array = [
            ["-0.375 + 0i",    Vector.<Number>([-0.375, 0])],
            ["-0.375 + 0.01i", Vector.<Number>([-0.375, 0.01])],
            ["-0.338 + 0i",    Vector.<Number>([-0.338, 0])],
            ["0.22 + 0i",      Vector.<Number>([0.22, 0])],
            ["0.34 - 0.14i",   Vector.<Number>([0.34, -0.14])],
            ["-0.36 + 0.57i",  Vector.<Number>([-0.36, 0.57])]
        ];

        // ボタンのラベルとプロパティ値のペア(カラーリング)
        private const 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  = 128;
            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  = 120;
            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);
            addChild(viewer_);
            
            // ユーザー入力挙動クラス
            inputBehavior_ = new InputBehavior(viewer_);
            
            // フラクタル描画エンジンクラス
            engine_ = new Engine();
            engine_.viewer     = viewer_;
            engine_.controller = inputBehavior_;
            engine_.calculator = calculator_;
            
            // ボタンパラメータ
            var buttonWidth:int  = 75;
            var buttonHeight:int = 20;
            // プリセットパラメータボタン(複素数c)
            complexButtons_ = new Buttons(buttonWidth, buttonHeight, WIDTH, COMPLEX_DATA);
            addChild(complexButtons_);
            complexButtons_.action = presetComplexButtonHandler;
            // プリセットパラメータボタン(カラーリング)
            colorButtons_ = new Buttons(buttonWidth, buttonHeight, WIDTH, COLOR_DATA);
            colorButtons_.y = buttonHeight;
            addChild(colorButtons_);
            colorButtons_.action = presetColorButtonHandler;
            // ズームリセットボタン
            var zoomResetButton:PushButton = new PushButton(this, 0, 0, "ZoomReset", zoomResetButtonHandler);
            zoomResetButton.width  = buttonWidth;
            zoomResetButton.height = buttonHeight;
            zoomResetButton.x      = buttonWidth * COLOR_DATA.length;
            zoomResetButton.y      = buttonHeight;
            // 複素数 c リセットボタン
            var complexResetButton:PushButton = new PushButton(this, buttonWidth, 0, "ComplexCReset", complexResetButtonHandler);
            complexResetButton.width  = buttonWidth;
            complexResetButton.height = buttonHeight;
            complexResetButton.x      = buttonWidth * (COLOR_DATA.length + 1);
            complexResetButton.y      = buttonHeight;

            // スライダーパラメータ
            var sliderValueMin:Number = calculator_.DEFAULT_RECT.x;
            var sliderValueMax:Number = calculator_.DEFAULT_RECT.width + sliderValueMin;
            var sliderLongEdge:int  = WIDTH;                    // スライダーの長辺
            var sliderShortEdge:int = stage.stageWidth - WIDTH;    // スライダーの短辺
            // 横スライダー(複素数 c の実数部)
            hslider_ = new HSlider(this, 0, HEIGHT);
            hslider_.width  = sliderLongEdge;
            hslider_.height = sliderShortEdge;
            hslider_.tick   = 0.001;
            hslider_.setSliderParams(sliderValueMin, sliderValueMax, calculator_.DEFAULT_REAL_NUMBER);
            // 縦スライダー(複素数 c の虚数部)
            vslider_ = new VSlider(this, WIDTH, 0);
            vslider_.width  = sliderShortEdge;
            vslider_.height = sliderLongEdge;
            vslider_.tick   = 0.001;
            vslider_.setSliderParams(sliderValueMin, sliderValueMax, calculator_.DEFAULT_IMAGINARY_NUMBER);
            // マウスハンドラ
            // スライダーに直接ハンドラを設定すると 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);
            
            // ラベル
            // 横スライダーのラベル
            hlabel_ = new Label(this, 0, HEIGHT - (15 * 2 + 5));
            hlabel_.blendMode = BlendMode.INVERT;
            // 縦スライダーのラベル
            vlabel_ = new Label(this, 0, HEIGHT - (15 + 5));
            vlabel_.blendMode = BlendMode.INVERT;
            
            // 初回の描画
            calculator_.reset();
            hlabelUpdate();
            vlabelUpdate();
            colorButtons_.selected(1);
            complexButtons_.selected(0);
            zoomResetButtonHandler(null);
        }
        
        // プリセットパラメータボタンハンドラ(複素数c)
        private function presetComplexButtonHandler(values:Vector.<Number>):void {
            calculator_.c.real = values[0];
            calculator_.c.imag = values[1];
            hlabelUpdate();
            vlabelUpdate();
            hslider_.value = calculator_.c.real;
            vslider_.value = calculator_.c.imag;
            engine_.start();
        }
        // プリセットパラメータボタンハンドラ(カラーリング)
        private function presetColorButtonHandler(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_.selected(0);
            calculator_.reset();
            hlabelUpdate();
            vlabelUpdate();
            hslider_.value = calculator_.c.real;
            vslider_.value = calculator_.c.imag;
            engine_.start();
        }
        
        // マウスハンドラ
        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;
        }
        
        // スライダーハンドラ
        private function hsliderHandler():void {
            complexButtons_.releaseSelectedButton();
            calculator_.c.real = hslider_.value;
            hlabelUpdate();
            engine_.start();
        }
        private function vsliderHandler():void {
            complexButtons_.releaseSelectedButton();
            calculator_.c.imag = vslider_.value;
            vlabelUpdate();
            engine_.start();
        }
        
        // ラベル処理
        private function hlabelUpdate():void {
            hlabel_.text = "real : " + String(calculator_.c.real);
        }
        private function vlabelUpdate():void {
            vlabel_.text = "imag : " + String(calculator_.c.imag);
        }
    }
}

//package {
    //import aquioux.display.fractal.ICalculator;
    //import aquioux.math.Complex;
    import flash.geom.Rectangle;
    /**
     * Glynn Fractal 計算クラス
     * base :Julia
     * デフォルト時、(-2.0, -2.0) ~ (2.0, 2.0) の領域を計算する
     * @author Aquioux(Yoshida, Akio)
     */
    /*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.375;
        public const DEFAULT_IMAGINARY_NUMBER:Number =  0.0;

        /**
         * 集合に該当する部分の色(一般的には色なし=黒)
         */
        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 reset():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 ← z^1.75 + 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;
                var zSqr:Number   = zRlSqr + zImSqr;
                if (zSqr > 4) break;
                
                // 漸化式(ド・モアブルの定理)
                // 局座標値化
                var radian:Number = Math.atan2(zIm, zRl);
                var dist1:Number  = Math.sqrt(zSqr);
                // 冪乗計算
                // 偏角
                radian *= 1.75;
                // 距離
                var dist2:Number = dist1 * dist1 * dist1 * dist1 * dist1 * dist1 * dist1;
                var dist3:Number = Math.pow(dist2, 0.25);
                // 直交座標値化
                zRl = Math.cos(radian) * dist3 + cRl;
                zIm = Math.sin(radian) * dist3 + cIm;
            }
            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 Aquioux(Yoshida, Akio)
     */
    /*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 Aquioux(Yoshida, Akio)
     */
    /*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;
        
        /**
         * インストラクタ
         */
        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 selected(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.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);
        }
    }
//}

//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";
        }
    }
//}