You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

六边形网格中螺旋坐标与轴向坐标的转换方法

世界坐标转六边形螺旋坐标实现方案

配置参考

  • 顶点朝上的六边形螺旋布局:
    spiral coordinates layer/position
  • 螺旋索引规则:
    spiral coordinates index
  • 轴向坐标系统:
    axial coordinates

你的思路完全可行:世界坐标 → 轴向坐标 → 螺旋坐标,以下是分步实现细节:

一、世界坐标转轴向坐标(顶点朝上六边形)

先确定核心参数:

  • hexSize:六边形外接圆半径(中心到顶点的距离)
  • centerWorldX/Y:螺旋中心瓦片的世界坐标(需将鼠标坐标转换为相对中心的坐标)

1. 相对坐标转换

先把鼠标点击的世界坐标转为以中心为原点的相对坐标:

const relX = worldX - centerWorldX;
const relY = worldY - centerWorldY;

2. 浮点轴向坐标计算

针对顶点朝上的六边形,使用以下公式转换为轴向坐标(q, r):

const q = (Math.sqrt(3)/3 * relX - 1/3 * relY) / hexSize;
const r = (2/3 * relY) / hexSize;
// 轴向坐标第三分量 s = -q - r,后续取整会用到
const s = -q - r;

3. 轴向坐标取整

由于浮点坐标存在精度误差,需要用立方体坐标取整法得到整数轴向坐标:

function cubeRound(q: number, r: number): [number, number] {
    let qInt = Math.round(q);
    let rInt = Math.round(r);
    const sInt = Math.round(-q - r);

    const qDiff = Math.abs(qInt - q);
    const rDiff = Math.abs(rInt - r);
    const sDiff = Math.abs(sInt - (-q - r));

    // 修正偏差最大的分量,保证 q + r + s = 0
    if (qDiff > rDiff && qDiff > sDiff) {
        qInt = -rInt - sInt;
    } else if (rDiff > sDiff) {
        rInt = -qInt - sInt;
    }

    return [qInt, rInt];
}

// 使用示例
const [qInt, rInt] = cubeRound(q, r);

二、轴向坐标转螺旋坐标

利用你已有的螺旋坐标工具函数,配合以下步骤完成转换:

1. 计算螺旋层级(Layer)

螺旋层级等于轴向坐标对应立方体坐标的最大绝对值:

const s = -qInt - rInt;
const layer = Math.max(Math.abs(qInt), Math.abs(rInt), Math.abs(s));

层级从0开始(中心瓦片为层级0),和你提供的Layer(index)函数逻辑一致。

2. 计算层级内位置(Position)

层级layer包含6*layer个瓦片(层级0仅1个),根据轴向坐标所在的边计算位置:

function getPositionInLayer(q: number, r: number, layer: number): number {
    if (layer === 0) return 0; // 中心瓦片位置固定为0

    const s = -q - r;
    let position = 0;

    // 对应你提供的螺旋布局,6条边的位置区间划分
    if (r === -layer) {
        // 顶部边:q从layer到0 → 位置0 ~ layer-1
        position = layer - q;
    } else if (s === -layer) {
        // 右上侧边:q从0到-layer → 位置layer ~ 2*layer-1
        position = layer + (-q);
    } else if (q === -layer) {
        // 右下侧边:r从0到layer → 位置2*layer ~ 3*layer-1
        position = 2 * layer + r;
    } else if (r === layer) {
        // 底部边:q从-layer到0 → 位置3*layer ~ 4*layer-1
        position = 3 * layer + (layer + q);
    } else if (s === layer) {
        // 左下侧边:q从0到layer → 位置4*layer ~ 5*layer-1
        position = 4 * layer + (layer - q);
    } else if (q === layer) {
        // 左上侧边:r从0到-layer → 位置5*layer ~ 6*layer-1
        position = 5 * layer + (-r);
    }

    return position;
}

3. 计算螺旋索引(Index)

直接调用你已实现的Index函数:

const Index = (layer: number, position: number): number => {
    return 3 * layer * (layer - 1) + 1 + position;
}

// 使用示例
const spiralIndex = Index(layer, position);

三、完整转换示例

// 示例参数
const centerWorldX = 400;
const centerWorldY = 300;
const hexSize = 50;
// 鼠标点击的世界坐标
const worldX = 500;
const worldY = 250;

// 1. 世界坐标转相对坐标
const relX = worldX - centerWorldX;
const relY = worldY - centerWorldY;

// 2. 转浮点轴向坐标
const q = (Math.sqrt(3)/3 * relX - 1/3 * relY) / hexSize;
const r = (2/3 * relY) / hexSize;

// 3. 轴向坐标取整
const [qInt, rInt] = cubeRound(q, r);

// 4. 计算螺旋层级
const s = -qInt - rInt;
const layer = Math.max(Math.abs(qInt), Math.abs(rInt), Math.abs(s));

// 5. 计算层级内位置
const position = getPositionInLayer(qInt, rInt, layer);

// 6. 计算螺旋索引
const spiralIndex = Index(layer, position);

console.log(`螺旋坐标:层级${layer},位置${position},索引${spiralIndex}`);

验证提示

  • 中心瓦片测试:世界坐标(400,300) → 相对坐标(0,0) → 轴向(0,0) → 层级0,位置0,索引1(符合你的Index函数逻辑)
  • 层级1的瓦片可逐个测试,确保位置和索引与你的螺旋图完全对应

内容的提问来源于stack exchange,提问作者Jomity

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 09:20:33