Мой ответ немного длиннее других, но он исходит из другой точки зрения.
Ключ не в том, если вы находитесь внутри прямоугольника , но если выв любом месте в пределах коридоров, определяемых путем взятия сторон прямоугольника и их бесконечного вытягивания (изобразите бесконечный знак плюс, центрированный в прямоугольнике).
Если он находится внутри этих коридоров, то ближайшее расстояние ортогонально одному изстороны.
Если он снаружи, то самое близкое расстояние - это расстояние до ближайшего угла.
Ваш код может выглядеть так:
nearest_distance(rectangle, point):
d_top = abs(rectangle.top - point.y)
d_bottom = abs(rectangle.bottom - point.y)
corner_y = d_top < d_bottom ? rectangle.top : rectangle.bottom
d_left = abs(rectangle.left - point.x)
d_right = abs(rectangle.right - point.x)
corner_x = d_left < d_right ? rectangle.left : rectangle.right
d_cx = corner_x - point.x
d_cy = corner_y - point.y
d_corner = sqrt(d_cx*d_cx + d_cy*d_cy)
return min(d_top, d_bottom, d_left, d_right, d_corner)
Если вы хотитечтобы попытаться сохранить sqrt, вы можете проверить, находитесь ли вы в коридорах или за их пределами.В этом случае вы бы изменили его следующим образом:
nearest_distance(rectangle, point):
d_top = abs(rectangle.top - point.y)
d_bottom = abs(rectangle.bottom - point.y)
d_left = abs(rectangle.left - point.x)
d_right = abs(rectangle.right - point.x)
r = rectangle # just to make the next line neater
if r.left <= point.x <= r.right or r.bottom <= point.y <= r.top:
return min(d_top, d_bottom, d_left, d_right)
else:
corner_y = d_top < d_bottom ? rectangle.top : rectangle.bottom
corner_x = d_left < d_right ? rectangle.left : rectangle.right
d_cx = corner_x - point.x
d_cy = corner_y - point.y
d_corner = sqrt(d_cx*d_cx + d_cy*d_cy)
return d_corner