§Algorithm§


☆直接的な線分交差判定☆

 与えられた2線分の交差判定を行います。線分の交差なんて「見ればわかるのに・・・」と いう感じですが、コンピューターはそういうわけにはいかないので、 計算によって交差判定を行う必要があります。ここでは、直接的な方法とその 欠点について、ふれています。

 『線分の交差判定』とは、

「交点を求め、その交点が2つの線分の範囲にあるかを調べる」

という考え方です。
簡単なように見えますが、特殊な線分、例えば、y=aとの交差判定を行う場合等の 例外処理も行う必要があるので、それほど単純というわけではありません。 コードでは次のようにまとめられます。

'構造体
Private Type POINTAPI
    x As Long
    y As Long
End Type

'座標 p1,p2 を結ぶ線分と座標 p3,p4 を結ぶ線分が交差しているかを調べる
'ただし、線分が重なっている場合(4点が一直線上にある)、「交差していない」、と判定します。
Private Function IntersectionStandard(p1 As POINTAPI, p2 As POINTAPI, _
                        p3 As POINTAPI, p4 As POINTAPI) As Boolean
    'それぞれの点と点の差
    Dim dx1 As Long, dx2 As Long, dy1 As Long, dy2 As Long
    '交点
    Dim xx As Long, yy As Long
    
    dx1 = p1.x - p2.x: dy1 = p1.y - p2.y
    dx2 = p3.x - p4.x: dy2 = p3.y - p4.y
    
    'どちらもy軸に平行な線分ではない
    If (dx1 <> 0& And dx2 <> 0&) Then
        '平行な2線分ではない
        If ((dy1 / dx1 - dy2 / dx2) <> 0&) Then
            '交点を求める
            xx = (p3.y - p1.y - p3.x * dy2 / dx2 + p1.x * dy1 / dx1) / _
                 (dy1 / dx1 - dy2 / dx2)
            'その交点が線分の範囲にあるか
            If (((xx <= p1.x And xx >= p2.x) Or (xx >= p1.x And xx <= p2.x)) And _
                ((xx <= p3.x And xx >= p4.x) Or (xx >= p3.x And xx <= p4.x))) Then
                IntersectionStandard = True: Exit Function
            End If
        End If
    'p1,p2 を結ぶ線分がy軸に平行である
    ElseIf (dx1 = 0& And dx2 <> 0&) Then
        '交点を求める
        yy = p1.x * dy2 / dx2 + p3.y - p3.x * dy2 / dx2
        'その交点が線分の範囲にあるか
        If (((yy <= p1.y And yy >= p2.y) Or (yy >= p1.y And yy <= p2.y)) And _
            ((p1.x <= p3.x And p1.x >= p4.x) Or (p1.x >= p3.x And p1.x <= p4.x))) Then
            IntersectionStandard = True: Exit Function
        End If
    'p3,p4 を結ぶ線分がy軸に平行である
    ElseIf (dx1 <> 0& And dx2 = 0&) Then
        yy = p3.x * dy1 / dx1 + p1.y - p1.x * dy1 / dx1
        If (((yy <= p3.y And yy >= p4.y) Or (yy >= p3.y And yy <= p4.y)) And _
            ((p3.x <= p1.x And p3.x >= p2.x) Or (p3.x >= p1.x And p3.x <= p2.x))) Then
            IntersectionStandard = True: Exit Function
        End If
    End If
    'それ以外は交差しない
    IntersectionStandard = False: Exit Function
End Function

 上記の判定方法の問題点は次の点です。

1.
 0除算を行う可能性はないですが、dx1=0に限りなく近い値,あるいは、 dx2=0に限りなく近い値の場合、除算によるオーバーフローが起きる可能性があります。 もっとも、上のようなLong型の整数計算のみであれば、この心配はないのですが、 もし、これを浮動小数点を含んだ計算で行うときは、注意が必要です。 (通常、Windowsの描画で行うのであれば、意識しなくても良い)

2.
 多くの処理系で、除算による計算は乗算よりも負担がかかります。 高速処理を行いたいのであれば、1のオーバーフロー対策とあわせて、 できることなら除算の計算を少なくする必要があります。

この2つの問題点を解消し、かつシンプルなコードで判定する 線分交差判定の定石といわれる方法があります。 もっと簡単に−線分交差判定−をご覧下さい。


(サンプルプログラムの動作確認)

機種 PC-9821V13S
OS Windows95
開発ツール Visual Basic Ver.4.0
更新日 00/07/22

ダウンロード DirCross.lzh(3.00KB)

Visual Basic Ver.5.0,Ver.6.0でも問題なく動作すると思います。
なお、このコーナーに掲載されているプログラムコード、およびプログラムファ イルが原因で起きた損害などに関して一切の責任を負うことはできません。

★この線分交差は色々な処理で使用できると思います。 本ソース文書の配布・転載は禁止ですが、掲載されているプログラムコード、 およびプログラムファイルについては、各自の責任においてご自由に配布して もらって構いません。その時、本サイトを紹介していただけると非常にうれしいです。


Algorithmインデックス トップ


Copyright(C)2000 Tomoya. All rights reserved.