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

点と多角形との囲み判定

-------------------------------------------------
点と多角形との囲み判定
画面をドラッグし続けると多角形を描画できます。
マウスを離すと、マウスカーソルとのあたり判定を確認できます。
囲みが2重に重なった場合、Flashの描画と同様に
判定を反転しています。
取りこぼしが多かったので+0.0000001したりしてみましたが
形状によっては計算が失敗します。
-------------------------------------------------
Get Adobe Flash player
by Hakuhin 29 Jun 2010
/**
 * Copyright Hakuhin ( http://wonderfl.net/user/Hakuhin )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/kiGA
 */

// -------------------------------------------------
//
// 点と多角形との囲み判定
//
// 画面をドラッグし続けると多角形を描画できます。
// マウスを離すと、マウスカーソルとのあたり判定を確認できます。
//
// 囲みが2重に重なった場合、Flashの描画と同様に
// 判定を反転しています。
// 取りこぼしが多かったので+0.0000001したりしてみましたが
// 形状によっては計算が失敗します。
//
// -------------------------------------------------
package {
    import flash.events.*;
    import flash.display.*;
    import flash.net.*;
    import flash.text.*;
    import flash.utils.*;
    import flash.system.*;
    import flash.geom.*;
    import flash.ui.*;
    import flash.media.*;

    public class Main extends Sprite {
        public function Main() {

        
// -------------------------------------------------
// コンストラクタ
// -------------------------------------------------

// キャプチャタイミング
Wonderfl.capture_delay( 1000 );

// フレームレート
stage.frameRate = 60;

// 100%表示
stage.scaleMode = StageScaleMode.NO_SCALE;

// 左上
stage.align = StageAlign.TOP_LEFT;
stage.align = "TL";


var vertex:Object = null;        // 頂点データ
var mouse_left:Boolean = false;        // 左マウスボタン状態

var tf:TextField = new TextField();
tf.width = 400;
tf.height = 400;
tf.selectable = false;
tf.multiline = true;
tf.wordWrap = true;
addChild(tf);

var shape:Shape = new Shape();    // 描画用シェイプ
addChild(shape);
var graphic:Graphics = shape.graphics;

// マウスが押されたときに実行されるイベント
stage.addEventListener(MouseEvent.MOUSE_DOWN,function(e:MouseEvent):void{
    mouse_left = true; 
    vertex = VertexCreate(new Point(e.localX+0.0000001,e.localY+0.0000001));
});

// マウスが離されたときに実行されるイベント
stage.addEventListener(MouseEvent.MOUSE_UP,function(e:MouseEvent):void{
    mouse_left = false;
    VertexClose(vertex);
});

// マウスが移動したときに実行されるイベント
stage.addEventListener(MouseEvent.MOUSE_MOVE,function(e:MouseEvent):void{
    if(!vertex)    return;
    
    var str:String = "";
    
    str += "頂点数:" + vertex.count + "\n";

    // マウス押しっぱなし
    if(mouse_left){    
    
        var pos:Point = new Point(e.localX+0.0000001,e.localY+0.0000001);
        var vec:Point = pos.subtract(VertexGetPushPoint(vertex));
        if(vec.length > 2){
            VertexPushPoint(vertex,pos);
        }

    // マウスを離した
    }else{        
        if(VertexHittest(vertex,new Point(e.localX,e.localY))){
            VertexSetFillColor(vertex,0xFF8080);
        }else{
            VertexSetFillColor(vertex,0x8080FF);        
        }

        str += "走査 y 座標:" + e.localY + "\n";
        
        str += "交差検出:" + VertexHittestDebug(vertex,new Point(e.localX,e.localY));

    }

    // 描画
    graphic.clear();
    if(mouse_left)        VertexDrawLine(vertex,graphic);
    else                VertexDraw(vertex,graphic);
    
    tf.text = str;
});




// バーテックス作成
function VertexCreate(p:Point):Object{
    var pos:Vector.<Point> = new Vector.<Point>();
    pos.push(p);
    return {
        count:1,
        pos:pos,
        fill_color:0x000000
    };
}

// バーテックスに座標を積む
function VertexPushPoint(obj:Object,p:Point):void{
    obj.pos.push(p);
    obj.count ++;
}

// バーテックスに積んだ座標を取得
function VertexGetPushPoint(obj:Object):Point{
    return obj.pos[obj.count-1];
}

// バーテックスを閉じる
function VertexClose(obj:Object):void{
    if(obj.count > 0){
        obj.pos.push(obj.pos[0]);
        obj.count ++;
    }
}

// バーテックスの面の色
function VertexSetFillColor(obj:Object,color:uint):void{
    obj.fill_color = color;
}

// バーテックスのライン描画
function VertexDrawLine(obj:Object,g:Graphics):void{
    if(obj.count < 1)    return;
    
    var i:int;
    var num:int = obj.count;
    
    g.lineStyle(2.0,0x606060,1.0);
    
    for(i=1;i<num;i++){
        g.moveTo(obj.pos[i-1].x,obj.pos[i-1].y);
        g.lineTo(obj.pos[i].x,obj.pos[i].y);
    }
}

// バーテックスの描画
function VertexDraw(obj:Object,g:Graphics):void{
    if(obj.count < 1)    return;
    
    var i:int;
    var num:int = obj.count;
    
    g.lineStyle(2.0,0x606060,1.0);
    g.beginFill(obj.fill_color,0.6);
    g.moveTo(obj.pos[0].x,obj.pos[0].y);
    
    for(i=1;i<num;i++){
        g.lineTo(obj.pos[i].x,obj.pos[i].y);
    }
    g.endFill();
}


// バーテックスとあたり判定
function VertexHittest(obj:Object,p:Point):Boolean{

    if(obj.count < 2)    return false;

    var i:int;
    var j:int;

    var pos:Vector.<Point> = obj.pos;
    var num:int = pos.length;

    // 双方向リスト構築
    var count:Number = 0;
    var list:Object;
    var prev:Object;
    var next:Object;
    var pref:Object = new Object();
    var post:Object = new Object();
    pref.pref = post;
    pref.post = post;
    post.pref = pref;
    post.post = pref;

    var py:Number = p.y;

    // 水平ラインと線との交差チェック
    for(i=0;i<num;i++){
        
        var b:int = i;
        var e:int = i+1;
        if(e >= num)    e = 0;
    

        // 交差判定
        var nx:Number = -(pos[e].y - pos[b].y);
        var ny:Number =  (pos[e].x - pos[b].x);

        if(nx == 0.0)    continue;

        // 交点
        var px:Number = -(ny * py -(pos[b].x * nx + pos[b].y * ny)) / (nx);


        // 線分交差か調べる
        var ax:Number = px - pos[b].x;
        var ay:Number = py - pos[b].y;
        var bx:Number = px - pos[e].x;
        var by:Number = py - pos[e].y;
        
        if((ax * bx) + (ay * by) >= 0)    continue;

        // 格納位置を検索(ソート)
        list = pref.post;
        while(true){
            if(list == post)    break;
            if(list.pos >= px){
                break;
            }

            list = list.post;
        }

        var front:Boolean = (nx >= 0) ? true : false;
        
        // 一致すれば登録しない
        if(list.pos == px){
            if(list.front == front){
                continue;
            }
        }

        // リストに挿入
        prev = list.pref;
        next = list;
        list = new Object();

        list.pref = prev;
        list.post = next;
        prev.post = list;
        next.pref = list;
        list.pos = px;
        list.front = front;
        count ++;
    }


    // 開始地点
    pref.front = false;

    // 反転検索
    list = pref;
    while(true){
        next = list.post;
        if(next == post)    break;

        // 次のデータと裏表が一致するなら逆転
        if(next.front == list.front){
            next.front = (next.front) ? false:true;
        }

        list = next;
    }

    list = pref.post;
    while(true){
        if(list == post)    break;
        if(list.pos < p.x){

            list = list.post;

            continue;
        }
        break;
    }

    if(list.pref.front){
        return true;
    }

    return false;
};




// バーテックスとあたり判定のデバッグ
function VertexHittestDebug(obj:Object,p:Point):String{

    if(obj.count < 2)    return "";

    var str:String = "";
    var i:int;
    var j:int;

    var pos:Vector.<Point> = obj.pos;
    var num:int = pos.length;

    // 双方向リスト構築
    var count:Number = 0;
    var list:Object;
    var prev:Object;
    var next:Object;
    var pref:Object = new Object();
    var post:Object = new Object();
    pref.pref = post;
    pref.post = post;
    post.pref = pref;
    post.post = pref;

    var py:Number = p.y;

    // 水平ラインと線との交差チェック
    for(i=0;i<num;i++){
        
        var b:int = i;
        var e:int = i+1;
        if(e >= num)    e = 0;
    

        // 交差判定
        var nx:Number = -(pos[e].y - pos[b].y);
        var ny:Number =  (pos[e].x - pos[b].x);

        if(nx == 0.0)    continue;

        // 交点
        var px:Number = -(ny * py -(pos[b].x * nx + pos[b].y * ny)) / (nx);


        // 線分交差か調べる
        var ax:Number = px - pos[b].x;
        var ay:Number = py - pos[b].y;
        var bx:Number = px - pos[e].x;
        var by:Number = py - pos[e].y;
        
        if((ax * bx) + (ay * by) >= 0)    continue;

        // 格納位置を検索(ソート)
        list = pref.post;
        while(true){
            if(list == post)    break;
            if(list.pos >= px){
                break;
            }

            list = list.post;
        }

        var front:Boolean = (nx >= 0) ? true : false;
        
        // 一致すれば除去
        if(list.pos == px){
            if(list.front == front){
                continue;
            }
        }

        // リストに挿入
        prev = list.pref;
        next = list;
        list = new Object();

        list.pref = prev;
        list.post = next;
        prev.post = list;
        next.pref = list;
        list.pos = px;
        list.front = front;
        count ++;
    }
    
    if(!count)    return "";


    // 開始地点
    pref.front = false;

    // 反転検索
    list = pref;
    while(true){
        next = list.post;
        if(next == post)    break;

        // 次のデータと裏表が一致するなら逆転
        if(next.front == list.front){
            next.front = (next.front) ? false:true;
        }

        list = next;
    }

    var hit:Boolean = false;
    list = pref.post;
    while(true){
        if(list == post)    break;
        
        if(list.pos > p.x){
            if(!hit)    str += "★";
            hit = true;
        }
        str += "[x:" + (Math.floor(list.pos * 10) / 10) + ((list.front)?"開":"閉") + "]";

        list = list.post;
    }
    if(!hit)    str += "★";

    return str;
};



// リサイズ時にフィット
stage.addEventListener(Event.RESIZE,ResizeFunc);
function ResizeFunc(e:Event):void{
    var w:uint = stage.stageWidth;
    var h:uint = stage.stageHeight;
    
    tf.width = w;
    tf.height = h;
}
ResizeFunc(null);


        }
    }
}



// -------------------------------------------------
// 外部画像をサムネイルとしてキャプチャ
// -------------------------------------------------
import flash.net.*;
import flash.events.*;
import flash.display.*;
import flash.geom.*;
function ThumbnailCapture(url:String,time:uint,stage:Stage):void{

    // キャプチャタイミング
    Wonderfl.capture_delay( time );

    // スプライト作成
    var sprite : Sprite = new Sprite();

    // ステージ最前面に配置
    stage.addChildAt(sprite,stage.numChildren);
    
    // ローダー
    var loader_obj : Loader = new Loader();
    loader_obj.contentLoaderInfo.addEventListener (Event.INIT,function(e:Event):void{

        // メモリからインスタンス化
        var loader_memory : Loader = new Loader();
        loader_memory.contentLoaderInfo.addEventListener (Event.INIT,function(e:Event):void{

            // キャプチャ
            var bmp : BitmapData = new BitmapData(loader_memory.width,loader_memory.height,true,0);
            sprite.addChild(loader_memory);
            bmp.draw(sprite);
            sprite.removeChild(loader_memory);
            loader_memory.unload();
            loader_obj.unload();
            loader_memory = null;
            loader_obj = null;
            
            
            // 画像を配置
            var bmp_obj : Bitmap = new Bitmap(bmp);
            bmp_obj .width = stage.stageWidth;
            bmp_obj .height = stage.stageHeight;
            stage.addChild(bmp_obj );
            
        });
        
        // 読み込み開始
        loader_memory.loadBytes(loader_obj.contentLoaderInfo.bytes);
    });
    
    // 読み込み開始
    loader_obj.load(new URLRequest(url));
}