円と線分の交差判定
こちらのサイトによると円と線分の交差判定方法は、
線分の始点から終点へのベクトルを v、 線分の始点から球の中心へのベクトルを c とします。 v・c<0 の時、球の中心が線分の始点よりも線分から遠くにあるので、 c の長さが球の半径よりも小さければ交差と判定します。 v・c≧0 の時、v・c と v2 の長さを比べます (v 方向での c の長さと v の比較)。 v・c の方が大きければ、球の中心が線分の終点よりも線分から遠くにあるので、 線分の終点と球の中心の距離の 2 乗を求めて、 球の半径の 2 乗よりも小さければ交差と判定します。 v2 の方が大きければ、球の中心から線分に降ろした足が線分上に 存在するはずです。 c2-(v・c/v2)*v・c でその長さの 2 乗が分かり、 球の半径の 2 乗よりも小さければ交差と判定します。
とのことで、詳しくは理解していませんがActionScriptに移植しました。
class Equation{ //========================================================================// // // 円と線分の交差判定を行う // 交差していない場合は null を返却する // // crcl : { x:円中心点X座標, y:円中心点Y座標, r:半径 } // line : { pt1:{ x:X座標, y:Y座標 }, pt2:{ x:X座標, y:Y座標 } } // // ※ : line.pt1を始点 line.pt2を終点 とする // // return : 交差している/true or 交差していない/false // //========================================================================// public static function checkCrclCls( crcl:Object, line:Object ):Boolean{ //V : 線分始点から終点へのベクトル //C : 線分始点から円中心へのベクトル var V:Object = { x:line.pt2.x-line.pt1.x, y:line.pt2.y-line.pt1.y }; var C:Object = { x:crcl.x-line.pt1.x, y:crcl.y-line.pt1.y }; //二つのベクトルの内積を求める var n1:Number = Equation.dotProduct( V, C ); if( n1 < 0 ){ //Cの長さが円の半径より小さい場合 : 交差している return (Equation.distance(line.pt1, crcl) < crcl.r) ? true : false; } var n2:Number = Equation.dotProduct( V, V ); if( n1 > n2 ){ //線分の終点と円の中心の距離の二乗を求める var len:Number = Math.pow( Equation.distance(line.pt2, crcl), 2 ); //円の半径の二乗よりも小さい場合 : 交差している return ( len < Math.pow( crcl.r, 2 ) ) ? true : false; }else{ var n3:Number = Equation.dotProduct( C, C ); return ( n3-(n1/n2)*n1 < Math.pow( crcl.r, 2 ) ) ? true : false; } } //========================================================================// // // ベクトルとベクトルの内積を求める // // vec1 : { x, y } // vec2 : { x, y } // // retrun : 内積 // //========================================================================// public static function dotProduct( vec1:Object, vec2:Object ):Number{ return ( vec1.x * vec2.x ) + ( vec1.y * vec2.y ); } //========================================================================// // // 二点の成す線分の移動量を求める // // pt1 : { x:点1X座標, y:点1Y座標 } // pt2 : { x:点2X座標, y:点2Y座標 } // // retrun : 移動量 // //========================================================================// public static function distance( pt1:Object, pt2:Object ):Number{ return Math.sqrt(Math.pow(pt1.x-pt2.x, 2) + Math.pow(pt1.y-pt2.y, 2)); } }
【 使用例 】
//_rootに点を示すムービークリップ mc1, mc2, mc3が存在する var CRCL_R:Number = 60; //円の半径 var pt1 :Object = { x:_root.mc1._x, y:_root.mc1._y }; var pt2 :Object = { x:_root.mc2._x, y:_root.mc2._y }; var crcl:Object = { x:_root.mc3._x, y:_root.mc3._y, r:CRCL_R }; var line:Object = { pt1:pt1, pt2:pt2 }; //円と線分の交差判定を行う trace( Equation.checkCrclCls( crcl, line ) );
【 サンプル1 】円と線分との交差判定
線分の始点と終点が両方とも円内部にある場合もEquation.checkCrclClsメソッドは交差していると判定しています。円周と線分との交差判定でないことにご注意ください。
円周と線分の交差判定を行いたい場合は、あらかじめ線分の始点と終点が円内部にあるかどうかを調査し、始点と終点の両方がが円内部にある場合、円と線分の交差判定を行わないようにすればよいと思われます。
点と円の衝突判定には以下のメソッドを利用します。
class Equation{ //========================================================================// // // 点と円の衝突判定 // // 点と円の中心の距離の二乗を求め // その長さが円の半径の二乗以下なら衝突している // // pt : { x:点X座標, y:点Y座標 } // crcl : { x:円中心点X座標, y:円中心点Y座標, r:半径 } // // return : true/衝突している or false/衝突していない // //========================================================================// public static function checkPntCrclCrs( pt:Object, crcl:Object ):Boolean{ var dis:Number = Math.pow( (pt.x - crcl.x), 2 ) + Math.pow( (pt.y - crcl.y), 2 ); return ( dis <= Math.pow( crcl.r, 2 ) ) ? true : false; } }
【 サンプル2 】円周と線分との交差判定
円周と線分とが交差している場合のみ、円周上に交点が表示されます。