package { import com.bit101.components.HSlider; import com.bit101.components.RadioButton; import com.bit101.components.Label; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import flash.events.TimerEvent; import flash.utils.Timer; import frocessing.color.ColorHSV; [SWF(width = "465", height = "465", frameGOLDEN_RATIO = "30", backgroundColor = "#000000")] /** * 葉序開度 - Divergence of Phyllotaxy - * ---------- * 参考:「黄金比」 創元社(アルケミスト双書) スコット・オルセン著・藤田優里子訳 P12 「葉序のパターン」 * http://www.amazon.co.jp/gp/product/4422214756?ie=UTF8&tag=laxcomplex-22&linkCode=as2&camp=247&creative=1211&creativeASIN=4422214756 * 参考:「フィボナッチ数列と葉序」 http://www.dainippon-tosho.co.jp/mathlab/flash/no_002/math2.html * 参考:「フィボナッチ数と植物」 http://mshi.no.coocan.jp/pukiwiki/?%B8%A6%B5%E6%BC%BC%2F%A5%D5%A5%A3%A5%DC%A5%CA%A5%C3%A5%C1%BF%F4%A4%C8%BF%A2%CA%AA * ---------- * 解説:http://aquioux.blog48.fc2.com/blog-entry-692.html * ---------- * @author Aquioux(Yoshida, Akio) */ public class Main extends Sprite { private const GOLDEN_RATIO:Number = (Math.sqrt(5) - 1) / 2; // 黄金比(内率) private const NUM_OF_DOT:uint = 360; // 生成する Dot の数 private const RADIAN90:Number = Math.PI / 2; // 90度のときのラジアン値 private const CX:Number = stage.stageWidth / 2; private const CY:Number = stage.stageHeight / 2; private var dots:Array = []; // Dot 格納配列 private var label:Label; private var slider:HSlider; private var selectedRadioButton:RadioButton; private var isAuto:Boolean = false; private var autoValue:Number; private var timer:Timer; public function Main():void { // Dot の生成 var hsv:ColorHSV = new ColorHSV(); var dist:Number = 0.0; var n:uint = NUM_OF_DOT; var cx:Number = CX; var cy:Number = CY; var goldenRatio:Number = GOLDEN_RATIO; for (var i:int = 0; i < n; i++) { hsv.h = i; var dot:Dot = new Dot(Math.sqrt(dist) * goldenRatio, hsv.toRGB().value); dot.x = cx; dot.y = cy; addChild(dot); dots.push(dot); dist += goldenRatio; } // スライダー slider = new HSlider(this, 0, 0, sliderHandler); slider.width = stage.stageWidth; var max:Number = 360.0; var min:Number = 0.0; slider.setSliderParams(min, max, min); // ラベル label = new Label(this, 5, slider.height + 5); // ラジオボタン var labels:Array = [ // ラジオボタンラベル "degree : 180 (1/2 Phyllotaxis)", "degree : 120 (1/3 = 2/3 Phyllotaxis)", "degree : 144 (2/5 = 3/5 Phyllotaxis)", "degree : 135 (3/8 = 5/8 Phyllotaxis)", "degree : 138.5 (5/13 = 8/13 Phyllotaxis)", "degree : 137.3 (Fibonacci - 0.2)", "degree : 137.5 (Fibonacci)", "degree : 137.6 (Fibonacci + 0.1)", "degree : 222.5 (360 - Fibonacci)", "degree : 85 (360 - Fibonacci * 2)", "degree : 99.5 (Lucas)", "degree : 260.5 (360 - Lucas)", "degree : 161 (360 - Lucas * 2)", "degree : 61.5 (360 - Lucas * 3)", "degree : 237 (Fibonacci + Lucas)", "degree : 38 (Fibonacci - Lucas)", "autoStart(++0.1)" ]; n = labels.length; var handler:Function = radioHandler; for (i = 0; i < n; i++) { if (i == n - 1) handler = autoHandler; var radio:RadioButton = new RadioButton(this, 8, label.y + label.height + 5 + 17 * i, labels[i], false, handler); } // 初期配置 dotPlace(min); } // ラジオボタンハンドラ private function radioHandler(e:MouseEvent):void { // 選ばれたラジオボタンの保持 selectedRadioButton = e.currentTarget as RadioButton; // オートモードだったら停止 if (isAuto) autoStop(); // ラジオボタンで設定した角度の取得 var str:String = selectedRadioButton.label; var degree:Number = Number(str.split(" ")[2]); // スライダーの設定 slider.value = degree; // 配置実行 dotPlace(degree); } // ラジオボタンハンドラ(自動) private function autoHandler(e:MouseEvent):void { // timer が未生成ならば生成する if (!timer) { timer = new Timer(50); timer.addEventListener(TimerEvent.TIMER, autoStart); } // 選ばれたラジオボタンの保持 selectedRadioButton = e.currentTarget as RadioButton; // オートモードフラグ isAuto = true; // 角度の取得 autoValue = slider.value; // オート開始 autoStart(null); timer.start(); } // オート開始 private function autoStart(e:TimerEvent):void { // 角度更新 autoValue += 0.1; autoValue %= 360; // スライダーの設定 slider.value = autoValue; // 配置実行 dotPlace(autoValue); } // オート停止 private function autoStop():void { isAuto = false; timer.stop(); timer.reset(); } // スライダーハンドラ private function sliderHandler(e:Event):void { // ラジオボタンのリセット if (selectedRadioButton) selectedRadioButton.selected = false; // オートモードだったら停止 if (isAuto) autoStop(); // 配置実行 dotPlace(e.target.value); } // Dot の配置 private function dotPlace(degree:Number):void { // ラベルテキストの設定 label.text = "degree : " + String(degree); // 配置の設定 var radian:Number = degree * Math.PI / 180; var dist:Number = 0.0; var n:uint = NUM_OF_DOT; var cx:Number = CX; var cy:Number = CY; var radian90:Number = RADIAN90; var goldenRatio:Number = GOLDEN_RATIO; for (var i:int = 0; i < n; i++) { var dot:Dot = dots[i]; var angle:Number = radian * i - radian90; dot.x = Math.cos(angle) * dist + cx; dot.y = Math.sin(angle) * dist + cy; dist += goldenRatio; } } } } // Dot Class import flash.display.Graphics; import flash.display.Shape; class Dot extends Shape { public function Dot(radius:Number = 5, color:uint = 0x000000) { var g:Graphics = graphics; g.beginFill(color); g.drawCircle(0, 0, radius); g.endFill(); } } 葉序開度 - Divergence of Phyllotaxy -