Hexagonal coordinates: Polar to Cartesian

11

Wikipedia says about Polar Coordinates:

In mathematics, the polar coordinate system is a two-dimensional coordinate system in which each point on a plane is determined by a distance from a reference point and an angle from a reference direction.

This seems perfect for describing hexagonal grids. Take the following hexagonal grid for example:

  A B C
 D E F G
H I J K L
 M N O P
  Q R S

Our reference point will be the center of the hexagon ('J'), and our reference angle will be to the top left corner of the hexagon ('A'). However, we'll describe the angle in terms of the number of clockwise steps around the outside of the hexagon from this point, not in angles. So we'll call it "Step number" instead of angle.

For example, 'C' is at (2, 2) because it has a radius of 2 (since it is two rings away from the center, 'J'), and an step number of 2 (2 clockwise steps forward from 'A'). Similarly, 'O' is at (1, 3), because it is one ring away from the center, and three clockwise steps forward from 'E' (which is on the reference angle).

For completeness, 'J' is at (0, 0), since you need 0 steps out and 0 steps clockwise to reach it.

Now, you can also describe a hexagonal with Cartesian Coordinates, but because of the offset this is a little weird. Just like with our polar coordinates, we will put the center at (0, 0). Each space takes up a coordinate also, so 'K' is at (2, 0), not (1, 0). This would put 'A' at (-2, 2), and 'O' at (1, -1).

The challenge

Given polar hexagonal coordinates, output the same coordinates in Cartesian coordinates. You may take these coords, and the output the answer in any reasonable format. This means that you may reverse the order of the inputs if you like. This also means you could output the coords as (Y, X), but if you do, please mention this in your answer to avoid confusion.

You do not have to handle negative radii, but you may get negative angles, or angles that go more than a full revolution around the hexagon. For example, you may receive (1, 10), or (1, -2) as input. These would both correspond to 'N' in our previous hexagon. You do not have to handle non-integers for input.

Sample IO

#Polar      #Cartesian
(0, 0)      (0, 0)
(1, 2)      (2, 0)
(6, 0)      (-6, 6)
(2, -3)     (-3, -1)
(4, 23),    (-5, 3)
(5, -3),    (-8, 2)
(10, 50),   (-20, 0)
(6, 10),    (10, 2)
(8, 28),    (0, -8)
(8, -20),   (0, -8)

James

Posted 2016-11-22T20:40:25.353

Reputation: 54 537

4someone answer this in hexagony... – FlipTack – 2016-11-22T20:52:11.243

To clarify, do the units used to measure the angle depend on the radius? (e.g. (1, 1) is an angle of 60° from the reference angle, but (2, 1) is only 30° because it's further out and thus there are more letters there). The question seems to imply that, but that's not the normal way polar coordinates work, so it may be worth explaining that yours are differnet. – None – 2016-11-22T20:59:43.857

Do we only have to consider a distance of up to 2 from the origin, or does it have to work further away than that? – Level River St – 2016-11-22T21:00:21.963

@ais523 Yes, it's measured in steps not angles. I've clarified that a little bit in the post. – James – 2016-11-22T21:05:31.423

@LevelRiverSt No, it should theoretically work for any radius. The test IO goes up to 10. – James – 2016-11-22T21:08:29.307

Answers

3

JavaScript (ES6), 93 bytes

(r,d)=>[...Array(d+r*6)].map((_,i)=>x+="431013"[y+="122100"[i=i/r%6|0]-1,i]-2,x=y=-r)&&[x,-y]

Test snippet:

f=(r,d)=>[...Array(d+r*6)].map((_,i)=>x+="431013"[y+="122100"[i=i/r%6|0]-1,i]-2,x=y=-r)&&[x,-y]

g=([r,d],e)=>console.log(`f(${r},${d}):`, `[${f(r,d)}]`, "expected:", `[${e}]`)

g([0,0],[0,0])
g([1,2],[2,0])
g([6,0],[-6,6])
g([2,-3],[-3,-1])
g([4,23],[-5,3])
g([5,-3],[-8,2])
g([10,50],[-20,0])
g([6,10],[10,2])
g([8,28],[0,-8])
g([8,-20],[0,-8])

ETHproductions

Posted 2016-11-22T20:40:25.353

Reputation: 47 880

You have to handle angles that go more than a full revolution; your code doesn't seem to work for (1, -7). – Neil – 2016-11-24T20:22:12.983

1

JavaScript (ES6), 95 bytes

f=(r,t,x=-r,y=r,d=2,e=0)=>t<0?f(r,t+r*6):t>r?g(r,t-r,x+r*d,y+r*e,d+e*3>>1,e-d>>1):[x+t*d,y+t*e]

Explanation: The solution for a zero angle is simply -r,r, so we start at that point. If the angle is negative, we add on a whole hexagon and call ourselves recursively, otherwise we start walking around the hexagon with a d,e=2,0 step. Where possible, we leap r such steps, then rotating the step using the formula d+e*3>>1,e-d>>1 to progress to the next side. Finally we take any remaining steps to reach our destination.

Neil

Posted 2016-11-22T20:40:25.353

Reputation: 95 035