Ruby/SDLで計算幾何(3) 線分交差判定のディテール

intersectの謎の分析をしようと思いましたが、ccwの分析ができてればそう悩むこともなくてですね。
再掲。

module GeoUtil
  module_function
  
 # 線分p0p1を基準にして、線分p0p2が
 #  反時計回りの向きにあれば+1 
 #    時計回りの向きにあれば-1
  def ccw(p0, p1, p2)
    dx1 = p1.x - p0.x; dy1 = p1.y - p0.y
    dx2 = p2.x - p0.x; dy2 = p2.y - p0.y
    return +1 if dx1*dy2 > dy1*dx2
    return -1 if dx1*dy2 < dy1*dx2
    return -1 if (dx1*dx2 < 0) || (dy1*dy2 < 0)  #(1)
    return +1 if dx1*dx1+dy1*dy1 < dx2*dx2+dy2*dy2 #(2)
    return 0                                       #(3)
  end
  
 # 2線分が交差しているかを判定する
  def intersect(l1, l2)
    return ((ccw(l1.p1, l1.p2, l2.p1) * ccw(l1.p1, l1.p2, l2.p2)) <= 0 ) &&
           ((ccw(l2.p1, l2.p2, l1.p1) * ccw(l2.p1, l2.p2, l1.p2)) <= 0 )
  end
end

「一方の線分から見て、他方の線分の両端が左右に分かれている」&&「他方から見ても同様」なら、交差しているとみなすのがintersectメソッド。

そして、他方の端点が一方の線分上にある場合は、これは交差しているとみなされます。

線分が同一直線上にある場合、端点位置のパターンとしては上図の3つしかないのですが、その場合の交差・非交差の状況は上の通り。
うん、直感には反してないと思います。

ただ、「一方の線分の端点が同一(線分が一点)の場合」は、個人的には直感に反する結果が出てきます。

class GeoBaseTest < GeoBase
  def start
    puts GeoUtil.intersect(l(30,30,30,30), l(20,20,40,40))
  end
  
  def self.start
    geo = self.new
    geo.start
  end
end

GeoBaseTest.start  #=> false

仕方ないのですがね。ccwにおいてp0==p1なら、p2がp0以外の任意の点にあればccwの値は+1ですから。