スポンサーサイト

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

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

[ActionScript 3.0] 線分の交差判定

2007-12-15 | 16:02

他の線分と交差している線分は赤、交差していない線は青で表示。
線分を延長した直線同士の交点をまず求め、その交点が互いの線分の両端の内側にあるかをベクトルの内積を使って求めている。

package
{
        import flash.display.*;
        import flash.geom.*;
        import flash.events.*;
        import flash.utils.*;
        
        [SWF(width="500", height="500", framerate="30", backgroundColor="#ffffff")]
        public class LineCross extends Sprite
        {
                private var balls:Array;
                
                private var WIDTH:int = 500;
                private var HEIGHT:int = 500;
                
                private var CNT:int = 30;
                
                public function LineCross()
                {
                        balls = new Array();
                        for(var i:int = 0 ; i < CNT ; i++){
                                var b:Ball = new Ball(0xff00, 2);
                                b.x = Math.random()*WIDTH;
                                b.y = Math.random()*HEIGHT;
                                b.vx = Math.random()*3+1;
                                b.vy = Math.random()*3+1;
                                addChild(b);
                                balls.push(b);
                        }
                        
                        stage.addEventListener(Event.ENTER_FRAME, loop);
                        addEventListener(MouseEvent.CLICK, function(e:*):void{
                                stage.removeEventListener(Event.ENTER_FRAME, loop);
                        });
                        
                }
                
                private function loop(event:*):void
                {
                        graphics.clear();
                        
                        var points:Array = [];
                        for each (var b:Ball in balls){
                                
                                b.x += b.vx;
                                b.y += b.vy;
                                if(b.x < 0 || b.x > WIDTH)
                                b.vx *= -1;
                                if(b.y < 0 || b.y > HEIGHT)
                                b.vy *= -1;
                        }
                        
                        var lines:Array = [];
                        
                        for(var j:int = 0 ; j < CNT ; j += 2){
                                var b1:Ball = balls[j];
                                var b2:Ball = balls[j+1];
                                
                                lines.push(new Line(new Point(b1.x, b1.y), new Point(b2.x, b2.y)));
                                
                                graphics.lineStyle(2, 0xff, 0.5);
                                graphics.moveTo(b1.x, b1.y);
                                graphics.lineTo(b2.x, b2.y);
                        }
                        
                        for(var k:int = 0 ; k < CNT/2 - 1 ; k++){
                                for(var l:int = k + 1 ; l < CNT/2 ; l++){
                                        if(Line.isCross(lines[k], lines[l])){
                                                graphics.lineStyle(3, 0xff0000, 0.5);
                                                graphics.moveTo(lines[k].p1.x, lines[k].p1.y);
                                                graphics.lineTo(lines[k].p2.x, lines[k].p2.y);
                                                graphics.moveTo(lines[l].p1.x, lines[l].p1.y);
                                                graphics.lineTo(lines[l].p2.x, lines[l].p2.y);
                                        }
                                }
                        }
                }
        }
}

import flash.display.*;
internal class Ball extends Sprite{
        public var vx:int = 2;
        public var vy:int = 2;
        public var radius:int;
        public var currentColor:int;
        public function Ball(c:Number=0, radius:Number = 1){
                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{
                
        }
}

import flash.geom.*;
internal class Line{
        public var p1:Point;
        public var p2:Point;
        public function Line(p1:Point, p2:Point){
                this.p1 = p1;
                this.p2 = p2;
        }
        
        // 直線の交点(線分の交点ではない)
        public static function crossPoint(lhs:Line, rhs:Line):Point {
                var a:Point = new Point(lhs.p2.x - lhs.p1.x, lhs.p2.y- lhs.p1.y);
                var b:Point = new Point(rhs.p2.x - rhs.p1.x, rhs.p2.y- rhs.p1.y);
                var c:Point = new Point(rhs.p1.x - lhs.p1.x, rhs.p1.y- lhs.p1.y);
                
                var result:Point = new Point();
                
                var cross_b_c:Number = b.x*c.y - b.y*c.x;
                var cross_b_a:Number = b.x*a.y - b.y*a.x;
                
                if(cross_b_a == 0)
                return null;
                
                result.x = lhs.p1.x + a.x * cross_b_c / cross_b_a;
                result.y = lhs.p1.y + a.y * cross_b_c / cross_b_a;
                
                return result;
        }
        
        public static function isCross(lhs:Line, rhs:Line):Boolean{
                var p:Point = crossPoint(lhs,rhs);
                
                return (p != null &&
                (p.x - rhs.p1.x) * (p.x - rhs.p2.x) + (p.y - rhs.p1.y) * (p.y - rhs.p2.y) < 0) &&
                ((p.x - lhs.p1.x) * (p.x - lhs.p2.x) + (p.y - lhs.p1.y) * (p.y - lhs.p2.y) < 0)
                ;
        }
}


スポンサーサイト

Comment

Post a comment

Secret

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