2つのセグメントの交差を決定する別のアルゴリズム

最近、 「2つのセグメントの交差を決定するための簡単なアルゴリズム」という出版物がありました。 2つのセグメントを少しずつ、より幾何学的に交差させる問題を解決することにしました。



2つのセグメントの交点を見つける。



2つのセグメント{P0、P1}および{P2、P3}があります。P0、P1、P2、P3は平面内の点です。 点Pのxy座標をPxおよびPyとして表します

ポイント(x float、y float)構造のP(0..3)配列に4つのポイントの座標があります。







ステップ1-オリジンを転送します。



追加の配列P_copyの点Pの座標を覚えておいてください。 座標系の原点をポイントP0に転送し、ポイントの座標を再計算します。



P_copy = P P(0).x = 0 ; P(0).y = 0 for ii = 1 to 3 P(ii).x = P(ii).x - P_copy(1).x ; P(ii).y = P(ii).y - P_copy(1).y next
      
      





ステップ2-原点の回転

セグメント{P0、P1}が垂直位置(Y軸上にある)になるように座標系を回転します。 セグメントの長さ{P0、P1}を次のように計算します。

L1 = SQRT ( (P(1).x)^2 + (P(1).y)^2 )







座標軸の回転角の正弦と余弦:



   L1 > 0 sin_alf = sin(alfa) = P(1).x / L1 cos_alf = cos(alfa) = P(1).y / L1  L1 = 0 //    sin_alf = 0 cos_alf = 1
      
      





ここでも、ポイントP1、P2、P3の座標を再計算します。



  P(0).x = 0 ; P(0).y = 0 //  P0  ,     P(1).x = 0 ; P(1).y = L1 P(2).x = P(2).x * cos_alf - P(2).y * sin_alf P(2).y = P(2).y * cos_alf + P(2).x * sin_alf P(3).x = P(3).x * cos_alf - P(3).y * sin_alf P(3).y = P(3).y * cos_alf + P(3).x * sin_alf
      
      





ステップ3-セグメントの交点を検索します。



セグメント{P2、P3}の方程式を書き、Y軸との交点CRを見つけます。



P23X = P(2).x + ( P(3).x - P(2).x ) * beta







P23Y = P(2).y + ( P(3).y - P(2).y ) * beta







ここで、0 <= beta <= 1



セグメント{P2、P3}とY軸の交差点CRで:

P(2).x + ( P(3).x - P(2).x ) * beta =0







P(3).x-P(2).xの値に応じて、さらに2つのオプションが可能です。



1つのオプション:



   ( P(2).x - P(3).x ) <> 0 //  {P2,P3}   beta = P(2).x / ( P(2).x - P(3).x )  beta >= 0  beta <= 1 //  {P2,P3}   Y CR.x = 0 CR.y = P(2).y + ( P(3).y - P(2).y ) * beta //  : 0 <= CR.y <= L1
      
      





2オプション:



P(2).x = P(3).xの場合、これはセグメント{P2、P3}が垂直であり、セグメント{P0、P1}に平行であることを意味します。 セグメントの交差は、2番目のセグメント{P2、P3}もY軸上にあり、その端の1つが最初のセグメント{P0、P1}(またはタッチ)にあるか、セグメント{P2、P3}が{P0、P1}を覆う場合にのみ可能 結果のために必要なポイントは1つだけであると仮定します。 これはポイントP0..P3の1つになります。



条件:



  P(2).x = P(3).x = 0 //   {P2,P3}  b    Y.  //  : P(2).y >= 0  P(2).y <= L1 // P2   {P0,P1} -> CR = P_copy(2) //    P2  P(3).y >= 0  P(3).y <= L1 // P3   {P0,P1} -> CR = P_copy(3) //    P3  P(2).y < 0  P(3).y > L1 //  {P0,P1}   {P2,P3}  P(3).y < 0  P(2).y > L1 -> CR = P_copy(0) // //    P0 ( P1) )
      
      





ステップ4



ステップ3のオプション1に従ってCR交点が見つかった場合、その座標は元の座標系に対して再計算されます。 手順1と2で保存された変数を使用します。 回転角-アルファ:



  CR.x = CR.x * cos(-alfa) + CR.y * sin(-alfa) = CR.x * cos_alf + CR.y * sin_alf CR.y = CR.y * cos(-alfa) - CR.x * sin(-alfa) = CR.y * cos_alf - CR.x * sin_alf
      
      





返送:



  CR.x = CR.x + P_copy(0).x CR.y = CR.y + P_copy(0).y
      
      





ステップ3の条件2で CR交点が見つかった場合 、座標の再カウントは必要ありません。 catの下のサンプルgolangコード。 Golang ohmちょっと手を出しただけなので、コードに優しくしてください。 コードはgolang.orgで実行できます。



ゴーランコード


 // line_cross project main.go package main import ( "fmt" "math" ) type point struct { x float64 y float64 } func main() { var P [4]point var P_copy [4]point var L1, sin_alf, cos_alf, wsp1, wsp2, beta float64 var flag_cross bool var CR point //   xy   P[0].x = 1.0 P[0].y = 2.0 P[1].x = 10.0 P[1].y = 20.0 P[2].x = 3.0 P[2].y = 9.0 P[3].x = 9.0 P[3].y = 3.0 //  1 P_copy = P fmt.Println(" :") for ii := 0; ii < 4; ii++ { fmt.Println(" p", ii+1, " x", P_copy[ii].x, " y", P_copy[ii].y) } P[0].x = 0 P[0].y = 0 for ii := 1; ii < 4; ii++ { P[ii].x = P[ii].x - P_copy[0].x P[ii].y = P[ii].y - P_copy[0].y } //  2 L1 = math.Sqrt(P[1].x*P[1].x + P[1].y*P[1].y) if L1 > 0 { sin_alf = P[1].x / L1 cos_alf = P[1].y / L1 } else { sin_alf = 0 cos_alf = 0 } P[1].x = 0 P[1].y = L1 for ii := 2; ii < 4; ii++ { wsp1 = P[ii].x*cos_alf - P[ii].y*sin_alf wsp2 = P[ii].y*cos_alf + P[ii].x*sin_alf P[ii].x = wsp1 P[ii].y = wsp2 } // 3 flag_cross = false if P[2].xP[3].x == 0 { //  {P3,P4)  {P0,P1) if P[2].x == 0 && P[3].x == 0 { switch { case P[2].y >= 0 && P[2].y <= L1: flag_cross = true CR = P_copy[2] case P[3].y >= 0 && P[3].y <= L1: flag_cross = true CR = P_copy[3] case (P[2].y < 0 && P[3].y > L1) || (P[3].y < 0 && P[2].y > L1): flag_cross = true CR = P_copy[0] } } } else { beta = P[2].x / (P[2].x - P[3].x) if beta >= 0 && beta <= 1 { CR.x = 0 CR.y = P[2].y + (P[3].yP[2].y)*beta if CR.y >= 0 && CR.y <= L1 { // 4 //   flag_cross = true wsp1 = CR.x*cos_alf + CR.y*sin_alf wsp2 = CR.y*cos_alf - CR.x*sin_alf CR.x = wsp1 CR.y = wsp2 CR.x = CR.x + P_copy[0].x CR.y = CR.y + P_copy[0].y } } } if flag_cross { fmt.Println(" :  =", CR.x, " y=", CR.y) } else { fmt.Println("   !") } }
      
      






All Articles