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

forked from: 反転の「見える化」(シュタイナー・チェーン版)

円による「反転」の様子を見てみる(シュタイナー・チェーン版)
/**
 * Copyright Aquioux ( http://wonderfl.net/user/Aquioux )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/bwce
 */

// forked from Aquioux's 反転の「見える化」
package {
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Graphics;
    import flash.display.Shape;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.geom.Point;
    [SWF(width = "465", height = "465", frameRate = "30", backgroundColor = "#FFFFFF")]
    /**
     * 反転の「見える化」(シュタイナー・チェーン版)
     * 
     * 青:反転前図形
     * 緑:反転対称軸としての円とその円の中心点を通る縦横の直線
     * 赤:反転後座標
     * 
     * ステージクリックで連なる円の数が変わる
     * 
     * @see http://aquioux.net/blog/?p=557
     * 
     * @author YOSHIDA, Akio (Aquioux)
     */
    public class Main extends Sprite {
        private const RADIUS:uint = 70;    // 反転軸円の半径
        private const RADIUS_SQUARE:uint = RADIUS * RADIUS;    // 反転軸円の半径の2乗

        private const N_PIXEL_COLOR:uint  = 0xFF0000FF;    // 反転前ピクセルの色
        private const I_PIXEL_COLOR:uint  = 0xFFFF0000;    // 反転後ピクセルの色
        private const BMD_FILL_COLOR:uint = 0x00000000;    // ピクセルを描く BitmapData の fill 色
        private const AXIS_COLOR:uint   = 0x00FF00;    // 反転軸円の色
        
        private var nBmd_:BitmapData;    // 反転前ピクセルを描く BitmapData;
        private var iBmd_:BitmapData;    // 反転後ピクセルを描く BitmapData;
        
        private var axis_:Shape;        // 反転軸円と中心交差線を描く表示物
        
        // 反転前座標
        private var nCoordinatesArray_:Array;
        private var nCoordinates_:Vector.<int>;
        // 反転後座標
        private var iCoordinates_:Vector.<int>;

        private var len_:int;        // [n/i]Coordinates の length
        
        private var toggle_:int = 0;    // トグルスイッチ
        private var toggleLen_:int = 10;
        

        // コンストラクタ
        public function Main() {
            setup1();
            setup2();
            addEventListener(Event.ENTER_FRAME, update);
            stage.addEventListener(MouseEvent.CLICK, clickHandler);
        }
        
        private function clickHandler(e:MouseEvent):void {
            toggle_++;
            toggle_ %= toggleLen_;
            setup2();
        }
        
        // 表示物の生成と不動要素の描画
        private function setup1():void {
            var sw:Number = stage.stageWidth;
            var sh:Number = stage.stageHeight;
            var cx:Number = sw / 2;
            var cy:Number = sh / 2;

            // 表示物の生成
            // BitmapData および Bitmap
            nBmd_ = new BitmapData(sw, sh, true, BMD_FILL_COLOR);
            iBmd_ = nBmd_.clone();
            // 反転軸円と中心交差線を描く Shape
            axis_ = new Shape();
            
            addChild(axis_);
            addChild(new Bitmap(nBmd_));
            addChild(new Bitmap(iBmd_));

            // 反転軸円と中心交差線を描く
            var g_:Graphics = axis_.graphics;
            g_.lineStyle(0, AXIS_COLOR);
            g_.drawCircle(0, 0, RADIUS);
            g_.moveTo(0, -sh);
            g_.lineTo(0,  sh);
            g_.moveTo(-sw, 0);
            g_.lineTo( sw, 0);
        
            // 反転前座標の生成
            nCoordinatesArray_ = [];
            for (var j:int = 0; j < toggleLen_; j++) {
                nCoordinates_ = new Vector.<int>();
                // 内側の円
                nCoordinates_ = nCoordinates_.concat(DataFactory.drawCircle(sw, sh, cx, cy, RADIUS));
                // 取り巻く円
                var numOfCircle:uint = 6 + j;    // 取り巻く円の数
                var radian:Number = Math.PI / numOfCircle;    // 小円から見て、ひとつの円が占有するラジアンの半分
                var radius:Number = RADIUS * Math.sin(radian) / (1 - Math.sin(radian));    // 半径
                radian *= 2;
                var dist:Number = RADIUS + radius;    // 原点からひとつの円の中心までの距離
                for (var i:int = 0; i < numOfCircle; i++) {
                    var p:Point = Point.polar(dist, radian * i);
                    nCoordinates_ = nCoordinates_.concat(DataFactory.drawCircle(sw, sh, p.x + cx, p.y + cy, radius));
                }
                // 外側の円
                nCoordinates_ = nCoordinates_.concat(DataFactory.drawCircle(sw, sh, cx, cy, RADIUS + radius * 2));
                nCoordinates_.fixed = true;
                
                nCoordinatesArray_.push(nCoordinates_);
            }
        }
        
        // 反転前座標の切り替えと描画
        private function setup2():void {
            nCoordinates_ = nCoordinatesArray_[toggle_];
            len_          = nCoordinates_.length;
            iCoordinates_ = new Vector.<int>(len_, true);
            
            // 反転前座標の描画
            nBmd_.lock();
            nBmd_.fillRect(nBmd_.rect, BMD_FILL_COLOR);
            for (var i:int = 0; i < len_; i += 2) {
                var posX:Number = nCoordinates_[i];
                var posY:Number = nCoordinates_[i + 1];
                nBmd_.setPixel32(posX, posY, N_PIXEL_COLOR);
            }
            nBmd_.unlock();
        }
        
        
        // ループ処理
        private function update(e:Event):void {
            // マウスカーソル座標取得
            var mx:Number = mouseX;
            var my:Number = mouseY;
            
            // マウスの移動に伴い対称軸円と中心交差線を動かす
            axis_.x = mx;
            axis_.y = my;
            
            // 座標の反転計算
            invert(mx, my, nCoordinates_, iCoordinates_);

            // 反転座標の描画
            iBmd_.lock();
            iBmd_.fillRect(iBmd_.rect, BMD_FILL_COLOR);
            for (var i:int = 0; i < len_; i += 2) {
                var posX:Number = iCoordinates_[i];
                var posY:Number = iCoordinates_[i + 1];
                iBmd_.setPixel32(posX, posY, I_PIXEL_COLOR);
            }
            iBmd_.unlock();
        }
        
        // 座標の反転計算
        private function invert(x0:Number, y0:Number, nCoordinate:Vector.<int>, iCoordinate:Vector.<int>):void {
            for (var i:int = 0; i < len_; i += 2) {
                // 円の中心O(x0, y0)    -> マウスカーソルの座標
                // 与えられた点P(x, y)    -> nCoordinates_
                // 求める点P'(x', y')    -> iCoordinates_
                // 反転計算式
                // x' = r^2 * (x - x0) / ((x - x0)^2 + (y - y0)^2) + x0
                // y' = r^2 * (y - y0) / ((x - x0)^2 + (y - y0)^2) + y0
                var xp:Number = nCoordinates_[i];
                var yp:Number = nCoordinates_[i + 1];
                var distX:Number = xp - x0;
                var distY:Number = yp - y0;
                var distXY:Number = distX * distX + distY * distY;
                iCoordinates_[i]     = RADIUS_SQUARE * distX / distXY + x0;
                iCoordinates_[i + 1] = RADIUS_SQUARE * distY / distXY + y0;
            }
        }
    }
}

//package {
    import flash.display.BitmapData;
    import flash.display.Graphics;
    import flash.display.Shape;
    /**
     * 指定図形を構成する座標値の取得
     * @author YOSHIDA, Akio (Aquioux)
     */
    /*public*/ class DataFactory {
        
        public function DataFactory() {
        }

        /**
         * 線の座標取得
         * @param    sw    ステージサイズ幅
         * @param    sh    ステージサイズ高
         * @param    x0    開始座標X
         * @param    y0    開始座標Y
         * @param    x1    終了座標X
         * @param    y1    終了座標Y
         * @return    座標を1次元配列で格納した Vector
         */
        public static function drawLine(sw:int, sh:int, x0:int, y0:int, x1:int, y1:int):Vector.<int> {
            var shape:Shape = new Shape();
            var g:Graphics = shape.graphics;
            g.lineStyle(0, 0x000000);
            g.moveTo(x0, y0);
            g.lineTo(x1, y1);
            return getVector(shape, sw, sh);
        }
        
        /**
         * 円の座標取得
         * @param    sw    ステージサイズ幅
         * @param    sh    ステージサイズ高
         * @param    px    中心座標X
         * @param    py    中心座標Y
         * @param    radius    半径
         * @return    座標を1次元配列で格納した Vector
         */
        public static function drawCircle(sw:int, sh:int, px:int, py:int, radius:int):Vector.<int> {
            var shape:Shape = new Shape();
            var g:Graphics = shape.graphics;
            g.lineStyle(0, 0x000000);
            g.drawCircle(px, py, radius);
            return getVector(shape, sw, sh);
        }
        
        static private function getVector(shape:Shape, sw:int, sh:int):Vector.<int> {
            var transparent:int = 0x00000000;
            
            var bmd:BitmapData = new BitmapData(sw, sh, true, transparent);
            bmd.draw(shape);
            
            var v:Vector.<int> = new Vector.<int>();
            for (var y:int = 0; y < sh; y++) {
                for (var x:int = 0; x < sw; x++) {
                    if (bmd.getPixel32(x, y) != transparent) v.push(x, y);
                }
            }
            return v;
        }
    }
//}