Beautifl - Flash Gallery

Thumbnail : 凸面の閉路
凸面の閉路
umhr 2010-05-21 MIT License

再生するにはFlash Playerが必要です。デスクトップのブラウザでご覧ください。

/*
 * 凸面の閉路
 * 
 * 立方体のシルエットだけ欲しいときがあって、
 * でも、描画に負担をかけたくない時用。
 * */

package {
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.geom.Matrix3D;
    import flash.geom.Point;
    import flash.geom.Vector3D;
    import org.libspark.betweenas3.BetweenAS3;
    import org.libspark.betweenas3.easing.*;
    import org.libspark.betweenas3.tweens.ITween;
    [SWF(width = 465, height = 465, backgroundColor = 0x282222, frameRate = 30)]
    public class Main extends Sprite {
        private var _sps:Array;
        private var _sp:Sprite;
        private const DEGREE_FROM_RADIAN:Number = 180 / Math.PI;
        private var _canvas:Sprite = new Sprite();
        private var _vector3Ds:Vector.<Vector3D> = new Vector.<Vector3D>();
        public function Main():void {
            
            this.addChild(_canvas);
            
            _sp = new Sprite();
            _sp.x = stage.stageWidth / 2;
            _sp.y = stage.stageHeight / 2;
            this.addChild(_sp);
            
            _sps = [];
            for (var i:int = 0; i < 24; i++) {
                _sps[i] = new Sprite();
                _sps[i].graphics.beginFill(0xFF0000);
                _sps[i].graphics.drawCircle(0, 0, 5);
                this.addChild(_sps[i]);
                _vector3Ds[i] = new Vector3D(Math.random() * 100 - 50, Math.random() * 100 - 50, Math.random() * 100 - 50);
            }
            
            this.addEventListener(Event.ENTER_FRAME, onEnter);
            
        }
        private function onEnter(event:Event):void {
            _sp.rotationX += (stage.mouseY-stage.stageHeight/2)/100;
            _sp.rotationY += Math.round((stage.mouseX-stage.stageWidth/2)/100);
            draw();
            if (_sp.rotationY % 180 == 0) {
                var t_array:Array = [];
                var n:int = _sps.length;
                for (var i:int = 0; i < n; i++) {
                    t_array.push(BetweenAS3.tween(_vector3Ds[i],{x:Math.random() * 360 - 180,z:Math.random() * 360 - 180},null,1,Cubic.easeOut));
                    t_array.push(BetweenAS3.tween(_vector3Ds[i],{y:Math.random() * 360 - 180},null,1,Cubic.easeIn));
                }
                var t:ITween;
                t = BetweenAS3.parallel.apply(null, t_array);
                t.play();
            }
        }
        private function draw():void {
            var _array:Array = [];
            
            var n:int = _sps.length;
            for (var i:int = 0; i < n; i++) {
                var poz:Vector3D = _sp.transform.matrix3D.transformVector(_vector3Ds[i]);
                _array.push(new Point(poz.x, poz.y));
                _sps[i].x = poz.x;
                _sps[i].y = poz.y;
            }
            
            var points:Array = Geometry.getConvex.apply(null, Geometry.sortPosition.apply(null, _array));
            
            _canvas.graphics.clear();
            _canvas.graphics.lineStyle(0, 0x00FF00);
            _canvas.graphics.beginFill(0x001100);
            _canvas.graphics.moveTo(points[0].x, points[0].y);
            n = points.length;
            for (i = 1; i < n; i++) {
                _canvas.graphics.lineTo(points[i].x, points[i].y);
            }
            _canvas.graphics.lineTo(points[0].x, points[0].y);
            
        }
    }
}
import flash.geom.Point;

//Geometry
class Geometry {
    static public const DEGREE_FROM_RADIAN:Number = 180 / Math.PI;
    /*
    //参考:三角形の面積
    //http://www5d.biglobe.ne.jp/~tomoya03/shtml/algorithm/SurfaceArea.htm
    static public function getTriSurfaceArea(a:Point, b:Point, c:Point):Number {
        return Math.abs((c.x - a.x) * (b.y - a.y) - (b.x - a.x) * (c.y - a.y)) / 2;
    }
    //多角形の面積。ただし、凹形によっては間違った面積が返る
    static public function getPolySurfaceArea(... rest):Number {
        var result:Number = 0;
        var n:int = rest.length;
        for (var i:int = 2; i < n; i++) {
            result += getTriSurfaceArea(rest[0], rest[i - 1], rest[i]);
        }
        return result;
    }
    */
    //三点のなす角
    static public function getTriRadian(a:Point, r:Point, b:Point):Number {
        var ra:Point = r.subtract(a);
        var rb:Point = r.subtract(b);
        return Math.atan2(ra.x * rb.y - ra.y * rb.x, ra.x * rb.x + ra.y * rb.y);
    }
    
    //角度の和による内外判定
    //http://kone.vis.ne.jp/diary/diaryb09.html#040518_result
    static public function pointInPolygon(... rest):Boolean {
        var radian:Number = 0;
        var n:int = rest.length - 1;
        for (var i:int = 0; i < n; i++) {
            radian += getTriRadian(rest[i + 1], rest[0], rest[((i + 1) % n) + 1]);
        }
        return nearEquals(Math.abs(DEGREE_FROM_RADIAN * radian), 360, 0.1);
    }
    
    //だいたい同じ
    static public function nearEquals(a:Number, b:Number, tolerance:Number):Boolean {
        return ((b - tolerance) <= a && a <= (b + tolerance));
    }
    
    //凸型にする。
    //ある点が他の点からなる多角形の内側にあれば、それは凹点とみなす
    static public function getConvex(... rest):Array {
        var result:Array = [];
        var n:int = rest.length;
        for (var i:int = 0; i < n; i++) {
            var ar:Array = [];
            ar.push(rest[i]);
            for (var j:int = 0; j < n; j++) {
                if (j != i) {
                    ar.push(rest[j]);
                }
            }
            if (!pointInPolygon.apply(null, ar)) {
                result.push(rest[i]);
            }
        }
        
        if (n > result.length) {
            result = getConvex.apply(null, result);
        }
        return result;
    }
    
    
    //閉路作成:http://www5d.biglobe.ne.jp/~tomoya03/shtml/algorithm/Heiro.htm
    static public function sortPosition(... rest):Array {
        var temp:Array = [];
        var sorted:Array = [];
        var sorted2:Array = [];
        var radians:Array = [0];
        var result:Array = [];
        var n:int = rest.length;
        for (var i:int = 0; i < n; i++) {
            temp.push(rest[i].y);
        }
        sorted = temp.sort(Array.NUMERIC | Array.RETURNINDEXEDARRAY);
        for (i = 1; i < n; i++) {
            var j:int = sorted[i];
            radians.push(Math.atan2(rest[j].y - rest[sorted[0]].y, rest[j].x - rest[sorted[0]].x));
        }
        sorted2 = radians.sort(Array.NUMERIC | Array.RETURNINDEXEDARRAY);
        temp = [];
        for (i = 0; i < n; i++) {
            temp.push(sorted[sorted2[i]]);
        }
        for (i = 0; i < n; i++) {
            result.push(rest[temp[i]]);
        }
        return result;
    }
    
}