Beautifl - Flash Gallery

Thumbnail : [Math] Integral Simulation
[Math] Integral Simulation
clockmaker 2010-03-27 MIT License

再生するにはFlash Playerが必要です。デスクトップのブラウザでご覧ください。

/*
   積分の復習
   区分求積法的なことをAS3でやってみる。
   微小な短冊形の長方形を敷き詰め、
   その長方形の面積の総和によって関数の面積を確定する方法。
 */
package {
    import flash.display.Sprite;
    
    [SWF(width="465", height="465", frameRate="60")]
    public class Main extends Sprite {
        public function Main() {
            // ビュー
            view = new View();
            addChild(view);
            // コントローラー
            controller = new Controller();
            addChild(controller);
            // モデル
            model = new Model(view, controller);
        }
        private var controller:Controller;
        private var model:Model;
        private var view:View;
    }
}
import com.bit101.components.Label;
import com.bit101.components.PushButton;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.Rectangle;
import jp.nium.utils.NumberUtil;
import jp.progression.commands.Func;
import jp.progression.commands.lists.TweenList;

/**
 * MVCのModelを担当するクラスです。
 */
class Model {
    /**
     * 計算を行うxの最大値です。
     */
    public static const MAX_X:Number = 400;
    
    /**
     * 新しいModelインスタンスを作成します。
     */
    public function Model(view:View, controller:Controller):void {
        _view = view;
        _controller = controller;
        _controller.addEventListener(Controller.STEP_0_EVENT, _onClick);
        _controller.addEventListener(Controller.STEP_1_EVENT, _onClick);
        _controller.addEventListener(Controller.STEP_2_EVENT, _onClick);
        _controller.addEventListener(Controller.STEP_3_EVENT, _onClick);
    }
    private var _controller:Controller;
    private var _view:View;
    
    /**
     * 二次曲線の関数
     * @param value x
     * @return y
     */
    private function _func(value:Number):Number {
        return 0.002 * value * value + 50;
    }
    
    /**
     * コントローラーのイベントハンドラー
     * @param event
     */
    private function _onClick(event:Event):void {
        var calcStep:int;
        switch (event.type) {
            case Controller.STEP_0_EVENT:
                calcStep = Controller.STEP_0_NUM;
                break;
            case Controller.STEP_1_EVENT:
                calcStep = Controller.STEP_1_NUM;
                break;
            case Controller.STEP_2_EVENT:
                calcStep = Controller.STEP_2_NUM;
                break;
            case Controller.STEP_3_EVENT:
                calcStep = Controller.STEP_3_NUM;
                break;
        }
        var results:Vector.<Number> = new Vector.<Number>();
        for (var i:int = 0; i < MAX_X; i++) {
            results[ i ] = _func(i);
        }
        var integrate:Vector.<IntegrateData> = new Vector.<IntegrateData>();
        for (i = 0; i < calcStep; i++) {
            integrate[ i ] = new IntegrateData();
            integrate[ i ].value = _func(MAX_X / calcStep * i);
            var add:Number = integrate[ i ].value * MAX_X / calcStep;
            integrate[ i ].sum = i == 0 ? add : integrate[ i - 1 ].sum + add;
        }
        _view.draw(results, integrate);
    }
}

/**
 * 区分積分の値を保持するクラスです。
 */
class IntegrateData {
    /**
     * n=xまでの加算値を保持します。
     * Viewでの表示のために設けた変数です。
     */
    public var sum:Number = 0;
    /**
     * dxの計算結果を保持します。
     */
    public var value:Number = 0;
}

/**
 * MVCのViewを担当するクラスです。
 */
class View extends Sprite {
    private static const GRAPH_RECT:Rectangle = new Rectangle(15, 15, 440, 400);
    private static const STAGE_RECT:Rectangle = new Rectangle(0, 0, 465, 465);
    private static const STEP:Number = 20;
    
    /**
     * 新しいViewインスタンスを作成します。
     */
    public function View():void {
        // 背景
        _bg = new Shape();
        _bg.graphics.beginFill(0);
        _bg.graphics.drawRect(STAGE_RECT.x, STAGE_RECT.y, STAGE_RECT.width, STAGE_RECT.height);
        addChild(_bg);
        
        // 目盛り
        _division = new Shape();
        _division.graphics.lineStyle(1, 0x333333);
        for (var i:int = 0; i <= GRAPH_RECT.width; i++) {
            if (i % STEP == 0) {
                _division.graphics.moveTo(i, 0);
                _division.graphics.lineTo(i, GRAPH_RECT.height);
            }
        }
        for (var j:int = 0; j <= GRAPH_RECT.height; j++) {
            if (j % STEP == 0) {
                _division.graphics.moveTo(0, j);
                _division.graphics.lineTo(GRAPH_RECT.width, j);
            }
        }
        _division.x = GRAPH_RECT.x;
        _division.y = GRAPH_RECT.y;
        addChild(_division);
        
        // グラフ
        _canvas = new Sprite();
        _canvas.x = GRAPH_RECT.x;
        _canvas.y = GRAPH_RECT.y;
        addChild(_canvas);
        
        new Label(this, 17, 17, "INTEGRATION APP");
        _sumLabel = new Label(this, 17, 36, "SUM : 0");
    }
    private var _bg:Shape;
    private var _canvas:Sprite;
    private var _cmd:TweenList;
    private var _division:Shape;
    private var _integrate:Vector.<IntegrateData>;
    private var _results:Vector.<Number>;
    private var _sumLabel:Label;
    
    /**
     * Modelで計算した結果を描写します
     */
    public function draw(results:Vector.<Number>, integrate:Vector.<IntegrateData>):void {
        _results = results;
        _integrate = integrate;
        _canvas.graphics.clear();
        _drawResults();
        if (_cmd && _cmd.state != 0)
            _cmd.interrupt();
        _cmd = new TweenList(1);
        for (var i:int = 0; i < _integrate.length; i++) {
            _cmd.addCommand(new Func(_drawIntegrate, [ i ]));
        }
        _cmd.execute();
    }
    
    /**
     * 区分積分の結果を描写します
     */
    private function _drawIntegrate(i:int):void {
        _canvas.graphics.lineStyle(1, 0xFFFFFF);
        _canvas.graphics.beginFill(0xFFFFFF, 0.25);
        _canvas.graphics.drawRect(i * GRAPH_RECT.width / _integrate.length, GRAPH_RECT.height - _integrate[ i ].value, GRAPH_RECT.width / _integrate.length, _integrate[ i ].value);
        _canvas.graphics.endFill();
        _sumLabel.text = "SUM : " + NumberUtil.format(Math.round(_integrate[ i ].sum));
    }
    
    /**
     * 二次曲線の結果を描写します
     */
    private function _drawResults():void {
        for (var i:int = 0; i < _results.length; i++) {
            if (i == _results.length - 1)
                continue;
            _canvas.graphics.lineStyle(1, 0xFF0000);
            _canvas.graphics.moveTo(i * GRAPH_RECT.width / _results.length, GRAPH_RECT.height - _results[ i ]);
            _canvas.graphics.lineTo((i + 1) * GRAPH_RECT.width / _results.length, GRAPH_RECT.height - _results[ i + 1 ]);
        }
    }
}

/**
 * MVCのControllerを担当するクラスです。
 */
class Controller extends Sprite {
    public static const STEP_0_EVENT:String = "stepBig";
    public static const STEP_0_NUM:int = 10;
    public static const STEP_1_EVENT:String = "stepMiddle";
    public static const STEP_1_NUM:int = 20;
    public static const STEP_2_EVENT:String = "stepSmall";
    public static const STEP_2_NUM:int = 50;
    public static const STEP_3_EVENT:String = "stepNano";
    public static const STEP_3_NUM:int = 120;
    
    /**
     * 新しいControllerインスタンスを作成します。
     */
    public function Controller() {
        _btnA = new PushButton(this, 15, 430, "CALC n=" + STEP_0_NUM, _onClick);
        _btnB = new PushButton(this, 125, 430, "CALC n=" + STEP_1_NUM, _onClick);
        _btnC = new PushButton(this, 235, 430, "CALC n=" + STEP_2_NUM, _onClick);
        _btnD = new PushButton(this, 345, 430, "CALC n=" + STEP_3_NUM, _onClick);
    }
    private var _btnA:PushButton;
    private var _btnB:PushButton;
    private var _btnC:PushButton;
    private var _btnD:PushButton;
    
    /**
     * @private
     */
    private function _onClick(e:Event):void {
        switch (e.currentTarget) {
            case _btnA:
                dispatchEvent(new Event(STEP_0_EVENT));
                break;
            case _btnB:
                dispatchEvent(new Event(STEP_1_EVENT));
                break;
            case _btnC:
                dispatchEvent(new Event(STEP_2_EVENT));
                break;
            case _btnD:
                dispatchEvent(new Event(STEP_3_EVENT));
                break;
        }
    }
}