正規分布するような乱数
スライダーで偏差やらなんやら設定してRunで動く。
別アプリ用にパラメーターの試験用とかなんとか。ENTER_FRAME使わない方がツールとしては便利。
/**
* Copyright kske ( http://wonderfl.net/user/kske )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/v0mm
*/
package {
import com.bit101.components.Label;
import flash.geom.Vector3D;
import flash.geom.Rectangle;
import flash.events.MouseEvent;
import flash.events.Event;
import com.bit101.components.Panel;
import com.bit101.components.PushButton;
import com.bit101.components.HSlider;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.display.Bitmap;
public class BMTest extends Sprite {
private var canvas:BitmapData;
private var bitmap:Bitmap;
private var MeanSlider:HSlider;
private var StdDevSlider:HSlider;
private var runButton:PushButton;
private var meanLabel:Label;
private var devLabel:Label;
private var activeParticles:Vector.<Particle>;
private var restParticles:Vector.<Particle>;
private static var MAX_SAMPLE:int = 10000;
private static var CREATE_PER_FRAME:int = 5;
private static var STEP_PER_FRAME:int = 4;
private var samples:int;
private var bmt:BMTRandom;
private var values:Array;
private var isStarted:Boolean;
[SWF(backgoundColor=0x0, frameRate="60", width=465, height=465)]
public function BMTest() {
addEventListener(Event.ADDED_TO_STAGE, init);
//run(0, 1, 0xff44ccc, canvas);
}
private function init(e:Event):void{
removeEventListener(Event.ADDED_TO_STAGE, arguments.callee);
canvas = new BitmapData(465, 465, true, 0xff000000);
bitmap = new Bitmap(canvas);
addChild(bitmap);
isStarted = false;
samples = 0;
createControls();
}
// initが長くなりそうだからminimalcompsはこっちに
private function createControls():void{
MeanSlider = new HSlider(this, 10, 5);
MeanSlider.maximum = 3;
MeanSlider.minimum = -3;
meanLabel = new Label(this, 110, 0, "0.0");
StdDevSlider = new HSlider(this, 10, 17);
StdDevSlider.maximum = 3;
StdDevSlider.minimum = 0.2;
devLabel = new Label(this, 110, 12, "0.2");
MeanSlider.addEventListener(Event.CHANGE, MeanSliderChange);
StdDevSlider.addEventListener(Event.CHANGE, DevSliderChange);
runButton = new PushButton(this, 10, 29, "Run");
runButton.addEventListener(MouseEvent.CLICK, onClick);
}
private function MeanSliderChange(e:Event):void
{
meanLabel.text = MeanSlider.value.toFixed(1);
}
private function DevSliderChange(e:Event):void
{
devLabel.text = StdDevSlider.value.toFixed(1);
}
private function onClick(e:Event):void{
run(MeanSlider.value, StdDevSlider.value);
}
private function update(e:Event):void{
var i:int;
var j:int;
for(j = 0; j < CREATE_PER_FRAME; j++){
if(samples < MAX_SAMPLE){
activeParticles.push(createParticle());
samples++;
}
}
canvas.lock();
canvas.fillRect(new Rectangle(0, 0, 465, 465), 0xff000000);
for(i = activeParticles.length - 1; i >= 0; i--){
var p:Particle = activeParticles[i];
p.y += BMTest.STEP_PER_FRAME;
if(p.y >= p.distY){
p.y = p.distY; // いちおー
restParticles.push(p);
activeParticles.splice(i, 1);
}else{
canvas.setPixel(p.x, p.y, 0x1144ee);
}
}
drawRests();
canvas.unlock();
}
private function drawRests():void{
var i:uint; // 別BMP用意して一度描画して重ねちゃった方が早そう
for(i = 0; i < restParticles.length; i++){
var p:Particle = restParticles[i];
canvas.setPixel(p.x, p.y, 0x3399ff);
}
}
private function createParticle():Particle{
var val:int;
val = bmt.random() * 50;
if(values[val]){
values[val]++;
}else{
values[val] = 1;
}
return new Particle(val + 262, 0, val + 262, Math.max(465 - values[val], 0));
}
private function run(mean:Number, stdDev:Number):void{
bmt = new BMTRandom(mean, stdDev);
samples = 0;
values = [];
activeParticles = new Vector.<Particle>();
restParticles = new Vector.<Particle>();
if(!isStarted){
addEventListener(Event.ENTER_FRAME, update);
isStarted = true;
}
}
}
}
class BMTRandom{
private var result1:Number;
private var result2:Number;
private var isCached:Boolean;
private var mean:Number;
private var stdDev:Number;
public function BMTRandom(_mean:Number, _stdDev:Number){
isCached = false;
mean = _mean;
stdDev = _stdDev;
}
public function set Mean(_mean:Number):void{
isCached = false;
mean = _mean;
}
public function set StdDev(_stdDev:Number):void{
isCached = false;
stdDev = _stdDev;
}
public function get Mean():Number{
return mean;
}
public function get StdDev():Number{
return stdDev;
}
public function random():Number{
var result:Number;
if(isCached){
isCached = false;
result = normalDistribute(result2);
}else{
BMTransform();
isCached = true;
result = normalDistribute(result1);
}
return result;
}
private function normalDistribute(v:Number):Number{
return v * stdDev + mean;
}
private function BMTransform():void{
var n:Number = 0.0;
var m:Number = Math.random();
while(n == 0.0){
n = Math.random();
}
result1 = Math.sqrt(-2 * Math.log(n)) * Math.sin( 2 * Math.PI * m);
result2 = Math.sqrt(-2 * Math.log(n)) * Math.cos( 2 * Math.PI * m);
}
}
class Particle{
public var x:int;
public var y:int;
public var distX:int;
public var distY:int;
public function Particle(_x:int, _y:int, _distX:int, _distY:int){
x = _x;
y = _y;
distX = _distX;
distY = _distY;
}
}