用Python检查一个点是否存在于圆扇形中。

3

我知道这个问题在网上和这里已经被问过了,但不幸的是并非针对Python环境。在网上搜索时,我找到了这个(链接),从那里开始进行工作。由于我正在使用Pyglet,我将该函数编写为一个线程。但首先,我会向您展示我的想法和目标:

enter image description here

P = 精灵玩家的位置

M = 鼠标的位置

C = 一个想象中的圆,它的半径是P和M之间的距离

0、1、2、3、4、5、6、7 = 精灵可以朝向的方向

a = 一个方向与另一个方向之间的角度 = 45°

S = 对应于精灵方向的圆形部分。简单地说,如果M在S中出现,则方向等于1。

start、end = 起始角度和结束角度

因此,在函数中,我插入了一个while循环。稍后,我必须计算半径何时为:

while mpc_thread:
    radius = math.hypot(mpx - cpx, mpy - cpy) + 20

mpx,mpy = 鼠标位置(X,Y)

cpx,cpy = 精灵玩家位置(X,Y)

我使用了math.hypot,感谢这个(Link)。我添加了20,以便半径略微超过鼠标的位置。

然后,我添加了一个for循环来检查每个方向的圆形部分:

while mpc_thread:
    radius = math.hypot(mpx - cpx, mpy - cpy) + 20
    for ang_obj in range(0, fchar):
        reference_angle = 360 // fchar * ang_obj
        s_angle = reference_angle - (360 / (fchar / 2))
        e_angle = reference_angle + (360 / (fchar / 2))

fchar = 精灵方向的数量,在这种情况下为8

为了找出每个方向的起始和结束角度,我将弧度角除以两倍的方向数。然后从参考角度中减去/加上结果。

从这里开始出现了问题。按照我发布第一个链接的方式编写,if函数没有检测到任何内容,如果我进入负数,则会出现错误。然后我寻找解决方法,并在用户7048690的答案中找到了这个(Link)。修改了函数之后,我遇到了一个新问题(数学域错误)。所以我用cmath.sqrt替换了math.sqrt,它就可以工作了。但是又出现了一个新问题。也就是说,始终遵循那个答案,if函数会将FPS大幅降低到0/1。现在我不知道该往哪里去。你能帮我解决这个问题吗?我希望我理解了我的问题。

1个回答

3
最简单的找到最佳方向的方法是计算从玩家位置到鼠标位置的线与从玩家位置到8个点的线之间夹角的余弦值。
必须找到具有与“鼠标”方向夹角最小的方向向量。 0度的余弦值为1,180°的余弦值为-1。因此,具有最大余弦值的方向就是需要找到的方向。

计算余弦值最简单的方法是点积

一般来说,2个向量的点积等于两个向量长度乘以它们夹角的余弦值。

dot( A, B ) == | A | * | B | * cos( angle_A_B ) 

这意味着,两个单位向量的点积等于它们之间夹角的余弦值,因为单位向量的长度为1。
uA = normalize( A )
uB = normalize( B )
cos( angle_A_B ) == dot( uA, uB )

2维向量A和B的点乘可以通过2次乘法和1次加法计算:

dotAB = Ax * Bx + Ay * By  

设置一个包含8个标准方向的列表:

dir = [(0, 1), (0.707, 0.707), (1, 0), (0.707, -0.707),
       (0, -1), (-0.707, -0.707), (-1, 0), (-0.707, 0.707)]

找到“最佳”方向,即与角度最接近或余弦值最大的方向:

dx, dy = mpx - cpx, mpy - cpy
max_i = max([i for i in range(len(dir))], key = lambda i: dx*dir[i][0] + dy*dir[i][1])

最终,max_i 包含了搜索方向。

请注意,该算法不计算和比较角度的余弦值,而是比较余弦值和半径的乘积。 dx*dir[i][0] + dy*dir[i][1] 等于 radius * cos(alpha)

最终搜索到的点为:

radius = math.hypot(mdir_x, mdir_y) + 20
X = (dir[max_i][0] * radius, dir[max_i][1] * radius)


我不太确定如何解释它,因为英语并不是我的母语。在这种情况下,我有8张关于玩家的图像与图像中8个方向相对应。 - BlackFenix06
事实上,我并没有说你错了,事实上我也感谢你的帮助 =D 当我写第二个答案时,只是想问一下我是否已经解释清楚我所寻找的东西。我很抱歉,也许我造成了更多的困惑。 - BlackFenix06
啊,好的,现在我明白了。再次非常感谢你的帮助 =D - BlackFenix06
现在不需要了。这与你问题中的代码 radius = math.hypot(mpx - cpx, mpy - cpy) + 20 有关。我最初认为你想计算一个特定距离的点。 - Rabbid76
啊,好的,所以这只是一个例子,如果我理解正确的话。我用我的替换它然后结束,对吗? - BlackFenix06
显示剩余8条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接