Pregunta

Estoy tratando de llegar a una función iterativa que genera coordenadas XYZ para una rejilla hexagonal. Con una posición de partida hexagonal (0,0,0 decir por simplicidad), quiero calcular las coordenadas de cada "anillo" sucesiva de hexágonos, como se ilustra a continuación:

Hasta ahora, todo lo que he conseguido llegar a decir esto (ejemplo en javascript):

var radius = 3
var xyz = [0,0,0];

// for each ring
for (var i = 0; i < radius; i++) {
    var tpRing = i*6;
    var tpVect = tpRing/3;
    // for each vector of ring
    for (var j = 0; j < 3; j++) {
        // for each tile in vector
        for(var k = 0; k < tpVect; k++) {
            xyz[0] = ???;
            xyz[1] = ???;
            xyz[2] = ???;
            console.log(xyz);
        }
    }
}

Sé que cada anillo contiene seis puntos más que el anterior y cada 120 ° vector contiene un punto adicional para cada paso del centro. También sé que x + y + z = 0 para todos los azulejos. Pero, ¿cómo puedo generar una lista de coordenadas que siguen la secuencia de abajo?

    0, 0, 0

    0,-1, 1
    1,-1, 0
    1, 0,-1
    0, 1,-1
   -1, 1, 0
   -1, 0, 1

    0,-2, 2
    1,-2, 1
    2,-2, 0
    2,-1,-1
    2, 0,-2
    1, 1,-2
    0, 2,-2
   -1, 2,-1
   -2, 2, 0
   -2, 1, 1
   -2, 0, 2
   -1,-1, 2
¿Fue útil?

Solución

Otra posible solución, que se ejecuta en O (radio 2 ), a diferencia de la O (radio 4 ) de solución de tehMick (a expensas de un montón de estilo) es la siguiente:

radius = 4
for r in range(radius):
    print "radius %d" % r
    x = 0
    y = -r
    z = +r
    print x,y,z
    for i in range(r):
        x = x+1
        z = z-1
        print x,y,z
    for i in range(r):
        y = y+1
        z = z-1
        print x,y,z
    for i in range(r):
        x = x-1
        y = y+1
        print x,y,z
    for i in range(r):
        x = x-1
        z = z+1
        print x,y,z
    for i in range(r):
        y = y-1
        z = z+1
        print x,y,z
    for i in range(r-1):
        x = x+1
        y = y-1
        print x,y,z

o escrita un poco más concisa:

radius = 4
deltas = [[1,0,-1],[0,1,-1],[-1,1,0],[-1,0,1],[0,-1,1],[1,-1,0]]
for r in range(radius):
    print "radius %d" % r
    x = 0
    y = -r
    z = +r
    print x,y,z
    for j in range(6):
        if j==5:
            num_of_hexas_in_edge = r-1
        else:
            num_of_hexas_in_edge = r
        for i in range(num_of_hexas_in_edge):
            x = x+deltas[j][0]
            y = y+deltas[j][1]
            z = z+deltas[j][2]            
            print x,y,z

Está inspirado por el hecho de los hexágonos están realmente en el exterior de un hexágono a sí mismos, para que pueda encontrar las coordenadas de 1 de sus puntos, y luego calcular los demás moviendo en sus bordes 6.

Otros consejos

No sólo es x + y + z = 0, pero los valores absolutos de x, y y z son iguales a dos veces el radio del anillo. Esto debería ser suficiente para identificar cada hexágono en cada anillo sucesivo:

var radius = 4;
for(var i = 0; i < radius; i++)
{
    for(var j = -i; j <= i; j++)
    for(var k = -i; k <= i; k++)
    for(var l = -i; l <= i; l++)
        if(Math.abs(j) + Math.abs(k) + Math.abs(l) == i*2 && j + k + l == 0)
            console.log(j + "," + k + "," + l);
    console.log("");
}

Ok, después de probar las dos opciones me he decidido por la solución de Ofri ya que es un poquito más rápido y hace que sea fácil para proporcionar un valor de desplazamiento inicial. Mi código ahora se ve así:

var xyz = [-2,2,0];
var radius = 16;
var deltas = [[1,0,-1],[0,1,-1],[-1,1,0],[-1,0,1],[0,-1,1],[1,-1,0]];
for(var i = 0; i < radius; i++) {
        var x = xyz[0];
        var y = xyz[1]-i;
        var z = xyz[2]+i;
        for(var j = 0; j < 6; j++) {
                for(var k = 0; k < i; k++) {
                        x = x+deltas[j][0]
                        y = y+deltas[j][1]
                        z = z+deltas[j][2]
                        placeTile([x,y,z]);
                }
        }
}

El método "placeTile" utiliza cloneNode copiar un elemento SVG predefinido y se tarda aproximadamente 0,5 ms por azulejo para ejecutar el cual es más que suficiente. Muchas gracias a tehMick y Ofri por su ayuda!

JS

scroll top