Encontrar celdas dentro del rango en una cuadrícula hexagonal


8

Primero: sé que estoy siendo súper denso aquí.

Con eso fuera del camino, estoy tratando de escribir una implementación en C # de este algoritmo:

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)))

He tomado esto de este tremendo recurso.

Mi problema es que cada implementación de esto que he probado hasta ahora ha tenido resultados locos. Por ejemplo, el código que se muestra a continuación actualmente da como resultado esto:

1

y esto:

2

Mi código actualmente se encuentra así:

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);
        }
    }

¿Alguien puede ver algo mal aquí? Todas las sugerencias son bienvenidas. He estado golpeándome la cabeza con esto hace un tiempo.

¡Gracias!

Nota actualizada: estoy usando coordenadas axiales en la cuadrícula. Actualización n. ° 2: como se señala a continuación, tenía mal mi ciclo ... cada uno y no estaba usando deltas para hacer ejercicio. ¡Gracias por la ayuda!

Actualmente tengo un problema como se muestra a continuación con la implementación de las respuestas: ingrese la descripción de la imagen aquí

Seguiré investigando; si lo descubro, publicaré los resultados completos aquí. ¡Gracias a todos!


1
¡Gracias por ese recurso se ve muy bien! Estaba un poco impresionado cuando me di cuenta de que casi todos los gráficos eran interactivos. :)
Christer

3
El ejemplo que da usa coordenadas de cubo, mientras que parece que estás usando coordenadas offset o axiales. Debe convertir la x, y, z de las coordenadas cúbicas que tiene a cualquier sistema de coordenadas que esté utilizando.
Alex Sherman

1
@ Vector57 Estoy usando Axial. Desde la sección de conversión se menciona que no necesito hacer nada con la propiedad Z y que q / r y x / y son intercambiables ... ¿o lo he entendido mal?
aaron-bond

Parece de esa manera, aunque en los ejemplos usa r = z pero no veo por qué debería importar cuál elijas.
Alex Sherman

Respuestas:


4

Entonces, después de una inspección más profunda, su problema no tiene nada que ver con las conversiones del sistema de coordenadas. Esto podría haber quedado más claro al no nombrar sus coordenadas axiales X e Y, sino más bien Q y R. El problema que realmente tiene es malas condiciones de bucle. El ejemplo de código original produce delta q's y r's que intenta convertir, en sus bucles for, a coordenadas absolutas y cometió un error. El algoritmo debería verse como sigue:

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);
    }
}

Oh derp ... el artículo incluso menciona que son valores delta :( Voy a probar esto ahora y ver cómo funciona. Gracias :)
aaron-bond

Gracias por esto. Definitivamente está mucho más cerca de la forma correcta de hacerlo. Todavía estoy estropeando algo con las coordenadas, ¡pero al menos tengo el número correcto! Por alguna razón, termino con una celda demasiado alta en -x y otra demasiado baja en + x. He publicado una foto en la parte superior si sabes algo al respecto, pero continuaré investigando de todos modos :) ¡gracias por tu ayuda!
aaron-bond

¿Estás interpretando correctamente los coordinadores axiales? Recuerde que eligió usar x e y en lugar de x y z, por lo que si el resto de su código no tiene en cuenta este cambio de los ejemplos, puede provocar un comportamiento extraño.
Alex Sherman

Sí, he cambiado para que sea x y z. dx se convierte en x y z = -dx - dy ...
aaron-bond

1
La nueva foto que publicaste muestra 7 hexes resaltados. Esto es lo que esperarías con la distancia = 1. Intente imprimir los valores. Con CellPosition establecido en 0,0 y la distancia 1, los hexágonos que obtienes deben ser (-1, 0); (-1, 1); (0, -1); (0, 0); (0, 1); (1, -1); (1, 0)
amitp

7

Como señaló Vector57 , el problema es que está utilizando un sistema de coordenadas incorrecto . El algoritmo descrito está destinado a usarse con coordenadas de cubo , que tienen componentes x, y y z :

coordenadas del cubo

Esto puede no ser obvio por el pseudocódigo del algoritmo, pero eso es porque es una simplificación de esto :

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)))

... un bucle anidado simple sobre x, y y z, lo que esperarías de un algoritmo de rango.

No sé qué sistema de coordenadas está utilizando, pero supongo que es uno de los sistemas de "coordenadas de desplazamiento", que son populares porque son fáciles de implementar colocando las celdas de la cuadrícula dentro de una matriz 2D:

desplazamiento q diseños verticales

Esto no significa que no pueda usar estos algoritmos de cubo; solo significa que necesitas convertir las coordenadas del cubo a las tuyas . Por ejemplo, para convertir a / desde el diseño vertical "impar-q", use estos:

# 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

Tenía la sensación de que era algo así. Había una parte de esa página que mencionaba la conversión de Cube a Axial y decía que solo eliminaba la porción z y las q y r restantes se convertían en x e y. Creo que debo haber simplificado demasiado allí. Gracias por esto. Excelente explicación de lo que me faltaba. ¡Lo intentaré más tarde! :)
aaron-bond

Acabo de echar un vistazo y estoy usando axial. Seguramente, dado que el algoritmo no menciona a Z, también es un método directoq = x y r = yel sistema también?
aaron-bond
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.