编辑:这个问题比我一开始想的要难,我会用一些工作来重写我的答案,但是我不确定解决方案路径是否对其他答案有任何改进。
这个问题可以改写:给定任何 x,y 找到中心最接近 x,y 的六边形
即在 n 上最小化 dist_squared( Hex[n].center, (x,y) ) (平方意味着你不需要担心平方根,这会节省一些 CPU)
但是,首先我们应该缩小要检查的六边形的数量——我们可以通过以下方法将其缩小到最多 5 个:

因此,第一步是在 UV 空间中表达您的点 (x,y),即 (x,y) = lambda U + mu V, 所以 = (lambda, mu) 在 UV 空间中
这只是一个 2D 矩阵变换(如果您不了解线性变换,http: //playtechs.blogspot.co.uk/2007/04/hex-grids.html可能会有所帮助)。
现在给定一个点 (lambda, mu),如果我们将两者都四舍五入到最接近的整数,那么我们有:

绿色广场内的任何地方都映射回 (2,1)
因此,该绿色正方形内的大多数点都是正确的,即它们在六边形 (2,1) 中。
但是有些点应该返回六边形#(2,2),即:

同样,有些应该返回六边形#(3,1)。然后在那个绿色平行四边形的对角,还有两个区域。
总而言之,如果 int(lambda,mu) = (p,q) 那么我们可能在六边形 (p,q) 内,但我们也可能在六边形 (p+1,q), (p,q+1) 内, (p-1,q) 或 (p,q-1)
有几种方法可以确定其中的哪一个。最简单的方法是将所有这 5 个六边形的中心转换回原始坐标系,然后找到最接近我们的点。
但事实证明,您可以将范围缩小到约 50% 的时间不进行距离检查,约 25% 的时间进行一次距离检查,其余约 25% 的时间进行两次距离检查(我猜通过查看每个检查的区域来计算数字):
p,q = int(lambda,mu)
if lambda * mu < 0.0:
// opposite signs, so we are guaranteed to be inside hexagon (p,q)
// look at the picture to understand why; we will be in the green regions
outPQ = p,q

else:
// circle check
distSquared = dist2( Hex2Rect(p,q), Hex2Rect(lambda, mu) )
if distSquared < .5^2:
// inside circle, so guaranteed inside hexagon (p,q)
outPQ = p,q

else:
if lambda > 0.0:
candHex = (lambda>mu) ? (p+1,q): (p,q+1)
else:
candHex = (lambda<mu) ? (p-1,q) : (p,q-1)
最后一个测试可以整理一下:
else:
// same sign, but which end of the parallelogram are we?
sign = (lambda<0) ? -1 : +1
candHex = ( abs(lambda) > abs(mu) ) ? (p+sign,q) : (p,q+sign)
现在我们已经将其缩小到另一个可能的六边形,我们只需要找到更接近的一个:
dist2_cand = dist2( Hex2Rect(lambda, mu), Hex2Rect(candHex) )
outPQ = ( distSquared < dist2_cand ) ? (p,q) : candHex
Dist2_hexSpace(A,B) 函数可以进一步整理。