ニュートン法によるフラクタル(1) Aquioux forked:2favorite:5lines:202license : MIT License modified : 2011-11-14 21:29:04 Embed Tweet package { //import aquioux.display.colorUtil.CycleRGB; import com.bit101.components.PushButton; import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.Sprite; import flash.events.Event; import flash.geom.Rectangle; [SWF(width = "465", height = "465", frameRate = "60", backgroundColor = "#000000")] /** * ニュートン法によるフラクタル(1) * @see http://aquioux.net/blog/?p=2089 * @author Aquioux(Yoshida, Akio) */ public class Main extends Sprite { // 色 private var colors0_:Vector.<uint>; private var colors1_:Vector.<uint>; private var colors2_:Vector.<uint>; // 計算クラス private var newton_:Newton; // 走査クラス private var scan_:Scan; // 表示用 BitmapData private var bmd_:BitmapData; private var rect_:Rectangle; // bmd_ 用 Rectangle // 前回押したボタン private var prevButton_:PushButton; public function Main():void { // ステージサイズ var sw:int = stage.stageWidth; var sh:int = stage.stageHeight; // カラーセットパターン1 var bw:Vector.<uint> = Vector.<uint>([0x000000, 0xFFFFFF]); colors0_ = new Vector.<uint>(); degree = 255; for (i = 0; i < degree; i++) colors0_[i] = bw[i % 2]; colors0_.fixed = true; // カラーセットパターン2 colors1_ = new Vector.<uint>(); var degree:int = 0x11; var step:Number = 0xFF / degree; for (i = 0; i < degree; i++) { var c:uint = step * i; colors1_[i] = c << 16 | c << 8 | c; } colors1_.fixed = true; // カラーセットパターン3 colors2_ = new Vector.<uint>(); degree = 24; step = 60; for (var i:int = 0; i < degree; i++) colors2_[i] = CycleRGB.getColor(i * step + 180); colors2_.fixed = true; // Newton クラスのセットアップ newton_ = new Newton(); // Scan クラスのセットアップ scan_ = new Scan(); scan_.calculator = newton_; scan_.setup(sw, sh); rect_ = new Rectangle(0, 0, sw, sh); // Viewer の作成 bmd_ = new BitmapData(sw, sh, false, 0x0); addChild(new Bitmap(bmd_)); // ボタンの作成 var buttonWidth:int = 60; var button0:PushButton = new PushButton(this, 0, 0, "2 tone", button0Handler); var button1:PushButton = new PushButton(this, buttonWidth, 0, "monochome", button1Handler); var button2:PushButton = new PushButton(this, buttonWidth * 2, 0, "colorful", button2Handler); button0.width = buttonWidth; button1.width = buttonWidth; button2.width = buttonWidth; // 初回状態の表示 button1Handler(null); button1.selected = true; changeButton(button1); } // 描画 private function draw():void { bmd_.lock(); bmd_.setVector(rect_, scan_.update()); bmd_.unlock(); } // ボタンハンドラ private function button0Handler(e:Event):void { if (e) changeButton(PushButton(e.target)); newton_.colors = colors0_; draw(); } private function button1Handler(e:Event):void { if (e) changeButton(PushButton(e.target)); newton_.colors = colors1_; draw(); } private function button2Handler(e:Event):void { if (e) changeButton(PushButton(e.target)); newton_.colors = colors2_; draw(); } private function changeButton(currentButton:PushButton):void { if (prevButton_) prevButton_.enabled = true; currentButton.enabled = false; prevButton_ = currentButton; } } } //package { import flash.geom.Rectangle; /** * ニュートン法によるフラクタル描画クラス * _scale = 1.0 のとき (-2, -2) ~ (2, 2) の領域を対象に計算する * @author Aquioux(Yoshida, Akio) */ /*public*/ class Newton implements ICalculator { /** * 描画範囲 */ public function get rect():Rectangle { return RECTANGLE; } private const RECTANGLE:Rectangle = new Rectangle(MIN_X, MIN_Y, (MAX_X - MIN_X), (MAX_Y - MIN_Y)); // 個別の開始座標、終了座標 private const MIN_X:Number = -2.0; // X軸最小値 private const MIN_Y:Number = -2.0; // Y軸最小値 private const MAX_X:Number = 2.0; // X軸最大値 private const MAX_Y:Number = 2.0; // Y軸最大値 /** * どの解にも属さない部分の色(一般的には色なし=黒) */ private var _color:uint = 0x000000; public function set color(value:uint):void { _color = value; } /** * いずれかの解に属する部分の色階調 */ private var _colors:Vector.<uint>; public function set colors(value:Vector.<uint>):void { _colors = value; degree_ = value.length; } // 収束チェックループ回数(_colors.length の値) private var degree_:int; /** * Scan クラスからの走査データを受け、計算をおこなう * @param x X座標値 * @param y Y座標値 * @return 計算結果 */ public function calculate(x:Number, y:Number):uint { var r:int = formula(x, y); return (r >= 0) ? _colors[r] : _color; } /** * 漸化式 z ← z - (z^3 - 1) / (3 * z^2) の評価 * @param zRl 複素数 z の実数部 * @param zIm 複素数 z の虚数部 * @return 収束評価値 * @private */ private function formula(zRl:Number, zIm:Number):int { // 漸化式の計算要素の複素数 var zRlSqr:Number; // 実数部の2乗 var zImSqr:Number; // 虚数部の2乗 var i:int = degree_; while (i--) { // z^2 zRlSqr = zRl * zRl - zIm * zIm; zImSqr = 2 * zRl * zIm; // z^3 - 1 var z1rl:Number = zRlSqr * zRl - zImSqr * zIm - 1; var z1im:Number = zRlSqr * zIm + zImSqr * zRl; // 収束評価 if (z1rl * z1rl + z1im * z1im < 1.0E-6) break; // 3 * z^2 var z2rl:Number = zRlSqr * 3; var z2im:Number = zImSqr * 3; // z - (z^3 - 1) / (3 * z^2) var z2norm:Number = z2rl * z2rl + z2im * z2im; zRl -= (z1rl * z2rl + z1im * z2im) / z2norm; zIm -= (z1im * z2rl - z1rl * z2im) / z2norm; } return i; // break で脱しなかった(収束しなかった)場合、while を回りきるので -1 になる } } //} //package { import flash.geom.Rectangle; /** * 計算クラスの interface * @author YOSHIDA, Akio (Aquioux) */ /*public*/ interface ICalculator { function get rect():Rectangle; function calculate(x:Number, y:Number):uint; } //} //package { import flash.geom.Rectangle; /** * 二次元走査クラス * @author Aquioux(Yoshida, Akio) */ /*public*/ class Scan { /** * 計算クラス */ private var _calculator:ICalculator; public function set calculator(value:ICalculator):void { _calculator = value; rect = _calculator.rect; } /** * 描画領域(_scale = 1.0 における値) */ private var _rect:Rectangle; public function set rect(value:Rectangle):void { _rect = value; } /** * 表示位置オフセットX座標値 */ private var _offsetX:Number = 0.0; public function set offsetX(value:Number):void { _offsetX = value; calcValue(); } /** * 表示位置オフセットY座標値 */ private var _offsetY:Number = 0.0; public function set offsetY(value:Number):void { _offsetY = value; calcValue(); } /** * スケール値 */ private var _scale:Number = 1.0; public function set scale(value:Number):void { _scale = value; calcValue(); } // ----- その他変数 ----- // 計算加算値 private var stepX_:Number; // X軸 private var stepY_:Number; // Y軸 // 走査開始座標 private var startX_:Number; // X座標 private var startY_:Number; // Y座標 // 表示領域 private var displayWidth_:int; // 幅 private var displayHeight_:int; // 高 // ビューアへ渡すデータ private var data_:Vector.<uint>; // data_ のインデックス private var idx_:int; /** * 初期化 * @param width 表示幅 * @param height 表示高 */ public function setup(width:int, height:int):void { // 表示サイズ displayWidth_ = width; displayHeight_ = height; // data_ の生成 data_ = new Vector.<uint>(width * height, true); // 複素数平面走査用の各変数を計算する calcValue(); } /** * 複素数平面を走査し、その値を計算クラスの渡す * @return 計算クラスから返ってきた値を格納した Vector */ public function update():Vector.<uint> { idx_ = 0; for (var y:int = 0; y < displayHeight_; y++) { for (var x:int = 0; x < displayWidth_; x++) { data_[idx_++] = _calculator.calculate(startX_ + x * stepX_, startY_ + y * stepY_); } } return data_; } // 複素数平面走査用の変数を計算する private function calcValue():void { stepX_ = (_rect.width / _scale) / displayWidth_; stepY_ = (_rect.height / _scale) / displayHeight_; startX_ = (_rect.width * 0.5 + _rect.x + _offsetX) - displayWidth_ * 0.5 * stepX_; startY_ = (_rect.height * 0.5 + _rect.y + _offsetY) - displayHeight_ * 0.5 * stepY_; } } //} //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); } } //} Code Fullscreen Preview Fullscreen gaziya ProjectNya andrewexex88.. Albert merrycat : artfractal art fractal fractals フラクタル Rectangle target height alpha fixed width Math.cos Vector Event Math.PI length addChild Sprite uint int Number sort new page view favorite forked pv845 ニュートン法によるフラクタル(3) ~3乗以外の冪乗~ Aquioux forked:2 favorite:5lines:212 (diff:153) tag: fractal fractals フラクタル pv673 ニュートン法によるフラクタル(2) ~根による塗り分け~ Aquioux forked:2 favorite:0lines:164 (diff:150) tag: fractal fractals フラクタル