【问题标题】:How to efficiently calculate distance in toroidal space?如何有效地计算环形空间中的距离?
【发布时间】:2019-04-01 06:26:51
【问题描述】:

我有大小为 640 x 480 的游戏窗口,它由粒子填充,但是当粒子离开一侧时,它会环绕到另一侧(即它是一个环形)。

我想计算每个粒子之间的距离,因为这将用于对每个粒子施加不同的力。

一开始我循环遍历每一对粒子,然后重新调整所有内容,使对中的第一个粒子居中,然后计算到第二个粒子的距离,但这运行起来非常慢。

然后我在 scipy.spatial.distance 中找到了一些函数,可以让我非常快速地计算所有点之间的距离,但唯一的问题是它没有考虑环绕。

这是我当前的代码

from scipy.spatial.distance import pdist, squareform
...
distance = squareform(pdist([(p.x, p.y) for p in particles]))

这适用于中心附近的粒子,但如果一个粒子在 (1, 320) 而另一个粒子在 (639, 320),那么它会将它们的距离计算为 638 而不是 2。它不需要考虑到包装。

我可以使用不同的功能,或者我可以在之前/之后应用一些转换以考虑换行吗?

【问题讨论】:

  • “当一个粒子离开一侧时,它会缠绕到另一侧”。不要认为你描述的是一个“环形”。那是一个甜甜圈。

标签: python numpy scipy


【解决方案1】:

您可以计算 x 和 y 差异中较小的一个(窗口内差异与边缘交叉距离),如下所示:

game_width = 640
game_height = 480

def smaller_xy(point1, point2):

    xdiff = abs(point1.x - point2.x)
    if xdiff > (game_width / 2):
        xdiff = game_width - xdiff

    ydiff = abs(point1.y - point2.y)
    if ydiff > (game_height / 2):
        ydiff = game_height - ydiff

    return xdiff, ydiff

也就是说,如果 x 或 y 方向上的窗口内距离大于该方向上窗口大小的一半,则最好离开边缘 - 在这种情况下,距离将是窗口该方向的大小减去原来的窗口内距离。

显然,一旦有了 x 和 y 分离,您就可以计算点之间的距离:

import math

small_x, small_y = smaller_xy(p1, p2)
least_distance = math.sqrt(small_x**2 + small_y**2)

但是,根据力计算的定义方式,您可能会发现您真正需要的只是距离的平方(只需 (small_x**2 + small_y**2)),因此您可以避免查找 sqrt 的工作。

要将其连接到scipy.pdist,请注意除了点之外,还可以使用函数参数调用pdist,如下所示:

Y = pdist(X, func)

这是pdisthttps://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.pdist.html#scipy.spatial.distance.pdist的描述中显示的最后一种调用形式

您应该能够使用该功能使pdist 根据应用smaller_xy 计算的回调函数计算的距离来构建其所有点对之间的距离矩阵。

【讨论】:

    【解决方案2】:

    假设您将四块板复制到原始板上、下、左和右,并将原始板上的粒子复制到新板上。让我们也标记粒子。

    表示原始板上的N 粒子o(i)i1N 运行。 a(i) 上面复制板上的粒子。 b(i)l(i)r(i) 分别代表下方、左侧和右侧。

    对于所有不同的ij,您需要找到o(i)o(j)o(i)a(j) 之间的距离,等等。有5x5 = 25 个距离来计算每个一对ij。获得所有这些距离后,为每对取最小值,这就是 ij 的距离。

    我在想可能有办法修剪计算。但我的想法是,您至少需要计算粒子与边界之间的距离,并将其与原始板上的距离进行比较。这也是开销。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-12-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-09
      • 2016-08-17
      相关资源
      最近更新 更多