H3 gridDistance函数报错疑问:‘相距过远’与五边形畸变解析
H3的gridDistance文档中提到:“距离计算可能失败,原因包括两个索引不可比(分辨率不同)、相距过远或被五边形畸变分隔”。分辨率不同的情况很容易理解,但我对另外两个异常存在困惑:“相距过远”具体指什么?是H3单元格距离还是公里距离?
请看以下示例:
function example1() { const cellA = '801bfffffffffff'; // base cell 13 const cellB = '8035fffffffffff'; // base cell 26 return h3.gridDistance(cellA , cellB); // <--- distance 1 }这两个相邻的Res0单元格,gridDistance返回1,结果正常。
再看以下示例:
function example2() { const cellA = '801bfffffffffff'; // base cell 13 const cellC = '8055fffffffffff'; // base cell 42 return h3.gridDistance(cellA , cellC); // <--- error }cellC是cellB的邻居(但不是cellA的邻居),我认为距离应该是2,但却返回错误。
起初我以为是正二十面体的面导致问题,因为801bfffffffffff跨两个正二十面体面,但再看下面的示例:
function example3() { const cellA = '8019fffffffffff'; // base cell 12 const cellC = '803bfffffffffff'; // base cell 29 return h3.gridDistance(cellA , cellC); // <--- error }我认为距离应该是2,但仍报错。我猜测“相距过远”可能指英里或公里距离,但这似乎不合理。而且示例3中的两个单元格都完全在一个正二十面体面内,我不理解五边形畸变如何影响它。
请问我忽略了什么?
注:我的实际应用需要计算不相邻的R7单元格之间的距离,经常遇到gridDistance报错,为清晰说明问题,本文以Res0单元格为例。
核心原因解析
gridDistance计算的是网格步行距离(即从一个单元格到另一个单元格需要经过的最少相邻单元格步数),文档里的两个报错原因实际是以下逻辑:
1. “相距过远”不是地理距离,而是网格计算阈值限制
H3的gridDistance内部有算法迭代次数的上限,不同分辨率下这个阈值差异很大:
- 低分辨率(比如Res0)的单元格对应正二十面体的大区域,跨面的网格路径会快速触发迭代上限,即使你认为步数只有2,算法也无法完成路径计算。
- 高分辨率(比如R7)的阈值更高,但当两个单元格的网格步行距离超过预设步数,或路径需要跨过多组正二十面体的面边界时,依然会返回错误。
2. “被五边形畸变分隔”的影响
H3存在12个五边形单元格用于修正球面投影的畸变,这些单元格的邻接关系和六边形不同:
- 如果两个单元格的最短网格路径必须经过五边形单元格,或者被五边形单元格阻断了所有可能的连续路径,
gridDistance就会报错。 - 你的示例3虽然单元格不在五边形区域,但Res0的网格分区逻辑本身就受正二十面体顶点/边的影响,本质上是算法对低分辨率跨区域路径的计算限制,而非直接的五边形畸变。
针对你的示例的具体说明
Example2和Example3中,看似步数为2的Res0单元格,实际它们的网格路径需要绕经正二十面体的顶点或跨多个面,超出了Res0下gridDistance的计算阈值,因此返回错误。
实际应用(R7单元格)的解决方案
如果需要计算R7单元格的距离,可参考以下方案:
- 若只需地理距离:用
h3Distance函数计算两个单元格中心的球面直线距离(单位米),这个方法没有路径限制。 - 必须用网格步行距离:
- 先通过
h3IsPentagon排查是否涉及五边形单元格,避免路径被阻断。 - 尝试用
h3GridPathCells生成路径,若该函数失败,则说明两个单元格无法通过连续网格路径到达,gridDistance也会报错。 - 对于跨面的情况,可以先将单元格转换到更高分辨率,计算网格距离后再做适配,但可能引入微小误差。
- 先通过
内容的提问来源于stack exchange,提问作者Michael Houlihan

