いろんなあたり判定できた

ネットを漁ってとりあえずRubyで実装。
基本アルゴリズムとしてはこれでOKだろう。

require "dxruby"

Vector = Struct.new(:x, :y)
Point = Struct.new(:x, :y)

# 線分と直線 <0 交差する, =0 上, >0 交差しない
def intersect(p1, p2, p3, p4)
  return ((p1.x - p2.x) * (p3.y - p1.y) + (p1.y - p2.y) * (p1.x - p3.x)) *
         ((p1.x - p2.x) * (p4.y - p1.y) + (p1.y - p2.y) * (p1.x - p4.x))
end

# へこんでない右回りの四角と点
def checkbox(p, p1, p2, p3, p4)
    c = Point.new
    c.x = (p1.x + p2.x + p3.x + p4.x) / 4 # 中心点x
    c.y = (p1.y + p2.y + p3.y + p4.y) / 4 # 中心点y
    return false if intersect(p1, p2, p, c) < 0 or
                    intersect(p2, p3, p, c) < 0 or
                    intersect(p3, p4, p, c) < 0 or
                    intersect(p4, p1, p, c) < 0
    return true
end

# 線分同士
def checkline(a1, a2, b1, b2)
  s1 = (a1.y - a2.y) * (b1.x - a1.x) - (a1.x - a2.x) * (b1.y - a1.y)
  s2 = (a1.y - a2.y) * (b2.x - a1.x) - (a1.x - a2.x) * (b2.y - a1.y)
  s3 = (b1.y - b2.y) * (a1.x - b1.x) - (b1.x - b2.x) * (a1.y - b1.y)
  s4 = (b1.y - b2.y) * (a2.x - b1.x) - (b1.x - b2.x) * (a2.y - b1.y)
  return (s1 * s2 <= 0 and s3 * s4 <= 0)
end

# 内積
def dotProduct(vec1, vec2)
  vec1.x * vec2.x + vec1.y * vec2.y
end

# 距離
def distance(pt1, pt2)
   Math.sqrt((pt1.x - pt2.x)**2 + (pt1.y - pt2.y) **2)
end

# 円と線分の判定
def checkCrclCls(ptc, cr, pt1, pt2)
  # vは線分始点から終点
  # cは線分始点から円中心
  v = Vector.new(pt2.x - pt1.x, pt2.y - pt1.y)
  c = Vector.new(ptc.x - pt1.x, ptc.y - pt1.y)

  # 二つのベクトルの内積を求める
  n1 = dotProduct(v, c)

  if n1 < 0 then
    # cの長さが円の半径より小さい場合は交差している
    return distance(pt1, ptc) < cr ? true : false
  end

  n2 = dotProduct( v, v )

  if n1 > n2 then
    # 線分の終点と円の中心の距離の二乗を求める
    len = distance(pt2, ptc)**2

    # 円の半径の二乗よりも小さい場合は交差している
    return  len < cr * cr ? true : false
  else
    n3 = dotProduct( c, c )
    return ( n3-(n1/n2.to_f)*n1 < cr * cr ) ? true : false
  end
end

image = Image.new(640, 480)
cimage = Image.new(101,101).circle(50,50,50,[255,255,255,255])
cimage2 = Image.new(101,101).circle(50,50,50,[255,0,255,255])

pt1 = nil
pt2 = nil
pt3 = Point.new(400,300)
pt4 = Point.new(500,400)

bp1 = Point.new(400,100)
bp2 = Point.new(450,150)
bp3 = Point.new(400,200)
bp4 = Point.new(350,150)

Window.loop do
  image.box(0, 0, 639, 479, [255,0,0,0])  # 背景
  image.line(pt3.x, pt3.y, pt4.x, pt4.y, [255,255,255,255])  # せん
  image.line(bp1.x, bp1.y, bp2.x, bp2.y, [255,255,255,255])  # しかく1
  image.line(bp2.x, bp2.y, bp3.x, bp3.y, [255,255,255,255])  # しかく2
  image.line(bp3.x, bp3.y, bp4.x, bp4.y, [255,255,255,255])  # しかく3
  image.line(bp4.x, bp4.y, bp1.x, bp1.y, [255,255,255,255])  # しかく4
  Window.draw(100,100,cimage, 1)  # まる

  pt2 = Point.new(Input.mousePosX, Input.mousePosY)

  # マウスが押されたらラインの始点を設定
  if Input.mousePush?(M_LBUTTON) then
    pt1 = pt2
  end

  # マウスが押されていたら当たり判定
  if Input.mouseDown?(M_LBUTTON) then
    image.line(pt1.x, pt1.y, pt2.x, pt2.y, [255,255,255,255])

    if pt1.x != pt2.x or pt1.y != pt2.y then
      # まると
      if checkCrclCls(Point.new(150, 150), 50, pt1, pt2) then
        Window.draw(100, 100, cimage2, 1)
      end

      # せんと
      if checkline(pt1, pt2, pt3, pt4) then
        image.line(pt3.x, pt3.y, pt4.x, pt4.y, [255,0,255,255])
      end

      # しかくと
      if checkbox(pt1, bp1, bp2, bp3, bp4) or
        checkline(pt1, pt2, bp1, bp2) or
        checkline(pt1, pt2, bp2, bp3) or
        checkline(pt1, pt2, bp3, bp4) or
        checkline(pt1, pt2, bp4, bp1) then
        image.line(bp1.x, bp1.y, bp2.x, bp2.y, [255,0,255,255])  # しかく1
        image.line(bp2.x, bp2.y, bp3.x, bp3.y, [255,0,255,255])  # しかく2
        image.line(bp3.x, bp3.y, bp4.x, bp4.y, [255,0,255,255])  # しかく3
        image.line(bp4.x, bp4.y, bp1.x, bp1.y, [255,0,255,255])  # しかく4
      end
    end
  end
  break if Input.keyPush?(K_ESCAPE)
  Window.draw(0,0,image)
end

なぜか丸だけイメージなのは、丸を描くのが遅いという話ではなく、はじめに画像を作ったけど線分と四角が面倒になったからというだけで、特に意味は無い。