package { import flash.display.Sprite; import flash.events.MouseEvent; import flash.geom.Point; import flash.display.Graphics; public class LineTest extends Sprite { //マウスドラッグの始点と終点 private var s_p:Point; private var e_p:Point; //描画領域 private var canvas:Sprite; //四角形の四辺を格納する配列 private var lineArray:Array; function LineTest():void{ //四角形の四隅のポイント var leftTop:Point = new Point(stage.stageWidth / 2 - 100, stage.stageHeight / 2 - 100); var rightTop:Point = new Point(stage.stageWidth / 2 + 100, stage.stageHeight / 2 - 100); var rightBottom:Point = new Point(stage.stageWidth / 2 + 100, stage.stageHeight / 2 + 100); var leftBottom:Point = new Point(stage.stageWidth / 2 - 100, stage.stageHeight / 2 + 100); //四角形の描画 var base:Sprite = new Sprite(); var g:Graphics = base.graphics; base.x = base.y = 0; stage.addChild(base); g.lineStyle(3, 0x000000); g.drawRect(leftTop.x, leftTop.y, 200, 200); //四角形の4つの辺をLineインスタンスとして作成し、配列に格納 var line1:Line = new Line(leftTop, rightTop, Line.TYPE_SEGMENT); var line2:Line = new Line(rightTop, rightBottom, Line.TYPE_SEGMENT); var line3:Line = new Line(rightBottom, leftBottom, Line.TYPE_SEGMENT); var line4:Line = new Line(leftBottom, leftTop, Line.TYPE_SEGMENT); lineArray = [line1, line2, line3, line4]; //赤線の描画領域を作成 canvas = new Sprite(); canvas.x = 0; canvas.y = 0; stage.addChild(canvas); stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown); } private function onMouseDown(event:MouseEvent):void{ stage.removeEventListener(MouseEvent.MOUSE_DOWN, onMouseDown); stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp); //ドラッグ開始点の保存(線分の始点) s_p = new Point(mouseX, mouseY); } private function onMouseMove(event:MouseEvent):void{ //ドラッグ終了点の保存(線分の終点) e_p = new Point(mouseX, mouseY); //マウスドラッグによりできた線分の描画 var g:Graphics = canvas.graphics; g.clear(); g.lineStyle(3, 0xff0000); g.moveTo(s_p.x, s_p.y); g.lineTo(e_p.x, e_p.y); //描画された線分と四角形の四辺それぞれの交点を計算 var line:Line = new Line(s_p, e_p, Line.TYPE_SEGMENT); lineArray.forEach(function(item:*, index:int, array:Array):void{ var p:Point = item.getIntersectionPoint(line); if(p != null){ //交点があれば円を描画 g.beginFill(0xff0000); g.drawCircle(p.x, p.y, 10); } }); } private function onMouseUp(event:MouseEvent):void{ stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp); stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown); } } } import flash.geom.Point; import flash.display.Graphics; class Line { /* 2点を通る直線(終端はない) */ public static const TYPE_STRAIGHT:String = "straight"; /* p1からp2の方向に延びる半直線 */ public static const TYPE_HALF:String = "half"; /* p1, p2間の線分 */ public static const TYPE_SEGMENT:String = "segment"; public var p1:Point; public var p2:Point; public var type:String; public function Line(p1:Point, p2:Point, type:String=TYPE_STRAIGHT) { this.p1 = p1; this.p2 = p2; this.type = type; } /** * 2つのLineインスタンスの交点を表わすPointインスタンスを取得する * 交点がない場合はnullを返す * @param line * @return * */ public function getIntersectionPoint(line:Line):Point{ var vector1:Point = this.getVector(); var vector2:Point = line.getVector(); if(cross(vector1, vector2) == 0.0){ //2直線が並行の場合はnullを返す return null; } // 交点を this.p1 + s * vector1 としたとき var s:Number = cross(vector2, line.p1.subtract(this.p1)) / cross(vector2, vector1); // 交点を line.p1 + t * vector2 としたとき var t:Number = cross(vector1, this.p1.subtract(line.p1)) / cross(vector1, vector2); if(this.validateIntersect(s) && line.validateIntersect(t)){ vector1.x *= s; vector1.y *= s; return this.p1.add(vector1); }else{ return null; } } public function getVector():Point{ return p2.subtract(p1); } /** * 交点までのベクトルを p1 + n * (p2 - p1) であらわしたとき、 * nが適切な値の範囲内かどうかを判定する。 * * 直線の場合:nはどの値でもよい * 半直線の場合:nは0以上である必要がある * 線分の場合:nは0以上1以下である必要がある * @param n * @return * */ private function validateIntersect(n:Number):Boolean{ if(this.type === TYPE_HALF){ return (0 <= n); }else if(this.type === TYPE_SEGMENT){ return ((0 <= n) && (n <= 1)); }else{ return true; } } /** * 2つの2次元ベクトルの外積を返す * @param vector1 2次ベクトルを表わすPointインスタンス * @param vector2 2次ベクトルを表わすPointインスタンス * @return * */ private function cross(vector1:Point, vector2:Point):Number{ return (vector1.x * vector2.y - vector1.y * vector2.x); } public function toString():String{ var str:String = ""; if(type === TYPE_STRAIGHT){ str += "---> "; } str += "(" + p1.x + ", " + p1.y + ") ---> (" + p2.x + ", " + p2.y + ")"; if(type === TYPE_STRAIGHT || type === TYPE_HALF){ str += " --->"; } return str; } } 直線や線分の交点を計算する