Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.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
.net 在六角网格中捕捉到最近的六角中心_.net_Algorithm_C++ Cli_Rounding_Hexagonal Tiles - Fatal编程技术网

.net 在六角网格中捕捉到最近的六角中心

.net 在六角网格中捕捉到最近的六角中心,.net,algorithm,c++-cli,rounding,hexagonal-tiles,.net,Algorithm,C++ Cli,Rounding,Hexagonal Tiles,我正在尝试创建一个基于网格的游戏。到目前为止,我有一个基于六边形瓷砖的网格,其坐标方案如下所示: col 0 | col 1 | | col 2 | | | __ | __ __ __ __ /00\__/02\__/04\__/06\__/08\__ \__/01\__/03\__/05\__/07\__/09\--- row 0 /10\__/12\__/14\__/16\__/18\__/ \__/11\__/13\__/15\__/17\__/

我正在尝试创建一个基于网格的游戏。到目前为止,我有一个基于六边形瓷砖的网格,其坐标方案如下所示:

col 0
 | col 1
 |   | col 2
 |   |  |
 __  | __    __    __    __   
/00\__/02\__/04\__/06\__/08\__
\__/01\__/03\__/05\__/07\__/09\--- row 0
/10\__/12\__/14\__/16\__/18\__/
\__/11\__/13\__/15\__/17\__/19\--- row 1
/20\__/22\__/24\__/26\__/28\__/
\__/21\__/23\__/25\__/27\__/29\--- row 2
/30\__/32\__/34\__/36\__/38\__/
\__/  \__/  \__/  \__/  \__/   --- row 3
在现实生活中,每个六边形的颜色都是随机的:

我想弄清楚的是,当用户点击一个六边形时,我如何确定他们点击了哪个六边形

到目前为止,我尝试的代码如下:

private: System::Void MyForm_MouseDown(System::Object^  sender,
    System::Windows::Forms::MouseEventArgs^  e) {

    int CloseI=0,CloseJ=0;
    CloseJ = FindNearesetX(e->X);
    CloseI = FindNearesetY(e->Y);
    //Grid[down(y)][along(x)]
    P1.X = Grid[CloseI][CloseJ].GetX();
    P1.Y = Grid[CloseI][CloseJ].GetY();
} // END MOUSE DOWN EVENT

int FindNearesetX(int ActualX){
    int ClosestJPos;
    ClosestJPos = ((ActualX-Grid[0][0].GetX())/(1.5*HexSideLength));
    return ClosestJPos;
}//END FIND NEAREST X

int FindNearesetY(int ActualY){
    int ClosestIPos;
    ClosestIPos = ((ActualY-Grid[0][0].getY())/(HexHeight));
    return ClosestIPos;
}//END FIND NEAREST Y

private: System::Void MyForm_MouseMove(System::Object^  sender,
    System::Windows::Forms::MouseEventArgs^  e) {
    this->Invalidate();

    P2.X = e->X;
    P2.Y = e->Y; 
} // END MOUSE MOVE EVENT       
然而,这并没有达到我的预期效果,这是因为当用户单击六边形中心点的左侧时,它会捕捉到他们单击的六边形左侧的六边形,并且如果他们单击所有奇数列上的中心点上方,它会捕捉到他们单击的六边形上方的六边形

我已经在这个问题上纠缠了两天了,我真的很想把它弄清楚。
感谢

单击的点将始终最接近发生单击的六边形的中心,除非该点正好位于两个六边形之间,在这种情况下,它将与两个中心等距。两点之间距离的方程式为SQRT((x1-x2)^2+(y1-y2)^2)


您不必测试到每个六边形的距离。通过创建x/y阈值,可以将测试限制在附近的六边形。例如,如果六边形的宽度为10,且点位于(51,73),则不必测试x坐标小于40或大于70的六边形。

实际上,由于六边形的规则形状(所有边的长度相同),这就像在六角形瓷砖列表中循环一样简单,只需单击鼠标即可确定哪个瓷砖的中心距离最近

C++伪代码:

//assuming "map" is an array of "Tile" pointers

Tile *closest = nullptr;
int fromClosestCenterToClick = INT_MAX;

for (int row = 0; row < map.numRows(); row++)
{
   for (int col = 0; col < map.numCols(); col++)
   {
      int distance = std::sqrt(std::pow(map[row][column]->center.x - mouseClickX, 2) + std::pow(map[row][column]->center.y - mouseClickY, 2) < fromClosestCenterToClick);
      if (distance < fromClosestCenterToClick)
      {
         closest = map[row][column];
         fromClosestCenterToClick = distance;
      }
   }
}
//closest now holds the correct tile
//假设“map”是一个“Tile”指针数组
瓦片*最近=空PTR;
int fromClosestCenterToClick=int_MAX;
对于(int row=0;rowcenter.x-mouseClickX,2)+std::pow(map[row][column]->center.y-mouseClickY,2)
一个人应该能够找到最接近O(1)复杂度的六边形:

    odd     even    odd    even
 0 +----+  |    |  +----+  |
   | 00 |\ |    |  | 02 |  |
   |    | \+----+  |    |  +
   |    | /| 01 |  |    |  |
 H +----+/ |    |  +----+  |
   | 10 |\ |    |  | 12 |  |
   |    | \+----+  |    |  +
   |    | /| 11 |  |    |  |
2H +----+/ |    |  +----+  |
   0....X..W.......2W......3W

角“+”也是六边形的角当‘x’mod W

注意:SS2DCoordinates和SS3DCoordinates是简单的结构,具有两个或三个整数变量,分别表示2D和3D网格上的坐标(x/y表示2D,x/y/z表示3D)。请注意,我的十六进制网格从1/1开始,而不是从0/0开始

SS2DCoordinates coordinatesForHexAtPoint(float a, float b)
{
    // Get basic hex information - pseudocode
    float radius = <radius of one hexagon>

    // Estimate the most likely hex and round to nearest values
    float x = 2.0/3.0*a/radius;
    float z = (1.0/3.0*sqrt(3.0)*b-1.0/3.0*a)/radius;
    float y = -x-z;

    int ix = (int)round((floor(x-y)-floor(z-x))/3.0);
    int iy = (int)round((floor(y-z)-floor(x-y))/3.0);
    int iz = (int)round((floor(z-x)-floor(y-z))/3.0);

    // Adjust to flat coordinates on the offset numbering system
    SS2DCoordinates corrected = hexToFlatCoordinates(SS3DCoordinatesMake(ix, iy, iz));
    corrected.x --;
    return axialToOffsetCoordinates(corrected);
}


SS2DCoordinates hexToFlatCoordinates(SS3DCoordinates hex)
{
    SS2DCoordinates coordinates;
    coordinates.x = hex.x;
    coordinates.y = hex.z;
    return coordinates;
}


SS2DCoordinates axialToOffsetCoordinates(SS2DCoordinates axial)
{
    SS2DCoordinates offset;
    offset.x = axial.x;
    offset.y = axial.y + (NSInteger)ceilf((float)axial.x/2.0);
    return offset;
}
ss2d六点坐标(浮点a、浮点b)
{
//获取基本十六进制信息-伪代码
浮动半径=
//估计最可能的十六进制和四舍五入到最接近的值
浮动x=2.0/3.0*a/半径;
浮动z=(1.0/3.0*sqrt(3.0)*b-1.0/3.0*a)/半径;
浮动y=-x-z;
int ix=(int)圆形((地板(x-y)-地板(z-x))/3.0);
int iy=(int)圆形((地板(y-z)-地板(x-y))/3.0);
int iz=(int)圆形((地板(z-x)-地板(y-z))/3.0);
//调整到偏移编号系统上的平面坐标
校正的SS2D坐标=六角坐标(SS3DCoordinateMake(ix,iy,iz));
更正.x--;
返回轴向偏移设置坐标(校正);
}
SS2D坐标六角坐标平面坐标(SS3D坐标六角)
{
ss2d坐标;
坐标x=十六进制x;
坐标y=十六进制z;
返回坐标;
}
SS2D坐标轴偏移设置坐标(SS2D坐标轴)
{
ss2d坐标偏移;
偏移量x=轴向偏移量x;
偏移量y=轴向y+(NSInteger)ceilf((浮动)轴向x/2.0);
返回偏移量;
}

gah,你复制了我的answer@TylerDurdenxD我可能先开始打字,但是是的。讽刺的是,你的更完整。阈值是个好主意+1此外,由于您只对查找最近的六边形感兴趣,您应该能够省略平方根检查,因为实际长度不会用于任何东西。如果要检查大量多边形,这可能会节省一些周期。泰勒基于宽度的剔除点也是一个非常快的优化,你应该考虑实现,并且绝对应该被用作一个预测试。在一个实际的实现中,你不需要做sqrt,只需要差分的平方和,即点之间的方差。我发布这个问题已经2年了,但我确实记得看到过那个帖子,我相信它并没有解决我的问题(尽管我确信它有帮助),然而,对于我来说,它太长了,我记不起它为什么没有回答我的问题的细节。这么长时间之后,在这篇文章上看到活动真奇怪!啊哈