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

Check whether a point exists in circle sector or not with Python

我知道在网上和这里已经有人问过这个问题,但不幸的是 Python 环境中没有。在网上查找时,我发现了这个 (Link) 并从那里开始研究它。因为我使用的是 Pyglet,所以我将函数编写为线程。但首先,我向您展示我的想法和想要完成的事情:

P = Sprite 玩家位置

M = 鼠标位置

C = 一个假想的圆,其半径为 P 和 M 之间的距离。

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

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

S = 精灵方向对应的圆截面。简单来说,如果S中存在M,则方向等于1

start, end = 开始角度和结束角度

因此,在函数中,我插入了一个 while 循环。后来不得不计算当半径为:

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

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

cpx, cpy = Sprite Player Position (X, Y)

多亏了这个(Link),我用了math.hypot。我加了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

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

问题从这里开始。以我发布第一个 link 的方式编写,if 函数没有检测到任何东西,如果我进入否定 (,我得到一个错误。然后我搜索了一个解决方案并找到了这个 (Link ) 来自user7048690的回答,修改了函数,又遇到了新问题(数学域错误),所以我把math.sqrt改成cmath.sqrt,成功了,但是又出现了新问题,就是,始终遵循该答案,if 函数将 FPS 大幅降低到 0/1。现在我不知道该去哪里。你能帮我解决这个问题吗?我应该如何正确构建函数并正常工作?希望我理解我的问题是什么意思。

找到最佳方向的最简单方法是计算从玩家位置到鼠标位置的直线与从玩家位置到 8 个点的直线之间夹角的余弦值。
必须找到与 "mouse" 方向成最小角度的方向矢量。 0度的余弦为1,180°的余弦为-1。所以余弦最大的方向就是要找的方向

计算余弦的最简单方法是 dot product

一般来说,2个向量的乘积等于2个向量夹角的余弦乘以大小(长度) 的两个向量。

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

因此,2 个单位向量的 乘积等于 2 个向量之间夹角的 余弦 ,因为单位向量的长度为 1.

uA = normalize( A )
uB = normalize( B )
cos( angle_A_B ) == dot( uA, uB )

二维向量A和B的dot product可以通过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)]

求"best"方向,即角度最近或角度余弦最大的方向:

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)