曼哈顿六角形网格中瓷砖之间的距离

时间:2011-02-22 22:30:23

标签: algorithm path distance hexagonal-tiles

对于正方形网格,图块A和B之间的欧氏距离为:

distance = sqrt(sqr(x1-x2)) + sqr(y1-y2))

对于一个被限制沿着正方形网格移动的演员,曼哈顿距离可以更好地衡量我们必须行驶的实际距离:

manhattanDistance = abs(x1-x2) + abs(y1-y2))

如何在六边形网格中获得两块瓷砖之间的曼哈顿距离,如下面的红线和蓝线所示?

enter image description here

6 个答案:

答案 0 :(得分:41)

我曾经在游戏中设置了一个六边形坐标系,以便 y -axis与 x -axis成60度角。这避免了奇数偶数行的区别。

Hexagonal grid http://althenia.net/svn/stackoverflow/hexgrid.png?usemime=1&rev=3

此坐标系中的距离为:

dx = x1 - x0
dy = y1 - y0

if sign(dx) == sign(dy)
    abs(dx + dy)
else
    max(abs(dx), abs(dy))

您可以将( x ', y )从坐标系转换为( x y )在这一个使用:

x = x' - floor(y/2)

所以dx变为:

dx = x1' - x0' - floor(y1/2) + floor(y0/2)

使用整数除法实现此操作时要小心舍入。在C中,int y floor(y/2)(y%2 ? y-1 : y)/2

答案 1 :(得分:1)

我假设您希望在图中显示的两个图块的中心之间的平面中的欧几里德距离。我认为这可以从图中得出。对于任何x和y,从瓦片中心(x,y)到瓦片中心(x + dx,y)的矢量是(dx,0)。来自瓦片(x,y)和(x,y + dy)中心的矢量是(-dy / 2,dy * sqrt(3)/ 2)。对于任何x,y,dx,简单向量加法给出(x,y)和(x + dx,y + dy)之间的(dx - (dy / 2),dy * sqrt(3)/ 2)向量,和dy。总距离是向量的范数:sqrt((dx - (dy / 2))^ 2 + 3 * dy * dy / 4)

答案 2 :(得分:1)

如果你想要直线距离:

double dy = y2 - y1;
double dx = x2 - x1;
// if the height is odd
if ((int)dy & 1){
    // whether the upper x coord is displaced left or right
    // depends on whether the y1 coordinate is odd
    dx += ((y1 & 1) ? -0.5 : 0.5);
}
double dis = sqrt(dx*dx + dy*dy);

我想说的是,如果dy是偶数,它只是一个矩形空间。如果dy为奇数,则右上角的位置为左侧或右侧的1/2单位。

答案 3 :(得分:1)

这个问题的直接答案是不可能的。这个问题的答案与你如何在内存中组织瓷砖有很大关系。我使用odd-q垂直布局,并使用以下matlab代码给我正确的答案。

function f = offset_distance(x1,y1,x2,y2)
    ac = offset_to_cube(x1,y1);
    bc = offset_to_cube(x2,y2);
    f = cube_distance(ac, bc);
end

function f = offset_to_cube(row,col)
    %x = col - (row - (row&1)) / 2;
    x = col - (row - mod(row,2)) / 2;
    z = row;
    y = -x-z;
    f = [x,z,y];
end

function f= cube_distance(p1,p2)
    a = abs( p1(1,1) - p2(1,1));
    b = abs( p1(1,2) - p2(1,2));
    c = abs( p1(1,3) - p2(1,3));
    f =  max([a,b,c]);
end

这是一个matlab测试代码

sx = 6;
sy = 1;
for i = 0:7
    for j = 0:5
        k = offset_distance(sx,sy,i,j);
        disp(['(',num2str(sx),',',num2str(sy),')->(',num2str(i),',',num2str(j),')=',num2str(k)])
    end
end

有关此解决方案的数学详细信息,请访问:http://www.redblobgames.com/grids/hexagons/。您可以在http://www.redblobgames.com/grids/hexagons/implementation.html

获得完整的图书馆

答案 4 :(得分:0)

这听起来像是Bresenham line algorithm的工作。您可以使用它来计算从A到B的段数,这将告诉您路径距离。

答案 5 :(得分:0)

如果将不同的六边形定义为图形,则可以获得从节点A到节点B的最短路径。由于距六边形中心的距离是恒定的,因此将其设置为边缘权重。

但是对于大型领域来说这可能效率低下。