This guide will show coordinate systems for tiles (faces), vertices (corners), and edges for square, hexagon, and triangle[1] grids. There are algorithms for going from a tile to its corners, an edge to its tiles, and many others. For a more detailed guide to hexagons, see my guide to hexagonal grids. For more on square grids, see my pages on edges, line-drawing, and circle fills.
Part A (black) | Part B (red) | ||
---|---|---|---|
Face | Edge | Vertex | |
Face | Neighbors: | Borders: | Corners: |
Edge | Joins: | Continues: | Endpoints: |
Vertex | Touches: | Protrudes: | Adjacent: |
The names and definitions here are arbitrary. This page isn't about the way to set up relationships, but one way to set up relationships. You'll want to adapt these for your own project. For example, you might choose to have neighbors and adjacent include diagonals. You might choose continues to include edges that aren't colinear. You might choose additional relationships. I hope this page gives you ideas for designing your own system for your project.
This page is an updated version of my 2006 guide to grid parts[2].
1 Square grids#
Square grids are common. In both 2D and 3D graphics systems, we have to transform “world” coordinates into “screen” coordinates and back. With grids, we also have to transform “grid” coordinates into “world” coordinates and back. The world↔screen transform will be different for a top-down or side or isometric view, but the grid↔world transform works the same. This page covers the grid coordinates only and not the transforms.
1.1. Coordinates#
Part | Diagram | Notes |
---|---|---|
Tile | Square tiles are the default choice because they're easy to work with. I'm using "y down" on this page but everything works the same if you use "y up". | |
Vertex | Each square has 4 vertices. We can choose 1 vertex that is each shared with 4 tiles. Here, I've picked the northwest vertex, but any of them will do. | |
Edge | There are four edges per square. You can either keep them separate or share them with adjacent squares. Here I'm using the west edge shared with the east edge of the adjacent tile, and the north edge shared with the south edge of the adjacent tile. |
1.2. Relationships#
Each of these 9 relationships can be expressed as taking an input and generating a list of outputs. For some types of input there is a different rule for each s
value.
Relationship | Diagram | Formula |
---|---|---|
Neighbors | q,r → q,r-1 q-1,r q,r+1 q+1,r | |
Borders | q,r → q,r,N q,r,W q,r+1,N q+1,r,W | |
Corners | q,r → q,r q,r+1 q+1,r+1 q+1,r | |
Joins W | q,r,W → q,r q-1,r | |
Joins N | q,r,N → q,r-1 q,r | |
Continues W | q,r,W → q,r-1,W q,r+1,W | |
Continues N | q,r,N → q-1,r,N q+1,r,N | |
Endpoints W | q,r,W → q,r q,r+1 | |
Endpoints N | q,r,N → q+1,r q,r | |
Touches | q,r → q,r q,r-1 q-1,r-1 q-1,r | |
Protrudes | q,r → q,r,W q,r,N q,r-1,W q-1,r,N | |
Adjacent | q,r → q,r+1 q+1,r q,r-1 q-1,r |
2 Hexagon Grids#
In this article, I use pointy-top hexagons, but the math works the same if you want flat-top hexagons. To construct hexagon coordinates, we can start with a square grid and morph it into a hexagon grid:
This is the "axial" coordinate system from my comprehensive hexagonal grid guide[3]. That page has more coordinate systems and many more algorithms.
2.1. Coordinates#
Part | Diagram | Notes |
---|---|---|
Tile | There are many coordinate systems for hexagonal grids. This one is the "axial" system. See my hexagonal grid guide for more. | |
Vertex | Each hexagon has 6 vertices. We can choose 2 vertices that are each shared with 3 tiles. Here, I've picked the north and south vertices, but there are many ways to do this. | |
Edge | There are six edges per hexagon. You can either keep them separate or share them with adjacent hexagons. Here they are shared. |
2.2. Relationships#
Relationship | Diagram | Formula |
---|---|---|
Neighbors | q,r → q,r+1 q+1,r q+1,r-1 q,r-1 q-1,r q-1,r+1 | |
Borders | q,r → q,r,NE q,r,NW q,r,W q-1,r+1,NE q,r+1,NW q+1,r,W | |
Corners | q,r → q,r,N q,r-1,S q-1,r+1,N q,r,S q,r+1,N q+1,r-1,S | |
Joins NE | q,r,NE → q+1,r-1 q,r | |
Joins NW | q,r,NW → q,r q,r-1 | |
Joins W | q,r,W → q,r q-1,r | |
Endpoints NE | q,r,NE → q+1,r-1,S q,r,N | |
Endpoints NW | q,r,NW → q,r,N q,r-1,S | |
Endpoints W | q,r,W → q,r-1,S q-1,r+1,N | |
Touches N | q,r,N → q+1,r-1 q,r q,r-1 | |
Touches S | q,r,S → q,r q,r+1 q-1,r+1 | |
Protrudes N | q,r,N → q,r,NE q+1,r-1,W q,r,NW | |
Protrudes S | q,r,S → q,r+1,NW q-1,r+1,NE q,r+1,W | |
Adjacent N | q,r,N → q+1,r-2,S q,r-1,S q+1,r-1,S | |
Adjacent S | q,r,S → q-1,r+1,N q-1,r+2,N q,r+1,N |
For squares and triangles, I defined the Continues relation for collinear edges, but with hexes there aren't any. It would be reasonable to define them to be non-collinear edges. Don't take the relations here as the way to define the relations; they're one way to define them. Adapt the rules here to match the needs of your project.
3 Triangle Grids#
Triangles are common in 3d graphics but are less commonly used for game maps. In this article I use triangles pointed up and down, but the math works the same if your triangles point left and right.
Other variants:
- GridLogic's library[4] encodes
L
andR
as 1 and 0. - mhwombat's scheme[5] is similar to "doubled coordinates" for hexagonal grids. It skips some coordinates like (0,1) and encodes the
L
,R
annotations into the q,r values. - For triangle-shaped maps ZenoRogue's scheme[6] folds a rhombus in half to encode the
L
,R
annotations into the two halves of the rhombus. - BorisTheBrave writes about a three-lane coordinate system[7] that is similar to "cube coordinates" for hexagonal grids[8]. The
q
,r
values from this page becomea
,b
values, andc
is computed as 1 - q - r forL
triangles and 2 - q - r forR
triangles. This is similar to how cube hex coordinates are related to axial hex coordinates, by computing the third value as -q - r. - Vsevolod Kvachev's post[9] has several distance functions for triangle grids, including handling diagonal movement.
3.1. Coordinates#
Part | Diagram | Notes |
---|---|---|
Tile | To define triangle grid coordinates we can start with square grid coordinates, shear the squares, then split the rhombuses into two triangles. This means each square face coordinate needs to be two triangle face coordinates. I chose to label them L and R. | |
Vertex | Triangles are the "dual" of hexagons. Triangle tiles are similar to hexagon vertices; triangle vertices are similar to hexagon tiles. The extra triangle face does not create any additional vertices, so the vertex labeling is the same as the square grid labeling. | |
Edge | Triangle tiles are up or down facing, and that makes the edge assignment trickier. The edges are the same as those for squares (W and N), except we have one additional edge from the splitting of the face in two, and I've labeled that E. |
To convert triangle vertices from grid coordinates to world coordinates, multiply by the axis vectors i
and j
:
⎛ x ⎞ ⎡ i.x j.x ⎤ ⎛ u ⎞ ⎝ y ⎠ = ⎣ i.y j.y ⎦ ⎝ v ⎠
Expanded out, that's
x = i.x * u + j.x * v y = i.y * u + j.y * v
To convert triangle face coordinates to world coordinates involves an adjustment. For face (q, r, L/R)
first calculate the world coordinates of the lower left vertex, (q, r)
. Then for an L
face, add (1/2 * i, 1/3 * j)
to the upper left vertex location. For an R
face, add (i, 2/3 * j)
to the upper left vertex location. The result will be the center of the face.
To convert from world coordinates to triangle vertices, first find the upper left corner of the rhombus (q, r)
using algebra, or by inverting the i.x,j.x,i.y,j.y matrix. The rhombus contains two triangle faces. To determine which face the point is in, look at the edge that divides the two triangles inside each rhombus. If frac(q) + frac(r) < 1.0
, the point is on the left of the line, and is therefore in the L
face; otherwise it is in the R
face.
When working with triangles, treat vertices as primary, and face centers as secondary. This is the opposite of how we treat hexagons.
Distance on a triangle grid is something I explore here[10]. I haven't worked much with triangle grids and don't know if this is the best way to approach it. This article from symbo1ics[11] has more math for triangle grids.
3.2. Relationships#
Relationship | Diagram | Formula |
---|---|---|
Neighbors L | q,r,L → q,r,R q,r-1,R q-1,r,R | |
Neighbors R | q,r,R → q,r+1,L q+1,r,L q,r,L | |
Borders L | q,r,L → q,r,E q,r,N q,r,W | |
Borders R | q,r,R → q,r+1,N q+1,r,W q,r,E | |
Corners L | q,r,L → q,r+1 q+1,r q,r | |
Corners R | q,r,R → q+1,r+1 q+1,r q,r+1 | |
Joins E | q,r,E → q,r,R q,r,L | |
Joins N | q,r,N → q,r,L q,r-1,R | |
Joins W | q,r,W → q,r,L q-1,r,R | |
Continues E | q,r,E → q+1,r-1,E q-1,r+1,E | |
Continues N | q,r,N → q+1,r,N q-1,r,N | |
Continues W | q,r,W → q,r+1,W q,r-1,W | |
Endpoints E | q,r,E → q+1,r q,r+1 | |
Endpoints N | q,r,N → q+1,r q,r | |
Endpoints W | q,r,W → q,r+1 q,r | |
Touches | q,r → q-1,r,R q,r,L q,r-1,R q,r-1,L q-1,r-1,R q-1,r,L | |
Protrudes | q,r → q,r,W q,r,N q,r-1,E q,r-1,W q-1,r,N q-1,r,E | |
Adjacent | q,r → q,r+1 q+1,r q+1,r-1 q,r-1 q-1,r q-1,r+1 |
4 More#
For implementation of the Tile, Edge, Vertex data structures, I usually use a struct
with public fields, q
and r
being integers and s
being a symbol (:L
in Ruby, 'L
in Lisp) or a character ('L'
in C or C++ or Java or Rust) or a one-character string ('L'
in Python). Each of the relationship algorithms is a function that takes a part as input and returns a list of parts as output. Parts that have s
variants can be handled using switch
or pattern matching. I made a JavaScript implementation to implement the diagrams on this page.
What else would you like to see me include in this document? Was anything confusing? Incomplete? Incorrect? Let me know.
There are some things I didn't find a place for, but might be of interest. Mathematicians have found five types of grids in 2D space[12]: squares, triangles, hexagons[13], rectangles, and parallelograms. However only squares, triangles, and hexagons are regular polygons. Spiral Honeycomb Mosaic[14] (search the page for "Spiral Honeycomb Mosaic") is an interesting way to assign numbers to hexagons in a hexagonal grid. It results in bizarre properties.