Ya he respondido una pregunta similar, con objetivos idénticos, en Stack Overflow , la volveré a publicar aquí para mayor comodidad: (Nota: todo el código está escrito y probado en Java)
Esta imagen muestra la esquina superior izquierda de una cuadrícula hexagonal y superpuesta es una cuadrícula cuadrada azul. Es fácil encontrar en cuál de los cuadrados hay un punto dentro y esto también daría una aproximación aproximada de cada hexágono. Las porciones blancas de los hexágonos muestran dónde el cuadrado y la cuadrícula hexagonal comparten las mismas coordenadas y las porciones grises de los hexágonos muestran dónde no.
La solución ahora es tan simple como encontrar en qué cuadro se encuentra un punto, luego verificar si el punto está en cualquiera de los triángulos y corregir la respuesta si es necesario.
private final Hexagon getSelectedHexagon(int x, int y)
{
// Find the row and column of the box that the point falls in.
int row = (int) (y / gridHeight);
int column;
boolean rowIsOdd = row % 2 == 1;
// Is the row an odd number?
if (rowIsOdd)// Yes: Offset x to match the indent of the row
column = (int) ((x - halfWidth) / gridWidth);
else// No: Calculate normally
column = (int) (x / gridWidth);
En este punto, tenemos la fila y la columna de la caja en la que se encuentra nuestro punto, luego debemos probar nuestro punto contra los dos bordes superiores del hexágono para ver si nuestro punto se encuentra en cualquiera de los hexágonos anteriores:
// Work out the position of the point relative to the box it is in
double relY = y - (row * gridHeight);
double relX;
if (rowIsOdd)
relX = (x - (column * gridWidth)) - halfWidth;
else
relX = x - (column * gridWidth);
Tener coordenadas relativas facilita el siguiente paso.
Al igual que en la imagen de arriba, si la y de nuestro punto es > mx + c , sabemos que nuestro punto se encuentra por encima de la línea y, en nuestro caso, el hexágono arriba ya la izquierda de la fila y columna actuales. Tenga en cuenta que el sistema de coordenadas en Java tiene y comenzando en 0 en la parte superior izquierda de la pantalla y no en la parte inferior izquierda, como es habitual en matemáticas, de ahí el gradiente negativo utilizado para el borde izquierdo y el gradiente positivo utilizado para la derecha.
// Work out if the point is above either of the hexagon's top edges
if (relY < (-m * relX) + c) // LEFT edge
{
row--;
if (!rowIsOdd)
column--;
}
else if (relY < (m * relX) - c) // RIGHT edge
{
row--;
if (rowIsOdd)
column++;
}
return hexagons[column][row];
}
Una explicación rápida de las variables utilizadas en el ejemplo anterior:
m es el gradiente, entonces m = c / halfWidth
La adición de NeoShamam a lo anterior
Esta es una adición a la respuesta de Sebastian Troy. Lo dejaría como un comentario, pero todavía no tengo suficiente reputación.
Si desea implementar un sistema de coordenadas axiales como se describe aquí:
http://www.redblobgames.com/grids/hexagons/
Puede hacer una ligera modificación al código.
En lugar de
// Is the row an odd number?
if (rowIsOdd)// Yes: Offset x to match the indent of the row
column = (int) ((x - halfWidth) / gridWidth);
else// No: Calculate normally
column = (int) (x / gridWidth);
utilizar esta
float columnOffset = row * halfWidth;
column = (int)(x + columnOffset)/gridWidth; //switch + to - to align the grid the other way
Esto hará que la coordenada (0, 2) esté en la misma columna diagonal que (0, 0) y (0, 1) en lugar de estar directamente debajo de (0, 0).