スポンサーサイト

-------- | --:--

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

[ActionScript 3.0] 行列式を利用した多角形と点の位置関係

2007-11-06 | 20:12

前回は三角形だったが、四角形以上の多角形でもまったく同じようにして判定できる。
(ただし、凸な多角形である必要がある)
それぞれの辺の両方の頂点と点を結んだ三角形の行列式を求めて符号を調べればよい

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

    [SWF(width="500", height="500", backgroundColor="#ffffff")]
        public class Main extends Sprite
        {
            public var vertexes:Array;

            private var balls:Array;
            private var rad:Number=0;

            public function Main()
            {
                balls = new Array();
                for(var i:int = 0 ; i < 50 ; i++){
                    var b:Ball = new Ball(0xff00, 5);
                    b.x = Math.random()*500;
                    b.y = Math.random()*500;
                    b.vx = Math.random()*2+1;
                    b.vy = Math.random()*2+1;
                    addChild(b);
                    balls.push(b);
                }

                this.vertexes = new Array();
                this.vertexes.push( new Ball(0xff, 2, 200, 50));
                this.vertexes.push( new Ball(0xff, 2, 300, 50));
                this.vertexes.push( new Ball(0xff, 2, 350, 90));
                this.vertexes.push( new Ball(0xff, 2, 400, 150));
                this.vertexes.push( new Ball(0xff, 2, 360, 350));
                this.vertexes.push( new Ball(0xff, 2, 290, 410));
                this.vertexes.push( new Ball(0xff, 2, 250, 440));
                this.vertexes.push( new Ball(0xff, 2, 200, 450));
                this.vertexes.push( new Ball(0xff, 2, 100, 200));
                this.vertexes.push( new Ball(0xff, 2, 100,100));

                for each (var v:Ball in vertexes){
                    addChild(v);
                }

                this.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
            }

            private function enterFrameHandler(event:Event):void
            {
                var rad:Number = 0.02;
                var px:Number = 250;
                var py:Number = 250;
                for each (var v:Ball in vertexes){
                    var x:Number = v.x -px;
                    var y:Number = v.y -px;
                    v.x = x*Math.cos(rad) - y*Math.sin(rad) +px;
                    v.y = x*Math.sin(rad) + y*Math.cos(rad) +py;
                }

                graphics.clear();
                graphics.lineStyle(1, 0x0000ff, 0.5);
                graphics.moveTo(vertexes[0].x, vertexes[0].y);
                for(var j:int = 0; j < vertexes.length ; j++){
                    graphics.lineTo(vertexes[j].x, vertexes[j].y);
                }
                graphics.lineTo(vertexes[0].x, vertexes[0].y);

                for each (var b:Ball in balls){
                    b.move();

                    var inn:Boolean = true;
                    for (var i:int = 0 ; i < vertexes.length-1 ; i++){
                        var det:Number = (vertexes[i].x-b.x)*(vertexes[i+1].y-b.y)-
                            (vertexes[i+1].x - b.x)*(vertexes[i].y - b.y);
                        if(det < 0){
                            inn = false;
                            break;
                        }
                    }
                    // 最後と先頭
                    if(inn && (vertexes[i].x-b.x)*(vertexes[0].y-b.y)-
                            (vertexes[0].x - b.x)*(vertexes[i].y - b.y) < 0) inn = false;

                    var c:int = (inn) ? 0xff0000 : 0xff;
                    b.color = c;
                }
            }
        }
}

import flash.display.*;
internal class Ball extends Sprite{
    public var vx:int = 0;
    public var vy:int = 0;
    public var radius:int;
    public var currentColor:int;
    public function Ball(c:Number=0, radius:Number = 0, x:int=0,y:int=0){
        this.x = x;
        this.y = y;
        graphics.lineStyle(1, 0, 0.5);
        graphics.beginFill(c);
        graphics.drawCircle(0,0,radius);
        graphics.endFill();
        this.radius = radius;
    }

    public function set color(c:int):void{
        if(currentColor != c){
            currentColor = c;
            graphics.clear();
            graphics.lineStyle(1, 0, 0.5);
            graphics.beginFill(currentColor);
            graphics.drawCircle(0,0,radius);
            graphics.endFill();
        }
    }

    public function move():void{
        x += vx;
        y += vy;
        if(x < 0 || x > 500)
            vx *= -1;
        if(y < 0 || y > 500)
            vy *= -1;
    }
}


スポンサーサイト

Comment

Post a comment

Secret

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。