Tuesday, May 5, 2020

Mathpost: Coordinates on a tesselating hexagonal world.

Turn back now, if ye be looking for some narrative content. This be nothin' but a big wad of barely polished geometry.


Basic idea is that you live on a giant flat plane that loops. (As in this story) Go far enough in any direction, and you'll end up back where you started. Navigational systems evolve to meet the needs of the people using them. What kind of system of coordinates would be useful for navigating on a looping hex?


Your browser does not support the HTML5 canvas tag.





Rectangular Coords

X: Y:



Hexline Offset Coords

A: B: C:






 Unit length is equal to the inner radius of the hex.

(X,Y) coordinates are the standard Cartesian kind.

(A,B,C) coordinates are "Hexline Offsets". Basically, choose 2 opposite edges of the hex perimeter, and draw parallel lines first through the origin and then through your point. The absolute value of coordinate is the ratio of (the distance between the point and the line through the origin) and (the distance between the center and the perimeter line)








Further Explanation 


More detailed unpolished explanation below.

Neither the images nor text were optimized, so everything is a bit too large.


We're on a flat tessellating hexagonal world and want to describe our position.

There is some "origin point" on the plane which is defined by social convention.

For simplicity, let's define our unit length as the distance from the center of an edge to the center of the hex.

Sections:
  • Cartesian Grid
  • Oblique Grid
  • Hexline Offset System
  • Equivalence of Offset System to 3D Cartesian Grid

Systems with two coordinates:

Cartesian Grid

One way we could design our coordinate system is using a standard Cartesian Grid, like so


The dot in the middle represents the origin.

The big dark bolded lines have two important meanings:
  •  The dark vertical line is the set of points at which X=0, while the horizontal line is the set of points for which Y=0.
  • The lines are also our axes, indicating the direction of the basis vectors for the coordinate system. The vertical line is the Y-axis, and the horizontal line is our X-axis.
Here are the aforementioned basis vectors:



The gridlines are contours along which one of our coordinates remains constant. For example, here's the contour for X=.5:


One interpretation of this is that any point along this line is distance 0.5 from the dark vertical X=0 line.


Take a look at the point (X,Y)=(.5,.5)


We can equivalently think of this as either:
  • The intersection of (the set of points where X=.5) with (the set of points where Y=.5)
  • The intersection of (the set of points where X is distance .5 from the X=0 set) with (the set of points where Y is distance .5 from the Y=0 set)
  • The position resulting from moving along half of the X basis vector and then moving along half of the Y basis vector


And this works fine, but if we live on a tessellating hex, then we run into a few problems when trying to use this system near the edges of the hex.



If we go far enough in any direction, we will eventually come back close to our starting point. Thus the coordinates should be in some sense cyclical. If we go off the "North" or "South" edges, we'll loop back around in a consistent way, and can just add ±2 to the Y coordinate. No problem. But if we want to cross one of the other edges, the math becomes a bit messier. You can work it out with a bit of trigonometry sure. But it's hard to do in your head.

Also, I don't like how the gridlines fail to line up with the edges of the hex.



Oblique Grid

 Although it's standard to define 2D coordinates in terms of a pair of orthogonal vectors, we could use any pair of independent basis vectors we want.

We could for example use basis vectors pointing towards the centers of the edges of the hex



 And then our grid of points will look like this:


 The grid lines up a bit more nicely with the hex, and things get more manageable near the edges.

If we go over the Top or Bottom Edges, then our coordinates go from (U,V) to (U,V±2). For example, see that the point (.4, 1.2) is equivalent to the point (.4, -.8)

If we cross the Top-left or Bottom-right edges, then our coordinates from (U,V) to (U±2,V). For example, the points (1.1, .2) and (-9, .2) are equivalent.

.

Finally, if we cross the Top-right or Bottom-left edges, then both coordinates are adjusted. For example, the points (.8, 1.2) and (-1.2, -.8) are equivalent.


(Note also the relationship between a hexagonal tiling and a rhombic tiling. If we live on a tessellating hex, then we also live on a tessellating rhombus.)

That's all well and good.

But now we run into a new problem. If we try to apply standard distance calculations, using the Pythagorean theorem, we'll get results like that the following two red points are the same distance from the origin:




To actually calculate distances for navigation, you need to convert back to the Cartesian coordinate system, then apply the Pythagorean theorem. Again, doable, but inconvenient.





Is there a way to get the best of both worlds? Can we have a coordinate system with a cleanly tessellating grid which also uses Cartesian distances?

 Yes! But first let's make a quick digression into something that doesn't work at all.


Systems with three coordinates:

Linearly dependent 2D basis vectors.

Start with the Oblique Grid above. Now for symmetry, we might want to add a third basis in there. 

 But we can't. With three basis vectors in a 2D plane, the vectors can't be independent, and so there are infinitely many ways to represent each point, even before getting into the cyclical hex stuff.

For example, the origin can be represented as (0,0,0) or (.2,.2,.2) or (.5,.5,.5), while the point (.5,.5,0) can also be represented as (.6,.6,-.1). If I give you a coordinate, you'll be able to plot it on the map, but you won't be able to associate a point on the map with a unique coordinate.

The most obvious thing to do would be just always set the third coordinate to zero, and then the whole system would collapse back to the Oblique Grid.

Or...




Offset Towards the Perimeter.


Remember back with our basic grid, how the Y component of a coordinate can represent either the amount of Y-basis-vector added to the mix OR the distance from the line at which Y=0.

Because we chose a distance unit equal to the the inner radius of the hex, and because the Y-basis-vector goes from the origin to the center of an edge, we can also think of the Y coordinate as the portion of the way we've traveled from the East-west diameter up to the top perimeter.

For example, the set of points where Y=.3 is 30% of the way from the horizontal diameter up to the top perimeter.


Let's rename Y to B so that we can distinguish between our two systems.

And let's also add some offset lines for each of the other two pairs of parallel perimeter lines:


Note that when we draw the grid this way, the dark bolded lines are no longer axes. They're just the sets of points at which either A,B, or C is equal to zero.  And the grid lines are acting solely as the contours for each of our three offsets.

Since we're describing a 2D object with three parameters, there are going to be restrictions on which (A,B,C) triplets are actually valid. With this setup, it must always be the case that A+B+C=0.

Here's the point (.4, .3, -.7)

On the other hand, if we try to find the point (-.6,.2,.2), we can see that there is no point on the surface of the hex which exists with those offsets, because the sum of coords is -.2 (In a certain sense, the point  does exist but deep underground, as we'll see in a minute.)



 If you know your coordinates, then you can tell that you are on the perimeter route whenever one of your coords is close to 1 or -1.


And this system makes it relatively painless to deal with hexal edges. Each edge is associated with an offset direction. As soon as the absolute value of one of your offsets exceeds 1, you know it's time to make a conversion. And the rule is If you cross an edge, adjust the cooresponding offset by 2 and adjust each of the other offsets by 1 in the opposite direction.

Example: You start at offset (.9, -.2, -.7)


 Now move along the offset direction (.2, -.2, 0) and you'll travel to offset (1.1, -.4, -.7).
 Now we've gone over the +A edge, and the A offset has exceeded 1. So if we want to stay in the cannonical hex, we need to decrease A by two, and increase B and C each by one. So our new canonical offset is (-.9, .6, .3)

Even better than the Oblique coordinates because the conversion operations are symettrical.

Even corners aren't much of a problem. Start at (.9, 0, -.9), move along direction (.2, 0, -.2), crossing through a vertex in the process. Unadjusted offset is now (1.1, 0, -1.1). Because A exceeds 1, we need to decrease A by two while increasing each of the other offsets by one, bringing us to a final offset of (-.9, 1, -.1). Alternatively, because -C exceeds 1, we could increase C by two while decreasing each of the other variables by one, to get (.1, -1, .9). Consult the charts and you can see that they're the same point.



The magic is that adding any of the following vectors to our offset moves us to the same position in an "adjacent hex": (2,-1,-1),(-1,2,-1),(-1,-1,2),(-2,1,1),(1,-2,1),(1,1,-2),

And if we are frequently crossing some edge, we can work with unconverted form and then do the conversions all at once for standardized archival purposes.

We can also easily convert the system to use a different origin point by adding a constant offset to every coordinate on record and then performing loop adjustments as needed. Politically convinient!





But we were promised Cartesian Distances. And guess what! This system has those too! Almost!

The distance between two points (in terms of hex inradius units) is given by

And if the distance exceeds 2/sqrt(3), which is the outer radius of the hex, then the shortest path actually crosses over an edge, so do a little loop conversion then recalculate.

Why does this system work out so nicely? Where does that sqrt(2/3) factor come from? Here's the secret. This whole 3 variable offset thing? It's actually a Cartesian coordinate system, but in






Orthogonal 3D basis vectors. AKA the true form of the hexline offset system.

Instead of representing our 2D world with two dimensions, we can instead represent it as a two-dimensional 'slice' of a 3D world.

Start with standard Cartesian coordinates in 3D. You've probably seen something like this before, and you know the system well if you've ever played Minecraft.



Any 2D plane that passes through the origin of this 3D space has the property that every point in the plane satisfies  the constraint that  αX+ βY + γZ=0 for some triplet of constants (α,β,γ).

For example, we could choose (α,β,γ)=(0,0,1) and get the plane orthogonal to the Z axis, and every point on the plane can be represented purely in terms of X and Y. This is equivalent to the 2D Cartesian Grid describe previously.

But we could also tilt the plane a bit. Let's choose (α,β,γ)=(1,1,1).

Generated with Wolfram Alpha
Hey, notice how Wolfram only renders a cubic volume, and the part of the plane intersecting the cubic volume is a hexagon. Wink wink nudge nudge.

Look at this image again:



But now imagine that each of the three basis vectors is coming out of the page towards your face. (At an angle of about 35 degrees) That's essentially what we've done.



We need just one final tweak before we get to our hexline offset system. Choose the length of our 3D basis vectors to be equal to sqrt(2/3) times the inner radius of our hex.  Why? Because then the cross section of a cube of inner-radius 1 will be a regular hexagon of inner radius 1. Which means that our 3D coordinates perfectly match the offsets system given above.

The perimeter of our hex is a slice of a giant cuuuuube!



(If we don't make this adjustment, then the cross section hex will have inner radius of sqrt(3/2). That would work fine, but would make the adjustments much uglier for whenever you need to cross over an edge. Also, the distance unit would be defined in terms of some giant angle jutting off into the sky instead of in terms of the surface you live on. Maybe there would be multiple distance units, like the nautical mile kinda jam.)



Another implication of this is that the contours in the offset system are actually planes. And you could sensibly talk about a point where the offsets don't add up to zero. It's just that the contour planes intersect at a point above or below sea level.

For example, (A,B,C) at sea level, with (A+B+C)=0. (A+1,B+1,C+1) must then be sqrt(3) up in the air, in 3D cubic coordinate terms. Thus in terms of hexal inradii, it's  sqrt(2/3)*sqrt(3)=sqrt(2) up in the air. In general, if A+B+C=🐦, then the closet sea-level point is A-🐦/3, B-🐦/3, C-🐦/3. So point is sqrt(3)*🐦/3 up in the air in cubic terms. So sqrt(2)*🐦/3 up in the air in hexal inradii terms.

Surface altitude will be neglible when measured in hexal inradii. Might be worth keeping in mind for stuff way high up in the air.








There are other arrangements, but this one seems to be the one which makes it easiest to navigate the edges.








See also: These interactive visuals from Red Blob Games explaining a similar problem, with discrete hexagonally tiling positions instead of a single very large space which loops in a hexagonally tiling pattern.


3 comments:

  1. This is a good explanation and a cool idea. I still need to read the short story you link to appreciate the implications of this for worldbuilding. I could imagine in some way combining this with goblin henchman's hex flower mechanic.

    ReplyDelete
  2. A plane tiled by a hexagon can also be tiled by a rectangle. Like this one:

    (0,0,0), (1,0,0), (0,0.5,-0.5), (1, 0.5, -0.5).

    "Aerb is a hexagon" is more of a convention among the characters in the world than a statement about geometry.

    ReplyDelete
    Replies
    1. Yep. This is specifically an attempt to reverse engineer the coordinate system mentioned in chapter 202:

      “Our position, using the planar hexline system with offsets, is -0.57891, 0.17663, 0.40288.”
      “You use three axes?” I asked. “Not two?”
      “If you want to do the math to transform the two axis system into the three axis system, knock yourself out,” she replied.

      (Though it's also worth noting that while you can represent it as a tessellating rectangle, those rectangles would still be hexagonally tiled. So the hexagonitude isn't completely arbitrary.)

      Delete