2線分の交点

線分AB、CDがあったときに、その交点を求めるには?
要素は2次元空間内に存在するものとします。

解説

線分AB上の任意の点Pは、媒介変数 r を用いて、以下のように表現できます。

P = A + r ( B - A ) ( r は[0~1]の値を取る) ・・・式①

同様に、CD上の任意の点Qも、媒介変数 s を用いて、以下のように表現できます。

Q = C + s ( D - C ) ( s は[0~1]の値を取る) ・・・式②

PとQが同一点になる場合の r と s を求めれば、ABとCDの交点は求まったことになります。

というわけで、P = Q を解きます。

  P = Q
⇔ A + r ( B - A ) = C + s ( D - C )

X、Yに関する連立方程式にします。

⇔ Ax + r ( Bx - Ax ) = Cx + s ( Dx - Cx )
  Ay + r ( By - Ay ) = Cy + s ( Dy - Cy )

これを解きますと、
r = { (Dy - Cy)(Cx - Ax) - (Dx - Cx)(Cy - Ay) }
 / { (Bx - Ax)(Dy - Cy) - (By - Ay)(Dx - Cx) } ・・・式③
s = { (By - Ay)(Cx - Ax) - (Bx - Ax)(Cy - Ay) }
 / { (Bx - Ax)(Dy - Cy) - (By - Ay)(Dx - Cx) } ・・・式④

演算回数を減らすために、一時変数を用います。

ACx = Cx - Ax
ACy = Cy - Ay
BUNBO = (Bx - Ax)(Dy - Cy) - (By - Ay)(Dx - Cx )

として、

r = { (Dy - Cy)ACx - (Dx - Cx)ACy } / BUNBO ・・・式⑤
s = { (By - Ay)ACx - (Bx - Ax)ACy } / BUNBO ・・・式⑥

・平行チェック

r、s を求めようとしたときに、r、s が求まらない場合があります。すなわち、BUNBOがゼロの場合です。このとき、2線分は平行であり、交差しません。

・重なりチェック

BUNBOがゼロで、さらに、式⑤、⑥の分子もゼロの場合には、2線分は重なりあっています。

・線分交差チェック

式①、②より、r、s が共に 0~1 の間の値として求まらなければ、2線分は交差していないとなります。
r、s 個別に言うと、

r < 0 :点Pは、点Aより手前

r > 1 :点Pは、点Bより奥

s < 0 :点Qは、点Cより手前

s > 1 :点Qは、点Dより奥

となります。

考察

r、s の数値が0、1に非常に近い数値の場合には、演算誤差によって、
交差していないのに交差していると判定される場合や、
交差しているのに交差していないと判定される場合
がないとは言えません。
このような場合に配慮して、実用においては、交点計算に加えて、
・点と直線の距離計算を用いて、線分の端点がもう一方の線分上にあるかの判定を行う
もしくは、
・点と直線の半空間テストを用いて、線分の2端点がもう一方の線分をまたいでいるかかの判定を行う
必要があります。

ダウンロード

サンプルプロジェクト

参考

Graphics Gems Ⅲ:Faster Line Segment Intersection