Ottieni l'anello di tessere nella griglia esagonale


17

Grazie a questo post: tessere esagonali e trovando i loro vicini adiacenti , sono in grado di raccogliere tessere adiacenti in una determinata tessera. Ma sono praticamente bloccato su un algoritmo che mi dà solo un "anello" di tessere specificato da un offset. L'algoritmo fornito in quel post Stack Overflow non si preoccupa esattamente dell'ordine in cui raccoglie le tessere.

So che ad ogni offset vengono aggiunte 6 tessere.

  • Offset 1 ti dà 6 tessere (le prime tessere adiacenti).
  • Offset 2 ti dà 12.
  • Offset 3 ti dà 18, ecc.

C'è una crescita costante di 6 con ogni offset. Quindi presumo che ci dovrebbe essere una regola che si adatta a questi offset. Non riesco esattamente a capirlo. Chiunque?

Risposte:


23

Un anello esagonale con il raggio di N è costituito da 6 linee rette, ognuna con lunghezza N - vedi il mio esempio estremamente grezzo di seguito :) Per N = 2:

inserisci qui la descrizione dell'immagine

Le frecce coprono 2 esagoni ciascuna.

Suppongo che tu abbia alcune funzioni che ti danno la tessera vicina in una direzione specifica, come nord (), sud-est () ecc. Quindi il tuo algoritmo, in pseudocodice, dovrebbe essere qualcosa del genere:

var point = startingPoint.north(N)
for i = 0..N-1:
    result.add(point)
    point = point.southeast(1);
for i = 0..N-1:
    result.add(point)
    point = point.south(1);
for i = 0..N-1:
    result.add(point)
    point = point.southwest(1);
for i = 0..N-1:
    result.add(point)
    point = point.northwest(1);
for i = 0..N-1:
    result.add(point)
    point = point.north(1);
for i = 0..N-1:
    result.add(point)
    point = point.northeast(1);

Si noti che questo dovrebbe funzionare anche per i casi limite N = 1, che restituiscono 6 tessere e N = 0 che restituisce un set vuoto.

So che il codice non è perfetto :) C'è un po 'di ridondanza qui. Nei miei progetti con mappe regolarmente piastrellate (esagonali o di altro tipo) di solito ho una "Direzione" enum che mi permette di farlo in modo più fluido:

var point = startingPoint.inDir(N, Direction.North)
var dir = Direction.SouthEast.
for d = 0..Direction.count():
    for i = 0..N-1:
        result.add(point)
        point = point.inDir(1, dir);
    dir = nextDirection(dir);

Questo dovrebbe spingermi nella giusta direzione. Grazie!
Sidar,

2
Si noti che l'esempio di codice aggiungerà punti duplicati per i primi cinque segmenti. Tuttavia, è una bella risposta.
MichaelHouse

@ Byte56 Sì, ho pensato. Ma almeno vedo la connessione tra i cambi di direzione!
Sidar,

1
@ Byte56 Davvero? Hm. Ho cercato di evitare che uno ... 0..N-1 dia 0..1 per N = 2, quindi sono i = 0 e i = 1, ovvero 2 valori. 2 valori ogni volta che 6 direzioni sono 12 tessere, come dovrebbe essere ...?
Liosan,

No. Hai ragione. Dato che ogni loop aggiunge un punto dall'ultimo loop, ne sono stato disattivato uno per i loop, il mio errore. È un algoritmo intelligente.
MichaelHouse

2

Ho trovato questo articolo un ottimo riferimento per gli algoritmi a griglia esagonale e la sua sezione su "Distanze" fornisce un metodo per determinare il numero di passaggi tra due tessere. Se converti le tue coordinate assiali (xy) in coordinate cubiche (xyz), la distanza è sempre uguale al più grande degli offset di coordinate tra le due tessere, o max (| dx |, | dy |, | dz |).

O(n2)

inserisci qui la descrizione dell'immagine

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.