flash on 2011-11-3

by bradsedito
♥0 | Line 149 | Modified 2011-11-03 11:48:14 | MIT License
play

ActionScript3 source code

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




package  
{
    import flash.display.*;
    import flash.events.*;
    import flash.geom.*;

    public class ConvexHull extends Sprite
    {
         public  var validFaces:Vector.<Face>;
         public  var visibleFaces:Vector.<Face>;
         public  var tmpFaces:Vector.<Face>;
        
/*
     * performs a convexhull in 3D
     * @param    points the Vector3D cloud
     * @return a series of indices to create the faces of the hull
*/         
        
        public function ConvexHull():void
        {    
             addEventListener( Event.ENTER_FRAME, loop);
             function loop( event:Event ):void
             {
                 //var validFaces:Vector.<Face>;
                 //var visibleFaces:Vector.<Face>;
                 //var tmpFaces:Vector.<Face>;    
             }
        }


        public function process( points:Vector.<Vector3D> ):Vector.<int>
        {
            if ( points.length < 3 ) 
            {
                return null;
            }
            
            //local copy of the point set
            //vertices = .concat();
            Face.points = points;
            
            
            //calculates the first convex tetrahedron 
            
            //creates a face with the first 3 vertices
            var face:Face = new Face( 0, 1, 2 );
            
            //this is the center of the tetrahedron, all face should point outwards:
            //they should not be visible to the centroid
            var v:Vector3D = centroid( points, 3, face );
            
            if ( face.isVisible( v ) ) face.flip();
            
            var face0:Face = new Face( 3, face.i0, face.i1 );
            if ( face0.isVisible( v ) ) face0.flip();
            
            var face1:Face = new Face( 3, face.i1, face.i2 );
            if ( face1.isVisible( v ) ) face1.flip();
            
            var face2:Face = new Face( 3, face.i2, face.i0 );
            if ( face2.isVisible( v ) ) face2.flip();
            
            
            //store the tetrahedron faces in the valid faces list
            validFaces = Vector.<Face>( [ face, face0, face1, face2 ] );
            
            visibleFaces = new Vector.<Face>();
            tmpFaces = new Vector.<Face>();
            
            
            
            //so as we have a convex tetrahedron, we can skip the first 4 points
            for ( var i:int = 4; i < points.length; i++ )
            {
                //for each avaiable vertices
                v = points[ i ];
                
                //checks the point's visibility from all faces
                visibleFaces.length = 0;
                for each( face in validFaces )
                {    
                    if ( face.isVisible( v ) )
                    {
                        visibleFaces.push( face ); 
                    }
                }
                
                 
                 var validFaces:Vector.<Face>;
                 var visibleFaces:Vector.<Face>;
                 var tmpFaces:Vector.<Face>;                   
                               
                //the vertex is not visible : it is inside the convex hull, keep on
                if ( visibleFaces.length == 0 )
                {
                    continue;
                }
                
                //the vertex is outside the convex hull
                //delete all visible faces from the valid List
                for each ( face in visibleFaces )
                {
                    validFaces.splice( validFaces.indexOf( face ), 1 );
                }
                
                //special case : only one face is visible
                //it's ok to create 3 faces directly for they won't enclose any other point
                if ( visibleFaces.length == 1 )
                {
                    face = visibleFaces[ 0 ];
                    validFaces.push( new Face( i, face.i0, face.i1 ) );
                    validFaces.push( new Face( i, face.i1, face.i2 ) );
                    validFaces.push( new Face( i, face.i2, face.i0 ) );
                    continue;
                }
                
                //creates all possible new faces from the visibleFaces
                tmpFaces.length = 0;
                for each( face in visibleFaces )
                {
                    tmpFaces.push( new Face( i, face.i0, face.i1 ) );
                    tmpFaces.push( new Face( i, face.i1, face.i2 ) );
                    tmpFaces.push( new Face( i, face.i2, face.i0 ) );
                }
                
                var other:Face;
                for each( face in tmpFaces )
                {
                    //search if there is a point in front of the face : 
                    //this means the face doesn't belong to the convex hull
                    search : for each( other in tmpFaces )
                    {
                        if ( face != other )
                        {
                            if ( face.isVisible( other.centroid ) )
                            {
                                face = null;
                                break search;
                            }
                        }
                    }
                    //the face has no point in front of it
                    if ( face != null ) validFaces.push( face );
                }
            }
            
            var result:Vector.<int> = new Vector.<int>();
            for each( face in validFaces ) 
            {
                result.push( face.i0, face.i1, face.i2 );
            }
            return result;
        }
        
         private function centroid( points:Vector.<Vector3D>, index:int, face:Face ):Vector3D
        {
            
            var p:Vector3D = points[ index ];
            var p0:Vector3D = points[ face.i0 ];
            var p1:Vector3D = points[ face.i1 ];
            var p2:Vector3D = points[ face.i2 ];
            return new Vector3D(     ( p.x + p0.x +  p1.x +  p2.x  ) / 4,    ( p.y + p0.y +  p1.y +  p2.y  ) / 4,    ( p.z + p0.z +  p1.z +  p2.z  ) / 4        );
            
        }
    }
}
import flash.geom.Vector3D;
class Face
{
    static public var points:Vector.<Vector3D>;
    public var i0:int, i1:int, i2:int;
    public var a:Number, b:Number, c:Number, d:Number;
    
    public function Face( i0:int, i1:int, i2:int )
    {
        
        this.i0 = i0;
        this.i1 = i1;
        this.i2 = i2;
        
        computePlane();
        
    }
    
    private function computePlane():void 
    {
        
        var v1:Vector3D = points[ i0 ];
        var v2:Vector3D = points[ i1 ];
        var v3:Vector3D = points[ i2 ];
     
        a = v1.y * (v2.z - v3.z) + v2.y * (v3.z - v1.z) + v3.y * (v1.z - v2.z);
        b = v1.z * (v2.x - v3.x) + v2.z * (v3.x - v1.x) + v3.z * (v1.x - v2.x);
        c = v1.x * (v2.y - v3.y) + v2.x * (v3.y - v1.y) + v3.x * (v1.y - v2.y);
        d = -( v1.x * ( v2.y * v3.z - v3.y * v2.z ) + v2.x * (v3.y * v1.z - v1.y * v3.z) + v3.x * (v1.y * v2.z - v2.y * v1.z) );
        
    }
    
    public function isVisible( p:Vector3D ):Boolean
    {
        
        return ( a * p.x + b * p.y + c * p.z + d ) > 0;
        
    }
    
    public function get centroid( ):Vector3D
    {
        
        var p0:Vector3D = points[ i0 ];
        var p1:Vector3D = points[ i1 ];
        var p2:Vector3D = points[ i2 ];
        return new Vector3D( ( p0.x + p1.x + p2.x ) / 3, ( p0.y + p1.y + p2.y ) / 3, ( p0.z + p1.z + p2.z ) / 3 );
        
    }
    
    public function flip():void
    {
        var t:int = i0;
        i0 = i1;
        i1 = t;
        computePlane();
    }
    
}