J'ai déjà répondu à une question similaire, avec des objectifs identiques, sur Stack Overflow, je vais le republier ici pour plus de commodité: (NB - tout le code est écrit et testé en Java)
Cette image montre le coin supérieur gauche d'une grille hexagonale et superposée est une grille carrée bleue. Il est facile de trouver lequel des carrés un point est à l'intérieur et cela donnerait une approximation approximative de quel hexagone aussi. Les parties blanches des hexagones montrent où la grille carrée et hexagonale partagent les mêmes coordonnées et les parties grises des hexagones montrent où elles ne le font pas.
La solution est maintenant aussi simple que de trouver la case dans laquelle se trouve un point, puis de vérifier si le point se trouve dans l'un des triangles et de corriger la réponse si nécessaire.
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);
À ce stade, nous avons la ligne et la colonne de la boîte dans laquelle se trouve notre point, ensuite nous devons tester notre point contre les deux bords supérieurs de l'hexagone pour voir si notre point se trouve dans l'un des hexagones ci-dessus:
// 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);
Avoir des coordonnées relatives facilite la prochaine étape.
Comme dans l'image ci-dessus, si le y de notre point est > mx + c, nous savons que notre point se situe au-dessus de la ligne, et dans notre cas, l'hexagone au-dessus et à gauche de la ligne et de la colonne en cours. Notez que le système de coordonnées en java a y commençant à 0 en haut à gauche de l'écran et non en bas à gauche comme d'habitude en mathématiques, d'où le gradient négatif utilisé pour le bord gauche et le gradient positif utilisé pour la droite.
// 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];
}
Une explication rapide des variables utilisées dans l'exemple ci-dessus:
m est le gradient, donc m = c / halfWidth
Ceci est un addendum à la réponse de SebastianTroy. Je le laisserais comme un commentaire mais je n'ai pas encore assez de réputation.
Si vous souhaitez implémenter un système de coordonnées axiales comme décrit ici:
http://www.redblobgames.com/grids/hexagons/
Vous pouvez apporter une légère modification au code.
Au lieu 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);
utilisez ceci
float columnOffset = row * halfWidth;
column = (int)(x + columnOffset)/gridWidth; //switch + to - to align the grid the other way
Cela fera que les coordonnées (0, 2) seront sur la même colonne diagonale que (0, 0) et (0, 1) au lieu d'être directement en dessous (0, 0).