Ho già risposto a una domanda simile, con obiettivi identici, sopra Stack Overflow lo ripubblicherò qui per comodità: (NB - tutto il codice è scritto e testato in Java)
Questa immagine mostra l'angolo in alto a sinistra di una griglia esagonale e sovrapposta è una griglia quadrata blu. È facile trovare quale dei quadrati è presente un punto e ciò darebbe una approssimazione approssimativa di quale esagono. Le porzioni bianche degli esagoni mostrano dove la griglia quadrata ed esagonale condividono le stesse coordinate e le porzioni grigie degli esagoni mostrano dove non lo fanno.
La soluzione ora è semplice come trovare la casella in cui si trova un punto, quindi verificare se il punto si trova in uno dei triangoli e correggere la risposta, se necessario.
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);
A questo punto abbiamo la riga e la colonna della casella in cui si trova il nostro punto, quindi dobbiamo testare il nostro punto contro i due bordi superiori dell'esagono per vedere se il nostro punto si trova in uno degli esagoni sopra:
// 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);
Avere coordinate relative semplifica il passaggio successivo.
Come nell'immagine sopra, se y del nostro punto è > mx + c sappiamo che il nostro punto si trova sopra la linea e, nel nostro caso, l'esagono sopra e a sinistra della riga e della colonna correnti. Si noti che il sistema di coordinate in Java ha y che inizia da 0 nella parte superiore sinistra dello schermo e non nella parte inferiore sinistra, come al solito in matematica, quindi il gradiente negativo usato per il bordo sinistro e il gradiente positivo usato per quello destro.
// 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 rapida spiegazione delle variabili utilizzate nell'esempio sopra:
m è il gradiente, quindi m = c / halfWidth
L' aggiunta di NeoShamam a quanto sopra
Questa è un'aggiunta alla risposta di SebastianTroy. Lo lascerei come commento ma non ho ancora abbastanza reputazione.
Se si desidera implementare un sistema di coordinate assiali come descritto qui:
http://www.redblobgames.com/grids/hexagons/
Puoi apportare una leggera modifica al codice.
Invece di
// 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);
Usa questo
float columnOffset = row * halfWidth;
column = (int)(x + columnOffset)/gridWidth; //switch + to - to align the grid the other way
Ciò farà sì che le coordinate (0, 2) si trovino sulla stessa colonna diagonale di (0, 0) e (0, 1) anziché essere direttamente sotto (0, 0).