我有一个六边形网格:
使用模板类型坐标T.如何计算两个六边形之间的距离?
例如:
dist((3,3),(5,5))= 3
dist((1,2),(1,4))= 2
答案 0 :(得分:6)
首先应用变换(y,x)| - > (u,v)=(x,y + floor(x / 2))。
现在面部邻接看起来像
0 1 2 3
0*-*-*-*
|\|\|\|
1*-*-*-*
|\|\|\|
2*-*-*-*
让点为(u1,v1)和(u2,v2)。设du = u2 - u1和dv = v2 - v1。距离是
if du and dv have the same sign: max(|du|, |dv|), by using the diagonals
if du and dv have different signs: |du| + |dv|, because the diagonals are unproductive
在Python中:
def dist(p1, p2):
y1, x1 = p1
y2, x2 = p2
du = x2 - x1
dv = (y2 + x2 // 2) - (y1 + x1 // 2)
return max(abs(du), abs(dv)) if ((du >= 0 and dv >= 0) or (du < 0 and dv < 0)) else abs(du) + abs(dv)
答案 1 :(得分:2)
使用坐标系的距离的正确显式公式由下式给出:
d((x1,y1),(x2,y2)) = max( abs(x1 - x2),
abs((y1 + floor(x1/2)) - (y2 + floor(x2/2)))
)
答案 2 :(得分:1)
这是做了什么:
以一个单元格为中心(很容易看出是否选择0,0
),距离dY
的单元格形成一个大的六边形(“半径”dY
)。这个六边形的一个顶点是(dY2,dY).
如果dX<=dY2
,则该路径与距离为dY
的大六边形的公羊形成锯齿形。如果不是,则路径是顶点的“对角线”,加上从顶点到第二个单元的垂直路径,添加dX-dY2
个单元格。
也许更好理解:led:
dX = abs(x1 - x2);
dY = abs(y1 - y2);
dY2= floor((abs(y1 - y2) + (y1+1)%2 ) / 2);
然后:
d = d((x1,y1),(x2,y2))
= dX < dY2 ? dY : dY + dX-dY2 + y1%2 * dY%2
答案 3 :(得分:1)
首先,您需要将坐标转换为&#34;数学&#34;坐标系。每两列您在y方向上移动坐标1个单位。 &#34; mathamatical&#34;坐标(s,t)可以从坐标(u,v)计算如下:
s = u + floor(v / 2) t = v
如果调用六边形a的一边,坐标系的基矢量为(0,-sqrt(3)a)和(3a / 2,sqrt(3)a / 2)。要找到点之间的最小距离,您需要计算坐标系中的曼哈顿距离,该距离由| s1-s2 | + | t1-t2 |给出。其中s和t是系统中的坐标。曼哈顿距离仅涵盖基础向量的方向,因此它仅涵盖步行:| /但不是这样行走:| \。您需要将矢量转换为另一个具有基矢量(0,-sqrt(3)a)和(3a / 2,-sqrt(3)a / 2)的坐标系。该系统中的坐标由s&#39; = st和t&#39; = t给出,因此该坐标系中的曼哈顿距离由| s1&#39; -s2&#39; | + | t1&#39;给出 - T2&#39; |。您要寻找的距离是两个计算的曼哈顿距离的最小值。你的代码看起来像这样:
struct point
{
int u;
int v;
}
int dist(point const & p, point const & q)
{
int const ps = p.u + (p.v / 2); // integer division!
int const pt = p.v;
int const qs = q.u + (q.v / 2);
int const qt = q.v;
int const dist1 = abs(ps - qs) + abs(pt - qt);
int const dist2 = abs((ps - pt) - (qs - qt)) + abs(pt - qt);
return std::min(dist1, dist2);
}
答案 4 :(得分:1)
在我看到我的博客帖子之后在这里发布了来自另一个答案的推荐流量。它被投了票,这是正确的,因为它是不正确的;但这是我在帖子中提出的解决方案的错误描述。
你的'波浪'轴 - 就你的x坐标每隔一行移位 - 会导致各种各样的头痛,试图确定距离或稍后进行寻路,如果这是某种类型的游戏。六边形网格自然地适应三个轴,六边形的“平方”网格最佳地具有一些负坐标,这允许围绕距离进行更简单的数学计算。
这是一个带有(x,y)的网格,x向右下方增加,y向上增加。
通过拉直,第三轴变得明显。
关于这一点的巧妙之处在于三个坐标相互关联 - 所有三个坐标的总和将始终为0.
使用这样一致的坐标系,任何两个六边形之间的原子距离是三个坐标之间的最大变化,或者:
d = max( abs(x1 - x2), abs(y1 -y2), abs( (-x1 + -y1) - (-x2 + -y2) )
非常简单。但是你必须先修复你的网格!
答案 5 :(得分:0)
(奇数-r)(不带z,仅x,y)
我在上面的实现中看到了一些问题。抱歉,我没有全部检查。但是也许我的解决方案会对某人有所帮助,也许这是一个糟糕且未优化的解决方案。
主要思想是对角线然后水平。但是为此,我们需要注意:
1)例如,我们有0; 3(x1 = 0; y1 = 3),然后转到y2 = 6,我们可以在6个步骤内处理每个点(0-6; 6) 所以:0-left_border,6-right_border
2)计算一些偏移量
#include <iostream>
#include <cmath>
int main()
{
//while(true){
int x1,y1,x2,y2;
std::cin>>x1>>y1;
std::cin>>x2>>y2;
int diff_y=y2-y1; //only up-> bottom no need abs
int left_x,right_x;
int path;
if( y1>y2 ) { // if Down->Up then swap
int temp_y=y1;
y1=y2;
y2=temp_y;
//
int temp_x=x1;
x1=x2;
x2=temp_x;
} // so now we have Up->Down
// Note that it's odd-r horizontal layout
//OF - Offset Line (y%2==1)
//NOF -Not Offset Line (y%2==0)
if( y1%2==1 && y2%2==0 ){ //OF ->NOF
left_x = x1 - ( (y2 - y1 + 1)/2 -1 ); //UP->DOWN no need abs
right_x = x1 + (y2 - y1 + 1)/2; //UP->DOWN no need abs
}
else if( y1%2==0 && y2%2==1 ){ // OF->NOF
left_x = x1 - (y2 - y1 + 1)/2; //UP->DOWN no need abs
right_x = x1 + ( (y2 - y1 + 1)/2 -1 ); //UP->DOWN no need abs
}
else{
left_x = x1 - (y2 - y1 + 1)/2; //UP->DOWN no need abs
right_x = x1 + (y2 - y1 + 1)/2; //UP->DOWN no need abs
}
/////////////////////////////////////////////////////////////
if( x2>=left_x && x2<=right_x ){
path = y2 - y1;
}
else {
int min_1 = std::abs( left_x - x2 );
int min_2 = std::abs( right_x - x2 );
path = y2 - y1 + std::min(min_1, min_2);
}
std::cout<<"Path: "<<path<<"\n\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n";
//}
return 0;
}
答案 6 :(得分:-3)
我相信你寻求的答案是:
d((x1,y1),(x2,y2))=max(abs(x1-x2),abs(y1-y2));
你可以在这里找到关于六边形网格坐标系/距离的一个很好的解释:
http://keekerdc.com/2011/03/hexagon-grids-coordinate-systems-and-distance-calculations/