ddo*_*nik 4 algorithm math geometry trigonometry vector
我在二维坐标系中有一个轴对齐的矩形,由左下角的点和右上角的点以及可能位于矩形内部或外部的点表示。我想找到该点到矩形最近点的距离,无论它是否在矩形内部。当然,我可以只编写一个具有 9 个不同结果的 switch case,但我希望有一个更优雅的解决方案。
另外,我已经找到了解决此问题的多种解决方案(例如这个),但如果该点位于框内,则所有这些解决方案都会将距离计算为 0,这是我不希望的。
我的回答比其他人稍长一些,但来自不同的角度。
关键不在于您是否在矩形内部,而在于您是否位于通过获取矩形边并将其无限延伸而定义的走廊内的任何位置(想象一个无限加号,以矩形为中心)。
如果它位于这些走廊内,则最近的距离与其中一侧正交。
如果在室外,则最近距离是到最近角点的距离。
您的代码可能如下所示:
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)
Run Code Online (Sandbox Code Playgroud)
如果您想尝试保存开方,您可以检查您是在走廊内还是在走廊外。在这种情况下,您可以按如下方式重新排列:
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
Run Code Online (Sandbox Code Playgroud)