In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

フォードの円でパターンを描く(1)

Get Adobe Flash player
by Aquioux 12 Oct 2011
/**
 * Copyright Aquioux ( http://wonderfl.net/user/Aquioux )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/tWKI
 */

package {
    import flash.display.Graphics;
    import flash.display.Shape;
    import flash.display.Sprite;
    import flash.events.MouseEvent;
    [SWF(width = "465", height = "465", frameRate = "30", backgroundColor = "#FFFFFF")]
    /**
     * フォードの円でパターンを描く(1)
     * ステージをクリックしてください。
     */
    public class Main2 extends Sprite {
        // ファレイ数列から計算されたフォードの円の座標値を一次元配列で格納
        private var data_:Vector.<Number>;

        // 描画パターンの切り替え関連
        private var switcher_:Switcher;
        private var numOfPattern_:int;
        private var currentPattern_:int;

        // キャンバス
        private var canvas_:Shape;

        /**
         * コンストラクタ
         */
        public function Main2() {
            setup();
            stage.addEventListener(MouseEvent.CLICK, clickHandler);
            clickHandler(null);
        }
        
        // セットアップ
        private function setup():void {
            // ファレイ数列生成
            var farey0:Vector.<String>  = Calculator.createFareySequence(6);
            var fareyP1:Vector.<String> = Calculator.shift(farey0, 1);
            var fareyP2:Vector.<String> = Calculator.shift(farey0, 2);
            farey0.fixed  = false;
            fareyP1.fixed = false;
            farey0.pop();
            fareyP1.pop();
            var farey:Vector.<String> = new Vector.<String>();
            farey = farey.concat(farey0, fareyP1, fareyP2);
            
            // フォードの円の座標値計算
            data_ = Calculator.calcFordCircleCenter(farey);
            
            // 描画パターンの切り替え
            switcher_ = new Switcher();
            numOfPattern_   = switcher_.patterns.length;
            currentPattern_ = 0;
            
            // キャンバス生成
            canvas_ = new Shape();
            addChild(canvas_);
        }
        
        // マウスハンドラ
        private function clickHandler(e:MouseEvent):void {
            switcher_.patterns[currentPattern_](data_, canvas_, stage.stageWidth);
            currentPattern_++;
            currentPattern_ %= numOfPattern_
        }
    }
}


//package {
    /**
     * ファレイ数列とフォードの円 Farey sequence & Ford circle
     */
    /*public*/ class Calculator {
        // F1 のファレイ数列
        private static const FAREY1:Vector.<String> = Vector.<String>(["0/1", "1/1"]);

        /**
         * コンストラクタ
         */
        public function Calculator() {
        }
        
        /**
         * ファレイ数列の生成
         * @param    degree    ファレイ数列が対応する整数
         * @return    ファレイ数列
         */
        public static function createFareySequence(degree:uint):Vector.<String> {
            var currentData:Vector.<String> = new Vector.<String>();
            var nextData:Vector.<String>    = new Vector.<String>();
            var prevStr1:String = null;

            currentData = FAREY1;
            // ファレイ数列に対応する i をインクリメントする
            for (var i:int = 2; i <= degree; i++) {
                var len:int = currentData.length;
                // i-1 に対応するファレイ数列から i に対応するファレイ数列を作るため、ファレイ数列の要素を爪弾く
                for (var j:int = 1; j < len; j++) {
                    var str0:String = currentData[j - 1];
                    var str1:String = currentData[j];
                    var uints0:Vector.<int> = stringToInt(str0);
                    var uints1:Vector.<int> = stringToInt(str1);
                    var a:uint = uints0[0];    // 小さい分数の分子
                    var b:uint = uints0[1];    // 小さい分数の分母
                    var c:uint = uints1[0];    // 大きい分数の分子
                    var d:uint = uints1[1];    // 大きい分数の分母
                    
                    // 前回の str1 の確認
                    if ((prevStr1) && (prevStr1 != str0)) nextData.push(prevStr1);
                    // 今回の str0 をデータとして登録
                    nextData.push(str0);
                    // 中間数の計算および評価
                    var mediant:String = null;
                    var denominator:uint = b + d;
                    if (denominator <= degree) mediant = String(a + c) + "/" + String(denominator);
                    if (mediant) nextData.push(mediant);
                    
                    // ファレイ数列の要素爪弾く前の準備
                    prevStr1 = str1;
                }
                // ループを抜けた(i に対応するファレイ数列ができた)ので、最後の分数 str1(= "1/1")を登録
                nextData.push(str1);
                
                // ファレイ数列に対応する整数をインクリメントする前の準備
                currentData = nextData;
                nextData    = new Vector.<String>();
                prevStr1 = null;
            }
            currentData.fixed = true;
            return currentData;
        }
        
        /**
         * ファレイ数列のシフト
         * 0 ~ 1の範囲から scale ~ scale+1 の範囲の値にシフトする
         * @param    farey    元データ
         * @param    scale    シフト値
         * @return    シフト後のデータ
         */
        public static function shift(farey:Vector.<String>, scale:int):Vector.<String> {
            var ret:Vector.<String> = new Vector.<String>();
            var len:int = farey.length;
            for (var i:int = 0; i < len; i++) {
                // String から Number に
                var fraction:Vector.<int> = stringToInt(farey[i]);
                var numerator:Number   = Number(fraction[0]);
                var denominator:Number = Number(fraction[1]);
                // シフト計算
                numerator += denominator * scale;
                // 再び分数の形式にして置換
                ret.push(String(numerator) + "/" + String(denominator));
            }
            ret.fixed = true;
            return ret;
        }
        
        /**
         * ファレイ数列からフォードの円の中心座標を計算
         * @param    farey    ファレイ数列
         * @return    フォードの円の中心座標を一次元配列で格納した Vector
         */
        public static function calcFordCircleCenter(farey:Vector.<String>):Vector.<Number> {
            var data:Vector.<Number> = new Vector.<Number>();

            var len:int = farey.length;
            for (var i:int = 0; i < len; i++) {
                // String から Number に
                var fraction:Vector.<int> = stringToInt(farey[i]);
                var numerator:Number   = Number(fraction[0]);
                var denominator:Number = Number(fraction[1]);
                // 座標値
                var posX:Number = numerator / denominator;
                var posY:Number = 1 / (denominator * denominator * 2);
                data.push(posX, posY);
            }
            data.fixed = true;
            
            return data;
        }

        // ファレイ数列のひとつの要素を String から、分子・分母の二つの uint に変換
        private static function stringToInt(data:String):Vector.<int> {
            var d:Array = data.split("/");
            return Vector.<int>([int(d[0]), int(d[1])]);
        }
    }
//}


//package {
    //import aquioux.display.colorUtil.CycleRGB;
    import flash.display.Graphics;
    import flash.display.Shape;
    /**
     * ファレイ数列とフォードの円 Farey sequence & Ford circle
     */
    /*public*/ class Switcher {
    
        public function get patterns():Array { return _patterns; }
        private var _patterns:Array;


        /**
         * コンストラクタ
         */
        public function Switcher() {
            _patterns = [pattern11, pattern12, pattern21, pattern22, pattern31, pattern32, pattern41, pattern42];
        }


        // 描画パターン
        private function pattern11(data:Vector.<Number>, canvas:Shape, size:int):void {
            var g:Graphics = canvas.graphics;
            g.clear();
            g.lineStyle(0, CycleRGB.getColor(Math.random() * 360));
            //g.beginFill(CycleRGB.getColor(Math.random() * 360));
            var scale:int = size;
            var len:int = data.length;
            for (var i:int = 0; i < len; i += 2) {
                var posX:Number = data[i];
                var posY:Number = data[i + 1];
                g.drawCircle(posX * scale, posY * scale, posY * scale);
                g.drawCircle(posY * scale, posX * scale, posY * scale);
                g.drawCircle(posX * scale, (1 - posY) * scale, posY * scale);
                g.drawCircle((1 - posY) * scale, posX * scale, posY * scale);
            }
        }
        private function pattern12(data:Vector.<Number>, canvas:Shape, size:int):void {
            var g:Graphics = canvas.graphics;
            g.clear();
            //g.lineStyle(0, CycleRGB.getColor(Math.random() * 360));
            g.beginFill(CycleRGB.getColor(Math.random() * 360));
            var scale:int = size;
            var len:int = data.length;
            for (var i:int = 0; i < len; i += 2) {
                var posX:Number = data[i];
                var posY:Number = data[i + 1];
                g.drawCircle(posX * scale, posY * scale, posY * scale);
                g.drawCircle(posY * scale, posX * scale, posY * scale);
                g.drawCircle(posX * scale, (1 - posY) * scale, posY * scale);
                g.drawCircle((1 - posY) * scale, posX * scale, posY * scale);
            }
        }
        private function pattern21(data:Vector.<Number>, canvas:Shape, size:int):void {
            var g:Graphics = canvas.graphics;
            g.clear();
            g.lineStyle(0, CycleRGB.getColor(Math.random() * 360));
            //g.beginFill(CycleRGB.getColor(Math.random() * 360));
            var scale:int = size;
            var len:int = data.length;
            for (var i:int = 0; i < len; i += 2) {
                var posX:Number = data[i] - 0.5;
                var posY:Number = data[i + 1];
                g.drawCircle(posX * scale, posY * scale, posY * scale);
                g.drawCircle(posX * scale, (1 - posY) * scale, posY * scale);
                g.drawCircle(posY * scale, posX * scale, posY * scale);
                g.drawCircle((1 - posY) * scale, posX * scale, posY * scale);
            }
        }
        private function pattern22(data:Vector.<Number>, canvas:Shape, size:int):void {
            var g:Graphics = canvas.graphics;
            g.clear();
            //g.lineStyle(0, CycleRGB.getColor(Math.random() * 360));
            g.beginFill(CycleRGB.getColor(Math.random() * 360));
            var scale:int = size;
            var len:int = data.length;
            for (var i:int = 0; i < len; i += 2) {
                var posX:Number = data[i] - 0.5;
                var posY:Number = data[i + 1];
                g.drawCircle(posX * scale, posY * scale, posY * scale);
                g.drawCircle(posX * scale, (1 - posY) * scale, posY * scale);
                g.drawCircle(posY * scale, posX * scale, posY * scale);
                g.drawCircle((1 - posY) * scale, posX * scale, posY * scale);
            }
        }
        private function pattern31(data:Vector.<Number>, canvas:Shape, size:int):void {
            var g:Graphics = canvas.graphics;
            g.clear();
            g.lineStyle(0, CycleRGB.getColor(Math.random() * 360));
            //g.beginFill(CycleRGB.getColor(Math.random() * 360));
            var scale:int = size / 2;
            var len:int = data.length;
            for (var i:int = 0; i < len; i += 2) {
                var posX:Number = data[i] - 0.5;
                var posY:Number = data[i + 1];
                g.drawCircle(posX * scale, posY * scale, posY * scale);
                g.drawCircle(posX * scale, (posY + 1) * scale, posY * scale);
                g.drawCircle(posX * scale, (1 - posY) * scale, posY * scale);
                g.drawCircle(posX * scale, (2 - posY) * scale, posY * scale);
                    
                g.drawCircle(posY * scale, posX * scale, posY * scale);
                g.drawCircle((posY + 1) * scale, posX * scale, posY * scale);
                g.drawCircle((1 - posY) * scale, posX * scale, posY * scale);
                g.drawCircle((2 - posY) * scale, posX * scale, posY * scale);
            }
        }
        private function pattern32(data:Vector.<Number>, canvas:Shape, size:int):void {
            var g:Graphics = canvas.graphics;
            g.clear();
            //g.lineStyle(0, CycleRGB.getColor(Math.random() * 360));
            g.beginFill(CycleRGB.getColor(Math.random() * 360));
            var scale:int = size / 2;
            var len:int = data.length;
            for (var i:int = 0; i < len; i += 2) {
                var posX:Number = data[i] - 0.5;
                var posY:Number = data[i + 1];
                g.drawCircle(posX * scale, posY * scale, posY * scale);
                g.drawCircle(posX * scale, (posY + 1) * scale, posY * scale);
                g.drawCircle(posX * scale, (1 - posY) * scale, posY * scale);
                g.drawCircle(posX * scale, (2 - posY) * scale, posY * scale);
                    
                g.drawCircle(posY * scale, posX * scale, posY * scale);
                g.drawCircle((posY + 1) * scale, posX * scale, posY * scale);
                g.drawCircle((1 - posY) * scale, posX * scale, posY * scale);
                g.drawCircle((2 - posY) * scale, posX * scale, posY * scale);
            }
        }
        private function pattern41(data:Vector.<Number>, canvas:Shape, size:int):void {
            var g:Graphics = canvas.graphics;
            g.clear();
            g.lineStyle(0, CycleRGB.getColor(Math.random() * 360));
            //g.beginFill(CycleRGB.getColor(Math.random() * 360));
            var scale:int = size / 2;
            var len:int = data.length;
            for (var i:int = 0; i < len; i += 2) {
                var posX:Number = data[i] - 0.5;
                var posY:Number = data[i + 1];
                g.drawCircle(posX * scale, posY * scale, posY * scale);
                g.drawCircle(posX * scale, (1 - posY) * scale, posY * scale);
                g.drawCircle(posX * scale, (posY + 1) * scale, posY * scale);
                g.drawCircle(posX * scale, (2 - posY) * scale, posY * scale);
                g.drawCircle((posX - 0.5) * scale, (0.5 - posY) * scale, posY * scale);
                g.drawCircle((posX - 0.5) * scale, (posY + 0.5) * scale, posY * scale);
                g.drawCircle((posX - 0.5) * scale, (1.5 - posY) * scale, posY * scale);
                g.drawCircle((posX - 0.5) * scale, (posY + 1.5) * scale, posY * scale);
                
                g.drawCircle(posY * scale, posX * scale, posY * scale);
                g.drawCircle((posY + 1) * scale, posX * scale, posY * scale);
                g.drawCircle((1 - posY) * scale, posX * scale, posY * scale);
                g.drawCircle((2 - posY) * scale, posX * scale, posY * scale);
                g.drawCircle((0.5 - posY) * scale, (posX - 0.5) * scale, posY * scale);
                g.drawCircle((posY + 0.5) * scale, (posX - 0.5) * scale, posY * scale);
                g.drawCircle((1.5 - posY) * scale, (posX - 0.5) * scale, posY * scale);
                g.drawCircle((posY + 1.5) * scale, (posX - 0.5) * scale, posY * scale);
            }
        }
        private function pattern42(data:Vector.<Number>, canvas:Shape, size:int):void {
            var g:Graphics = canvas.graphics;
            g.clear();
            //g.lineStyle(0, CycleRGB.getColor(Math.random() * 360));
            g.beginFill(CycleRGB.getColor(Math.random() * 360));
            var scale:int = size / 2;
            var len:int = data.length;
            for (var i:int = 0; i < len; i += 2) {
                var posX:Number = data[i] - 0.5;
                var posY:Number = data[i + 1];
                g.drawCircle(posX * scale, posY * scale, posY * scale);
                g.drawCircle(posX * scale, (1 - posY) * scale, posY * scale);
                g.drawCircle(posX * scale, (posY + 1) * scale, posY * scale);
                g.drawCircle(posX * scale, (2 - posY) * scale, posY * scale);
                g.drawCircle((posX - 0.5) * scale, (0.5 - posY) * scale, posY * scale);
                g.drawCircle((posX - 0.5) * scale, (posY + 0.5) * scale, posY * scale);
                g.drawCircle((posX - 0.5) * scale, (1.5 - posY) * scale, posY * scale);
                g.drawCircle((posX - 0.5) * scale, (posY + 1.5) * scale, posY * scale);
                
                g.drawCircle(posY * scale, posX * scale, posY * scale);
                g.drawCircle((posY + 1) * scale, posX * scale, posY * scale);
                g.drawCircle((1 - posY) * scale, posX * scale, posY * scale);
                g.drawCircle((2 - posY) * scale, posX * scale, posY * scale);
                g.drawCircle((0.5 - posY) * scale, (posX - 0.5) * scale, posY * scale);
                g.drawCircle((posY + 0.5) * scale, (posX - 0.5) * scale, posY * scale);
                g.drawCircle((1.5 - posY) * scale, (posX - 0.5) * scale, posY * scale);
                g.drawCircle((posY + 1.5) * scale, (posX - 0.5) * scale, posY * scale);
            }
        }
    }
//}


//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);
        }
    }
//}