Pappus Chain (advanced, interactive)

by Aquioux forked from Pappus Chain (basic, interactive) (diff: 34)
♥0 | Line 103 | Modified 2013-12-25 20:31:41 | MIT License
play

ActionScript3 source code

/**
 * Copyright Aquioux ( http://wonderfl.net/user/Aquioux )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/8ABm
 */

// forked from Aquioux's Pappus Chain (basic, interactive)
// forked from Aquioux's Pappus Chain (basic, static)
package {
    //import aquioux.display.colorUtil.RGBWheel;
    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")]
    /**
     * パップス・チェーン Pappus Chain (4)
     * 発展形(マウス・インタラクティブ)
     * @see http://aquioux.net/blog/?p=3831
     * @author Yoshida, Akio
     */
    public class Main extends Sprite {
        // サイズ
        private const STAGE_WIDTH:int = stage.stageWidth;

        // スケール
        static private const SCALE:int = 455;

        // キャンバス
        private var canvas_:Shape;
        // 背景色
        static private const FILL_COLOR:uint = 0xffffff;
        // 円の色
        static private const CIRCLE_COLOR:uint = 0x000000;

        // 円を半円に見せるための覆い
        private var cover_:Shape;


        /**
         * コンストラクタ
         */
        public function Main():void {
            setup();
            stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
            draw(0.618);
        }

        /**
         * セットアップ
         */
        private function setup():void {
            // サイズ
            const STAGE_HEIGHT:int = stage.stageHeight;

            // キャンバスの生成
            canvas_ = new Shape();
            canvas_.x = (STAGE_WIDTH - SCALE) / 2;
            canvas_.y = STAGE_HEIGHT * 0.75;
            addChild(canvas_);

            // 円を半円に見せるための覆いの生成
            cover_ = new Shape();
            cover_.x = canvas_.x - 1;
            cover_.y = canvas_.y;
            addChild(cover_);
            var g:Graphics = cover_.graphics;
            g.beginFill(FILL_COLOR);
            g.drawRect(0, 0, STAGE_WIDTH, STAGE_HEIGHT / 2);
            g.endFill();
            g.lineStyle(0, 0x0);
            g.moveTo(0, 0);
            g.lineTo(SCALE + 1, 0);
        }

        // マウスハンドラ
        private function mouseMoveHandler(event:MouseEvent):void {
            var r:Number = mouseX / STAGE_WIDTH;
            if (r < 0.05) r = 0.05;
            if (r > 0.95) r = 0.95;
            draw(r);
        }

        /**
         * パップス・チェーンの計算および描画
         */
        private function draw(r:Number):void {
            // キャンバス・クリア
            canvas_.graphics.clear();

            // 正接円の直径
            var s:Number = 1.0 - r;
            // 正接円の半径
            var rRadius:Number = r / 2;
            var sRadius:Number = s / 2;

            // 外接円
            drawCircle(0.5, 0.0, 0.5, CIRCLE_COLOR);
            // 正接円1
            drawCircle(rRadius, 0.0, rRadius, FILL_COLOR);
            // 正接円2
            drawCircle(r + sRadius, 0.0, sRadius, FILL_COLOR);

            var ss:Number = s * s;        // 円鎖計算用パラメータ1
            var rs:Number = r * s;        // 円鎖計算用パラメータ2
            var len:int = 5 / s >> 0;    // 円鎖の数
            var angle:Number = 0;        // 円列色用パラメータ1
            var add:Number   = -360 / 5;    // 円列色用パラメータ1
            for (var i:int = 1; i < len; ++i) {
                // 円列1
                var val:Number = i * i * ss + r;
                var centerX:Number = r * (1 + r) / (2 * val);
                var centerY:Number = i * rs      /      val;
                var radius:Number  = rs          / (2 * val);
                drawCircle(centerX, -centerY, radius, RGBWheel.getDegreeColor(angle + add * 0));
                // 円列2
                val = 4 + 4 * i * (i - 1) * ss + r * (r - 1);
                centerX = r * (7 + r)          / (2 * val);
                centerY = 2 * (2 * i - 1) * rs /      val;
                radius  = rs                   / (2 * val);
                drawCircle(centerX, -centerY, radius, RGBWheel.getDegreeColor(angle + add * 1));
                // 円列3(1)
                val = 12 + 3 * i * (3 * i - 4) * ss + r * (4 * r - 7);
                centerX = r * (17 + r)         / (2 * val);
                centerY = 3 * (3 * i - 2) * rs /      val;
                radius  = rs                   / (2 * val);
                drawCircle(centerX, -centerY, radius, RGBWheel.getDegreeColor(angle + add * 2));
                // 円列3(2)
                val = 9 + 12 * i * (i - 1) * ss + r * (4 * r - 1);
                centerX = r * (17 + 7 * r)     / (2 * val);
                centerY = 6 * (2 * i - 1) * rs /      val;
                radius  = rs                   / (2 * val);
                drawCircle(centerX, -centerY, radius, RGBWheel.getDegreeColor(angle + add * 3));
                // 円列3(3)
                val = 9 + 3 * i * (3 * i - 2) * ss - rs;
                centerX = r * (17 + r)         / (2 * val);
                centerY = 3 * (3 * i - 1) * rs /      val;
                radius  = rs                   / (2 * val);
                drawCircle(centerX, -centerY, radius, RGBWheel.getDegreeColor(angle + add * 4));
            }
        }
        // 円の描画
        private function drawCircle(x:Number, y:Number, radius:Number, color:uint):void {
            var g:Graphics = canvas_.graphics;
            g.lineStyle(0, 0x0);
            g.beginFill(color);
            g.drawCircle(x * SCALE, y * SCALE, radius * SCALE);
            g.endFill();
        }
    }
}


//package aquioux.display.colorUtil {
    /**
     * コサインカーブで色相環的に RGB を計算
     * @author YOSHIDA, Akio
     */
    /*public*/ class RGBWheel {
        /**
         * 角度 angle に応じた RGB を得る(弧度法指定 radian)
         * @param    radian    角度(弧度法)
         * @return    色(0xRRGGBB)
         */
        static public function getRadianColor(radian:Number):uint {
            var r:uint = (Math.cos(radian)                      + 1) * 0xff >> 1;
            var g:uint = (Math.cos(radian + 2.0943951023931953) + 1) * 0xff >> 1;
            var b:uint = (Math.cos(radian - 2.0943951023931953) + 1) * 0xff >> 1;
            // 2.0943951023931953 = Math.PI * 2 / 3 radian(= 120 degree)
            return r << 16 | g << 8 | b;
        }
        /**
         * 角度 angle に応じた RGB を得る(度数法指定 degree)
         * @param    degree    角度(度数法)
         * @return    色(0xRRGGBB)
         */
        static public function getDegreeColor(degree:Number):uint {
            return getRadianColor(degree * 0.017453292519943295);
        }
    }
//}