Questions & Clarification on Coordinate Systems
See original GitHub issueA few questions & clarifications:
Unfortunately I do not have a background in mathematics, please be patient with me.
The gist of my use case is a geo-location based mobile game that uses a hexagonal grid to represent the world, something H3 appears to exactly solve for. Though, this use case necessitates the need to have a coordinate system that can uniquely identify each cell in the global grid for a variety of reasons. I am having a hard time figuring out how to obtain coordinates from the cells of an H3 grid.
H3 Coordinate Systems: https://h3geo.org/docs/core-library/coordsystems Hexagonal Coordinate Systems: https://www.redblobgames.com/grids/hexagons/#coordinates
I marginally familiar three coordinate systems for hexagonal grids:
- Offset Coordinates
- Cube Coordinates (3 axes 120 degrees apart)
- Axial Coordinates (Essentially cube coordinates sans an axis) [What I am aiming for here]
In the H3 docs, it mentions:
- IJK Coordinates
- This is noted as being the
3 coordinate axes spaced 120° apart
which seems like a cube coordinate system. However the example picture’s coordinates don’t seem to line up with the expectation ofi+j+k == 0
. - What is this if not cube coordinates?
- Are these globally unique?
- How can this coordinate be obtained for a given H3Index?
- This is noted as being the
- FaceIJK Coordinates
- Simply the IJK coordinates, but centered on each face. And I assume constrained to each face. Definitely not what I’m after.
- Hex2d Coordinates.
[x,y]
coordinates for theIJK
coordinates with the+x axis
aligned oni axis
. This appears to be what I am looking for.- Are these essentially
Axial Coordinates
? - Is there a specific conversion expectation to go from
IJK
toHex2d
? - How can this coordinate be obtained for a given H3Index?
- Local IJ Coordinates.
- At first this looked promising, until I read
local coordinates are only valid near the origin.
. Which points out that these coordinates are really only valid within the same base cell.
- At first this looked promising, until I read
TL;DR: How can I obtain cartesian coordinates for each cell that are globally unique?
Issue Analytics
- State:
- Created 3 years ago
- Comments:9
First, on your questions about H3: the algorithm is (simplified a bit)
(lat, lng) -> (x, y, z)
(to spherical coordinates), then(x, y, z) -> (x, y) + icosahedron face id
(to hex2d, per icosahedron) then(x, y) + icosahedron -> FaceIJK (icosahedron face + (i, j, k)
(where IJK here is a 2D coordinate system such that all values are positive and therefore storable inside of an integer) and finally to the H3 Index where it is subdivided such that each 3-bit segment stores a value 0-6 corresponding to one of the IJK subdivision+traversal steps.It is possible to rederive the original XYZ spherical coordinates from the H3 cells, but involving H3 at all would be a waste of your time, as the conversion from
(lat, lng) -> (x, y, z)
is literally just this:But if you did go with spherical coordinates, you’d need a 3D perlin noise algorithm and some way to sample out from the unit sphere of that noise to then generate what you’re actually after.
If the main thing you’re after from H3 is the ability to generate perlin noise on a sphere, I would have to point you to the Google S2 project that this was was inspired by. You would be working with square-ish indexes, and while you do still have the issue that boundaries along the 6 cube faces would have weird traversal rules and odd boundary behavior for the perlin noise if you unfolded that, it could be possible to simply compute the noise 6 times for each unfolding and sum them together and divide by 6 to avoid it.
It should be possible to port a perlin noise function to H3 (unfold the icosahedron centered on each face, then use IJ coordinates then translate back), but it would still have the same unfolding problem, except now you have 20 icosahedron faces to deal with so your function would be ~3x slower to accommodate the boundary problem.
Finally, the fastest way to generate perlin noise on the sphere is to just use (r, theta, phi) with a fixed
r
you can ignore, and some sort of consideration for the antimerdian problem if you care about that at all (it’s also mostly over water). (EDIT 2: Which is basically lat, lng.)Edit: I missed one last part about how H3 handles hexagons in multiple faces: there are a fixed set of these and they are assigned to one of the two bisecting faces following a rule to make sure all faces have an equal number of hexagons. I don’t recall the rule off the top of my head, but the H3 code doesn’t compute it, either, the 122 base cells are simply stored in the code with which face they are associated with.
To expand a bit on this, hexagons don’t map onto a sphere, so there can’t be a singular grid system for the entire globe. H3 almost accomplishes this by being a grid system on equilateral triangles and then arranging them into an icosahedron such that the points of the icosahedron map to 12 special pentagons, leaving the rest to be hexagons.
The only 2D grid that can work is isolated to one of the icosahedron faces. It would be possible to unfold the icosahedron into a Dymaxion Map and then apply the right transformations to allow traversal between icosahedron faces, but that would lead to “edge of the world” problems where you can define hexagons that map to nothing. It can work if you know you are constrained to land only, though, and it is one of the things that has been discussed to potentially offer, but with all of those caveats above.
However, you have not explained what exactly you are trying to accomplish with the game. I am going to make some educated guesses:
geoToH3
.kRing
to get the indexes to query your server, with the size based on how far out the map is zoomed, the resolution you choose to operate on, and so on.h3Line
), hexagon neighbors (kRing
of 1 to get,h3IndexesAreNeighbors
to check), outlines for rendering (h3ToGeoBoundary
), calculating hex-level distances for attack ranges (h3Distance
), etc.I don’t see the explicit need for a 2D grid for the game logic. The various APIs of H3 are designed to give you most of the optionality of a grid despite that being impossible on the sphere. If there is an operation that we have missed, we would be glad to hear about that and add it, but the exact request is technically not possible.