If I had a grid of squares, they can be labeled with Cartesian coordinates such that given square $(x,y)$, you know it shares a boundary with squares $(x+1,y),(x-1,y),(x,y+1),(x,y-1)$.

Is there a way of labeling a tessellated hexagon grid, so that given any hexagon label you can work out it's neighbors?

  • 9
    $\begingroup$ Everything you want to know about hex grids is at redblobgames.com/grids/hexagons . In particular see the sections on "coordinate systems" and "neighbors". $\endgroup$ Apr 27, 2017 at 13:41

3 Answers 3


In the interest of closing the question I've posted this answer, but full credit for the answer goes to Michael Lugo for his comment on my initial Post.

All information comes from this link. It goes into far more detail than this answer.

There are multiple approaches to labeling Hexagon grids, each with advantages and disadvantages.

Offset coordinates

The most common approach is to offset every other column or row. Columns are named col or q. Rows are named row or r. You can either offset the odd or the even column/rows, so the horizontal and vertical hexagons each have two variants.

Offset coordinates, horizontal layout

Cube coordinates

Another way to look at hexagonal grids is to see that there are three primary axes, unlike the two we have for square grids. There’s an elegant symmetry with these.

enter image description here

Instead of having two values per coodinate, representing how far North and South the hexagon is, you can use three dimensions.

Axial Coordinates

The axial coordinate system, sometimes called “trapezoidal”, is built by taking two of the three coordinates from a cube coordinate system. Since we have a constraint such as x + y + z = 0, the third coordinate is redundant. Axial coordinates are useful for map storage and for displaying coordinates to the user. Like cube coordinates, you can use the standard add, subtract, multiply, divide operations from cartesian coordinates.

enter image description here

So for my purposes, the most useful map system was cube coordinates, as they have the simplest and most consistent rules for changing coordinates based movement between cells.

  • 5
    $\begingroup$ Beautiful answer -- this helped with the Advent of Code 2020 adventofcode.com/2020/day/24 $\endgroup$ Dec 24, 2020 at 19:10
  • $\begingroup$ Be sure to use floats or other non-integer data types when doing conversions between hex and pixel. I spent hours trying to figure out why my grid looked weird, and it was all because my code (3 / 2) was doing integer division instead of floating point division. $\endgroup$ May 7, 2021 at 14:17

While I use redblobgames' hexagons page for all sorts of things hexagonal, there is a simple 'other way', very similar to the cartesian neighbour calculation. The normal way we imagine bricks (stretcher bond) has the same relationship as a hex-grid.
Recognising that bricks on every other row have a horizontal offset, we count (along the rows) using +2 increments instead of +1.

This gives us our x values as following

3:0 2 4 6 8
2: 1 3 5 7
1:0 2 4 6 8
0: 1 3 5 7

Whereas y values are the same as cartesian. Now we can work out our neighbours:

For any brick/hex (x, y) where (x+y)%2==1 the neighbours are (x-2,y),(x+2,y),(x-1,y+1),(x+1,y+1),(x-1,y-1),(x+1,y-1)

Placing a hex (x,y) into an approximate cartesian position can be done by (x+y%2,y) (where % is the modulo operation)

If we want to label without using +2 increments, we can still do that, but we need to use the modulo operation for calculating neighbours.

3:0 1 2 3 4
2: 1 2 3 4
1:0 1 2 3 4
0: 1 2 3 4
  0-1-2-3-4 y%2=1
  -1-2-3-4- y%2=0

Now we can work out our neighbours: For any brick/hex (x, y) the neighbours are (x-1,y),(x+1,y),(x,y+1),(x+2(y%2)-1,y+1),(x,y-1),(x+2(y%2)-1,y-1).


Create the grid by drawing horizontal lines thru ALL hexagon centers and drawing vertical lines thru ALL hexagon centers. The neighbors are:

(+1,-1), (+2,0), (+1,+1), (-1,+1), (-2,0), (-1,-1)

Note: the x-axis is scaled by a factor of sqrt(3). This is ok. Cartesian coordinates can have an axis that is scaled.

Note: the x,y does not match the hexagon label. This is ok.

If we set the upper left hexagon with a coordinate of (0,0), the hexagon label is: Math.floor(x/2)+1 plus y+1

(0,0) => 0101 (2,0) => 0201 (4,0) => 0301 (1,1) => 0102 (3,1) => 0202 (5,1) => 0302


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.