在我用 Pygame 编写的游戏中,我有一个 2D 点 (x,y)
在一个从 (0,0)
到 (1,1)
(带边的完美正方形)的框中长度 1)。
我想计算从点到框边界在 alpha
方向上的欧几里德距离,其中 alpha
是一个以逆时针弧度为单位的方位角方向,从 alpha=0
开始作为 x -轴方向。
我写了一个 python 代码来计算这个距离,但我不确定这是最有效/最干净的方法:
import numpy as np
def get_distance_to_boundary(x, y, angle):
cos_angle, sin_angle = np.cos(angle), np.sin(angle)
if cos_angle == 0:
return y if sin_angle < 0 else 1 - y
if sin_angle == 0:
return x if cos_angle < 0 else 1 - x
x_target = 1 if cos_angle > 0 else 0
y_target = y + (x_target - x) * np.tan(angle)
if y_target > 1:
return np.fabs((1 - y) / sin_angle)
if y_target < 0:
return np.fabs(y / sin_angle)
return np.sqrt((x_target - x) ** 2 + (y_target - y) ** 2)
有更好的方法吗?
插图:
答案 0 :(得分:1)
这种方法更高效/更简洁,因为您不需要 tan
、fabs
、sqrt
或 **2
:
def distance(x,y,angle):
cos_angle, sin_angle = np.cos(angle), np.sin(angle)
if cos_angle == 0:
return y if sin_angle < 0 else 1 - y
if sin_angle == 0:
return x if cos_angle < 0 else 1 - x
distance_EW = (1-x)/cos_angle if cos_angle>0 else -x/cos_angle
distance_NS = (1-y)/sin_angle if sin_angle>0 else -y/sin_angle
return min(distance_EW, distance_NS)
我将 distance_EW
定义为目标在东墙(如果 cos_angle>0)或在西墙(如果 cos_angle<0)的情况下的距离。同样,为北墙或南墙定义 distance_NS
。
...
警告:由于舍入误差,我的距离函数有时会产生与您的函数不同的结果!!当您的起点位于框的边界并且 angle
接近 π/2 的倍数时,这尤其成问题。
我建议您设置某种容差,例如 if abs(sin_angle) < 1e-12:
,而不是 if sin_angle == 0:
。这样,sin_angle = np.sin(np.pi)
将在 if
条件中被接受,即使它不完全等于 0(因为 np.sin(np.pi)
是 1.2e-16
与 python)。