Recherche de cellules à portée sur une grille hexagonale

8

Tout d'abord - je sais que je suis super dense ici.

Avec cela à l'écart, j'essaie d'écrire une implémentation C # de cet algorithme:

var results = []
for each -N  dx  N:
  for each max(-N, -dx-N)  dy  min(N, -dx+N):
    var dz = -dx-dy
    results.append(cube_add(center, Cube(dx, dy, dz)))

J'ai tiré cela de cette formidable ressource.

Mon problème est que chaque implémentation de ce que j'ai essayé jusqu'à présent a eu des résultats fous. Par exemple, le code ci-dessous donne actuellement ceci:

1

et ça:

2

Mon code se trouve actuellement comme ceci:

for (int x = this.CellPositionX - distance; x <= this.CellPositionX + distance; x++)
    {
        for (int y = this.CellPositionY - Math.Max(-distance, -x - distance); y <= this.CellPositionY + Math.Min(distance, -x + distance); y++)
        {
            HexPosition rangePosition = new HexPosition(x, y);
            range.Add(rangePosition);
        }
    }

Quelqu'un peut-il repérer quelque chose de mal ici? Toutes les suggestions sont les bienvenues. Je me tape la tête sur celui-ci depuis un moment maintenant.

Merci!

Note mise à jour: j'utilise des coordonnées axiales dans la grille. Mise à jour # 2: comme indiqué ci-dessous, ma boucle for..each était incorrecte et je n'utilisais pas de deltas pour le travail. Merci pour l'aide!

J'ai actuellement un problème comme indiqué ci-dessous avec la mise en œuvre des réponses: entrez la description de l'image ici

Je vais continuer à enquêter - si je le comprends, je posterai les résultats complets ici. Merci a tous!

aaron-bond
la source
1
Merci pour cette ressource, elle a l'air vraiment bien! J'ai été un peu époustouflé quand j'ai réalisé que presque tous les graphiques étaient interactifs. :)
Christer
3
L'exemple qu'il donne utilise des coordonnées de cube, alors qu'il semble que vous utilisiez des coordonnées décalées ou axiales. Vous devez convertir les x, y, z des coordonnées cubiques qu'il a en n'importe quel système de coordonnées que vous utilisez.
Alex Sherman
1
@ Vector57 J'utilise Axial. Dans la section de conversion, il est mentionné que je n'ai pas besoin de faire quoi que ce soit avec la propriété Z et que q / r et x / y sont interchangeables ... ou ai-je mal compris cela?
aaron-bond
Cela apparaît de cette façon, bien que dans les exemples, il utilise r = z, mais je ne vois pas pourquoi cela devrait avoir une importance.
Alex Sherman

Réponses:

4

Ainsi, après une inspection plus approfondie, votre problème n'a en fait rien à voir avec les conversions du système de coordonnées. Cela aurait pu être plus clair en ne nommant pas vos coordonnées axiales X et Y mais plutôt Q et R. Le problème que vous rencontrez est en fait de mauvaises conditions de boucle. L'exemple de code d'origine produit des delta q et r que vous essayez de convertir, dans vos boucles for, en coordonnées absolues et vous avez fait une erreur. L'algorithme devrait plutôt ressembler à ceci:

for (int dx = -distance; dx <= distance; dx++)
{
    for (int dy = Math.Max(-distance, -dx - distance); dy <= Math.Min(distance, -dx + distance); dy++)
    {
        HexPosition rangePosition = new HexPosition(
            this.CellPositionX + dx, this.CellPositionY + dy);
        range.Add(rangePosition);
    }
}
Alex Sherman
la source
Oh derp ... l'article mentionne même que ce sont des valeurs delta :( Je vais essayer maintenant et voir comment ça se passe. Merci :)
aaron-bond
Merci pour cela. C'est certainement beaucoup plus proche de la bonne façon de procéder. Je gâche encore quelque chose avec les coordonnées mais au moins j'ai le bon numéro! Pour une raison quelconque, je me retrouve avec une cellule trop haute sur le -x et une trop basse sur le + x. J'ai posté une photo en haut si vous en savez quelque chose mais je continuerai quand même à enquêter :) merci pour votre aide!
aaron-bond
Interprétez-vous correctement les coordonnées axiales? N'oubliez pas que vous avez choisi d'utiliser x et y plutôt que x et z, donc si le reste de votre code ne tient pas compte de ce changement par rapport aux exemples, cela peut entraîner un comportement étrange.
Alex Sherman
Oui, j'ai changé pour que ce soit x et z. dx devient x et z = -dx - dy ...
aaron-bond
1
La nouvelle photo que vous avez publiée montre 7 hexagones en surbrillance. C'est ce à quoi vous vous attendez avec distance = 1. Essayez d'imprimer les valeurs. Avec CellPosition réglé sur 0,0 et la distance 1, les hexs que vous obtenez doivent être (-1, 0); (-1, 1); (0, -1); (0, 0); (0, 1); (1, -1); (1, 0)
amitp
7

Comme l'a souligné Vector57 , le problème est que vous utilisez le mauvais système de coordonnées . L'algorithme décrit est destiné à être utilisé avec des coordonnées de cube , qui ont des composantes x, y et z :

coordonnées du cube

Cela peut ne pas être évident d'après le pseudocode de l'algorithme, mais c'est parce que c'est une simplification de ceci :

var results = []
for each -N  dx  N:
    for each -N  dy  N:
        for each -N  dz  N:
            if dx + dy + dz = 0:
                results.append(cube_add(center, Cube(dx, dy, dz)))

... une boucle simple imbriquée sur x, y et z, ce que vous attendez d'un algorithme de plage.

Je ne sais pas quel système de coordonnées vous utilisez, mais je suppose que c'est l'un des systèmes de "coordonnées décalées", qui sont populaires car ils sont faciles à mettre en œuvre en plaçant les cellules de la grille dans un tableau 2D:

décalage q dispositions verticales

Cela ne signifie pas que vous ne pouvez pas utiliser ces algorithmes de cube; cela signifie simplement que vous devez convertir les coordonnées du cube en vos propres coordonnées . Par exemple, pour effectuer une conversion vers / depuis la disposition verticale "odd-q", utilisez-les:

# convert cube to odd-q offset
col = x
row = z + (x - (x&1)) / 2

# convert odd-q offset to cube
x = col
z = row - (col - (col&1)) / 2
y = -x-z
congusbongus
la source
J'avais le sentiment que c'était quelque chose comme ça. Il y avait une partie de cette page qui mentionnait la conversion de Cube en Axial et disait de supprimer simplement la partie z et les q et r restants devenaient x et y. Je pense que je dois avoir trop simplifié là-bas. Merci pour cela. Excellente explication de ce qui me manquait. Je vais essayer plus tard! :)
aaron-bond
Je viens de jeter un œil et j'utilise axial. Sûrement, puisque l'algorithme ne fait pas mention de Z, c'est aussi un système droit q = xet r = yaussi?
aaron-bond