六边形网格中螺旋坐标与轴向坐标的转换方法
世界坐标转六边形螺旋坐标实现方案
配置参考
- 顶点朝上的六边形螺旋布局:

- 螺旋索引规则:

- 轴向坐标系统:

你的思路完全可行:世界坐标 → 轴向坐标 → 螺旋坐标,以下是分步实现细节:
一、世界坐标转轴向坐标(顶点朝上六边形)
先确定核心参数:
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
相关产品推荐
相关产品推荐

