/// <summary> /// 光線r = p + tdが円sと交差しているかどうかを判定 /// </summary> /// <param name="vP">基点</param> /// <param name="vD">方向ベクトル</param> /// <param name="circle">対象とする円</param> /// <return>交差している場合、true返す</return> public static bool RayCircle(MCVector2 vP, MCVector2 vD, MCCircle2 circle) { MCVector2 vM = vP - circle.C; float fC = vM.Dot() - circle.R * circle.R; // 少なくとも1つの実数解が存在している場合、交差している if (fC <= 0.0f) { return(true); } float fB = vM.Dot(vD); // 光線の原点が円の外側にあり光線が円から離れた方向を指している場合には早期に終了 if (fB > 0.0f) { return(false); } float fDiscr = fB * fB - fC; // 負の判別式は光線が円を外れていることに一致 if (fDiscr < 0.0f) { return(false); } // これで光線は円と交差している return(true); }
/// <summary> /// 光線r = p + td, |rvD| = 1が円sに対して交差しているかどうか。 /// </summary> /// <param name="rvP">基点</param> /// <param name="rvD">方向ベクトル</param> /// <param name="rS">対象とする円</param> /// <param name="time">0≦t≦Tmax</param> /// <param name="vIntersect">交差した位置</param> /// <return>交差している場合、交差している*pTの値および交差点*pQを返す</return> bool IntersectRayCircle(MCVector2 rvP, MCVector2 rvD, MCCircle2 rS, out float time, out MCVector2 vIntersect) { time = 0; vIntersect = new MCVector2(); MCVector2 vM = rvP - rS.C; float fB = vM.Dot(rvD); float fC = vM.Dot() - rS.R * rS.R; // rの原点が*rSの外側にあり(c > 0)、rが*rSから離れていく方向を指している場合(fB > 0)に終了 if (fC > 0.0f && fB > 0.0f) { return(false); } float fDiscr = fB * fB - fC; // 負の判別式は光線が円を外れていることに一致 if (fDiscr < 0.0f) { return(false); } // これで光線は円と交差していることが分かり、交差する最小の値*pTを計算 time = -fB - (float)System.Math.Sqrt(fDiscr); // *pTが負である場合、光線は円の内側から開始しているので*pTをゼロにクランプ if (time < 0.0f) { time = 0.0f; } vIntersect = rvP + time * rvD; return(true); }
/// <summary> /// 光線r = p + td, |vDir| = 1が円sに対して交差しているかどうか。 /// </summary> /// <param name="position">基点</param> /// <param name="vDir">方向ベクトル</param> /// <param name="rS">対象とする円</param> /// <param name="vIntersect1">接触点1</param> /// <param name="vIntersect2">接触点2</param> /// <return>交差している場合、交差点の数を返す</return> int IntersectRayCircle(MCVector2 position, MCVector2 vDir, out MCVector2 vIntersect1, out MCVector2 vIntersect2) { vIntersect1 = new MCVector2(); vIntersect2 = new MCVector2(); float t; MCVector2 vM = position - C; float a = vM.Dot(vDir); float b = vM.Dot() - R * R; // rの原点が*rSの外側にあり(c > 0)、rが*rSから離れていく方向を指している場合(a > 0)に終了 if (b > 0 && a > 0) { return(0); } float discr = a * a - b; // 負の判別式は光線が円を外れている if (discr < 0) { return(0); } // これで光線は円と交差していることが分かり、交差する最小の値*pTを計算 t = -a - (float)System.Math.Sqrt(discr); // tが負である場合、光線は円の内側 if (t < 0) { vIntersect1 = position + (t * -1) * vDir; return(1); } else if (discr == 0) { vIntersect1 = position + t * vDir; return(1); } vIntersect1 = position + t * vDir; vIntersect2 = position + (-a + (float)System.Math.Sqrt(discr)) * vDir; return(2); }
/// <summary> /// 平面に対してvPointの点を垂直射影したときの点との大きさpTを返す@n /// </summary> /// 戻り値がマイナスの場合は裏面、プラスの時は表面に点vPointがある@n /// 平面の法線は正規化されている物とする。 /// <param name="vPoint">垂直射影する点</param> /// <return>平面から指定した点までの距離</return> float DistanceTo(MCVector2 vPoint) { return(vNormal.Dot(vPoint) - distance); }