CGL_2_D: Distance (続き3)
交わらない場合に進む
まずは場合分け
線分の幅の範囲にあるかその外にあるかどうか
内積を取れば始点から終点の幅にいるかどうかは判定できる
んだけど関数名が思いつかない
class Point:
def in_side_of(self, seg: 'Segment') -> bool:
return seg.vector().dot(
Segment(seg.p1, self).vector()) >= 0
def in_width_of(self, seg: 'Segment') -> bool:
return \
self.in_side_of(seg) and \
self.in_side_of(seg.reverse())
class Segment:
def reverse(self) -> 'Segment':
return Segment(self.p2, self.p1)
おっと2点間の距離がまだなかった
class Point:
def distance(self, other: 'Point') -> float:
return Segment(self, other).vector().abs()
えーとこれで点と線分の距離が出せるようになったかな
名前が苦しい
オーバーロードしたい
class Point:
def distance_to_segment(self, seg: 'Segment') -> float:
if self.in_width_of(seg):
return self.distance(seg.projection(self))
else:
return min(self.distance(seg.p1),
self.distance(seg.p2))
ここまでくれば晴れて線分と線分の間の距離が出るはず
class Segment:
def distance_with_segment(self, other: 'Segment') -> float:
if not self.is_parallel(other) and \
self.intersects(other):
return 0
else:
return min(
self.p1.distance_to_segment(other),
self.p2.distance_to_segment(other),
other.p1.distance_to_segment(self),
other.p2.distance_to_segment(self))
あとは呼ぶだけ
def main() -> None:
n = int(input())
for _ in range(n):
x1, y1, x2, y2, x3, y3, x4, y4 = [int(x) for x in input().split()]
s1 = Segment(Point(x1, y1), Point(x2, y2))
s2 = Segment(Point(x3, y3), Point(x4, y4))
print(s1.distance_with_segment(s2))
if __name__ == "__main__":
main()
AC