# encoding: utf-8
"""
Cubic coordinate helper functions assuming pointy side up.
This draws heavily from the excellent reference:
https://www.redblobgames.com/grids/hexagons/
"""
import numpy as np
from . import axial
[docs]def to_axial(i, j, k):
"""Convert cube coordinates to axial coordinates"""
q, r = i, k
return q, r
[docs]def to_offset(i, j, k):
"""Convert cube coordinates to offset coordinates, odd rows shifted by +1/2 col"""
col = i + (j - (j & 1)) // 2
row = j
return col, row
[docs]def to_cart(i, j, k):
"""Convert cube coordinates to cartesian"""
# col, row = to_offset(i, j, k)
# x, y = offset.to_cart(col, row)
x, y = axial.to_cart(*to_axial(i, j, k))
return x, y
[docs]def distance(i_1, j_1, k_1, i_2, j_2, k_2):
"""Distance between two hexagons in cube coordinates"""
a = np.array((i_1, j_1, k_1))
b = np.array((i_2, j_2, k_2))
dist = np.sum(np.abs(np.subtract(a, b))) / 2
return dist
[docs]def within_radius(i, j, k, n, original=(0, 0, 0)):
"""Is this new location within a radius from an original (default origin)"""
if original == (0, 0, 0):
within_radius = max((abs(i), abs(j), abs(k))) <= n
else:
within_radius = distance(i, j, k, *original) <= n
return within_radius
[docs]def validate(i, j, k):
"""Is this a valid cube coordinate?"""
valid = (i + j + k) == 0
return valid
[docs]def neighbors(i, j, k):
"""Give me a list of neighboring hexagon locations"""
neighbors = [
(i, j + 1, k - 1),
(i + 1, j, k - 1),
(i + 1, j - 1, k),
(i, j - 1, k + 1),
(i - 1, j, k + 1),
(i - 1, j + 1, k),
]
return neighbors
[docs]def rotate_about_center(i, j, k, n_steps):
"""Rotate the coordinate i,j,k about the 0,0,0 center by n_steps
Each step is one 60 degree rotation to the right. Negative steps are
60 degree rotations to the left.
"""
coord = np.roll([i, j, k], n_steps)
if n_steps % 2 == 1: # odd rotations invert signs
coord *= -1
return list(coord)
[docs]def closest(i, j, k, points):
"""Which point (in a list) is closest to a single passed point?"""
def dist(pt):
return distance(i, j, k, *pt)
dists = [dist(pt) for pt in points]
return points[np.argmin(dists)]