环形六边形地图中的距离计算

时间:2018-01-06 06:37:45

标签: java dictionary distance hexagonal-tiles

所以我试图获得六边形平铺地图的基本计算。我正在使用这个经典宝石中显示的菱形样式图(检查“菱形”选项):

https://www.redblobgames.com/grids/hexagons/#map-storage

在我的地图中,R和Q不一定相同,也就是说,地图可以是“矩形”。由于地图包含在R和Q中,因此有许多可能的正确距离,我有兴趣找到最短距离。

E.g。如果你去(0,0) - (1,0) - (2,0) - (3,0) - (4,0) - (4),从(0,0)到(4,2)的距离是6 ,1) - (4,2),但如果你去(4,2) - (5,1) - (6,0)=(0,0)

它是2

所以我得到了这个正确计算这个包裹距离的代码:

public static Integer distance(HexCubeCoord origin, HexCubeCoord destination) {
    // Normalize destination taking origin to (0, 0)
    Integer dR = destination.getGridR() - origin.getGridR();
    Integer dC = destination.getGridC() - origin.getGridC();
    // Wrap normalized distance
    HexCubeCoord normDest = new HexCubeCoord(HexCalculator.wrapR(dR), HexCalculator.wrapC(dC));
    // Calculate distances to (0, 0) and the other three mirror origins
    Integer d0 = simpleDistance(new HexCubeCoord(0, 0), normDest);
    Integer d1 = simpleDistance(new HexCubeCoord(0, HexGridData.getColCount()), normDest);
    Integer d2 = simpleDistance(new HexCubeCoord(HexGridData.getRowCount(), 0), normDest);
    Integer d3 = simpleDistance(new HexCubeCoord(HexGridData.getRowCount(), HexGridData.getColCount()), normDest);
    // Return the min of those four distances
    return Math.min(Math.min(Math.min(d0, d1), d2), d3);
}

public static Integer simpleDistance(HexCubeCoord origin, HexCubeCoord destination) {
    Integer dR = destination.getGridR() - origin.getGridR();
    Integer dC = destination.getGridC() - origin.getGridC();
    Integer dZ = - dC - dR;
    return Math.max(Math.max(Math.abs(dR), Math.abs(dC)), Math.abs(dZ));
}

现在,我将使用距离计算A LOT,我希望它更简单。我已经花了很多时间试图减少所需的操作量,特别是我想避免计算到四个镜像原点的距离以获得最小的镜像原点。

我不是要求明显的优化,例如避免实例化新对象,我可以在以后弄清楚。我可以使用任何数学方法来使这个算法更简单吗?

1 个答案:

答案 0 :(得分:0)

经过大量的工作和时间,我终于找到了一个似乎适用于我所有测试用例的距离计算。

我希望能回答我自己的问题,我将结果距离计算发布在一个环绕的六角形地图中,以防其他人发现它有趣。

public static Integer distance(HexCubeCoord origin, HexCubeCoord destination) {
    // Normalize destination taking origin to (0, 0)
    Integer dR = destination.getGridR() - origin.getGridR();
    Integer dC = destination.getGridC() - origin.getGridC();
    // Wrap normalized distance to get closer to (0, 0)
    // Wrap c-wise
    if (Math.abs(dC) >= HexGridData.getColCount() / 2) {
        dC = (HexGridData.getColCount() - Math.abs(dC)) * (- Integer.signum(dC));
    }
    // Wrap r-wise
    if (Math.abs(dR) >= (HexGridData.getRowCount() / 2) - Math.floor(dC / 2)) {
        dR = (HexGridData.getRowCount() - Math.abs(dR)) * (- Integer.signum(dR));
    }
    Integer dZ = (- dC - dR);
    // Calculate distance in the usual form
    return Math.max(Math.max(Math.abs(dR), Math.abs(dC)), Math.abs(dZ));
}

它从https://blog.demofox.org/2017/10/01/calculating-the-distance-between-points-in-wrap-around-toroidal-space/中概述的方法开始,但是当包装r方式时,我添加“ - Math.floor(dC / 2)”部分来补偿网格上的分配( +,+)---( - , - )对角线。

编辑(1919年1月):

我发现提供的解决方案在某些极端情况下不起作用。

过了一段时间,我再次接受了这个问题,经过大量的尝试,我发现如果使用偏移坐标而不是轴向或立方体,计算环绕六边形地图中距离的问题就变得微不足道了。唯一需要注意的是,无论你决定做出什么偏移,行或列的数量必须是均匀的,这样地图才能正确包装。