There are several different ways to convert a pixel location into a hex coordinate. On the main page I cover what I consider to be the simplest approach. Here are some of the others I’ve found. Most of these can work directly with offset grids.
Guess and test
If you can somehow guess a location within a hex of the true answer, you can then correct the guess. Scan its neighbors and itself, and pick the one closest with Euclidean distance. This works because a regular hex grid also happens to satisfy the Voronoi property: the hexagon contains all points that are closer to its center than to any other hexagon center.
Unlike hex rounding, this approach doesn’t require you to use cube coordinates. It’s just as simple with offset as with axial coordinates.
Instead of scanning the neighbors each time, note that the answer is always the same relative to the position you’re given. You can store the answer in a 2D array or bitmap. Given a screen location
x, y, make an initial guess
q0, r0. If that hexagon is centered at
y0, so you can store
dq, dr for each
- x0, y - y0. Then the answer will be
q0 + dq, r0 +
- A system I used for an old game encodes the pixel boundary in an array.
An advantage of this technique is that it works at the pixel level instead of the geometric level, so you get precise control of what happens for the points on the boundary between two hexes.
By looking at the geometry of hexagons you can narrow down a pixel location to either one, two, or three hexagons, typically by dividing hexagons into smaller shapes. You can then use the edges between hexes to determine which subshape the pixel coordinate is on. There are a variety of shapes you can use. Here are some articles to read with details:
- Hexagonal Grid Math uses a combination of one rectangle and two triangles per hexagon.
- Hexagonal tilemap picking also uses rectangles and triangles.
- Resolving the Hexagonal Coordinates of Screen Points uses three rhombuses per hexagon.
- Coordinates in Hexagon Based Tile Maps uses two triangles and one pentagon for even rows and one triangle and two quadrilaterals for odd rows.
- Hexagon hit testing also uses different shapes for even/odd rows.
- Paul Gyugyi’s system uses six triangles per hexagon.
- The HexPart system uses four quadrilaterals per hexagon.
All the pixel to hex conversions I’ve seen use branches or a lookup table. I was mystified when Charles Chambers sent me pixel to hex conversion code that uses
floor() five times, but no branches. First, divide
size * sqrt(3); then find
q, r with:
temp = floor(x + sqrt(3) * y + 1) q = floor((floor(2*x+1) + temp) / 3); r = floor((temp + floor(-x + sqrt(3) * y + 1))/3);
How does it work? I admit I don’t yet fully understand this one. Charles uses the
floor() function to divide space into rhombuses which make up hexagonal rows. If you look at subexpressions in the “inner” calls to
2 * x,
x + sqrt(3) * y, and
sqrt(3) * y, you’ll notice that they’re dot products of
(x, y) with the three basis vectors aligned with the hex grid. Each “outer” call to
floor() combines two of the dot products.
If you’re using this for your own project, note that the
q, r here are for a different axial form than the one I use in this guide. See this comment from Kenneth Shaw for a version that works with axial coordinates.
I suspect that extending this to work with cube coordinates directly will help me understand how it works.