[Math] Integral Simulation
積分の復習
区分求積法的なことをAS3でやってみる。
微小な短冊形の長方形を敷き詰め、
その長方形の面積の総和によって関数の面積を確定する方法。
/**
* Copyright clockmaker ( http://wonderfl.net/user/clockmaker )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/bvqp
*/
/*
積分の復習
区分求積法的なことを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;
}
}
}