Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/145.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 六边形网格上两个六边形之间的距离_C++_Algorithm_Distance_Hexagonal Tiles - Fatal编程技术网

C++ 六边形网格上两个六边形之间的距离

C++ 六边形网格上两个六边形之间的距离,c++,algorithm,distance,hexagonal-tiles,C++,Algorithm,Distance,Hexagonal Tiles,我有一个六边形网格: 使用模板类型坐标T。如何计算两个六边形之间的距离 例如: 距离((3,3)、(5,5))=3 dist((1,2),(1,4))=2我相信你寻求的答案是: d((x1,y1),(x2,y2))=max(abs(x1-x2),abs(y1-y2)); 您可以在此处找到关于六边形栅格坐标系/距离的良好解释: 正确的明确距离公式(使用坐标系)如下所示: d((x1,y1),(x2,y2)) = max( abs(x1 - x2),

我有一个六边形网格:

使用模板类型坐标T。如何计算两个六边形之间的距离

例如:

距离((3,3)、(5,5))=3


dist((1,2),(1,4))=2我相信你寻求的答案是:

d((x1,y1),(x2,y2))=max(abs(x1-x2),abs(y1-y2));
您可以在此处找到关于六边形栅格坐标系/距离的良好解释:


正确的明确距离公式(使用坐标系)如下所示:

d((x1,y1),(x2,y2)) = max( abs(x1 - x2), 
                          abs((y1 + floor(x1/2)) - (y2 + floor(x2/2)))
                        )
下面是一位女士所做的:


以一个单元格为中心(如果选择
0,0
,很容易看到),距离
dY
的单元格形成一个大六边形(带有“半径”
dY
)。此六边形的一个顶点是
(dY2,dY)。
如果
dX首先,需要将坐标转换为“数学”坐标系。每两列在y方向上移动坐标1个单位。“数学”坐标(s,t)可根据坐标(u,v)计算如下:

s=u+地板(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'=s-t和t'=t给出,因此该坐标系中的曼哈顿距离由| s1'-s2'|+| t1'-t2'|给出。您要查找的距离是两个计算的曼哈顿距离中的最小值。您的代码如下所示:

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);
}
首先应用变换(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)
def dist(p1、p2):
y1,x1=p1
y2,x2=p2
du=x2-x1
dv=(y2+x2//2)-(y1+x1//2)
如果((du>=0和dv>=0)或(du<0和dv<0))其他abs(du)+abs(dv),则返回max(abs(du),abs(dv)

在我看到我的一篇博文后,从另一个答案中获得了推荐流量。它被否决了,这是正确的,因为它是不正确的;但这是对我在帖子中提出的解决方案的错误描述

你的“蠕动”轴——就你的x坐标每隔一行被移动一次而言——将给你带来各种各样的头痛,如果这是为了某种游戏的话,你将在以后尝试确定距离或进行寻路。六边形网格自然适用于三个轴,六边形的“平方”网格最好有一些负坐标,这使得距离的数学计算更简单

这是一个绘制了(x,y)的网格,x增加到右下角,y向上增加

通过理顺问题,第三个轴变得显而易见

关于这一点,最巧妙的是三个坐标相互关联——所有三个坐标的总和总是0

在这种一致的坐标系中,任意两个六角之间的原子距离是三个坐标之间的最大变化,或者:

d = max( abs(x1 - x2), abs(y1 -y2), abs( (-x1 + -y1) - (-x2 + -y2) )
很简单。但你必须先修复你的网格

(奇数-r)(不带z,仅x,y)

我在上面的实现中看到了一些问题。对不起,我没有全部检查。但也许我的解决方案会对某些人有所帮助,也许这是一个糟糕的、未经优化的解决方案

主要思路是先按对角线,然后按水平线。但为此,我们需要注意:

1) 例如,我们有0;3(x1=0;y1=3)并且要转到y2=6,我们可以在6个步骤内处理每个点(0-6;6) 所以:0-左边界,6-右边界

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;
}
#包括
#包括
int main()
{
//while(true){
int-x1,y1,x2,y2;
标准:cin>>x1>>y1;
标准:cin>>x2>>y2;
int diff_y=y2-y1;//仅向上->底部无需abs
int left_x,right_x;
int路径;
如果(y1>y2){//如果向下->向上,则交换
内部温度y=y1;
y1=y2;
y2=温度;
//
int temp_x=x1;
x1=x2;
x2=温度x;
}//现在我们有了向上->向下
//请注意,它是奇数-r水平布局
//OF-偏移线(y%2==1)
//NOF-未偏移行(y%2==0)
如果(y1%2==1&&y2%2==0){//OF->NOF
左_x=x1-((y2-y1+1)/2-1);//向上->向下无需abs
右_x=x1+(y2-y1+1)/2;//向上->向下无需abs
}
如果(y1%2==0&&y2%2==1){//OF->NOF
左x=x1-(y2-y1+1)/2;//向上->向下无需abs
右_x=x1+((y2-y1+1)/2-1);//向上->向下无需abs
}
否则{
左x=x1-(y2-y1+1)/2;//向上->向下无需abs
右_x=x1+(y2-y1+1)/2;//向上->向下无需abs
}
/////////////////////////////////////////////////////////////

如果(x2>=left_x&&x2您的网格有多大?为什么不使用距离公式?@OGH六边形网格中没有这样的步长公式,或者至少不像您所说的那样广为人知。网格的大小是m行和n列。不。它不适用于dist((2,0),(5,2))=4!=max(3,2)=3此方法无法确定给定示例之一的距离,dist((3,3),(5,5))=3此方法失败,因为它们使用不同的坐标系。@Serdalis是一个拼写错误,我的意思是“-”而不是“,”它似乎返回的距离比实际答案小1。(armin在对我答案的评论中给出的示例)。@Serdalis:我尝试过它:dist((0,0),(5,4))=max(5,abs((0+0/2)-(5+4/2))=max(5,7)=7;dist((3,3),(5,4))=max(2,abs((3+3/2)-(5+4/2))=ma
d = max( abs(x1 - x2), abs(y1 -y2), abs( (-x1 + -y1) - (-x2 + -y2) )
#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;
}