x = __import__( 'sol_import' ).do( 'e1_geometry' ) from typing import TYPE_CHECKING, Union from math import isclose from math import sqrt,acos if not TYPE_CHECKING: Point = x.Point Vector = x.Vector Line = x.Line Segment = x.Segment Circle = x.Circle def distance_point_point( a: Point, b: Point ) -> float: p = a - b return Vector( p.x, p.y ).length() def distance_point_line( a: Point, l: Line ) -> float: p1 = l.get_point() p2 = p1.translated( l.get_direction() ) x1, y1, x2, y2 = p1.x, p1.y, p2.x, p2.y return ( abs( ( y2 - y1 ) * a.x - ( x2 - x1 ) * a.y + ( x2 * y1 ) - ( y2 * x1 ) ) / sqrt( ( y2 - y1 ) * ( y2 - y1 ) + ( x2 - x1 ) * ( x2 - x1 ) ) ) def distance_line_line( p: Line, q: Line ) -> float: p1 = p.get_point() return distance_point_line( p1, q ) def distance_point_circle( a: Point, c: Circle ) -> float: return abs( distance_point_point( a, c.center() ) - c.radius() ) def distance_line_circle( l: Line, c: Circle ) -> float: dist = distance_point_line( c.center(), l ) - c.radius() return 0 if dist <= 0 else dist def distance( a: Union[ Point, Line, Circle ], b: Union[ Point, Line, Circle ] ) -> float: if type( a ) == Point and type( b ) == Point: return distance_point_point( a, b ) if type( a ) == Point and type( b ) == Line: return distance_point_line( a, b ) if type( a ) == Line and type( b ) == Point: return distance_point_line( b, a ) if type( a ) == Line and type( b ) == Line: return distance_line_line( a, b ) if type( a ) == Point and type( b ) == Circle: return distance_point_circle( a, b ) if type( a ) == Circle and type( b ) == Point: return distance_point_circle( b, a ) if type( a ) == Line and type( b ) == Circle: return distance_line_circle( a, b ) if type( a ) == Circle and type( b ) == Line: return distance_line_circle( b, a ) assert False