Hexagonal tiles 在六边形网格上计算距离

Hexagonal tiles 在六边形网格上计算距离,hexagonal-tiles,Hexagonal Tiles,我想做的是找出六边形网格上两点之间有多少六边形。我试着在网上搜索一个公式,但我没有找到一个与我使用的十六进制网格类型匹配的公式 六边形网格的布局如下所示,具有相同的坐标系: 我知道这在这个坐标系下是不可能的,但在我回去改变它之前,这是最后的努力。 提前非常感谢。这里有一个次优但不太次优(应该是O(n))的算法: 首先,创建一个函数,确定六边形网格中某个位置的六边形是否与具有某个起点和终点的线段相交(例如,计算由其组成的六条直线,并执行如下操作:) 第二,创建一个函数,确定点所在的六边形网格上的哪

我想做的是找出六边形网格上两点之间有多少六边形。我试着在网上搜索一个公式,但我没有找到一个与我使用的十六进制网格类型匹配的公式

六边形网格的布局如下所示,具有相同的坐标系:

我知道这在这个坐标系下是不可能的,但在我回去改变它之前,这是最后的努力。
提前非常感谢。

这里有一个次优但不太次优(应该是O(n))的算法:

首先,创建一个函数,确定六边形网格中某个位置的六边形是否与具有某个起点和终点的线段相交(例如,计算由其组成的六条直线,并执行如下操作:)

第二,创建一个函数,确定点所在的六边形网格上的哪个六边形

现在,编写如下算法:

  • 保留线段到目前为止已重叠的所有六边形的列表
  • 从线段起点所在的六边形开始
  • 对于最近重叠的六边形周围的每个六边形,如果不在列表中,请查看lin段是否与该六边形相交。如果是这样,请将其作为列表的新标题并重复
  • 如果要测试的六边形已用完,请返回我们制作的列表

我建议您测试直线段与六边形接缝完全平行并沿六边形接缝运行的情况,以查看六边形是否位于一侧、两侧或两侧(并因此停止)。

要找到两个六边形之间的最短路径:

  • 从一个十六进制开始
  • 在不同的行上,沿着对角线指向另一行
  • 当在同一排时,径直朝另一个六边形走去
    让我们调用x方向的差
    dx
    和y方向的差
    dy
    。如果
    dy/2>dx
    ,则不必执行第二步,因此距离仅为
    dy
    。否则,距离为
    dy+(dx-dy/2)
    。除非我犯了错误。

    如果网格上的瓷砖可能会被阻塞,那么您对a*(或a-Star)迷宫解决算法感兴趣:

    本视频中使用的机制适用于正方形网格,但几乎不需要任何额外编码就可以将其应用于六边形网格。 对于每个图块,解算器都知道下一步尝试哪个图块,因为这些图块存储指向其周围图块的指针。在正方形网格中,每个磁贴最多可存储4个指针(最大值是因为它们只存储指向未阻塞磁贴的指针),而在您的情况下,唯一的区别是最多可存储6个指针

    如果平铺始终是可遍历的,那么A*肯定会完成任务,不过可能有一种更快的方法。如果我正确地解释了你的问题,你感兴趣的不是距离,而是两个给定的十六进制数之间的整数计数?请尝试以下操作:

    类协作{
    int x;
    int-y;
    }
    内部区(坐标轴1,坐标轴2){
    intxsteps=Math.abs(hex1.x-hex2.x);
    int-ySteps=Math.abs(hex1.y-hex2.y);
    返回Math.max(xSteps,ySteps)+Math.abs(xSteps-ySteps);
    }
    

    你为什么会问?这个问题是关于确定我们必须垂直或水平移动多少次,而不是对角移动。我们希望尽可能多地沿对角线移动,否则我们对距离就不聪明了
    Math.abs(xSteps-ySteps)
    是我们必须进行的非对角移动的数量。再加上x和y的较大距离,就完成了。

    如果您使用的坐标系沿六边形的纹理向两个方向移动,您可以使用:

    distance = max(
         abs(dest.y - start.y),     
         abs(dest.x - start.x),
         abs((dest.x - dest.y)*-1 - (start.x - start.y)*-1)
    )
    
    但你们并没有,你们使用的是一个扭曲的坐标系,它只沿着一个方向(水平方向)排列。幸运的是,我们可以使用

    straight.y = squiggle.y
    straight.x = ciel(squiggle.y / -2) + squiggle.x
    
    所以,使用这个方程组来求解距离可以得到:

    distance = max(
         abs(dest.y - start.y),     
         abs(ceil(dest.y / -2) + dest.x - ceil(start.y / -2) - start.x),
         abs(-dest.y - ceil(dest.y / -2) - dest.x + start.y  + ceil(start.y / -2) + start.x)
    )
    
    这将得到两个六角之间的曼哈顿距离,只使用它们的坐标(假设我没有做任何错字,将x和y转换,因为你的网格与我的网格旋转90度)。然而,你必须为我的中学代数老师买一块饼干才能让它工作,否则我会弄乱分配属性

    注意:可能需要摆弄负坐标,我没有检查。

    不正确。当它提到在非正交轴上使用正交坐标时,我最初对此表示怀疑,但根据我自己的解决方案运行代码表明,距离估计过高

    实际正确的解决方案是:

    def hextance(开始、结束):
    如果(start.x==dest.x):
    返回abs(目标y-开始y)
    elif(开始时y==结束时y):
    返回abs(dest.x-start.x)
    其他:
    dx=绝对值(dest.x-start.x)
    dy=绝对值(目标y-开始y)
    如果起始y<目的y:
    返回dx+dy-int(math.ceil(dx/2.0))
    其他:
    返回dx+dy-int(数学地板(dx/2.0))
    
    这使用十六进制->正方形表示法:

    ------ ------ 0, +1 ------ -1, +1 ------ +1, +1 ------ 0, 0 ------ -1, 0 ------ +1, 0 ------ 0, -1 ------ ------ -------------------------- | -1, +1 | 0, +1 | +1, +1 | |-------------------------- | -1, 0 | 0, 0 | +1, 0 | |--------------------------| | | 0, -1 | | -------------------------- ------ ------ 0, +1 ------ -1, +1 ------ +1, +1 ------ 0, 0 ------ -1, 0 ------ +1, 0 ------ 0, -1 ------ ------ -------------------------- | -1, +1 | 0, +1 | +1, +1 | |-------------------------- | -1, 0 | 0, 0 | +1, 0 | |--------------------------| | | 0, -1 | | --------------------------
    感谢@user2709663和@jonathankoren提供答案。我花了很多时间研究你的答案,但发现这两个问题都存在。或者至少这些答案所考虑的网格类型没有明确说明。然而,我发现了一个关于这个问题的非常好的教程和代码实现,以及一个用于管理十六进制网格的库:(库代码:)。我还实现了一个matlab版本的距离代码为“o”
    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
    
    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
    
    def distance(self):
        # Take diagonal steps towards self.x == 0
        steps = abs(self.x)
        # y moves closer to 0 by steps because moving diagonal, but never moving too far
        if self.y > 0:
            # Might still be positive, but never negative
            y = max(self.y - steps, 0)
        else:
            # Might still be negative, but not positive
            y = min(self.y + steps, 0)
        # You move 2 positions north/south by a single move so divide y's by 2
        return abs(y) // 2 + abs(steps)