I'm trying to come up with an iterative function that generates xyz coordinates for a hexagonal grid. With a starting hex position (say 0,0,0 for simplicity), I want to calculate the coordinates for each successive "ring" of hexagons, as illustrated here:
So far, all I've managed to come up with is this (example in 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); } } }
I know each ring contains six more points than the previous and each 120° vector contains one additional point for each step from the center. I also know that x + y + z = 0
for all tiles. But how can I generate a list of coordinates that follow the sequence below?
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
Where A₀ means the area of each of the equilateral triangles in which we have divided the hexagon. After multiplying this area by six (because we have 6 triangles), we get the hexagon area formula: A = 6 * A₀ = 6 * √3/4 * a² A = 3 * √3/2 * a²
Hexagons have 6 sides and 6 corners. Each side is shared by 2 hexagons. Each corner is shared by 3 hexagons. For more about centers, sides, and corners, see my article on grid parts (squares, hexagons, and triangles).
Not only is x + y + z = 0
, but the absolute values of x, y and z are equal to twice the radius of the ring. This should be sufficient to identify every hexagon on each successive ring:
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(""); }
Another possible solution, that runs in O(radius2), unlike the O(radius4) of tehMick's solution (at the expense of a lot of style) is this:
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
or written a little more concisely:
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
It's inspired by the fact the hexagons are actually on the exterior of a hexagon themselves, so you can find the coordinates of 1 of its points, and then calculate the others by moving on its 6 edges.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With