环形包裹(x和y包裹)地图上点之间的最短距离?

时间:2010-06-14 22:22:25

标签: algorithm language-agnostic math geometry distance

我有一个环形欧几里德地图。也就是说,表面是一个平坦的欧几里德矩形,但是当一个点移动到右边界时,它将出现在左边界(在相同的y值处),由x_new = x_old%width

给出

基本上,基于以下方式绘制点:* 参见编辑

(x_new, y_new) = ( x_old % width, y_old % height)

Think Pac Man - 走出屏幕的一边会让你出现在对面的边缘。

计算两点之间最短距离的最佳方法是什么?典型的实施方案表明,地图对角处的点距离较远,实际上,实际包裹的距离非常接近。

我能想到的最好方法是计算经典Delta X和Wrapped Delta X,以及经典Delta Y和Wrapped Delta Y,并使用Sqrt(x ^ 2 + y ^ 2)距离公式中每对的较低值

但这会涉及许多检查,计算和操作 - 我认为可能没有必要。

有更好的方法吗?


修改

当一个物体移动时,它移动到位置(x_old,y_old),通过上面的公式运行它,并存储(x_new,y_new)作为它的位置。仅添加上述公式以阐明当物体越过边界时会发生什么;实际上,每次只有一个(x,y)对存储在每个对象中。

7 个答案:

答案 0 :(得分:11)

  

我能想到的最好方法是计算经典Delta X和Wrapped Delta X,以及经典Delta Y和Wrapped Delta Y,并使用Sqrt(x ^ 2 + y ^ 2)距离公式中每对的较低值

就是这样,我认为没有更快的方法。但是计算并不难;你可以做点什么

dx = abs(x1 - x2);
if (dx > width/2)
  dx = width - dx;
// again with x -> y and width -> height

(我相信你可以将其翻译成您的首选语言)

答案 1 :(得分:4)

周期性域中两点之间的最短距离可以如下计算,而不使用任何循环。

    dx = x2-x1
    dx = dx - x_width*ANINT(dx/x_width)

这将给出签名的最短距离。 ANINT是一个内在的FORTRAN函数,使得ANINT(x)给出最接近的整数,其幅度小于abs(x)+0.5,其符号与x相同。例如,ANINT(0.51)= 1.0,ANINT(-0.51)= - 1.0等。其他语言也存在类似的函数。

答案 2 :(得分:3)

要找到值aa1的新坐标的a2 - 轴中的最小增量,其中aBoundarya的边界轴:

def delta(a1, a2, aBoundary):
  return min(abs(a2 - a1), abs(a2 + aBoundary - a1))

因此,如果您有两个新坐标x1,y1x2,y2的积分,您可以这样做:

sumOfSquares(delta(x1,x2,width), delta(y1,y2,height))

这实际上是你的建议,但我不会说这是“许多检查,计算和操作”。

答案 3 :(得分:0)

(delta_x, delta_y)= 
     (min(width - abs(x_new - x_new), abs(x_new - x_old)), 
      min(height - abs(y_new - y_old), abs(y_new - y_old)))

答案 4 :(得分:0)

距离不能大于宽度/ 2和高度/ 2。如果得到的差值(X1-X2)大于宽度/ 2,则减去宽度/ 2以获得快捷距离。然后像往常一样计算距离。

答案 5 :(得分:0)

男人我做了不同的事情......

这里有一点额外的功能,但核心是包裹屏幕上的距离......

longname

答案 6 :(得分:-1)

你不能在mod操作符中使用“abs”函数!

xd =(x1-x2+Width)%Width
yd=(y1-y2+Height)%Height
D=sqrt(xd^2+yd^2)